diff --git a/packages/less/lib/less/parser/parser.js b/packages/less/lib/less/parser/parser.js index 6a439fb89..4053d279d 100644 --- a/packages/less/lib/less/parser/parser.js +++ b/packages/less/lib/less/parser/parser.js @@ -1875,15 +1875,21 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) { let p; let rangeP; let spacing = false; + const cssKeyword = () => { + const k = parserInput.$re(/^(?:--|-?(?:[_a-zA-Z0-9]|[^\0-\x7F]|\\[0-9a-fA-F]{1,6}\s?|\\[^\n\r\f0-9a-fA-F]))(?:[-_a-zA-Z0-9]|[^\0-\x7F]|\\[0-9a-fA-F]{1,6}\s?|\\[^\n\r\f0-9a-fA-F])*/); + if (k) { + return tree.Color.fromKeyword(k) || new(tree.Keyword)(k); + } + }; parserInput.save(); do { parserInput.save(); - if (parserInput.$re(/^[0-9a-z-]*\s+\(/)) { + if (parserInput.$re(/^(?:--|-?(?:[_a-zA-Z0-9]|[^\0-\x7F]|\\[0-9a-fA-F]{1,6}\s?|\\[^\n\r\f0-9a-fA-F]))(?:[-_a-zA-Z0-9]|[^\0-\x7F]|\\[0-9a-fA-F]{1,6}\s?|\\[^\n\r\f0-9a-fA-F])*\s+\(/)) { spacing = true; } parserInput.restore(); - e = entities.declarationCall.bind(this)() || entities.keyword() || entities.variable() || entities.mixinLookup() + e = entities.declarationCall.bind(this)() || cssKeyword() || entities.keyword() || entities.variable() || entities.mixinLookup() if (e) { nodes.push(e); if (e.type === 'Variable' || @@ -1920,7 +1926,11 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) { } if (closed) { if (p && !e) { - nodes.push(new (tree.Paren)(new (tree.QueryInParens)(p.op, p.lvalue, p.rvalue, rangeP ? rangeP.op : null, rangeP ? rangeP.rvalue : null, p._index))); + const paren = new (tree.Paren)(new (tree.QueryInParens)(p.op, p.lvalue, p.rvalue, rangeP ? rangeP.op : null, rangeP ? rangeP.rvalue : null, p._index)); + if (!spacing) { + paren.noSpacing = true; + } + nodes.push(paren); e = p; } else if (p && e) { nodes.push(new (tree.Paren)(new (tree.Declaration)(p, e, null, null, parserInput.i + currentIndex, fileInfo, true))); @@ -1929,7 +1939,11 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) { } spacing = false; } else if (e) { - nodes.push(new(tree.Paren)(e)); + const paren = new(tree.Paren)(e); + if (!spacing) { + paren.noSpacing = true; + } + nodes.push(paren); spacing = false; } else { error('badly formed media feature definition'); @@ -1942,7 +1956,14 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) { parserInput.forget(); if (nodes.length > 0) { - return new(tree.Expression)(nodes); + const expression = new(tree.Expression)(nodes); + if (nodes.length === 2 + && (nodes[0].type === 'Keyword' || nodes[0].type === 'Variable') + && nodes[1].type === 'Paren' + && nodes[1].noSpacing) { + expression.noSpacing = true; + } + return expression; } }, diff --git a/packages/test-data/tests-unit/container/container.css b/packages/test-data/tests-unit/container/container.css index dd9673c7e..f13b3ae99 100644 --- a/packages/test-data/tests-unit/container/container.css +++ b/packages/test-data/tests-unit/container/container.css @@ -130,6 +130,46 @@ 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; @@ -268,6 +308,11 @@ font-size: 75%; } } +@container sidebar (min-width: 400px), scroll-state(stuck: top) { + #sticky-child { + font-size: 80%; + } +} @container foo (min-width: 400px) { #sticky-child { font-size: 75%; diff --git a/packages/test-data/tests-unit/container/container.less b/packages/test-data/tests-unit/container/container.less index 013a9e243..4eeb8958c 100644 --- a/packages/test-data/tests-unit/container/container.less +++ b/packages/test-data/tests-unit/container/container.less @@ -159,6 +159,54 @@ } } +@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; @@ -319,6 +367,12 @@ } } +@container sidebar (min-width: 400px), scroll-state(stuck: top) { + #sticky-child { + font-size: 80%; + } +} + @varfoo: foo; @threshold: 400px; @container @varfoo (min-width: @threshold) {