Giter Site home page Giter Site logo

postcss-less's Introduction

postcss-less

tests cover size

A PostCSS Syntax for parsing LESS

Note: This module requires Node v6.14.4+. poscss-less is not a LESS compiler. For compiling LESS, please use the official toolset for LESS.

Install

Using npm:

npm install postcss-less --save-dev

Please consider becoming a patron if you find this module useful.

Usage

The most common use of postcss-less is for applying PostCSS transformations directly to LESS source. eg. ia theme written in LESS which uses Autoprefixer to add appropriate vendor prefixes.

const syntax = require('postcss-less');
postcss(plugins)
  .process(lessText, { syntax: syntax })
  .then(function (result) {
    result.content // LESS with transformations
});

LESS Specific Parsing

@import

Parsing of LESS-specific @import statements and options are supported.

@import (option) 'file.less';

The AST will contain an AtRule node with:

  • an import: true property
  • a filename: <String> property containing the imported filename
  • an options: <String> property containing any import options specified

Inline Comments

Parsing of single-line comments in CSS is supported.

:root {
    // Main theme color
    --color: red;
}

The AST will contain a Comment node with an inline: true property.

Mixins

Parsing of LESS mixins is supported.

.my-mixin {
  color: black;
}

The AST will contain an AtRule node with a mixin: true property.

!important

Mixins that declare !important will contain an important: true property on their respective node.

Variables

Parsing of LESS variables is supported.

@link-color: #428bca;

The AST will contain an AtRule node with a variable: true property.

Note: LESS variables are strictly parsed - a colon (:) must immediately follow a variable name.

Stringifying

To process LESS code without PostCSS transformations, custom stringifier should be provided.

const postcss = require('postcss');
const syntax = require('postcss-less');

const less = `
    // inline comment

    .container {
        .mixin-1();
        .mixin-2;
        .mixin-3 (@width: 100px) {
            width: @width;
        }
    }

    .rotation(@deg:5deg){
      .transform(rotate(@deg));
    }
`;

const result = await postcss().process(less, { syntax });

 // will contain the value of `less`
const { content } = result;

Use Cases

  • Lint LESS code with 3rd-party plugins.
  • Apply PostCSS transformations (such as Autoprefixer) directly to the LESS source code

Meta

CONTRIBUTING

LICENSE (MIT)

postcss-less's People

Contributors

davidyorr avatar e-cloud avatar garyanikin avatar hauptmanneck avatar heychenfq avatar jeddy3 avatar jeffal avatar jwilsson avatar kinfoo avatar life777 avatar ludofischer avatar mattlyons0 avatar nwalters512 avatar orottier avatar paazmaya avatar shellscape avatar sosukesuzuki avatar vilemj-viclick avatar webschik avatar ymichael avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

postcss-less's Issues

incorrect parse mixin

.test4 {
  .mixin();
  background: red;
}

We get (Rule mixin):

raws: { before: '\n', between: '', after: '' },

Correctly:

raws: { before: '\n', between: '', semicolon: true}

And next decl have also incorrect values

raws: { before: ';\n', between: ':' }

Correctly:

raws: { before: '\n', between: ':' }

Ref: stylelint/stylelint#1409

Selector contains "!important" when there is no whitespace following a mixin

  • Node Version: 6.11.1
  • NPM Version: 5.3.0
  • postcss-less Version: 1.1.0

LESS

a {
    .mixin(val)!important;
}

JavaScript

console.dir(require("postcss-less").parse('a{.mixin(val)!important;}'), {colors: true, depth: null})

Expected Behavior

{
            selector: '.mixin(val)',
            params: '(val) !important',
            mixin: true,
            important: true
}

Actual Behavior

{
            selector: '.mixin(val)!important',
            params: '(val)!important',
            mixin: true,
            important: true
}

Going upstream from prettier/prettier#2880

Extra semicolon produced by mixins

Tied to stylelint/stylelint#1389

Given the following:

.foo { .thing(); }

I end up with a rule node that erroneously has a ; in raws.after. The rule node that is produced when rendered to a string (node.toString()) looks like this: .foo { .thing(){}; }. Looking at that, it's clear that the semicolon is superfluous.

It doesn't work

I've trying to test this parser, but it doesn't work. PostCSS doesn't understand it:

$ node index.js
/Users/aleks/projects/postcss-less-bug/node_modules/postcss/lib/lazy-result.js:58
            if (parser.parse) parser = parser.parse;
                      ^

TypeError: Cannot read property 'parse' of undefined
    at new LazyResult (/Users/aleks/projects/postcss-less-bug/node_modules/postcss/lib/lazy-result.js:58:23)
    at Processor.process (/Users/aleks/projects/postcss-less-bug/node_modules/postcss/lib/processor.js:34:16)
    at Object.<anonymous> (/Users/aleks/projects/postcss-less-bug/index.js:5:11)
    at Module._compile (module.js:398:26)
    at Object.Module._extensions..js (module.js:405:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)
    at Function.Module.runMain (module.js:430:10)
    at startup (node.js:141:18)
    at node.js:980:3

I've created test case for this: https://github.com/hudochenkov/postcss-less-bug

Distinguish between multiline and single line comments

(I'll say first and foremost that I applaud your enthusiasm for this project. I've back-pedaled on my choice to pursue a separate lib; it was too reactionary.)

Consider the following input: /* Hello World */

And the following node that corresponds to the input:

Comment {
  raws: { before: '', inline: true, left: ' ', right: '' },
  type: 'comment',
  parent: 
   Root {
     raws: { semicolon: false, after: '' },
     type: 'root',
     nodes: [ [Circular] ],
     source: { input: [Object], start: [Object] },
     lastEach: 1,
     indexes: {} },
  source: 
   { start: { line: 1, column: 1 },
     input: Input { css: '/* Hello world */', id: '<input css 2>' },
     end: { line: 1, column: 14 } },
  text: 'Hello world' }

It would be very helpful to be able to distinguish between a multiline comment (one that starts with /*) and a single line comment (//). I'd imagine this is something that stylelint could make use of as well, to determine if a particular comment type is allowed or not.

Problems on parsing root mixins with parameters with Stylelint

I managed to scope this problem out to a compatibility issue with Stylelint. This is the code:

.foo() {
    color: #fff;
}

This works with Stylelint. However if I use parameters:

.foo(@bar) {
    color: @bar;
}

This immediately returns an error:

TypeError: this[node.type] is not a function
    at Stringifier.stringify (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/stringifier.js:33:24)
    at stringify (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/stringify.js:14:9)
    at AtRule.toString (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/node.js:97:9)
    at Array.toString (native)
    at Stringifier.atrule (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/stringifier.js:74:35)
    at Stringifier.stringify (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/stringifier.js:33:24)
    at Stringifier.body (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/stringifier.js:93:18)
    at Stringifier.root (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/stringifier.js:37:14)
    at Stringifier.stringify (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/stringifier.js:33:24)
    at stringify (/Volumes/g/repos/gaf-stylelint/node_modules/postcss/lib/stringify.js:14:9)

I've tested this on both gulp-postcss and PostCSS's Node API and both returns the same thing when Stylelint is added to the mix. mixinsAsAtRules and innerMixinsAsRules is already set to true.

Also if you change the mixin from a root mixin to be scoped inside another block, the error goes away.

Incorrect parsing selectors starting `.` and containing parenthesis `()`

  • Node Version: 7.10.0
  • NPM Version: 4.2.0
  • postcss-less Version: 0.16.1

If you have a large amount of code to share which demonstrates the problem you're experiencing, please provide a link to your
repository rather than pasting code. Otherwise, please paste relevant short snippets below.

LESS

.foo:not(.a) {}

JavaScript

import postCssLess from 'postcss-less';
const less = `.foo:not(.a) {}`;
const root = postCssLess.parse(less);

Expected Behavior

rule.parent.nodes[0].params should be not defined (property should be not exists)

Actual Behavior

rule.parent.nodes[0].params is true

How can we reproduce the behavior?

Use example in javascript section.

Issue was created based on stylelint/stylelint#1741

LESS syntax full support

After some discussions 1, 2 I've decided to remove LESS-specific hacks from postcss-less and support full-syntax tree.

less mixins don't work

Hi! I've tried an example from Readme.md and it doesn't work:

import postCssLess from 'postcss-less';
const less = `
    .class2 {
        &:extend(.class1);
        .mixin-name(@param1, @param2);
    }
`;
const root = postCssLess.parse(less); // CssSyntaxError: <css input>:4:9: Unknown word

Seems like postcss-less doesn't support less mixins despite the description in Readme.md. Am I missing something?

Thanks in advance.

Rule with pseudo selector has false params property

We've been struggling with some baddish logic in postcss-less while analyzing rules. Given this rule:

.test1,
.test2:not(.test3) {
    width: 100%;
}

The resulting node looks like this:

Rule {
  raws: 
   { before: '',
     between: ' ',
     params: { value: '(.test3)', raw: '(.test3) ' },
     semicolon: true,
     after: '\n' },
  type: 'rule',
  nodes: 
   [ Declaration {
       raws: [Object],
       type: 'decl',
       parent: [Circular],
       source: [Object],
       prop: 'width',
       value: '100%' } ],
  parent: 
   Root { ... },
  source: 
   { start: { line: 1, column: 1 },
     input: 
      Input {
        css: '.test1,\n.test2:not(.test3) {\n    width: 100%;\n}\n',
        id: '<input css 1>' },
     end: { line: 4, column: 1 } },
  selector: '.test1,\n.test2:not(.test3)',
  params: '(.test3)',
  lastEach: 4,
  indexes: {},
  selectorAst: 
   Root { ... }

You'll notice that this is not a mixin definition or use, but the params property is being assigned based on the pseudo selector :not value. On the surface, this looks like a bug. The value of the pseudo selector should be simply part of the selector, as it's not treated any different in plain css, and params should be empty.

Integration tests

Users afraid that done third-party's parser could brake user's sources. This is why good integration tests are highly recommended.

In PostCSS default parser I use Github and Twitter styles. In save parser I use browserhacks styles.

I think you should ask Less team for some integration tests. Smoke test will be enough - just parse all they tests sources without a errors.

Tag releases

In order to see what had changed between npm releases, please use git tags.

For example

git tag v0.9.0 feee3c86e50543f44c25609216c78e6e941e8224
git tag v0.10.0 fcb9afaa30c2808431674e9bf331e6bc06171e77
git tag v0.11.0 c3474e3ed0780b53b32432e31caa1d7ade348236

... and so forth

AtRule without body

Requesting a small improvement to the AtRule type. When parsing @rule(); or @rule; it would be great to have a convenience property shared with regular Rule types; node.ruleWithoutBody. Presently we're having to frequently use:

(node.type === 'atrule' && (!node.nodes || (node.nodes && node.nodes.length === 0)))

which works, but it gets messy. Any chance of adding that property to AtRule nodes as well?

!important with space and mixins

  • Node Version: 6.11.1
  • NPM Version: 5.3.0
  • postcss-less Version: 1.1.0

In Less, it's possible to suffix mixins with !important to mark all the declartaions in the mixin with !important (http://lesscss.org/features/#mixins-feature-the-important-keyword).

This is currently handled by postcss-less but only when used as !important. It's also possible (and valid) to add one or more spaces between the exclamation mark (!) and important, i.e. ! important. PostCSS handles this on declarations by adding a important property to raws and I think it would make sense to do the same thing here.

Hopefully, we'll be able to use the same logic as PostCSS does (I haven't investigated that yet). But if not, we can probably get some pointers from there at least.

LESS

.foo() ! important;

Expected Behavior

An AST similar to this:

Rule {
    raws: { before: '', between: '', semicolon: true, after: '', important: ' ! important' }, // Note the "important" here
    type: 'rule',
    important: true,
    [...]
}

Shortened for brevity because it's only raws that's important (pun intended).

Actual Behavior

This AST:

Rule {
    raws: { before: '', between: '', semicolon: true, after: '' },
    type: 'rule',
    [...]
}

Shortened for brevity because it's only raws that's important (pun intended).

How can we reproduce the behavior?

Run postcss-less on the Less example above.

Keep changelog up to date

We're currently using 0.10.0 in stylelint, but we've got a pending PR to update to 0.12.0. It doesn't look like the changelog has been updated since 0.3.0, so it's a bit tricky for us to quickly verify what has changed between the releases. If possible, can you add some (back-dated) release notes to the changelog? And can you update it before each release?

I'm not sure if you'll find it useful, but we use npmpub to help with the stylelint releases. It uses the changelog to tag (which will help with #41), release and publish a new version. There's other automated tooling out there as well too :)

CSS spec compliance: `!IMPORTANT` is valid โ€“ should be case insensitive

  • Node Version: 8.3.0
  • NPM Version: 5.3.0
  • postcss-less Version: 1.1.0

LESS

a{k: v !IMPORTANT;}

JavaScript

console.dir(require("postcss-less").parse('a{k: v !IMPORTANT;}'), {colors: true, depth: null})

Expected Behavior

The declaration should be parsed as:

Declaration {
  prop: 'k',
  important: true,
  value: 'v'
}

Just like for a{k: v !important;}.

Actual Behavior

The declaration is parsed as:

Declaration {
  prop: 'k',
  value: 'v !IMPORTANT' }
}

How can we reproduce the behavior?

console.dir(require("postcss-less").parse('a{k: v !IMPORTANT;}'), {colors: true, depth: null})

Spec

CSS is actually mostly case insensitive. Here is the spec mentioning how !important should be parsed case insensitively: https://www.w3.org/TR/css-syntax-3/#consume-a-declaration

If the last two non-<whitespace-token>s in the declarationโ€™s value are a <delim-token> with the value "!" followed by an <ident-token> with a value that is an ASCII case-insensitive match for "important", remove them from the declarationโ€™s value and set the declarationโ€™s important flag to true.

Related

postcss/postcss#1065

stylelint integration issues

I got around to doing the stylelint integration tests today and saw that there is an issue with mixin parsing. postcss-scss parses their mixins as an atrule node, which is handled by the postcss stringifier. The solution is to either write a custom stringify function for mixin node, or fix the tokenizer to emit atrule nodes for mixins. Either choice is fine, but the latter may be easier (and is consistent with what is mentioned in the readme file).

Here is an example of a broken LESS snippet with respect to the stringifier:

.for(@n: 1) when (@n <= 10) { .n-@{n} { content: %(\"n: %d\", 1 + 1); } .for(@n + 1); }

@import with option parsed incorrectly

Doesn't look like the parser is handling @import with options correctly. See http://lesscss.org/features/#import-options

Consider this import: @import (inline) "foo.less";

PostCSS-LESS parses and returns:

AtRule {
  raws: { before: '', between: '', afterName: ' ' },
  type: 'atrule',
  name: 'import',
  parent: 
   Root {
     raws: { semicolon: true, after: '' },
     type: 'root',
     nodes: [ [Circular] ],
     source: { input: [Object], start: [Object] },
     lastEach: 2,
     indexes: {} },
  source: 
   { start: { line: 1, column: 1 },
     input: Input { css: '@import (inline) "foo";', id: '<input css 1>' },
     end: { line: 1, column: 23 } },
  params: '(inline) "foo"',
  lastEach: 2,
  indexes: { '1': 0, '2': 0 } }

A few things wrong here. The params property contains the import option and the import file path. It would be a reasonable workaround if the parser was updated so that anything following the closing paren of params was treated as a separate value. However, imports could really benefit from having a separate node type to accommodate how LESS uses them.

Tests

Writing a parsers is very complicated process. Tests are required for any good open source project, but they are required twice for parsers.

Look into postcss-scss tests. They are very easy. I think tests save development time in parsers case.

Move dist from repo

Good repositories avoid generated content. There is many reasons for it, but I think main reasons is:

  • Some user may make mistake and fix for dist content.
  • dist makes diffs much harder to read

So we should add dist to .gitignore

Conflict With CSSNext

  • Node Version: 4
  • NPM Version: 3.10.10
  • postcss-less Version: 0.16.0 (also tried 1.0.1, which is not officially compatible with Node 4)

If you have a large amount of code to share which demonstrates the problem you're experiencing, please provide a link to your
repository rather than pasting code. Otherwise, please paste relevant short snippets below.

LESS

// less that demonstrates the issue

/******** PASSING ********/

.mixin() {
    .class& {
        background-color: black;
    }
}

body {
    .mixin();
}

/******** FAILING ********/

.mixin() {
    // this line fails
    &.class {
        background-color: black;
    }
}

body {
    .mixin();
}

JavaScript

// js that reproduces the issue

/** gulpfile.js **/

'use strict';

const gulp = require('gulp');
const lessParser = require('postcss-less');
const next = require('postcss-cssnext');
const postcss = require('gulp-postcss');
const less = require('gulp-less');
const tap = require('gulp-tap');

const plugins = [
    next(),
];

const options = {
    syntax: lessParser,
};

gulp.task('less', () =>
    gulp.src('app.less')
        .pipe(tap(file => {
            console.log(`Original LESS:\n`);
            console.log(`${file.contents.toString()}\n`);
        }))
        .pipe(postcss(plugins, options))
        .pipe(tap(file => {
            console.log(`After cssnext:\n`);
            console.log(file.contents.toString());
        }))
        .pipe(less())
        .pipe(gulp.dest('dest/')));

In the console, run gulp less.

postcss-cssnext version: 2.11.0
gulp-postcss version: 6.4.0

// actual error output, if error was thrown
[11:07:37] Using gulpfile ~/repo/tests/postless-next/gulpfile.js
[11:07:37] Starting 'less'...
Original LESS:

.mixin() {
  &.class {
    background-color: black;
  }
}

body {
  .mixin();
}


After cssnext:

.mixin() {
}

.mixin().class {

  background-color: black
}

body {
  .mixin();
}

Potentially unhandled rejection [2] Unrecognised input in file /home/smoran/repo/tests/postless-next/app.less line no. 4

Expected Behavior

Builds with no errors.

Actual Behavior

Builds with a single error (see error).

How can we reproduce the behavior?

Install all dependencies, run gulp with the gulpfile provided and the LESS provided.

NOTE: This is not an issue when using postcss-scss.

I know the intent of this plugin is not to be a LESS compiler. I had to close one of my other issues because I did not fully understand that. That being said, I think cssnext is a case where parsing LESS applies, as it is essentially a transpiler. Transpiling does not make sense to do after preprocessing with something like LESS or SCSS, and in fact most of the new CSS features outlined in cssnext will fail if you try to put them into LESS. If I am wrong on any of this, and this does not fit the plugin's purpose or you do not care, feel free to tell me.

I am still not sure whether this issue belongs here or on the cssnext repository, as the error only shows up if I combine both this plugin and cssnext. To see for yourself, try taking out cssnext and building again.

Should missing semicolons result in a parse error?

Firstly, thanks for your work on this parser!

The following code:

.class5 {
  color: green
  .mixin()
  .mixin2
}

Is parsed to:

Declaration {
  raws: { before: '\n  ', between: ': ' },
  type: 'decl',
  parent: 
   Rule {
     raws: { before: '', between: ' ', semicolon: false, after: '\n' },
     type: 'rule',
     nodes: [ [Circular] ],
     parent: 
      Root {
        raws: [Object],
        type: 'root',
        nodes: [Object],
        source: [Object],
        lastEach: 36,
        indexes: [Object] },
     source: { start: [Object], input: [Object], end: [Object] },
     selector: '.class5',
     lastEach: 37,
     indexes: { '37': 0 } },
  source: 
   { start: { line: 2, column: 3 },
     input: 
      Input {
        css: '.class5 {\n  color: green\n  .mixin()\n  .mixin2\n}\n',
        file: '/home/sheo13666q/IdeaProjects/stylelint/test/test.less' },
     end: { line: 4, column: 9 } },
  prop: 'color',
  value: 'green\n  .mixin()\n  .mixin2' }

i.e. a rule with a single declaration.

This is also how the standard PostCSS parses it. However, the Less parser throws a parse error. In stylelint, we're just going to document this limitation but I wanted to create an issue here in case you want, if it's at all possible, to match the Less parser's behaviour in this situation.

@import url() without quotes omits importPath

Seems we missed this one in #75 :/

  • Node Version: 6.10.3
  • NPM Version: 4.6.1
  • postcss-less Version: 1.0.1

If you have a large amount of code to share which demonstrates the problem you're experiencing, please provide a link to your repository rather than pasting code. Otherwise, please paste relevant short snippets below.

LESS

@import url(foo.less)

JavaScript

const postcss = require('postcss');
const syntax = require('postcss-less');

const lessText = '@import url(foo.less)';

postcss([])
  .process(lessText, { syntax: syntax })
  .then(function (result) {
      console.log(result.root.first);
  });

Expected Behavior

There should be a importPath property on the Import node containing foo.less.

Actual Behavior

It's putting (foo.less) in directives and omits importPath completely:

Import {
  raws: { before: '', afterName: ' ', semicolon: true },
  type: 'import',
  nodes: [],
  name: 'import',
  parent:
   Root {
     raws: { semicolon: false, after: '\n' },
     type: 'root',
     nodes: [ [Circular] ],
     source: { input: [Object], start: [Object] },
     lastEach: 3,
     indexes: { '3': 0 } },
  source:
   { start: { line: 1, column: 1 },
     input: Input { css: '@import url(foo.less);\n', id: '<input css 1>' },
     end: { line: 1, column: 22 } },
  urlFunc: true,
  directives: '(foo.less)',
  lastEach: 2,
  indexes: {} }

How can we reproduce the behavior?

Please see code in JavaScript section.

Getting error "rule.params.trim is not a function"

When we run our less files through stylelint, we were getting an error about mixin rules. We updated to the latest version of all our npm packages and got a different mixin rule error. After adding your recommended postcss config (mixinsAsAtRules: true, innerMixinsAsRules: true), we're now getting an error that says "rule.params.trim is not a function"

It still appears to render warnings from stylelint, so I think it's more of an annoyance at the moment.

Let me know how I can help track that down, if it's not already a known issue.

Mixins within rules aren't added to nodes collection

Consider the following input: .foo { .mixin(); }

And the resulting Rule node:

Rule {
  raws: { before: '', between: ' ', after: ' .mixin(); ' },
  type: 'rule',
  nodes: [],
  parent: 
   Root {
     raws: { semicolon: false, after: '' },
     type: 'root',
     nodes: [ [Circular] ],
     source: { input: [Object], start: [Object] },
     lastEach: 1,
     indexes: {} },
  source: 
   { start: { line: 1, column: 1 },
     input: Input { css: '.foo { .mixin(); }', id: '<input css 5>' },
     end: { line: 1, column: 18 } },
  selector: '.foo',
  lastEach: 2,
  indexes: {} }

The nodes array is empty, and node.raws.after contains the source for the mixin declaration, but it should probably be part of the nodes collection as a node type.

Mixins without a body, or an empty body, aren't parsed correctly

This may seem silly on the surface, but this is actually valid LESS: .foo();. Unfortunately, postcss-less doesn't parse this mixin, rather the result is a Root node:

Root {
  raws: { after: '.foo();' },
  type: 'root',
  nodes: [],
  source: 
   { input: Input { css: '.foo();', id: '<input css 1>' },
     start: { line: 1, column: 1 } },
  lastEach: 1,
  indexes: {} }

Mixins with an empty body also fail to parse correctly, and are instead parsed as a rule: .foo(){}

Rule {
  raws: { before: '', between: '', after: '' },
  type: 'rule',
  nodes: [],
  parent: 
   Root {
     raws: { semicolon: false, after: '' },
     type: 'root',
     nodes: [ [Circular] ],
     source: { input: [Object], start: [Object] },
     lastEach: 1,
     indexes: {} },
  source: 
   { start: { line: 1, column: 1 },
     input: Input { css: '.foo(){}', id: '<input css 1>' },
     end: { line: 1, column: 8 } },
  selector: '.foo()',
  lastEach: 1,
  indexes: {} }

Incorrect value `rule.raws.semicolon`

  • Node Version: 7.10.0
  • NPM Version: 4.2.0
  • postcss-less Version: 0.16.1

If you have a large amount of code to share which demonstrates the problem you're experiencing, please provide a link to your
repository rather than pasting code. Otherwise, please paste relevant short snippets below.

LESS

a { .mixin; .mixin2; }

JavaScript

import postCssLess from 'postcss-less';
const less = `a { .mixin; .mixin2; }`;
const root = postCssLess.parse(less);

Expected Behavior

root.nodes[0].raws.semicolon should be true.
root.nodes[0].raws.after should be .

Actual Behavior

root.nodes[0].raws.semicolon is false.
root.nodes[0].raws.after is ; .

How can we reproduce the behavior?

Use example in javascript section.

Issue was created based on stylelint/stylelint#2547.
Information about stylelint/stylelint#2547 (comment).
Information about expected behavior based on postcss docs http://api.postcss.org/Node.html#raws

Spaces between variable name and `:` are not handled

  • Node Version: 6.11.3
  • NPM Version: 3.10.10
  • postcss-less Version: 1.1.1

I pin pointed tokenize-at-rule.js#L36.
When declaration contains a space between variable name and :,
It makes state.cssPart one character to shorter to enter word definition bloc.
Test named parses variables with whitespaces between name and ":", merged in #93, reproduces bug.

LESS

.navbar {
  @borderTopPx : 4px;
  .media {
    i.user {
      margin-top: @borderTopPx + 10px;
    }
  }
}

JavaScript

prettier/prettier#2925

Expected Behavior

@borderTopPx to be handled like a variable.

Actual Behavior

@borderTopPx not handled like a variable.

How can we reproduce the behavior?

I noticed this bug using prettier on Less pasted above.
It is described at prettier/prettier#2925, where @lydell can provide more accurate details about parsing expectations.

Test named parses variables with whitespaces between name and ":" reproduces issue.

Thank for the good work

Throws with sourcemap

  • Node Version: 5.0.0
  • NPM Version: yarn 0.24.3
  • postcss-less Version: 1.0.0

LESS

/*# sourceMappingURL=data:application/json;base64,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QUNiO0VBQ0UsZUFBZTtDQUNoQjs7QUFFRCxlQUFlO0FBQ2Y7RUFDRSxlQUFlO0NBQ2hCOztBQUVELGNBQWM7QUFDZDtFQUNFLGVBQWU7Q0FDaEI7O0FBRUQsZUFBZTtBQUNmO0VBQ0UsZUFBZTtDQUNoQjs7QUFFRCxVQUFVO0FBQ1Y7RUFDRSxlQUFlO0NBQ2hCIiwiZmlsZSI6ImFwcC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZ3JhcGhpcWwtY29udGFpbmVyLFxuLmdyYXBoaXFsLWNvbnRhaW5lciBidXR0b24sXG4uZ3JhcGhpcWwtY29udGFpbmVyIGlucHV0IHtcbiAgY29sb3I6ICMxNDE4MjM7XG4gIGZvbnQtZmFtaWx5OlxuICAgIHN5c3RlbSxcbiAgICAtYXBwbGUtc3lzdGVtLFxuICAgICdTYW4gRnJhbmNpc2NvJyxcbiAgICAnLlNGTlNEaXNwbGF5LVJlZ3VsYXInLFxuICAgICdTZWdvZSBVSScsXG4gICAgU2Vnb2UsXG4gICAgJ1NlZ29lIFdQJyxcbiAgICAnSGVsdmV0aWNhIE5ldWUnLFxuICAgIGhlbHZldGljYSxcbiAgICAnTHVjaWRhIEdyYW5kZScsXG4gICAgYXJpYWwsXG4gICAgc2Fucy1zZXJpZjtcbiAgZm9udC1zaXplOiAxNHB4O1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgaGVpZ2h0OiAxMDAlO1xuICBtYXJnaW46IDA7XG4gIG92ZXJmbG93OiBoaWRkZW47XG4gIHdpZHRoOiAxMDAlO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5lZGl0b3JXcmFwIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgZmxleDogMTtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAudGl0bGUge1xuICBmb250LXNpemU6IDE4cHg7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLnRpdGxlIGVtIHtcbiAgZm9udC1mYW1pbHk6IGdlb3JnaWE7XG4gIGZvbnQtc2l6ZTogMTlweDtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9wQmFyV3JhcCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLnRvcEJhciB7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgjZjdmN2Y3LCAjZTJlMmUyKTtcbiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNkMGQwZDA7XG4gIGN1cnNvcjogZGVmYXVsdDtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgZmxleDogMTtcbiAgaGVpZ2h0OiAzNHB4O1xuICBwYWRkaW5nOiA3cHggMTRweCA2cHg7XG4gIHVzZXItc2VsZWN0OiBub25lO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyIHtcbiAgb3ZlcmZsb3cteDogdmlzaWJsZTtcbiAgZGlzcGxheTogZmxleDtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAuZG9jRXhwbG9yZXJTaG93LFxuLmdyYXBoaXFsLWNvbnRhaW5lciAuaGlzdG9yeVNob3cge1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoI2Y3ZjdmNywgI2UyZTJlMik7XG4gIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZDBkMGQwO1xuICBib3JkZXItcmlnaHQ6IG5vbmU7XG4gIGJvcmRlci10b3A6IG5vbmU7XG4gIGNvbG9yOiAjM0I1OTk4O1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGZvbnQtc2l6ZTogMTRweDtcbiAgbWFyZ2luOiAwO1xuICBvdXRsaW5lOiAwO1xuICBwYWRkaW5nOiAycHggMjBweCAwIDE4cHg7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmRvY0V4cGxvcmVyU2hvdyB7XG4gIGJvcmRlci1sZWZ0OiAxcHggc29saWQgcmdiYSgwLCAwLCAwLCAwLjIpO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5oaXN0b3J5U2hvdyB7XG4gIGJvcmRlci1yaWdodDogMXB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC4yKTtcbiAgYm9yZGVyLWxlZnQ6IDA7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmRvY0V4cGxvcmVyU2hvdzpiZWZvcmUge1xuICBib3JkZXItbGVmdDogMnB4IHNvbGlkICMzQjU5OTg7XG4gIGJvcmRlci10b3A6IDJweCBzb2xpZCAjM0I1OTk4O1xuICBjb250ZW50OiAnJztcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICBoZWlnaHQ6IDlweDtcbiAgbWFyZ2luOiAwIDNweCAtMXB4IDA7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgdHJhbnNmb3JtOiByb3RhdGUoLTQ1ZGVnKTtcbiAgd2lkdGg6IDlweDtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAuZWRpdG9yQmFyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgZmxleDogMTtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAucXVlcnlXcmFwIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgZmxleDogMTtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAucmVzdWx0V3JhcCB7XG4gIGJvcmRlci1sZWZ0OiBzb2xpZCAxcHggI2UwZTBlMDtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgZmxleDogMTtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5kb2NFeHBsb3JlcldyYXAsXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5oaXN0b3J5UGFuZVdyYXAge1xuICBiYWNrZ3JvdW5kOiB3aGl0ZTtcbiAgYm94LXNoYWRvdzogMCAwIDhweCByZ2JhKDAsIDAsIDAsIDAuMTUpO1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gIHotaW5kZXg6IDM7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmhpc3RvcnlQYW5lV3JhcCB7XG4gIG1pbi13aWR0aDogMjMwcHg7XG4gIHotaW5kZXg6IDU7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmRvY0V4cGxvcmVyUmVzaXplciB7XG4gIGN1cnNvcjogY29sLXJlc2l6ZTtcbiAgaGVpZ2h0OiAxMDAlO1xuICBsZWZ0OiAtNXB4O1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRvcDogMDtcbiAgd2lkdGg6IDEwcHg7XG4gIHotaW5kZXg6IDEwO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5kb2NFeHBsb3JlckhpZGUge1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGZvbnQtc2l6ZTogMThweDtcbiAgbWFyZ2luOiAtN3B4IC04cHggLTZweCAwO1xuICBwYWRkaW5nOiAxOHB4IDE2cHggMTVweCAxMnB4O1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5xdWVyeS1lZGl0b3Ige1xuICBmbGV4OiAxO1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLnZhcmlhYmxlLWVkaXRvciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGhlaWdodDogMjlweDtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC52YXJpYWJsZS1lZGl0b3ItdGl0bGUge1xuICBiYWNrZ3JvdW5kOiAjZWVlZWVlO1xuICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI2Q2ZDZkNjtcbiAgYm9yZGVyLXRvcDogMXB4IHNvbGlkICNlMGUwZTA7XG4gIGNvbG9yOiAjNzc3O1xuICBmb250LXZhcmlhbnQ6IHNtYWxsLWNhcHM7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xuICBsZXR0ZXItc3BhY2luZzogMXB4O1xuICBsaW5lLWhlaWdodDogMTRweDtcbiAgcGFkZGluZzogNnB4IDAgOHB4IDQzcHg7XG4gIHRleHQtdHJhbnNmb3JtOiBsb3dlcmNhc2U7XG4gIHVzZXItc2VsZWN0OiBub25lO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5jb2RlbWlycm9yV3JhcCB7XG4gIGZsZXg6IDE7XG4gIGhlaWdodDogMTAwJTtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5yZXN1bHQtd2luZG93IHtcbiAgZmxleDogMTtcbiAgaGVpZ2h0OiAxMDAlO1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmZvb3RlciB7XG4gIGJhY2tncm91bmQ6ICNmNmY3Zjg7XG4gIGJvcmRlci1sZWZ0OiAxcHggc29saWQgI2UwZTBlMDtcbiAgYm9yZGVyLXRvcDogMXB4IHNvbGlkICNlMGUwZTA7XG4gIG1hcmdpbi1sZWZ0OiAxMnB4O1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmZvb3RlcjpiZWZvcmUge1xuICBiYWNrZ3JvdW5kOiAjZWVlZWVlO1xuICBib3R0b206IDA7XG4gIGNvbnRlbnQ6IFwiIFwiO1xuICBsZWZ0OiAtMTNweDtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IC0xcHg7XG4gIHdpZHRoOiAxMnB4O1xufVxuXG4vKiBObyBgLmdyYXBoaXFsLWNvbnRhaW5lcmAgaGVyZSBzbyB0aGVtZXMgY2FuIG92ZXJ3cml0ZSAqL1xuLnJlc3VsdC13aW5kb3cgLkNvZGVNaXJyb3Ige1xuICBiYWNrZ3JvdW5kOiAjZjZmN2Y4O1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5yZXN1bHQtd2luZG93IC5Db2RlTWlycm9yLWd1dHRlcnMge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZWVlZWVlO1xuICBib3JkZXItY29sb3I6ICNlMGUwZTA7XG4gIGN1cnNvcjogY29sLXJlc2l6ZTtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAucmVzdWx0LXdpbmRvdyAuQ29kZU1pcnJvci1mb2xkZ3V0dGVyLFxuLmdyYXBoaXFsLWNvbnRhaW5lciAucmVzdWx0LXdpbmRvdyAuQ29kZU1pcnJvci1mb2xkZ3V0dGVyLW9wZW46YWZ0ZXIsXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5yZXN1bHQtd2luZG93IC5Db2RlTWlycm9yLWZvbGRndXR0ZXItZm9sZGVkOmFmdGVyIHtcbiAgcGFkZGluZy1sZWZ0OiAzcHg7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItYnV0dG9uIHtcbiAgYmFja2dyb3VuZDogI2ZkZmRmZDtcbiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KCNmOWY5ZjksICNlY2VjZWMpO1xuICBib3JkZXItcmFkaXVzOiAzcHg7XG4gIGJveC1zaGFkb3c6XG4gICAgaW5zZXQgMCAwIDAgMXB4IHJnYmEoMCwwLDAsMC4yMCksXG4gICAgMCAxcHggMCByZ2JhKDI1NSwyNTUsMjU1LCAwLjcpLFxuICAgIGluc2V0IDAgMXB4ICNmZmY7XG4gIGNvbG9yOiAjNTU1O1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgbWFyZ2luOiAwIDVweDtcbiAgcGFkZGluZzogM3B4IDExcHggNXB4O1xuICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG4gIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xuICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICBtYXgtd2lkdGg6IDE1MHB4O1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyLWJ1dHRvbjphY3RpdmUge1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoI2VjZWNlYywgI2Q1ZDVkNSk7XG4gIGJveC1zaGFkb3c6XG4gICAgMCAxcHggMCByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNyksXG4gICAgaW5zZXQgMCAwIDAgMXB4IHJnYmEoMCwwLDAsMC4xMCksXG4gICAgaW5zZXQgMCAxcHggMXB4IDFweCByZ2JhKDAsIDAsIDAsIDAuMTIpLFxuICAgIGluc2V0IDAgMCA1cHggcmdiYSgwLCAwLCAwLCAwLjEpO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyLWJ1dHRvbi5lcnJvciB7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgjZmRmM2YzLCAjZTZkNmQ3KTtcbiAgY29sb3I6ICNiMDA7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItYnV0dG9uLWdyb3VwIHtcbiAgbWFyZ2luOiAwIDVweDtcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1idXR0b24tZ3JvdXAgPiAqIHtcbiAgbWFyZ2luOiAwO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyLWJ1dHRvbi1ncm91cCA+ICo6bm90KDpsYXN0LWNoaWxkKSB7XG4gIGJvcmRlci10b3AtcmlnaHQtcmFkaXVzOiAwO1xuICBib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1czogMDtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1idXR0b24tZ3JvdXAgPiAqOm5vdCg6Zmlyc3QtY2hpbGQpIHtcbiAgYm9yZGVyLXRvcC1sZWZ0LXJhZGl1czogMDtcbiAgYm9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czogMDtcbiAgbWFyZ2luLWxlZnQ6IC0xcHg7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmV4ZWN1dGUtYnV0dG9uLXdyYXAge1xuICBoZWlnaHQ6IDM0cHg7XG4gIG1hcmdpbjogMCAxNHB4IDAgMjhweDtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5leGVjdXRlLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgjZmRmZGZkLCAjZDJkM2Q2KTtcbiAgYm9yZGVyLXJhZGl1czogMTdweDtcbiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLDAsMCwwLjI1KTtcbiAgYm94LXNoYWRvdzogMCAxcHggMCAjZmZmO1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGZpbGw6ICM0NDQ7XG4gIGhlaWdodDogMzRweDtcbiAgbWFyZ2luOiAwO1xuICBwYWRkaW5nOiAwO1xuICB3aWR0aDogMzRweDtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAuZXhlY3V0ZS1idXR0b24gc3ZnIHtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmV4ZWN1dGUtYnV0dG9uOmFjdGl2ZSB7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgjZTZlNmU2LCAjYzNjM2MzKTtcbiAgYm94LXNoYWRvdzpcbiAgICAwIDFweCAwICNmZmYsXG4gICAgaW5zZXQgMCAwIDJweCByZ2JhKDAsIDAsIDAsIDAuMiksXG4gICAgaW5zZXQgMCAwIDZweCByZ2JhKDAsIDAsIDAsIDAuMSk7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmV4ZWN1dGUtYnV0dG9uOmZvY3VzIHtcbiAgb3V0bGluZTogMDtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1tZW51LFxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1zZWxlY3Qge1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLmV4ZWN1dGUtb3B0aW9ucyxcbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItbWVudS1pdGVtcyxcbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItc2VsZWN0LW9wdGlvbnMge1xuICBiYWNrZ3JvdW5kOiAjZmZmO1xuICBib3gtc2hhZG93OlxuICAgIDAgMCAwIDFweCByZ2JhKDAsMCwwLDAuMSksXG4gICAgMCAycHggNHB4IHJnYmEoMCwwLDAsMC4yNSk7XG4gIG1hcmdpbjogMDtcbiAgcGFkZGluZzogNnB4IDA7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgei1pbmRleDogMTAwO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5leGVjdXRlLW9wdGlvbnMge1xuICBtaW4td2lkdGg6IDEwMHB4O1xuICB0b3A6IDM3cHg7XG4gIGxlZnQ6IC0xcHg7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItbWVudS1pdGVtcyB7XG4gIGxlZnQ6IDFweDtcbiAgbWFyZ2luLXRvcDogLTFweDtcbiAgbWluLXdpZHRoOiAxMTAlO1xuICB0b3A6IDEwMCU7XG4gIHZpc2liaWxpdHk6IGhpZGRlbjtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1tZW51LWl0ZW1zLm9wZW4ge1xuICB2aXNpYmlsaXR5OiB2aXNpYmxlO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyLXNlbGVjdC1vcHRpb25zIHtcbiAgbGVmdDogMDtcbiAgbWluLXdpZHRoOiAxMDAlO1xuICB0b3A6IC01cHg7XG4gIHZpc2liaWxpdHk6IGhpZGRlbjtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1zZWxlY3Qtb3B0aW9ucy5vcGVuIHtcbiAgdmlzaWJpbGl0eTogdmlzaWJsZTtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAuZXhlY3V0ZS1vcHRpb25zID4gbGksXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyLW1lbnUtaXRlbXMgPiBsaSxcbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItc2VsZWN0LW9wdGlvbnMgPiBsaSB7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgZGlzcGxheTogYmxvY2s7XG4gIG1hcmdpbjogbm9uZTtcbiAgbWF4LXdpZHRoOiAzMDBweDtcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgcGFkZGluZzogMnB4IDIwcHggNHB4IDExcHg7XG4gIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xuICB3aGl0ZS1zcGFjZTogbm93cmFwO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5leGVjdXRlLW9wdGlvbnMgPiBsaS5zZWxlY3RlZCxcbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItbWVudS1pdGVtcyA+IGxpLmhvdmVyLFxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1tZW51LWl0ZW1zID4gbGk6YWN0aXZlLFxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1tZW51LWl0ZW1zID4gbGk6aG92ZXIsXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyLXNlbGVjdC1vcHRpb25zID4gbGkuaG92ZXIsXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyLXNlbGVjdC1vcHRpb25zID4gbGk6YWN0aXZlLFxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1zZWxlY3Qtb3B0aW9ucyA+IGxpOmhvdmVyLFxuLmdyYXBoaXFsLWNvbnRhaW5lciAuaGlzdG9yeS1jb250ZW50cyA+IHA6aG92ZXIsXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5oaXN0b3J5LWNvbnRlbnRzID4gcDphY3RpdmUge1xuICBiYWNrZ3JvdW5kOiAjZTEwMDk4O1xuICBjb2xvcjogI2ZmZjtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAudG9vbGJhci1zZWxlY3Qtb3B0aW9ucyA+IGxpID4gc3ZnIHtcbiAgZGlzcGxheTogaW5saW5lO1xuICBmaWxsOiAjNjY2O1xuICBtYXJnaW46IDAgLTZweCAwIDZweDtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItc2VsZWN0LW9wdGlvbnMgPiBsaS5ob3ZlciA+IHN2Zyxcbi5ncmFwaGlxbC1jb250YWluZXIgLnRvb2xiYXItc2VsZWN0LW9wdGlvbnMgPiBsaTphY3RpdmUgPiBzdmcsXG4uZ3JhcGhpcWwtY29udGFpbmVyIC50b29sYmFyLXNlbGVjdC1vcHRpb25zID4gbGk6aG92ZXIgPiBzdmcge1xuICBmaWxsOiAjZmZmO1xufVxuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5Db2RlTWlycm9yLXNjcm9sbCB7XG4gIG92ZXJmbG93LXNjcm9sbGluZzogdG91Y2g7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgLkNvZGVNaXJyb3Ige1xuICBjb2xvcjogIzE0MTgyMztcbiAgZm9udC1mYW1pbHk6XG4gICAgJ0NvbnNvbGFzJyxcbiAgICAnSW5jb25zb2xhdGEnLFxuICAgICdEcm9pZCBTYW5zIE1vbm8nLFxuICAgICdNb25hY28nLFxuICAgIG1vbm9zcGFjZTtcbiAgZm9udC1zaXplOiAxM3B4O1xuICBoZWlnaHQ6IDEwMCU7XG4gIGxlZnQ6IDA7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgdG9wOiAwO1xuICB3aWR0aDogMTAwJTtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciAuQ29kZU1pcnJvci1saW5lcyB7XG4gIHBhZGRpbmc6IDIwcHggMDtcbn1cblxuLkNvZGVNaXJyb3ItaGludC1pbmZvcm1hdGlvbiAuY29udGVudCB7XG4gIGJveC1vcmllbnQ6IHZlcnRpY2FsO1xuICBjb2xvcjogIzE0MTgyMztcbiAgZGlzcGxheTogZmxleDtcbiAgZm9udC1mYW1pbHk6IHN5c3RlbSwgLWFwcGxlLXN5c3RlbSwgJ1NhbiBGcmFuY2lzY28nLCAnLlNGTlNEaXNwbGF5LVJlZ3VsYXInLCAnU2Vnb2UgVUknLCBTZWdvZSwgJ1NlZ29lIFdQJywgJ0hlbHZldGljYSBOZXVlJywgaGVsdmV0aWNhLCAnTHVjaWRhIEdyYW5kZScsIGFyaWFsLCBzYW5zLXNlcmlmO1xuICBmb250LXNpemU6IDEzcHg7XG4gIGxpbmUtY2xhbXA6IDM7XG4gIGxpbmUtaGVpZ2h0OiAxNnB4O1xuICBtYXgtaGVpZ2h0OiA0OHB4O1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICB0ZXh0LW92ZXJmbG93OiAtby1lbGxpcHNpcy1sYXN0bGluZTtcbn1cblxuLkNvZGVNaXJyb3ItaGludC1pbmZvcm1hdGlvbiAuY29udGVudCBwOmZpcnN0LWNoaWxkIHtcbiAgbWFyZ2luLXRvcDogMDtcbn1cblxuLkNvZGVNaXJyb3ItaGludC1pbmZvcm1hdGlvbiAuY29udGVudCBwOmxhc3QtY2hpbGQge1xuICBtYXJnaW4tYm90dG9tOiAwO1xufVxuXG4uQ29kZU1pcnJvci1oaW50LWluZm9ybWF0aW9uIC5pbmZvVHlwZSB7XG4gIGNvbG9yOiAjQ0E5ODAwO1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGRpc3BsYXk6IGlubGluZTtcbiAgbWFyZ2luLXJpZ2h0OiAwLjVlbTtcbn1cblxuLmF1dG9JbnNlcnRlZExlYWYuY20tcHJvcGVydHkge1xuICBhbmltYXRpb24tZHVyYXRpb246IDZzO1xuICBhbmltYXRpb24tbmFtZTogaW5zZXJ0aW9uRmFkZTtcbiAgYm9yZGVyLWJvdHRvbTogMnB4IHNvbGlkIHJnYmEoMjU1LCAyNTUsIDI1NSwgMCk7XG4gIGJvcmRlci1yYWRpdXM6IDJweDtcbiAgbWFyZ2luOiAtMnB4IC00cHggLTFweDtcbiAgcGFkZGluZzogMnB4IDRweCAxcHg7XG59XG5cbkBrZXlmcmFtZXMgaW5zZXJ0aW9uRmFkZSB7XG4gIGZyb20sIHRvIHtcbiAgICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDApO1xuICAgIGJvcmRlci1jb2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwKTtcbiAgfVxuXG4gIDE1JSwgODUlIHtcbiAgICBiYWNrZ3JvdW5kOiAjZmJmZmM5O1xuICAgIGJvcmRlci1jb2xvcjogI2YwZjNjMDtcbiAgfVxufVxuXG5kaXYuQ29kZU1pcnJvci1saW50LXRvb2x0aXAge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTtcbiAgYm9yZGVyLXJhZGl1czogMnB4O1xuICBib3JkZXI6IDA7XG4gIGNvbG9yOiAjMTQxODIzO1xuICBib3gtc2hhZG93OiAwIDFweCAzcHggcmdiYSgwLCAwLCAwLCAwLjQ1KTtcbiAgZm9udC1mYW1pbHk6XG4gICAgc3lzdGVtLFxuICAgIC1hcHBsZS1zeXN0ZW0sXG4gICAgJ1NhbiBGcmFuY2lzY28nLFxuICAgICcuU0ZOU0Rpc3BsYXktUmVndWxhcicsXG4gICAgJ1NlZ29lIFVJJyxcbiAgICBTZWdvZSxcbiAgICAnU2Vnb2UgV1AnLFxuICAgICdIZWx2ZXRpY2EgTmV1ZScsXG4gICAgaGVsdmV0aWNhLFxuICAgICdMdWNpZGEgR3JhbmRlJyxcbiAgICBhcmlhbCxcbiAgICBzYW5zLXNlcmlmO1xuICBmb250LXNpemU6IDEzcHg7XG4gIGxpbmUtaGVpZ2h0OiAxNnB4O1xuICBtYXgtd2lkdGg6IDQzMHB4O1xuICBvcGFjaXR5OiAwO1xuICBwYWRkaW5nOiA4cHggMTBweDtcbiAgdHJhbnNpdGlvbjogb3BhY2l0eSAwLjE1cztcbiAgd2hpdGUtc3BhY2U6IHByZS13cmFwO1xufVxuXG5kaXYuQ29kZU1pcnJvci1saW50LXRvb2x0aXAgPiAqIHtcbiAgcGFkZGluZy1sZWZ0OiAyM3B4O1xufVxuXG5kaXYuQ29kZU1pcnJvci1saW50LXRvb2x0aXAgPiAqICsgKiB7XG4gIG1hcmdpbi10b3A6IDEycHg7XG59XG5cbi8qIENPTE9SUyAqL1xuXG4uZ3JhcGhpcWwtY29udGFpbmVyIC5Db2RlTWlycm9yLWZvbGRtYXJrZXIge1xuICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIGJhY2tncm91bmQ6ICMwOGY7XG4gIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgjNDNBOEZGLCAjMEY4M0U4KTtcbiAgYm94LXNoYWRvdzpcbiAgICAwIDFweCAxcHggcmdiYSgwLCAwLCAwLCAwLjIpLFxuICAgIGluc2V0IDAgMCAwIDFweCByZ2JhKDAsIDAsIDAsIDAuMSk7XG4gIGNvbG9yOiB3aGl0ZTtcbiAgZm9udC1mYW1pbHk6IGFyaWFsO1xuICBmb250LXNpemU6IDEycHg7XG4gIGxpbmUtaGVpZ2h0OiAwO1xuICBtYXJnaW46IDAgM3B4O1xuICBwYWRkaW5nOiAwcHggNHB4IDFweDtcbiAgdGV4dC1zaGFkb3c6IDAgLTFweCByZ2JhKDAsIDAsIDAsIDAuMSk7XG59XG5cbi5ncmFwaGlxbC1jb250YWluZXIgZGl2LkNvZGVNaXJyb3Igc3Bhbi5Db2RlTWlycm9yLW1hdGNoaW5nYnJhY2tldCB7XG4gIGNvbG9yOiAjNTU1O1xuICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcbn1cblxuLmdyYXBoaXFsLWNvbnRhaW5lciBkaXYuQ29kZU1pcnJvciBzcGFuLkNvZGVNaXJyb3Itbm9ubWF0Y2hpbmdicmFja2V0IHtcbiAgY29sb3I6ICNmMDA7XG59XG5cbi8qIENvbW1lbnQgKi9cbi5jbS1jb21tZW50IHtcbiAgY29sb3I6ICM5OTk7XG59XG5cbi8qIFB1bmN0dWF0aW9uICovXG4uY20tcHVuY3R1YXRpb24ge1xuICBjb2xvcjogIzU1NTtcbn1cblxuLyogS2V5d29yZCAqL1xuLmNtLWtleXdvcmQge1xuICBjb2xvcjogI0IxMUEwNDtcbn1cblxuLyogT3BlcmF0aW9uTmFtZSwgRnJhZ21lbnROYW1lICovXG4uY20tZGVmIHtcbiAgY29sb3I6ICNEMjA1NEU7XG59XG5cbi8qIEZpZWxkTmFtZSAqL1xuLmNtLXByb3BlcnR5IHtcbiAgY29sb3I6ICMxRjYxQTA7XG59XG5cbi8qIEZpZWxkQWxpYXMgKi9cbi5jbS1xdWFsaWZpZXIge1xuICBjb2xvcjogIzFDOTJBOTtcbn1cblxuLyogQXJndW1lbnROYW1lIGFuZCBPYmplY3RGaWVsZE5hbWUgKi9cbi5jbS1hdHRyaWJ1dGUge1xuICBjb2xvcjogIzhCMkJCOTtcbn1cblxuLyogTnVtYmVyICovXG4uY20tbnVtYmVyIHtcbiAgY29sb3I6ICMyODgyRjk7XG59XG5cbi8qIFN0cmluZyAqL1xuLmNtLXN0cmluZyB7XG4gIGNvbG9yOiAjRDY0MjkyO1xufVxuXG4vKiBCb29sZWFuICovXG4uY20tYnVpbHRpbiB7XG4gIGNvbG9yOiAjRDQ3NTA5O1xufVxuXG4vKiBFbnVtVmFsdWUgKi9cbi5jbS1zdHJpbmctMiB7XG4gIGNvbG9yOiAjMEI3RkM3O1xufVxuXG4vKiBWYXJpYWJsZSAqL1xuLmNtLXZhcmlhYmxlIHtcbiAgY29sb3I6ICMzOTdEMTM7XG59XG5cbi8qIERpcmVjdGl2ZSAqL1xuLmNtLW1ldGEge1xuICBjb2xvcjogI0IzMzA4Njtcbn1cblxuLyogVHlwZSAqL1xuLmNtLWF0b20ge1xuICBjb2xvcjogI0NBOTgwMDtcbn1cbiJdfQ== *//* BASICS */

.CodeMirror {
}

Errors

SyntaxError: Unexpected token
    at Object.parse (native)
    at new SourceMapConsumer (/Users/vjeux/random/prettier/node_modules/source-map/lib/source-map-consumer.js:17:22)
    at PreviousMap.consumer (/Users/vjeux/random/prettier/node_modules/postcss-less/node_modules/postcss/lib/previous-map.js:69:34)
    at new Input (/Users/vjeux/random/prettier/node_modules/postcss-less/node_modules/postcss/lib/input.js:84:28)
    at Object.lessParse [as parse] (/Users/vjeux/random/prettier/node_modules/postcss-less/dist/less-parse.js:19:15)

Expected Behavior

Would be nice not to throw. I have no idea if the source map is correct or not, but I'm interested in pretty printing the file, so I just want to put the comment as it was, not to parse it as source map.

Actual Behavior

Throws

How can we reproduce the behavior?

Parse this file using postcss-less

@import with url() gives empty importPath

  • Node Version: 6.10.3
  • NPM Version: 4.6.1
  • postcss-less Version: 1.0.0

If you have a large amount of code to share which demonstrates the problem you're experiencing, please provide a link to your repository rather than pasting code. Otherwise, please paste relevant short snippets below.

LESS

@import url("foo.css")

JavaScript

const postcss = require('postcss');
const syntax = require('postcss-less');

const lessText = '@import url("foo.css")';

postcss([])
  .process(lessText, { syntax: syntax })
  .then(function (result) {
      console.log(result.root.first);
  });

Expected Behavior

Not sure, but importPath should at least contain something more than just ). I don't know what I think really, if the whole url("foo.css") should be put in importPath or something else like params (which is what PostCSS does for at-rules).

Actual Behavior

importPath doesn't contain anything but the closing parentheses:

Import {
  raws: { before: '', afterName: ' ' },
  type: 'import',
  nodes: [],
  name: 'import',
  parent:
   Root {
     raws: { semicolon: false, after: '' },
     type: 'root',
     nodes: [ [Circular] ],
     source: { input: [Object], start: [Object] },
     lastEach: 1,
     indexes: {} },
  source:
   { start: { line: 1, column: 1 },
     input: Input { css: '@import url("foo.css")', id: '<input css 1>' },
     end: { line: 0, column: 0 } },
  importPath: ')',
  directives: '',
  lastEach: 1,
  indexes: {} }

How can we reproduce the behavior?

Please see code in JavaScript section.

Mixins aren't parsed correctly

I'm still having an issue like in #23. My mixin .mix() {color: red} results in .mix(){} when it is called in some selector.

postcss().process('.mix() {color: red} .selector {.mix()}', {
    syntax: postcssLess
}).then(function (result) {
    console.log(result.content); // .mix() {color: red}.selector {.mix(){}}
});

Do I have to set any further postcss configuration?

Update to PostCSS 6.x

PostCSS 6.0.6 is the latest release.

I'd created a PR in #83 to test this, Travis CI passed all 3 jobs though this was not actually the case, when inspecting the job logs all 3 had failed but still returned an exit of 0

Apologies for deleting the template, but there was not much to answer with this issue context

Error after parsing less with postcss-less

Repro demo: https://github.com/zry656565/postcss-less-issue-repro

# install dependencies
npm install
# run gulp task
gulp

Error Message:

[01:00:46] Starting 'default'...
[01:00:46] 'default' errored after 218 ms
[01:00:46] Error in plugin 'gulp-less'
Message:
    Unrecognised input in file /home/vagrant/postcss-issue-repro/demo.less line no. 8
Details:
    type: Parse
    filename: /home/vagrant/postcss-issue-repro/demo.less
    index: 181
    line: 8
    callLine: NaN
    callExtract: undefined
    column: 13
    extract:   .heading-font,  font-weight: 700;,}
    lineNumber: 8
    fileName: /home/vagrant/postcss-issue-repro/demo.less
[01:00:46] 'default' errored after 225 ms
[01:00:46] Error: task completion callback called too many times
    at finish (/home/vagrant/postcss-issue-repro/node_modules/orchestrator/lib/runTask.js:15:10)
    at /home/vagrant/postcss-issue-repro/node_modules/orchestrator/lib/runTask.js:52:4
    at f (/home/vagrant/postcss-issue-repro/node_modules/once/once.js:17:25)
    at DestroyableTransform.onend (/home/vagrant/postcss-issue-repro/node_modules/end-of-stream/index.js:31:18)
    at emitNone (events.js:85:20)
    at DestroyableTransform.emit (events.js:179:7)
    at /home/vagrant/postcss-issue-repro/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_readable.js:965:16
    at nextTickCallbackWith0Args (node.js:453:9)
    at process._tickCallback (node.js:382:13)

Comment Node Issues

Related to #20, but separate. There are a few issues with the Comment Node. Consider the following input: // Hello world

Results in the following Comment Node:

Comment {
  raws: { before: '', inline: true, left: ' ', right: '' },
  type: 'comment',
  parent: 
   Root {
     raws: { semicolon: false, after: '' },
     type: 'root',
     nodes: [ [Circular] ],
     source: { input: [Object], start: [Object] },
     lastEach: 1,
     indexes: {} },
  source: 
   { start: { line: 1, column: 1 },
     input: Input { css: '// Hello world', id: '<input css 2>' },
     end: { line: 1, column: 14 } },
  text: 'Hello world' }

With the following result for node.toString(): /* Hello world*/

  1. It would be reasonable to assume that the preceding characters // be somewhere in the raws property.
  2. The .toString() output looks a little off. Should the .toString() method assume a space between the node.text of 'Hello world' and the ending */ for single line comments that are transformed to the CSS standard?
  3. The original form of the comment (// Hello world) isn't present anywhere in the node's properties, and we can't use node.source.input.css since it'll contain all css passed in the current operation. This is an important issue for inspection of comments.

Missing semicolon after call mixins

Original issue: mrmlnc/vscode-autoprefixer#8

syntax: require('postcss-less')

The same result when:

{
  syntax: require('postcss-less'),
  stringifier: require('postcss-less/dist/less-stringify')
}

Before autoprefixer:

.slick-btns {
    .absolute();
    .p-top-right();
}

After autoprefixer:

.slick-btns {
    .absolute()
    .p-top-right()
}

parser: require('postcss-less')

Before autoprefixer:

.slick-btns {
    .absolute();
    .p-top-right();
}

After autoprefixer:

.slick-btns {
    .absolute(){}
    .p-top-right(){}
}

Tree

Link: http://www.jsoneditoronline.org/?id=d8b06c4dceda7a5767928ae6c9987fc3
Source:

{
  "raws":{
    "semicolon":false,
    "after":"\n"
  },
  "type":"root",
  "nodes":[
    {
      "raws":{
        "before":"",
        "between":" ",
        "semicolon":false,
        "after":"\n"
      },
      "type":"rule",
      "nodes":[
        {
          "raws":{
            "before":"\n    ",
            "between":"",
            "after":"",
            "semicolon":true
          },
          "type":"rule",
          "source":{
            "start":{
              "line":2,
              "column":5
            },
            "input":{
              "css":".slick-btns {\n    .absolute();\n    .p-top-right();\n}\n",
              "id":"<input css 1>"
            },
            "end":{
              "line":2,
              "column":14
            }
          },
          "selector":".absolute()",
          "params":"()",
          "ruleWithoutBody":true,
          "extendRule":false,
          "important":false
        },
        {
          "raws":{
            "before":"\n    ",
            "between":"",
            "after":"",
            "semicolon":true
          },
          "type":"rule",
          "source":{
            "start":{
              "line":3,
              "column":5
            },
            "input":{
              "css":".slick-btns {\n    .absolute();\n    .p-top-right();\n}\n",
              "id":"<input css 1>"
            },
            "end":{
              "line":3,
              "column":17
            }
          },
          "selector":".p-top-right()",
          "params":"()",
          "ruleWithoutBody":true,
          "extendRule":false,
          "important":false
        }
      ],
      "source":{
        "start":{
          "line":1,
          "column":1
        },
        "input":{
          "css":".slick-btns {\n    .absolute();\n    .p-top-right();\n}\n",
          "id":"<input css 1>"
        },
        "end":{
          "line":4,
          "column":1
        }
      },
      "selector":".slick-btns"
    }
  ],
  "source":{
    "input":{
      "css":".slick-btns {\n    .absolute();\n    .p-top-right();\n}\n",
      "id":"<input css 1>"
    },
    "start":{
      "line":1,
      "column":1
    }
  }
}

mixinsAsAtRules flag doesn't generate the correct node types

in order for stylelint to parse the at rules properly, we need to override mixin nodes as atrule nodes (which is already happening) and additionally the child node (the mixin function block) must be overriden as a rule node.

Currently two stylelint rule tests are failing due to this issue (both are essentially the same).

.for(@n: 1) when (@n <= 10) { .n-@{n} #foo { } .for(@n + 1) } with rule selector-no-id

the #foo should be detected in there and a warning should be reported.

NOTE: this is how the postcss-scss module is functioning, and I'm just reporting on how postcss-less is differing at the moment.

Stylelint Issue

Hi,
Using the latest stylelint and postcss-less in a project, I'm seeing a similar error as noted in stylelint/stylelint#2637 (comment)

You may already be aware of this -- but is this more on their side or this one? If there's something I can help test I'm more than happy to help.

Detached ruleset processing returns incorrect selector

  • Node Version: v6.8.0
  • NPM Version: 4.6.1
  • postcss-less Version: 1.1.0

LESS

.test({
	.hello {
		.test {
		}
	}

	.fred {
	}
})

JavaScript

postcss()
  .process(lessText, { syntax })
  .then(function (result) {
    console.log(result.root.nodes[0].selector)
});

Expected Behavior

Expected selector to not include mixin parameter

Actual Behavior

selector includes entire input less text (including parameter)

How can we reproduce the behavior?

Using code above

Note: It's possible I do not understand how the parsed output is supposed to look for the provided less content.

Examples gulp

I created a test repository (gulp), and when I get a simple analysis of the paradoxical error.

[22:31:07] Starting 'lint:less'...
[22:31:07] 'lint:less' errored after 28 ms
[22:31:07] Error in plugin 'gulp-postcss'
Message:
    D:\projects\stylelint-less-test\style.less:3:21: Missed semicolon
blockquote {
  border: 1px solid #999 !important;
                    ^
  page-break-inside: avoid;

Please tell me what I'm doing wrong?

Parsing escaped string fails if the property is in a nested selector

This is quite an edge case, but consider this:

@testVar: 10px;

.test-wrap {
    .selector {
        height: calc(~"100vh - @{testVar}");
    }
}

This will throw an error with this stack trace:

CssSyntaxError: /dir/test.less:5:106: Unclosed quote
    at Input.error (/dir/node_modules/postcss/lib/input.js:61:22)
    at unclosed (/dir/node_modules/stylelint/node_modules/postcss-less/dist/tokenizer/unclosed.js:8:23)
    at tokenizeQuotes (/dir/node_modules/stylelint/node_modules/postcss-less/dist/tokenizer/tokenize-quotes.js:24:36)
    at tokenizeSymbol (/dir/node_modules/stylelint/node_modules/postcss-less/dist/tokenizer/tokenize-symbol.js:74:42)
    at lessTokenize (/dir/node_modules/stylelint/node_modules/postcss-less/dist/less-tokenize.js:48:38)
    at LessParser.tokenize (/dir/node_modules/stylelint/node_modules/postcss-less/dist/less-parser.js:51:54)
    at lessParse (/dir/node_modules/stylelint/node_modules/postcss-less/dist/less-parse.js:22:12)
    at new LazyResult (/dir/node_modules/postcss/lib/lazy-result.js:61:24)
    at Processor.process (/dir/node_modules/postcss/lib/processor.js:34:16)
    at lintString (/dir/node_modules/stylelint/dist/standalone.js:97:9)

If you take .selector out of .test-wrap it won't fail parsing.

Bracket selectors are considered mixin parameters.

  • Node Version: v6.10.3
  • NPM Version: v5.5.1
  • postcss-less Version: v1.1.3

LESS

.a,
.b[type=text] {
  color: blue;
}

JavaScript

let postCssLess = require('./dist/less-syntax');
const less = `
.a,
.b[type=text] {
  color: blue;
}
`;
const root = postCssLess.parse(less);
console.log(root);

Expected Behavior

No params set to match other postcss outputs.

Actual Behavior

Bracket selector is considered a params value.

How can we reproduce the behavior?

Use above JS file at project root.
This issue was found when using stylelint.

Unexpectedly ignored words in @import

  • Node Version: 8.3.0
  • NPM Version: 5.3.0
  • postcss-less Version: 1.1.0

LESS

@import missing "missing" "not missing";

JavaScript

require("postcss-less").parse('@import missing "missing" "not missing";')

Expected Behavior

Error thrown, or missing and "missing" being somewhere on the Import node.

Note: The example code is invalid Less ("malformed import statement").

Actual Behavior

The example Less code parses the same as this:

@import "not missing";

In other words, missing and "missing" are totally ignored.

How can we reproduce the behavior?

require("postcss-less").parse('@import missing "missing" "not missing";')

Background

This causes problems for Prettier when people forget the semicolon after the @import: prettier/prettier#2584

@import "../assets/font/league-gothic/league-gothic.css"

.ManagerPage {
  height: 100%;
}

... is turned into this by Prettier:

@import .ManagerPage {
  height: 100%;
}

... because "../assets/font/league-gothic/league-gothic.css" is entirely missing from the AST. Prettier would need:

  • Either an error to be thrown
  • or "../assets/font/league-gothic/league-gothic.css" being somewhere on the Import node so that it can be printed back.

Cannot read property '2' of undefined

While being run through stylelint (itself being run in the Atom package linter-stylelint) the following stack trace was hit while attempting to parse .border:

TypeError: Cannot read property '2' of undefined
    at LessParser.rule (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss-less\dist\less-parser.js:64:38)
    at LessParser.createRule (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss-less\dist\less-parser.js:110:18)
    at LessParser.ruleWithoutBody (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss-less\dist\less-parser.js:141:18)
    at LessParser.processEndOfRule (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss-less\dist\less-parser.js:173:22)
    at LessParser.word (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss-less\dist\less-parser.js:272:44)
    at LessParser.loop (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss-less\dist\less-parser.js:300:30)
    at lessParse (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss-less\dist\less-parse.js:23:12)
    at new LazyResult (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss\lib\lazy-result.js:70:24)
    at Processor.process (C:\Users\Landon Abney\.atom\packages\linter-stylelint\node_modules\postcss\lib\processor.js:117:12)
    at file:///C:/Users/Landon Abney/Documents/GitHub-release/linter-stylelint/node_modules/stylelint/lib/getPostcssResult.js:81:29

You can reproduce this by:

  • Install Atom, linter-stylelint and open a new .less file.
  • Start typing out a class name, at some point during typing it you will get a popup of the Cannot read property '2' of undefined error
  • You can get a stack trace by placing a breakpoint here

I'm sure there are more direct ways of triggering this ๐Ÿ˜›.

Note: Originally filed as AtomLinter/linter-stylelint#181

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.