or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-postcss-less

LESS parser for PostCSS that enables PostCSS transformations and plugins to work directly with LESS source code without compilation.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/postcss-less@6.0.x

To install, run

npx @tessl/cli install tessl/npm-postcss-less@6.0.0

index.mddocs/

postcss-less

postcss-less is a PostCSS syntax parser specifically designed for LESS stylesheets. It enables PostCSS transformations and plugins to work directly with LESS source code without compilation, serving as a bridge between LESS syntax and the PostCSS ecosystem.

Package Information

  • Package Name: postcss-less
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install postcss-less
  • Node.js Version: >=12
  • Peer Dependencies: postcss ^8.3.5

Core Imports

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

For ES6 modules:

import syntax from 'postcss-less';

Individual imports:

const { parse, stringify, nodeToString } = require('postcss-less');

Basic Usage

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

// Parse LESS code with PostCSS
const lessCode = `
// This is an inline comment
@primary-color: #428bca;
@secondary-color: lighten(@primary-color, 20%);

.header {
  color: @primary-color;
  .nav {
    background: @secondary-color;
  }
}

.mixin-example() {
  border-radius: 4px;
}

.button {
  .mixin-example();
  &:hover {
    color: darken(@primary-color, 10%);
  }
}
`;

// Process with PostCSS and postcss-less syntax
postcss([
  // Add your PostCSS plugins here
])
  .process(lessCode, { syntax })
  .then(function (result) {
    console.log(result.css); // Processed LESS code
  });

Architecture

postcss-less extends the PostCSS parser and stringifier to handle LESS-specific syntax:

  • LessParser: Extends PostCSS Parser to recognize LESS constructs (variables, mixins, inline comments, imports with options)
  • LessStringifier: Extends PostCSS Stringifier to output LESS syntax correctly
  • Node Handlers: Specialized processors for different LESS node types (imports, variables, mixins, inline comments, interpolation)
  • AST Extensions: Adds LESS-specific properties to PostCSS AST nodes for semantic information

Capabilities

LESS Parsing

Parse LESS source code into a PostCSS-compatible AST with LESS-specific node properties.

/**
 * Parse LESS source code into PostCSS AST
 * @param {string} less - LESS source code to parse
 * @param {Object} options - PostCSS Input options (from, map, etc.)
 * @returns {Root} PostCSS Root AST node with LESS-specific extensions
 */
function parse(less, options);

Usage Example:

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

const lessCode = '@color: red; .test { color: @color; }';
const root = syntax.parse(lessCode, { from: 'input.less' });

// Access LESS-specific node properties
root.walkAtRules((rule) => {
  if (rule.variable) {
    console.log(`Variable: ${rule.name} = ${rule.value}`);
  }
});

LESS Stringification

Convert PostCSS AST nodes back to LESS syntax strings.

/**
 * Convert PostCSS AST nodes to LESS syntax strings
 * @param {Node} node - PostCSS AST node to stringify  
 * @param {Function} builder - String builder callback function
 */
function stringify(node, builder);

Usage Example:

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

const lessCode = '.mixin() { color: red; }';
const root = syntax.parse(lessCode);

syntax.stringify(root, (str) => {
  process.stdout.write(str);
});

Node String Conversion

Convert individual AST nodes to their string representation.

/**
 * Convert a single AST node to its string representation
 * @param {Node} node - PostCSS AST node to convert
 * @returns {string} String representation of the node
 */
function nodeToString(node);

Usage Example:

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

const lessCode = '@var: 10px; .test { margin: @var; }';
const root = syntax.parse(lessCode);

root.walkAtRules((rule) => {
  if (rule.variable) {
    const nodeStr = syntax.nodeToString(rule);
    console.log(`Variable node: ${nodeStr}`);
  }
});

LESS-Specific Features

Variable Support

LESS variables (@variable-name: value;) are parsed with special properties:

// Variable AtRule node properties
interface VariableAtRule extends AtRule {
  variable: true;      // Marks node as LESS variable
  name: string;        // Variable name (without @)
  value: string;       // Variable value
}

Import Support

LESS @import statements with options are supported:

// Import AtRule node properties  
interface ImportAtRule extends AtRule {
  import: true;        // Marks node as import
  filename: string;    // Imported filename
  options?: string;    // Import options (reference, inline, etc.)
}

Example:

@import (reference) "variables.less";
@import "mixins.less";

Mixin Support

LESS mixins (.mixin() and #mixin) are parsed with special properties:

// Mixin AtRule node properties
interface MixinAtRule extends AtRule {
  mixin: true;         // Marks node as mixin call
  important?: true;    // Present if mixin uses !important
}

Function Support

LESS each functions and other function calls are supported:

// Function AtRule node properties
interface FunctionAtRule extends AtRule {
  function: true;      // Marks node as function call
  params: string;      // Function parameters
}

Example:

each(@list, {
  .column-@{value} {
    width: 100% / @length;
  }
});

Interpolation Support

LESS variable interpolation (@{variable}) is processed during parsing to handle dynamic property names and values.

Inline Comment Support

Double-slash comments (//) are supported with special properties:

// Inline Comment node properties
interface InlineComment extends Comment {
  inline: true;        // Marks comment as inline
  raws: {
    begin: '//';       // Comment delimiter
    left: string;      // Whitespace before text
    right: string;     // Whitespace after text
  };
}

Extend Support

LESS :extend() syntax is recognized on both rules and declarations:

// Extend Rule/Declaration properties
interface ExtendNode extends Rule | Declaration {
  extend: true;        // Marks node as using extend
}

Error Handling

postcss-less follows PostCSS error handling patterns. Parse errors throw CssSyntaxError:

const postcss = require('postcss');
const syntax = require('postcss-less');
const CssSyntaxError = require('postcss/lib/css-syntax-error');

try {
  const result = await postcss().process('.@{]', { syntax });
} catch (error) {
  if (error instanceof CssSyntaxError) {
    console.log(`Parse error at line ${error.line}, column ${error.column}: ${error.message}`);
  }
}

PostCSS Integration

Use as a syntax plugin with PostCSS processors:

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

// Apply autoprefixer to LESS code
postcss([autoprefixer])
  .process(lessCode, { 
    syntax,
    from: 'input.less',
    to: 'output.less'
  })
  .then(result => {
    console.log(result.css); // LESS code with vendor prefixes
  });

Types

// Main syntax object
interface PostcssLessSyntax {
  parse: (less: string, options?: ProcessOptions) => Root;
  stringify: (node: Node, builder: (str: string) => void) => void;
  nodeToString: (node: Node) => string;
}

// PostCSS types (from postcss package)
interface ProcessOptions {
  from?: string;
  to?: string;
  map?: SourceMapOptions | boolean;
  parser?: Parser;
  stringifier?: Stringifier;
}

interface Root extends Container {
  type: 'root';
  walk(callback: (node: Node) => boolean | void): Root;
  walkAtRules(callback: (atRule: AtRule) => boolean | void): Root;
  walkComments(callback: (comment: Comment) => boolean | void): Root;
  walkDecls(callback: (decl: Declaration) => boolean | void): Root;
  walkRules(callback: (rule: Rule) => boolean | void): Root;
}

interface AtRule extends Container {
  type: 'atrule';
  name: string;
  params: string;
  // LESS extensions
  import?: boolean;
  filename?: string;
  options?: string;
  variable?: boolean;
  value?: string;
  mixin?: boolean;
  function?: boolean;
  important?: boolean;
}

interface Comment extends Node {
  type: 'comment';
  text: string;
  // LESS extensions
  inline?: boolean;
}

interface Rule extends Container {
  type: 'rule';
  selector: string;
  // LESS extensions
  extend?: boolean;
}

interface Declaration extends Node {
  type: 'decl';
  prop: string;
  value: string;
  // LESS extensions
  extend?: boolean;
}