Skip to content

Less 5.0 Changes / Features (WIP) #33

Closed
@matthew-dean

Description

@matthew-dean

EDIT: I've moved this to a 5.0 plan vs. 4.0 to make a 4.0 release with some incremental changes.

I've mentioned as an aside in other Less issues that I've been experimenting with some work that is likely, but not guaranteed, to make it into a 5.0 PR.

I thought I'd start a list of 5.0 features / changes that I intend to update as I progress. All of this is a WIP, subject to change, and open for comment.

5.0 Codebase / Repo Changes

  1. The repo is converted to a mono-repo, with a separation into packages that can be not only installed separately and extended in other projects, but also helps define separation of concerns. So, the future less package would import a few other @less/[name] packages to build the Node.js version.
  2. The source code is in TypeScript. This is saving my brain. The historical codebase, over time, has had added a number of object mutations which are undocumented: on nodes, on the options object, on the context object, etc. Just reading a file, sometimes there's no explicit import that tells you where a parameter comes from, so I'm doing the archeological work of figuring out where an object comes from, what its properties will be, and of what type. In places, I've discovered properties or parameters that do absolutely nothing, which TypeScript can flag while developing. This also will allow auto-generation of API docs, since everything is already forced to have very clear definitions. It's slow work, but will make the codebase way more maintainable.
  3. The parser is re-written from scratch based on Chevrotain. Chevrotain is super-fast and easy to debug, but the real reason I'm doing it is that I'm collaborating directly with the developer of Chevrotain, and he's super-knowledgable about parsing theory.
  4. The parser is split into an explicit CSS parser, and that parser is then extended for Less. This has two advantages: a) this creates, automatically, a spec-compliant CSS parser which can be installed/maintained on its own, b) it makes it extremely clear, in a self-documenting way, exactly which parts of Less are extensions of CSS, which makes the Less parser more maintainable.
  5. Both the CSS and Less parsers have a CST (concrete syntax tree) stage, which makes for easy integration into CSS/Less-related tooling, as it can return multiple parse errors (and you can begin parsing at any level) with a tree of exact input / location vs. failing a parse at the first parse error.
  6. The AST nodes are also in the process of being re-written, to make similar nodes re-use the same behavior and normalize the API (Some discussion about that here: Less Public API Proposal - Next version #31).

Note: A lot of this refactoring is as a direct result of lessons learned while developing 3.0 (#28)

5.0 Breaking changes (so far)

TL;DR 5.0 Grammar changes:

/**
 * To be aligned more with CSS function calls,
 * mixin calls require a left-parentheses after
 * the identifier.
 */
.mixin;    // error
.mixin
();        // error
.mixin();  // pass


/** Namespacing similarly removes whitespace and > */
#ns > .mixin();  // error
// whitespace between ns / mixin
#ns
.mixin();    // error
#ns.mixin(); // pass


/** whitespace still allowed in mixin definitions */
.mixin (@arg: 1) {
   value: @arg
}


/** Variable leaks removed */
.mixin() {
  @val: 1;
}
.a {
  .mixin();
  value: @val;  // error
}
// workaround using lookups
.a {
  value: .mixin[@val];  // pass
}

/** Forced root division removed */
prop: 6 ./ 2;   // error
prop: (6 / 2);  // pass

/** Permissive parsing fallback removed in variable assignment */
// this next line of code is allowed in 3.x, but is an error in 5.x
// it's too ambiguous to the user what should happen with 1 + @foo
@foo: 2;
@var: () => 1 + @foo;
--var: @var;

// instead write:
@var: ~"() => 1 + @{foo}";

/** Identifiers conform to CSS grammar */
@3: foo; // error, as an identifier must start with a-z
.-() { } // error, as an identifier can start with `-` only if followed by a-z

/** Legacy experimental CSS selectors removed */
// the following is now invalid
.shadow ^ .dom,
body ^^ .shadow {
  display: done;
}

Options changes

  1. compress is removed - whitespace is preserved as-is; CSS compression is left to other better tools
  2. --math=parens-division is the default math option
  3. --math=strict-legacy is removed

Other Details

TBD

I'll add more to this as I go, but feel free to ask questions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions