Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions lib/LessParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,23 @@ module.exports = class LessParser extends Parser {
}
}

// Test for the mixin definition pattern
// .mixin-name() {
// .mixin-name(@param1; @param2) {
// .mixin-name(@param1; @param2) when (@condition) {
// .mixin-name(@param1; @param2) when (@condition) and (@condition) {
if (tokens[0][0] === 'word' && isMixinToken(tokens[0])) {
const bracketsIndex = tokens.findIndex((t) => t[0] === 'brackets');
const firstParenIndex = tokens.findIndex((t) => t[0] === '(');
const spaceIndex = tokens.findIndex((t) => t[0] === 'space');

if ((spaceIndex === 1 && (firstParenIndex === 2 || bracketsIndex === 2)) ||
firstParenIndex === 1 || bracketsIndex === 1) {
this.mixin(tokens);
return;
}
}

super.rule(tokens);

// #123: add `extend` decorator to nodes
Expand Down
8 changes: 6 additions & 2 deletions test/parser/interpolation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ test('parses mixin interpolation', (t) => {
const less = '.browser-prefix(@prop, @args) {\n @{prop}: @args;\n}';
const root = parse(less);

t.is(root.first.selector, '.browser-prefix(@prop, @args)');
t.is(root.first.type, 'atrule');
t.is(root.first.name, 'browser-prefix');
t.is(root.first.params, '(@prop, @args)');
t.is(root.first.first.prop, '@{prop}');
t.is(root.first.first.value, '@args');
});
Expand Down Expand Up @@ -77,7 +79,9 @@ test('parses escaping', (t) => {

const root = parse(code);
const { first } = root;
t.is(first.selector, '.m_transition (...)');
t.is(first.type, 'atrule');
t.is(first.name, 'm_transition');
t.is(first.params, '(...)');
t.is(first.first.name, 'props');
t.is(first.first.value, '~`"@{arguments}".replace(/[[]]/g, \'\')`');
t.is(root.nodes[1].first.selector, '& ~ .stock-bar__content .stock-bar__control_pause');
Expand Down
58 changes: 58 additions & 0 deletions test/parser/mixins-definition.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const test = require('ava');

const { parse } = require('../../lib');

test('with empty params', async (t) => {
const less = '.foo() { color: red; }';
const { first } = parse(less);

t.is(first.type, 'atrule');
t.is(first.name, 'foo');
t.is(first.params, '()');

console.log(first);
});

test('with one param', async (t) => {
const less = '.foo(@_color: red) { color: @_color; }';
const { first } = parse(less);

t.is(first.type, 'atrule');
t.is(first.name, 'foo');
t.is(first.params, '(@_color: red)');
});

test('with two params', async (t) => {
const less = '.foo(@_color: red; @_width: 100px) { color: @_color; width: @_width; }';
const { first } = parse(less);

t.is(first.type, 'atrule');
t.is(first.name, 'foo');
t.is(first.params, '(@_color: red; @_width: 100px)');
});

test('with params and when condition', async (t) => {
const less = '.foo(@_color: red; @_width: 100px) when (@mode = huge) { color: @_color; width: @_width; }';
const { first } = parse(less);

t.is(first.type, 'atrule');
t.is(first.name, 'foo');
t.is(first.params, '(@_color: red; @_width: 100px) when (@mode = huge)');
});

test('with params and 2x when condition', async (t) => {
const less = '.foo(@_color: red; @_width: 100px) when (@mode = huge) and (@mode = small) { color: @_color; width: @_width; }';
const { first } = parse(less);

t.is(first.type, 'atrule');
t.is(first.name, 'foo');
t.is(first.params, '(@_color: red; @_width: 100px) when (@mode = huge) and (@mode = small)');
});

test('avoids parsing pseudos as mixins', async (t) => {
const less = '.foo:is(input) { color: red; }';
const { first } = parse(less);

t.is(first.type, 'rule');
t.is(first.selector, '.foo:is(input)');
});
15 changes: 11 additions & 4 deletions test/parser/mixins.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ test('basic', (t) => {
const root = parse(less);
const { first } = root;

t.is(first.type, 'rule');
t.is(first.selector, selector);
t.is(first.type, 'atrule');
t.is(first.name, 'foo');
t.is(first.params, params);
t.is(first.first.prop, 'border');
t.is(first.first.value, 'baz');
t.is(nodeToString(root), less);
Expand Down Expand Up @@ -128,8 +129,14 @@ test('guarded namespaces', (t) => {
const root = parse(less);
const { first } = root;

t.is(first.first.selector, '.mixin()');
t.is(first.next().first.selector, '.mixin() when (@mode=huge)');
t.is(first.first.type, 'atrule');
t.is(first.first.name, 'mixin');
t.is(first.first.params, '()');

const next = first.next();
t.is(next.first.type, 'atrule');
t.is(next.first.name, 'mixin');
t.is(next.first.params, '() when (@mode=huge)');
t.is(nodeToString(root), less);
});

Expand Down