diff --git a/package.json b/package.json
index fce87d835..98514259a 100644
--- a/package.json
+++ b/package.json
@@ -175,6 +175,7 @@
"json-test-suite": "1.0.0",
"jsx-test-suite": "0.0.2",
"knip": "6.21.0",
+ "less-test-suite": "0.0.1",
"magic-string": "0.30.21",
"make-synchronized": "0.8.0",
"nano-spawn": "2.1.0",
diff --git a/tests/format/less/less-test-suite/__snapshots__/format.test.js.snap b/tests/format/less/less-test-suite/__snapshots__/format.test.js.snap
new file mode 100644
index 000000000..86eadb4a4
--- /dev/null
+++ b/tests/format/less/less-test-suite/__snapshots__/format.test.js.snap
@@ -0,0 +1,17561 @@
+// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+
+exports[`snippet: plugin/plugin-transitive.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@plugin "plugin-transitive";
+
+.other {
+ trans : test-transitive();
+}
+=====================================output=====================================
+@plugin "plugin-transitive";
+
+.other {
+ trans: test-transitive();
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/3rd-party/bootstrap4.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "bootstrap-less-port/less/bootstrap";
+=====================================output=====================================
+@import "bootstrap-less-port/less/bootstrap";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/at-rules-compressed/at-rules-compressed.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Tests for atrule.js coverage - compressed output path (lines 243-250)
+// Also covers parser + genCSS + outputRuleset
+
+// Compressed @media with rules
+@media screen {
+ body { margin: 0; }
+ p { padding: 0; }
+}
+
+// Compressed @layer with multiple rules
+@layer base {
+ body { margin: 0; }
+ p { padding: 0; }
+ div { border: 0; }
+}
+
+// Compressed @supports
+@supports (display: grid) {
+ .grid { display: grid; }
+ .item { grid-column: 1; }
+}
+
+// Compressed @page
+@page {
+ margin: 2cm;
+ size: A4;
+}
+
+// Compressed @keyframes
+@keyframes slide {
+ from { transform: translateX(0); }
+ to { transform: translateX(100px); }
+}
+
+
+=====================================output=====================================
+// Tests for atrule.js coverage - compressed output path (lines 243-250)
+// Also covers parser + genCSS + outputRuleset
+
+// Compressed @media with rules
+@media screen {
+ body {
+ margin: 0;
+ }
+ p {
+ padding: 0;
+ }
+}
+
+// Compressed @layer with multiple rules
+@layer base {
+ body {
+ margin: 0;
+ }
+ p {
+ padding: 0;
+ }
+ div {
+ border: 0;
+ }
+}
+
+// Compressed @supports
+@supports (display: grid) {
+ .grid {
+ display: grid;
+ }
+ .item {
+ grid-column: 1;
+ }
+}
+
+// Compressed @page
+@page {
+ margin: 2cm;
+ size: A4;
+}
+
+// Compressed @keyframes
+@keyframes slide {
+ from {
+ transform: translateX(0);
+ }
+ to {
+ transform: translateX(100px);
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/at-rules-compressed-evaluation/at-rules-compressed-evaluation.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Test at-rule evaluation paths (eval, evalRoot, genCSS, accept, etc.)
+
+// Test keywordList - @media with keyword list
+@media screen, print, handheld {
+ body {
+ font-size: 12pt;
+ }
+}
+
+// Test declarationsBlock with mergeable=true (nested ruleset with declarations)
+@media screen {
+ .container {
+ color: red;
+ background: blue;
+ }
+}
+
+// Test simpleBlock optimization with allRulesetDeclarations (single ruleset)
+@media screen {
+ .test {
+ color: red;
+ background: blue;
+ }
+}
+
+// Test eval with value evaluation and keywordList conversion
+@breakpoint: screen;
+@media @breakpoint, print {
+ body {
+ margin: 0;
+ }
+}
+
+// Test evalRoot with ampersand handling
+.container {
+ @media screen {
+ & {
+ color: red;
+ }
+ .child {
+ color: blue;
+ }
+ }
+}
+
+// Test evalRoot with mixed ampersands
+.wrapper {
+ .inner {
+ @media screen {
+ & {
+ color: green;
+ }
+ }
+ }
+}
+
+// Test genCSS with value
+@charset "UTF-8";
+
+// Test genCSS with simpleBlock
+@page {
+ margin: 2cm;
+ size: A4;
+}
+
+// Test genCSS with rules (non-simpleBlock)
+@supports (display: grid) {
+ .grid {
+ display: grid;
+ }
+ .flex {
+ display: flex;
+ }
+}
+
+// Test isCharset
+@charset "UTF-8";
+
+// Test isRulesetLike (non-charset)
+@media screen {
+ body {
+ color: black;
+ }
+}
+
+// Test compressed output (outputRuleset compressed path)
+@layer base {
+ body {
+ margin: 0;
+ }
+ p {
+ padding: 0;
+ }
+}
+
+// Test variable/find/rulesets delegation
+@media screen {
+ @var: value;
+ .test {
+ color: @var;
+ }
+}
+
+// Test eval with media bubbling
+@media screen {
+ @media print {
+ body {
+ color: black;
+ }
+ }
+}
+
+
+=====================================output=====================================
+// Test at-rule evaluation paths (eval, evalRoot, genCSS, accept, etc.)
+
+// Test keywordList - @media with keyword list
+@media screen, print, handheld {
+ body {
+ font-size: 12pt;
+ }
+}
+
+// Test declarationsBlock with mergeable=true (nested ruleset with declarations)
+@media screen {
+ .container {
+ color: red;
+ background: blue;
+ }
+}
+
+// Test simpleBlock optimization with allRulesetDeclarations (single ruleset)
+@media screen {
+ .test {
+ color: red;
+ background: blue;
+ }
+}
+
+// Test eval with value evaluation and keywordList conversion
+@breakpoint: screen;
+@media @breakpoint, print {
+ body {
+ margin: 0;
+ }
+}
+
+// Test evalRoot with ampersand handling
+.container {
+ @media screen {
+ & {
+ color: red;
+ }
+ .child {
+ color: blue;
+ }
+ }
+}
+
+// Test evalRoot with mixed ampersands
+.wrapper {
+ .inner {
+ @media screen {
+ & {
+ color: green;
+ }
+ }
+ }
+}
+
+// Test genCSS with value
+@charset "UTF-8";
+
+// Test genCSS with simpleBlock
+@page {
+ margin: 2cm;
+ size: A4;
+}
+
+// Test genCSS with rules (non-simpleBlock)
+@supports (display: grid) {
+ .grid {
+ display: grid;
+ }
+ .flex {
+ display: flex;
+ }
+}
+
+// Test isCharset
+@charset "UTF-8";
+
+// Test isRulesetLike (non-charset)
+@media screen {
+ body {
+ color: black;
+ }
+}
+
+// Test compressed output (outputRuleset compressed path)
+@layer base {
+ body {
+ margin: 0;
+ }
+ p {
+ padding: 0;
+ }
+}
+
+// Test variable/find/rulesets delegation
+@media screen {
+ @var: value;
+ .test {
+ color: @var;
+ }
+}
+
+// Test eval with media bubbling
+@media screen {
+ @media print {
+ body {
+ color: black;
+ }
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/compression/compression.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#colours {
+ color1: #fea;
+ color2: #ffeeaa;
+ color3: rgba(255, 238, 170, 0.1);
+ @color1: #fea;
+ string: "@{color1}";
+ /* comments are stripped */
+ // both types!
+ /*! but not this type
+ Note preserved whitespace
+ */
+}
+dimensions {
+ val: 0.1px;
+ val: 0em;
+ val: 4cm;
+ val: 0.2;
+ val: 5;
+ angles-must-have-unit: 0deg;
+ durations-must-have-unit: 0s;
+ length-doesnt-have-unit: 0px;
+ width: auto\\9;
+}
+@page {
+ marks: none;
+@top-left-corner {
+ vertical-align: top;
+}
+@top-left {
+ vertical-align: top;
+}
+}
+.shadow ^ .dom,
+body ^^ .shadow {
+ display: done;
+}
+
+=====================================output=====================================
+#colours {
+ color1: #fea;
+ color2: #ffeeaa;
+ color3: rgba(255, 238, 170, 0.1);
+ @color1: #fea;
+ string: "@{color1}";
+ /* comments are stripped */
+ // both types!
+ /*! but not this type
+ Note preserved whitespace
+ */
+}
+dimensions {
+ val: 0.1px;
+ val: 0em;
+ val: 4cm;
+ val: 0.2;
+ val: 5;
+ angles-must-have-unit: 0deg;
+ durations-must-have-unit: 0s;
+ length-doesnt-have-unit: 0px;
+ width: auto\\9;
+}
+@page {
+ marks: none;
+ @top-left-corner {
+ vertical-align: top;
+ }
+ @top-left {
+ vertical-align: top;
+ }
+}
+.shadow ^ .dom,
+body ^^ .shadow {
+ display: done;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/debug/all/linenumbers-all.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Entry file for -all configuration
+@import "../linenumbers.less";
+
+=====================================output=====================================
+// Entry file for -all configuration
+@import "../linenumbers.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/debug/comments/linenumbers-comments.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Entry file for -comments configuration
+@import "../linenumbers.less";
+
+=====================================output=====================================
+// Entry file for -comments configuration
+@import "../linenumbers.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/debug/import/test.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@charset "ISO-8859-1";
+
+.mixin_import1() {
+ @media all {
+ .tst {
+ color: black;
+ @media screen {
+ color: red;
+ .tst3 {
+ color: inherit;
+ }
+ }
+ }
+ }
+}
+
+.mixin_import2() {
+ .tst2 {
+ color: inherit;
+ }
+}
+
+.tst3 {
+ color: grey;
+}
+=====================================output=====================================
+@charset "ISO-8859-1";
+
+.mixin_import1() {
+ @media all {
+ .tst {
+ color: black;
+ @media screen {
+ color: red;
+ .tst3 {
+ color: inherit;
+ }
+ }
+ }
+ }
+}
+
+.mixin_import2() {
+ .tst2 {
+ color: inherit;
+ }
+}
+
+.tst3 {
+ color: grey;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/debug/linenumbers.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@charset "UTF-8";
+
+@import "import/test.less";
+
+.start() {
+ .test-rule2 {
+ color: red;
+ }
+}
+
+.mix() {
+ color: black;
+}
+
+.test-rule1 {
+ .mix();
+}
+
+.start();
+
+.mixin_import1();
+
+.mixin_import2();
+
+@debug: 1;
+& when (@debug = 1) {
+ .test-rule {
+ color: red;
+ & when (@debug = 1) {
+ width: 2;
+ }
+ }
+}
+
+.supports-rule {
+ @supports (display: grid) {
+ color: green;
+ .nested-supports {
+ color: blue;
+ }
+ }
+}
+=====================================output=====================================
+@charset "UTF-8";
+
+@import "import/test.less";
+
+.start() {
+ .test-rule2 {
+ color: red;
+ }
+}
+
+.mix() {
+ color: black;
+}
+
+.test-rule1 {
+ .mix();
+}
+
+.start();
+
+.mixin_import1();
+
+.mixin_import2();
+
+@debug: 1;
+& when (@debug = 1) {
+ .test-rule {
+ color: red;
+ & when (@debug = 1) {
+ width: 2;
+ }
+ }
+}
+
+.supports-rule {
+ @supports (display: grid) {
+ color: green;
+ .nested-supports {
+ color: blue;
+ }
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/debug/mediaquery/linenumbers-mediaquery.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Entry file for -mediaquery configuration
+@import "../linenumbers.less";
+
+=====================================output=====================================
+// Entry file for -mediaquery configuration
+@import "../linenumbers.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/filemanagerPlugin/filemanager.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "test.test";
+.test-rule {
+ color: @color;
+}
+
+=====================================output=====================================
+@import "test.test";
+.test-rule {
+ color: @color;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/globalVars/extended.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#header {
+ color: (@base-color * 3);
+ border-left: @the-border;
+ border-right: (@the-border * 2);
+}
+#footer {
+ color: (@base-color + #003300);
+ border-color: @red;
+}
+@red: desaturate(red, 10%); // less file overrides passed in color <- note line comment on last line to check it is okay
+=====================================output=====================================
+#header {
+ color: (@base-color * 3);
+ border-left: @the-border;
+ border-right: (@the-border * 2);
+}
+#footer {
+ color: (@base-color + #003300);
+ border-color: @red;
+}
+@red: desaturate(
+ red,
+ 10%
+); // less file overrides passed in color <- note line comment on last line to check it is okay
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/globalVars/simple.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.class {
+ color: @my-color;
+}
+=====================================output=====================================
+.class {
+ color: @my-color;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/import-redirect/import-redirect.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "https://example.com/redirect.less";
+
+h1 { color: red; }
+
+=====================================output=====================================
+@import "https://example.com/redirect.less";
+
+h1 {
+ color: red;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/include-path/import-test-e.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+
+body { width: 100% }
+
+=====================================output=====================================
+body {
+ width: 100%;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/include-path/include-path.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "import-test-e";
+
+data-uri {
+ property: data-uri('image.svg');
+}
+image-size {
+ property: image-size('image.svg');
+}
+
+=====================================output=====================================
+@import "import-test-e";
+
+data-uri {
+ property: data-uri("image.svg");
+}
+image-size {
+ property: image-size("image.svg");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/include-path-string/include-path-string.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+data-uri {
+ property: data-uri('image.svg');
+}
+
+=====================================output=====================================
+data-uri {
+ property: data-uri("image.svg");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/js-type-errors/js-type-error.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.scope {
+ var: \`this.foo.toJS\`;
+}
+
+=====================================output=====================================
+.scope {
+ var: \`this.foo.toJS\`;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-always/mixins-guards.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// https://github.com/less/less.js/issues/2798
+.test-rule-2798 when ((8+4) < 13) {
+ regression: fixed;
+}
+.test-rule-2798 when ((8+6) < 13) {
+ regression: should not be visible;
+}
+.conditions-parser-1 when (8+4 < 13) {
+ only-atomic: ok;
+}
+.conditions-parser-1 when (8+6 < 13) {
+ only-atomic: should not be visible;
+}
+.conditions-parser-2 when (8+(5-1) < 13) {
+ only-atomic-with-nested-parenthesis: ok;
+}
+.conditions-parser-2 when (8+(15-1) < 13) {
+ only-atomic-with-nested-parenthesis: should not be visible;
+}
+.conditions-parser-3 when (8 < (13+1)) {
+ only-atomic-nested-parenthesis-on-right: ok;
+}
+.conditions-parser-3 when (8 < (3+1)) {
+ only-atomic-nested-parenthesis-on-right: should not be visible;
+}
+
+=====================================output=====================================
+// https://github.com/less/less.js/issues/2798
+.test-rule-2798 when ((8+4) < 13) {
+ regression: fixed;
+}
+.test-rule-2798 when ((8+6) < 13) {
+ regression: should not be visible;
+}
+.conditions-parser-1 when (8+4 < 13) {
+ only-atomic: ok;
+}
+.conditions-parser-1 when (8+6 < 13) {
+ only-atomic: should not be visible;
+}
+.conditions-parser-2 when (8+(5-1) < 13) {
+ only-atomic-with-nested-parenthesis: ok;
+}
+.conditions-parser-2 when (8+(15-1) < 13) {
+ only-atomic-with-nested-parenthesis: should not be visible;
+}
+.conditions-parser-3 when (8 < (13+1)) {
+ only-atomic-nested-parenthesis-on-right: ok;
+}
+.conditions-parser-3 when (8 < (3+1)) {
+ only-atomic-nested-parenthesis-on-right: should not be visible;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-always/no-sm-operations.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.named-colors-in-expressions {
+ color-0: 0 -red;
+ color-1: 1 - red;
+ color-2: red * 2;
+ color-3: 2 * red;
+ @3: -red;
+ &-bar@{3} {x: y}
+ @color: red;
+ &-bar@{color} {a: a};
+ background-color: blue-2;
+ color: green-black;
+ animation: blue-change 5s infinite;
+}
+.division {
+ value: ((16px ./ 2) / 2) / 2;
+}
+=====================================output=====================================
+.named-colors-in-expressions {
+ color-0: 0 -red;
+ color-1: 1 - red;
+ color-2: red * 2;
+ color-3: 2 * red;
+ @3: -red;
+ &-bar@{3} {
+ x: y;
+ }
+ @color: red;
+ &-bar@{color} {
+ a: a;
+ }
+ background-color: blue-2;
+ color: green-black;
+ animation: blue-change 5s infinite;
+}
+.division {
+ value: ((16px ./ 2) / 2) / 2;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-parens-division/media-math.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@var: 10 + 6;
+
+@media (min-width: @var + 1) {
+ .foo { bar: 1; }
+}
+
+@media (min-width: @var / 9) {
+ .foo { bar: 1; }
+}
+=====================================output=====================================
+@var: 10 + 6;
+
+@media (min-width: @var + 1) {
+ .foo {
+ bar: 1;
+ }
+}
+
+@media (min-width: @var / 9) {
+ .foo {
+ bar: 1;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-parens-division/mixins-args.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mixin (@a: 1px, @b: 50%) {
+ width: (@a * 5);
+ height: (@b - 1%);
+ depth: @b - 1%;
+}
+
+.mixina (@style, @width, @color: black) {
+ border: @width @style @color;
+}
+
+.mixiny
+(@a: 0, @b: 0) {
+ margin: @a;
+ padding: @b;
+}
+
+.hidden() {
+ color: transparent; // asd
+}
+
+#hidden {
+ .hidden();
+}
+
+#hidden1 {
+ .hidden();
+}
+
+.two-args {
+ color: blue;
+ .mixin(2px, 100%);
+ .mixina(dotted, 2px);
+}
+
+.one-arg {
+ .mixin(3px);
+}
+
+.no-args {
+ .mixin();
+}
+
+.var-args {
+ @var: 9;
+ .mixin(@var, (@var * 2) / 2);
+}
+
+.multi-mix {
+ .mixin(2px, 30%);
+ .mixiny(4, 5);
+}
+
+.maxa(@arg1: 10, @arg2: #f00) {
+ padding: (@arg1 * 2px);
+ color: @arg2;
+}
+
+body {
+ .maxa(15);
+}
+
+@glob: 5;
+.global-mixin(@a:2) {
+ width: (@glob + @a);
+}
+
+.scope-mix {
+ .global-mixin(3);
+}
+
+.nested-ruleset (@width: 200px) {
+ width: @width;
+ .column { margin: @width; }
+}
+.content {
+ .nested-ruleset(600px);
+}
+
+//
+
+.same-var-name2(@radius) {
+ radius: @radius;
+}
+.same-var-name(@radius) {
+ .same-var-name2(@radius);
+}
+#same-var-name {
+ .same-var-name(5px);
+}
+
+//
+
+.var-inside () {
+ @var: 10px;
+ width: @var;
+}
+#var-inside { .var-inside(); }
+
+.mixin-arguments (@width: 0px, ...) {
+ border: @arguments;
+ width: @width;
+}
+
+.arguments {
+ .mixin-arguments(1px, solid, black);
+}
+.arguments2 {
+ .mixin-arguments();
+}
+.arguments3 {
+ .mixin-arguments();
+}
+
+.mixin-arguments2 (@width, @rest...) {
+ border: @arguments;
+ rest: @rest;
+ width: @width;
+}
+.arguments4 {
+ .mixin-arguments2(0, 1, 2, 3, 4);
+}
+
+// Edge cases
+
+.edge-case {
+ .mixin-arguments("{");
+}
+
+// Division vs. Literal Slash
+.border-radius(@r: 2px/5px) {
+ border-radius: @r;
+}
+.slash-vs-math {
+ .border-radius();
+ .border-radius(5px/10px);
+ .border-radius((3px * 2));
+}
+// semi-colon vs comma for delimiting
+
+.mixin-takes-one(@a) {
+ one: @a;
+}
+
+.mixin-takes-two(@a; @b) {
+ one: @a;
+ two: @b;
+}
+
+.comma-vs-semi-colon {
+ .mixin-takes-two(@a : a; @b : b, c);
+ .mixin-takes-two(@a : d, e; @b : f);
+ .mixin-takes-one(@a: g);
+ .mixin-takes-one(@a : h;);
+ .mixin-takes-one(i);
+ .mixin-takes-one(j;);
+ .mixin-takes-two(k, l);
+ .mixin-takes-one(m, n;);
+ .mixin-takes-two(o, p; q);
+ .mixin-takes-two(r, s; t;);
+}
+
+.mixin-conflict(@a:defA, @b:defB, @c:defC) {
+ three: @a, @b, @c;
+}
+
+.mixin-conflict(@a:defA, @b:defB, @c:defC, @d:defD) {
+ four: @a, @b, @c, @d;
+}
+
+#named-conflict {
+ .mixin-conflict(11, 12, 13, @a:a);
+ .mixin-conflict(@a:a, 21, 22, 23);
+}
+@a: 3px;
+.mixin-default-arg(@a: 1px, @b: @a, @c: @b) {
+ defaults: 1px 1px 1px;
+ defaults: 2px 2px 2px;
+}
+
+.test-rule-mixin-default-arg {
+ .mixin-default-arg();
+ .mixin-default-arg(2px);
+}
+
+.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) {
+ margin: @margin;
+}
+.selector {
+ .mixin-comma-default1(#33acfe; 4);
+}
+.mixin-comma-default2(@margin: 2, 2, 2, 2;) {
+ margin: @margin;
+}
+.selector2 {
+ .mixin-comma-default2();
+}
+.mixin-comma-default3(@margin: 2, 2, 2, 2) {
+ margin: @margin;
+}
+.selector3 {
+ .mixin-comma-default3(4,2,2,2);
+}
+
+.test-rule-calling-one-arg-mixin(@a) {
+}
+
+.test-rule-calling-one-arg-mixin(@a, @b, @rest...) {
+}
+
+div {
+ .test-rule-calling-one-arg-mixin(1);
+}
+
+mixins-args-expand-op- {
+ @x: 1, 2, 3;
+ @y: 4 5 6;
+
+ &1 {.m3(@x...)}
+ &2 {.m3(@y...)}
+ &3 {.wr(a, b, c)}
+ &4 {.wr(a; b; c, d)}
+ &5 {.wr(@x...)}
+ &6 {.m4(0; @x...)}
+ &7 {.m4(@x..., @a: 0)}
+ &8 {.m4(@b: 1.5; @x...)}
+ &9 {.aa(@y, @x..., and again, @y...)}
+
+ .m3(@a, @b, @c) {
+ m3: @a, @b, @c;
+ }
+
+ .m4(@a, @b, @c, @d) {
+ m4: @a, @b, @c, @d;
+ }
+
+ .wr(@a...) {
+ &a {.m3(@a...)}
+ &b {.m4(0, @a...)}
+ &c {.m4(@a..., 4)}
+ }
+
+ .aa(@a...) {
+ aa: @a;
+ a4: extract(@a, 5);
+ a8: extract(@a, 8);
+ }
+}
+#test-mixin-matching-when-default-2645 {
+ .mixin(@height) {
+ height: @height;
+ }
+
+ .mixin(@width, @height: 10px) {
+ width: @width;
+
+ .mixin(@height: @height);
+ }
+
+ .mixin(@height: 20px);
+}
+=====================================output=====================================
+.mixin (@a: 1px, @b: 50%) {
+ width: (@a * 5);
+ height: (@b - 1%);
+ depth: @b - 1%;
+}
+
+.mixina (@style, @width, @color: black) {
+ border: @width @style @color;
+}
+
+.mixiny (@a: 0, @b: 0) {
+ margin: @a;
+ padding: @b;
+}
+
+.hidden() {
+ color: transparent; // asd
+}
+
+#hidden {
+ .hidden();
+}
+
+#hidden1 {
+ .hidden();
+}
+
+.two-args {
+ color: blue;
+ .mixin(2px, 100%);
+ .mixina(dotted, 2px);
+}
+
+.one-arg {
+ .mixin(3px);
+}
+
+.no-args {
+ .mixin();
+}
+
+.var-args {
+ @var: 9;
+ .mixin(@var, (@var * 2) / 2);
+}
+
+.multi-mix {
+ .mixin(2px, 30%);
+ .mixiny(4, 5);
+}
+
+.maxa(@arg1: 10, @arg2: #f00) {
+ padding: (@arg1 * 2px);
+ color: @arg2;
+}
+
+body {
+ .maxa(15);
+}
+
+@glob: 5;
+.global-mixin(@a:2) {
+ width: (@glob + @a);
+}
+
+.scope-mix {
+ .global-mixin(3);
+}
+
+.nested-ruleset (@width: 200px) {
+ width: @width;
+ .column {
+ margin: @width;
+ }
+}
+.content {
+ .nested-ruleset(600px);
+}
+
+//
+
+.same-var-name2(@radius) {
+ radius: @radius;
+}
+.same-var-name(@radius) {
+ .same-var-name2(@radius);
+}
+#same-var-name {
+ .same-var-name(5px);
+}
+
+//
+
+.var-inside () {
+ @var: 10px;
+ width: @var;
+}
+#var-inside {
+ .var-inside();
+}
+
+.mixin-arguments (@width: 0px, ...) {
+ border: @arguments;
+ width: @width;
+}
+
+.arguments {
+ .mixin-arguments(1px, solid, black);
+}
+.arguments2 {
+ .mixin-arguments();
+}
+.arguments3 {
+ .mixin-arguments();
+}
+
+.mixin-arguments2 (@width, @rest...) {
+ border: @arguments;
+ rest: @rest;
+ width: @width;
+}
+.arguments4 {
+ .mixin-arguments2(0, 1, 2, 3, 4);
+}
+
+// Edge cases
+
+.edge-case {
+ .mixin-arguments("{");
+}
+
+// Division vs. Literal Slash
+.border-radius(@r: 2px/5px) {
+ border-radius: @r;
+}
+.slash-vs-math {
+ .border-radius();
+ .border-radius(5px/10px);
+ .border-radius((3px * 2));
+}
+// semi-colon vs comma for delimiting
+
+.mixin-takes-one(@a) {
+ one: @a;
+}
+
+.mixin-takes-two(@a; @b) {
+ one: @a;
+ two: @b;
+}
+
+.comma-vs-semi-colon {
+ .mixin-takes-two(@a : a; @b : b, c);
+ .mixin-takes-two(@a : d, e; @b : f);
+ .mixin-takes-one(@a: g);
+ .mixin-takes-one(@a : h;);
+ .mixin-takes-one(i);
+ .mixin-takes-one(j;);
+ .mixin-takes-two(k, l);
+ .mixin-takes-one(m, n;);
+ .mixin-takes-two(o, p; q);
+ .mixin-takes-two(r, s; t;);
+}
+
+.mixin-conflict(@a:defA, @b:defB, @c:defC) {
+ three: @a, @b, @c;
+}
+
+.mixin-conflict(@a:defA, @b:defB, @c:defC, @d:defD) {
+ four: @a, @b, @c, @d;
+}
+
+#named-conflict {
+ .mixin-conflict(11, 12, 13, @a:a);
+ .mixin-conflict(@a:a, 21, 22, 23);
+}
+@a: 3px;
+.mixin-default-arg(@a: 1px, @b: @a, @c: @b) {
+ defaults: 1px 1px 1px;
+ defaults: 2px 2px 2px;
+}
+
+.test-rule-mixin-default-arg {
+ .mixin-default-arg();
+ .mixin-default-arg(2px);
+}
+
+.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) {
+ margin: @margin;
+}
+.selector {
+ .mixin-comma-default1(#33acfe; 4);
+}
+.mixin-comma-default2(@margin: 2, 2, 2, 2;) {
+ margin: @margin;
+}
+.selector2 {
+ .mixin-comma-default2();
+}
+.mixin-comma-default3(@margin: 2, 2, 2, 2) {
+ margin: @margin;
+}
+.selector3 {
+ .mixin-comma-default3(4,2,2,2);
+}
+
+.test-rule-calling-one-arg-mixin(@a) {
+}
+
+.test-rule-calling-one-arg-mixin(@a, @b, @rest...) {
+}
+
+div {
+ .test-rule-calling-one-arg-mixin(1);
+}
+
+mixins-args-expand-op- {
+ @x: 1, 2, 3;
+ @y: 4 5 6;
+
+ &1 {
+ .m3(@x...);
+ }
+ &2 {
+ .m3(@y...);
+ }
+ &3 {
+ .wr(a, b, c);
+ }
+ &4 {
+ .wr(a; b; c, d);
+ }
+ &5 {
+ .wr(@x...);
+ }
+ &6 {
+ .m4(0; @x...);
+ }
+ &7 {
+ .m4(@x..., @a: 0);
+ }
+ &8 {
+ .m4(@b: 1.5; @x...);
+ }
+ &9 {
+ .aa(@y, @x..., and again, @y...);
+ }
+
+ .m3(@a, @b, @c) {
+ m3: @a, @b, @c;
+ }
+
+ .m4(@a, @b, @c, @d) {
+ m4: @a, @b, @c, @d;
+ }
+
+ .wr(@a...) {
+ &a {
+ .m3(@a...);
+ }
+ &b {
+ .m4(0, @a...);
+ }
+ &c {
+ .m4(@a..., 4);
+ }
+ }
+
+ .aa(@a...) {
+ aa: @a;
+ a4: extract(@a, 5);
+ a8: extract(@a, 8);
+ }
+}
+#test-mixin-matching-when-default-2645 {
+ .mixin(@height) {
+ height: @height;
+ }
+
+ .mixin(@width, @height: 10px) {
+ width: @width;
+
+ .mixin(@height: @height);
+ }
+
+ .mixin(@height: 20px);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-parens-division/new-division.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.units {
+ font: 1.2rem/2rem;
+ font: 8vw/9vw;
+ font: 10vh/12vh;
+ font: 12vm/15vm;
+ font: 12vmin/15vmin;
+ font: 1.2ch/1.5ch;
+}
+
+.math {
+ a: 1 + 1;
+ b: 2px / 2;
+ c: 2px ./ 2;
+ d: (10px / 10px);
+ e: ((16px ./ 2) / 2) / 2;
+ f: ((16px ./ 2) / 2) ./ 2;
+}
+=====================================output=====================================
+.units {
+ font: 1.2rem/2rem;
+ font: 8vw/9vw;
+ font: 10vh/12vh;
+ font: 12vm/15vm;
+ font: 12vmin/15vmin;
+ font: 1.2ch/1.5ch;
+}
+
+.math {
+ a: 1 + 1;
+ b: 2px / 2;
+ c: 2px ./ 2;
+ d: (10px / 10px);
+ e: ((16px ./ 2) / 2) / 2;
+ f: ((16px ./ 2) / 2) ./ 2;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-parens-division/parens.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.parens-issues-3616 {
+ bar: if(false, 666, 888 / 444);
+ bar2: if(false, 666, (666 / 333));
+ bar3: if(false, 666, ((444 / 222)));
+}
+
+.parens {
+ @var: 1px;
+ border: (@var * 2) solid black;
+ margin: (@var * 1) (@var + 2) (4 * 4) 3;
+ width: (6 * 6);
+ padding: 2px (6 * 6px);
+}
+
+.more-parens {
+ @var: (2 * 2);
+ padding: (2 * @var) 4 4 (@var * 1px);
+ width-all: ((@var * @var) * 6);
+ width-first: ((@var * @var)) * 6;
+ width-keep: (@var * @var) * 6;
+ height: calc(100% + (25vh - 20px));
+ height-keep: (7 * 7) + (8 * 8);
+ height-all: ((7 * 7) + (8 * 8));
+ height-parts: ((7 * 7)) + ((8 * 8));
+ margin-keep: (4 * (5 + 5) / 2) - (@var * 2);
+ margin-parts: ((4 * (5 + 5) / 2)) - ((@var * 2));
+ margin-all: ((4 * (5 + 5) / 2) + (-(@var * 2)));
+ border-radius-keep: 4px * (1 + 1) / @var + 3px;
+ border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px));
+ border-radius-all: (4px * (1 + 1) / @var + 3px);
+ // margin: (6 * 6)px;
+}
+
+.negative {
+ @var: 1;
+ neg-var: -@var; // -1 ?
+ neg-var-paren: -(@var); // -(1) ?
+}
+
+.nested-parens {
+ width: 2 * (4 * (2 + (1 + 6))) - 1;
+ height: ((2 + 3) * (2 + 3) / (9 - 4)) + 1;
+}
+
+.mixed-units {
+ margin: 2px 4em 1 5pc;
+ padding: (2px + 4px) 1em 2px 2;
+}
+
+.test-rule-false-negatives {
+ a: ~"(";
+}
+
+=====================================output=====================================
+.parens-issues-3616 {
+ bar: if(false, 666, 888 / 444);
+ bar2: if(false, 666, (666 / 333));
+ bar3: if(false, 666, ((444 / 222)));
+}
+
+.parens {
+ @var: 1px;
+ border: (@var * 2) solid black;
+ margin: (@var * 1) (@var + 2) (4 * 4) 3;
+ width: (6 * 6);
+ padding: 2px (6 * 6px);
+}
+
+.more-parens {
+ @var: (2 * 2);
+ padding: (2 * @var) 4 4 (@var * 1px);
+ width-all: ((@var * @var) * 6);
+ width-first: ((@var * @var)) * 6;
+ width-keep: (@var * @var) * 6;
+ height: calc(100% + (25vh - 20px));
+ height-keep: (7 * 7) + (8 * 8);
+ height-all: ((7 * 7) + (8 * 8));
+ height-parts: ((7 * 7)) + ((8 * 8));
+ margin-keep: (4 * (5 + 5) / 2) - (@var * 2);
+ margin-parts: ((4 * (5 + 5) / 2)) - ((@var * 2));
+ margin-all: ((4 * (5 + 5) / 2) + (-(@var * 2)));
+ border-radius-keep: 4px * (1 + 1) / @var + 3px;
+ border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px));
+ border-radius-all: (4px * (1 + 1) / @var + 3px);
+ // margin: (6 * 6)px;
+}
+
+.negative {
+ @var: 1;
+ neg-var: -@var; // -1 ?
+ neg-var-paren: -(@var); // -(1) ?
+}
+
+.nested-parens {
+ width: 2 * (4 * (2 + (1 + 6))) - 1;
+ height: ((2 + 3) * (2 + 3) / (9 - 4)) + 1;
+}
+
+.mixed-units {
+ margin: 2px 4em 1 5pc;
+ padding: (2px + 4px) 1em 2px 2;
+}
+
+.test-rule-false-negatives {
+ a: ~"(";
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-strict/css.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@charset "utf-8";
+div { color: black; }
+div { width: 99%; }
+
+* {
+ min-width: 45em;
+}
+
+h1, h2 > a > p, h3 {
+ color: none;
+}
+
+div.class {
+ color: blue;
+}
+
+div#id {
+ color: green;
+}
+
+.class#id {
+ color: purple;
+}
+
+.one.two.three {
+ color: grey;
+}
+
+@media print {
+ * {
+ font-size: 3em;
+ }
+}
+
+@media screen {
+ * {
+ font-size: 10px;
+ }
+}
+
+@font-face {
+ font-family: 'Garamond Pro';
+}
+
+a:hover, a:link {
+ color: #999;
+}
+
+p, p:first-child {
+ text-transform: none;
+}
+
+q:lang(no) {
+ quotes: none;
+}
+
+p + h1 {
+ font-size: +2.2em;
+}
+
+#shorthands {
+ border: 1px solid #000;
+ font: 12px/16px Arial;
+ font: 100%/16px Arial;
+ margin: 1px 0;
+ padding: 0 auto;
+}
+
+#more-shorthands {
+ margin: 0;
+ padding: 1px 0 2px 0;
+ font: normal small/20px 'Trebuchet MS', Verdana, sans-serif;
+ font: 0/0 a;
+ border-radius: 5px / 10px;
+}
+
+.misc {
+ -moz-border-radius: 2px;
+ display: -moz-inline-stack;
+ width: .1em;
+ background-color: #009998;
+ background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
+ margin: ;
+ .nested-multiple {
+ multiple-semi-colons: yes;;;;;;
+ };
+ filter: alpha(opacity=100);
+ width: auto\\9;
+}
+
+#important {
+ color: red !important;
+ width: 100%!important;
+ height: 20px ! important;
+}
+
+.def-font(@name) {
+ @font-face {
+ font-family: @name
+ }
+}
+
+.def-font(font-a);
+.def-font(font-b);
+
+.æøå {
+ margin: 0;
+}
+
+=====================================output=====================================
+@charset "utf-8";
+div {
+ color: black;
+}
+div {
+ width: 99%;
+}
+
+* {
+ min-width: 45em;
+}
+
+h1,
+h2 > a > p,
+h3 {
+ color: none;
+}
+
+div.class {
+ color: blue;
+}
+
+div#id {
+ color: green;
+}
+
+.class#id {
+ color: purple;
+}
+
+.one.two.three {
+ color: grey;
+}
+
+@media print {
+ * {
+ font-size: 3em;
+ }
+}
+
+@media screen {
+ * {
+ font-size: 10px;
+ }
+}
+
+@font-face {
+ font-family: "Garamond Pro";
+}
+
+a:hover,
+a:link {
+ color: #999;
+}
+
+p,
+p:first-child {
+ text-transform: none;
+}
+
+q:lang(no) {
+ quotes: none;
+}
+
+p + h1 {
+ font-size: +2.2em;
+}
+
+#shorthands {
+ border: 1px solid #000;
+ font: 12px/16px Arial;
+ font: 100%/16px Arial;
+ margin: 1px 0;
+ padding: 0 auto;
+}
+
+#more-shorthands {
+ margin: 0;
+ padding: 1px 0 2px 0;
+ font:
+ normal small/20px "Trebuchet MS",
+ Verdana,
+ sans-serif;
+ font: 0/0 a;
+ border-radius: 5px / 10px;
+}
+
+.misc {
+ -moz-border-radius: 2px;
+ display: -moz-inline-stack;
+ width: 0.1em;
+ background-color: #009998;
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ from(red),
+ to(blue)
+ );
+ margin:;
+ .nested-multiple {
+ multiple-semi-colons: yes;
+ }
+ filter: alpha(opacity=100);
+ width: auto\\9;
+}
+
+#important {
+ color: red !important;
+ width: 100% !important;
+ height: 20px !important;
+}
+
+.def-font(@name) {
+ @font-face {
+ font-family: @name;
+ }
+}
+
+.def-font(font-a);
+.def-font(font-b);
+
+.æøå {
+ margin: 0;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-strict/media-math.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@var: 16;
+
+@media (min-width: @var + 1) {
+ .foo { bar: 1; }
+}
+
+@media (min-width: @var / 9) {
+ .foo { bar: 1; }
+}
+=====================================output=====================================
+@var: 16;
+
+@media (min-width: @var + 1) {
+ .foo {
+ bar: 1;
+ }
+}
+
+@media (min-width: @var / 9) {
+ .foo {
+ bar: 1;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-strict/mixins-args.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mixin (@a: 1px, @b: 50%) {
+ width: (@a * 5);
+ height: (@b - 1%);
+ depth: @b - 1%;
+}
+
+.mixina (@style, @width, @color: black) {
+ border: @width @style @color;
+}
+
+.mixiny
+(@a: 0, @b: 0) {
+ margin: @a;
+ padding: @b;
+}
+
+.hidden() {
+ color: transparent; // asd
+}
+
+#hidden {
+ .hidden();
+}
+
+#hidden1 {
+ .hidden();
+}
+
+.two-args {
+ color: blue;
+ .mixin(2px, 100%);
+ .mixina(dotted, 2px);
+}
+
+.one-arg {
+ .mixin(3px);
+}
+
+.no-args {
+ .mixin();
+}
+
+.var-args {
+ @var: 9;
+ .mixin(@var, (@var * 2) / 2);
+}
+
+.multi-mix {
+ .mixin(2px, 30%);
+ .mixiny(4, 5);
+}
+
+.maxa(@arg1: 10, @arg2: #f00) {
+ padding: (@arg1 * 2px);
+ color: @arg2;
+}
+
+body {
+ .maxa(15);
+}
+
+@glob: 5;
+.global-mixin(@a:2) {
+ width: (@glob + @a);
+}
+
+.scope-mix {
+ .global-mixin(3);
+}
+
+.nested-ruleset (@width: 200px) {
+ width: @width;
+ .column { margin: @width; }
+}
+.content {
+ .nested-ruleset(600px);
+}
+
+//
+
+.same-var-name2(@radius) {
+ radius: @radius;
+}
+.same-var-name(@radius) {
+ .same-var-name2(@radius);
+}
+#same-var-name {
+ .same-var-name(5px);
+}
+
+//
+
+.var-inside () {
+ @var: 10px;
+ width: @var;
+}
+#var-inside { .var-inside(); }
+
+.mixin-arguments (@width: 0px, ...) {
+ border: @arguments;
+ width: @width;
+}
+
+.arguments {
+ .mixin-arguments(1px, solid, black);
+}
+.arguments2 {
+ .mixin-arguments();
+}
+.arguments3 {
+ .mixin-arguments();
+}
+
+.mixin-arguments2 (@width, @rest...) {
+ border: @arguments;
+ rest: @rest;
+ width: @width;
+}
+.arguments4 {
+ .mixin-arguments2(0, 1, 2, 3, 4);
+}
+
+// Edge cases
+
+.edge-case {
+ .mixin-arguments("{");
+}
+
+// Division vs. Literal Slash
+.border-radius(@r: 2px/5px) {
+ border-radius: @r;
+}
+.slash-vs-math {
+ .border-radius();
+ .border-radius(5px/10px);
+ .border-radius((3px * 2));
+}
+// semi-colon vs comma for delimiting
+
+.mixin-takes-one(@a) {
+ one: @a;
+}
+
+.mixin-takes-two(@a; @b) {
+ one: @a;
+ two: @b;
+}
+
+.comma-vs-semi-colon {
+ .mixin-takes-two(@a : a; @b : b, c);
+ .mixin-takes-two(@a : d, e; @b : f);
+ .mixin-takes-one(@a: g);
+ .mixin-takes-one(@a : h;);
+ .mixin-takes-one(i);
+ .mixin-takes-one(j;);
+ .mixin-takes-two(k, l);
+ .mixin-takes-one(m, n;);
+ .mixin-takes-two(o, p; q);
+ .mixin-takes-two(r, s; t;);
+}
+
+.mixin-conflict(@a:defA, @b:defB, @c:defC) {
+ three: @a, @b, @c;
+}
+
+.mixin-conflict(@a:defA, @b:defB, @c:defC, @d:defD) {
+ four: @a, @b, @c, @d;
+}
+
+#named-conflict {
+ .mixin-conflict(11, 12, 13, @a:a);
+ .mixin-conflict(@a:a, 21, 22, 23);
+}
+@a: 3px;
+.mixin-default-arg(@a: 1px, @b: @a, @c: @b) {
+ defaults: 1px 1px 1px;
+ defaults: 2px 2px 2px;
+}
+
+.test-rule-mixin-default-arg {
+ .mixin-default-arg();
+ .mixin-default-arg(2px);
+}
+
+.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) {
+ margin: @margin;
+}
+.selector {
+ .mixin-comma-default1(#33acfe; 4);
+}
+.mixin-comma-default2(@margin: 2, 2, 2, 2;) {
+ margin: @margin;
+}
+.selector2 {
+ .mixin-comma-default2();
+}
+.mixin-comma-default3(@margin: 2, 2, 2, 2) {
+ margin: @margin;
+}
+.selector3 {
+ .mixin-comma-default3(4,2,2,2);
+}
+
+.test-rule-calling-one-arg-mixin(@a) {
+}
+
+.test-rule-calling-one-arg-mixin(@a, @b, @rest...) {
+}
+
+div {
+ .test-rule-calling-one-arg-mixin(1);
+}
+
+mixins-args-expand-op- {
+ @x: 1, 2, 3;
+ @y: 4 5 6;
+
+ &1 {.m3(@x...)}
+ &2 {.m3(@y...)}
+ &3 {.wr(a, b, c)}
+ &4 {.wr(a; b; c, d)}
+ &5 {.wr(@x...)}
+ &6 {.m4(0; @x...)}
+ &7 {.m4(@x..., @a: 0)}
+ &8 {.m4(@b: 1.5; @x...)}
+ &9 {.aa(@y, @x..., and again, @y...)}
+
+ .m3(@a, @b, @c) {
+ m3: @a, @b, @c;
+ }
+
+ .m4(@a, @b, @c, @d) {
+ m4: @a, @b, @c, @d;
+ }
+
+ .wr(@a...) {
+ &a {.m3(@a...)}
+ &b {.m4(0, @a...)}
+ &c {.m4(@a..., 4)}
+ }
+
+ .aa(@a...) {
+ aa: @a;
+ a4: extract(@a, 5);
+ a8: extract(@a, 8);
+ }
+}
+#test-mixin-matching-when-default-2645 {
+ .mixin(@height) {
+ height: @height;
+ }
+
+ .mixin(@width, @height: 10px) {
+ width: @width;
+
+ .mixin(@height: @height);
+ }
+
+ .mixin(@height: 20px);
+}
+=====================================output=====================================
+.mixin (@a: 1px, @b: 50%) {
+ width: (@a * 5);
+ height: (@b - 1%);
+ depth: @b - 1%;
+}
+
+.mixina (@style, @width, @color: black) {
+ border: @width @style @color;
+}
+
+.mixiny (@a: 0, @b: 0) {
+ margin: @a;
+ padding: @b;
+}
+
+.hidden() {
+ color: transparent; // asd
+}
+
+#hidden {
+ .hidden();
+}
+
+#hidden1 {
+ .hidden();
+}
+
+.two-args {
+ color: blue;
+ .mixin(2px, 100%);
+ .mixina(dotted, 2px);
+}
+
+.one-arg {
+ .mixin(3px);
+}
+
+.no-args {
+ .mixin();
+}
+
+.var-args {
+ @var: 9;
+ .mixin(@var, (@var * 2) / 2);
+}
+
+.multi-mix {
+ .mixin(2px, 30%);
+ .mixiny(4, 5);
+}
+
+.maxa(@arg1: 10, @arg2: #f00) {
+ padding: (@arg1 * 2px);
+ color: @arg2;
+}
+
+body {
+ .maxa(15);
+}
+
+@glob: 5;
+.global-mixin(@a:2) {
+ width: (@glob + @a);
+}
+
+.scope-mix {
+ .global-mixin(3);
+}
+
+.nested-ruleset (@width: 200px) {
+ width: @width;
+ .column {
+ margin: @width;
+ }
+}
+.content {
+ .nested-ruleset(600px);
+}
+
+//
+
+.same-var-name2(@radius) {
+ radius: @radius;
+}
+.same-var-name(@radius) {
+ .same-var-name2(@radius);
+}
+#same-var-name {
+ .same-var-name(5px);
+}
+
+//
+
+.var-inside () {
+ @var: 10px;
+ width: @var;
+}
+#var-inside {
+ .var-inside();
+}
+
+.mixin-arguments (@width: 0px, ...) {
+ border: @arguments;
+ width: @width;
+}
+
+.arguments {
+ .mixin-arguments(1px, solid, black);
+}
+.arguments2 {
+ .mixin-arguments();
+}
+.arguments3 {
+ .mixin-arguments();
+}
+
+.mixin-arguments2 (@width, @rest...) {
+ border: @arguments;
+ rest: @rest;
+ width: @width;
+}
+.arguments4 {
+ .mixin-arguments2(0, 1, 2, 3, 4);
+}
+
+// Edge cases
+
+.edge-case {
+ .mixin-arguments("{");
+}
+
+// Division vs. Literal Slash
+.border-radius(@r: 2px/5px) {
+ border-radius: @r;
+}
+.slash-vs-math {
+ .border-radius();
+ .border-radius(5px/10px);
+ .border-radius((3px * 2));
+}
+// semi-colon vs comma for delimiting
+
+.mixin-takes-one(@a) {
+ one: @a;
+}
+
+.mixin-takes-two(@a; @b) {
+ one: @a;
+ two: @b;
+}
+
+.comma-vs-semi-colon {
+ .mixin-takes-two(@a : a; @b : b, c);
+ .mixin-takes-two(@a : d, e; @b : f);
+ .mixin-takes-one(@a: g);
+ .mixin-takes-one(@a : h;);
+ .mixin-takes-one(i);
+ .mixin-takes-one(j;);
+ .mixin-takes-two(k, l);
+ .mixin-takes-one(m, n;);
+ .mixin-takes-two(o, p; q);
+ .mixin-takes-two(r, s; t;);
+}
+
+.mixin-conflict(@a:defA, @b:defB, @c:defC) {
+ three: @a, @b, @c;
+}
+
+.mixin-conflict(@a:defA, @b:defB, @c:defC, @d:defD) {
+ four: @a, @b, @c, @d;
+}
+
+#named-conflict {
+ .mixin-conflict(11, 12, 13, @a:a);
+ .mixin-conflict(@a:a, 21, 22, 23);
+}
+@a: 3px;
+.mixin-default-arg(@a: 1px, @b: @a, @c: @b) {
+ defaults: 1px 1px 1px;
+ defaults: 2px 2px 2px;
+}
+
+.test-rule-mixin-default-arg {
+ .mixin-default-arg();
+ .mixin-default-arg(2px);
+}
+
+.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) {
+ margin: @margin;
+}
+.selector {
+ .mixin-comma-default1(#33acfe; 4);
+}
+.mixin-comma-default2(@margin: 2, 2, 2, 2;) {
+ margin: @margin;
+}
+.selector2 {
+ .mixin-comma-default2();
+}
+.mixin-comma-default3(@margin: 2, 2, 2, 2) {
+ margin: @margin;
+}
+.selector3 {
+ .mixin-comma-default3(4,2,2,2);
+}
+
+.test-rule-calling-one-arg-mixin(@a) {
+}
+
+.test-rule-calling-one-arg-mixin(@a, @b, @rest...) {
+}
+
+div {
+ .test-rule-calling-one-arg-mixin(1);
+}
+
+mixins-args-expand-op- {
+ @x: 1, 2, 3;
+ @y: 4 5 6;
+
+ &1 {
+ .m3(@x...);
+ }
+ &2 {
+ .m3(@y...);
+ }
+ &3 {
+ .wr(a, b, c);
+ }
+ &4 {
+ .wr(a; b; c, d);
+ }
+ &5 {
+ .wr(@x...);
+ }
+ &6 {
+ .m4(0; @x...);
+ }
+ &7 {
+ .m4(@x..., @a: 0);
+ }
+ &8 {
+ .m4(@b: 1.5; @x...);
+ }
+ &9 {
+ .aa(@y, @x..., and again, @y...);
+ }
+
+ .m3(@a, @b, @c) {
+ m3: @a, @b, @c;
+ }
+
+ .m4(@a, @b, @c, @d) {
+ m4: @a, @b, @c, @d;
+ }
+
+ .wr(@a...) {
+ &a {
+ .m3(@a...);
+ }
+ &b {
+ .m4(0, @a...);
+ }
+ &c {
+ .m4(@a..., 4);
+ }
+ }
+
+ .aa(@a...) {
+ aa: @a;
+ a4: extract(@a, 5);
+ a8: extract(@a, 8);
+ }
+}
+#test-mixin-matching-when-default-2645 {
+ .mixin(@height) {
+ height: @height;
+ }
+
+ .mixin(@width, @height: 10px) {
+ width: @width;
+
+ .mixin(@height: @height);
+ }
+
+ .mixin(@height: 20px);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/math-strict/parens.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.parens-issues-3616 {
+ bar: if(false, 666, 888 / 444);
+ bar2: if(false, 666, (666 / 333));
+ bar3: if(false, 666, ((444 / 222)));
+}
+
+.parens {
+ @var: 1px;
+ border: (@var * 2) solid black;
+ margin: (@var * 1) (@var + 2) (4 * 4) 3;
+ width: (6 * 6);
+ padding: 2px (6 * 6px);
+}
+
+.more-parens {
+ @var: (2 * 2);
+ padding: (2 * @var) 4 4 (@var * 1px);
+ width-all: ((@var * @var) * 6);
+ width-first: ((@var * @var)) * 6;
+ width-keep: (@var * @var) * 6;
+ height: calc(100% + (25vh - 20px));
+ height-keep: (7 * 7) + (8 * 8);
+ height-all: ((7 * 7) + (8 * 8));
+ height-parts: ((7 * 7)) + ((8 * 8));
+ margin-keep: (4 * (5 + 5) / 2) - (@var * 2);
+ margin-parts: ((4 * (5 + 5) / 2)) - ((@var * 2));
+ margin-all: ((4 * (5 + 5) / 2) + (-(@var * 2)));
+ border-radius-keep: 4px * (1 + 1) / @var + 3px;
+ border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px));
+ border-radius-all: (4px * (1 + 1) / @var + 3px);
+ // margin: (6 * 6)px;
+}
+
+.negative {
+ @var: 1;
+ neg-var: -@var; // -1 ?
+ neg-var-paren: -(@var); // -(1) ?
+}
+
+.nested-parens {
+ width: 2 * (4 * (2 + (1 + 6))) - 1;
+ height: ((2 + 3) * (2 + 3) / (9 - 4)) + 1;
+}
+
+.mixed-units {
+ margin: 2px 4em 1 5pc;
+ padding: (2px + 4px) 1em 2px 2;
+}
+
+.test-rule-false-negatives {
+ a: ~"(";
+}
+
+=====================================output=====================================
+.parens-issues-3616 {
+ bar: if(false, 666, 888 / 444);
+ bar2: if(false, 666, (666 / 333));
+ bar3: if(false, 666, ((444 / 222)));
+}
+
+.parens {
+ @var: 1px;
+ border: (@var * 2) solid black;
+ margin: (@var * 1) (@var + 2) (4 * 4) 3;
+ width: (6 * 6);
+ padding: 2px (6 * 6px);
+}
+
+.more-parens {
+ @var: (2 * 2);
+ padding: (2 * @var) 4 4 (@var * 1px);
+ width-all: ((@var * @var) * 6);
+ width-first: ((@var * @var)) * 6;
+ width-keep: (@var * @var) * 6;
+ height: calc(100% + (25vh - 20px));
+ height-keep: (7 * 7) + (8 * 8);
+ height-all: ((7 * 7) + (8 * 8));
+ height-parts: ((7 * 7)) + ((8 * 8));
+ margin-keep: (4 * (5 + 5) / 2) - (@var * 2);
+ margin-parts: ((4 * (5 + 5) / 2)) - ((@var * 2));
+ margin-all: ((4 * (5 + 5) / 2) + (-(@var * 2)));
+ border-radius-keep: 4px * (1 + 1) / @var + 3px;
+ border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px));
+ border-radius-all: (4px * (1 + 1) / @var + 3px);
+ // margin: (6 * 6)px;
+}
+
+.negative {
+ @var: 1;
+ neg-var: -@var; // -1 ?
+ neg-var-paren: -(@var); // -(1) ?
+}
+
+.nested-parens {
+ width: 2 * (4 * (2 + (1 + 6))) - 1;
+ height: ((2 + 3) * (2 + 3) / (9 - 4)) + 1;
+}
+
+.mixed-units {
+ margin: 2px 4em 1 5pc;
+ padding: (2px + 4px) 1em 2px 2;
+}
+
+.test-rule-false-negatives {
+ a: ~"(";
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/modifyVars/extended.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#header {
+ color: (@base-color * 3);
+ border-left: @the-border;
+ border-right: (@the-border * 2);
+}
+#footer {
+ color: (@base-color + #003300);
+ border-color: @red;
+}
+@red: blue; // var is overridden by the modifyVars
+//@base-color: green;
+=====================================output=====================================
+#header {
+ color: (@base-color * 3);
+ border-left: @the-border;
+ border-right: (@the-border * 2);
+}
+#footer {
+ color: (@base-color + #003300);
+ border-color: @red;
+}
+@red: blue; // var is overridden by the modifyVars
+//@base-color: green;
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/imports/a-better-bootstrap.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#theme() {
+ .light() {} //...
+ .dark() {
+ // ...
+ .navbar() {
+ .colors() {
+ primary: blue;
+ secondary: lightblue;
+ }
+ }
+ // ...
+ }
+}
+=====================================output=====================================
+#theme() {
+ .light() {
+ } //...
+ .dark() {
+ // ...
+ .navbar() {
+ .colors() {
+ primary: blue;
+ secondary: lightblue;
+ }
+ }
+ // ...
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/imports/library.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+
+// I am a library
+#library {
+ .sizes() {
+ @width: 600px;
+ }
+ .add-one(@val) {
+ @return: @val + 1px;
+ }
+ .sizes(@test) when (@test = true) {
+ @width: 400px;
+ }
+}
+
+
+=====================================output=====================================
+// I am a library
+#library {
+ .sizes() {
+ @width: 600px;
+ }
+ .add-one(@val) {
+ @return: @val + 1px;
+ }
+ .sizes(@test) when (@test = true) {
+ @width: 400px;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-1.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@varToGet: default-color;
+.foo {
+ color1: @defaults[@default-color];
+ color2: @defaults[@nested][@color];
+ color3: @theme[color];
+ color4: @theme[@nested][color];
+ color5: @defaults[@@varToGet];
+ prop: #ns1[foo];
+ var: #ns1[@foo];
+ sub: #ns1.vars[$sub];
+}
+
+@defaults: {
+ @default-color: red;
+ @nested: {
+ @color: yellow;
+ }
+};
+
+@theme: {
+ color: red;
+ @nested: {
+ color: yellow;
+ }
+};
+
+#ns1 {
+ foo: bar;
+ @foo: baz;
+ .vars() {
+ sub: value;
+ }
+}
+
+// Test that it matches more than one mixin
+#ns1 {
+ foo: uno;
+ @foo: dos;
+ .vars() {
+ sub: tres;
+ }
+}
+
+// https://github.com/less/less.js/issues/3346
+#DEF() {
+ .colors() { primary: grey; }
+}
+
+.button {
+ color: #DEF.colors[primary];
+ border-color: #AAA #CCC;
+}
+=====================================output=====================================
+@varToGet: default-color;
+.foo {
+ color1: @defaults[@default-color];
+ color2: @defaults[@nested][@color];
+ color3: @theme[color];
+ color4: @theme[@nested][color];
+ color5: @defaults[@@varToGet];
+ prop: #ns1[foo];
+ var: #ns1[ @foo];
+ sub: #ns1.vars[$sub];
+}
+
+@defaults: {
+ @default-color: red;
+ @nested: {
+ @color: yellow;
+ };
+};
+
+@theme: {
+ color: red;
+ @nested: {
+ color: yellow;
+ };
+};
+
+#ns1 {
+ foo: bar;
+ @foo: baz;
+ .vars() {
+ sub: value;
+ }
+}
+
+// Test that it matches more than one mixin
+#ns1 {
+ foo: uno;
+ @foo: dos;
+ .vars() {
+ sub: tres;
+ }
+}
+
+// https://github.com/less/less.js/issues/3346
+#DEF() {
+ .colors() {
+ primary: grey;
+ }
+}
+
+.button {
+ color: #DEF.colors[primary];
+ border-color: #aaa #ccc;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-2.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "imports/library.less";
+
+.bar {
+ width: #library.sizes[@width];
+ height: #library.add-one(1px)[@return];
+}
+
+// I'm gonna override some values
+#library {
+ .sizes() {
+ @width: 800px;
+ }
+}
+
+.foo {
+ width: #library.sizes[@width];
+}
+
+.foods() {
+ @dessert: ice cream;
+}
+
+@key-to-lookup: dessert;
+
+.lunch {
+ treat: .foods[@@key-to-lookup];
+}
+=====================================output=====================================
+@import "imports/library.less";
+
+.bar {
+ width: #library.sizes[ @width];
+ height: #library.add-one(1px)[@return];
+}
+
+// I'm gonna override some values
+#library {
+ .sizes() {
+ @width: 800px;
+ }
+}
+
+.foo {
+ width: #library.sizes[ @width];
+}
+
+.foods() {
+ @dessert: ice cream;
+}
+
+@key-to-lookup: dessert;
+
+.lunch {
+ treat: .foods[ @@key-to-lookup];
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-3.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@map: {
+ @width: 400px;
+ @colors: {
+ toolbar-background: red;
+ toolbar-foreground: inherit;
+ }
+};
+
+#ns {
+ .mixin() {
+ @height: 200px;
+ }
+}
+
+@breakpoints: {
+ mobile: 320px;
+ tablet: 768px;
+ desktop: 1024px;
+};
+
+@media (min-width: @breakpoints[mobile]) {
+ .toolbar {
+ width: @map[@width];
+ height: #ns.mixin[@height];
+ background: @map[@colors][toolbar-background];
+ color: @map[@colors][toolbar-foreground];
+ }
+}
+
+// !important after map usage
+// https://github.com/less/less.js/issues/3430
+@margins: {
+ zero: 0;
+ ten: 10px;
+}
+.cell {
+ margin: @margins[zero] (@margins[ten]/2) !important;
+}
+
+.mixin(@color: black; @margin: 10px; @padding: 20px) {
+ color: @color;
+ margin: @margin;
+ padding: @padding;
+ width: @margins[zero] !important
+}
+.class1 {
+ .mixin(@margin: 20px; @color: #33acfe) !important;
+}
+.class2 {
+ .mixin(#efca44; @padding: 40px 10px);
+}
+
+=====================================output=====================================
+@map: {
+ @width: 400px;
+ @colors: {
+ toolbar-background: red;
+ toolbar-foreground: inherit;
+ };
+};
+
+#ns {
+ .mixin() {
+ @height: 200px;
+ }
+}
+
+@breakpoints: {
+ mobile: 320px;
+ tablet: 768px;
+ desktop: 1024px;
+};
+
+@media (min-width: @breakpoints[mobile]) {
+ .toolbar {
+ width: @map[@width];
+ height: #ns.mixin[ @height];
+ background: @map[@colors][toolbar-background];
+ color: @map[@colors][toolbar-foreground];
+ }
+}
+
+// !important after map usage
+// https://github.com/less/less.js/issues/3430
+@margins: {
+ zero: 0;
+ ten: 10px;
+};
+.cell {
+ margin: @margins[zero] (@margins[ten] / 2) !important;
+}
+
+.mixin(@color: black; @margin: 10px; @padding: 20px) {
+ color: @color;
+ margin: @margin;
+ padding: @padding;
+ width: @margins[zero] !important;
+}
+.class1 {
+ .mixin(@margin: 20px; @color: #33acfe) !important;
+}
+.class2 {
+ .mixin(#efca44; @padding: 40px 10px);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-4.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#ns {
+ .mixin(@a) when (@a = 1) {
+ @a: 20px;
+ }
+}
+
+.alias() {
+ #ns.mixin(1);
+}
+
+#library {
+ .core() {
+ .colors() {
+ primary: blue;
+ foreground: inherit;
+ }
+ }
+}
+
+#library {
+ .core() {
+ .colors() {
+ primary: rebeccapurple;
+ }
+ }
+}
+
+.foo {
+ .colors() { #library.core.colors(); }
+ width: .alias[@a];
+ background: .colors[primary];
+ color: .colors[foreground];
+}
+=====================================output=====================================
+#ns {
+ .mixin(@a) when (@a = 1) {
+ @a: 20px;
+ }
+}
+
+.alias() {
+ #ns.mixin(1);
+}
+
+#library {
+ .core() {
+ .colors() {
+ primary: blue;
+ foreground: inherit;
+ }
+ }
+}
+
+#library {
+ .core() {
+ .colors() {
+ primary: rebeccapurple;
+ }
+ }
+}
+
+.foo {
+ .colors() {
+ #library.core.colors();
+ }
+ width: .alias[ @a];
+ background: .colors[primary];
+ color: .colors[foreground];
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-5.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "imports/a-better-bootstrap";
+
+#theme.dark.navbar {
+ .colors() {
+ primary: rebeccapurple;
+ }
+ .colors(dark) {
+ primary: black;
+ secondary: grey;
+ }
+ .test-rule() {
+ val: output;
+ }
+}
+
+.my-navbar {
+ #theme.dark.navbar();
+ background: .colors[primary];
+ .test-rule();
+}
+
+.another-navbar {
+ @colors: #theme.dark.navbar.colors() !important;
+ background: @colors[primary];
+ border: 1px solid @colors[secondary];
+}
+
+.another {
+ @colors: #theme.dark.navbar.colors(dark);
+ background: @colors[primary];
+ border: 1px solid @colors[secondary];
+}
+=====================================output=====================================
+@import "imports/a-better-bootstrap";
+
+#theme.dark.navbar {
+ .colors() {
+ primary: rebeccapurple;
+ }
+ .colors(dark) {
+ primary: black;
+ secondary: grey;
+ }
+ .test-rule() {
+ val: output;
+ }
+}
+
+.my-navbar {
+ #theme.dark.navbar();
+ background: .colors[primary];
+ .test-rule();
+}
+
+.another-navbar {
+ @colors: #theme.dark.navbar.colors() !important;
+ background: @colors[primary];
+ border: 1px solid @colors[secondary];
+}
+
+.another {
+ @colors: #theme.dark.navbar.colors(dark);
+ background: @colors[primary];
+ border: 1px solid @colors[secondary];
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-6.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.wrapper(@another-mixin) {
+ @another-mixin();
+}
+
+.something(foo) {
+ width: 10px;
+}
+
+.output-height() {
+ height: 10px;
+}
+
+.rule-1 {
+ @alias: .something(foo);
+ @alias();
+}
+
+.rule-2 {
+ @alias: .something(foo);
+ .wrapper(@alias);
+}
+
+.rule-3 {
+ .wrapper(.something(foo));
+ .wrapper(.output-height());
+}
+=====================================output=====================================
+.wrapper(@another-mixin) {
+ @another-mixin();
+}
+
+.something(foo) {
+ width: 10px;
+}
+
+.output-height() {
+ height: 10px;
+}
+
+.rule-1 {
+ @alias: .something(foo);
+ @alias();
+}
+
+.rule-2 {
+ @alias: .something(foo);
+ .wrapper(@alias);
+}
+
+.rule-3 {
+ .wrapper(.something(foo));
+ .wrapper(.output-height());
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-7.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#ns {
+ .options() {
+ option: true;
+ }
+}
+
+@ns: {
+ @options: {
+ option: true;
+ };
+};
+
+& when (#ns.options[option]) {
+ .output {
+ a: b;
+ }
+}
+
+& when (#ns.options[option] = true) {
+ .output-2 {
+ c: d;
+ }
+}
+
+& when (#ns.options[option] = false) {
+ .no-reach {
+ c: d;
+ }
+}
+
+// DR access
+& when (@ns[@options][option]) {
+ .dr {
+ a: b;
+ }
+}
+
+& when (@ns[@options][option] = true) {
+ .dr-2 {
+ c: d;
+ }
+}
+
+& when (@ns[@options][option] = false) {
+ .dr-no-reach {
+ c: d;
+ }
+}
+=====================================output=====================================
+#ns {
+ .options() {
+ option: true;
+ }
+}
+
+@ns: {
+ @options: {
+ option: true;
+ };
+};
+
+& when (#ns.options[option]) {
+ .output {
+ a: b;
+ }
+}
+
+& when (#ns.options[option] = true) {
+ .output-2 {
+ c: d;
+ }
+}
+
+& when (#ns.options[option] = false) {
+ .no-reach {
+ c: d;
+ }
+}
+
+// DR access
+& when (@ns[@options][option]) {
+ .dr {
+ a: b;
+ }
+}
+
+& when (@ns[@options][option] = true) {
+ .dr-2 {
+ c: d;
+ }
+}
+
+& when (@ns[@options][option] = false) {
+ .dr-no-reach {
+ c: d;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-8.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// see: https://github.com/less/less.js/issues/3368
+@vars: {
+ background-color: black;
+ color: contrast($background-color, #000, #fff);
+}
+
+:root {
+ each(@vars, {
+ --@{key}: @value;
+ });
+}
+
+div {
+ display: inline-block;
+ padding: 1rem;
+ background-color: var(--background-color);
+ color: var(--color);
+}
+
+// see: https://github.com/less/less.js/issues/3339
+// still fails - move to 4.0
+// @components: {
+// columns: true;
+// ratios: false;
+// };
+
+// each(@components, {
+// & when (@value = true) {
+// @import (optional) "components/@{key}.less";
+// }
+// });
+=====================================output=====================================
+// see: https://github.com/less/less.js/issues/3368
+@vars: {
+ background-color: black;
+ color: contrast($background-color, #000, #fff);
+};
+
+:root {
+ each(@vars, {
+ --@{key}: @value;
+ });
+}
+
+div {
+ display: inline-block;
+ padding: 1rem;
+ background-color: var(--background-color);
+ color: var(--color);
+}
+
+// see: https://github.com/less/less.js/issues/3339
+// still fails - move to 4.0
+// @components: {
+// columns: true;
+// ratios: false;
+// };
+
+// each(@components, {
+// & when (@value = true) {
+// @import (optional) "components/@{key}.less";
+// }
+// });
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-functions.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.add(@a, @b) {
+ @r: @a + @b;
+}
+.foo {
+ width: .add(10px, 10px)[];
+ bar: @return[];
+}
+
+@return: {
+ single: val;
+}
+
+// Issue #3405
+#lookup {
+ @prop: test;
+}
+
+.mix (@var) {
+ width: @var;
+}
+
+.bar {
+ .mix(#lookup[@prop]);
+}
+
+// Issue #3406
+.mix2 (@n) {
+ value: @n;
+}
+#lookup2 {
+ @var: .mix2(lookup);
+}
+.example {
+ // #lookup[@var](); -- fails, need the following alias
+ @dr: #lookup2[@var];
+ @dr();
+}
+=====================================output=====================================
+.add(@a, @b) {
+ @r: @a + @b;
+}
+.foo {
+ width: .add(10px, 10px) [];
+ bar: @return[];
+}
+
+@return: {
+ single: val;
+};
+
+// Issue #3405
+#lookup {
+ @prop: test;
+}
+
+.mix (@var) {
+ width: @var;
+}
+
+.bar {
+ .mix(#lookup[@prop]);
+}
+
+// Issue #3406
+.mix2 (@n) {
+ value: @n;
+}
+#lookup2 {
+ @var: .mix2(lookup);
+}
+.example {
+ // #lookup[@var](); -- fails, need the following alias
+ @dr: #lookup2[ @var];
+ @dr();
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-media.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#ns {
+ .sizes() {
+ @small: 600px;
+ }
+ .breakpoint(@size) {
+ @val: #ns.sizes[@@size];
+ @min: (min-width: @val);
+ @max: not all and @min;
+ }
+}
+
+#ns {
+ .sizes() {
+ @small: 480px;
+ }
+}
+
+.valToGet() {
+ keyword: small;
+}
+
+@media #ns.breakpoint(.valToGet[])[@max] {
+ .selector {
+ prop: val;
+ }
+}
+=====================================output=====================================
+#ns {
+ .sizes() {
+ @small: 600px;
+ }
+ .breakpoint(@size) {
+ @val: #ns.sizes[ @@size];
+ @min: (min-width: @val);
+ @max: not all and @min;
+ }
+}
+
+#ns {
+ .sizes() {
+ @small: 480px;
+ }
+}
+
+.valToGet() {
+ keyword: small;
+}
+
+@media #ns.breakpoint(.valToGet[]) [@max] {
+ .selector {
+ prop: val;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/namespacing/namespacing-operations.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#ns {
+ .options() {
+ val1: 10px;
+ }
+}
+
+@ns: {
+ @options: {
+ val2: 20px;
+ }
+}
+
+.foo {
+ val: #ns.options[val1] + @ns[@options][val2] + 5px;
+}
+=====================================output=====================================
+#ns {
+ .options() {
+ val1: 10px;
+ }
+}
+
+@ns: {
+ @options: {
+ val2: 20px;
+ };
+};
+
+.foo {
+ val: #ns.options[val1] + @ns[@options][val2] + 5px;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/no-js-errors/no-js-errors.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.a {
+ a: \`1 + 1\`;
+}
+=====================================output=====================================
+.a {
+ a: \`1 + 1\`;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/postProcessorPlugin/postProcessor.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@color: inherit;
+.test-rule {
+ color: @color;
+}
+
+=====================================output=====================================
+@color: inherit;
+.test-rule {
+ color: @color;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/preProcessorPlugin/preProcessor.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.test-rule {
+ color: @color;
+}
+
+=====================================output=====================================
+.test-rule {
+ color: @color;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/process-imports/google.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700');
+
+.a { b: c; }
+=====================================output=====================================
+@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");
+
+.a {
+ b: c;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/rewrite-urls-all/folder/file.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#imported-file {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("../../relative/path");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+=====================================output=====================================
+#imported-file {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("../../relative/path");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/rewrite-urls-all/rewrite-urls-all.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "./folder/file.less";
+
+#rewrite-urls-all {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("./relative/../path");
+ background-image: url("./relative/../path/..");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+=====================================output=====================================
+@import "./folder/file.less";
+
+#rewrite-urls-all {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("./relative/../path");
+ background-image: url("./relative/../path/..");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/rewrite-urls-local/folder/file.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#imported-file {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("../../relative/path");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+=====================================output=====================================
+#imported-file {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("../../relative/path");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/rewrite-urls-local/rewrite-urls-local.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "./folder/file.less";
+
+#rewrite-urls-local {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("./relative/../path");
+ background-image: url("./relative/../path/..");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+=====================================output=====================================
+@import "./folder/file.less";
+
+#rewrite-urls-local {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("./relative/../path");
+ background-image: url("./relative/../path/..");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/root-registry/file.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@charset "utf-8";
+=====================================output=====================================
+@charset "utf-8";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/root-registry/root.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// https://github.com/less/less.js/issues/3112
+@file: ext();
+@import '@{file}';
+=====================================output=====================================
+// https://github.com/less/less.js/issues/3112
+@file: ext();
+@import "@{file}";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/rootpath-rewrite-urls-all/folder/file.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#imported-file {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("../../relative/path");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+=====================================output=====================================
+#imported-file {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("../../relative/path");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/rootpath-rewrite-urls-all/rootpath-rewrite-urls-all.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "./folder/file.less";
+
+#rootpath-rewrite-urls-all {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("./relative/../path");
+ background-image: url("./relative/../path/..");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+=====================================output=====================================
+@import "./folder/file.less";
+
+#rootpath-rewrite-urls-all {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("./relative/../path");
+ background-image: url("./relative/../path/..");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/rootpath-rewrite-urls-local/folder/file.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#imported-file {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("../../relative/path");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+=====================================output=====================================
+#imported-file {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("../../relative/path");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/rootpath-rewrite-urls-local/rootpath-rewrite-urls-local.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "./folder/file.less";
+
+#rootpath-rewrite-urls-local {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("./relative/../path");
+ background-image: url("./relative/../path/..");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+=====================================output=====================================
+@import "./folder/file.less";
+
+#rootpath-rewrite-urls-local {
+ background-image: url("./relative/path");
+ background-image: url("../relative/path");
+ background-image: url("./relative/../path");
+ background-image: url("./relative/../path/..");
+ background-image: url("module");
+ background-image: url("module/path");
+ background-image: url("module/path/../relative/path");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps/basic.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@var: black;
+
+.a() {
+ color: red;
+}
+
+.b {
+ color: green;
+ .a();
+ color: blue;
+ background: @var;
+}
+
+.a, .b {
+ background: green;
+ .c, .d {
+ background: gray;
+ & + & {
+ color: red;
+ }
+ }
+}
+
+.extend:extend(.a all) {
+ color: pink;
+}
+@import (inline) "imported.css";
+=====================================output=====================================
+@var: black;
+
+.a() {
+ color: red;
+}
+
+.b {
+ color: green;
+ .a();
+ color: blue;
+ background: @var;
+}
+
+.a,
+.b {
+ background: green;
+ .c,
+ .d {
+ background: gray;
+ & + & {
+ color: red;
+ }
+ }
+}
+
+.extend:extend(.a all) {
+ color: pink;
+}
+@import (inline) "imported.css";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps/comprehensive/comprehensive.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Comprehensive sourcemap test covering various Less.js features
+// This test exercises sourcemap generation for different code structures
+
+// Variables
+@primary-color: #3498db;
+@secondary-color: #2ecc71;
+@spacing: 20px;
+
+// Mixins
+.border-radius(@radius: 5px) {
+ border-radius: @radius;
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+}
+
+.box-shadow(@x: 0, @y: 0, @blur: 10px, @color: rgba(0,0,0,0.5)) {
+ box-shadow: @x @y @blur @color;
+}
+
+// Nested rules
+.container {
+ padding: @spacing;
+ background: @primary-color;
+
+ .header {
+ color: white;
+ font-size: 24px;
+
+ .title {
+ font-weight: bold;
+ margin-bottom: 10px;
+ }
+ }
+
+ .content {
+ background: @secondary-color;
+ padding: 15px;
+
+ p {
+ margin: 0;
+ line-height: 1.5;
+ }
+ }
+}
+
+// Operations
+.calculated {
+ width: calc(100% - @spacing * 2);
+ height: calc(50vh + 20px);
+ margin: (@spacing / 2);
+}
+
+// Functions
+.functions {
+ color: darken(@primary-color, 10%);
+ background: lighten(@secondary-color, 20%);
+ border: 1px solid fade(@primary-color, 50%);
+}
+
+// Mixins
+.card {
+ .border-radius(10px);
+ .box-shadow(0, 2px, 15px, rgba(0,0,0,0.1));
+ padding: @spacing;
+ background: white;
+}
+
+// @-rules
+@media (max-width: 768px) {
+ .container {
+ padding: (@spacing / 2);
+
+ .header {
+ font-size: 18px;
+ }
+ }
+}
+
+@supports (display: grid) {
+ .grid-layout {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: @spacing;
+ }
+}
+
+// Extend
+.button-base {
+ padding: 10px 20px;
+ border: none;
+ cursor: pointer;
+}
+
+.button-primary {
+ &:extend(.button-base);
+ background: @primary-color;
+ color: white;
+}
+
+// Selectors with &
+.navigation {
+ ul {
+ list-style: none;
+
+ li {
+ display: inline-block;
+
+ a {
+ text-decoration: none;
+
+ &:hover {
+ color: @primary-color;
+ }
+
+ &:active {
+ color: darken(@primary-color, 20%);
+ }
+ }
+ }
+ }
+}
+
+// Import (if we have imported files)
+// @import "imported.less";
+
+// Variables in selectors
+@selector-name: my-component;
+.@{selector-name} {
+ color: @primary-color;
+}
+
+// Multiple levels of nesting
+.level1 {
+ .level2 {
+ .level3 {
+ .level4 {
+ color: @secondary-color;
+ }
+ }
+ }
+}
+
+
+=====================================output=====================================
+// Comprehensive sourcemap test covering various Less.js features
+// This test exercises sourcemap generation for different code structures
+
+// Variables
+@primary-color: #3498db;
+@secondary-color: #2ecc71;
+@spacing: 20px;
+
+// Mixins
+.border-radius(@radius: 5px) {
+ border-radius: @radius;
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+}
+
+.box-shadow(@x: 0, @y: 0, @blur: 10px, @color: rgba(0,0,0,0.5)) {
+ box-shadow: @x @y @blur @color;
+}
+
+// Nested rules
+.container {
+ padding: @spacing;
+ background: @primary-color;
+
+ .header {
+ color: white;
+ font-size: 24px;
+
+ .title {
+ font-weight: bold;
+ margin-bottom: 10px;
+ }
+ }
+
+ .content {
+ background: @secondary-color;
+ padding: 15px;
+
+ p {
+ margin: 0;
+ line-height: 1.5;
+ }
+ }
+}
+
+// Operations
+.calculated {
+ width: calc(100% - @spacing * 2);
+ height: calc(50vh + 20px);
+ margin: (@spacing / 2);
+}
+
+// Functions
+.functions {
+ color: darken(@primary-color, 10%);
+ background: lighten(@secondary-color, 20%);
+ border: 1px solid fade(@primary-color, 50%);
+}
+
+// Mixins
+.card {
+ .border-radius(10px);
+ .box-shadow(0, 2px, 15px, rgba(0,0,0,0.1));
+ padding: @spacing;
+ background: white;
+}
+
+// @-rules
+@media (max-width: 768px) {
+ .container {
+ padding: (@spacing / 2);
+
+ .header {
+ font-size: 18px;
+ }
+ }
+}
+
+@supports (display: grid) {
+ .grid-layout {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: @spacing;
+ }
+}
+
+// Extend
+.button-base {
+ padding: 10px 20px;
+ border: none;
+ cursor: pointer;
+}
+
+.button-primary {
+ &:extend(.button-base);
+ background: @primary-color;
+ color: white;
+}
+
+// Selectors with &
+.navigation {
+ ul {
+ list-style: none;
+
+ li {
+ display: inline-block;
+
+ a {
+ text-decoration: none;
+
+ &:hover {
+ color: @primary-color;
+ }
+
+ &:active {
+ color: darken(@primary-color, 20%);
+ }
+ }
+ }
+ }
+}
+
+// Import (if we have imported files)
+// @import "imported.less";
+
+// Variables in selectors
+@selector-name: my-component;
+.@{selector-name} {
+ color: @primary-color;
+}
+
+// Multiple levels of nesting
+.level1 {
+ .level2 {
+ .level3 {
+ .level4 {
+ color: @secondary-color;
+ }
+ }
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps/custom-props.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@color: var(--foo);
+
+body {
+ border-left: 1px solid @color;
+ width: calc(50% - 5px);
+ border-top: 1px solid @color;
+}
+
+
+=====================================output=====================================
+@color: var(--foo);
+
+body {
+ border-left: 1px solid @color;
+ width: calc(50% - 5px);
+ border-top: 1px solid @color;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-basepath/sourcemaps-basepath.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@size: 16px;
+
+.text {
+ font-size: @size;
+ line-height: 1.5;
+}
+
+.title {
+ font-weight: bold;
+}
+
+
+=====================================output=====================================
+@size: 16px;
+
+.text {
+ font-size: @size;
+ line-height: 1.5;
+}
+
+.title {
+ font-weight: bold;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-disable-annotation/basic.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+body {
+ /*# sourceMappingURL=this-should-be-ok.css.map */
+ color: white;
+}
+=====================================output=====================================
+body {
+ /*# sourceMappingURL=this-should-be-ok.css.map */
+ color: white;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-empty/empty.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+
+=====================================output=====================================
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-empty/var-defs.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@test-var: 'something';
+=====================================output=====================================
+@test-var: "something";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-include-source/sourcemaps-include-source.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@primary: #007bff;
+@secondary: #6c757d;
+
+.button {
+ background: @primary;
+ color: white;
+ padding: 10px 20px;
+}
+
+.secondary {
+ background: @secondary;
+}
+
+
+=====================================output=====================================
+@primary: #007bff;
+@secondary: #6c757d;
+
+.button {
+ background: @primary;
+ color: white;
+ padding: 10px 20px;
+}
+
+.secondary {
+ background: @secondary;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-rootpath/sourcemaps-rootpath.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@var: green;
+
+.container {
+ padding: 20px;
+ color: @var;
+}
+
+.item {
+ margin: 5px;
+}
+
+
+=====================================output=====================================
+@var: green;
+
+.container {
+ padding: 20px;
+ color: @var;
+}
+
+.item {
+ margin: 5px;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-url/sourcemaps-url.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@color: red;
+
+.header {
+ color: @color;
+ background: blue;
+}
+
+.footer {
+ margin: 10px;
+}
+
+
+=====================================output=====================================
+@color: red;
+
+.header {
+ color: @color;
+ background: blue;
+}
+
+.footer {
+ margin: 10px;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-variable-selector/basic.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import (reference) "./vars.less";
+
+.@{hello}-class {
+ font-size: @font-size;
+}
+
+=====================================output=====================================
+@import (reference) "./vars.less";
+
+.@{hello}-class {
+ font-size: @font-size;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/sourcemaps-variable-selector/vars.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@foo: bar;
+@font-size: 12px;
+@hello: world;
+
+=====================================output=====================================
+@foo: bar;
+@font-size: 12px;
+@hello: world;
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/static-urls/urls.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@font-face {
+ src: url("/fonts/garamond-pro.ttf");
+ src: local(Futura-Medium),
+ url(fonts.svg#MyGeometricModern) format("svg");
+}
+#shorthands {
+ background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
+}
+#misc {
+ background-image: url(images/image.jpg);
+}
+#data-uri {
+ background: url(data:image/png;charset=utf-8;base64,
+ kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
+ k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
+ kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
+ background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
+ background-image: url(http://fonts.googleapis.com/css?family=\\"Rokkitt\\":\\(400\\),700);
+}
+
+#svg-data-uri {
+ background: transparent url('data:image/svg+xml, ');
+}
+
+.comma-delimited {
+ background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg);
+}
+.values {
+ @a: 'Trebuchet';
+ url: url(@a);
+}
+
+@import "../../tests-unit/import/import/import-and-relative-paths-test";
+
+
+=====================================output=====================================
+@font-face {
+ src: url("/fonts/garamond-pro.ttf");
+ src:
+ local(Futura-Medium),
+ url(fonts.svg#MyGeometricModern) format("svg");
+}
+#shorthands {
+ background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
+}
+#misc {
+ background-image: url(images/image.jpg);
+}
+#data-uri {
+ background: url(data:image/png;charset=utf-8;base64,
+ kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
+ k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
+ kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
+ background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
+ background-image: url(http://fonts.googleapis.com/css?family=\\"Rokkitt\\":\\(400\\),700);
+}
+
+#svg-data-uri {
+ background: transparent
+ url('data:image/svg+xml, ');
+}
+
+.comma-delimited {
+ background:
+ url(bg.jpg) no-repeat,
+ url(bg.png) repeat-x top left,
+ url(bg);
+}
+.values {
+ @a: "Trebuchet";
+ url: url(@a);
+}
+
+@import "../../tests-unit/import/import/import-and-relative-paths-test";
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/strict-imports/imported.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.imported {
+ background: green;
+}
+
+=====================================output=====================================
+.imported {
+ background: green;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/strict-imports/strict-imports.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Test that strictImports: true allows @import at root level
+@import "imported.less";
+
+// Test that strictImports: true allows @import inside @media blocks
+@media (max-width: 768px) {
+ @import "imported.less";
+ .mobile {
+ color: red;
+ }
+}
+
+// Test that strictImports: true skips @import inside selector blocks (import is not processed)
+.container {
+ @import "imported.less";
+ .nested {
+ color: blue;
+ }
+}
+
+
+=====================================output=====================================
+// Test that strictImports: true allows @import at root level
+@import "imported.less";
+
+// Test that strictImports: true allows @import inside @media blocks
+@media (max-width: 768px) {
+ @import "imported.less";
+ .mobile {
+ color: red;
+ }
+}
+
+// Test that strictImports: true skips @import inside selector blocks (import is not processed)
+.container {
+ @import "imported.less";
+ .nested {
+ color: blue;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/units/no-strict/no-strict.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@media (-o-min-device-pixel-ratio: 2) {
+ .test-rule-math-and-units {
+ font: ignores 0/0 rules;
+ test-division: 4 / 2 + 5em;
+ simple: 1px + 1px;
+ }
+}
+#units {
+ t1: (2em/1em) + 20;
+ t2: 20 + (2em/1em);
+ t3: 2em/1em;
+ t4: (2em/1px) + 20;
+ t5: 20 + (2em/1px);
+ t6: 2em/1px;
+ t7: (2em*1em) + 20;
+ t8: 20 + (2em*1em);
+ t9: 2em*1em;
+ t10: (2em*1px) + 20;
+ t11: 20 + (2em*1px);
+ t12: 2em*1px;
+}
+=====================================output=====================================
+@media (-o-min-device-pixel-ratio: 2) {
+ .test-rule-math-and-units {
+ font: ignores 0/0 rules;
+ test-division: 4 / 2 + 5em;
+ simple: 1px + 1px;
+ }
+}
+#units {
+ t1: (2em/1em) + 20;
+ t2: 20 + (2em/1em);
+ t3: 2em/1em;
+ t4: (2em/1px) + 20;
+ t5: 20 + (2em/1px);
+ t6: 2em/1px;
+ t7: (2em * 1em) + 20;
+ t8: 20 + (2em * 1em);
+ t9: 2em * 1em;
+ t10: (2em * 1px) + 20;
+ t11: 20 + (2em * 1px);
+ t12: 2em * 1px;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/units/strict/strict-units.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.units {
+ cancels-to-nothing: (1px / 1px);
+ cancels: ((((10px / 5em) / 1px) * 3em) * 1px);
+}
+
+=====================================output=====================================
+.units {
+ cancels-to-nothing: (1px / 1px);
+ cancels: ((((10px / 5em) / 1px) * 3em) * 1px);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/url-args/urls.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@font-face {
+ src: url("/fonts/garamond-pro.ttf");
+ src: local(Futura-Medium),
+ url(fonts.svg#MyGeometricModern) format("svg");
+}
+#shorthands {
+ background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
+ background: url("img.jpg") center / 100px;
+ background: #fff url(image.png) center / 1px 100px repeat-x scroll content-box padding-box;
+}
+#misc {
+ background-image: url(images/image.jpg);
+}
+#data-uri {
+ background: url(data:image/png;charset=utf-8;base64,
+ kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
+ k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
+ kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
+ background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
+ background-image: url(http://fonts.googleapis.com/css?family=\\"Rokkitt\\":\\(400\\),700);
+ background-image: url("http://fonts.googleapis.com/css?family=\\"Rokkitt\\":\\(400\\),700");
+}
+
+#svg-data-uri {
+ background: transparent url('data:image/svg+xml, ');
+}
+
+.comma-delimited {
+ background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg);
+}
+.values {
+ @a: 'Trebuchet';
+ url: url(@a);
+}
+
+@import "../../tests-unit/import/import/imports/font";
+
+#data-uri {
+ uri: data-uri('image/jpeg;base64', '../../data/image.jpg');
+}
+
+#data-uri-guess {
+ uri: data-uri('../../data/image.jpg');
+}
+
+#data-uri-ascii {
+ uri-1: data-uri('text/html', '../../data/page.html');
+ uri-2: data-uri('../../data/page.html');
+}
+
+#svg-functions {
+ background-image: svg-gradient(to bottom, black, white);
+ background-image: svg-gradient(to bottom, black, orange 3%, white);
+ @green_5: green 5%;
+ @orange_percentage: 3%;
+ @orange_color: orange;
+ background-image: svg-gradient(to bottom, (mix(black, white) + #444) 1%, @orange_color @orange_percentage, ((@green_5)), white 95%);
+}
+
+#data-uri-with-spaces {
+ background-image: url( data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
+ background-image: url( ' data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==');
+}
+
+=====================================output=====================================
+@font-face {
+ src: url("/fonts/garamond-pro.ttf");
+ src:
+ local(Futura-Medium),
+ url(fonts.svg#MyGeometricModern) format("svg");
+}
+#shorthands {
+ background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
+ background: url("img.jpg") center / 100px;
+ background: #fff url(image.png) center / 1px 100px repeat-x scroll content-box
+ padding-box;
+}
+#misc {
+ background-image: url(images/image.jpg);
+}
+#data-uri {
+ background: url(data:image/png;charset=utf-8;base64,
+ kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
+ k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
+ kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
+ background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
+ background-image: url(http://fonts.googleapis.com/css?family=\\"Rokkitt\\":\\(400\\),700);
+ background-image: url('http://fonts.googleapis.com/css?family="Rokkitt":\\(400\\),700');
+}
+
+#svg-data-uri {
+ background: transparent
+ url('data:image/svg+xml, ');
+}
+
+.comma-delimited {
+ background:
+ url(bg.jpg) no-repeat,
+ url(bg.png) repeat-x top left,
+ url(bg);
+}
+.values {
+ @a: "Trebuchet";
+ url: url(@a);
+}
+
+@import "../../tests-unit/import/import/imports/font";
+
+#data-uri {
+ uri: data-uri("image/jpeg;base64", "../../data/image.jpg");
+}
+
+#data-uri-guess {
+ uri: data-uri("../../data/image.jpg");
+}
+
+#data-uri-ascii {
+ uri-1: data-uri("text/html", "../../data/page.html");
+ uri-2: data-uri("../../data/page.html");
+}
+
+#svg-functions {
+ background-image: svg-gradient(to bottom, black, white);
+ background-image: svg-gradient(to bottom, black, orange 3%, white);
+ @green_5: green 5%;
+ @orange_percentage: 3%;
+ @orange_color: orange;
+ background-image: svg-gradient(
+ to bottom,
+ (mix(black, white) + #444) 1%,
+ @orange_color @orange_percentage,
+ ((@green_5)),
+ white 95%
+ );
+}
+
+#data-uri-with-spaces {
+ background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
+ background-image: url(" data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-config/visitorPlugin/visitor.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.test-rule {
+ color: red;
+ -some-aribitrary-property: value;
+}
+
+=====================================output=====================================
+.test-rule {
+ color: red;
+ -some-aribitrary-property: value;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/at-rules/at-rules.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Test various @-rule types and structures
+
+// @page with simple block
+@page {
+ margin: 2cm;
+ @top-left {
+ content: "Page " counter(page);
+ }
+}
+
+// @page with nested rules
+@page :first {
+ margin: 3cm;
+ @top-center {
+ content: "First Page";
+ }
+}
+
+// @charset
+@charset "UTF-8";
+
+// @namespace
+@namespace url(http://www.w3.org/1999/xhtml);
+@namespace svg url(http://www.w3.org/2000/svg);
+
+// @viewport
+@viewport {
+ width: device-width;
+ initial-scale: 1.0;
+}
+
+// @keyframes with simple block
+@keyframes slidein {
+ from {
+ margin-left: 100%;
+ width: 300%;
+ }
+ to {
+ margin-left: 0%;
+ width: 100%;
+ }
+}
+
+// @keyframes with nested rules (name can be a string)
+@keyframes "complex-animation" {
+ 0% {
+ opacity: 0;
+ transform: scale(0.5);
+ }
+ 50% {
+ opacity: 0.5;
+ transform: scale(1.2);
+ }
+ 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+// @font-face with simple block
+@font-face {
+ font-family: "MyFont";
+ src: url("myfont.woff2") format("woff2");
+ font-weight: normal;
+ font-style: normal;
+}
+
+// @font-face with variables
+@font-family-name: "CustomFont";
+@font-face {
+ font-family: @font-family-name;
+ src: url("custom.woff") format("woff");
+}
+
+// @supports with simple block
+@supports (display: grid) {
+ .grid-container {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+// @supports with nested @-rules
+@supports (transform-style: preserve-3d) {
+ @media (min-width: 768px) {
+ .card {
+ transform: rotateY(15deg);
+ }
+ }
+}
+
+// @media with simple block
+@media print {
+ body {
+ font-size: 12pt;
+ color: black;
+ }
+}
+
+// @media with nested @-rules
+@media screen {
+ @supports (display: flex) {
+ .container {
+ display: flex;
+ }
+ }
+}
+
+// @-rule with value (not simple block)
+@media (max-width: 600px) {
+ .sidebar {
+ display: none;
+ }
+}
+
+// @-rule inside ruleset
+.container {
+ @media (max-width: 768px) {
+ padding: 10px;
+ }
+}
+
+// Multiple @-rules
+@page :left {
+ margin-left: 4cm;
+ margin-right: 3cm;
+}
+
+@page :right {
+ margin-left: 3cm;
+ margin-right: 4cm;
+}
+
+// @-rule with mixins
+.mixin-with-atrule() {
+ @media (max-width: 600px) {
+ .mobile-only {
+ display: block;
+ }
+ }
+}
+
+.wrapper {
+ .mixin-with-atrule();
+}
+
+// @-rule with variables in value
+@breakpoint: 1024px;
+@media (min-width: @breakpoint) {
+ .desktop {
+ display: block;
+ }
+}
+
+
+=====================================output=====================================
+// Test various @-rule types and structures
+
+// @page with simple block
+@page {
+ margin: 2cm;
+ @top-left {
+ content: "Page " counter(page);
+ }
+}
+
+// @page with nested rules
+@page :first {
+ margin: 3cm;
+ @top-center {
+ content: "First Page";
+ }
+}
+
+// @charset
+@charset "UTF-8";
+
+// @namespace
+@namespace url(http://www.w3.org/1999/xhtml);
+@namespace svg url(http://www.w3.org/2000/svg);
+
+// @viewport
+@viewport {
+ width: device-width;
+ initial-scale: 1;
+}
+
+// @keyframes with simple block
+@keyframes slidein {
+ from {
+ margin-left: 100%;
+ width: 300%;
+ }
+ to {
+ margin-left: 0%;
+ width: 100%;
+ }
+}
+
+// @keyframes with nested rules (name can be a string)
+@keyframes "complex-animation" {
+ 0% {
+ opacity: 0;
+ transform: scale(0.5);
+ }
+ 50% {
+ opacity: 0.5;
+ transform: scale(1.2);
+ }
+ 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+// @font-face with simple block
+@font-face {
+ font-family: "MyFont";
+ src: url("myfont.woff2") format("woff2");
+ font-weight: normal;
+ font-style: normal;
+}
+
+// @font-face with variables
+@font-family-name: "CustomFont";
+@font-face {
+ font-family: @font-family-name;
+ src: url("custom.woff") format("woff");
+}
+
+// @supports with simple block
+@supports (display: grid) {
+ .grid-container {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+// @supports with nested @-rules
+@supports (transform-style: preserve-3d) {
+ @media (min-width: 768px) {
+ .card {
+ transform: rotateY(15deg);
+ }
+ }
+}
+
+// @media with simple block
+@media print {
+ body {
+ font-size: 12pt;
+ color: black;
+ }
+}
+
+// @media with nested @-rules
+@media screen {
+ @supports (display: flex) {
+ .container {
+ display: flex;
+ }
+ }
+}
+
+// @-rule with value (not simple block)
+@media (max-width: 600px) {
+ .sidebar {
+ display: none;
+ }
+}
+
+// @-rule inside ruleset
+.container {
+ @media (max-width: 768px) {
+ padding: 10px;
+ }
+}
+
+// Multiple @-rules
+@page :left {
+ margin-left: 4cm;
+ margin-right: 3cm;
+}
+
+@page :right {
+ margin-left: 3cm;
+ margin-right: 4cm;
+}
+
+// @-rule with mixins
+.mixin-with-atrule() {
+ @media (max-width: 600px) {
+ .mobile-only {
+ display: block;
+ }
+ }
+}
+
+.wrapper {
+ .mixin-with-atrule();
+}
+
+// @-rule with variables in value
+@breakpoint: 1024px;
+@media (min-width: @breakpoint) {
+ .desktop {
+ display: block;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/at-rules-declarations/at-rules-declarations.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Tests for atrule.js line 117 - genCSS with simpleBlock declarations
+// Covers parser + genCSS + outputRuleset with declarations path
+
+// @page with declarations (simpleBlock)
+@page {
+ margin: 2cm;
+ size: A4;
+ marks: crop cross;
+}
+
+// @font-face with declarations
+@font-face {
+ font-family: "MyFont";
+ src: url("myfont.woff2");
+ font-weight: 400;
+ font-style: normal;
+}
+
+// @counter-style with declarations
+@counter-style my-counter {
+ system: fixed;
+ symbols: "A" "B" "C";
+ suffix: ". ";
+}
+
+
+=====================================output=====================================
+// Tests for atrule.js line 117 - genCSS with simpleBlock declarations
+// Covers parser + genCSS + outputRuleset with declarations path
+
+// @page with declarations (simpleBlock)
+@page {
+ margin: 2cm;
+ size: A4;
+ marks: crop cross;
+}
+
+// @font-face with declarations
+@font-face {
+ font-family: "MyFont";
+ src: url("myfont.woff2");
+ font-weight: 400;
+ font-style: normal;
+}
+
+// @counter-style with declarations
+@counter-style my-counter {
+ system: fixed;
+ symbols: "A" "B" "C";
+ suffix: ". ";
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/at-rules-empty/at-rules-empty.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Tests for atrule.js line 121 - genCSS with no rules or declarations
+// Covers parser + genCSS path
+
+// @charset without block
+@charset "UTF-8";
+
+// @import (will be processed separately, but tests the path)
+@import url("test.css");
+
+// @namespace
+@namespace "http://www.w3.org/1999/xhtml";
+
+// @namespace with prefix
+@namespace svg "http://www.w3.org/2000/svg";
+
+
+=====================================output=====================================
+// Tests for atrule.js line 121 - genCSS with no rules or declarations
+// Covers parser + genCSS path
+
+// @charset without block
+@charset "UTF-8";
+
+// @import (will be processed separately, but tests the path)
+@import url("test.css");
+
+// @namespace
+@namespace "http://www.w3.org/1999/xhtml";
+
+// @namespace with prefix
+@namespace svg "http://www.w3.org/2000/svg";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/at-rules-empty-block/at-rules-empty-block.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Tests for atrule.js lines 255-256 - empty rules block in non-compressed mode
+// Covers parser + genCSS + outputRuleset with empty rules
+
+// @media with empty block
+@media screen {
+}
+
+// @supports with empty block
+@supports (display: grid) {
+}
+
+// @layer with empty block
+@layer base {
+}
+
+// @page with empty block
+@page {
+}
+
+
+=====================================output=====================================
+// Tests for atrule.js lines 255-256 - empty rules block in non-compressed mode
+// Covers parser + genCSS + outputRuleset with empty rules
+
+// @media with empty block
+@media screen {
+}
+
+// @supports with empty block
+@supports (display: grid) {
+}
+
+// @layer with empty block
+@layer base {
+}
+
+// @page with empty block
+@page {
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/at-rules-keyword-comments/at-rules-keyword-comments.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Tests for atrule.js keywordList method with Comments (line 84)
+// Covers parser + eval + keywordList path
+// This tests when a keyword list contains Comments
+
+@media screen /* comment */, print /* another */, handheld {
+ body {
+ font-size: 12pt;
+ }
+}
+
+// @import with media queries containing comments
+@import "test.css" screen /* comment */, print;
+
+
+=====================================output=====================================
+// Tests for atrule.js keywordList method with Comments (line 84)
+// Covers parser + eval + keywordList path
+// This tests when a keyword list contains Comments
+
+@media screen /* comment */, print /* another */, handheld {
+ body {
+ font-size: 12pt;
+ }
+}
+
+// @import with media queries containing comments
+@import "test.css" screen /* comment */, print;
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/at-rules-targeted/at-rules-targeted.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Targeted tests for specific uncovered lines in atrule.js
+
+// Line 35-36: Single ruleset with declarations (allRulesetDeclarations path)
+@media screen {
+ .test {
+ color: red;
+ }
+}
+
+// Line 138-140: Value that evaluates to keyword list (keywordList method)
+@media screen, print, handheld {
+ body {
+ font-size: 12pt;
+ }
+}
+
+// Line 146-154: rules[0].rules path with mergeable declarations
+@supports (display: grid) {
+ .grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+// Line 155-158: simpleBlock with rules evaluation
+@page {
+ margin: 2cm;
+ size: A4;
+}
+
+// Line 172-174: Non-simpleBlock rules evaluation (evalRoot)
+@media screen {
+ @media (max-width: 768px) {
+ .nested {
+ display: block;
+ }
+ }
+}
+
+// Line 203-215: evalRoot with ampersand counting
+.container {
+ @media screen {
+ & {
+ color: red;
+ }
+ .child {
+ color: blue;
+ }
+ }
+}
+
+// Line 217-236: variable, find, rulesets methods
+// These methods are called when accessing variables/properties from within at-rule scope
+@media screen {
+ @var: value;
+ .test-var-access {
+ color: @var;
+ }
+}
+
+// Line 238-270: outputRuleset (compressed and non-compressed)
+@layer base {
+ body {
+ margin: 0;
+ }
+ p {
+ padding: 0;
+ }
+}
+
+// Line 121: At-rule without rules or declarations
+@charset "UTF-8";
+
+// Line 103-105: isRulesetLike and isCharset
+@charset "UTF-8";
+@media screen {
+ body {
+ color: black;
+ }
+}
+
+
+=====================================output=====================================
+// Targeted tests for specific uncovered lines in atrule.js
+
+// Line 35-36: Single ruleset with declarations (allRulesetDeclarations path)
+@media screen {
+ .test {
+ color: red;
+ }
+}
+
+// Line 138-140: Value that evaluates to keyword list (keywordList method)
+@media screen, print, handheld {
+ body {
+ font-size: 12pt;
+ }
+}
+
+// Line 146-154: rules[0].rules path with mergeable declarations
+@supports (display: grid) {
+ .grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+// Line 155-158: simpleBlock with rules evaluation
+@page {
+ margin: 2cm;
+ size: A4;
+}
+
+// Line 172-174: Non-simpleBlock rules evaluation (evalRoot)
+@media screen {
+ @media (max-width: 768px) {
+ .nested {
+ display: block;
+ }
+ }
+}
+
+// Line 203-215: evalRoot with ampersand counting
+.container {
+ @media screen {
+ & {
+ color: red;
+ }
+ .child {
+ color: blue;
+ }
+ }
+}
+
+// Line 217-236: variable, find, rulesets methods
+// These methods are called when accessing variables/properties from within at-rule scope
+@media screen {
+ @var: value;
+ .test-var-access {
+ color: @var;
+ }
+}
+
+// Line 238-270: outputRuleset (compressed and non-compressed)
+@layer base {
+ body {
+ margin: 0;
+ }
+ p {
+ padding: 0;
+ }
+}
+
+// Line 121: At-rule without rules or declarations
+@charset "UTF-8";
+
+// Line 103-105: isRulesetLike and isCharset
+@charset "UTF-8";
+@media screen {
+ body {
+ color: black;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/calc/calc.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@val: 10px;
+@var: 50vh/2;
+
+.calc-basic {
+ width: calc(100% - 30px);
+ height: calc(50% + 20px);
+ margin: calc(10px * 2);
+ padding: calc(100vh - 50px);
+}
+
+.calc-variables {
+ @c: 10px + 20px;
+ @calc: (@val + 30px);
+ root: calc(100% - @c);
+ root2: calc(100% - @calc);
+ width: calc(50% + (@var - 20px));
+ height: calc(50% + ((@var - 20px)));
+}
+
+.calc-nested {
+ min-height: calc(((10vh)) + calc((5vh)));
+ nested: calc(calc(2.25rem + 2px) - 1px * 2);
+}
+
+.calc-functions {
+ @a: 10px;
+ @b: 10px;
+ @floor: floor(1 + .1);
+
+ one: calc(100% - ((min(@a + @b))));
+ two: calc(100% - (((@a + @b))));
+ bar: calc(@floor + 20%);
+}
+
+.calc-escape {
+ three: calc(e('100%') - (3 * 1));
+ four: calc(~'100%' - (3 * 1));
+}
+
+.calc-mixed {
+ foo: 1 + 2 calc(3 + 4) 5 + 6;
+ @v: 10px;
+ height: calc(100% - ((@v * 3) + (@v * 2)));
+}
+
+
+
+=====================================output=====================================
+@val: 10px;
+@var: 50vh/2;
+
+.calc-basic {
+ width: calc(100% - 30px);
+ height: calc(50% + 20px);
+ margin: calc(10px * 2);
+ padding: calc(100vh - 50px);
+}
+
+.calc-variables {
+ @c: 10px + 20px;
+ @calc: (@val + 30px);
+ root: calc(100% - @c);
+ root2: calc(100% - @calc);
+ width: calc(50% + (@var - 20px));
+ height: calc(50% + ((@var - 20px)));
+}
+
+.calc-nested {
+ min-height: calc(((10vh)) + calc((5vh)));
+ nested: calc(calc(2.25rem + 2px) - 1px * 2);
+}
+
+.calc-functions {
+ @a: 10px;
+ @b: 10px;
+ @floor: floor(1 + 0.1);
+
+ one: calc(100% - ((min(@a + @b))));
+ two: calc(100% - (((@a + @b))));
+ bar: calc(@floor + 20%);
+}
+
+.calc-escape {
+ three: calc(e("100%") - (3 * 1));
+ four: calc(~"100%" - (3 * 1));
+}
+
+.calc-mixed {
+ foo: 1 + 2 calc(3 + 4) 5 + 6;
+ @v: 10px;
+ height: calc(100% - ((@v * 3) + (@v * 2)));
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/charsets/charsets.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// @charset directive test
+@charset "UTF-8";
+
+@import "import/import-charset-test";
+
+=====================================output=====================================
+// @charset directive test
+@charset "UTF-8";
+
+@import "import/import-charset-test";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/charsets/import/import-charset-test.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@charset "ISO-8859-1";
+
+=====================================output=====================================
+@charset "ISO-8859-1";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/color-functions/alpha.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Alpha function tests - no nesting, just alpha function behavior
+#alpha {
+ @colorvar: rgba(150, 200, 150, 0.7);
+ #fromvar {
+ opacity: alpha(@colorvar);
+ }
+ #short {
+ opacity: alpha(#aaa);
+ }
+ #long {
+ opacity: alpha(#bababa);
+ }
+ #rgba {
+ opacity: alpha(rgba(50, 120, 95, 0.2));
+ }
+ #hsl {
+ opacity: alpha(hsl(120, 100%, 50%));
+ }
+ #transparent-hex4 {
+ opacity: alpha(#0000);
+ }
+ #transparent-hex8 {
+ opacity: alpha(#00000000);
+ }
+}
+
+=====================================output=====================================
+// Alpha function tests - no nesting, just alpha function behavior
+#alpha {
+ @colorvar: rgba(150, 200, 150, 0.7);
+ #fromvar {
+ opacity: alpha(@colorvar);
+ }
+ #short {
+ opacity: alpha(#aaa);
+ }
+ #long {
+ opacity: alpha(#bababa);
+ }
+ #rgba {
+ opacity: alpha(rgba(50, 120, 95, 0.2));
+ }
+ #hsl {
+ opacity: alpha(hsl(120, 100%, 50%));
+ }
+ #transparent-hex4 {
+ opacity: alpha(#0000);
+ }
+ #transparent-hex8 {
+ opacity: alpha(#00000000);
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/color-functions/basic.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Basic color function tests - no nesting, just color functions
+.lightenblue {
+ color: lighten(blue, 10%);
+}
+
+.darkenblue {
+ color: darken(blue, 10%);
+}
+
+.unknowncolors {
+ color: blue2;
+ border: 2px solid superred;
+}
+
+.transparent {
+ color: transparent;
+ background-color: rgba(0, 0, 0, 0);
+}
+
+#percentage {
+ color: red(rgb(100%, 0, 0));
+ border-color: rgba(100%, 0, 0, 50%);
+}
+
+=====================================output=====================================
+// Basic color function tests - no nesting, just color functions
+.lightenblue {
+ color: lighten(blue, 10%);
+}
+
+.darkenblue {
+ color: darken(blue, 10%);
+}
+
+.unknowncolors {
+ color: blue2;
+ border: 2px solid superred;
+}
+
+.transparent {
+ color: transparent;
+ background-color: rgba(0, 0, 0, 0);
+}
+
+#percentage {
+ color: red(rgb(100%, 0, 0));
+ border-color: rgba(100%, 0, 0, 50%);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/color-functions/comprehensive.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Comprehensive color function tests - all color functions without problematic nesting
+.lightenblue {
+ color: lighten(blue, 10%);
+}
+
+.darkenblue {
+ color: darken(blue, 10%);
+}
+
+.unknowncolors {
+ color: blue2;
+ border: 2px solid superred;
+}
+
+.transparent {
+ color: transparent;
+ background-color: rgba(0, 0, 0, 0);
+}
+
+#alpha {
+ @colorvar: rgba(150, 200, 150, 0.7);
+ #fromvar {
+ opacity: alpha(@colorvar);
+ }
+ #short {
+ opacity: alpha(#aaa);
+ }
+ #long {
+ opacity: alpha(#bababa);
+ }
+ #rgba {
+ opacity: alpha(rgba(50, 120, 95, 0.2));
+ }
+ #hsl {
+ opacity: alpha(hsl(120, 100%, 50%));
+ }
+}
+
+#percentage {
+ color: red(rgb(100%, 0, 0));
+ border-color: rgba(100%, 0, 0, 50%);
+}
+
+#grey {
+ color: rgb(200, 200, 200);
+}
+
+#aa3333 {
+ color: rgb(66.66%, 20%, 20%);
+}
+
+#bb8080 {
+ color: hsl(0deg, 30%, 62%);
+}
+
+#ccff00 {
+ color: hsl(72deg, 100%, 50%);
+}
+
+=====================================output=====================================
+// Comprehensive color function tests - all color functions without problematic nesting
+.lightenblue {
+ color: lighten(blue, 10%);
+}
+
+.darkenblue {
+ color: darken(blue, 10%);
+}
+
+.unknowncolors {
+ color: blue2;
+ border: 2px solid superred;
+}
+
+.transparent {
+ color: transparent;
+ background-color: rgba(0, 0, 0, 0);
+}
+
+#alpha {
+ @colorvar: rgba(150, 200, 150, 0.7);
+ #fromvar {
+ opacity: alpha(@colorvar);
+ }
+ #short {
+ opacity: alpha(#aaa);
+ }
+ #long {
+ opacity: alpha(#bababa);
+ }
+ #rgba {
+ opacity: alpha(rgba(50, 120, 95, 0.2));
+ }
+ #hsl {
+ opacity: alpha(hsl(120, 100%, 50%));
+ }
+}
+
+#percentage {
+ color: red(rgb(100%, 0, 0));
+ border-color: rgba(100%, 0, 0, 50%);
+}
+
+#grey {
+ color: rgb(200, 200, 200);
+}
+
+#aa3333 {
+ color: rgb(66.66%, 20%, 20%);
+}
+
+#bb8080 {
+ color: hsl(0deg, 30%, 62%);
+}
+
+#ccff00 {
+ color: hsl(72deg, 100%, 50%);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/color-functions/formats.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Color format tests - testing different color formats and conversions
+#yelow #short {
+ color: #fea;
+}
+#yelow #long {
+ color: #ffeeaa;
+}
+#yelow #rgba {
+ color: rgba(255, 238, 170, 0.1);
+}
+#yelow #argb {
+ color: argb(rgba(255, 238, 170, 0.1));
+}
+
+#blue #short {
+ color: #00f;
+}
+#blue #long {
+ color: #0000ff;
+}
+#blue #rgba {
+ color: rgba(0, 0, 255, 0.1);
+}
+#blue #argb {
+ color: argb(rgba(0, 0, 255, 0.1));
+}
+
+#alpha #hsla {
+ color: hsla(11, 20%, 20%, 0.6);
+}
+
+#grey {
+ color: rgb(200, 200, 200);
+}
+
+#aa3333 {
+ color: rgb(66.66%, 20%, 20%);
+}
+
+#bb8080 {
+ color: hsl(0deg, 30%, 62%);
+}
+
+#ccff00 {
+ color: hsl(72deg, 100%, 50%);
+}
+
+=====================================output=====================================
+// Color format tests - testing different color formats and conversions
+#yelow #short {
+ color: #fea;
+}
+#yelow #long {
+ color: #ffeeaa;
+}
+#yelow #rgba {
+ color: rgba(255, 238, 170, 0.1);
+}
+#yelow #argb {
+ color: argb(rgba(255, 238, 170, 0.1));
+}
+
+#blue #short {
+ color: #00f;
+}
+#blue #long {
+ color: #0000ff;
+}
+#blue #rgba {
+ color: rgba(0, 0, 255, 0.1);
+}
+#blue #argb {
+ color: argb(rgba(0, 0, 255, 0.1));
+}
+
+#alpha #hsla {
+ color: hsla(11, 20%, 20%, 0.6);
+}
+
+#grey {
+ color: rgb(200, 200, 200);
+}
+
+#aa3333 {
+ color: rgb(66.66%, 20%, 20%);
+}
+
+#bb8080 {
+ color: hsl(0deg, 30%, 62%);
+}
+
+#ccff00 {
+ color: hsl(72deg, 100%, 50%);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/color-functions/modern.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Modern color space function tests
+.color-oklch-sub {
+ background: oklch(from #0000FF calc(l - 0.1) c h);
+}
+
+.color-oklch-add {
+ background: oklch(from #0000FF calc(l + 0.1) c h);
+}
+
+.color-oklch-mult {
+ background: oklch(from #0000FF calc(l * 0.1) c h);
+}
+
+.color-oklch-div {
+ background: oklch(from #0000FF calc(l / 2) c h);
+}
+
+.color-hsl-sub {
+ background: hsl(from #0000FF calc(h - 1) s l);
+}
+
+.color-hsl-add {
+ background: hsl(from #0000FF calc(h + 1) s l);
+}
+
+.color-hsl-mult {
+ background: hsl(from #0000FF calc(h * 1) s l);
+}
+
+.color-hsl-div {
+ background: hsl(from #0000FF calc(h / 2) s l);
+}
+
+.color-rgb-sub {
+ background: rgb(from #0000FF calc(r - 1) g b);
+}
+
+.color-rgb-add {
+ background: rgb(from #0000FF calc(r + 1) g b);
+}
+
+.color-rgb-mult {
+ background: rgb(from #0000FF calc(r * 1) g b);
+}
+
+.color-rgb-div {
+ background: rgb(from #0000FF calc(r / 2) g b);
+}
+
+.color-rgb-sub-right-operand {
+ background: rgb(from blue calc(100 - r) g b);
+}
+
+.color-rgb-add-left-operand {
+ background: rgb(from blue calc(r + 100) g b);
+}
+
+=====================================output=====================================
+// Modern color space function tests
+.color-oklch-sub {
+ background: oklch(from #0000ff calc(l - 0.1) c h);
+}
+
+.color-oklch-add {
+ background: oklch(from #0000ff calc(l + 0.1) c h);
+}
+
+.color-oklch-mult {
+ background: oklch(from #0000ff calc(l * 0.1) c h);
+}
+
+.color-oklch-div {
+ background: oklch(from #0000ff calc(l / 2) c h);
+}
+
+.color-hsl-sub {
+ background: hsl(from #0000ff calc(h - 1) s l);
+}
+
+.color-hsl-add {
+ background: hsl(from #0000ff calc(h + 1) s l);
+}
+
+.color-hsl-mult {
+ background: hsl(from #0000ff calc(h * 1) s l);
+}
+
+.color-hsl-div {
+ background: hsl(from #0000ff calc(h / 2) s l);
+}
+
+.color-rgb-sub {
+ background: rgb(from #0000ff calc(r - 1) g b);
+}
+
+.color-rgb-add {
+ background: rgb(from #0000ff calc(r + 1) g b);
+}
+
+.color-rgb-mult {
+ background: rgb(from #0000ff calc(r * 1) g b);
+}
+
+.color-rgb-div {
+ background: rgb(from #0000ff calc(r / 2) g b);
+}
+
+.color-rgb-sub-right-operand {
+ background: rgb(from blue calc(100 - r) g b);
+}
+
+.color-rgb-add-left-operand {
+ background: rgb(from blue calc(r + 100) g b);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/color-functions/modern-syntax.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Modern CSS color syntax tests - space-separated values and / alpha syntax
+foo {
+ color: rgb(0 128 255);
+ color: rgb(0 128 255 / 50%);
+ color: hsl(198deg 28% 50%);
+ color: hsl(198deg 28% 50% / 50%);
+}
+
+=====================================output=====================================
+// Modern CSS color syntax tests - space-separated values and / alpha syntax
+foo {
+ color: rgb(0 128 255);
+ color: rgb(0 128 255 / 50%);
+ color: hsl(198deg 28% 50%);
+ color: hsl(198deg 28% 50% / 50%);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/color-functions/operations.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Color operations tests - testing color math operations
+#overflow {
+ .a { color: (#111111 - #444444); } // #000000
+ .b { color: (#eee + #fff); } // #ffffff
+ .c { color: (#aaa * 3); } // #ffffff
+ .d { color: (#00ee00 + #009900); } // #00ff00
+ .e { color: rgba(-99.9, 31.4159, 321, 0.42); }
+}
+
+=====================================output=====================================
+// Color operations tests - testing color math operations
+#overflow {
+ .a {
+ color: (#111111 - #444444);
+ } // #000000
+ .b {
+ color: (#eee + #fff);
+ } // #ffffff
+ .c {
+ color: (#aaa * 3);
+ } // #ffffff
+ .d {
+ color: (#00ee00 + #009900);
+ } // #00ff00
+ .e {
+ color: rgba(-99.9, 31.4159, 321, 0.42);
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/color-functions/rgba.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// RGBA and RRGGBBAA tests
+#rrggbbaa {
+ test-1: #55FF5599;
+ test-2: #5F59;
+ test-3: lighten(#55FF5599, 10%);
+ test-4: fade(#5F59, 10%);
+ test-5: rgba(#55FF5599);
+ test-6: rgba(#5F59);
+ test-7: rgba(#5F59, 0.5);
+ test-8: rgba(var(--color-accent), 0.2);
+ test-9: rgb(var(--color-accent));
+ test-9: hsla(var(--color-accent));
+ test-10: color('#55FF5599');
+ test-11: hsla(#5F59);
+ test-12: hsla(#5F59, 0.5);
+ --semi-transparent-dark-background: #001e00ee;
+ --semi-transparent-dark-background-2: rgba(0, 30, 0, 238); // invalid opacity will be capped
+}
+
+=====================================output=====================================
+// RGBA and RRGGBBAA tests
+#rrggbbaa {
+ test-1: #55ff5599;
+ test-2: #5f59;
+ test-3: lighten(#55ff5599, 10%);
+ test-4: fade(#5f59, 10%);
+ test-5: rgba(#55ff5599);
+ test-6: rgba(#5f59);
+ test-7: rgba(#5f59, 0.5);
+ test-8: rgba(var(--color-accent), 0.2);
+ test-9: rgb(var(--color-accent));
+ test-9: hsla(var(--color-accent));
+ test-10: color("#55FF5599");
+ test-11: hsla(#5f59);
+ test-12: hsla(#5f59, 0.5);
+ --semi-transparent-dark-background: #001e00ee;
+ --semi-transparent-dark-background-2: rgba(
+ 0,
+ 30,
+ 0,
+ 238
+ ); // invalid opacity will be capped
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/comments/comments2.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Inline comments and grid system tests
+@media all and/*! */(max-width:1024px) {}
+@-webkit-keyframes hover /* Safari and Chrome */{ }
+.bg {
+ background-image: linear-gradient(#333 /*{comment}*/, #111);
+}
+#planadvisor,
+/*comment*//*comment*/
+.first,/*comment*//*comment*/.planning {
+ margin:10px;
+ total-width: @total-width;
+}
+@base : 1;
+@column-width : @base * 6em; // Width of column */
+@gutter-width : 2em; // Width of column spacing */
+@columns : 12; // Number of Columns */
+@gridsystem-width : (@column-width * // For calculating the total */
+ @columns) + ( // width of the content area. */
+ @gutter-width * // We strongly recommend you */
+ @columns); // do not change this formula. */
+@total-width : @gridsystem-width; // set to 100% for fluid grid */
+
+// .............................................................................
+
+.some-inline-comments {
+ a: yes /* comment */;
+ b: red /* comment */;
+ @c: yes /* comment */;
+ @d: red /* comment */;
+ c: @c;
+ d: @d;
+}
+
+=====================================output=====================================
+// Inline comments and grid system tests
+@media all and/*! */(max-width:1024px) {
+}
+@-webkit-keyframes hover /* Safari and Chrome */ {
+}
+.bg {
+ background-image: linear-gradient(#333 /*{comment}*/, #111);
+}
+#planadvisor,
+/*comment*//*comment*/
+.first,/*comment*//*comment*/.planning
+{
+ margin: 10px;
+ total-width: @total-width;
+}
+@base: 1;
+@column-width: @base * 6em; // Width of column */
+@gutter-width: 2em; // Width of column spacing */
+@columns: 12; // Number of Columns */
+@gridsystem-width: (
+ @column-width * // For calculating the total */
+ @columns
+ ) +
+ (
+ // width of the content area. */
+ @gutter-width * // We strongly recommend you */
+ @columns
+ ); // do not change this formula. */
+@total-width: @gridsystem-width; // set to 100% for fluid grid */
+
+// .............................................................................
+
+.some-inline-comments {
+ a: yes /* comment */;
+ b: red /* comment */;
+ @c: yes/* comment */ ;
+ @d: red/* comment */ ;
+ c: @c;
+ d: @d;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/container/container.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.widget.discoverresults, .widget.repositoriesresults {
+ container-type: inline-size;
+
+ @container (max-width: 350px) {
+ .cite {
+ .wdr-authors {
+ display: none;
+ }
+ }
+ }
+}
+
+@container (min-width: 700px) {
+ .card h2 {
+ font-size: 2em;
+ }
+}
+
+@container sidebar (min-width: 700px) {
+ .card {
+ font-size: 2em;
+ }
+}
+
+@container (min-width: 60ch) {
+ .container:nth-child(odd) > article {
+ border: 1px solid grey;
+ }
+}
+
+@container size(min-width: 60ch) {
+ .article--post header {
+ grid-template-areas:
+ "avatar name"
+ "avatar headline";
+ align-items: start;
+ }
+
+ .article--post {
+ grid-template-areas: "header header" ". stats" ". content";
+ grid-auto-columns: 5rem 1fr;
+ column-gap: 1rem;
+ }
+
+ .article--post__title {
+ font-size: 1.75rem;
+ }
+}
+
+.card h2 {
+ container-type: inline-size;
+ margin: 0;
+ padding: 10px;
+
+ @container (min-width: 500px) {
+ .card-content {
+ grid-template-columns: 1fr 2fr;
+ grid-template-rows: auto 1fr;
+ align-items: start;
+ column-gap: 20px;
+ }
+
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container (width >= 500px) and (height >= 500px) {
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+}
+
+@container (width > 760px) not (height > 670px) {
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+}
+
+@container not (height <= 1080px) {
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+}
+
+@container (width < 500px) or (height < 500px) {
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+}
+
+@container (width < 500px) or (height < 500px) and (inline-size >= 0px) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container my-page-layout (width < 500px) or (height < 500px) and (block-size > 12em) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container (width < 500px) or (height < 500px) and (aspect-ratio: 3/2) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container (width < 500px) or (height < 500px) and (orientation: portrait) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container card (inline-size > 30em) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+
+ @container style(--responsive: true) {
+ .card-content {
+ grid-template-columns: 1fr 2fr;
+ grid-template-rows: auto 1fr;
+ align-items: start;
+ column-gap: 20px;
+ }
+
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container card (width > 400px), style(--responsive: true), scroll-state(stuck: top) {
+ h2 {
+ font-size: 1.5em;
+ }
+}
+
+@container style(--theme) {
+ .style-query {
+ color: red;
+ }
+}
+
+@container style((--theme: one) or (--theme: two)) {
+ .style-query-list {
+ color: blue;
+ }
+}
+
+@container contactBody (min-width: 1300px) {
+ .named-container {
+ width: 25%;
+ }
+}
+
+@container _body (min-width: 1300px) {
+ .underscored-container {
+ width: 25%;
+ }
+}
+
+@container --body (min-width: 1300px) {
+ .custom-ident-container {
+ width: 25%;
+ }
+}
+
+@container contact\\.body (min-width: 1300px) {
+ .escaped-container {
+ width: 25%;
+ }
+}
+
+@container café (min-width: 1300px) {
+ .nonascii-container {
+ width: 25%;
+ }
+}
+
+@container ( width < 500px ) or (height<500px) and (orientation: portrait) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container my-page-layout ( width< 500px) or ( height<500px) and ( block-size>12em ) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+.wrapper {
+ container-name: wrapper;
+ container-type: size;
+}
+
+.my_mixin(@height) {
+ @container wrapper (height < @height) {
+ a {
+ max-height: @height;
+ }
+ }
+}
+
+.my_mixin(100);
+.my_mixin(200);
+.my_mixin(300);
+
+@media only screen and (min-width: 768px) {
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .media-1 {
+ font-size: 1.5rem;
+ }
+
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .media-1 {
+ font-size: 1.5rem;
+ }
+
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+ }
+
+ .media-2 {
+ font-size: 2rem;
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .media-1 {
+ font-size: 1.5rem;
+ }
+
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+
+ @media (hover: hover) {
+ .foo {
+ font-size: 1.75rem;
+ }
+ }
+ }
+
+ .media-2 {
+ font-size: 2rem;
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .media-1 {
+ font-size: 1.5rem;
+ }
+
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+
+ @media (hover: hover) {
+ .foo {
+ font-size: 1.75rem;
+
+ @media not all and (hover: hover) {
+ color: limegreen;
+ }
+ }
+
+ .media-3 {
+ padding: 0.5rem;
+ }
+ }
+ }
+
+ .media-2 {
+ font-size: 2rem;
+ }
+}
+
+@container (min-width: 768px) {
+ @media only screen and (min-width: 768px) {
+ .foo {
+ color: aliceblue;
+ }
+ }
+
+ .container-1 {
+ color: purple;
+ }
+}
+
+#sticky {
+ position: sticky;
+ container-type: scroll-state;
+}
+
+@container scroll-state(stuck: top) {
+ #sticky-child {
+ font-size: 75%;
+ }
+}
+
+@container scroll-state(snapped: x) {
+ #sticky-child {
+ font-size: 75%;
+ }
+}
+
+@container scroll-state(scrollable: top) {
+ #sticky-child {
+ font-size: 75%;
+ }
+}
+
+@container sidebar (min-width: 400px), scroll-state(stuck: top) {
+ #sticky-child {
+ font-size: 80%;
+ }
+}
+
+@varfoo: foo;
+@threshold: 400px;
+@container @varfoo (min-width: @threshold) {
+ #sticky-child {
+ font-size: 75%;
+ }
+}
+
+// Regression test: mixin with variable container name and variable query condition
+// Issue: mixins with parameters using @container @name (condition < @var) failed
+// with "variable @bp is undefined" error in older versions
+@issue-width: 125px;
+
+.container-query-mixin(@container-name; @bp) {
+ @container @container-name (width < @bp) {
+ display: none;
+ }
+}
+
+.mixin-container-test {
+ .container-query-mixin(name, @issue-width);
+ color: red;
+}
+
+// Verify multiple calls with different params produce correct output
+.sidebar-test {
+ .container-query-mixin(sidebar, 500px);
+}
+.header-test {
+ .container-query-mixin(header, 800px);
+}
+
+=====================================output=====================================
+.widget.discoverresults,
+.widget.repositoriesresults {
+ container-type: inline-size;
+
+ @container (max-width: 350px) {
+ .cite {
+ .wdr-authors {
+ display: none;
+ }
+ }
+ }
+}
+
+@container (min-width: 700px) {
+ .card h2 {
+ font-size: 2em;
+ }
+}
+
+@container sidebar (min-width: 700px) {
+ .card {
+ font-size: 2em;
+ }
+}
+
+@container (min-width: 60ch) {
+ .container:nth-child(odd) > article {
+ border: 1px solid grey;
+ }
+}
+
+@container size(min-width: 60ch) {
+ .article--post header {
+ grid-template-areas:
+ "avatar name"
+ "avatar headline";
+ align-items: start;
+ }
+
+ .article--post {
+ grid-template-areas: "header header" ". stats" ". content";
+ grid-auto-columns: 5rem 1fr;
+ column-gap: 1rem;
+ }
+
+ .article--post__title {
+ font-size: 1.75rem;
+ }
+}
+
+.card h2 {
+ container-type: inline-size;
+ margin: 0;
+ padding: 10px;
+
+ @container (min-width: 500px) {
+ .card-content {
+ grid-template-columns: 1fr 2fr;
+ grid-template-rows: auto 1fr;
+ align-items: start;
+ column-gap: 20px;
+ }
+
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container (width >= 500px) and (height >= 500px) {
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+}
+
+@container (width > 760px) not (height > 670px) {
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+}
+
+@container not (height <= 1080px) {
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+}
+
+@container (width < 500px) or (height < 500px) {
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+}
+
+@container (width < 500px) or (height < 500px) and (inline-size >= 0px) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container my-page-layout (width < 500px) or (height < 500px) and (block-size > 12em) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container (width < 500px) or (height < 500px) and (aspect-ratio: 3/2) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container (width < 500px) or (height < 500px) and (orientation: portrait) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container card (inline-size > 30em) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+
+ @container style(--responsive: true) {
+ .card-content {
+ grid-template-columns: 1fr 2fr;
+ grid-template-rows: auto 1fr;
+ align-items: start;
+ column-gap: 20px;
+ }
+
+ .card-content h2 {
+ padding: 0;
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container card (width > 400px), style(--responsive: true), scroll-state(stuck: top) {
+ h2 {
+ font-size: 1.5em;
+ }
+}
+
+@container style(--theme) {
+ .style-query {
+ color: red;
+ }
+}
+
+@container style((--theme: one) or (--theme: two)) {
+ .style-query-list {
+ color: blue;
+ }
+}
+
+@container contactBody (min-width: 1300px) {
+ .named-container {
+ width: 25%;
+ }
+}
+
+@container _body (min-width: 1300px) {
+ .underscored-container {
+ width: 25%;
+ }
+}
+
+@container --body (min-width: 1300px) {
+ .custom-ident-container {
+ width: 25%;
+ }
+}
+
+@container contact\\.body (min-width: 1300px) {
+ .escaped-container {
+ width: 25%;
+ }
+}
+
+@container café (min-width: 1300px) {
+ .nonascii-container {
+ width: 25%;
+ }
+}
+
+@container ( width < 500px ) or (height<500px) and (orientation: portrait) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+@container my-page-layout ( width< 500px) or ( height<500px) and ( block-size>12em ) {
+ .card-content p {
+ padding: 0;
+
+ h2 {
+ margin: 0.5em 0 0 0;
+ }
+ }
+}
+
+.wrapper {
+ container-name: wrapper;
+ container-type: size;
+}
+
+.my_mixin(@height) {
+ @container wrapper (height < @height) {
+ a {
+ max-height: @height;
+ }
+ }
+}
+
+.my_mixin(100);
+.my_mixin(200);
+.my_mixin(300);
+
+@media only screen and (min-width: 768px) {
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .media-1 {
+ font-size: 1.5rem;
+ }
+
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .media-1 {
+ font-size: 1.5rem;
+ }
+
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+ }
+
+ .media-2 {
+ font-size: 2rem;
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .media-1 {
+ font-size: 1.5rem;
+ }
+
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+
+ @media (hover: hover) {
+ .foo {
+ font-size: 1.75rem;
+ }
+ }
+ }
+
+ .media-2 {
+ font-size: 2rem;
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .media-1 {
+ font-size: 1.5rem;
+ }
+
+ @container (min-width: 500px) {
+ .primary-content {
+ font-size: 1rem;
+ }
+
+ @media (hover: hover) {
+ .foo {
+ font-size: 1.75rem;
+
+ @media not all and (hover: hover) {
+ color: limegreen;
+ }
+ }
+
+ .media-3 {
+ padding: 0.5rem;
+ }
+ }
+ }
+
+ .media-2 {
+ font-size: 2rem;
+ }
+}
+
+@container (min-width: 768px) {
+ @media only screen and (min-width: 768px) {
+ .foo {
+ color: aliceblue;
+ }
+ }
+
+ .container-1 {
+ color: purple;
+ }
+}
+
+#sticky {
+ position: sticky;
+ container-type: scroll-state;
+}
+
+@container scroll-state(stuck: top) {
+ #sticky-child {
+ font-size: 75%;
+ }
+}
+
+@container scroll-state(snapped: x) {
+ #sticky-child {
+ font-size: 75%;
+ }
+}
+
+@container scroll-state(scrollable: top) {
+ #sticky-child {
+ font-size: 75%;
+ }
+}
+
+@container sidebar (min-width: 400px), scroll-state(stuck: top) {
+ #sticky-child {
+ font-size: 80%;
+ }
+}
+
+@varfoo: foo;
+@threshold: 400px;
+@container @varfoo (min-width: @threshold) {
+ #sticky-child {
+ font-size: 75%;
+ }
+}
+
+// Regression test: mixin with variable container name and variable query condition
+// Issue: mixins with parameters using @container @name (condition < @var) failed
+// with "variable @bp is undefined" error in older versions
+@issue-width: 125px;
+
+.container-query-mixin(@container-name; @bp) {
+ @container @container-name (width < @bp) {
+ display: none;
+ }
+}
+
+.mixin-container-test {
+ .container-query-mixin(name, @issue-width);
+ color: red;
+}
+
+// Verify multiple calls with different params produce correct output
+.sidebar-test {
+ .container-query-mixin(sidebar, 500px);
+}
+.header-test {
+ .container-query-mixin(header, 800px);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/css-3/css-3.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@namespace foo url(http://www.example.com);
+.comma-delimited {
+ text-shadow: -1px -1px 1px red, 6px 5px 5px yellow;
+ -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset,
+ 0pt 4px 6px rgba(255, 255, 255, 0.4) inset;
+ -webkit-transform: rotate(-0.0000000001deg);
+}
+@font-face {
+ font-family: Headline;
+ unicode-range: U+??????, U+0???, U+0-7F, U+A5;
+}
+.other {
+ -moz-transform: translate(0, 11em) rotate(-90deg);
+ transform: rotateX(45deg);
+}
+.item[data-cra_zy-attr1b-ut3=bold] {
+ font-weight: bold;
+}
+p:not([class*="lead"]) {
+ color: black;
+}
+
+input[type="text"].class#id[attr=i32]:not(.one) {
+ color: inherit;
+}
+
+div#id.class[a=one][b=two].class:not(.one) {
+ color: inherit;
+}
+
+ul.comma > li:not(:only-child)::after {
+ color: inherit;
+}
+
+ol.comma > li:nth-last-child(2)::after {
+ color: inherit;
+}
+
+li:nth-child(4n+1),
+li:nth-child(-5n),
+li:nth-child(-n+2) {
+ color: inherit;
+}
+
+a[href^="http://"] {
+ color: black;
+}
+
+a[href$="http://"] {
+ color: black;
+}
+
+form[data-disabled] {
+ color: black;
+}
+
+p::before {
+ color: black;
+}
+
+#issue322 {
+ -webkit-animation: anim2 7s infinite ease-in-out;
+}
+
+@-webkit-keyframes frames {
+ 0% { border: 1px }
+ 5.5% { border: 2px }
+ 100% { border: 3px }
+}
+
+@keyframes fontbulger1 {
+ to {
+ font-size: 15px;
+ }
+ from,to {
+ font-size: 12px;
+ }
+ 0%,100% {
+ font-size: 12px;
+ }
+}
+
+@supports ( box-shadow: 2px 2px 2px black ) or
+ ( -moz-box-shadow: 2px 2px 2px black ) {
+ .outline {
+ box-shadow: 2px 2px 2px black;
+ -moz-box-shadow: 2px 2px 2px black;
+ }
+}
+
+@-x-document url-prefix(""github.com"") {
+ h1 {
+ color: red;
+ }
+}
+
+@viewport {
+ font-size: 10px;
+}
+
+foo|h1 { color: blue; }
+foo|* { color: yellow; }
+*|h1 { color: green; }
+h1 { color: green; }
+.upper-test {
+ UpperCaseProperties: allowed;
+}
+@host {
+ div {
+ display: block;
+ }
+}
+:not(input::placeholder) {
+ color: #b3b3b3;
+}
+.shadow > .dom,
+body > .shadow {
+ display: done;
+}
+
+:host(.sel.a),
+:host-context(.sel.b),
+.sel > .b,
+::content .sel {
+ type: shadow-dom;
+}
+* b {
+ c: 'd';
+ &[e]{
+ f: 'g';
+ }
+}
+
+#issue2066 {
+ background: url('/images/icon-team.svg') 0 0 / contain;
+}
+
+@counter-style triangle {
+ system: cyclic;
+ symbols: ‣;
+ suffix: " ";
+}
+
+@-ms-viewport{
+ // width: auto !important;
+}
+
+@unknown foo 42 (bar) {
+ x {y: z}
+}
+
+@unknown foo 43;
+
+
+
+=====================================output=====================================
+@namespace foo url(http://www.example.com);
+.comma-delimited {
+ text-shadow:
+ -1px -1px 1px red,
+ 6px 5px 5px yellow;
+ -moz-box-shadow:
+ 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset,
+ 0pt 4px 6px rgba(255, 255, 255, 0.4) inset;
+ -webkit-transform: rotate(-0.0000000001deg);
+}
+@font-face {
+ font-family: Headline;
+ unicode-range: U+??????, U+0???, U+0-7F, U+A5;
+}
+.other {
+ -moz-transform: translate(0, 11em) rotate(-90deg);
+ transform: rotateX(45deg);
+}
+.item[data-cra_zy-attr1b-ut3="bold"] {
+ font-weight: bold;
+}
+p:not([class*="lead"]) {
+ color: black;
+}
+
+input[type="text"].class#id[attr="i32"]:not(.one) {
+ color: inherit;
+}
+
+div#id.class[a="one"][b="two"].class:not(.one) {
+ color: inherit;
+}
+
+ul.comma > li:not(:only-child)::after {
+ color: inherit;
+}
+
+ol.comma > li:nth-last-child(2)::after {
+ color: inherit;
+}
+
+li:nth-child(4n + 1),
+li:nth-child(-5n),
+li:nth-child(-n + 2) {
+ color: inherit;
+}
+
+a[href^="http://"] {
+ color: black;
+}
+
+a[href$="http://"] {
+ color: black;
+}
+
+form[data-disabled] {
+ color: black;
+}
+
+p::before {
+ color: black;
+}
+
+#issue322 {
+ -webkit-animation: anim2 7s infinite ease-in-out;
+}
+
+@-webkit-keyframes frames {
+ 0% {
+ border: 1px;
+ }
+ 5.5% {
+ border: 2px;
+ }
+ 100% {
+ border: 3px;
+ }
+}
+
+@keyframes fontbulger1 {
+ to {
+ font-size: 15px;
+ }
+ from,
+ to {
+ font-size: 12px;
+ }
+ 0%,
+ 100% {
+ font-size: 12px;
+ }
+}
+
+@supports (box-shadow: 2px 2px 2px black) or
+ (-moz-box-shadow: 2px 2px 2px black) {
+ .outline {
+ box-shadow: 2px 2px 2px black;
+ -moz-box-shadow: 2px 2px 2px black;
+ }
+}
+
+@-x-document url-prefix(""github.com"") {
+ h1 {
+ color: red;
+ }
+}
+
+@viewport {
+ font-size: 10px;
+}
+
+foo|h1 {
+ color: blue;
+}
+foo|* {
+ color: yellow;
+}
+*|h1 {
+ color: green;
+}
+h1 {
+ color: green;
+}
+.upper-test {
+ uppercaseproperties: allowed;
+}
+@host {
+ div {
+ display: block;
+ }
+}
+:not(input::placeholder) {
+ color: #b3b3b3;
+}
+.shadow > .dom,
+body > .shadow {
+ display: done;
+}
+
+:host(.sel.a),
+:host-context(.sel.b),
+.sel > .b,
+::content .sel {
+ type: shadow-dom;
+}
+* b {
+ c: "d";
+ &[e] {
+ f: "g";
+ }
+}
+
+#issue2066 {
+ background: url("/images/icon-team.svg") 0 0 / contain;
+}
+
+@counter-style triangle {
+ system: cyclic;
+ symbols: ‣;
+ suffix: " ";
+}
+
+@-ms-viewport {
+ // width: auto !important;
+}
+
+@unknown foo 42 (bar) {
+ x {
+ y: z;
+ }
+}
+
+@unknown foo 43;
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/css-grid/css-grid.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.wrapper {
+ display: grid;
+ grid-template-columns: [col1-start] 9fr [col1-end] 10px [col2-start] 3fr [col2-end];
+ grid-template-rows: auto;
+}
+
+.wrapper {
+ display: grid;
+ grid-template-columns: [left-bound] auto [container-left] 1170px [container-right] auto [right-bound];
+ grid-template-rows: [row-1-start] 140px [row-2-start] 390px [row-3-start] 200px [row-4-start] 120px [row-5-start] 120px [row-6-start] 120px;
+}
+
+.container-12 {
+ z-index: 20;
+ display: grid;
+ grid-column: container-left / span 1;
+ grid-row: 2;
+ grid-template-columns: [wrapcol-1-start] 1fr [wrapcol-1-end] 15px [wrapcol-2-start] 1fr [wrapcol-2-end] 15px [wrapcol-3-start] 1fr [wrapcol-3-end] 15px [wrapcol-4-start] 1fr [wrapcol-4-end] 15px [wrapcol-5-start] 1fr [wrapcol-5-end] 15px [wrapcol-6-start] 1fr [wrapcol-6-end] 15px [wrapcol-7-start] 1fr [wrapcol-7-end] 15px [wrapcol-8-start] 1fr [wrapcol-8-end] 15px [wrapcol-9-start] 1fr [wrapcol-9-end] 15px [wrapcol-10-start] 1fr [wrapcol-10-end] 15px [wrapcol-11-start] 1fr [wrapcol-11-end] 15px [wrapcol-12-start] 1fr [wrapcol-12-end];
+ grid-template-rows: repeat(14, [gutter] 10px [row] 60px);
+}
+
+.wrapper {
+ display: grid;
+ grid-template-columns: 9fr 1.875em 3fr;
+ grid-template-rows: auto;
+ grid-template-areas:
+ "header header header"
+ "content . sidebar"
+ "footer footer footer";
+}
+
+
+
+=====================================output=====================================
+.wrapper {
+ display: grid;
+ grid-template-columns: [col1-start] 9fr [col1-end] 10px [col2-start] 3fr [col2-end];
+ grid-template-rows: auto;
+}
+
+.wrapper {
+ display: grid;
+ grid-template-columns: [left-bound] auto [container-left] 1170px [container-right] auto [right-bound];
+ grid-template-rows: [row-1-start] 140px [row-2-start] 390px [row-3-start] 200px [row-4-start] 120px [row-5-start] 120px [row-6-start] 120px;
+}
+
+.container-12 {
+ z-index: 20;
+ display: grid;
+ grid-column: container-left / span 1;
+ grid-row: 2;
+ grid-template-columns: [wrapcol-1-start] 1fr [wrapcol-1-end] 15px [wrapcol-2-start] 1fr [wrapcol-2-end] 15px [wrapcol-3-start] 1fr [wrapcol-3-end] 15px [wrapcol-4-start] 1fr [wrapcol-4-end] 15px [wrapcol-5-start] 1fr [wrapcol-5-end] 15px [wrapcol-6-start] 1fr [wrapcol-6-end] 15px [wrapcol-7-start] 1fr [wrapcol-7-end] 15px [wrapcol-8-start] 1fr [wrapcol-8-end] 15px [wrapcol-9-start] 1fr [wrapcol-9-end] 15px [wrapcol-10-start] 1fr [wrapcol-10-end] 15px [wrapcol-11-start] 1fr [wrapcol-11-end] 15px [wrapcol-12-start] 1fr [wrapcol-12-end];
+ grid-template-rows: repeat(14, [gutter] 10px [row] 60px);
+}
+
+.wrapper {
+ display: grid;
+ grid-template-columns: 9fr 1.875em 3fr;
+ grid-template-rows: auto;
+ grid-template-areas:
+ "header header header"
+ "content . sidebar"
+ "footer footer footer";
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/css-guards/css-guards.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.light when (lightness(@a) > 50%) {
+ color: green;
+}
+.dark when (lightness(@a) < 50%) {
+ color: orange;
+}
+@a: #ddd;
+
+.see-the {
+ @a: #444; // this mirrors what mixins do - they evaluate the guards at the point of definition
+ .light();
+ .dark();
+}
+
+.hide-the {
+ .light();
+ .dark();
+}
+
+.multiple-conditions-1 when (@b = 1), (@c = 2), (@d = 3) {
+ color: red;
+}
+
+.multiple-conditions-2 when (@b = 1), (@c = 2), (@d = 2) {
+ color: blue;
+}
+
+@b: 2;
+@c: 3;
+@d: 3;
+
+.inheritance when (@b = 2) {
+ .test-rule {
+ color: black;
+ }
+ &:hover {
+ color: pink;
+ }
+ .hideme when (@b = 1) {
+ color: green;
+ }
+ & when (@b = 1) {
+ hideme: green;
+ }
+}
+
+.hideme when (@b = 1) {
+ .test-rule {
+ color: black;
+ }
+ &:hover {
+ color: pink;
+ }
+ .hideme when (@b = 1) {
+ color: green;
+ }
+}
+
+& when (@b = 1) {
+ .hideme {
+ color: red;
+ }
+}
+
+.mixin-with-guard-inside(@colWidth) {
+ // selector with guard (applies also to & when() ...)
+ .clsWithGuard when (@colWidth <= 0) {
+ dispaly: none;
+ }
+}
+
+.mixin-with-guard-inside(0px);
+
+.dont-split-me-up {
+ width: 1px;
+ & when (@c = 3) {
+ color: red;
+ }
+ & when (@c = 3) {
+ height: 1px;
+ }
+ * & when (@c = 3) {
+ sibling: true;
+ }
+}
+
+.scope-check when (@c = 3) {
+ @k: 1px;
+ & when (@c = 3) {
+ @k: 2px;
+ sub-prop: @k;
+ }
+ prop: @k;
+}
+.scope-check-2 {
+ .scope-check();
+ @k:4px;
+}
+.errors-if-called when (@c = never) {
+ .mixin-doesnt-exist();
+}
+a:hover when (2 = true) {5:-}
+
+
+
+=====================================output=====================================
+.light when (lightness(@a) > 50%) {
+ color: green;
+}
+.dark when (lightness(@a) < 50%) {
+ color: orange;
+}
+@a: #ddd;
+
+.see-the {
+ @a: #444; // this mirrors what mixins do - they evaluate the guards at the point of definition
+ .light();
+ .dark();
+}
+
+.hide-the {
+ .light();
+ .dark();
+}
+
+.multiple-conditions-1 when (@b = 1), (@c = 2), (@d = 3) {
+ color: red;
+}
+
+.multiple-conditions-2 when (@b = 1), (@c = 2), (@d = 2) {
+ color: blue;
+}
+
+@b: 2;
+@c: 3;
+@d: 3;
+
+.inheritance when (@b = 2) {
+ .test-rule {
+ color: black;
+ }
+ &:hover {
+ color: pink;
+ }
+ .hideme when (@b = 1) {
+ color: green;
+ }
+ & when (@b = 1) {
+ hideme: green;
+ }
+}
+
+.hideme when (@b = 1) {
+ .test-rule {
+ color: black;
+ }
+ &:hover {
+ color: pink;
+ }
+ .hideme when (@b = 1) {
+ color: green;
+ }
+}
+
+& when (@b = 1) {
+ .hideme {
+ color: red;
+ }
+}
+
+.mixin-with-guard-inside(@colWidth) {
+ // selector with guard (applies also to & when() ...)
+ .clsWithGuard when (@colWidth <= 0) {
+ dispaly: none;
+ }
+}
+
+.mixin-with-guard-inside(0px);
+
+.dont-split-me-up {
+ width: 1px;
+ & when (@c = 3) {
+ color: red;
+ }
+ & when (@c = 3) {
+ height: 1px;
+ }
+ * & when (@c = 3) {
+ sibling: true;
+ }
+}
+
+.scope-check when (@c = 3) {
+ @k: 1px;
+ & when (@c = 3) {
+ @k: 2px;
+ sub-prop: @k;
+ }
+ prop: @k;
+}
+.scope-check-2 {
+ .scope-check();
+ @k: 4px;
+}
+.errors-if-called when (@c = never) {
+ .mixin-doesnt-exist();
+}
+a:hover when (2 = true) {
+ 5: -;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/detached-rulesets/detached-rulesets.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@ruleset: {
+ color: black;
+ background: white;
+}
+
+@a: 1px;
+.wrap-mixin(@ruleset) {
+ @a: hidden and if you see this in the output its a bug;
+ @b: visible;
+ @d: magic-frame; // same behaviour as mixin calls - falls back to this frame
+ .wrap-selector {
+ @c: visible;
+ @ruleset();
+ visible-one: @b;
+ visible-two: @c;
+ }
+}
+
+.wrap-mixin({
+ color: black;
+ one: @a;
+ @b: hidden and if you see this in the output its a bug;
+ @c: hidden and if you see this in the output its a bug;
+ four: @d;
+});
+
+.wrap-mixin(@ruleset: {
+ color: red;
+});
+
+.wrap-mixin(@ruleset);
+
+.desktop-and-old-ie(@rules) {
+ @media screen and (min-width: 1200) { @rules() }
+ html.lt-ie9 & { @rules() }
+}
+
+header {
+ background: blue;
+
+ .desktop-and-old-ie({
+ background: red;
+ });
+}
+
+.wrap-mixin-calls-wrap(@ruleset) {
+ .wrap-mixin(@ruleset);
+};
+
+.wrap-mixin({
+ test: extra-wrap;
+ .wrap-mixin-calls-wrap({
+ test: wrapped-twice;
+ });
+});
+
+.wrap-mixin({
+ test-func: unit(90px);
+ test-arithmetic: unit((9+9), px);
+});
+// without mixins
+@ruleset-2: {
+ b: 1;
+};
+.without-mixins {
+ @ruleset-2();
+}
+@my-ruleset: {
+ .my-selector {
+ @media (tv) {
+ background-color: black;
+ }
+ }
+ };
+@media (orientation:portrait) {
+ @my-ruleset();
+ .wrap-media-mixin({
+ @media (tv) {
+ .triple-wrapped-mq {
+ triple: true;
+ }
+ }
+ });
+}
+.wrap-media-mixin(@ruleset) {
+ @media (widescreen) {
+ @media (print) {
+ @ruleset();
+ }
+ @ruleset();
+ }
+ @ruleset();
+}
+// unlocking mixins
+@my-mixins: {
+ .mixin() {
+ test: test;
+ }
+};
+@my-mixins();
+.a {
+ .mixin();
+}
+// as mixin argument default
+.mixin-definition(@a: {}; @b: {default: works;};) {
+ @a();
+ @b();
+}
+.argument-default {
+ .mixin-definition();
+ .mixin-definition({direct: works;}; @b: {named: works;});
+}
+
+
+
+=====================================output=====================================
+@ruleset: {
+ color: black;
+ background: white;
+};
+
+@a: 1px;
+.wrap-mixin(@ruleset) {
+ @a: hidden and if you see this in the output its a bug;
+ @b: visible;
+ @d: magic-frame; // same behaviour as mixin calls - falls back to this frame
+ .wrap-selector {
+ @c: visible;
+ @ruleset();
+ visible-one: @b;
+ visible-two: @c;
+ }
+}
+
+.wrap-mixin({
+ color: black;
+ one: @a;
+ @b: hidden and if you see this in the output its a bug;
+ @c: hidden and if you see this in the output its a bug;
+ four: @d;
+});
+
+.wrap-mixin(@ruleset: {
+ color: red;
+});
+
+.wrap-mixin(@ruleset);
+
+.desktop-and-old-ie(@rules) {
+ @media screen and (min-width: 1200) {
+ @rules();
+ }
+ html.lt-ie9 & {
+ @rules();
+ }
+}
+
+header {
+ background: blue;
+
+ .desktop-and-old-ie({
+ background: red;
+ });
+}
+
+.wrap-mixin-calls-wrap(@ruleset) {
+ .wrap-mixin(@ruleset);
+}
+
+.wrap-mixin({
+ test: extra-wrap;
+ .wrap-mixin-calls-wrap({
+ test: wrapped-twice;
+ });
+});
+
+.wrap-mixin({
+ test-func: unit(90px);
+ test-arithmetic: unit((9+9), px);
+});
+// without mixins
+@ruleset-2: {
+ b: 1;
+};
+.without-mixins {
+ @ruleset-2();
+}
+@my-ruleset: {
+ .my-selector {
+ @media (tv) {
+ background-color: black;
+ }
+ }
+};
+@media (orientation: portrait) {
+ @my-ruleset();
+ .wrap-media-mixin({
+ @media (tv) {
+ .triple-wrapped-mq {
+ triple: true;
+ }
+ }
+ });
+}
+.wrap-media-mixin(@ruleset) {
+ @media (widescreen) {
+ @media (print) {
+ @ruleset();
+ }
+ @ruleset();
+ }
+ @ruleset();
+}
+// unlocking mixins
+@my-mixins: {
+ .mixin() {
+ test: test;
+ }
+};
+@my-mixins();
+.a {
+ .mixin();
+}
+// as mixin argument default
+.mixin-definition(@a: {}; @b: {default: works;};) {
+ @a();
+ @b();
+}
+.argument-default {
+ .mixin-definition();
+ .mixin-definition({direct: works;}; @b: {named: works;});
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/directives-bubbling/directives-bubbling.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+//simple case: @document
+.parent {
+ color:green;
+
+ @document url-prefix() {
+ .child {
+ color:red;
+ }
+ }
+}
+
+//selectors joinings test
+.top {
+ @supports (sandwitch: butter) {
+ .inside & {
+ property: value;
+ }
+ }
+}
+
+@supports (sandwitch: bread) {
+ .in1 {
+ .in2 {
+ property: value;
+ }
+ }
+}
+
+.top {
+ .inside & {
+ @supports (sandwitch: ham) {
+ property: value;
+ }
+ }
+}
+
+//combined with @font-face which has different kind of body
+@supports (font-family: weirdFont) {
+ @font-face {
+ font-family: something;
+ src: made-up-url;
+ }
+}
+
+@font-face {
+ @supports not (-webkit-font-smoothing: subpixel-antialiased) {
+ font-family: something;
+ src: made-up-url;
+ }
+}
+
+//bubbling through media
+@supports (property: value) {
+ .outOfMedia & {
+ @media (max-size: 2px) {
+ @supports (whatever: something) {
+ property: value;
+ }
+ }
+ }
+}
+
+.onTop & {
+ @supports (property: value) {
+ @media (max-size: 2px) {
+ @supports (whatever: something) {
+ property: value;
+ }
+ }
+ }
+}
+
+
+//long combination of supports and media
+@media print {
+ html {
+ in-html: visible;
+ @supports (upper: test) {
+ in-supports: first;
+ div {
+ in-div: visible;
+ @supports not (-webkit-font-smoothing: subpixel-antialiased) {
+ in-supports: second;
+ @media screen {
+ font-weight: 400;
+ nested {
+ property: value;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+//another long combination of supports and media
+@media print {
+ @media (max-size: 2px) {
+ .in1 {
+ stay: here;
+ @supports not (-webkit-font-smoothing: subpixel-antialiased) {
+ .in2 & {
+ @supports (whatever: something) {
+ property: value;
+ }
+ }
+ }
+ }
+ }
+}
+
+//called from mixin
+.nestedSupportsMixin() {
+ font-weight: 300;
+ -webkit-font-smoothing: subpixel-antialiased;
+ @supports not (-webkit-font-smoothing: subpixel-antialiased) {
+ font-weight: 400;
+ nested {
+ property: value;
+ }
+ }
+}
+
+html {
+ .nestedSupportsMixin();
+}
+
+// selectors should not propagate into all directive types
+.onTop {
+ @font-face {
+ font-family: something;
+ src: made-up-url;
+ }
+
+ @keyframes "textscale" {
+ 0% { font-size : 1em; }
+ 100% { font-size : 2em; }
+ }
+
+ animation : "textscale";
+ font-family : something;
+}
+
+
+=====================================output=====================================
+//simple case: @document
+.parent {
+ color: green;
+
+ @document url-prefix() {
+ .child {
+ color: red;
+ }
+ }
+}
+
+//selectors joinings test
+.top {
+ @supports (sandwitch: butter) {
+ .inside & {
+ property: value;
+ }
+ }
+}
+
+@supports (sandwitch: bread) {
+ .in1 {
+ .in2 {
+ property: value;
+ }
+ }
+}
+
+.top {
+ .inside & {
+ @supports (sandwitch: ham) {
+ property: value;
+ }
+ }
+}
+
+//combined with @font-face which has different kind of body
+@supports (font-family: weirdFont) {
+ @font-face {
+ font-family: something;
+ src: made-up-url;
+ }
+}
+
+@font-face {
+ @supports not (-webkit-font-smoothing: subpixel-antialiased) {
+ font-family: something;
+ src: made-up-url;
+ }
+}
+
+//bubbling through media
+@supports (property: value) {
+ .outOfMedia & {
+ @media (max-size: 2px) {
+ @supports (whatever: something) {
+ property: value;
+ }
+ }
+ }
+}
+
+.onTop & {
+ @supports (property: value) {
+ @media (max-size: 2px) {
+ @supports (whatever: something) {
+ property: value;
+ }
+ }
+ }
+}
+
+//long combination of supports and media
+@media print {
+ html {
+ in-html: visible;
+ @supports (upper: test) {
+ in-supports: first;
+ div {
+ in-div: visible;
+ @supports not (-webkit-font-smoothing: subpixel-antialiased) {
+ in-supports: second;
+ @media screen {
+ font-weight: 400;
+ nested {
+ property: value;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+//another long combination of supports and media
+@media print {
+ @media (max-size: 2px) {
+ .in1 {
+ stay: here;
+ @supports not (-webkit-font-smoothing: subpixel-antialiased) {
+ .in2 & {
+ @supports (whatever: something) {
+ property: value;
+ }
+ }
+ }
+ }
+ }
+}
+
+//called from mixin
+.nestedSupportsMixin() {
+ font-weight: 300;
+ -webkit-font-smoothing: subpixel-antialiased;
+ @supports not (-webkit-font-smoothing: subpixel-antialiased) {
+ font-weight: 400;
+ nested {
+ property: value;
+ }
+ }
+}
+
+html {
+ .nestedSupportsMixin();
+}
+
+// selectors should not propagate into all directive types
+.onTop {
+ @font-face {
+ font-family: something;
+ src: made-up-url;
+ }
+
+ @keyframes "textscale" {
+ 0% {
+ font-size: 1em;
+ }
+ 100% {
+ font-size: 2em;
+ }
+ }
+
+ animation: "textscale";
+ font-family: something;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/empty/empty.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+
+
+
+
+=====================================output=====================================
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/extend/extend.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Extend functionality tests
+.error {
+ border: 1px #f00;
+ background: #fdd;
+}
+.error.intrusion {
+ font-size: 1.3em;
+ font-weight: bold;
+}
+.intrusion .error {
+ display: none;
+}
+.badError {
+ &:extend(.error all);
+ border-width: 3px;
+}
+
+.foo .bar, .foo .baz {
+ display: none;
+}
+
+.ext1 .ext2 {
+ &:extend(.foo all);
+}
+
+.ext3,
+.ext4 {
+ &:extend(.foo all);
+ &:extend(.bar all);
+}
+
+div.ext5,
+.ext6 > .ext5 {
+ width: 100px;
+}
+
+.ext7 {
+ &:extend(.ext5 all);
+}
+
+.ext8.ext9 {
+ result: add-foo;
+}
+.ext8 .ext9,
+.ext8 + .ext9,
+.ext8 > .ext9 {
+ result: bar-matched;
+}
+.ext8.nomatch {
+ result: none;
+}
+.ext8 {
+ .ext9 {
+ result: match-nested-bar;
+ }
+}
+.ext8 {
+ &.ext9 {
+ result: match-nested-foo;
+ }
+}
+
+.fuu:extend( .ext8.ext9 all) {}
+.buu:extend(.ext8 .ext9 all) {}
+.zap:extend(.ext8 + .ext9 all) {}
+.zoo:extend(.ext8 > .ext9 all) {}
+
+.aa {
+ color: black;
+ .dd {
+ background: red;
+ }
+}
+.bb {
+ background: red;
+ .bb {
+ color: black;
+ }
+}
+.cc:extend(.aa,.bb) {}
+.ee:extend(.dd all,.bb) {}
+.ff:extend(.dd,.bb all) {}
+
+=====================================output=====================================
+// Extend functionality tests
+.error {
+ border: 1px #f00;
+ background: #fdd;
+}
+.error.intrusion {
+ font-size: 1.3em;
+ font-weight: bold;
+}
+.intrusion .error {
+ display: none;
+}
+.badError {
+ &:extend(.error all);
+ border-width: 3px;
+}
+
+.foo .bar,
+.foo .baz {
+ display: none;
+}
+
+.ext1 .ext2 {
+ &:extend(.foo all);
+}
+
+.ext3,
+.ext4 {
+ &:extend(.foo all);
+ &:extend(.bar all);
+}
+
+div.ext5,
+.ext6 > .ext5 {
+ width: 100px;
+}
+
+.ext7 {
+ &:extend(.ext5 all);
+}
+
+.ext8.ext9 {
+ result: add-foo;
+}
+.ext8 .ext9,
+.ext8 + .ext9,
+.ext8 > .ext9 {
+ result: bar-matched;
+}
+.ext8.nomatch {
+ result: none;
+}
+.ext8 {
+ .ext9 {
+ result: match-nested-bar;
+ }
+}
+.ext8 {
+ &.ext9 {
+ result: match-nested-foo;
+ }
+}
+
+.fuu:extend(.ext8.ext9 all) {
+}
+.buu:extend(.ext8 .ext9 all) {
+}
+.zap:extend(.ext8 + .ext9 all) {
+}
+.zoo:extend(.ext8 > .ext9 all) {
+}
+
+.aa {
+ color: black;
+ .dd {
+ background: red;
+ }
+}
+.bb {
+ background: red;
+ .bb {
+ color: black;
+ }
+}
+.cc:extend(.aa, .bb) {
+}
+.ee:extend(.dd all, .bb) {
+}
+.ff:extend(.dd, .bb all) {
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/extend/extend-clearfix.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.clearfix {
+ *zoom: 1;
+ &:after {
+ content: '';
+ display: block;
+ clear: both;
+ height: 0;
+ }
+}
+
+.foo {
+ &:extend(.clearfix all);
+ color: red;
+}
+
+.bar {
+ &:extend(.clearfix all);
+ color: blue;
+}
+
+=====================================output=====================================
+.clearfix {
+ *zoom: 1;
+ &:after {
+ content: "";
+ display: block;
+ clear: both;
+ height: 0;
+ }
+}
+
+.foo {
+ &:extend(.clearfix all);
+ color: red;
+}
+
+.bar {
+ &:extend(.clearfix all);
+ color: blue;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/extend-clearfix/extend-clearfix.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.clearfix {
+ *zoom: 1;
+ &:after {
+ content: '';
+ display: block;
+ clear: both;
+ height: 0;
+ }
+}
+
+.foo {
+ &:extend(.clearfix all);
+ color: red;
+}
+
+.bar {
+ &:extend(.clearfix all);
+ color: blue;
+}
+
+
+=====================================output=====================================
+.clearfix {
+ *zoom: 1;
+ &:after {
+ content: "";
+ display: block;
+ clear: both;
+ height: 0;
+ }
+}
+
+.foo {
+ &:extend(.clearfix all);
+ color: red;
+}
+
+.bar {
+ &:extend(.clearfix all);
+ color: blue;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/extend-exact/extend-exact.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.replace.replace,
+.c.replace + .replace {
+ .replace,
+ .c {
+ prop: copy-paste-replace;
+ }
+}
+.rep_ace:extend(.replace.replace .replace) {}
+
+.a .b .c {
+ prop: not_effected;
+}
+
+.a {
+ prop: is_effected;
+ .b {
+ prop: not_effected;
+ }
+ .b.c {
+ prop: not_effected;
+ }
+}
+
+.c, .a {
+ .b, .a {
+ .a, .c {
+ prop: not_effected;
+ }
+ }
+}
+
+.effected {
+ &:extend(.a);
+ &:extend(.b);
+ &:extend(.c);
+}
+
+.e {
+ && {
+ prop: extend-double;
+ &:hover {
+ hover: not-extended;
+ }
+ }
+}
+.dbl:extend(.e.e) {}
+
+
+=====================================output=====================================
+.replace.replace,
+.c.replace + .replace {
+ .replace,
+ .c {
+ prop: copy-paste-replace;
+ }
+}
+.rep_ace:extend(.replace.replace .replace) {
+}
+
+.a .b .c {
+ prop: not_effected;
+}
+
+.a {
+ prop: is_effected;
+ .b {
+ prop: not_effected;
+ }
+ .b.c {
+ prop: not_effected;
+ }
+}
+
+.c,
+.a {
+ .b,
+ .a {
+ .a,
+ .c {
+ prop: not_effected;
+ }
+ }
+}
+
+.effected {
+ &:extend(.a);
+ &:extend(.b);
+ &:extend(.c);
+}
+
+.e {
+ && {
+ prop: extend-double;
+ &:hover {
+ hover: not-extended;
+ }
+ }
+}
+.dbl:extend(.e.e) {
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/extend-media/extend-media.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.ext1 .ext2 {
+ background: black;
+}
+
+@media (tv) {
+ .ext1 .ext3 {
+ color: inherit;
+ }
+ .tv-lowres :extend(.ext1 all) {
+ background: blue;
+ }
+ @media (hires) {
+ .ext1 .ext4 {
+ color: green;
+ }
+ .tv-hires :extend(.ext1 all) {
+ background: red;
+ }
+ }
+}
+
+.all:extend(.ext1 all) {
+
+}
+
+
+=====================================output=====================================
+.ext1 .ext2 {
+ background: black;
+}
+
+@media (tv) {
+ .ext1 .ext3 {
+ color: inherit;
+ }
+ .tv-lowres :extend(.ext1 all) {
+ background: blue;
+ }
+ @media (hires) {
+ .ext1 .ext4 {
+ color: green;
+ }
+ .tv-hires :extend(.ext1 all) {
+ background: red;
+ }
+ }
+}
+
+.all:extend(.ext1 all) {
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/extend-nest/extend-nest.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.sidebar {
+ width: 300px;
+ background: red;
+
+ .box {
+ background: #FFF;
+ border: 1px solid #000;
+ margin: 10px 0;
+ }
+}
+
+.sidebar2 {
+ &:extend(.sidebar all);
+ background: blue;
+}
+
+.type1 {
+ .sidebar3 {
+ &:extend(.sidebar all);
+ background: green;
+ }
+}
+
+.type2 {
+ &.sidebar4 {
+ &:extend(.sidebar all);
+ background: red;
+ }
+}
+
+.button {
+ color: black;
+ &:hover {
+ color: inherit;
+ }
+}
+.submit {
+ &:extend(.button);
+ &:hover:extend(.button:hover) {}
+}
+
+.nomatch {
+ &:hover:extend(.button :hover) {}
+}
+
+.button2 {
+ :hover {
+ nested: white;
+ }
+}
+.button2 :hover {
+ notnested: black;
+}
+
+.nomatch :extend(.button2:hover) {}
+
+.amp-test-a,
+.amp-test-b {
+ .amp-test-c &.amp-test-d&.amp-test-e {
+ .amp-test-f&+&.amp-test-g:extend(.amp-test-h) {}
+ }
+}
+.amp-test-h {
+ test: extended by masses of selectors;
+}
+
+
+=====================================output=====================================
+.sidebar {
+ width: 300px;
+ background: red;
+
+ .box {
+ background: #fff;
+ border: 1px solid #000;
+ margin: 10px 0;
+ }
+}
+
+.sidebar2 {
+ &:extend(.sidebar all);
+ background: blue;
+}
+
+.type1 {
+ .sidebar3 {
+ &:extend(.sidebar all);
+ background: green;
+ }
+}
+
+.type2 {
+ &.sidebar4 {
+ &:extend(.sidebar all);
+ background: red;
+ }
+}
+
+.button {
+ color: black;
+ &:hover {
+ color: inherit;
+ }
+}
+.submit {
+ &:extend(.button);
+ &:hover:extend(.button:hover) {
+ }
+}
+
+.nomatch {
+ &:hover:extend(.button :hover) {
+ }
+}
+
+.button2 {
+ :hover {
+ nested: white;
+ }
+}
+.button2 :hover {
+ notnested: black;
+}
+
+.nomatch :extend(.button2:hover) {
+}
+
+.amp-test-a,
+.amp-test-b {
+ .amp-test-c &.amp-test-d&.amp-test-e {
+ .amp-test-f& + &.amp-test-g:extend(.amp-test-h) {
+ }
+ }
+}
+.amp-test-h {
+ test: extended by masses of selectors;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/extend-selector/extend-selector.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.error {
+ border: 1px #f00;
+ background: #fdd;
+}
+.error.intrusion {
+ font-size: 1.3em;
+ font-weight: bold;
+}
+.intrusion .error {
+ display: none;
+}
+.badError:extend(.error all) {
+ border-width: 3px;
+}
+
+.foo .bar, .foo .baz {
+ display: none;
+}
+
+.ext1 .ext2
+ :extend(.foo all) {
+}
+
+.ext3:extend(.foo all),
+.ext4:extend(.foo all) {
+}
+
+div.ext5,
+.ext6 > .ext5 {
+ width: 100px;
+}
+
+.should-not-exist-in-output,
+.ext7:extend(.ext5 all) {
+}
+
+.ext {
+ test: 1;
+}
+// same as
+// .a .c:extend(.ext all)
+// .b .c:extend(.ext all)
+// .a .c .d
+// .b .c .d
+.a, .b {
+ test: 2;
+ .c:extend(.ext all) {
+ test: 3;
+ .d {
+ test: 4;
+ }
+ }
+}
+
+.replace.replace,
+.c.replace + .replace {
+ .replace,
+ .c {
+ prop: copy-paste-replace;
+ }
+}
+.rep_ace:extend(.replace all) {}
+
+.attributes {
+ [data="test"] {
+ extend: attributes;
+ }
+ .attribute-test {
+ &:extend([data="test"] all);
+ }
+ [data] {
+ extend: attributes2;
+ }
+ .attribute-test2 {
+ &:extend([data] all); //you could argue it should match [data="test"]... not for now though...
+ }
+ @attr-data: "test3";
+ [data=@{attr-data}] {
+ extend: attributes2;
+ }
+ .attribute-test {
+ &:extend([data="test3"] all);
+ }
+}
+
+.header {
+ .header-nav {
+ background: red;
+ &:before {
+ background: blue;
+ }
+ }
+}
+
+.footer {
+ .footer-nav {
+ &:extend( .header .header-nav all );
+ }
+}
+
+.issue-2586-bordered {
+ border: solid 1px black;
+}
+.issue-2586-somepage {
+ .content:extend(.issue-2586-bordered) {
+ &>span {
+ margin-bottom: 10px;
+ }
+ }
+}
+
+
+=====================================output=====================================
+.error {
+ border: 1px #f00;
+ background: #fdd;
+}
+.error.intrusion {
+ font-size: 1.3em;
+ font-weight: bold;
+}
+.intrusion .error {
+ display: none;
+}
+.badError:extend(.error all) {
+ border-width: 3px;
+}
+
+.foo .bar,
+.foo .baz {
+ display: none;
+}
+
+.ext1 .ext2 :extend(.foo all) {
+}
+
+.ext3:extend(.foo all),
+.ext4:extend(.foo all) {
+}
+
+div.ext5,
+.ext6 > .ext5 {
+ width: 100px;
+}
+
+.should-not-exist-in-output,
+.ext7:extend(.ext5 all) {
+}
+
+.ext {
+ test: 1;
+}
+// same as
+// .a .c:extend(.ext all)
+// .b .c:extend(.ext all)
+// .a .c .d
+// .b .c .d
+.a,
+.b {
+ test: 2;
+ .c:extend(.ext all) {
+ test: 3;
+ .d {
+ test: 4;
+ }
+ }
+}
+
+.replace.replace,
+.c.replace + .replace {
+ .replace,
+ .c {
+ prop: copy-paste-replace;
+ }
+}
+.rep_ace:extend(.replace all) {
+}
+
+.attributes {
+ [data="test"] {
+ extend: attributes;
+ }
+ .attribute-test {
+ &:extend([data="test"] all);
+ }
+ [data] {
+ extend: attributes2;
+ }
+ .attribute-test2 {
+ &:extend([data]
+ all); //you could argue it should match [data="test"]... not for now though...
+ }
+ @attr-data: "test3";
+ [data="@{attr-data}"] {
+ extend: attributes2;
+ }
+ .attribute-test {
+ &:extend([data="test3"] all);
+ }
+}
+
+.header {
+ .header-nav {
+ background: red;
+ &:before {
+ background: blue;
+ }
+ }
+}
+
+.footer {
+ .footer-nav {
+ &:extend(.header .header-nav all);
+ }
+}
+
+.issue-2586-bordered {
+ border: solid 1px black;
+}
+.issue-2586-somepage {
+ .content:extend(.issue-2586-bordered) {
+ & > span {
+ margin-bottom: 10px;
+ }
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/functions-each/functions-each.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@selectors: blue, green, red;
+@list: a b c d;
+
+each(@selectors, {
+ .sel-@{value} {
+ a: b;
+ }
+});
+
+.each {
+ each(@list, {
+ index+: @index;
+ item@{index}: @value;
+ });
+
+ // nested each
+ each(10px 15px, 20px 25px; {
+ // demonstrates nesting of each()
+ each(@value; #(@v, @k, @i) {
+ nest-@{i}-@{index}: @v @k;
+ });
+ });
+
+ // nested anonymous mixin
+ .nest-anon {
+ each(a b, .(@v;@i) {
+ each(c d, .(@vv;@ii) {
+ nest-@{i}-@{ii}: @v @vv;
+ });
+ });
+ }
+
+ // vector math
+ each(1 2 3 4, {
+ padding+_: (@value * 10px);
+ });
+}
+
+@set: {
+ one: blue;
+ // skip comments
+ two: green;
+ /** and these
+ */
+ three: red; //and this
+}
+.set {
+ each(@set, {
+ @{key}: @value;
+ });
+}
+.set-2() {
+ one: blue;
+ two: green;
+ three: red;
+}
+.set-2 {
+ each(.set-2(), .(@v, @k, @i) {
+ @{k}-@{i}: @v;
+ });
+}
+
+.pick(@a) when (@a = 4) {
+ val3: @a;
+}
+.single {
+ each(true, {
+ val: @value;
+ });
+ @exp: 1 + 1;
+ each(@exp, {
+ val2: @value;
+ });
+ each(1 2 3 4, {
+ .pick(@value);
+ });
+}
+
+@columns: range(4);
+.column-list {
+ list: @columns;
+}
+
+each(@columns, .(@val) {
+ .col-@{val} {
+ width: (100% / length(@columns));
+ }
+});
+
+each(range(10px, 30px, 10px), .(@val, @index) {
+ .row-@{index} {
+ width: @val;
+ }
+});
+
+@list: a b c d;
+.box {
+ each(@list, {
+ -less-log: extract(@list, @index);
+ })
+}
+
+// https://github.com/less/less.js/issues/3325
+
+@color-schemes: {
+ @primary: {
+ @color: blue;
+ }
+ @secondary: {
+ @color: red;
+ }
+}
+.test-rule {
+ each(primary secondary, .(@color-name) {
+ @scheme: @color-schemes[@@color-name]; // e.g. @color-name = primary
+ color: @scheme[@color];
+ });
+}
+
+@one: {
+ @two: {
+ foo: red;
+ bar: blue;
+ };
+};
+
+each(@one[@two], {
+ .@{key} {
+ content: @value;
+ }
+});
+
+// https://github.com/less/less.js/issues/3354
+.log(@msgs) {
+ each(@msgs; {
+ content: @value;
+ });
+}
+
+@messages: 'foo', 'bar';
+
+span {
+ .log(@messages);
+}
+
+div {
+ .log('foo');
+}
+
+// https://github.com/less/less.js/issues/3345
+.mixin-create-width-style() {
+ @list: e("90 100 110");
+
+ each(@list, {
+ .w-@{key} {
+ width: @value;
+ }
+ })
+}
+
+.a {
+ .mixin-create-width-style();
+}
+
+
+
+=====================================output=====================================
+@selectors: blue, green, red;
+@list: a b c d;
+
+each(@selectors, {
+ .sel-@{value} {
+ a: b;
+ }
+});
+
+.each {
+ each(@list, {
+ index+: @index;
+ item@{index}: @value;
+ });
+
+ // nested each
+ each(10px 15px, 20px 25px; {
+ // demonstrates nesting of each()
+ each(@value; #(@v, @k, @i) {
+ nest-@{i}-@{index}: @v @k;
+ });
+ });
+
+ // nested anonymous mixin
+ .nest-anon {
+ each(a b, .(@v;@i) {
+ each(c d, .(@vv;@ii) {
+ nest-@{i}-@{ii}: @v @vv;
+ });
+ });
+ }
+
+ // vector math
+ each(1 2 3 4, {
+ padding+_: (@value * 10px);
+ });
+}
+
+@set: {
+ one: blue;
+ // skip comments
+ two: green;
+ /** and these
+ */
+ three: red; //and this
+};
+.set {
+ each(@set, {
+ @{key}: @value;
+ });
+}
+.set-2() {
+ one: blue;
+ two: green;
+ three: red;
+}
+.set-2 {
+ each(.set-2(), .(@v, @k, @i) {
+ @{k}-@{i}: @v;
+ });
+}
+
+.pick(@a) when (@a = 4) {
+ val3: @a;
+}
+.single {
+ each(true, {
+ val: @value;
+ });
+ @exp: 1 + 1;
+ each(@exp, {
+ val2: @value;
+ });
+ each(1 2 3 4, {
+ .pick(@value);
+ });
+}
+
+@columns: range(4);
+.column-list {
+ list: @columns;
+}
+
+each(@columns, .(@val) {
+ .col-@{val} {
+ width: (100% / length(@columns));
+ }
+});
+
+each(range(10px, 30px, 10px), .(@val, @index) {
+ .row-@{index} {
+ width: @val;
+ }
+});
+
+@list: a b c d;
+.box {
+ each(@list, {
+ -less-log: extract(@list, @index);
+ });
+}
+
+// https://github.com/less/less.js/issues/3325
+
+@color-schemes: {
+ @primary: {
+ @color: blue;
+ };
+ @secondary: {
+ @color: red;
+ };
+};
+.test-rule {
+ each(primary secondary, .(@color-name) {
+ @scheme: @color-schemes[@@color-name]; // e.g. @color-name = primary
+ color: @scheme[@color];
+ });
+}
+
+@one: {
+ @two: {
+ foo: red;
+ bar: blue;
+ };
+};
+
+each(@one[@two], {
+ .@{key} {
+ content: @value;
+ }
+});
+
+// https://github.com/less/less.js/issues/3354
+.log(@msgs) {
+ each(@msgs; {
+ content: @value;
+ });
+}
+
+@messages: "foo", "bar";
+
+span {
+ .log(@messages);
+}
+
+div {
+ .log("foo");
+}
+
+// https://github.com/less/less.js/issues/3345
+.mixin-create-width-style() {
+ @list: e("90 100 110");
+
+ each(@list, {
+ .w-@{key} {
+ width: @value;
+ }
+ });
+}
+
+.a {
+ .mixin-create-width-style();
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/ie-filters/ie-filters.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@fat: 0;
+@cloudhead: "#000000";
+
+.nav {
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 20);
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@fat);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr=@cloudhead, GradientType=@fat);
+}
+.evalTest(@arg) {
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@arg);
+}
+.evalTest1 {
+ .evalTest(30);
+ .evalTest(5);
+}
+
+
+
+=====================================output=====================================
+@fat: 0;
+@cloudhead: "#000000";
+
+.nav {
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 20);
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@fat);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr=@cloudhead, GradientType=@fat);
+}
+.evalTest(@arg) {
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@arg);
+}
+.evalTest1 {
+ .evalTest(30);
+ .evalTest(5);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/impor/impor.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// https://github.com/less/less.js/issues/3660
+// const dir = parserInput.$re(/^@import?\\s+/);
+// correct regexp is /^@import\\s+/
+// so follow code will change nothing, parse result is same with raw less code
+@impor "impor-typo-dont-parse-as-@import.less";
+
+=====================================output=====================================
+// https://github.com/less/less.js/issues/3660
+// const dir = parserInput.$re(/^@import?\\s+/);
+// correct regexp is /^@import\\s+/
+// so follow code will change nothing, parse result is same with raw less code
+@impor "impor-typo-dont-parse-as-@import.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+/** comment at the top**/
+@plugin "../../plugin/plugin-simple";
+
+@import url(/absolute/something.css) screen and (color) and (max-width: 600px);
+
+@import (optional) "file-does-not-exist.does-not-exist";
+
+@var: 100px;
+@import url("//ha.com/file.css") (min-width:@var);
+
+#import-test {
+ .mixin();
+ width: 10px;
+ height: (@a + 10%);
+ value: pi-anon();
+}
+@import "import/import-test-e" screen and (max-width: 600px);
+
+@import url("import/import-test-a.less");
+
+@import (less, multiple) "import/import-test-d.css" screen and (max-width: 601px);
+
+@import (multiple) "import/import-test-e" screen and (max-width: 602px);
+
+@import (less, multiple) url("import/import-test-d.css") screen and (max-width: 603px);
+
+@media print {
+ @import (multiple) "import/import-test-e";
+}
+
+@charset "UTF-8"; // climb on top #2126
+
+
+=====================================output=====================================
+/** comment at the top**/
+@plugin "../../plugin/plugin-simple";
+
+@import url(/absolute/something.css) screen and (color) and (max-width: 600px);
+
+@import (optional) "file-does-not-exist.does-not-exist";
+
+@var: 100px;
+@import url("//ha.com/file.css") (min-width: @var);
+
+#import-test {
+ .mixin();
+ width: 10px;
+ height: (@a + 10%);
+ value: pi-anon();
+}
+@import "import/import-test-e" screen and (max-width: 600px);
+
+@import url("import/import-test-a.less");
+
+@import (less, multiple) "import/import-test-d.css" screen and
+ (max-width: 601px);
+
+@import (multiple) "import/import-test-e" screen and (max-width: 602px);
+
+@import (less, multiple) url("import/import-test-d.css") screen and
+ (max-width: 603px);
+
+@media print {
+ @import (multiple) "import/import-test-e";
+}
+
+@charset "UTF-8"; // climb on top #2126
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/css-import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import url("test.css");
+
+=====================================output=====================================
+@import url("test.css");
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/deeper/deeper-2/url-import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import url("url-import-2.less");
+=====================================output=====================================
+@import url("url-import-2.less");
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/deeper/deeper-2/url-import-2.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.deep-import-url {
+ color: red;
+}
+=====================================output=====================================
+.deep-import-url {
+ color: red;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/deeper/import-once-test-a.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "../import-once-test-c";
+=====================================output=====================================
+@import "../import-once-test-c";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/deeper/url-import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import url("deeper-2/url-import.less");
+=====================================output=====================================
+@import url("deeper-2/url-import.less");
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-and-relative-paths-test.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "css/background.css";
+@import "import-test-d.css";
+
+@import "imports/logo";
+@import "imports/font";
+
+.unquoted-relative-path-bg() {
+ background-image: url(../../data/image.jpg);
+}
+.quoted-relative-path-border-image() {
+ border-image: url('../../data/image.jpg');
+}
+
+#imported-relative-path {
+ .unquoted-relative-path-bg();
+ .quoted-relative-path-border-image();
+}
+=====================================output=====================================
+@import "css/background.css";
+@import "import-test-d.css";
+
+@import "imports/logo";
+@import "imports/font";
+
+.unquoted-relative-path-bg() {
+ background-image: url(../../data/image.jpg);
+}
+.quoted-relative-path-border-image() {
+ border-image: url("../../data/image.jpg");
+}
+
+#imported-relative-path {
+ .unquoted-relative-path-bg();
+ .quoted-relative-path-border-image();
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-charset-test.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@charset "ISO-8859-1";
+=====================================output=====================================
+@charset "ISO-8859-1";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-inline-invalid-css.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import (inline) "invalid-css.less";
+=====================================output=====================================
+@import (inline) "invalid-css.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-interpolation.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import (inline) "imports/logo.less";
+@import "import-@{in}@{terpolation}2.less";
+=====================================output=====================================
+@import (inline) "imports/logo.less";
+@import "import-@{in}@{terpolation}2.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-interpolation2.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.a {
+ var: test;
+}
+
+@in: "redefined-does-nothing";
+=====================================output=====================================
+.a {
+ var: test;
+}
+
+@in: "redefined-does-nothing";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-once-test-c.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+
+@c: red;
+
+#import {
+ color: @c;
+}
+
+=====================================output=====================================
+@c: red;
+
+#import {
+ color: @c;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-reference.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.z {
+ color: red;
+ .c {
+ color: green;
+ }
+}
+.only-with-visible,
+.z {
+ color: green;
+ &:hover {
+ color: green;
+ }
+ & {
+ color: green;
+ }
+ & + & {
+ color: green;
+ .sub {
+ color: green;
+ }
+ }
+}
+
+& {
+ .hidden {
+ hidden: true;
+ }
+}
+
+@media tv {
+ .hidden {
+ hidden: true;
+ }
+}
+
+/* comment is not output */
+
+.zz {
+ .y {
+ pulled-in: yes /* inline comment survives */;
+ }
+ /* comment pulled in */
+}
+@max-size: 450px;
+.mixin-with-mediaq(@num) {
+ color: green;
+ test: @num;
+ @media (max-size: @max-size) {
+ color: red;
+ }
+}
+//https://github.com/less/less.js/issues/2359
+@supports (something: else) {
+ .class {
+ something: else;
+ }
+ .nestedToo {
+ .class {
+ something: else;
+ }
+ }
+ .invisible {
+ something: else;
+ }
+}
+//https://github.com/less/less.js/issues/1979
+.mixin-with-nested-selectors() {
+ .test-rule {
+ color: red;
+ &:first-child {
+ color: blue;
+ }
+ }
+}
+.mixin-with-directives(@keyframeName) {
+ @keyframes @keyframeName {
+ @rules1();
+ }
+ @supports (animation-name: test) {
+ @keyframes @keyframeName {
+ @rules2();
+ }
+ .selector {
+ color: red;
+ }
+ }
+ @rules1: {property: value;};
+ @rules2: {property: value;};
+}
+
+@import (inline, multiple) "invalid-css.less";
+@import "import-inline-invalid-css.less";
+.print-referenced-import-inline() {
+ div {
+ @import (inline, multiple) "invalid-css.less";
+ }
+ @import (inline, multiple) "invalid-css.less";
+}
+=====================================output=====================================
+.z {
+ color: red;
+ .c {
+ color: green;
+ }
+}
+.only-with-visible,
+.z {
+ color: green;
+ &:hover {
+ color: green;
+ }
+ & {
+ color: green;
+ }
+ & + & {
+ color: green;
+ .sub {
+ color: green;
+ }
+ }
+}
+
+& {
+ .hidden {
+ hidden: true;
+ }
+}
+
+@media tv {
+ .hidden {
+ hidden: true;
+ }
+}
+
+/* comment is not output */
+
+.zz {
+ .y {
+ pulled-in: yes /* inline comment survives */;
+ }
+ /* comment pulled in */
+}
+@max-size: 450px;
+.mixin-with-mediaq(@num) {
+ color: green;
+ test: @num;
+ @media (max-size: @max-size) {
+ color: red;
+ }
+}
+//https://github.com/less/less.js/issues/2359
+@supports (something: else) {
+ .class {
+ something: else;
+ }
+ .nestedToo {
+ .class {
+ something: else;
+ }
+ }
+ .invisible {
+ something: else;
+ }
+}
+//https://github.com/less/less.js/issues/1979
+.mixin-with-nested-selectors() {
+ .test-rule {
+ color: red;
+ &:first-child {
+ color: blue;
+ }
+ }
+}
+.mixin-with-directives(@keyframeName) {
+ @keyframes @keyframeName {
+ @rules1();
+ }
+ @supports (animation-name: test) {
+ @keyframes @keyframeName {
+ @rules2();
+ }
+ .selector {
+ color: red;
+ }
+ }
+ @rules1: {
+ property: value;
+ };
+ @rules2: {
+ property: value;
+ };
+}
+
+@import (inline, multiple) "invalid-css.less";
+@import "import-inline-invalid-css.less";
+.print-referenced-import-inline() {
+ div {
+ @import (inline, multiple) "invalid-css.less";
+ }
+ @import (inline, multiple) "invalid-css.less";
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-test-a.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "import-test-b.less";
+@import url(import-test-f.less);
+@import url("deeper/url-import.less");
+@a: 20%;
+@import "urls.less";
+=====================================output=====================================
+@import "import-test-b.less";
+@import url(import-test-f.less);
+@import url("deeper/url-import.less");
+@a: 20%;
+@import "urls.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-test-b.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "import-test-c";
+
+@b: 100%;
+
+.mixin {
+ height: 10px;
+ color: @c;
+}
+
+=====================================output=====================================
+@import "import-test-c";
+
+@b: 100%;
+
+.mixin {
+ height: 10px;
+ color: @c;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-test-c.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+
+@c: red;
+
+#import {
+ color: @c;
+}
+
+=====================================output=====================================
+@c: red;
+
+#import {
+ color: @c;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-test-e.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+
+body { width: 100% }
+
+=====================================output=====================================
+body {
+ width: 100%;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/import-test-f.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "import-test-e";
+
+.test-rule-f {
+ height: 10px;
+}
+
+=====================================output=====================================
+@import "import-test-e";
+
+.test-rule-f {
+ height: 10px;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/imports/font.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@font-face {
+ font-family: xecret;
+ src: url('../assets/xecret.ttf');
+}
+
+#secret {
+ font-family: xecret, sans-serif;
+}
+
+=====================================output=====================================
+@font-face {
+ font-family: xecret;
+ src: url("../assets/xecret.ttf");
+}
+
+#secret {
+ font-family: xecret, sans-serif;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/imports/logo.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#logo {
+ width: 100px;
+ height: 100px;
+ background: url('./assets/logo.png');
+ background: url("#inline-svg");
+}
+
+=====================================output=====================================
+#logo {
+ width: 100px;
+ height: 100px;
+ background: url("./assets/logo.png");
+ background: url("#inline-svg");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/interpolation-vars.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@in: "in";
+@terpolation: "terpolation";
+
+// should be ignored because its already imported
+// and it uses a variable from the parent scope
+@import "import-@{my_theme}-e.less";
+
+=====================================output=====================================
+@in: "in";
+@terpolation: "terpolation";
+
+// should be ignored because its already imported
+// and it uses a variable from the parent scope
+@import "import-@{my_theme}-e.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/json/index.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "../import-test-a";
+=====================================output=====================================
+@import "../import-test-a";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/layer-import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.sub-rule {
+ ul {
+ color: white;
+ }
+}
+
+=====================================output=====================================
+.sub-rule {
+ ul {
+ color: white;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import/urls.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// empty file showing that it loads from the relative path first
+
+=====================================output=====================================
+// empty file showing that it loads from the relative path first
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-inline.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import url("import/import-test-c.less");// import inline should not float above this #1954
+@import (inline) url("import/import-test-d.css") (min-width:600px);
+@import (inline, css) url("import/invalid-css.less");
+=====================================output=====================================
+@import url("import/import-test-c.less"); // import inline should not float above this #1954
+@import (inline) url("import/import-test-d.css") (min-width: 600px);
+@import (inline, css) url("import/invalid-css.less");
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-interpolation.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@my_theme: "test";
+
+@import "import/import-@{my_theme}-e.less";
+
+@import "import/import-@{in}@{terpolation}.less";
+
+@import "import/interpolation-vars.less";
+
+
+=====================================output=====================================
+@my_theme: "test";
+
+@import "import/import-@{my_theme}-e.less";
+
+@import "import/import-@{in}@{terpolation}.less";
+
+@import "import/interpolation-vars.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-module.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "@less/test-import-module/one/two/three/3.less";
+@import "@less/test-import-module/one/two/2";
+@import "@less/test-import-module/one/1.less";
+
+=====================================output=====================================
+@import "@less/test-import-module/one/two/three/3.less";
+@import "@less/test-import-module/one/two/2";
+@import "@less/test-import-module/one/1.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-once.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "import/import-once-test-c";
+@import "import/import-once-test-c";
+@import "import/import-once-test-c.less";
+@import "import/deeper/import-once-test-a";
+@import (multiple) "import/import-test-f.less";
+@import (multiple) "import/import-test-f.less";
+=====================================output=====================================
+@import "import/import-once-test-c";
+@import "import/import-once-test-c";
+@import "import/import-once-test-c.less";
+@import "import/deeper/import-once-test-a";
+@import (multiple) "import/import-test-f.less";
+@import (multiple) "import/import-test-f.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import (reference) url("import-once.less");
+@import (reference) url("../css-3/css-3.less");
+@import (reference) url("../media/media.less");
+@import (reference) url("import/import-reference.less");
+@import (reference) url("import/css-import.less");
+
+.b {
+ .z();
+}
+
+.zz();
+
+.visible:extend(.z all) {
+ extend: test;
+}
+
+.test-rule-mediaq-import {
+ .mixin-with-mediaq(340px);
+}
+
+.class:extend(.class all) {
+}
+.mixin-with-nested-selectors();
+.mixin-with-directives(some-name);
+
+.print-referenced-import-inline();
+
+=====================================output=====================================
+@import (reference) url("import-once.less");
+@import (reference) url("../css-3/css-3.less");
+@import (reference) url("../media/media.less");
+@import (reference) url("import/import-reference.less");
+@import (reference) url("import/css-import.less");
+
+.b {
+ .z();
+}
+
+.zz();
+
+.visible:extend(.z all) {
+ extend: test;
+}
+
+.test-rule-mediaq-import {
+ .mixin-with-mediaq(340px);
+}
+
+.class:extend(.class all) {
+}
+.mixin-with-nested-selectors();
+.mixin-with-directives(some-name);
+
+.print-referenced-import-inline();
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Tests following past issues:
+// * #1851 - Extend within (reference) imported files
+// * #1896 - Namespace imported less code does not get properly referenced, when there's a (reference) keyword.
+// * #1878 - extend inside referenced file should not extend outside selectors
+// * #2716 - A file imported by reference and then normally - multiple imports should be independent
+// * #1968 - When using an @import (reference), mixins that contain an & selector get added to the compiled output improperly
+// * #2162 - Cannot put import by reference inside of a mixin (also doubles #1896)
+// * #2991 - Empty @media queries generated through line comments when compiling less file with (reference)
+
+// #1878: extend inside referenced file should not extend outside selectors
+@import (reference) "import-reference-issues/global-scope-import.less";
+.theOnlySelector {
+ shall-have: one selector;
+}
+
+// #2716: A file imported by reference and then normally - multiple imports should be independent
+// #1878: - double nested version
+#do-not-show-import {
+ @import (reference, multiple) "import-reference-issues/multiple-import.less";
+}
+
+show-all-content {
+ @import (multiple) "import-reference-issues/multiple-import.less";
+}
+// #1896: Namespace imported less code does not get properly referenced, when there's a (reference) keyword.
+#Namespace {
+ @import (less, reference) "import-reference-issues/simple-mixin.css";
+}
+#used-namespaced-mixin {
+ #Namespace > .mixin();
+ shall-see: another property above;
+}
+
+// #1851: Extend within (reference) imported files
+// test-b is in global-scope-import.less file
+.test-rule-c {
+ &:extend(.test-rule-b all);
+}
+
+// #1968: When using an @import (reference), mixins that contain an & selector get added to the compiled output improperly
+@import "import-reference-issues/mixin-1968.less";
+@import (reference) "import-reference-issues/appender-reference-1968.less";
+
+// #2162 - Cannot put import by reference inside of a mixin (also doubles #1896)
+.mixin-with-import-by-reference-inside() {
+ the-only-property: nothing-below-this;
+ @import (reference) "import-reference-issues/simple-ruleset-2162.less";
+}
+call-mixin-with-import-by-reference-inside {
+ .mixin-with-import-by-reference-inside();
+}
+
+@import (reference) "import-reference-issues/comments-2991.less";
+=====================================output=====================================
+// Tests following past issues:
+// * #1851 - Extend within (reference) imported files
+// * #1896 - Namespace imported less code does not get properly referenced, when there's a (reference) keyword.
+// * #1878 - extend inside referenced file should not extend outside selectors
+// * #2716 - A file imported by reference and then normally - multiple imports should be independent
+// * #1968 - When using an @import (reference), mixins that contain an & selector get added to the compiled output improperly
+// * #2162 - Cannot put import by reference inside of a mixin (also doubles #1896)
+// * #2991 - Empty @media queries generated through line comments when compiling less file with (reference)
+
+// #1878: extend inside referenced file should not extend outside selectors
+@import (reference) "import-reference-issues/global-scope-import.less";
+.theOnlySelector {
+ shall-have: one selector;
+}
+
+// #2716: A file imported by reference and then normally - multiple imports should be independent
+// #1878: - double nested version
+#do-not-show-import {
+ @import (reference, multiple) "import-reference-issues/multiple-import.less";
+}
+
+show-all-content {
+ @import (multiple) "import-reference-issues/multiple-import.less";
+}
+// #1896: Namespace imported less code does not get properly referenced, when there's a (reference) keyword.
+#Namespace {
+ @import (less, reference) "import-reference-issues/simple-mixin.css";
+}
+#used-namespaced-mixin {
+ #Namespace > .mixin();
+ shall-see: another property above;
+}
+
+// #1851: Extend within (reference) imported files
+// test-b is in global-scope-import.less file
+.test-rule-c {
+ &:extend(.test-rule-b all);
+}
+
+// #1968: When using an @import (reference), mixins that contain an & selector get added to the compiled output improperly
+@import "import-reference-issues/mixin-1968.less";
+@import (reference) "import-reference-issues/appender-reference-1968.less";
+
+// #2162 - Cannot put import by reference inside of a mixin (also doubles #1896)
+.mixin-with-import-by-reference-inside() {
+ the-only-property: nothing-below-this;
+ @import (reference) "import-reference-issues/simple-ruleset-2162.less";
+}
+call-mixin-with-import-by-reference-inside {
+ .mixin-with-import-by-reference-inside();
+}
+
+@import (reference) "import-reference-issues/comments-2991.less";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues/appender-reference-1968.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.container-no-parent-selector {
+ .mixin-no-parent-selector();
+}
+.container-with-parent-selector {
+ .mixin-with-parent-selector()
+}
+
+=====================================output=====================================
+.container-no-parent-selector {
+ .mixin-no-parent-selector();
+}
+.container-with-parent-selector {
+ .mixin-with-parent-selector();
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues/comments-2991.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.referenced {
+ // This file should not output anything if referenced.
+ @media (hover) {
+ // This file should not output anything if referenced.
+ }
+ // This file should not output anything if referenced.
+ @media (hover) {
+ // This file should not output anything if referenced.
+ }
+ // This file should not output anything if referenced.
+ @media (hover) {
+ /* This file should not output anything if referenced. */
+ }
+ // This file should not output anything if referenced.
+ @media (hover) {
+ color: #000000;
+ }
+}
+// This file should not output anything if referenced.
+@media (hover) {
+ // This file should not output anything if referenced.
+}
+@media (hover) {
+ /* This file should not output anything if referenced. */
+}
+
+=====================================output=====================================
+.referenced {
+ // This file should not output anything if referenced.
+ @media (hover) {
+ // This file should not output anything if referenced.
+ }
+ // This file should not output anything if referenced.
+ @media (hover) {
+ // This file should not output anything if referenced.
+ }
+ // This file should not output anything if referenced.
+ @media (hover) {
+ /* This file should not output anything if referenced. */
+ }
+ // This file should not output anything if referenced.
+ @media (hover) {
+ color: #000000;
+ }
+}
+// This file should not output anything if referenced.
+@media (hover) {
+ // This file should not output anything if referenced.
+}
+@media (hover) {
+ /* This file should not output anything if referenced. */
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues/global-scope-import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.theOnlySelector {
+ avoid: warning;
+}
+.unusedAndReference:extend(.theOnlySelector) {
+ unused-and: reference;
+}
+
+@import (reference) "global-scope-nested.less";
+
+.test-rule-b {
+ background-color: green;
+ &:extend(.test-rule-a all);
+}
+
+=====================================output=====================================
+.theOnlySelector {
+ avoid: warning;
+}
+.unusedAndReference:extend(.theOnlySelector) {
+ unused-and: reference;
+}
+
+@import (reference) "global-scope-nested.less";
+
+.test-rule-b {
+ background-color: green;
+ &:extend(.test-rule-a all);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues/global-scope-nested.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.test-rule-a {
+ color: red;
+}
+
+=====================================output=====================================
+.test-rule-a {
+ color: red;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues/mixin-1968.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mixin-no-parent-selector() {
+ background-color: red;
+}
+.mixin-with-parent-selector() {
+ &:first-child{ // USING AN & SELECTOR HERE
+ background-color: blue;
+ }
+}
+
+=====================================output=====================================
+.mixin-no-parent-selector() {
+ background-color: red;
+}
+.mixin-with-parent-selector() {
+ &:first-child {
+ // USING AN & SELECTOR HERE
+ background-color: blue;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues/multiple-import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+/*
+ tralala
+*/
+.fix {
+ fix: fix;
+}
+.something {
+ @import (reference) "multiple-import-nested.less";
+ inside: something;
+}
+
+=====================================output=====================================
+/*
+ tralala
+*/
+.fix {
+ fix: fix;
+}
+.something {
+ @import (reference) "multiple-import-nested.less";
+ inside: something;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues/multiple-import-nested.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+/* double nested file */
+should {
+ be: invisible;
+}
+/* do not extend outside of this */
+.something {
+ invisible: suppress warning;
+}
+.invisible {
+ &:extend(.something all);
+}
+
+
+=====================================output=====================================
+/* double nested file */
+should {
+ be: invisible;
+}
+/* do not extend outside of this */
+.something {
+ invisible: suppress warning;
+}
+.invisible {
+ &:extend(.something all);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-reference-issues/simple-ruleset-2162.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+ruleset {
+ shall-be-invisible: less;
+}
+
+=====================================output=====================================
+ruleset {
+ shall-be-invisible: less;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/import/import-remote.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// https://github.com/less/less.js/issues/3541
+@import (reference) url(https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/selectors/selectors.less);
+@import (reference) url("https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/media/media.less");
+@import (reference) url("https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/empty/empty.less?arg");
+
+.test {
+ color: @var;
+}
+=====================================output=====================================
+// https://github.com/less/less.js/issues/3541
+@import (reference)
+ url(https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/selectors/selectors.less);
+@import (reference)
+ url("https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/media/media.less");
+@import (reference)
+ url("https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/empty/empty.less?arg");
+
+.test {
+ color: @var;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/javascript/javascript.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// JavaScript evaluation tests
+.eval {
+ js: \`42\`;
+ js: \`1 + 1\`;
+ js: \`"hello world"\`;
+ js: \`[1, 2, 3]\`;
+ title: \`typeof process.title\`;
+ ternary: \`(1 + 1 == 2 ? true : false)\`;
+ multiline: \`(function(){var x = 1 + 1;
+ return x})()\`;
+}
+.scope {
+ --empty: \`+function(){}\`;
+ @foo: 42;
+ var: \`parseInt(this.foo.toJS())\`;
+ escaped: ~\`2 + 5 + 'px'\`;
+}
+.vars {
+ @var: \`4 + 4\`;
+ width: @var;
+}
+.escape-interpol {
+ @world: "world";
+ width: ~\`"hello" + " " + @{world}\`;
+}
+.arrays {
+ @ary: 1, 2, 3;
+ @ary2: 1 2 3;
+ ary: \`@{ary}.join(', ')\`;
+ ary1: \`@{ary2}.join(', ')\`;
+}
+.transitions(...) {
+ @arg: ~\`"@{arguments}".replace(/[\\[\\]]*/g, '')\`;
+ one: @arg; // rounded to integers
+ two: ~\`"@{arguments}"\`; // rounded to integers
+ three: @arguments; // OK
+}
+.test-rule-tran {
+ .transitions(opacity 0.3s ease-in 0.3s, max-height 0.6s linear, margin-bottom 0.4s linear;);
+}
+
+=====================================output=====================================
+// JavaScript evaluation tests
+.eval {
+ js: \`42\`;
+ js: \`1 + 1\`;
+ js: \` "hello world" \`;
+ js: \`[1, 2, 3]\`;
+ title: \`typeof process.title\`;
+ ternary: \`(1 + 1 == 2 ? true: false) \`;
+ multiline: \`(function(){var x = 1 + 1; return x}) () \`;
+}
+.scope {
+ --empty: \` + function(){}\`;
+ @foo: 42;
+ var: \`parseInt(this.foo.toJS()) \`;
+ escaped: ~\`2 + 5 + 'px'\`;
+}
+.vars {
+ @var: \`4 + 4\`;
+ width: @var;
+}
+.escape-interpol {
+ @world: "world";
+ width: ~\`"hello" + " " + @{world}\`;
+}
+.arrays {
+ @ary: 1, 2, 3;
+ @ary2: 1 2 3;
+ ary: \` @{ary}.join(", ") \`;
+ ary1: \` @{ary2}.join(", ") \`;
+}
+.transitions(...) {
+ @arg: ~\`"@{arguments}".replace(/[\\[\\]]*/g, '')\`;
+ one: @arg; // rounded to integers
+ two: ~\`"@{arguments}"\`; // rounded to integers
+ three: @arguments; // OK
+}
+.test-rule-tran {
+ .transitions(opacity 0.3s ease-in 0.3s, max-height 0.6s linear, margin-bottom 0.4s linear;);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/layer/assets/import/layer-import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.layer-import {
+ color: indigo;
+}
+
+
+=====================================output=====================================
+.layer-import {
+ color: indigo;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/layer/import/layer-import.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.sub-rule {
+ ul {
+ color: white;
+ }
+}
+
+=====================================output=====================================
+.sub-rule {
+ ul {
+ color: white;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/layer/layer.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.main {
+ @layer {
+ &::before {
+ color: #f00;
+ }
+ }
+}
+
+@layer legacy {
+ @import "./import/layer-import.less";
+}
+
+@import url("/import/layer-import-2.css") layer(foo);
+@import url("/import/layer-import-3.css") layer(responsive) supports(display: flex) screen and (max-width: 768px);
+@import url("/import/layer-import-4.css") layer(print) print;
+@import url("/import/layer-import-4.css") layer(print) print, (max-width: 600px);
+@import url("/import/layer-import-5.css") layer(features) supports(display: grid);
+
+@layer-name: primevue;
+
+@layer @layer-name {
+ .test {
+ foo: bar;
+ }
+}
+
+@layer reset, base, components, utilities;
+
+@layer reset {
+
+ *,
+ *::before,
+ *::after {
+ box-sizing: border-box;
+ }
+}
+
+@layer base {
+ body {
+ margin: 0;
+ font-family: system-ui, sans-serif;
+
+ header {
+ background-color: #f0f0f0;
+ padding: 1rem;
+ }
+ }
+}
+
+@layer components {
+ .button {
+ display: inline-block;
+ padding: 0.5rem 1rem;
+ background-color: blue;
+ color: white;
+
+ &:hover {
+ background-color: darkblue;
+ }
+ }
+}
+
+@layer utilities {
+ .text-center {
+ text-align: center;
+ }
+
+ .responsive {
+ width: 100%;
+
+ @media (min-width: 768px) {
+ width: 50%;
+ }
+ }
+}
+
+.parent {
+ color: black;
+
+ .child {
+ color: red;
+ }
+
+ &:hover {
+ background: lightgray;
+ }
+}
+
+@layer foo.baz {
+ .bar {
+ font-weight: bold;
+ }
+}
+
+@layer framework {
+ @layer layout {
+ .container {
+ display: grid;
+ gap: 2rem;
+ }
+ }
+}
+
+@layer framework.layout {
+ main {
+ padding: 2rem;
+ }
+ p {
+ margin-block: 1rem;
+ color: #555;
+ }
+}
+
+
+@layer theme;
+@layer layout, utilities;
+
+body {
+ color: black;
+}
+
+@layer components {
+ .btn {
+ color: red;
+ &:hover {
+ color: blue;
+ }
+ }
+}
+
+@layer {
+ p {
+ margin-block: 1rem;
+ }
+}
+
+@layer framework.buttons.primary {
+ .btn-primary {
+ background: dodgerblue;
+ color: white;
+ }
+}
+
+.feature {
+ color: gray;
+
+ @layer component {
+ h2 {
+ font-size: 1.5rem;
+ }
+ }
+}
+
+@primary-color: rebeccapurple;
+
+.button-styles() {
+ padding: 0.5rem 1rem;
+ border-radius: 4px;
+}
+
+@layer ui {
+ .btn {
+ .button-styles();
+ background: @primary-color;
+ color: white;
+ }
+}
+
+=====================================output=====================================
+.main {
+ @layer {
+ &::before {
+ color: #f00;
+ }
+ }
+}
+
+@layer legacy {
+ @import "./import/layer-import.less";
+}
+
+@import url("/import/layer-import-2.css") layer(foo);
+@import url("/import/layer-import-3.css") layer(responsive)
+ supports(display: flex) screen and (max-width: 768px);
+@import url("/import/layer-import-4.css") layer(print) print;
+@import url("/import/layer-import-4.css") layer(print) print, (max-width: 600px);
+@import url("/import/layer-import-5.css") layer(features)
+ supports(display: grid);
+
+@layer-name: primevue;
+
+@layer @layer-name {
+ .test {
+ foo: bar;
+ }
+}
+
+@layer reset, base, components, utilities;
+
+@layer reset {
+ *,
+ *::before,
+ *::after {
+ box-sizing: border-box;
+ }
+}
+
+@layer base {
+ body {
+ margin: 0;
+ font-family: system-ui, sans-serif;
+
+ header {
+ background-color: #f0f0f0;
+ padding: 1rem;
+ }
+ }
+}
+
+@layer components {
+ .button {
+ display: inline-block;
+ padding: 0.5rem 1rem;
+ background-color: blue;
+ color: white;
+
+ &:hover {
+ background-color: darkblue;
+ }
+ }
+}
+
+@layer utilities {
+ .text-center {
+ text-align: center;
+ }
+
+ .responsive {
+ width: 100%;
+
+ @media (min-width: 768px) {
+ width: 50%;
+ }
+ }
+}
+
+.parent {
+ color: black;
+
+ .child {
+ color: red;
+ }
+
+ &:hover {
+ background: lightgray;
+ }
+}
+
+@layer foo.baz {
+ .bar {
+ font-weight: bold;
+ }
+}
+
+@layer framework {
+ @layer layout {
+ .container {
+ display: grid;
+ gap: 2rem;
+ }
+ }
+}
+
+@layer framework.layout {
+ main {
+ padding: 2rem;
+ }
+ p {
+ margin-block: 1rem;
+ color: #555;
+ }
+}
+
+@layer theme;
+@layer layout, utilities;
+
+body {
+ color: black;
+}
+
+@layer components {
+ .btn {
+ color: red;
+ &:hover {
+ color: blue;
+ }
+ }
+}
+
+@layer {
+ p {
+ margin-block: 1rem;
+ }
+}
+
+@layer framework.buttons.primary {
+ .btn-primary {
+ background: dodgerblue;
+ color: white;
+ }
+}
+
+.feature {
+ color: gray;
+
+ @layer component {
+ h2 {
+ font-size: 1.5rem;
+ }
+ }
+}
+
+@primary-color: rebeccapurple;
+
+.button-styles() {
+ padding: 0.5rem 1rem;
+ border-radius: 4px;
+}
+
+@layer ui {
+ .btn {
+ .button-styles();
+ background: @primary-color;
+ color: white;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/lazy-eval/lazy-eval.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Lazy evaluation tests
+@var: @a;
+@a: 100%;
+
+.lazy-eval {
+ width: @var;
+}
+
+=====================================output=====================================
+// Lazy evaluation tests
+@var: @a;
+@a: 100%;
+
+.lazy-eval {
+ width: @var;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/media/media.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// For now, variables can't be declared inside @media blocks.
+
+@var: 42;
+
+@media print {
+ .class {
+ color: blue;
+ .sub {
+ width: @var;
+ }
+ }
+ .top, header > h1 {
+ color: (#222 * 2);
+ }
+}
+
+@media screen {
+ @base: 8;
+ .body { max-width: (@base * 60); }
+}
+
+@ratio_large: 16;
+@ratio_small: 9;
+
+@media all and (device-aspect-ratio: ~'@{ratio_large} / @{ratio_small}') {
+ .body { max-width: 800px; }
+}
+
+@media all and (orientation:portrait) {
+ aside { float: none; }
+}
+
+@media handheld and (min-width: @var), screen and (min-width: 20em) {
+ .body {
+ max-width: 480px;
+ }
+}
+
+.body {
+ @media print {
+ padding: 20px;
+
+ header {
+ background-color: red;
+ }
+
+ @media (orientation:landscape) {
+ margin-left: 20px;
+ }
+ }
+}
+
+@media screen {
+ .sidebar {
+ width: 300px;
+ @media (orientation: landscape) {
+ width: 500px;
+ }
+ }
+}
+
+@media a {
+ .first {
+ @media (b) {
+ .second {
+ .third {
+ width: 300px;
+ @media (c) {
+ width: 500px;
+ }
+ }
+ .fourth {
+ width: 3;
+ }
+ }
+ }
+ }
+}
+
+.body {
+ @media a, (b) and (c) {
+ width: 95%;
+
+ @media (x), (y) {
+ width: 100%;
+ }
+ }
+}
+
+.mediaMixin(@fallback: 200px) {
+ background: black;
+
+ @media handheld {
+ background: white;
+
+ @media (max-width: @fallback) {
+ background: red;
+ }
+ }
+}
+
+.a {
+ .mediaMixin(100px);
+}
+
+.b {
+ .mediaMixin();
+}
+@smartphone: ~"only screen and (max-width: 200px)";
+@media @smartphone {
+ .body {
+ width: 480px;
+ }
+}
+
+@media print {
+ @page :left {
+ margin: 0.5cm;
+ }
+ @page :right {
+ margin: 0.5cm;
+ }
+ @page Test:first {
+ margin: 1cm;
+ }
+ @page :first {
+ size: 8.5in 11in;
+ @top-left {
+ margin: 1cm;
+ }
+ @top-left-corner {
+ margin: 1cm;
+ }
+ @top-center {
+ margin: 1cm;
+ }
+ @top-right {
+ margin: 1cm;
+ }
+ @top-right-corner {
+ margin: 1cm;
+ }
+ @bottom-left {
+ margin: 1cm;
+ }
+ @bottom-left-corner {
+ margin: 1cm;
+ }
+ @bottom-center {
+ margin: 1cm;
+ }
+ @bottom-right {
+ margin: 1cm;
+ }
+ @bottom-right-corner {
+ margin: 1cm;
+ }
+ @left-top {
+ margin: 1cm;
+ }
+ @left-middle {
+ margin: 1cm;
+ }
+ @left-bottom {
+ margin: 1cm;
+ }
+ @right-top {
+ margin: 1cm;
+ }
+ @right-middle {
+ content: "Page " counter(page);
+ }
+ @right-bottom {
+ margin: 1cm;
+ }
+ }
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: ~"2/1"), (min-resolution: 2dppx), (min-resolution: 128dpcm) {
+ .b {
+ background: red;
+ }
+}
+
+.bg() {
+ background: red;
+
+ @media (max-width: 500px) {
+ background: green;
+ }
+}
+
+.body {
+ .bg();
+}
+
+@bpMedium: 1000px;
+@media (max-width: @bpMedium) {
+ .body {
+ .bg();
+ background: blue;
+ }
+}
+
+@media (max-width: 1200px) {
+ /* a comment */
+
+ @media (max-width: 900px) {
+ .body { font-size: 11px; }
+ }
+}
+
+.nav-justified {
+ @media (min-width: 480px) {
+ > li {
+ display: table-cell;
+ }
+ }
+}
+
+.menu
+{
+ @media (min-width: 768px) {
+ .nav-justified();
+ }
+}
+@all: ~"all";
+@tv: ~"(tv)";
+@media @all and @tv {
+ .all-and-tv-variables {
+ var: all-and-tv;
+ }
+}
+
+@some-var: 60px;
+@media screen and (min-width: (@some-var + 1)) {
+ .selector {
+ foo: bar;
+ }
+}
+
+@media screen and (color), projection and (color) {
+ .selector {
+ color: #eee;
+ }
+}
+
+@media not (width <= -100px) {
+ body {
+ background: green;
+ }
+}
+
+@media (height > -100px) {
+ body {
+ background: green;
+ }
+}
+
+@media not (resolution: -300dpi) {
+ body {
+ background: green;
+ }
+}
+
+@media (min-orientation:portrait) {
+ body {
+ background: green;
+ }
+}
+
+@media print and (min-resolution: 118dpcm) {
+ body {
+ background: green;
+ }
+}
+
+@media (200px <= width <= 500px) {
+ .test-range-syntax {
+ padding: 0;
+ }
+}
+
+.selector {
+ color: #eee;
+
+ @media (200px <= width <= 500px) {
+ .test-range-syntax {
+ padding: 0;
+ }
+ }
+}
+
+@media print, (max-width: 992px) {
+ div {
+ color: red;
+ }
+}
+
+.form-process-table {
+ @media screen and(max-width: 1280px) {
+ color: red;
+ }
+}
+
+@media ((color) and (hover)), all {
+ body {
+ background: green;
+ }
+}
+
+=====================================output=====================================
+// For now, variables can't be declared inside @media blocks.
+
+@var: 42;
+
+@media print {
+ .class {
+ color: blue;
+ .sub {
+ width: @var;
+ }
+ }
+ .top,
+ header > h1 {
+ color: (#222 * 2);
+ }
+}
+
+@media screen {
+ @base: 8;
+ .body {
+ max-width: (@base * 60);
+ }
+}
+
+@ratio_large: 16;
+@ratio_small: 9;
+
+@media all and (device-aspect-ratio: ~"@{ratio_large} / @{ratio_small}") {
+ .body {
+ max-width: 800px;
+ }
+}
+
+@media all and (orientation: portrait) {
+ aside {
+ float: none;
+ }
+}
+
+@media handheld and (min-width: @var), screen and (min-width: 20em) {
+ .body {
+ max-width: 480px;
+ }
+}
+
+.body {
+ @media print {
+ padding: 20px;
+
+ header {
+ background-color: red;
+ }
+
+ @media (orientation: landscape) {
+ margin-left: 20px;
+ }
+ }
+}
+
+@media screen {
+ .sidebar {
+ width: 300px;
+ @media (orientation: landscape) {
+ width: 500px;
+ }
+ }
+}
+
+@media a {
+ .first {
+ @media (b) {
+ .second {
+ .third {
+ width: 300px;
+ @media (c) {
+ width: 500px;
+ }
+ }
+ .fourth {
+ width: 3;
+ }
+ }
+ }
+ }
+}
+
+.body {
+ @media a, (b) and (c) {
+ width: 95%;
+
+ @media (x), (y) {
+ width: 100%;
+ }
+ }
+}
+
+.mediaMixin(@fallback: 200px) {
+ background: black;
+
+ @media handheld {
+ background: white;
+
+ @media (max-width: @fallback) {
+ background: red;
+ }
+ }
+}
+
+.a {
+ .mediaMixin(100px);
+}
+
+.b {
+ .mediaMixin();
+}
+@smartphone: ~"only screen and (max-width: 200px)";
+@media @smartphone {
+ .body {
+ width: 480px;
+ }
+}
+
+@media print {
+ @page :left {
+ margin: 0.5cm;
+ }
+ @page :right {
+ margin: 0.5cm;
+ }
+ @page Test:first {
+ margin: 1cm;
+ }
+ @page :first {
+ size: 8.5in 11in;
+ @top-left {
+ margin: 1cm;
+ }
+ @top-left-corner {
+ margin: 1cm;
+ }
+ @top-center {
+ margin: 1cm;
+ }
+ @top-right {
+ margin: 1cm;
+ }
+ @top-right-corner {
+ margin: 1cm;
+ }
+ @bottom-left {
+ margin: 1cm;
+ }
+ @bottom-left-corner {
+ margin: 1cm;
+ }
+ @bottom-center {
+ margin: 1cm;
+ }
+ @bottom-right {
+ margin: 1cm;
+ }
+ @bottom-right-corner {
+ margin: 1cm;
+ }
+ @left-top {
+ margin: 1cm;
+ }
+ @left-middle {
+ margin: 1cm;
+ }
+ @left-bottom {
+ margin: 1cm;
+ }
+ @right-top {
+ margin: 1cm;
+ }
+ @right-middle {
+ content: "Page " counter(page);
+ }
+ @right-bottom {
+ margin: 1cm;
+ }
+ }
+}
+
+@media (-webkit-min-device-pixel-ratio: 2),
+ (min--moz-device-pixel-ratio: 2),
+ (-o-min-device-pixel-ratio: ~"2/1"),
+ (min-resolution: 2dppx),
+ (min-resolution: 128dpcm) {
+ .b {
+ background: red;
+ }
+}
+
+.bg() {
+ background: red;
+
+ @media (max-width: 500px) {
+ background: green;
+ }
+}
+
+.body {
+ .bg();
+}
+
+@bpMedium: 1000px;
+@media (max-width: @bpMedium) {
+ .body {
+ .bg();
+ background: blue;
+ }
+}
+
+@media (max-width: 1200px) {
+ /* a comment */
+
+ @media (max-width: 900px) {
+ .body {
+ font-size: 11px;
+ }
+ }
+}
+
+.nav-justified {
+ @media (min-width: 480px) {
+ > li {
+ display: table-cell;
+ }
+ }
+}
+
+.menu {
+ @media (min-width: 768px) {
+ .nav-justified();
+ }
+}
+@all: ~"all";
+@tv: ~"(tv)";
+@media @all and @tv {
+ .all-and-tv-variables {
+ var: all-and-tv;
+ }
+}
+
+@some-var: 60px;
+@media screen and (min-width: (@some-var + 1)) {
+ .selector {
+ foo: bar;
+ }
+}
+
+@media screen and (color), projection and (color) {
+ .selector {
+ color: #eee;
+ }
+}
+
+@media not (width <= -100px) {
+ body {
+ background: green;
+ }
+}
+
+@media (height > -100px) {
+ body {
+ background: green;
+ }
+}
+
+@media not (resolution: -300dpi) {
+ body {
+ background: green;
+ }
+}
+
+@media (min-orientation: portrait) {
+ body {
+ background: green;
+ }
+}
+
+@media print and (min-resolution: 118dpcm) {
+ body {
+ background: green;
+ }
+}
+
+@media (200px <= width <= 500px) {
+ .test-range-syntax {
+ padding: 0;
+ }
+}
+
+.selector {
+ color: #eee;
+
+ @media (200px <= width <= 500px) {
+ .test-range-syntax {
+ padding: 0;
+ }
+ }
+}
+
+@media print, (max-width: 992px) {
+ div {
+ color: red;
+ }
+}
+
+.form-process-table {
+ @media screen and(max-width: 1280px) {
+ color: red;
+ }
+}
+
+@media ((color) and (hover)), all {
+ body {
+ background: green;
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/merge/merge.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Merge functionality tests
+.first-transform() {
+ transform+: rotate(90deg), skew(30deg);
+}
+.second-transform() {
+ transform+: scale(2,4);
+}
+.third-transform() {
+ transform: scaleX(45deg);
+}
+.fourth-transform() {
+ transform+: scaleX(45deg);
+}
+.fifth-transform() {
+ transform+: scale(2,4) !important;
+}
+.first-background() {
+ background+: url(data://img1.png);
+}
+.second-background() {
+ background+: url(data://img2.png);
+}
+
+.test-rule1 {
+ // Can merge values
+ .first-transform();
+ .second-transform();
+}
+.test-rule2 {
+ // Won't merge values without +: merge directive, for backwards compatibility with css
+ .first-transform();
+ .third-transform();
+}
+.test-rule3 {
+ // Won't merge values from two sources with different properties
+ .fourth-transform();
+ .first-background();
+}
+.test-rule4 {
+ .first-transform();
+ .fifth-transform();
+}
+.test-rule5 {
+ .first-transform();
+ .second-transform() !important;
+}
+.test-rule6 {
+ .second-transform();
+}
+.test-rule7 {
+ // inherit !important from merged subrules
+ .second-transform();
+ .second-transform() !important;
+ .second-transform();
+}
+
+.test-rule-interleaved {
+ transform+: t1;
+ background+: b1;
+ transform+: t2;
+ background+: b2, b3;
+ transform+: t3;
+}
+
+.test-rule-spaced {
+ transform+_: t1;
+ background+_: b1;
+ transform+_: t2;
+ background+_: b2, b3;
+ transform+_: t3;
+}
+
+.test-rule-interleaved-with-spaced {
+ transform+_: t1s;
+ transform+: t2;
+ background+: b1;
+ transform+_: t3s;
+ transform+: t4 t5s;
+ background+_: b2s, b3;
+ transform+_: t6s;
+ background+: b4;
+}
+
+=====================================output=====================================
+// Merge functionality tests
+.first-transform() {
+ transform+: rotate(90deg), skew(30deg);
+}
+.second-transform() {
+ transform+: scale(2, 4);
+}
+.third-transform() {
+ transform: scaleX(45deg);
+}
+.fourth-transform() {
+ transform+: scaleX(45deg);
+}
+.fifth-transform() {
+ transform+: scale(2, 4) !important;
+}
+.first-background() {
+ background+: url(data://img1.png);
+}
+.second-background() {
+ background+: url(data://img2.png);
+}
+
+.test-rule1 {
+ // Can merge values
+ .first-transform();
+ .second-transform();
+}
+.test-rule2 {
+ // Won't merge values without +: merge directive, for backwards compatibility with css
+ .first-transform();
+ .third-transform();
+}
+.test-rule3 {
+ // Won't merge values from two sources with different properties
+ .fourth-transform();
+ .first-background();
+}
+.test-rule4 {
+ .first-transform();
+ .fifth-transform();
+}
+.test-rule5 {
+ .first-transform();
+ .second-transform() !important;
+}
+.test-rule6 {
+ .second-transform();
+}
+.test-rule7 {
+ // inherit !important from merged subrules
+ .second-transform();
+ .second-transform() !important;
+ .second-transform();
+}
+
+.test-rule-interleaved {
+ transform+: t1;
+ background+: b1;
+ transform+: t2;
+ background+: b2, b3;
+ transform+: t3;
+}
+
+.test-rule-spaced {
+ transform+_: t1;
+ background+_: b1;
+ transform+_: t2;
+ background+_: b2, b3;
+ transform+_: t3;
+}
+
+.test-rule-interleaved-with-spaced {
+ transform+_: t1s;
+ transform+: t2;
+ background+: b1;
+ transform+_: t3s;
+ transform+: t4 t5s;
+ background+_: b2s, b3;
+ transform+_: t6s;
+ background+: b4;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixin-noparens/mixin-noparens.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#theme {
+ > .mixin {
+ background-color: grey;
+ }
+}
+#container {
+ color: black;
+ #theme > .mixin;
+}
+
+=====================================output=====================================
+#theme {
+ > .mixin {
+ background-color: grey;
+ }
+}
+#container {
+ color: black;
+ #theme > .mixin;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins/maps.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.maps {
+ @a: 10;
+ h2 { width: unit(@a, px); }
+
+ .mk-map() {
+ text: white;
+ background: black;
+ }
+
+ @p: .mk-map();
+
+ h1 { color: @p[text]; }
+}
+
+
+
+=====================================output=====================================
+.maps {
+ @a: 10;
+ h2 {
+ width: unit(@a, px);
+ }
+
+ .mk-map() {
+ text: white;
+ background: black;
+ }
+
+ @p: .mk-map();
+
+ h1 {
+ color: @p[text];
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins/mixins.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mixin { border: 1px solid black; }
+.mixout { border-color: orange; }
+.borders { border-style: dashed; }
+.mixin > * { border: do not match me; }
+
+#namespace {
+ .borders {
+ border-style: dotted;
+ }
+ .biohazard {
+ content: "death";
+ .man {
+ color: transparent;
+ }
+ }
+}
+#theme {
+ > .mixin {
+ background-color: grey;
+ }
+}
+#container {
+ color: black;
+ .mixin();
+ .mixout ();
+ #theme > .mixin();
+}
+
+#header {
+ .milk {
+ color: inherit;
+ .mixin();
+ #theme > .mixin();
+ }
+ #cookie {
+ .chips {
+ #namespace .borders();
+ .calories {
+ #container();
+ }
+ }
+ .borders();
+ }
+}
+.secure-zone { #namespace .biohazard .man(); }
+.direct {
+ #namespace > .borders();
+}
+
+.bo, .bar {
+ width: 100%;
+}
+.bo {
+ border: 1px;
+}
+.ar.bo.ca {
+ color: black;
+}
+.jo.ki {
+ background: none;
+}
+.amp {
+ &.support {
+ color: orange;
+ .higher {
+ top: 0px;
+ }
+ &.deeper {
+ height: auto;
+ }
+ }
+}
+.extended {
+ .bo();
+ .jo.ki();
+ .amp.support();
+ .amp.support.higher();
+ .amp.support.deeper();
+}
+.do .re .mi .fa {
+ .sol .la {
+ .si {
+ color: cyan;
+ }
+ }
+}
+.mutli-selector-parents {
+ .do.re.mi.fa.sol.la.si();
+}
+.foo .bar {
+ .bar();
+}
+.has_parents() {
+ & .underParents {
+ color: red;
+ }
+}
+.has_parents();
+.parent {
+ .has_parents();
+}
+.margin_between(@above, @below) {
+ * + & { margin-top: @above; }
+ legend + & { margin-top: 0; }
+ & + * { margin-top: @below; }
+}
+h1 { .margin_between(25px, 10px); }
+h2 { .margin_between(20px, 8px); }
+h3 { .margin_between(15px, 5px); }
+
+.mixin_def(@url, @position){
+ background-image: @url;
+ background-position: @position;
+}
+.error{
+ @s: "/";
+ .mixin_def( "@{s}a.png", center center);
+}
+.recursion() {
+ color: black;
+}
+.test-rule-rec {
+ .recursion {
+ .recursion();
+ }
+}
+.paddingFloat(@padding) { padding-left: @padding; }
+
+.button {
+ .paddingFloat(((10px + 12) * 2));
+
+ &.large { .paddingFloat(((10em * 2) * 2)); }
+}
+.clearfix() {
+ // ...
+}
+.clearfix {
+ .clearfix();
+}
+.clearfix {
+ .clearfix();
+}
+.foo {
+ .clearfix();
+}
+
+=====================================output=====================================
+.mixin {
+ border: 1px solid black;
+}
+.mixout {
+ border-color: orange;
+}
+.borders {
+ border-style: dashed;
+}
+.mixin > * {
+ border: do not match me;
+}
+
+#namespace {
+ .borders {
+ border-style: dotted;
+ }
+ .biohazard {
+ content: "death";
+ .man {
+ color: transparent;
+ }
+ }
+}
+#theme {
+ > .mixin {
+ background-color: grey;
+ }
+}
+#container {
+ color: black;
+ .mixin();
+ .mixout ();
+ #theme > .mixin();
+}
+
+#header {
+ .milk {
+ color: inherit;
+ .mixin();
+ #theme > .mixin();
+ }
+ #cookie {
+ .chips {
+ #namespace .borders();
+ .calories {
+ #container();
+ }
+ }
+ .borders();
+ }
+}
+.secure-zone {
+ #namespace .biohazard .man();
+}
+.direct {
+ #namespace > .borders();
+}
+
+.bo,
+.bar {
+ width: 100%;
+}
+.bo {
+ border: 1px;
+}
+.ar.bo.ca {
+ color: black;
+}
+.jo.ki {
+ background: none;
+}
+.amp {
+ &.support {
+ color: orange;
+ .higher {
+ top: 0px;
+ }
+ &.deeper {
+ height: auto;
+ }
+ }
+}
+.extended {
+ .bo();
+ .jo.ki();
+ .amp.support();
+ .amp.support.higher();
+ .amp.support.deeper();
+}
+.do .re .mi .fa {
+ .sol .la {
+ .si {
+ color: cyan;
+ }
+ }
+}
+.mutli-selector-parents {
+ .do.re.mi.fa.sol.la.si();
+}
+.foo .bar {
+ .bar();
+}
+.has_parents() {
+ & .underParents {
+ color: red;
+ }
+}
+.has_parents();
+.parent {
+ .has_parents();
+}
+.margin_between(@above, @below) {
+ * + & {
+ margin-top: @above;
+ }
+ legend + & {
+ margin-top: 0;
+ }
+ & + * {
+ margin-top: @below;
+ }
+}
+h1 {
+ .margin_between(25px, 10px);
+}
+h2 {
+ .margin_between(20px, 8px);
+}
+h3 {
+ .margin_between(15px, 5px);
+}
+
+.mixin_def(@url, @position) {
+ background-image: @url;
+ background-position: @position;
+}
+.error {
+ @s: "/";
+ .mixin_def( "@{s}a.png", center center);
+}
+.recursion() {
+ color: black;
+}
+.test-rule-rec {
+ .recursion {
+ .recursion();
+ }
+}
+.paddingFloat(@padding) {
+ padding-left: @padding;
+}
+
+.button {
+ .paddingFloat(((10px + 12) * 2));
+
+ &.large {
+ .paddingFloat(((10em * 2) * 2));
+ }
+}
+.clearfix() {
+ // ...
+}
+.clearfix {
+ .clearfix();
+}
+.clearfix {
+ .clearfix();
+}
+.foo {
+ .clearfix();
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins/mixins-advanced.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Advanced mixin call tests to cover edge cases
+
+// Mixin call with expanded arguments
+.mixin(@a, @b) {
+ a: @a;
+ b: @b;
+}
+@args: 1px, 2px;
+.test-expanded {
+ .mixin(@args...);
+}
+
+// Mixin call with condition matching and multiple definitions
+.mixin-multi-def(@x: 10) when (@x > 10) {
+ large: @x;
+}
+.mixin-multi-def(@x: 10) when (@x <= 10) {
+ small: @x;
+}
+.test-multi-def {
+ .mixin-multi-def();
+ .mixin-multi-def(15);
+}
+
+// Mixin call with condition matching
+.mixin-guarded(@x) when (@x > 10) {
+ large: @x;
+}
+.mixin-guarded(@x) when (@x <= 10) {
+ small: @x;
+}
+.test-conditions {
+ .mixin-guarded(15);
+ .mixin-guarded(5);
+}
+
+// Mixin call with no arguments filter
+.mixin-no-args() {
+ no-args: true;
+}
+.mixin-no-args(@x) {
+ with-args: @x;
+}
+.test-no-args-filter {
+ .mixin-no-args();
+ .mixin-no-args(10);
+}
+
+// Mixin call with recursive mixin
+.mixin-recursive(@n) when (@n > 0) {
+ level: @n;
+ .mixin-recursive(@n - 1);
+}
+.mixin-recursive(@n) when (@n <= 0) {
+ done: true;
+}
+.test-recursive {
+ .mixin-recursive(3);
+}
+
+// Mixin call with namespace path
+#namespace {
+ .mixin() {
+ from-namespace: true;
+ }
+}
+.test-namespace-path {
+ #namespace > .mixin();
+}
+
+// Mixin call with important flag
+.mixin-important() {
+ important: true;
+}
+.test-important {
+ .mixin-important() !important;
+}
+
+// Mixin call with multiple candidates
+.mixin-multi(@x: 1) {
+ value1: @x;
+}
+.mixin-multi(@x: 2) {
+ value2: @x;
+}
+.test-multi {
+ .mixin-multi();
+}
+
+// Mixin call with named arguments
+.mixin-named(@a: a, @b: b) {
+ a: @a;
+ b: @b;
+}
+.test-named {
+ .mixin-named(@b: B, @a: A);
+}
+
+// Mixin call with expanded array
+.mixin-array(@a, @b, @c) {
+ a: @a;
+ b: @b;
+ c: @c;
+}
+@array: 1, 2, 3;
+.test-array-expand {
+ .mixin-array(@array...);
+}
+
+
+=====================================output=====================================
+// Advanced mixin call tests to cover edge cases
+
+// Mixin call with expanded arguments
+.mixin(@a, @b) {
+ a: @a;
+ b: @b;
+}
+@args: 1px, 2px;
+.test-expanded {
+ .mixin(@args...);
+}
+
+// Mixin call with condition matching and multiple definitions
+.mixin-multi-def(@x: 10) when (@x > 10) {
+ large: @x;
+}
+.mixin-multi-def(@x: 10) when (@x <= 10) {
+ small: @x;
+}
+.test-multi-def {
+ .mixin-multi-def();
+ .mixin-multi-def(15);
+}
+
+// Mixin call with condition matching
+.mixin-guarded(@x) when (@x > 10) {
+ large: @x;
+}
+.mixin-guarded(@x) when (@x <= 10) {
+ small: @x;
+}
+.test-conditions {
+ .mixin-guarded(15);
+ .mixin-guarded(5);
+}
+
+// Mixin call with no arguments filter
+.mixin-no-args() {
+ no-args: true;
+}
+.mixin-no-args(@x) {
+ with-args: @x;
+}
+.test-no-args-filter {
+ .mixin-no-args();
+ .mixin-no-args(10);
+}
+
+// Mixin call with recursive mixin
+.mixin-recursive(@n) when (@n > 0) {
+ level: @n;
+ .mixin-recursive(@n - 1);
+}
+.mixin-recursive(@n) when (@n <= 0) {
+ done: true;
+}
+.test-recursive {
+ .mixin-recursive(3);
+}
+
+// Mixin call with namespace path
+#namespace {
+ .mixin() {
+ from-namespace: true;
+ }
+}
+.test-namespace-path {
+ #namespace > .mixin();
+}
+
+// Mixin call with important flag
+.mixin-important() {
+ important: true;
+}
+.test-important {
+ .mixin-important() !important;
+}
+
+// Mixin call with multiple candidates
+.mixin-multi(@x: 1) {
+ value1: @x;
+}
+.mixin-multi(@x: 2) {
+ value2: @x;
+}
+.test-multi {
+ .mixin-multi();
+}
+
+// Mixin call with named arguments
+.mixin-named(@a: a, @b: b) {
+ a: @a;
+ b: @b;
+}
+.test-named {
+ .mixin-named(@b: B, @a: A);
+}
+
+// Mixin call with expanded array
+.mixin-array(@a, @b, @c) {
+ a: @a;
+ b: @b;
+ c: @c;
+}
+@array: 1, 2, 3;
+.test-array-expand {
+ .mixin-array(@array...);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins-closure/mixins-closure.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.scope {
+ @var: 99px;
+ .mixin () {
+ width: @var;
+ }
+}
+
+.class {
+ .scope > .mixin();
+}
+
+.overwrite {
+ @var: 0px;
+ .scope > .mixin();
+}
+
+.nested {
+ @var: 5px;
+ .mixin () {
+ width: @var;
+ }
+ .class {
+ @var: 10px;
+ .mixin();
+ }
+}
+
+=====================================output=====================================
+.scope {
+ @var: 99px;
+ .mixin () {
+ width: @var;
+ }
+}
+
+.class {
+ .scope > .mixin();
+}
+
+.overwrite {
+ @var: 0px;
+ .scope > .mixin();
+}
+
+.nested {
+ @var: 5px;
+ .mixin () {
+ width: @var;
+ }
+ .class {
+ @var: 10px;
+ .mixin();
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins-guards/mixins-guards.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Stacking, functions..
+
+.light (@a) when (lightness(@a) > 50%) {
+ color: inherit;
+}
+.light (@a) when (lightness(@a) < 50%) {
+ color: black;
+}
+.light (@a) {
+ margin: 1px;
+}
+
+.light1 { .light(#ddd) }
+.light2 { .light(#444) }
+
+// Arguments against each other
+
+.max (@a, @b) when (@a > @b) {
+ width: @a;
+}
+.max (@a, @b) when (@a < @b) {
+ width: @b;
+}
+
+.max1 { .max(3, 6) }
+.max2 { .max(8, 1) }
+
+// Globals inside guards
+
+@g: auto;
+
+.glob (@a) when (@a = @g) {
+ margin: @a @g;
+}
+.glob1 { .glob(auto) }
+
+// Other operators
+
+.ops (@a) when (@a >= 0) {
+ height: gt-or-eq;
+}
+.ops (@a) when (@a =< 0) {
+ height: lt-or-eq;
+}
+.ops (@a) when (@a <= 0) {
+ height: lt-or-eq-alias;
+}
+.ops (@a) when not(@a = 0) {
+ height: not-eq;
+}
+.ops1 { .ops(0) }
+.ops2 { .ops(1) }
+.ops3 { .ops(-1) }
+
+// Scope and default values
+
+@a: auto;
+
+.default (@a: inherit) when (@a = inherit) {
+ content: default;
+}
+.default1 { .default() }
+
+// true & false keywords
+.test-rule (@a) when (@a) {
+ content: "true.";
+}
+.test-rule (@a) when not (@a) {
+ content: "false.";
+}
+
+.test-rule1 { .test-rule(true) }
+.test-rule2 { .test-rule(false) }
+.test-rule3 { .test-rule(1) }
+.test-rule4 { .test-rule(boo) }
+.test-rule5 { .test-rule("true") }
+
+// Boolean expressions
+
+.bool () when (true) and (false) { content: true and false } // FALSE
+.bool () when (true) and (true) { content: true and true } // TRUE
+.bool () when (true) { content: true } // TRUE
+.bool () when (false) and (false) { content: true } // FALSE
+.bool () when (false), (true) { content: false, true } // TRUE
+.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE
+.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE
+.bool () when (false), (true) and (true) { content: false, true and true } // TRUE
+.bool () when (false), (false), (true) { content: false, false, true } // TRUE
+.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE
+.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE
+.bool () when not (false) { content: not false }
+.bool () when not (true) and not (false) { content: not true and not false }
+.bool () when not (true) and not (true) { content: not true and not true }
+.bool () when not (false) and (false), not (false) { content: not false and false, not false }
+
+.bool1 { .bool() }
+
+.equality-unit-test(@num) when (@num = 1%) {
+ test: fail;
+}
+.equality-unit-test(@num) when (@num = 2) {
+ test: pass;
+}
+.equality-units {
+ .equality-unit-test(1px);
+ .equality-unit-test(2px);
+}
+
+.colorguard(@col) when (@col = red) { content: is @col; }
+.colorguard(@col) when not (blue = @col) { content: is not blue its @col; }
+.colorguard(@col) {}
+.colorguardtest {
+ .colorguard(red);
+ .colorguard(blue);
+ .colorguard(purple);
+}
+
+.stringguard(@str) when (@str = "theme1") { content: @str is "theme1"; }
+.stringguard(@str) when not ("theme2" = @str) { content: @str is not "theme2"; }
+.stringguard(@str) when (@str = 'theme1') { content: @str is 'theme1'; }
+.stringguard(@str) when not ('theme2' = @str) { content: @str is not 'theme2'; }
+.stringguard(@str) when (~"theme1" = @str) { content: @str is theme1; }
+.stringguard(@str) {}
+.stringguardtest {
+ .stringguard("theme1");
+ .stringguard("theme2");
+ .stringguard('theme1');
+ .stringguard('theme2');
+ .stringguard(theme1);
+}
+
+.generic(@a, @b) {/**/}
+.generic(@a, @b) when (@a = @b) {content: @a is equal to @b}
+.generic(@a, @b) when (@b = @a) {content: @b is equal to @a too}
+.generic(@a, @b) when (@a < @b) {content: @a is less than @b}
+.generic(@a, @b) when (@b < @a) {content: @b is less than @a too}
+.generic(@a, @b) when (@a > @b) {content: @a is greater than @b}
+.generic(@a, @b) when (@b > @a) {content: @b is greater than @a too}
+.generic(@a, @b) when not(@a = @b) {content: @a is not equal to @b}
+.generic(@a, @b) when not(@b = @a) {content: @b is not equal to @a too}
+
+.variouse-types-comparison {
+ .generic(true, false);
+ .generic(1, true);
+ .generic(2, 2px);
+ .generic(3, ~"3");
+ .generic(5, ~"4");
+ .generic(abc, ~"abc");
+ .generic(abc, "abc");
+ .generic('abc', "abd");
+ .generic(6, e("6"));
+ .generic(9, 8);
+ .generic(a, b);
+ .generic(1 2, 3);
+}
+
+.list-comparison {
+ .generic(a b c, a b c);
+ .generic(a b c, a b d);
+ .generic(a, b, c; a, b, c);
+ .generic(a, b, c; a, b, d);
+ .generic(1 2px 300ms, 1em 2 .3s);
+
+ @space-list: 1 2 3;
+ @comma-list: 1, 2, 3;
+ @compound: @space-list @comma-list;
+
+ .generic(@space-list, @comma-list);
+ .generic(@comma-list, ~"1, 2, 3");
+ .generic(@compound, @space-list @comma-list);
+ .generic(@compound, @comma-list @space-list);
+ .generic(@compound 4, ~"1 2 3 1, 2, 3 4");
+}
+
+.mixin(...) {
+ catch:all;
+}
+.mixin(@var) when (@var=4) {
+ declare: 4;
+}
+.mixin(@var) when (@var=4px) {
+ declare: 4px;
+}
+#tryNumberPx {
+ .mixin(4px);
+}
+
+.lock-mixin(@a) {
+ .inner-locked-mixin(@x: @a) when (@a = 1) {
+ a: @a;
+ x: @x;
+ }
+}
+.call-lock-mixin {
+ .lock-mixin(1);
+ .call-inner-lock-mixin {
+ .inner-locked-mixin();
+ }
+}
+.bug-100cm-1m(@a) when (@a = 1) {
+ .failed {
+ one-hundred: not-equal-to-1;
+ }
+}
+.bug-100cm-1m(100cm);
+
+#ns {
+ .mixin-for-root-usage(@a) when (@a > 0) {
+ .mixin-generated-class {
+ a: @a;
+ }
+ }
+}
+
+#ns > .mixin-for-root-usage(1);
+
+@namespaceGuard: 1;
+#guarded when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ guarded: namespace;
+ }
+ }
+}
+#guarded() when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ silent: namespace;
+ }
+ }
+}
+#guarded(@variable) when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ should: not match because namespace argument;
+ }
+ }
+}
+#guarded(@variable: default) when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ guarded: with default;
+ }
+ }
+}
+#guarded when (@namespaceGuard<0) {
+ #deeper {
+ .mixin() {
+ should: not match because namespace guard;
+ }
+ }
+}
+#guarded-caller {
+ #guarded > #deeper > .mixin();
+}
+#top {
+ #deeper when (@namespaceGuard<0) {
+ .mixin(@a) {
+ should: not match because namespace guard;
+ }
+ }
+ #deeper() when (@namespaceGuard>0) {
+ .mixin(@a) {
+ should: match @a;
+ }
+ }
+}
+#guarded-deeper {
+ #top > #deeper > .mixin(1);
+}
+
+// namespaced & guarded mixin in root
+// outputs nothing but should pass:
+
+@guarded-mixin-for-root: true;
+#ns {
+ .guarded-mixin-for-root() when (@guarded-mixin-for-root) {}
+}
+#ns > .guarded-mixin-for-root();
+// various combinations of nested or, and, parenthesis and negation
+.parenthesisNot(@value) when ((((@value)))) {
+ parenthesisNot: just-value;
+}
+.parenthesisNot(@value) when (((not(@value)))) {
+ parenthesisNot: negated once inside;
+}
+.parenthesisNot(@value) when not((((@value)))) {
+ parenthesisNot: negated once outside;
+}
+.parenthesisNot(@value) when ((not((@value)))) {
+ parenthesisNot: negated once middle;
+}
+.parenthesisNot(@value) when not(((not(@value)))) {
+ parenthesisNot: negated twice 1;
+}
+.parenthesisNot(@value) when (not((not(@value)))) {
+ parenthesisNot: negated twice 2;
+}
+.parenthesisNot(@value) when ((not(not(@value)))) {
+ parenthesisNot: negated twice 3;
+}
+.parenthesisNot (...) when (default()) {
+ parenthesisNot: none matched;
+}
+
+#parenthesisNot-true {
+ .parenthesisNot(true);
+}
+#parenthesisNot-false {
+ .parenthesisNot(false);
+}
+
+.orderOfEvaluation(@a1, @a2, @a3) when ((@a1) and (@a2) or (@a3)) {
+ no-parenthesis: evaluated true 1a;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when ((@a3) or (@a1) and (@a2)) {
+ no-parenthesis: evaluated true 1b;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when ((@a1) and ((@a2) or (@a3))) {
+ no-parenthesis: evaluated true 1c;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (@a3), (@a1) and (@a2) {
+ no-parenthesis: evaluated true 1d;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (((@a3) or (@a1)) and (@a2)) {
+ no-parenthesis: evaluated true 1e;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when ((@a1) and (@a2) or not (@a3)) {
+ no-parenthesis: evaluated true 2a;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (not (@a3) or (@a1) and (@a2)) {
+ no-parenthesis: evaluated true 2b;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when not (@a3), (@a1) and (@a2) {
+ no-parenthesis: evaluated true 2c;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (not (@a1) and (@a2) or (@a3)) {
+ no-parenthesis: evaluated true 3;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when ((((@a1) and (@a2) or (@a3)))) {
+ no-parenthesis: evaluated true 4;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (((@a1) and (@a2)) or (@a3)) {
+ with-parenthesis: evaluated true;
+}
+.orderOfEvaluation(...) when (default()) {
+ orderOfEvaluation: evaluated false;
+}
+#orderOfEvaluation-false-false-true {
+ .orderOfEvaluation(false, false, true);
+}
+#orderOfEvaluation-false-false-false {
+ .orderOfEvaluation(false, false, false);
+}
+#orderOfEvaluation-true-true-false {
+ .orderOfEvaluation(true, true, false);
+}
+
+// not without parentheses should work the same as not with parentheses
+.test-not-noparens (@a) when not @a {
+ content: "not without parens false.";
+}
+.test-not-noparens (@a) when (@a) {
+ content: "not without parens true.";
+}
+
+.test-not-noparens1 { .test-not-noparens(true) }
+.test-not-noparens2 { .test-not-noparens(false) }
+
+
+=====================================output=====================================
+// Stacking, functions..
+
+.light (@a) when (lightness(@a) > 50%) {
+ color: inherit;
+}
+.light (@a) when (lightness(@a) < 50%) {
+ color: black;
+}
+.light (@a) {
+ margin: 1px;
+}
+
+.light1 {
+ .light(#ddd);
+}
+.light2 {
+ .light(#444);
+}
+
+// Arguments against each other
+
+.max (@a, @b) when (@a > @b) {
+ width: @a;
+}
+.max (@a, @b) when (@a < @b) {
+ width: @b;
+}
+
+.max1 {
+ .max(3, 6);
+}
+.max2 {
+ .max(8, 1);
+}
+
+// Globals inside guards
+
+@g: auto;
+
+.glob (@a) when (@a = @g) {
+ margin: @a @g;
+}
+.glob1 {
+ .glob(auto);
+}
+
+// Other operators
+
+.ops (@a) when (@a >= 0) {
+ height: gt-or-eq;
+}
+.ops (@a) when (@a =< 0) {
+ height: lt-or-eq;
+}
+.ops (@a) when (@a <= 0) {
+ height: lt-or-eq-alias;
+}
+.ops (@a) when not(@a = 0) {
+ height: not-eq;
+}
+.ops1 {
+ .ops(0);
+}
+.ops2 {
+ .ops(1);
+}
+.ops3 {
+ .ops(-1);
+}
+
+// Scope and default values
+
+@a: auto;
+
+.default (@a: inherit) when (@a = inherit) {
+ content: default;
+}
+.default1 {
+ .default();
+}
+
+// true & false keywords
+.test-rule (@a) when (@a) {
+ content: "true.";
+}
+.test-rule (@a) when not (@a) {
+ content: "false.";
+}
+
+.test-rule1 {
+ .test-rule(true);
+}
+.test-rule2 {
+ .test-rule(false);
+}
+.test-rule3 {
+ .test-rule(1);
+}
+.test-rule4 {
+ .test-rule(boo);
+}
+.test-rule5 {
+ .test-rule("true");
+}
+
+// Boolean expressions
+
+.bool () when (true) and (false) {
+ content: true and false;
+} // FALSE
+.bool () when (true) and (true) {
+ content: true and true;
+} // TRUE
+.bool () when (true) {
+ content: true;
+} // TRUE
+.bool () when (false) and (false) {
+ content: true;
+} // FALSE
+.bool () when (false), (true) {
+ content: false, true;
+} // TRUE
+.bool () when (false) and (true) and (true), (true) {
+ content:
+ false and true and true,
+ true;
+} // TRUE
+.bool () when (true) and (true) and (false), (false) {
+ content:
+ true and true and false,
+ false;
+} // FALSE
+.bool () when (false), (true) and (true) {
+ content:
+ false,
+ true and true;
+} // TRUE
+.bool () when (false), (false), (true) {
+ content: false, false, true;
+} // TRUE
+.bool () when (false), (false) and (true), (false) {
+ content:
+ false,
+ false and true,
+ false;
+} // FALSE
+.bool () when (false), (true) and (true) and (true), (false) {
+ content:
+ false,
+ true and true and true,
+ false;
+} // TRUE
+.bool () when not (false) {
+ content: not false;
+}
+.bool () when not (true) and not (false) {
+ content: not true and not false;
+}
+.bool () when not (true) and not (true) {
+ content: not true and not true;
+}
+.bool () when not (false) and (false),
+not (false) {
+ content:
+ not false and false,
+ not false;
+}
+
+.bool1 {
+ .bool();
+}
+
+.equality-unit-test(@num) when (@num = 1%) {
+ test: fail;
+}
+.equality-unit-test(@num) when (@num = 2) {
+ test: pass;
+}
+.equality-units {
+ .equality-unit-test(1px);
+ .equality-unit-test(2px);
+}
+
+.colorguard(@col) when (@col = red) {
+ content: is @col;
+}
+.colorguard(@col) when not (blue = @col) {
+ content: is not blue its @col;
+}
+.colorguard(@col) {
+}
+.colorguardtest {
+ .colorguard(red);
+ .colorguard(blue);
+ .colorguard(purple);
+}
+
+.stringguard(@str) when (@str = "theme1") {
+ content: @str is "theme1";
+}
+.stringguard(@str) when not ("theme2" = @str) {
+ content: @str is not "theme2";
+}
+.stringguard(@str) when (@str = "theme1") {
+ content: @str is "theme1";
+}
+.stringguard(@str) when not ("theme2" = @str) {
+ content: @str is not "theme2";
+}
+.stringguard(@str) when (~"theme1" = @str) {
+ content: @str is theme1;
+}
+.stringguard(@str) {
+}
+.stringguardtest {
+ .stringguard("theme1");
+ .stringguard("theme2");
+ .stringguard("theme1");
+ .stringguard("theme2");
+ .stringguard(theme1);
+}
+
+.generic(@a, @b) {
+ /**/
+}
+.generic(@a, @b) when (@a = @b) {
+ content: @a is equal to @b;
+}
+.generic(@a, @b) when (@b = @a) {
+ content: @b is equal to @a too;
+}
+.generic(@a, @b) when (@a < @b) {
+ content: @a is less than @b;
+}
+.generic(@a, @b) when (@b < @a) {
+ content: @b is less than @a too;
+}
+.generic(@a, @b) when (@a > @b) {
+ content: @a is greater than @b;
+}
+.generic(@a, @b) when (@b > @a) {
+ content: @b is greater than @a too;
+}
+.generic(@a, @b) when not(@a = @b) {
+ content: @a is not equal to @b;
+}
+.generic(@a, @b) when not(@b = @a) {
+ content: @b is not equal to @a too;
+}
+
+.variouse-types-comparison {
+ .generic(true, false);
+ .generic(1, true);
+ .generic(2, 2px);
+ .generic(3, ~"3");
+ .generic(5, ~"4");
+ .generic(abc, ~"abc");
+ .generic(abc, "abc");
+ .generic("abc", "abd");
+ .generic(6, e("6"));
+ .generic(9, 8);
+ .generic(a, b);
+ .generic(1 2, 3);
+}
+
+.list-comparison {
+ .generic(a b c, a b c);
+ .generic(a b c, a b d);
+ .generic(a, b, c; a, b, c);
+ .generic(a, b, c; a, b, d);
+ .generic(1 2px 300ms, 1em 2 0.3s);
+
+ @space-list: 1 2 3;
+ @comma-list: 1, 2, 3;
+ @compound: @space-list @comma-list;
+
+ .generic(@space-list, @comma-list);
+ .generic(@comma-list, ~"1, 2, 3");
+ .generic(@compound, @space-list @comma-list);
+ .generic(@compound, @comma-list @space-list);
+ .generic(@compound 4, ~"1 2 3 1, 2, 3 4");
+}
+
+.mixin(...) {
+ catch: all;
+}
+.mixin(@var) when (@var=4) {
+ declare: 4;
+}
+.mixin(@var) when (@var=4px) {
+ declare: 4px;
+}
+#tryNumberPx {
+ .mixin(4px);
+}
+
+.lock-mixin(@a) {
+ .inner-locked-mixin(@x: @a) when (@a = 1) {
+ a: @a;
+ x: @x;
+ }
+}
+.call-lock-mixin {
+ .lock-mixin(1);
+ .call-inner-lock-mixin {
+ .inner-locked-mixin();
+ }
+}
+.bug-100cm-1m(@a) when (@a = 1) {
+ .failed {
+ one-hundred: not-equal-to-1;
+ }
+}
+.bug-100cm-1m(100cm);
+
+#ns {
+ .mixin-for-root-usage(@a) when (@a > 0) {
+ .mixin-generated-class {
+ a: @a;
+ }
+ }
+}
+
+#ns > .mixin-for-root-usage(1);
+
+@namespaceGuard: 1;
+#guarded when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ guarded: namespace;
+ }
+ }
+}
+#guarded() when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ silent: namespace;
+ }
+ }
+}
+#guarded(@variable) when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ should: not match because namespace argument;
+ }
+ }
+}
+#guarded(@variable: default) when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ guarded: with default;
+ }
+ }
+}
+#guarded when (@namespaceGuard<0) {
+ #deeper {
+ .mixin() {
+ should: not match because namespace guard;
+ }
+ }
+}
+#guarded-caller {
+ #guarded > #deeper > .mixin();
+}
+#top {
+ #deeper when (@namespaceGuard<0) {
+ .mixin(@a) {
+ should: not match because namespace guard;
+ }
+ }
+ #deeper() when (@namespaceGuard>0) {
+ .mixin(@a) {
+ should: match @a;
+ }
+ }
+}
+#guarded-deeper {
+ #top > #deeper > .mixin(1);
+}
+
+// namespaced & guarded mixin in root
+// outputs nothing but should pass:
+
+@guarded-mixin-for-root: true;
+#ns {
+ .guarded-mixin-for-root() when (@guarded-mixin-for-root) {
+ }
+}
+#ns > .guarded-mixin-for-root();
+// various combinations of nested or, and, parenthesis and negation
+.parenthesisNot(@value) when ((((@value)))) {
+ parenthesisnot: just-value;
+}
+.parenthesisNot(@value) when (((not(@value)))) {
+ parenthesisnot: negated once inside;
+}
+.parenthesisNot(@value) when not((((@value)))) {
+ parenthesisnot: negated once outside;
+}
+.parenthesisNot(@value) when ((not((@value)))) {
+ parenthesisnot: negated once middle;
+}
+.parenthesisNot(@value) when not(((not(@value)))) {
+ parenthesisnot: negated twice 1;
+}
+.parenthesisNot(@value) when (not((not(@value)))) {
+ parenthesisnot: negated twice 2;
+}
+.parenthesisNot(@value) when ((not(not(@value)))) {
+ parenthesisnot: negated twice 3;
+}
+.parenthesisNot (...) when (default()) {
+ parenthesisnot: none matched;
+}
+
+#parenthesisNot-true {
+ .parenthesisNot(true);
+}
+#parenthesisNot-false {
+ .parenthesisNot(false);
+}
+
+.orderOfEvaluation(@a1, @a2, @a3) when ((@a1) and (@a2) or (@a3)) {
+ no-parenthesis: evaluated true 1a;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when ((@a3) or (@a1) and (@a2)) {
+ no-parenthesis: evaluated true 1b;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when ((@a1) and ((@a2) or (@a3))) {
+ no-parenthesis: evaluated true 1c;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (@a3), (@a1) and (@a2) {
+ no-parenthesis: evaluated true 1d;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (((@a3) or (@a1)) and (@a2)) {
+ no-parenthesis: evaluated true 1e;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when ((@a1) and (@a2) or not (@a3)) {
+ no-parenthesis: evaluated true 2a;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (not (@a3) or (@a1) and (@a2)) {
+ no-parenthesis: evaluated true 2b;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when not (@a3), (@a1) and (@a2) {
+ no-parenthesis: evaluated true 2c;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (not (@a1) and (@a2) or (@a3)) {
+ no-parenthesis: evaluated true 3;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when ((((@a1) and (@a2) or (@a3)))) {
+ no-parenthesis: evaluated true 4;
+}
+.orderOfEvaluation(@a1, @a2, @a3) when (((@a1) and (@a2)) or (@a3)) {
+ with-parenthesis: evaluated true;
+}
+.orderOfEvaluation(...) when (default()) {
+ orderofevaluation: evaluated false;
+}
+#orderOfEvaluation-false-false-true {
+ .orderOfEvaluation(false, false, true);
+}
+#orderOfEvaluation-false-false-false {
+ .orderOfEvaluation(false, false, false);
+}
+#orderOfEvaluation-true-true-false {
+ .orderOfEvaluation(true, true, false);
+}
+
+// not without parentheses should work the same as not with parentheses
+.test-not-noparens (@a) when not @a {
+ content: "not without parens false.";
+}
+.test-not-noparens (@a) when (@a) {
+ content: "not without parens true.";
+}
+
+.test-not-noparens1 {
+ .test-not-noparens(true);
+}
+.test-not-noparens2 {
+ .test-not-noparens(false);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins-guards-default-func/mixins-guards-default-func.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// basics:
+
+guard-default-basic-1 {
+ .m(1) {case: 1}
+ .m(@x) when (default()) {default: @x}
+
+ &-1 {.m(1)}
+ &-2 {.m(2)}
+}
+
+guard-default-basic-2 {
+ .m(1) {case: 1}
+ .m(2) {case: 2}
+ .m(3) {case: 3}
+ .m(@x) when (default()) {default: @x}
+
+ &-0 {.m(0)}
+ &-2 {.m(2)}
+}
+
+guard-default-basic-3 {
+ .m(@x) when (@x = 1) {case: 1}
+ .m(2) {case: 2}
+ .m(@x) when (@x = 3) {case: 3}
+ .m(@x) when (default()) {default: @x}
+
+ &-0 {.m(0)}
+ &-2 {.m(2)}
+ &-3 {.m(3)}
+}
+
+guard-default-definition-order {
+ .m(@x) when (default()) {default: @x}
+ .m(@x) when (@x = 1) {case: 1}
+ .m(2) {case: 2}
+ .m(@x) when (@x = 3) {case: 3}
+
+ &-0 {.m(0)}
+ &-2 {.m(2)}
+ &-2 {.m(3)}
+}
+
+// out of guard:
+
+guard-default-out-of-guard {
+ .m(1) {case-1: 1}
+ .m(@x: default()) when (default()) {default: @x}
+
+ &-0 {
+ case-0: default();
+ .m(1);
+ .m(2);
+ case-2: default();
+ }
+ &-1 {.m(default())}
+ &-2 {.m()}
+}
+
+// expressions:
+
+guard-default-expr-not {
+ .m(1) {case: 1}
+ .m(@x) when not(default()) {default: @x}
+
+ &-1 {.m(1)}
+ &-2 {.m(2)}
+}
+
+guard-default-expr-eq {
+ .m(@x) when (@x = true) {case: @x}
+ .m(@x) when (@x = false) {case: @x}
+ .m(@x) when (@x = default()) {default: @x}
+
+ &-true {.m(true)}
+ &-false {.m(false)}
+}
+
+guard-default-expr-or {
+ .m(1) {case: 1}
+ .m(2) {case: 2}
+ .m(@x) when (default()), (@x = 2) {default: @x}
+
+ &-1 {.m(1)}
+ &-2 {.m(2)}
+ &-3 {.m(3)}
+}
+
+guard-default-expr-and {
+ .m(1) {case: 1}
+ .m(2) {case: 2}
+ .m(@x) when (default()) and (@x = 3) {default: @x}
+
+ &-1 {.m(1)}
+ &-2 {.m(2)}
+ &-3 {.m(3)}
+ &-4 {.m(4)}
+}
+
+guard-default-expr-always {
+ .m(1) {case: 1}
+ .m(@x) when (default()), not(default()) {default: @x} // always match
+
+ &-1 {.m(1)}
+ &-2 {.m(2)}
+}
+
+guard-default-expr-never {
+ .m(1) {case: 1}
+ .m(@x) when (default()) and not(default()) {default: @x} // never match
+
+ &-1 {.m(1)}
+ &-2 {.m(2)}
+}
+
+
+// not conflicting multiple default() uses:
+
+guard-default-multi-1 {
+ .m(0) {case: 0}
+ .m(@x) when (default()) {default-1: @x}
+ .m(2) when (default()) {default-2: @x}
+
+ &-0 {.m(0)}
+ &-1 {.m(1)}
+}
+
+guard-default-multi-2 {
+ .m(1, @x) when (default()) {default-1: @x}
+ .m(2, @x) when (default()) {default-2: @x}
+ .m(@x, yes) when (default()) {default-3: @x}
+
+ &-1 {.m(1, no)}
+ &-2 {.m(2, no)}
+ &-3 {.m(3, yes)}
+}
+
+guard-default-multi-3 {
+ .m(red) {case-1: darkred}
+ .m(blue) {case-2: darkblue}
+ .m(@x) when (iscolor(@x)) and (default()) {default-color: @x}
+ .m('foo') {case-1: I am 'foo'}
+ .m('bar') {case-2: I am 'bar'}
+ .m(@x) when (isstring(@x)) and (default()) {default-string: I am @x}
+
+ &-blue {.m(blue)}
+ &-green {.m(green)}
+ &-foo {.m('foo')}
+ &-baz {.m('baz')}
+}
+
+guard-default-multi-4 {
+ .m(@x) when (default()), not(default()) {always: @x}
+ .m(@x) when (default()) and not(default()) {never: @x}
+ .m(2) {case: 2}
+
+ .m(1);
+ .m(2);
+}
+
+guard-default-not-ambiguous-2 {
+ .m(@x) {case: 1}
+ .m(@x) when (default()) {default: @x}
+ .m(@x) when not(default()) {not-default: @x}
+
+ .m(2);
+}
+
+guard-default-not-ambiguous-3 {
+ .m(@x) {case: 1}
+ .m(@x) when not(default()) {not-default-1: @x}
+ .m(@x) when not(default()) {not-default-2: @x}
+
+ .m(2);
+}
+
+// default & scope
+
+guard-default-scopes {
+ .s1() {.m(@v) {one: no condition}}
+ .s2() {.m(@v) when (@v) {two: when true}}
+ .s3() {.m(@v) when (default()) {three: when default}}
+
+ &-3 {
+ .s2();
+ .s3();
+ .m(false);
+ }
+
+ &-1 {
+ .s1();
+ .s3();
+ .m(false);
+ }
+}
+
+
+=====================================output=====================================
+// basics:
+
+guard-default-basic-1 {
+ .m(1) {
+ case: 1;
+ }
+ .m(@x) when (default()) {
+ default: @x;
+ }
+
+ &-1 {
+ .m(1);
+ }
+ &-2 {
+ .m(2);
+ }
+}
+
+guard-default-basic-2 {
+ .m(1) {
+ case: 1;
+ }
+ .m(2) {
+ case: 2;
+ }
+ .m(3) {
+ case: 3;
+ }
+ .m(@x) when (default()) {
+ default: @x;
+ }
+
+ &-0 {
+ .m(0);
+ }
+ &-2 {
+ .m(2);
+ }
+}
+
+guard-default-basic-3 {
+ .m(@x) when (@x = 1) {
+ case: 1;
+ }
+ .m(2) {
+ case: 2;
+ }
+ .m(@x) when (@x = 3) {
+ case: 3;
+ }
+ .m(@x) when (default()) {
+ default: @x;
+ }
+
+ &-0 {
+ .m(0);
+ }
+ &-2 {
+ .m(2);
+ }
+ &-3 {
+ .m(3);
+ }
+}
+
+guard-default-definition-order {
+ .m(@x) when (default()) {
+ default: @x;
+ }
+ .m(@x) when (@x = 1) {
+ case: 1;
+ }
+ .m(2) {
+ case: 2;
+ }
+ .m(@x) when (@x = 3) {
+ case: 3;
+ }
+
+ &-0 {
+ .m(0);
+ }
+ &-2 {
+ .m(2);
+ }
+ &-2 {
+ .m(3);
+ }
+}
+
+// out of guard:
+
+guard-default-out-of-guard {
+ .m(1) {
+ case-1: 1;
+ }
+ .m(@x: default()) when (default()) {
+ default: @x;
+ }
+
+ &-0 {
+ case-0: default();
+ .m(1);
+ .m(2);
+ case-2: default();
+ }
+ &-1 {
+ .m(default());
+ }
+ &-2 {
+ .m();
+ }
+}
+
+// expressions:
+
+guard-default-expr-not {
+ .m(1) {
+ case: 1;
+ }
+ .m(@x) when not(default()) {
+ default: @x;
+ }
+
+ &-1 {
+ .m(1);
+ }
+ &-2 {
+ .m(2);
+ }
+}
+
+guard-default-expr-eq {
+ .m(@x) when (@x = true) {
+ case: @x;
+ }
+ .m(@x) when (@x = false) {
+ case: @x;
+ }
+ .m(@x) when (@x = default()) {
+ default: @x;
+ }
+
+ &-true {
+ .m(true);
+ }
+ &-false {
+ .m(false);
+ }
+}
+
+guard-default-expr-or {
+ .m(1) {
+ case: 1;
+ }
+ .m(2) {
+ case: 2;
+ }
+ .m(@x) when (default()), (@x = 2) {
+ default: @x;
+ }
+
+ &-1 {
+ .m(1);
+ }
+ &-2 {
+ .m(2);
+ }
+ &-3 {
+ .m(3);
+ }
+}
+
+guard-default-expr-and {
+ .m(1) {
+ case: 1;
+ }
+ .m(2) {
+ case: 2;
+ }
+ .m(@x) when (default()) and (@x = 3) {
+ default: @x;
+ }
+
+ &-1 {
+ .m(1);
+ }
+ &-2 {
+ .m(2);
+ }
+ &-3 {
+ .m(3);
+ }
+ &-4 {
+ .m(4);
+ }
+}
+
+guard-default-expr-always {
+ .m(1) {
+ case: 1;
+ }
+ .m(@x) when (default()),
+ not(default()) {
+ default: @x;
+ } // always match
+
+ &-1 {
+ .m(1);
+ }
+ &-2 {
+ .m(2);
+ }
+}
+
+guard-default-expr-never {
+ .m(1) {
+ case: 1;
+ }
+ .m(@x) when (default()) and not(default()) {
+ default: @x;
+ } // never match
+
+ &-1 {
+ .m(1);
+ }
+ &-2 {
+ .m(2);
+ }
+}
+
+// not conflicting multiple default() uses:
+
+guard-default-multi-1 {
+ .m(0) {
+ case: 0;
+ }
+ .m(@x) when (default()) {
+ default-1: @x;
+ }
+ .m(2) when (default()) {
+ default-2: @x;
+ }
+
+ &-0 {
+ .m(0);
+ }
+ &-1 {
+ .m(1);
+ }
+}
+
+guard-default-multi-2 {
+ .m(1, @x) when (default()) {
+ default-1: @x;
+ }
+ .m(2, @x) when (default()) {
+ default-2: @x;
+ }
+ .m(@x, yes) when (default()) {
+ default-3: @x;
+ }
+
+ &-1 {
+ .m(1, no);
+ }
+ &-2 {
+ .m(2, no);
+ }
+ &-3 {
+ .m(3, yes);
+ }
+}
+
+guard-default-multi-3 {
+ .m(red) {
+ case-1: darkred;
+ }
+ .m(blue) {
+ case-2: darkblue;
+ }
+ .m(@x) when (iscolor(@x)) and (default()) {
+ default-color: @x;
+ }
+ .m("foo") {
+ case-1: I am "foo";
+ }
+ .m("bar") {
+ case-2: I am "bar";
+ }
+ .m(@x) when (isstring(@x)) and (default()) {
+ default-string: I am @x;
+ }
+
+ &-blue {
+ .m(blue);
+ }
+ &-green {
+ .m(green);
+ }
+ &-foo {
+ .m("foo");
+ }
+ &-baz {
+ .m("baz");
+ }
+}
+
+guard-default-multi-4 {
+ .m(@x) when (default()),
+ not(default()) {
+ always: @x;
+ }
+ .m(@x) when (default()) and not(default()) {
+ never: @x;
+ }
+ .m(2) {
+ case: 2;
+ }
+
+ .m(1);
+ .m(2);
+}
+
+guard-default-not-ambiguous-2 {
+ .m(@x) {
+ case: 1;
+ }
+ .m(@x) when (default()) {
+ default: @x;
+ }
+ .m(@x) when not(default()) {
+ not-default: @x;
+ }
+
+ .m(2);
+}
+
+guard-default-not-ambiguous-3 {
+ .m(@x) {
+ case: 1;
+ }
+ .m(@x) when not(default()) {
+ not-default-1: @x;
+ }
+ .m(@x) when not(default()) {
+ not-default-2: @x;
+ }
+
+ .m(2);
+}
+
+// default & scope
+
+guard-default-scopes {
+ .s1() {
+ .m(@v) {
+ one: no condition;
+ }
+ }
+ .s2() {
+ .m(@v) when (@v) {
+ two: when true;
+ }
+ }
+ .s3() {
+ .m(@v) when (default()) {
+ three: when default;
+ }
+ }
+
+ &-3 {
+ .s2();
+ .s3();
+ .m(false);
+ }
+
+ &-1 {
+ .s1();
+ .s3();
+ .m(false);
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins-important/mixins-important.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.submixin(@a) {
+ border-width: @a;
+}
+.mixin (9) {
+ border: 9 !important;
+}
+.mixin (@a: 0) {
+ border: @a;
+ boxer: @a;
+ .inner {
+ test: @a;
+ }
+ // comment
+ .submixin(@a);
+}
+
+.class {
+ .mixin(1);
+ .mixin(2) !important;
+ .mixin(3);
+ .mixin(4) !important;
+ .mixin(5);
+ .mixin() !important;
+ .mixin(9);
+}
+.size(@aaa: auto) {
+ .set-width(@aaa) {
+ width: @aaa;
+ }
+ .set-width(@aaa);
+}
+.when-calling-nested-issue-2394 {
+ .size() !important;
+}
+.when-calling-nested-with-param-issue-2394 {
+ .size(10px) !important;
+}
+.test-ruleMixin-2421 () {
+ .topCheck-2421 () {
+ .nestedCheck-2421() {
+ margin: 5px;
+ }
+ .nestedCheck-2421();
+ }
+ .topCheck-2421();
+}
+.class1-2421 {
+ .test-ruleMixin-2421() !important;
+}
+.class2-2421 {
+ .test-ruleMixin-2421();
+}
+
+=====================================output=====================================
+.submixin(@a) {
+ border-width: @a;
+}
+.mixin (9) {
+ border: 9 !important;
+}
+.mixin (@a: 0) {
+ border: @a;
+ boxer: @a;
+ .inner {
+ test: @a;
+ }
+ // comment
+ .submixin(@a);
+}
+
+.class {
+ .mixin(1);
+ .mixin(2) !important;
+ .mixin(3);
+ .mixin(4) !important;
+ .mixin(5);
+ .mixin() !important;
+ .mixin(9);
+}
+.size(@aaa: auto) {
+ .set-width(@aaa) {
+ width: @aaa;
+ }
+ .set-width(@aaa);
+}
+.when-calling-nested-issue-2394 {
+ .size() !important;
+}
+.when-calling-nested-with-param-issue-2394 {
+ .size(10px) !important;
+}
+.test-ruleMixin-2421 () {
+ .topCheck-2421 () {
+ .nestedCheck-2421() {
+ margin: 5px;
+ }
+ .nestedCheck-2421();
+ }
+ .topCheck-2421();
+}
+.class1-2421 {
+ .test-ruleMixin-2421() !important;
+}
+.class2-2421 {
+ .test-ruleMixin-2421();
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins-named-args/mixins-named-args.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mixin (@a: 1px, @b: 50%) {
+ width: (@a * 5);
+ height: (@b - 1%);
+ args: @arguments;
+}
+.mixin (@a: 1px, @b: 50%) when (@b > 75%){
+ text-align: center;
+}
+
+.named-arg {
+ color: blue;
+ .mixin(@b: 100%);
+}
+
+.class {
+ @var: 20%;
+ .mixin(@b: @var);
+}
+
+.all-args-wrong-args {
+ .mixin(@b: 10%, @a: 2px);
+}
+
+.mixin2 (@a: 1px, @b: 50%, @c: 50) {
+ width: (@a * 5);
+ height: (@b - 1%);
+ color: (#000000 + @c);
+}
+
+.named-args2 {
+ .mixin2(3px, @c: 100);
+}
+
+.named-args3 {
+ .mixin2(@b: 30%, @c: #123456);
+}
+
+=====================================output=====================================
+.mixin (@a: 1px, @b: 50%) {
+ width: (@a * 5);
+ height: (@b - 1%);
+ args: @arguments;
+}
+.mixin (@a: 1px, @b: 50%) when (@b > 75%) {
+ text-align: center;
+}
+
+.named-arg {
+ color: blue;
+ .mixin(@b: 100%);
+}
+
+.class {
+ @var: 20%;
+ .mixin(@b: @var);
+}
+
+.all-args-wrong-args {
+ .mixin(@b: 10%, @a: 2px);
+}
+
+.mixin2 (@a: 1px, @b: 50%, @c: 50) {
+ width: (@a * 5);
+ height: (@b - 1%);
+ color: (#000000 + @c);
+}
+
+.named-args2 {
+ .mixin2(3px, @c: 100);
+}
+
+.named-args3 {
+ .mixin2(@b: 30%, @c: #123456);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins-nested/mixins-nested.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mix-inner (@var) {
+ border-width: @var;
+}
+
+.mix (@a: 10) {
+ .inner {
+ height: (@a * 10);
+
+ .innest {
+ width: @a;
+ .mix-inner((@a * 2));
+ }
+ }
+}
+
+.class {
+ .mix(30);
+}
+
+.class2 {
+ .mix(60);
+}
+
+=====================================output=====================================
+.mix-inner (@var) {
+ border-width: @var;
+}
+
+.mix (@a: 10) {
+ .inner {
+ height: (@a * 10);
+
+ .innest {
+ width: @a;
+ .mix-inner((@a * 2));
+ }
+ }
+}
+
+.class {
+ .mix(30);
+}
+
+.class2 {
+ .mix(60);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/mixins-pattern/mixins-pattern.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mixin (...) {
+ variadic: true;
+}
+.mixin (@a...) {
+ named-variadic: true;
+}
+.mixin () {
+ zero: 0;
+}
+.mixin (@a: 1px) {
+ one: 1;
+}
+.mixin (@a) {
+ one-req: 1;
+}
+.mixin (@a: 1px, @b: 2px) {
+ two: 2;
+}
+
+.mixin (@a, @b, @c) {
+ three-req: 3;
+}
+
+.mixin (@a: 1px, @b: 2px, @c: 3px) {
+ three: 3;
+}
+
+.zero {
+ .mixin();
+}
+
+.one {
+ .mixin(1);
+}
+
+.two {
+ .mixin(1, 2);
+}
+
+.three {
+ .mixin(1, 2, 3);
+}
+
+//
+
+.mixout ('left') {
+ left: 1;
+}
+
+.mixout ('right') {
+ right: 1;
+}
+
+.left {
+ .mixout('left');
+}
+.right {
+ .mixout('right');
+}
+
+//
+
+.border (@side, @width) {
+ color: black;
+ .border-side(@side, @width);
+}
+.border-side (left, @w) {
+ border-left: @w;
+}
+.border-side (right, @w) {
+ border-right: @w;
+}
+
+.border-right {
+ .border(right, 4px);
+}
+.border-left {
+ .border(left, 4px);
+}
+
+//
+
+
+.border-radius (@r) {
+ both: (@r * 10);
+}
+.border-radius (@r, left) {
+ left: @r;
+}
+.border-radius (@r, right) {
+ right: @r;
+}
+
+.only-right {
+ .border-radius(33, right);
+}
+.only-left {
+ .border-radius(33, left);
+}
+.left-right {
+ .border-radius(33);
+}
+
+=====================================output=====================================
+.mixin (...) {
+ variadic: true;
+}
+.mixin (@a...) {
+ named-variadic: true;
+}
+.mixin () {
+ zero: 0;
+}
+.mixin (@a: 1px) {
+ one: 1;
+}
+.mixin (@a) {
+ one-req: 1;
+}
+.mixin (@a: 1px, @b: 2px) {
+ two: 2;
+}
+
+.mixin (@a, @b, @c) {
+ three-req: 3;
+}
+
+.mixin (@a: 1px, @b: 2px, @c: 3px) {
+ three: 3;
+}
+
+.zero {
+ .mixin();
+}
+
+.one {
+ .mixin(1);
+}
+
+.two {
+ .mixin(1, 2);
+}
+
+.three {
+ .mixin(1, 2, 3);
+}
+
+//
+
+.mixout ("left") {
+ left: 1;
+}
+
+.mixout ("right") {
+ right: 1;
+}
+
+.left {
+ .mixout("left");
+}
+.right {
+ .mixout("right");
+}
+
+//
+
+.border (@side, @width) {
+ color: black;
+ .border-side(@side, @width);
+}
+.border-side (left, @w) {
+ border-left: @w;
+}
+.border-side (right, @w) {
+ border-right: @w;
+}
+
+.border-right {
+ .border(right, 4px);
+}
+.border-left {
+ .border(left, 4px);
+}
+
+//
+
+.border-radius (@r) {
+ both: (@r * 10);
+}
+.border-radius (@r, left) {
+ left: @r;
+}
+.border-radius (@r, right) {
+ right: @r;
+}
+
+.only-right {
+ .border-radius(33, right);
+}
+.only-left {
+ .border-radius(33, left);
+}
+.left-right {
+ .border-radius(33);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/namespace-targeted/namespace-targeted.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Targeted tests for specific uncovered lines in namespace-value.js
+
+// Lines 51-52: $@var interpolation (property interpolation with variable)
+// This tests: name.substring(0, 2) === '$@'
+// The syntax is #namespace[$@var-name] where @var-name contains the property name
+@prop-name: my-prop;
+#namespace {
+ my-prop: prop-value;
+}
+.test-prop-interp {
+ value: #namespace[$@prop-name];
+}
+
+// Lines 43-47: Variable not found error path
+// Access a variable that doesn't exist in the namespace
+#namespace-with-var {
+ @existing-var: value;
+}
+.test-var-not-found {
+ // This will error: variable @nonexistent-var not found
+ // color: #namespace-with-var[@nonexistent-var];
+}
+
+// Lines 61-65: Property not found error path
+// Access a property that doesn't exist in the namespace
+#namespace-with-prop {
+ existing-prop: value;
+}
+.test-prop-not-found {
+ // This will error: property "nonexistent-prop" not found
+ // value: #namespace-with-prop[$nonexistent-prop];
+}
+
+
+=====================================output=====================================
+// Targeted tests for specific uncovered lines in namespace-value.js
+
+// Lines 51-52: $@var interpolation (property interpolation with variable)
+// This tests: name.substring(0, 2) === '$@'
+// The syntax is #namespace[$@var-name] where @var-name contains the property name
+@prop-name: my-prop;
+#namespace {
+ my-prop: prop-value;
+}
+.test-prop-interp {
+ value: #namespace[$ @prop-name];
+}
+
+// Lines 43-47: Variable not found error path
+// Access a variable that doesn't exist in the namespace
+#namespace-with-var {
+ @existing-var: value;
+}
+.test-var-not-found {
+ // This will error: variable @nonexistent-var not found
+ // color: #namespace-with-var[@nonexistent-var];
+}
+
+// Lines 61-65: Property not found error path
+// Access a property that doesn't exist in the namespace
+#namespace-with-prop {
+ existing-prop: value;
+}
+.test-prop-not-found {
+ // This will error: property "nonexistent-prop" not found
+ // value: #namespace-with-prop[$nonexistent-prop];
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/nesting/nesting.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.nesting-parent {
+ color: red;
+
+ .nesting-child {
+ color: blue;
+
+ .nesting-grandchild {
+ color: green;
+ }
+ }
+
+ &:hover {
+ color: orange;
+ }
+
+ &.modifier {
+ color: purple;
+ }
+}
+
+.correctly-exit-calc-mode {
+ @a: 10;
+ h2 { width: unit(@a, px); }
+
+ div { width: calc(100px * 2); }
+
+ .mk-map() {
+ text: white;
+ background: black;
+ }
+
+ @p: .mk-map();
+
+ h1 { color: @p[text]; }
+}
+
+
+
+=====================================output=====================================
+.nesting-parent {
+ color: red;
+
+ .nesting-child {
+ color: blue;
+
+ .nesting-grandchild {
+ color: green;
+ }
+ }
+
+ &:hover {
+ color: orange;
+ }
+
+ &.modifier {
+ color: purple;
+ }
+}
+
+.correctly-exit-calc-mode {
+ @a: 10;
+ h2 {
+ width: unit(@a, px);
+ }
+
+ div {
+ width: calc(100px * 2);
+ }
+
+ .mk-map() {
+ text: white;
+ background: black;
+ }
+
+ @p: .mk-map();
+
+ h1 {
+ color: @p[text];
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/no-output/no-output.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mixin() {
+}
+
+=====================================output=====================================
+.mixin() {
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/operations/operations.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Mathematical operations tests
+#operations {
+ color: (#110000 + #000011 + #001100); // #111111
+ color-2: (yellow - #070707);
+ height: (10px / 2px + 6px - 1px * 2); // 9px
+ width: (2 * 4 - 5em); // 3em
+ .spacing {
+ height: (10px / 2px+6px-1px*2);
+ width: (2 * 4-5em);
+ }
+ subtraction: (20 - 10 - 5 - 5); // 0
+ division: (20 / 5 / 4); // 1
+}
+
+@x: 4;
+@y: 12em;
+
+.with-variables {
+ height: (@x + @y); // 16em
+ width: (12 + @y); // 24em
+ size: (5cm - @x); // 1cm
+}
+
+.with-functions {
+ color: (rgb(200, 200, 200) / 2);
+ color: (2 * hsl(0, 50%, 50%));
+ color: (rgb(10, 10, 10) + hsl(0, 50%, 50%));
+}
+
+@z: -2;
+
+.negative {
+ height: (2px + @z); // 0px
+ width: (2px - @z); // 4px
+}
+
+.shorthands {
+ padding: -1px 2px 0 -4px; //
+}
+
+.rem-dimensions {
+ font-size: (20rem / 5 + 1.5rem); // 5.5rem
+}
+
+.colors {
+ color: #123; // #112233
+ border-color: (#234 + #111111); // #334455
+ background-color: (#222222 - #fff); // #000000
+ .other {
+ color: (2 * #111); // #222222
+ border-color: (#333333 / 3 + #111); // #222222
+ }
+}
+
+.negations {
+ @var: 4px;
+ variable: (-@var); // 4
+ variable1: (-@var + @var); // 0
+ variable2: (@var + -@var); // 0
+ variable3: (@var - -@var); // 8
+ variable4: (-@var - -@var); // 0
+ paren: (-(@var)); // -4px
+ paren2: (-(2 + 2) * -@var); // 16
+}
+
+=====================================output=====================================
+// Mathematical operations tests
+#operations {
+ color: (#110000 + #000011 + #001100); // #111111
+ color-2: (yellow - #070707);
+ height: (10px / 2px + 6px - 1px * 2); // 9px
+ width: (2 * 4 - 5em); // 3em
+ .spacing {
+ height: (10px / 2px+6px-1px * 2);
+ width: (2 * 4-5em);
+ }
+ subtraction: (20 - 10 - 5 - 5); // 0
+ division: (20 / 5 / 4); // 1
+}
+
+@x: 4;
+@y: 12em;
+
+.with-variables {
+ height: (@x + @y); // 16em
+ width: (12 + @y); // 24em
+ size: (5cm - @x); // 1cm
+}
+
+.with-functions {
+ color: (rgb(200, 200, 200) / 2);
+ color: (2 * hsl(0, 50%, 50%));
+ color: (rgb(10, 10, 10) + hsl(0, 50%, 50%));
+}
+
+@z: -2;
+
+.negative {
+ height: (2px + @z); // 0px
+ width: (2px - @z); // 4px
+}
+
+.shorthands {
+ padding: -1px 2px 0 -4px; //
+}
+
+.rem-dimensions {
+ font-size: (20rem / 5 + 1.5rem); // 5.5rem
+}
+
+.colors {
+ color: #123; // #112233
+ border-color: (#234 + #111111); // #334455
+ background-color: (#222222 - #fff); // #000000
+ .other {
+ color: (2 * #111); // #222222
+ border-color: (#333333 / 3 + #111); // #222222
+ }
+}
+
+.negations {
+ @var: 4px;
+ variable: (-@var); // 4
+ variable1: (-@var + @var); // 0
+ variable2: (@var + -@var); // 0
+ variable3: (@var - -@var); // 8
+ variable4: (-@var - -@var); // 0
+ paren: (-(@var)); // -4px
+ paren2: (-(2 + 2) * -@var); // 16
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/operations/operations-advanced.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Advanced operation tests to cover edge cases
+
+// Operations with math off
+@math-off: true;
+.test-math-off {
+ @a: 10px;
+ @b: 5px;
+ result: @a + @b;
+}
+
+// Operations with Dimension to Color conversion
+@dimension: 10px;
+@color: #ff0000;
+.test-dim-to-color {
+ // This should convert dimension to color for operation
+ result: @dimension + @color;
+}
+
+// Operations with Color to Dimension conversion
+.test-color-to-dim {
+ result: @color + @dimension;
+}
+
+// Operations with division and PARENS_DIVISION math mode
+@div-op: (10px / 2);
+.test-division {
+ result: @div-op * 2;
+}
+
+// Operations with nested operations
+@nested: (10px + 5px) * 2;
+.test-nested {
+ result: @nested;
+}
+
+// Operations with spaced operators
+@spaced: 10px + 5px;
+.test-spaced {
+ result: @spaced;
+}
+
+// Operations with non-spaced operators
+@non-spaced: 10px+5px;
+.test-non-spaced {
+ result: @non-spaced;
+}
+
+// Operations with division operator
+@div-op: 10px / 2;
+.test-div {
+ result: @div-op;
+}
+
+// Operations with invalid types (should error, but test the path)
+.test-invalid {
+ // This will error, but tests the error path
+ // result: "string" + 10px;
+}
+
+// Operations with Operation operands
+@op1: 10px + 5px;
+@op2: 20px - 10px;
+.test-op-operands {
+ result: @op1 * @op2;
+}
+
+// Operations with math context
+.test-math-context {
+ @a: 10;
+ @b: 5;
+ add: @a + @b;
+ sub: @a - @b;
+ mul: @a * @b;
+ div: @a / @b;
+}
+
+
+=====================================output=====================================
+// Advanced operation tests to cover edge cases
+
+// Operations with math off
+@math-off: true;
+.test-math-off {
+ @a: 10px;
+ @b: 5px;
+ result: @a + @b;
+}
+
+// Operations with Dimension to Color conversion
+@dimension: 10px;
+@color: #ff0000;
+.test-dim-to-color {
+ // This should convert dimension to color for operation
+ result: @dimension + @color;
+}
+
+// Operations with Color to Dimension conversion
+.test-color-to-dim {
+ result: @color + @dimension;
+}
+
+// Operations with division and PARENS_DIVISION math mode
+@div-op: (10px / 2);
+.test-division {
+ result: @div-op * 2;
+}
+
+// Operations with nested operations
+@nested: (10px + 5px) * 2;
+.test-nested {
+ result: @nested;
+}
+
+// Operations with spaced operators
+@spaced: 10px + 5px;
+.test-spaced {
+ result: @spaced;
+}
+
+// Operations with non-spaced operators
+@non-spaced: 10px+5px;
+.test-non-spaced {
+ result: @non-spaced;
+}
+
+// Operations with division operator
+@div-op: 10px / 2;
+.test-div {
+ result: @div-op;
+}
+
+// Operations with invalid types (should error, but test the path)
+.test-invalid {
+ // This will error, but tests the error path
+ // result: "string" + 10px;
+}
+
+// Operations with Operation operands
+@op1: 10px + 5px;
+@op2: 20px - 10px;
+.test-op-operands {
+ result: @op1 * @op2;
+}
+
+// Operations with math context
+.test-math-context {
+ @a: 10;
+ @b: 5;
+ add: @a + @b;
+ sub: @a - @b;
+ mul: @a * @b;
+ div: @a / @b;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/parse-interpolation/parse-interpolation.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Parse interpolation tests
+@inputs: input[type=text], input[type=email], input[type=password], textarea;
+
+@{inputs} {
+ &:focus {
+ foo: bar;
+ }
+}
+
+@classes: .a, .b, .c;
+
+@{classes} {
+ + .z {
+ color: blue;
+ }
+}
+
+.bar {
+ .d@{classes}&:hover, baz {
+ color: blue;
+ }
+}
+
+@c: ~'.a, .b';
+@d: ~'.c, .d';
+@e: ~' + .e';
+
+@{c}@{d} {
+ @{e} {
+ foo: bar;
+ }
+}
+
+@textClasses: ~'&[class="text"], &.text';
+
+input {
+ @{textClasses} {
+ background: red;
+ }
+}
+
+@my-selector: ~'.selector-1, .selector-2';
+.master-page-1 {
+ @{my-selector} {
+ background-color: red;
+ }
+}
+
+@list: apple, satsuma, banana, pear;
+@{list} {
+ .fruit-& {
+ content: "Just a test.";
+ }
+}
+
+=====================================output=====================================
+// Parse interpolation tests
+@inputs: input[type=text], input[type=email], input[type=password], textarea;
+
+@{inputs} {
+ &:focus {
+ foo: bar;
+ }
+}
+
+@classes: .a, .b, .c;
+
+@{classes} {
+ + .z {
+ color: blue;
+ }
+}
+
+.bar {
+ .d@{classes}&:hover,
+ baz {
+ color: blue;
+ }
+}
+
+@c: ~".a, .b";
+@d: ~".c, .d";
+@e: ~" + .e";
+
+@{c}@{d} {
+ @{e} {
+ foo: bar;
+ }
+}
+
+@textClasses: ~'&[class="text"], &.text';
+
+input {
+ @{textClasses} {
+ background: red;
+ }
+}
+
+@my-selector: ~".selector-1, .selector-2";
+.master-page-1 {
+ @{my-selector} {
+ background-color: red;
+ }
+}
+
+@list: apple, satsuma, banana, pear;
+@{list} {
+ .fruit-& {
+ content: "Just a test.";
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/parser-slashed-combinator/parser-slashed-combinator.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Test for slashedCombinator parser (lines 1392-1399)
+// This tests /deep/ and /shadow/ combinators
+// NOTE: These combinators are DEPRECATED in CSS and should not be used in new code
+// They were part of the Shadow DOM specification but have been removed
+
+// /deep/ combinator (deprecated)
+.parent /deep/ .child {
+ color: red;
+}
+
+// /shadow/ combinator (deprecated)
+.container /shadow/ .content {
+ background: blue;
+}
+
+// Test with nested selectors
+.wrapper /deep/ .inner /deep/ .deepest {
+ padding: 10px;
+}
+
+
+=====================================output=====================================
+// Test for slashedCombinator parser (lines 1392-1399)
+// This tests /deep/ and /shadow/ combinators
+// NOTE: These combinators are DEPRECATED in CSS and should not be used in new code
+// They were part of the Shadow DOM specification but have been removed
+
+// /deep/ combinator (deprecated)
+.parent /deep/ .child {
+ color: red;
+}
+
+// /shadow/ combinator (deprecated)
+.container /shadow/ .content {
+ background: blue;
+}
+
+// Test with nested selectors
+.wrapper /deep/ .inner /deep/ .deepest {
+ padding: 10px;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/plugi/plugi.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// https://github.com/less/less.js/issues/3660
+// const dir = parserInput.$re(/^@plugin?\\s+/);
+// correct regexp is /^@plugin\\s+/
+// so follow code will change nothing, parse result is same with raw less code
+@plugi "plugi-typo-dont-parse-as-@plugin";
+
+=====================================output=====================================
+// https://github.com/less/less.js/issues/3660
+// const dir = parserInput.$re(/^@plugin?\\s+/);
+// correct regexp is /^@plugin\\s+/
+// so follow code will change nothing, parse result is same with raw less code
+@plugi "plugi-typo-dont-parse-as-@plugin";
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/plugin-module/plugin-module.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Test NPM import
+@plugin "clean-css";
+
+a {
+ background: none;
+}
+
+=====================================output=====================================
+// Test NPM import
+@plugin "clean-css";
+
+a {
+ background: none;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/plugin-preeval/plugin-preeval.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@plugin "../../plugin/plugin-preeval";
+
+.two(@rules: {}) {
+ :root.two & {
+ @rules();
+ }
+}
+
+.one {
+ .two({
+ --foo: @replace !important;
+ });
+}
+
+@stop: end;
+
+=====================================output=====================================
+@plugin "../../plugin/plugin-preeval";
+
+.two(@rules: {}) {
+ :root.two & {
+ @rules();
+ }
+}
+
+.one {
+ .two({
+ --foo: @replace !important;
+ });
+}
+
+@stop: end;
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/property-targeted/property-targeted.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Targeted tests for specific uncovered lines in property.js
+
+// Lines 49-51: Property with important flag handling
+// This tests when a property accessor accesses a property that has !important
+.test-important {
+ color: red !important;
+ background: $color;
+}
+
+// Lines 60-64: Property undefined error (should be in tests-error, but testing the path)
+// This will error, but tests the error path
+.test-undefined {
+ // value: @undefined-property;
+}
+
+// Lines 72-73: find method returning null (property not found in any frame)
+// This tests the find method when property doesn't exist
+.test-not-found {
+ // value: @nonexistent;
+}
+
+
+=====================================output=====================================
+// Targeted tests for specific uncovered lines in property.js
+
+// Lines 49-51: Property with important flag handling
+// This tests when a property accessor accesses a property that has !important
+.test-important {
+ color: red !important;
+ background: $color;
+}
+
+// Lines 60-64: Property undefined error (should be in tests-error, but testing the path)
+// This will error, but tests the error path
+.test-undefined {
+ // value: @undefined-property;
+}
+
+// Lines 72-73: find method returning null (property not found in any frame)
+// This tests the find method when property doesn't exist
+.test-not-found {
+ // value: @nonexistent;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/rulesets/rulesets.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Ruleset nesting and selector tests
+#first > .one {
+ > #second .two > #deux {
+ width: 50%;
+ #third {
+ &:focus {
+ color: black;
+ #fifth {
+ > #sixth {
+ .seventh #eighth {
+ + #ninth {
+ color: purple;
+ }
+ }
+ }
+ }
+ }
+ height: 100%;
+ }
+ #fourth, #five, #six {
+ color: #110000;
+ .seven, .eight > #nine {
+ border: 1px solid black;
+ }
+ #ten {
+ color: red;
+ }
+ }
+ }
+ font-size: 2em;
+ hasOwnProperty: blue;
+}
+
+=====================================output=====================================
+// Ruleset nesting and selector tests
+#first > .one {
+ > #second .two > #deux {
+ width: 50%;
+ #third {
+ &:focus {
+ color: black;
+ #fifth {
+ > #sixth {
+ .seventh #eighth {
+ + #ninth {
+ color: purple;
+ }
+ }
+ }
+ }
+ }
+ height: 100%;
+ }
+ #fourth,
+ #five,
+ #six {
+ color: #110000;
+ .seven,
+ .eight > #nine {
+ border: 1px solid black;
+ }
+ #ten {
+ color: red;
+ }
+ }
+ }
+ font-size: 2em;
+ hasownproperty: blue;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/scope/scope.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@x: red;
+@x: blue;
+@z: transparent;
+@mix: none;
+
+.mixin {
+ @mix: #989;
+}
+@mix: blue;
+.tiny-scope {
+ color: @mix; // #989
+ .mixin();
+}
+
+.scope1 {
+ @y: orange;
+ @z: black;
+ color: @x; // blue
+ border-color: @z; // black
+ .hidden {
+ @x: #131313;
+ }
+ .scope2 {
+ @y: red;
+ color: @x; // blue
+ .scope3 {
+ @local: white;
+ color: @y; // red
+ border-color: @z; // black
+ background-color: @local; // white
+ }
+ }
+}
+
+#namespace {
+ .scoped_mixin() {
+ @local-will-be-made-global: green;
+ .scope {
+ scoped-val: @local-will-be-made-global;
+ }
+ }
+}
+
+#namespace > .scoped_mixin();
+
+.setHeight(@h) { @height: 1024px; }
+.useHeightInMixinCall(@h) { .useHeightInMixinCall { mixin-height: @h; } }
+@mainHeight: 50%;
+.setHeight(@mainHeight);
+.heightIsSet { height: @height; }
+.useHeightInMixinCall(@height);
+
+.importRuleset() {
+ .imported {
+ exists: true;
+ }
+}
+.importRuleset();
+.testImported {
+ .imported();
+}
+
+@parameterDefault: 'top level';
+@anotherVariable: 'top level';
+//mixin uses top-level variables
+.mixinNoParam(@parameter: @parameterDefault) when (@parameter = 'top level') {
+ default: @parameter;
+ scope: @anotherVariable;
+ sub-scope-only: @subScopeOnly;
+}
+
+#allAreUsedHere {
+ //redefine top-level variables in different scope
+ @parameterDefault: 'inside';
+ @anotherVariable: 'inside';
+ @subScopeOnly: 'inside';
+ //use the mixin
+ .mixinNoParam();
+}
+#parentSelectorScope {
+ @col: white;
+ & {
+ @col: black;
+ }
+ prop: @col;
+ & {
+ @col: black;
+ }
+}
+.test-empty-mixin() {
+}
+#parentSelectorScopeMixins {
+ & {
+ .test-empty-mixin() {
+ should: never seee 1;
+ }
+ }
+ .test-empty-mixin();
+ & {
+ .test-empty-mixin() {
+ should: never seee 2;
+ }
+ }
+}
+
+=====================================output=====================================
+@x: red;
+@x: blue;
+@z: transparent;
+@mix: none;
+
+.mixin {
+ @mix: #989;
+}
+@mix: blue;
+.tiny-scope {
+ color: @mix; // #989
+ .mixin();
+}
+
+.scope1 {
+ @y: orange;
+ @z: black;
+ color: @x; // blue
+ border-color: @z; // black
+ .hidden {
+ @x: #131313;
+ }
+ .scope2 {
+ @y: red;
+ color: @x; // blue
+ .scope3 {
+ @local: white;
+ color: @y; // red
+ border-color: @z; // black
+ background-color: @local; // white
+ }
+ }
+}
+
+#namespace {
+ .scoped_mixin() {
+ @local-will-be-made-global: green;
+ .scope {
+ scoped-val: @local-will-be-made-global;
+ }
+ }
+}
+
+#namespace > .scoped_mixin();
+
+.setHeight(@h) {
+ @height: 1024px;
+}
+.useHeightInMixinCall(@h) {
+ .useHeightInMixinCall {
+ mixin-height: @h;
+ }
+}
+@mainHeight: 50%;
+.setHeight(@mainHeight);
+.heightIsSet {
+ height: @height;
+}
+.useHeightInMixinCall(@height);
+
+.importRuleset() {
+ .imported {
+ exists: true;
+ }
+}
+.importRuleset();
+.testImported {
+ .imported();
+}
+
+@parameterDefault: "top level";
+@anotherVariable: "top level";
+//mixin uses top-level variables
+.mixinNoParam(@parameter: @parameterDefault) when (@parameter = "top level") {
+ default: @parameter;
+ scope: @anotherVariable;
+ sub-scope-only: @subScopeOnly;
+}
+
+#allAreUsedHere {
+ //redefine top-level variables in different scope
+ @parameterDefault: "inside";
+ @anotherVariable: "inside";
+ @subScopeOnly: "inside";
+ //use the mixin
+ .mixinNoParam();
+}
+#parentSelectorScope {
+ @col: white;
+ & {
+ @col: black;
+ }
+ prop: @col;
+ & {
+ @col: black;
+ }
+}
+.test-empty-mixin() {
+}
+#parentSelectorScopeMixins {
+ & {
+ .test-empty-mixin() {
+ should: never seee 1;
+ }
+ }
+ .test-empty-mixin();
+ & {
+ .test-empty-mixin() {
+ should: never seee 2;
+ }
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/selectors/selectors.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Selector handling tests
+h1, h2, h3 {
+ a, p {
+ &:hover {
+ color: red;
+ }
+ }
+}
+
+#all { color: blue; }
+#the { color: blue; }
+#same { color: blue; }
+
+ul, li, div, q, blockquote, textarea {
+ margin: 0;
+}
+
+td {
+ margin: 0;
+ padding: 0;
+}
+
+td, input {
+ line-height: 1em;
+}
+
+a {
+ color: red;
+
+ &:hover { color: blue; }
+
+ div & { color: green; }
+
+ p & span { color: yellow; }
+}
+
+.foo {
+ .bar, .baz {
+ & .qux {
+ display: block;
+ }
+ .qux & {
+ display: inline;
+ }
+ .qux& {
+ display: inline-block;
+ }
+ .qux & .biz {
+ display: none;
+ }
+ }
+}
+
+.b {
+ &.c {
+ .a& {
+ color: red;
+ }
+ }
+}
+
+.b {
+ .c & {
+ &.a {
+ color: red;
+ }
+ }
+}
+
+.p {
+ .foo &.bar {
+ color: red;
+ }
+}
+
+.p {
+ .foo&.bar {
+ color: red;
+ }
+}
+
+.foo {
+ .foo + & {
+ background: amber;
+ }
+ & + & {
+ background: amber;
+ }
+}
+
+.foo, .bar {
+ & + & {
+ background: amber;
+ }
+}
+
+.foo, .bar {
+ a, b {
+ & > & {
+ background: amber;
+ }
+ }
+}
+
+.other ::fnord { color: red }
+.other::fnord { color: red }
+.other {
+ ::bnord {color: red }
+ &::bnord {color: red }
+}
+
+// selector interpolation
+@theme: blood;
+@selector: ~".@{theme}";
+@{selector} {
+ color:red;
+}
+@{selector}red {
+ color: green;
+}
+.red {
+ #@{theme}.@{theme}&.black:@{theme} {
+ color:black;
+ }
+}
+@num: 3;
+:nth-child(@{num}) {
+ selector: interpolated;
+}
+.test-rule {
+ &:nth-child(@{num}) {
+ selector: interpolated;
+ }
+ &:nth-child(odd):not(:nth-child(3)) {
+ color: #ff0000;
+ }
+}
+@prop: p;
+[prop],
+[prop=ten-percent],
+[prop|="value@{num}"],
+[prop*="val@{num}"],
+[|prop~="val@{num}"],
+[*|prop$="val@{num}"],
+[ns|prop^="val@{num}"],
+[@{prop}^="val@{num}"],
+[@{prop}] {
+ attributes: yes;
+}
+
+/**
+ * https://www.w3.org/TR/selectors-4/#attribute-case
+ */
+@pattern: less;
+a[href*="insensitive" i] {
+ color: cyan;
+}
+a[href*="cAsE" s] {
+ color: pink;
+}
+a[href*="@{pattern}" I] {
+ background-color: silver;
+}
+a[href*="@{pattern}" S] {
+ background-color: red;
+}
+
+/*
+Large comment means chunk will be emitted after } which means chunk will begin with whitespace...
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+*/
+@{selector} {
+ color: red;
+}
+.only-nested {
+ .level2 {
+ .foo:not(.tst&:hover) {
+ test: only-nested;
+ }
+ }
+}
+.nestend-and-non-nested {
+ .foo&:not(.tst&:hover) {
+ test: nestend-and-non-nested;
+ }
+}
+.selector:not(&:hover) {
+ test: global scope;
+}
+// https://github.com/less/less.js/issues/2206
+.extend-this {
+ content: '\\2661';
+}
+.first-level {
+ .second-level {
+ .active&:extend(.extend-this) { }
+ &.active2:extend(.extend-this) { }
+ }
+}
+
+// https://github.com/less/less.js/issues/4358
+.x {
+ &:is(&.a) { color: red; }
+ &:not(&.b, &.c) { color: green; }
+ &:is(&.d, &.e, &.f) { color: blue; }
+}
+
+a:is(.b, :is(.c)) {
+ color: blue;
+}
+
+a:is(.b, :is(.c), :has(div)) {
+ color: red;
+}
+
+// https://github.com/less/less.js/issues/4378
+:is(:not(:has(>.foo)), :has(>.foo.bar)) {
+ overflow: clip;
+}
+
+:matches(:not(:has(>.foo)), :has(>.foo.bar)) {
+ overflow: clip;
+}
+
+:where(:not(:has(>.foo)), :has(>.foo.bar)) {
+ overflow: clip;
+}
+
+:is(:has(>.foo + .bar), :has(>.baz ~ .qux), :not(:has(.quux))) {
+ color: blue;
+}
+
+:where(.a, .b, .c) {
+ color: red;
+}
+
+:not(.a, .b, .c) {
+ color: green;
+}
+
+:where(:is(.a, .b), :has(>.c)) {
+ color: blue;
+}
+
+:is(:where(:has(.foo)), :not(:has(.bar))) {
+ color: purple;
+}
+
+=====================================output=====================================
+// Selector handling tests
+h1,
+h2,
+h3 {
+ a,
+ p {
+ &:hover {
+ color: red;
+ }
+ }
+}
+
+#all {
+ color: blue;
+}
+#the {
+ color: blue;
+}
+#same {
+ color: blue;
+}
+
+ul,
+li,
+div,
+q,
+blockquote,
+textarea {
+ margin: 0;
+}
+
+td {
+ margin: 0;
+ padding: 0;
+}
+
+td,
+input {
+ line-height: 1em;
+}
+
+a {
+ color: red;
+
+ &:hover {
+ color: blue;
+ }
+
+ div & {
+ color: green;
+ }
+
+ p & span {
+ color: yellow;
+ }
+}
+
+.foo {
+ .bar,
+ .baz {
+ & .qux {
+ display: block;
+ }
+ .qux & {
+ display: inline;
+ }
+ .qux& {
+ display: inline-block;
+ }
+ .qux & .biz {
+ display: none;
+ }
+ }
+}
+
+.b {
+ &.c {
+ .a& {
+ color: red;
+ }
+ }
+}
+
+.b {
+ .c & {
+ &.a {
+ color: red;
+ }
+ }
+}
+
+.p {
+ .foo &.bar {
+ color: red;
+ }
+}
+
+.p {
+ .foo&.bar {
+ color: red;
+ }
+}
+
+.foo {
+ .foo + & {
+ background: amber;
+ }
+ & + & {
+ background: amber;
+ }
+}
+
+.foo,
+.bar {
+ & + & {
+ background: amber;
+ }
+}
+
+.foo,
+.bar {
+ a,
+ b {
+ & > & {
+ background: amber;
+ }
+ }
+}
+
+.other ::fnord {
+ color: red;
+}
+.other::fnord {
+ color: red;
+}
+.other {
+ ::bnord {
+ color: red;
+ }
+ &::bnord {
+ color: red;
+ }
+}
+
+// selector interpolation
+@theme: blood;
+@selector: ~".@{theme}";
+@{selector} {
+ color: red;
+}
+@{selector}red {
+ color: green;
+}
+.red {
+ #@{theme}.@{theme}&.black:@{theme} {
+ color: black;
+ }
+}
+@num: 3;
+:nth-child(@{num}) {
+ selector: interpolated;
+}
+.test-rule {
+ &:nth-child(@{num}) {
+ selector: interpolated;
+ }
+ &:nth-child(odd):not(:nth-child(3)) {
+ color: #ff0000;
+ }
+}
+@prop: p;
+[prop],
+[prop="ten-percent"],
+[prop|="value@{num}"],
+[prop*="val@{num}"],
+[|prop~="val@{num}"],
+[*|prop$="val@{num}"],
+[ns|prop^="val@{num}"],
+[@{prop}^="val@{num}"],
+[@{prop}] {
+ attributes: yes;
+}
+
+/**
+ * https://www.w3.org/TR/selectors-4/#attribute-case
+ */
+@pattern: less;
+a[href*="insensitive" i] {
+ color: cyan;
+}
+a[href*="cAsE" s] {
+ color: pink;
+}
+a[href*="@{pattern}" I] {
+ background-color: silver;
+}
+a[href*="@{pattern}" S] {
+ background-color: red;
+}
+
+/*
+Large comment means chunk will be emitted after } which means chunk will begin with whitespace...
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
+*/
+@{selector} {
+ color: red;
+}
+.only-nested {
+ .level2 {
+ .foo:not(.tst&:hover) {
+ test: only-nested;
+ }
+ }
+}
+.nestend-and-non-nested {
+ .foo&:not(.tst&:hover) {
+ test: nestend-and-non-nested;
+ }
+}
+.selector:not(&:hover) {
+ test: global scope;
+}
+// https://github.com/less/less.js/issues/2206
+.extend-this {
+ content: "\\2661";
+}
+.first-level {
+ .second-level {
+ .active&:extend(.extend-this) {
+ }
+ &.active2:extend(.extend-this) {
+ }
+ }
+}
+
+// https://github.com/less/less.js/issues/4358
+.x {
+ &:is(&.a) {
+ color: red;
+ }
+ &:not(&.b, &.c) {
+ color: green;
+ }
+ &:is(&.d, &.e, &.f) {
+ color: blue;
+ }
+}
+
+a:is(.b, :is(.c)) {
+ color: blue;
+}
+
+a:is(.b, :is(.c), :has(div)) {
+ color: red;
+}
+
+// https://github.com/less/less.js/issues/4378
+:is(:not(:has(> .foo)), :has(> .foo.bar)) {
+ overflow: clip;
+}
+
+:matches(:not(:has(> .foo)), :has(> .foo.bar)) {
+ overflow: clip;
+}
+
+:where(:not(:has(> .foo)), :has(> .foo.bar)) {
+ overflow: clip;
+}
+
+:is(:has(> .foo + .bar), :has(> .baz ~ .qux), :not(:has(.quux))) {
+ color: blue;
+}
+
+:where(.a, .b, .c) {
+ color: red;
+}
+
+:not(.a, .b, .c) {
+ color: green;
+}
+
+:where(:is(.a, .b), :has(> .c)) {
+ color: blue;
+}
+
+:is(:where(:has(.foo)), :not(:has(.bar))) {
+ color: purple;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/starting-style/starting-style.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#nav {
+ transition: background-color 3.5s;
+ background-color: gray;
+}
+
+[popover]:popover-open {
+ opacity: 1;
+ transform: scaleX(1);
+
+ @starting-style {
+ opacity: 0;
+ transform: scaleX(0);
+ }
+}
+
+#target {
+ transition: background-color 1.5s;
+ background-color: green;
+}
+
+@starting-style {
+ #target {
+ background-color: transparent;
+ }
+}
+
+#source {
+ transition: background-color 2.5s;
+ background-color: red;
+}
+
+source:first {
+ opacity: 1;
+ transform: scaleX(1);
+
+ @starting-style {
+ opacity: 0;
+ transform: scaleX(0);
+ }
+}
+
+#footer {
+ color: yellow;
+}
+
+@starting-style {
+ #footer {
+ background-color: transparent;
+ }
+}
+
+nav > [popover]:popover-open {
+ opacity: 1;
+ transform: scaleX(1);
+
+ @starting-style {
+ padding+_: 10px;
+ padding+_: 8px;
+ padding+_: 6px;
+ padding+_: 4px;
+ }
+}
+
+aside > [popover]:popover-open {
+ opacity: 1;
+ transform: scaleX(1);
+
+ @starting-style {
+ // vector math
+ each(1 2 3 4, {
+ padding+_: (@value * 10px);
+ });
+ }
+}
+
+
+
+=====================================output=====================================
+#nav {
+ transition: background-color 3.5s;
+ background-color: gray;
+}
+
+[popover]:popover-open {
+ opacity: 1;
+ transform: scaleX(1);
+
+ @starting-style {
+ opacity: 0;
+ transform: scaleX(0);
+ }
+}
+
+#target {
+ transition: background-color 1.5s;
+ background-color: green;
+}
+
+@starting-style {
+ #target {
+ background-color: transparent;
+ }
+}
+
+#source {
+ transition: background-color 2.5s;
+ background-color: red;
+}
+
+source:first {
+ opacity: 1;
+ transform: scaleX(1);
+
+ @starting-style {
+ opacity: 0;
+ transform: scaleX(0);
+ }
+}
+
+#footer {
+ color: yellow;
+}
+
+@starting-style {
+ #footer {
+ background-color: transparent;
+ }
+}
+
+nav > [popover]:popover-open {
+ opacity: 1;
+ transform: scaleX(1);
+
+ @starting-style {
+ padding+_: 10px;
+ padding+_: 8px;
+ padding+_: 6px;
+ padding+_: 4px;
+ }
+}
+
+aside > [popover]:popover-open {
+ opacity: 1;
+ transform: scaleX(1);
+
+ @starting-style {
+ // vector math
+ each(1 2 3 4, {
+ padding+_: (@value * 10px);
+ });
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/strings/strings.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// String handling and interpolation tests
+#strings {
+ background-image: url("http://son-of-a-banana.com");
+ quotes: "~" "~";
+ content: "#*%:&^,)!.(~*})";
+ empty: "";
+ brackets: "{" "}";
+ escapes: "\\"hello\\" \\\\world";
+ escapes2: "\\"llo";
+}
+#comments {
+ content: "/* hello */ // not-so-secret";
+}
+#single-quote {
+ quotes: "'" "'";
+ content: '""#!&""';
+ empty: '';
+ semi-colon: ';';
+}
+#one-line { image: url(http://tooks.com) }
+#crazy { image: url(http://), "}", url("http://}") }
+#interpolation {
+ @var: '/dev';
+ url: "http://lesscss.org@{var}/image.jpg";
+
+ @var2: 256;
+ url2: "http://lesscss.org/image-@{var2}.jpg";
+
+ @var3: #456;
+ url3: "http://lesscss.org@{var3}";
+
+ @var4: hello;
+ url4: "http://lesscss.org/@{var4}";
+
+ @var5: 54.4px;
+ url5: "http://lesscss.org/@{var5}";
+}
+
+// multiple calls with string interpolation
+
+.mix-mul (@a: green) {
+ color: ~"@{a}";
+}
+.mix-mul-class {
+ .mix-mul(blue);
+ .mix-mul(red);
+ .mix-mul(black);
+ .mix-mul(orange);
+}
+
+@test: Arial, Verdana, San-Serif;
+.watermark {
+ @family: ~"Univers, @{test}";
+ family: @family;
+}
+#iterated-interpolation {
+ @box-small: 10px;
+ @box-large: 100px;
+
+ .mixin { // both ruleset and mixin
+ width: ~"@{box-@{suffix}}";
+ weird: ~"@{box}-@{suffix}}";
+ width-str: "@{box-@{suffix}}";
+ weird-str: "@{box}-@{suffix}}";
+ @box: ~"@{box";
+ @suffix: large;
+ }
+ .interpolation-mixin {
+ .mixin(); //call the above as mixin
+ }
+}
+
+=====================================output=====================================
+// String handling and interpolation tests
+#strings {
+ background-image: url("http://son-of-a-banana.com");
+ quotes: "~""~";
+ content: "#*%:&^,)!.(~*})";
+ empty: "";
+ brackets: "{" "}";
+ escapes: '"hello" \\\\world';
+ escapes2: '"llo';
+}
+#comments {
+ content: "/* hello */ // not-so-secret";
+}
+#single-quote {
+ quotes: "'" "'";
+ content: '""#!&""';
+ empty: "";
+ semi-colon: ";";
+}
+#one-line {
+ image: url(http://tooks.com);
+}
+#crazy {
+ image: url(http://), "}", url("http://}");
+}
+#interpolation {
+ @var: "/dev";
+ url: "http://lesscss.org@{var}/image.jpg";
+
+ @var2: 256;
+ url2: "http://lesscss.org/image-@{var2}.jpg";
+
+ @var3: #456;
+ url3: "http://lesscss.org@{var3}";
+
+ @var4: hello;
+ url4: "http://lesscss.org/@{var4}";
+
+ @var5: 54.4px;
+ url5: "http://lesscss.org/@{var5}";
+}
+
+// multiple calls with string interpolation
+
+.mix-mul (@a: green) {
+ color: ~"@{a}";
+}
+.mix-mul-class {
+ .mix-mul(blue);
+ .mix-mul(red);
+ .mix-mul(black);
+ .mix-mul(orange);
+}
+
+@test: Arial, Verdana, San-Serif;
+.watermark {
+ @family: ~"Univers, @{test}";
+ family: @family;
+}
+#iterated-interpolation {
+ @box-small: 10px;
+ @box-large: 100px;
+
+ .mixin {
+ // both ruleset and mixin
+ width: ~"@{box-@{suffix}}";
+ weird: ~"@{box}-@{suffix}}";
+ width-str: "@{box-@{suffix}}";
+ weird-str: "@{box}-@{suffix}}";
+ @box: ~"@{box";
+ @suffix: large;
+ }
+ .interpolation-mixin {
+ .mixin(); //call the above as mixin
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/tailwind/tailwind.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.box {
+ @apply h-64 w-64;
+}
+
+=====================================output=====================================
+.box {
+ @apply h-64 w-64;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/urls/assets/nested-gradient-with-svg-gradient/mixin-consumer.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.mixin-consumer {
+ color: violet;
+}
+
+
+=====================================output=====================================
+.mixin-consumer {
+ color: violet;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/urls/assets/nested-gradient-with-svg-gradient/svg-gradient-mixin.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.gradient-mixin(@color) {
+ background: svg-gradient(to bottom,
+ fade(@color, 0%) 0%,
+ fade(@color, 5%) 60%,
+ fade(@color, 10%) 70%,
+ fade(@color, 15%) 73%,
+ fade(@color, 20%) 75%,
+ fade(@color, 25%) 80%,
+ fade(@color, 30%) 85%,
+ fade(@color, 35%) 88%,
+ fade(@color, 40%) 90%,
+ fade(@color, 45%) 95%,
+ fade(@color, 50%) 100%
+ );
+}
+
+=====================================output=====================================
+.gradient-mixin(@color) {
+ background: svg-gradient(
+ to bottom,
+ fade(@color, 0%) 0%,
+ fade(@color, 5%) 60%,
+ fade(@color, 10%) 70%,
+ fade(@color, 15%) 73%,
+ fade(@color, 20%) 75%,
+ fade(@color, 25%) 80%,
+ fade(@color, 30%) 85%,
+ fade(@color, 35%) 88%,
+ fade(@color, 40%) 90%,
+ fade(@color, 45%) 95%,
+ fade(@color, 50%) 100%
+ );
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/urls/import/import-and-relative-paths-test.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "../css/background.css";
+@import "import-test-d.css";
+
+@import "imports/logo";
+@import "imports/font";
+
+.unquoted-relative-path-bg() {
+ background-image: url(../../../data/image.jpg);
+}
+.quoted-relative-path-border-image() {
+ border-image: url('../../../data/image.jpg');
+}
+
+#imported-relative-path {
+ .unquoted-relative-path-bg();
+ .quoted-relative-path-border-image();
+}
+
+=====================================output=====================================
+@import "../css/background.css";
+@import "import-test-d.css";
+
+@import "imports/logo";
+@import "imports/font";
+
+.unquoted-relative-path-bg() {
+ background-image: url(../../../data/image.jpg);
+}
+.quoted-relative-path-border-image() {
+ border-image: url("../../../data/image.jpg");
+}
+
+#imported-relative-path {
+ .unquoted-relative-path-bg();
+ .quoted-relative-path-border-image();
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/urls/import/imports/font.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@font-face {
+ font-family: xecret;
+ src: url('../assets/xecret.ttf');
+}
+
+#secret {
+ font-family: xecret, sans-serif;
+}
+
+=====================================output=====================================
+@font-face {
+ font-family: xecret;
+ src: url("../assets/xecret.ttf");
+}
+
+#secret {
+ font-family: xecret, sans-serif;
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/urls/import/imports/logo.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+#logo {
+ width: 100px;
+ height: 100px;
+ background: url('../assets/logo.png');
+ background: url("#inline-svg");
+}
+
+=====================================output=====================================
+#logo {
+ width: 100px;
+ height: 100px;
+ background: url("../assets/logo.png");
+ background: url("#inline-svg");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/urls/nested-gradient-with-svg-gradient/mixin-consumer.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "svg-gradient-mixin.less";
+
+.gray-gradient {
+ .gradient-mixin(#999);
+}
+
+=====================================output=====================================
+@import "svg-gradient-mixin.less";
+
+.gray-gradient {
+ .gradient-mixin(#999);
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/urls/nested-gradient-with-svg-gradient/svg-gradient-mixin.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+.gradient-mixin(@color) {
+ background: svg-gradient(to bottom,
+ fade(@color, 0%) 0%,
+ fade(@color, 5%) 60%,
+ fade(@color, 10%) 70%,
+ fade(@color, 15%) 73%,
+ fade(@color, 20%) 75%,
+ fade(@color, 25%) 80%,
+ fade(@color, 30%) 85%,
+ fade(@color, 35%) 88%,
+ fade(@color, 40%) 90%,
+ fade(@color, 45%) 95%,
+ fade(@color, 50%) 100%
+ );
+}
+
+=====================================output=====================================
+.gradient-mixin(@color) {
+ background: svg-gradient(
+ to bottom,
+ fade(@color, 0%) 0%,
+ fade(@color, 5%) 60%,
+ fade(@color, 10%) 70%,
+ fade(@color, 15%) 73%,
+ fade(@color, 20%) 75%,
+ fade(@color, 25%) 80%,
+ fade(@color, 30%) 85%,
+ fade(@color, 35%) 88%,
+ fade(@color, 40%) 90%,
+ fade(@color, 45%) 95%,
+ fade(@color, 50%) 100%
+ );
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/urls/urls.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@import "nested-gradient-with-svg-gradient/mixin-consumer.less";
+
+@font-face {
+ src: url("/fonts/garamond-pro.ttf");
+ src: local(Futura-Medium),
+ url(fonts.svg#MyGeometricModern) format("svg");
+ not-a-comment: url(//z);
+}
+#shorthands {
+ background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
+ background: url("img.jpg") center / 100px;
+ background: #fff url(image.png) center / 1px 100px repeat-x scroll content-box padding-box;
+}
+#misc {
+ background-image: url(images/image.jpg);
+}
+#data-uri {
+ background: url(data:image/png;charset=utf-8;base64,
+ kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
+ k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
+ kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
+ background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
+ background-image: url(http://fonts.googleapis.com/css?family=\\"Rokkitt\\":\\(400\\),700);
+ background-image: url("http://fonts.googleapis.com/css?family=\\"Rokkitt\\":\\(400\\),700");
+}
+
+#svg-data-uri {
+ background: transparent url('data:image/svg+xml, ');
+}
+
+.comma-delimited {
+ background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg);
+}
+.values {
+ @a: 'Trebuchet';
+ url: url(@a);
+}
+
+@import "import/import-and-relative-paths-test";
+
+#relative-url-import {
+ .unquoted-relative-path-bg();
+ .quoted-relative-path-border-image();
+}
+
+#data-uri {
+ uri: data-uri('image/jpeg;base64', '../../data/image.jpg');
+ @var: replace('../../data/replace.jpg', "replace", "image");
+ background-image: data-uri(@var), data-uri(replace('../../data/image.filext', "filext", "jpg"));
+
+ uri-fragment: data-uri('image/jpeg;base64', '../../data/image.jpg#fragment');
+}
+
+#data-uri-guess {
+ uri: data-uri('../../data/image.jpg');
+}
+
+#data-uri-ascii {
+ uri-1: data-uri('text/html', '../../data/page.html');
+ uri-2: data-uri('../../data/page.html');
+}
+
+#file-functions {
+ svg-not-base-64: data-uri('../../data/image.svg');
+ size: image-size('../../data/data-uri-fail.png');
+ width: image-width('../../data/data-uri-fail.png');
+ height: image-height('../../data/data-uri-fail.png');
+}
+.add_an_import(@file_to_import) {
+@import "@{file_to_import}";
+}
+
+.add_an_import("file.css");
+
+#svg-functions {
+ background-image: svg-gradient(to bottom, black, white);
+ background-image: svg-gradient(to bottom, black, orange 3%, white);
+ @green_5: green 5%;
+ @orange_percentage: 3%;
+ @orange_color: orange;
+ background-image: svg-gradient(to bottom, (mix(black, white) + #444) 1%, @orange_color @orange_percentage, ((@green_5)), white 95%);
+}
+//it should work also inside @font-face #2035
+@font-face {
+ font-family: 'MyWebFont';
+ src: url(webfont.eot);
+ src+: url('webfont.eot?#iefix');
+ src+_: format('embedded-opentype');
+ src+: url('webfont.woff') format('woff');
+ src+: format('truetype');
+ src+_: url('webfont.ttf');
+ src+: url('webfont.svg#svgFontName') format('svg');
+}
+
+=====================================output=====================================
+@import "nested-gradient-with-svg-gradient/mixin-consumer.less";
+
+@font-face {
+ src: url("/fonts/garamond-pro.ttf");
+ src:
+ local(Futura-Medium),
+ url(fonts.svg#MyGeometricModern) format("svg");
+ not-a-comment: url(//z);
+}
+#shorthands {
+ background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
+ background: url("img.jpg") center / 100px;
+ background: #fff url(image.png) center / 1px 100px repeat-x scroll content-box
+ padding-box;
+}
+#misc {
+ background-image: url(images/image.jpg);
+}
+#data-uri {
+ background: url(data:image/png;charset=utf-8;base64,
+ kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
+ k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
+ kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
+ background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
+ background-image: url(http://fonts.googleapis.com/css?family=\\"Rokkitt\\":\\(400\\),700);
+ background-image: url('http://fonts.googleapis.com/css?family="Rokkitt":\\(400\\),700');
+}
+
+#svg-data-uri {
+ background: transparent
+ url('data:image/svg+xml, ');
+}
+
+.comma-delimited {
+ background:
+ url(bg.jpg) no-repeat,
+ url(bg.png) repeat-x top left,
+ url(bg);
+}
+.values {
+ @a: "Trebuchet";
+ url: url(@a);
+}
+
+@import "import/import-and-relative-paths-test";
+
+#relative-url-import {
+ .unquoted-relative-path-bg();
+ .quoted-relative-path-border-image();
+}
+
+#data-uri {
+ uri: data-uri("image/jpeg;base64", "../../data/image.jpg");
+ @var: replace("../../data/replace.jpg", "replace", "image");
+ background-image:
+ data-uri(@var),
+ data-uri(replace("../../data/image.filext", "filext", "jpg"));
+
+ uri-fragment: data-uri("image/jpeg;base64", "../../data/image.jpg#fragment");
+}
+
+#data-uri-guess {
+ uri: data-uri("../../data/image.jpg");
+}
+
+#data-uri-ascii {
+ uri-1: data-uri("text/html", "../../data/page.html");
+ uri-2: data-uri("../../data/page.html");
+}
+
+#file-functions {
+ svg-not-base-64: data-uri("../../data/image.svg");
+ size: image-size("../../data/data-uri-fail.png");
+ width: image-width("../../data/data-uri-fail.png");
+ height: image-height("../../data/data-uri-fail.png");
+}
+.add_an_import(@file_to_import) {
+ @import "@{file_to_import}";
+}
+
+.add_an_import("file.css");
+
+#svg-functions {
+ background-image: svg-gradient(to bottom, black, white);
+ background-image: svg-gradient(to bottom, black, orange 3%, white);
+ @green_5: green 5%;
+ @orange_percentage: 3%;
+ @orange_color: orange;
+ background-image: svg-gradient(
+ to bottom,
+ (mix(black, white) + #444) 1%,
+ @orange_color @orange_percentage,
+ ((@green_5)),
+ white 95%
+ );
+}
+//it should work also inside @font-face #2035
+@font-face {
+ font-family: "MyWebFont";
+ src: url(webfont.eot);
+ src+: url("webfont.eot?#iefix");
+ src+_: format("embedded-opentype");
+ src+: url("webfont.woff") format("woff");
+ src+: format("truetype");
+ src+_: url("webfont.ttf");
+ src+: url("webfont.svg#svgFontName") format("svg");
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/variables/variables.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@a: 2;
+@x: (@a * @a);
+@y: (@x + 1);
+@z: (@x * 2 + @y);
+@var: -1;
+@b: @a * 10;
+@c: #888;
+@fonts: "Trebuchet MS", Verdana, sans-serif;
+@f: @fonts;
+@quotes: "~" "~";
+@q: @quotes;
+@onePixel: 1px;
+
+.variables-basic {
+ width: (@z + 1cm);
+ height: (@b + @x + 0px);
+ color: @c;
+ font-family: @f;
+ quotes: @q;
+}
+
+.variable-dash {
+ @jumbotron-padding: 30px;
+ padding: @jumbotron-padding (@jumbotron-padding/2);
+}
+
+.variable-redefinition {
+ @var: 0;
+ zero: @var;
+}
+
+.variable-scope {
+ @var: 4;
+ @var: 2;
+ three: @var;
+ @var: 3;
+}
+
+.variable-important {
+ @important-var: @c !important;
+ @important-var-two: @a !important;
+ minus-one: @var;
+ @a: 'Trebuchet';
+ @multi: 'A', B, C;
+ font-family: @a, @a, @a;
+ color: @c !important;
+ same-color: @important-var;
+ same-again: @important-var !important;
+ multi-important: @important-var @important-var, @important-var-two;
+ multi: something @multi, @a;
+}
+
+.variable-names-quoted {
+ @var: 'hello';
+ @name: 'var';
+ name: @@name;
+}
+
+.variable-names-unquoted {
+ @var: 'hello';
+ @name: var;
+ name: @@name;
+}
+
+.variable-names-color-keyword {
+ @red: 'hello';
+ @name: red;
+ name: @@name;
+}
+
+.variable-units {
+ width: @onePixel;
+ same-unit-as-previously: (@onePixel / @onePixel);
+ square-pixel-divided: (@onePixel * @onePixel / @onePixel);
+ odd-unit: unit((@onePixel * 4em / 2cm));
+}
+
+.variable-pollution {
+ @a: 'no-pollution';
+ a: @a;
+}
+
+.polluteMixin() {
+ @a: 'pollution';
+}
+
+
+
+// https://github.com/less/less.js/issues/2462
+@type: 5_large;
+.icon-@{type} {
+ background-image: ~"url(/img/icon/@{type}.svg)";
+}
+
+=====================================output=====================================
+@a: 2;
+@x: (@a * @a);
+@y: (@x + 1);
+@z: (@x * 2 + @y);
+@var: -1;
+@b: @a * 10;
+@c: #888;
+@fonts: "Trebuchet MS", Verdana, sans-serif;
+@f: @fonts;
+@quotes: "~""~";
+@q: @quotes;
+@onePixel: 1px;
+
+.variables-basic {
+ width: (@z + 1cm);
+ height: (@b + @x + 0px);
+ color: @c;
+ font-family: @f;
+ quotes: @q;
+}
+
+.variable-dash {
+ @jumbotron-padding: 30px;
+ padding: @jumbotron-padding (@jumbotron-padding / 2);
+}
+
+.variable-redefinition {
+ @var: 0;
+ zero: @var;
+}
+
+.variable-scope {
+ @var: 4;
+ @var: 2;
+ three: @var;
+ @var: 3;
+}
+
+.variable-important {
+ @important-var: @c !important;
+ @important-var-two: @a !important;
+ minus-one: @var;
+ @a: "Trebuchet";
+ @multi: "A", B, C;
+ font-family: @a, @a, @a;
+ color: @c !important;
+ same-color: @important-var;
+ same-again: @important-var !important;
+ multi-important:
+ @important-var @important-var,
+ @important-var-two;
+ multi:
+ something @multi,
+ @a;
+}
+
+.variable-names-quoted {
+ @var: "hello";
+ @name: "var";
+ name: @@name;
+}
+
+.variable-names-unquoted {
+ @var: "hello";
+ @name: var;
+ name: @@name;
+}
+
+.variable-names-color-keyword {
+ @red: "hello";
+ @name: red;
+ name: @@name;
+}
+
+.variable-units {
+ width: @onePixel;
+ same-unit-as-previously: (@onePixel / @onePixel);
+ square-pixel-divided: (@onePixel * @onePixel / @onePixel);
+ odd-unit: unit((@onePixel * 4em / 2cm));
+}
+
+.variable-pollution {
+ @a: "no-pollution";
+ a: @a;
+}
+
+.polluteMixin() {
+ @a: "pollution";
+}
+
+// https://github.com/less/less.js/issues/2462
+@type: 5_large;
+.icon-@{type} {
+ background-image: ~"url(/img/icon/@{type}.svg)";
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/variables-in-at-rules/variables-in-at-rules.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+@Eight: 8;
+@charset "UTF-@{Eight}";
+
+@ns: less;
+@namespace @ns "http://lesscss.org";
+
+@name: enlarger;
+@keyframes @name {
+ from {font-size: 12px;}
+ to {font-size: 15px;}
+}
+
+.m(reducer);
+.m(@name) {
+ @-webkit-keyframes @name {
+ from {font-size: 13px;}
+ to {font-size: 10px;}
+ }
+}
+
+=====================================output=====================================
+@Eight: 8;
+@charset "UTF-@{Eight}";
+
+@ns: less;
+@namespace @ns "http://lesscss.org";
+
+@name: enlarger;
+@keyframes @name {
+ from {
+ font-size: 12px;
+ }
+ to {
+ font-size: 15px;
+ }
+}
+
+.m(reducer);
+.m(@name) {
+ @-webkit-keyframes @name {
+ from {
+ font-size: 13px;
+ }
+ to {
+ font-size: 10px;
+ }
+ }
+}
+
+================================================================================
+`;
+
+exports[`snippet: tests-unit/whitespace/whitespace.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+ printWidth: 80 (default) |
+=====================================input======================================
+// Whitespace handling tests
+
+
+.whitespace
+ { color: white; }
+
+.whitespace
+{
+ color: white;
+}
+ .whitespace
+{ color: white; }
+
+.whitespace{color:white;}
+.whitespace { color : white ; }
+
+.white,
+.space,
+.mania
+{ color: white; }
+
+.no-semi-column { color: white }
+.no-semi-column {
+ color: white;
+ white-space: pre
+}
+.no-semi-column {border: 2px solid white}
+.newlines {
+ background: the,
+ great,
+ wall;
+ border: 2px
+ solid
+ black;
+}
+.empty {
+
+}
+.sel
+.newline_ws .tab_ws {
+color:
+white;
+background-position: 45
+-23;
+}
+
+=====================================output=====================================
+// Whitespace handling tests
+
+.whitespace {
+ color: white;
+}
+
+.whitespace {
+ color: white;
+}
+.whitespace {
+ color: white;
+}
+
+.whitespace {
+ color: white;
+}
+.whitespace {
+ color: white;
+}
+
+.white,
+.space,
+.mania {
+ color: white;
+}
+
+.no-semi-column {
+ color: white;
+}
+.no-semi-column {
+ color: white;
+ white-space: pre;
+}
+.no-semi-column {
+ border: 2px solid white;
+}
+.newlines {
+ background: the, great, wall;
+ border: 2px solid black;
+}
+.empty {
+}
+.sel .newline_ws .tab_ws {
+ color: white;
+ background-position: 45 -23;
+}
+
+================================================================================
+`;
diff --git a/tests/format/less/less-test-suite/format.test.js b/tests/format/less/less-test-suite/format.test.js
new file mode 100644
index 000000000..6b4a4652e
--- /dev/null
+++ b/tests/format/less/less-test-suite/format.test.js
@@ -0,0 +1,39 @@
+import lessTestSuite from "less-test-suite";
+
+/* spell-checker: disable */
+const SKIP = new Set(["tests-unit/import/import/invalid-css.less"]);
+const BUGS = new Set([
+ // Can't parse
+ "tests-unit/variables/variable-advanced.less",
+ "tests-unit/property-accessors/property-accessors.less",
+ "tests-unit/plugin/plugin.less",
+ "tests-unit/permissive-parse/permissive-parse.less",
+ "tests-unit/parser-property-interp/parser-property-interp.less",
+ "tests-unit/mixins-interpolated/mixins-interpolated.less",
+ "tests-unit/import/import/invalid-css.less",
+ "tests-unit/functions/functions.less",
+ "tests-unit/extract-and-length/extract-and-length.less",
+ "tests-unit/css-escapes/css-escapes.less",
+ "tests-unit/comments/comments.less",
+
+ // Ast changed or unstable
+ "tests-unit/property-name-interp/property-name-interp.less",
+ "tests-unit/extend-chaining/extend-chaining.less",
+]);
+/* spell-checker: enable */
+
+const testCases = lessTestSuite.filter(
+ ({ error, name }) => !error && !SKIP.has(name) && !BUGS.has(name),
+);
+
+runFormatTest(
+ {
+ importMeta: import.meta,
+ snippets: testCases.map(({ name, input }) => ({
+ name,
+ filename: name,
+ code: input,
+ })),
+ },
+ ["less"],
+);
diff --git a/yarn.lock b/yarn.lock
index 0936f9c1c..86059f3cd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6392,6 +6392,13 @@ __metadata:
languageName: node
linkType: hard
+"less-test-suite@npm:0.0.1":
+ version: 0.0.1
+ resolution: "less-test-suite@npm:0.0.1"
+ checksum: 10/89b750e91ab3d8309d130f240f6e9583b489265080989dc3398a66f45cf53faa7ebb29240746fb3820aa8caa4d9420601a19af3bb09eff1452a3dcdbba03363a
+ languageName: node
+ linkType: hard
+
"leven@npm:4.1.0, leven@npm:^4.1.0":
version: 4.1.0
resolution: "leven@npm:4.1.0"
@@ -8018,6 +8025,7 @@ __metadata:
json5: "npm:2.2.3"
jsx-test-suite: "npm:0.0.2"
knip: "npm:6.21.0"
+ less-test-suite: "npm:0.0.1"
leven: "npm:4.1.0"
linguist-languages: "npm:9.4.0"
magic-string: "npm:0.30.21"