less_dart 2.3.1

Native Dart Less compiler/builder/compressor for .less files and html style tags to css #

Less-builder for webdev serve, webdev build and Less-compiler for pub-run

This is a translation from Less 3.9.0 Javascript (over nodejs) to Dart. It is a pure Dart implementation for the server/developer side. The minimum dart sdk supported is 2.0.

As builder could work also with .html files, by converting <less> tags to <style> tags.

Use as Compiler or Builder #

The package is a Less compiler with wrappers for use in command line or as a dart builder. Also, it could be used in other Dart programs.

Pub-run usage #

If you get the full distribution (tar.gz file), the bin directory has the lessc.dart file for use with pub run:

CMD> pub run bin/lessc [args] file.less file.css

A working example: CMD> pub run bin/lessc test/less/charsets.less

Example with error output: CMD> pub run bin/lessc --no-color test/less/errors/import-subfolder1.less

For help: CMD> pub run bin/lessc --help

How to use in other dart programs #

You would need import the package, create the Less class and call the transform future. There is an example:

  import 'dart:io';
  import 'package:less_dart/less.dart';

  main() {
    List<String> args = [];
    Less less = new Less();


Use as a Dart Builder with webdev build or webdev serve #

Add the following lines to your pubspec.yaml:

  less_dart: any

Also, you will need a build.yaml file, with the configuration options.

One of them is the entry_points, to specify what files must be transformed. Could be:

entry_points: ['*.less', '*.html']

After that, all your .less files will be automatically transformed to corresponding .css files. Also the .less.html files will be processed. The standard default is *.less, but it could be modified by inclusion or exclusion paths. The exclusion path start with !. And * is supported in the paths.

The power of Dart builder is to chain builders, so a .less file will be converted to a .css file and this could be the source for another builder. Consider to use the less builder as the first in the chain.

builder.yaml Configuration #

In order to use the less builder, you must configure it:

          entry_points: ['path/to/file.less', 'or/other/file.less', 'path/to/file.less.html']
          include_path: 'path/to/directory/for/less/includes'
          cleancss: true or false or "option1 option2"
          compress: true or false
          other_flags: ['to include in the lessc command line', ...]
          enabled: true or false
  • entry_points (entry_point is equivalent):
    • If not supplied process all *.less files.
    • Could be a list of files to process, such as: ['web/file1.less', 'web/file2.less'].
    • Could be, also, a pattern for inclusion, as for example: ['*.less'].
    • Or have exclusion patterns that start with '!', such as: ['*.less', '!/lib/*.less'].

The output file will have the same name as the input, with .css extension for less. For html the file.less.html will be file.html.

less_source_cleanup is a post-builder that clean the *.less and *.less.html files in the build directory. It could be

  • enabled - true/false

Html transformation #

When a .less.html file is builded, the transformer look for <less>...</less> tags and then the equivalent <style>...</style> tags are added below, and at the same level.

All the <less> attributes are copied, except 'replace'. With this attribute <less> tags are removed in the final file.

The <less> tags in the final file are stamped with style="display:none" attribute, to avoid conflicts, easing debugging.

A .less.html could have various <less>...</less> pairs.

Also, you could use <style type="text/less">...</style> as equivalent to <less replace>...</less>.

Example for a polymer component:

<polymer-element name="test">
      @color: red;
      :host {
        background-color: @color;

Will result in:

<polymer-element name="test">
    <less style="display:none">
      @color: red;
      :host {
        background-color: @color;
      :host {
        background-color: red;

Custom Builder, Custom Plugin, Custom Functions #

You could clone the package to your local environment and modify it to add plugins. But, ...

Other way, is to inherit the builder in your project. Create a file lib\my_builder.dart which extends the less_dart LessBuilder (see example in: example\less_custom_builder.dart). The customOptions method could be override to modify the less options defining a custom plugin with custom functions.

Differences with official (js) version #

  • Javascript evaluation is not supported.

    • Alternatively you can use 'Custom Functions' (see example in: example/custom_functions_example.dart) from your dart project, or your custom builder.
  • Added option --banner=bannerfile.txt.

  • Added directive @options "--flags";. Intended to be the first line in a less file/tag, acts globally. This directive let specify individual options in batch processing. Example: @options "--strict-math=on --strict-units=on --include-path=test/data";.

  • Modified directive @plugin "lib";. lib is the plugin name and must exist as dart code in the plugins directory. By now are operative @plugin "less-plugin-advanced-color-functions"; and @plugin "less-plugin-clean-css" partially. You could define your custom plugins as indicated above.

  • Basic support for Custom CSS mixins as used by Polymer 1.0.

    • --mixin-name: {...}
    • @apply(--mixin-name);
  • Function rem to convert from px, pt or em to rem, defined as rem(fontSize, [baseFont]):

    • rem(16), rem(16px), rem(12pt), rem(1em), rem(20, 20)
    • 1rem, 1rem, 1rem, 1rem, 1rem
  • @import supports packages as source:

    • @import "packages/package-name/path/starting-in-lib";
    • @import "package://package-name/path/starting-in-lib";

    Also, option --include-path supports package, for easy use of shared mixins libraries:

    • --include-path=packages/package-name/path/starting-in-lib
    • --include-path=package://package-name/path/starting-in-lib

Known issues #

  • cleanCSS (as plugin) not fully implemented.

  • Error color output. In windows cmd don't support the color commands. ConEmu is an alternative.

Contribuitors #


License #

Copyright (c) 2009-2018 Alexis Sellier & The Core Less Team.

Copyright (c) 2014-2018 Adalberto Lacruz for dart translation.

Licensed under the Apache License.

2.3.1 (2019-07-08) #

  • Prepare for breaking change to HttpClientResponse return type (sdk #36900).

2.3.0 (2019-06-19) #

  • Less 3.9.0 code.
  • Dependencies upgrade.

2.2.0 (2018-11-19) #

  • Less 3.8.1 code, including namespaces and each function.

2.1.0 (2018-10-02) #

  • Less 3.0.4 code.
  • Build updated to 1.0.0.

2.0.1 (2018-09-09) #

  • Internal code to simplify types.

2.0.0 (2018-07-27) #

  • Dart 2.0.0-dev.68.0 compliant. It don't work with Dart 1.x.
  • Transformer replaced by builder.

1.1.1 (2017-12-18) #

  • Fix a crash that occurred in transformer mode in case if the less file imports another one from the same folder
  • Fix incorrect paths in relative imports

1.1.0 (2017-12-10) #

  • Less 3.0.0.-alpha.3 code.
  • imports in *.less which start from "packages/..." are now handled according paths in .packages file generated by pub. see Readme.
  • Linter suggested changes
  • Custom Functions annotation changed to @DefineMethod(...)
  • Internal node name Directive changed to AtRule, and Rule to Declaration. Could affect some plugins
  • options.definePlugin requires named parameters in load and options. See batch_test.

1.0.0 (2017-02-27) #

  • Min sdk 1.22.0
  • Enable strong mode
  • Boost speed
  • Analysis clean up
  • Some bugs removal

0.3.4 (2016-05-03) #

  • rem function to convert from px, pt or em

0.3.3 (2015-12-06) #

  • Basic support for Custom CSS mixins as used in Polymer 1.0: @apply(--mixin-name);

0.3.2 (2015-06-06) #

  • Repair transformer bugs

0.3.1 (2015-04-19) #

  • clean-css plugin with some optimizations

0.3.0 (2015-04-09) #

  • Less 2.5.0 code.
  • Custom transformer, custom plugin
  • Breaking Change: Custom functions go into custom plugin
  • @plugin directive with scope for custom functions

0.2.2 (2015-03-26) #

  • Transformer continous working with pub serve
  • Transformer accept .html files with <style type="text/less> tags

0.2.1 (2015-03-23) #

  • Transformer support for '.html' files (<less>..</less> -> <style>..</style>).
  • Transformer accept entry_points with * and !.
  • @options and @plugin directives.

0.2.0 (2015-03-16) #

  • Less 2.4.0 code.
  • Custom Functions.

0.1.4 (2015-01-12) #

  • Breaking Change: Transformer option 'build_mode' changed to 'dart' as default.
  • Updated Readme and some bugs resolved.

0.1.3 (2015-01-09) #

  • Final less 1.7.5 code.

0.1.2 (2015-01-06) #

  • SourceMaps generation.

0.1.1 (2015-01-02) #

  • Path package integration to normalize file path, according to windows/linux.

0.1.0 (2014-12-30) #


import 'dart:io';
import 'package:less_dart/less.dart';

void main() {
    final Less less = new Less();
    ]).then((int lessExitCode) {
      exitCode = lessExitCode;

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  less_dart: ^2.3.1

2. Install it

You can install packages from the command line:

with pub:

$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:less_dart/less.dart';
import 'package:less_dart/less_builder.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Aug 18, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19


Detected platforms: other

Platform components identified in package: build, io, mirrors.

Health suggestions

Fix lib/src/less_options.dart. (-1.99 points)

Analysis of lib/src/less_options.dart reported 4 hints:

line 3 col 9: Name libraries using lowercase_with_underscores.

line 280 col 13: DO use curly braces for all flow control structures.

line 309 col 13: DO use curly braces for all flow control structures.

line 315 col 13: DO use curly braces for all flow control structures.

Fix lib/src/import_manager.dart. (-1.49 points)

Analysis of lib/src/import_manager.dart reported 3 hints:

line 6 col 36: Use lowercase_with_underscores when specifying a library prefix.

line 224 col 11: Use rethrow to rethrow a caught exception.

line 235 col 9: Use rethrow to rethrow a caught exception.

Fix lib/src/functions/function_base.dart. (-1 points)

Analysis of lib/src/functions/function_base.dart reported 2 hints:

line 104 col 43: Use = to separate a named parameter from its default value.

line 104 col 70: Use = to separate a named parameter from its default value.

Fix additional 119 files with analysis or formatting issues. (-6.50 points)

Additional issues in the following files:

  • lib/src/tree/directive_base.dart (2 hints)
  • lib/src/tree/mixin_call.dart (2 hints)
  • lib/src/environment/bi_map.dart (1 hint)
  • lib/src/environment/environment.dart (1 hint)
  • lib/src/file_info.dart (1 hint)
  • lib/src/parser/parsers.dart (1 hint)
  • lib/src/plugins/less_plugin_advanced_color_functions/advanced_color_functions.dart (1 hint)
  • lib/src/tree/call.dart (1 hint)
  • lib/src/tree/options.dart (1 hint)
  • lib/src/tree/selector.dart (1 hint)
  • lib/src/visitor/process_extends_visitor.dart (1 hint)
  • lib/less.dart (Run dartfmt to format lib/less.dart.)
  • lib/less_builder.dart (Run dartfmt to format lib/less_builder.dart.)
  • lib/src/cleancss_options.dart (Run dartfmt to format lib/src/cleancss_options.dart.)
  • lib/src/contexts.dart (Run dartfmt to format lib/src/contexts.dart.)
  • lib/src/data/colors.dart (Run dartfmt to format lib/src/data/colors.dart.)
  • lib/src/data/constants.dart (Run dartfmt to format lib/src/data/constants.dart.)
  • lib/src/data/unit_conversions.dart (Run dartfmt to format lib/src/data/unit_conversions.dart.)
  • lib/src/environment/abstract_file_manager.dart (Run dartfmt to format lib/src/environment/abstract_file_manager.dart.)
  • lib/src/environment/base64_string.dart (Run dartfmt to format lib/src/environment/base64_string.dart.)
  • lib/src/environment/debug_functions.dart (Run dartfmt to format lib/src/environment/debug_functions.dart.)
  • lib/src/environment/file_file_manager.dart (Run dartfmt to format lib/src/environment/file_file_manager.dart.)
  • lib/src/environment/image_size.dart (Run dartfmt to format lib/src/environment/image_size.dart.)
  • lib/src/environment/more_list.dart (Run dartfmt to format lib/src/environment/more_list.dart.)
  • lib/src/environment/more_reg_exp.dart (Run dartfmt to format lib/src/environment/more_reg_exp.dart.)
  • lib/src/environment/package_resolver_provider.dart (Run dartfmt to format lib/src/environment/package_resolver_provider.dart.)
  • lib/src/environment/url_file_manager.dart (Run dartfmt to format lib/src/environment/url_file_manager.dart.)
  • lib/src/functions/boolean_functions.dart (Run dartfmt to format lib/src/functions/boolean_functions.dart.)
  • lib/src/functions/color_blend.dart (Run dartfmt to format lib/src/functions/color_blend.dart.)
  • lib/src/functions/color_functions.dart (Run dartfmt to format lib/src/functions/color_functions.dart.)
  • lib/src/functions/data_uri_functions.dart (Run dartfmt to format lib/src/functions/data_uri_functions.dart.)
  • lib/src/functions/default_func.dart (Run dartfmt to format lib/src/functions/default_func.dart.)
  • lib/src/functions/function_caller.dart (Run dartfmt to format lib/src/functions/function_caller.dart.)
  • lib/src/functions/function_registry.dart (Run dartfmt to format lib/src/functions/function_registry.dart.)
  • lib/src/functions/image_size_functions.dart (Run dartfmt to format lib/src/functions/image_size_functions.dart.)
  • lib/src/functions/list_functions.dart (Run dartfmt to format lib/src/functions/list_functions.dart.)
  • lib/src/functions/math_helper.dart (Run dartfmt to format lib/src/functions/math_helper.dart.)
  • lib/src/functions/number_functions.dart (Run dartfmt to format lib/src/functions/number_functions.dart.)
  • lib/src/functions/string_functions.dart (Run dartfmt to format lib/src/functions/string_functions.dart.)
  • lib/src/functions/svg_functions.dart (Run dartfmt to format lib/src/functions/svg_functions.dart.)
  • lib/src/functions/types_functions.dart (Run dartfmt to format lib/src/functions/types_functions.dart.)
  • lib/src/less_error.dart (Run dartfmt to format lib/src/less_error.dart.)
  • lib/src/lessc_helper.dart (Run dartfmt to format lib/src/lessc_helper.dart.)
  • lib/src/logger.dart (Run dartfmt to format lib/src/logger.dart.)
  • lib/src/output.dart (Run dartfmt to format lib/src/output.dart.)
  • lib/src/parser/charcode.dart (Run dartfmt to format lib/src/parser/charcode.dart.)
  • lib/src/parser/chunker.dart (Run dartfmt to format lib/src/parser/chunker.dart.)
  • lib/src/parser/entities.dart (Run dartfmt to format lib/src/parser/entities.dart.)
  • lib/src/parser/mixin.dart (Run dartfmt to format lib/src/parser/mixin.dart.)
  • lib/src/parser/parse_node.dart (Run dartfmt to format lib/src/parser/parse_node.dart.)
  • lib/src/parser/parser.dart (Run dartfmt to format lib/src/parser/parser.dart.)
  • lib/src/parser/parser_input.dart (Run dartfmt to format lib/src/parser/parser_input.dart.)
  • lib/src/plugins/less_plugin_advanced_color_functions/less_plugin_advanced_color_functions.dart (Run dartfmt to format lib/src/plugins/less_plugin_advanced_color_functions/less_plugin_advanced_color_functions.dart.)
  • lib/src/plugins/less_plugin_clean_css/clean_css_compatibility.dart (Run dartfmt to format lib/src/plugins/less_plugin_clean_css/clean_css_compatibility.dart.)
  • lib/src/plugins/less_plugin_clean_css/clean_css_context.dart (Run dartfmt to format lib/src/plugins/less_plugin_clean_css/clean_css_context.dart.)
  • lib/src/plugins/less_plugin_clean_css/clean_css_options.dart (Run dartfmt to format lib/src/plugins/less_plugin_clean_css/clean_css_options.dart.)
  • lib/src/plugins/less_plugin_clean_css/clean_css_processor.dart (Run dartfmt to format lib/src/plugins/less_plugin_clean_css/clean_css_processor.dart.)
  • lib/src/plugins/less_plugin_clean_css/clean_css_visitor.dart (Run dartfmt to format lib/src/plugins/less_plugin_clean_css/clean_css_visitor.dart.)
  • lib/src/plugins/less_plugin_clean_css/less_plugin_clean_css.dart (Run dartfmt to format lib/src/plugins/less_plugin_clean_css/less_plugin_clean_css.dart.)
  • lib/src/plugins/plugin.dart (Run dartfmt to format lib/src/plugins/plugin.dart.)
  • lib/src/plugins/plugin_loader.dart (Run dartfmt to format lib/src/plugins/plugin_loader.dart.)
  • lib/src/plugins/plugin_manager.dart (Run dartfmt to format lib/src/plugins/plugin_manager.dart.)
  • lib/src/render/parse_tree.dart (Run dartfmt to format lib/src/render/parse_tree.dart.)
  • lib/src/render/transform_tree.dart (Run dartfmt to format lib/src/render/transform_tree.dart.)
  • lib/src/sourcemap/source_map_builder.dart (Run dartfmt to format lib/src/sourcemap/source_map_builder.dart.)
  • lib/src/sourcemap/source_map_output.dart (Run dartfmt to format lib/src/sourcemap/source_map_output.dart.)
  • lib/src/tree/anonymous.dart (Run dartfmt to format lib/src/tree/anonymous.dart.)
  • lib/src/tree/apply.dart (Run dartfmt to format lib/src/tree/apply.dart.)
  • lib/src/tree/assignment.dart (Run dartfmt to format lib/src/tree/assignment.dart.)
  • lib/src/tree/at_rule.dart (Run dartfmt to format lib/src/tree/at_rule.dart.)
  • lib/src/tree/attribute.dart (Run dartfmt to format lib/src/tree/attribute.dart.)
  • lib/src/tree/color.dart (Run dartfmt to format lib/src/tree/color.dart.)
  • lib/src/tree/combinator.dart (Run dartfmt to format lib/src/tree/combinator.dart.)
  • lib/src/tree/comment.dart (Run dartfmt to format lib/src/tree/comment.dart.)
  • lib/src/tree/condition.dart (Run dartfmt to format lib/src/tree/condition.dart.)
  • lib/src/tree/debug_info.dart (Run dartfmt to format lib/src/tree/debug_info.dart.)
  • lib/src/tree/declaration.dart (Run dartfmt to format lib/src/tree/declaration.dart.)
  • lib/src/tree/detached_ruleset.dart (Run dartfmt to format lib/src/tree/detached_ruleset.dart.)
  • lib/src/tree/dimension.dart (Run dartfmt to format lib/src/tree/dimension.dart.)
  • lib/src/tree/element.dart (Run dartfmt to format lib/src/tree/element.dart.)
  • lib/src/tree/expression.dart (Run dartfmt to format lib/src/tree/expression.dart.)
  • lib/src/tree/extend.dart (Run dartfmt to format lib/src/tree/extend.dart.)
  • lib/src/tree/import.dart (Run dartfmt to format lib/src/tree/import.dart.)
  • lib/src/tree/javascript.dart (Run dartfmt to format lib/src/tree/javascript.dart.)
  • lib/src/tree/js_eval_node_mixin.dart (Run dartfmt to format lib/src/tree/js_eval_node_mixin.dart.)
  • lib/src/tree/keyword.dart (Run dartfmt to format lib/src/tree/keyword.dart.)
  • lib/src/tree/media.dart (Run dartfmt to format lib/src/tree/media.dart.)
  • lib/src/tree/merge_rules_mixin.dart (Run dartfmt to format lib/src/tree/merge_rules_mixin.dart.)
  • lib/src/tree/mixin_definition.dart (Run dartfmt to format lib/src/tree/mixin_definition.dart.)
  • lib/src/tree/namespace_value.dart (Run dartfmt to format lib/src/tree/namespace_value.dart.)
  • lib/src/tree/negative.dart (Run dartfmt to format lib/src/tree/negative.dart.)
  • lib/src/tree/node.dart (Run dartfmt to format lib/src/tree/node.dart.)
  • lib/src/tree/nodeset.dart (Run dartfmt to format lib/src/tree/nodeset.dart.)
  • lib/src/tree/operation.dart (Run dartfmt to format lib/src/tree/operation.dart.)
  • lib/src/tree/paren.dart (Run dartfmt to format lib/src/tree/paren.dart.)
  • lib/src/tree/property.dart (Run dartfmt to format lib/src/tree/property.dart.)
  • lib/src/tree/quoted.dart (Run dartfmt to format lib/src/tree/quoted.dart.)
  • lib/src/tree/ruleset.dart (Run dartfmt to format lib/src/tree/ruleset.dart.)
  • lib/src/tree/tree_api.dart (Run dartfmt to format lib/src/tree/tree_api.dart.)
  • lib/src/tree/unicode_descriptor.dart (Run dartfmt to format lib/src/tree/unicode_descriptor.dart.)
  • lib/src/tree/unit.dart (Run dartfmt to format lib/src/tree/unit.dart.)
  • lib/src/tree/url.dart (Run dartfmt to format lib/src/tree/url.dart.)
  • lib/src/tree/value.dart (Run dartfmt to format lib/src/tree/value.dart.)
  • lib/src/tree/variable.dart (Run dartfmt to format lib/src/tree/variable.dart.)
  • lib/src/tree/variable_call.dart (Run dartfmt to format lib/src/tree/variable_call.dart.)
  • lib/src/utils.dart (Run dartfmt to format lib/src/utils.dart.)
  • lib/src/visitor/css_visitor_utils.dart (Run dartfmt to format lib/src/visitor/css_visitor_utils.dart.)
  • lib/src/visitor/extend_finder_visitor.dart (Run dartfmt to format lib/src/visitor/extend_finder_visitor.dart.)
  • lib/src/visitor/ignition_visitor.dart (Run dartfmt to format lib/src/visitor/ignition_visitor.dart.)
  • lib/src/visitor/import_detector.dart (Run dartfmt to format lib/src/visitor/import_detector.dart.)
  • lib/src/visitor/import_visitor.dart (Run dartfmt to format lib/src/visitor/import_visitor.dart.)
  • lib/src/visitor/join_selector_visitor.dart (Run dartfmt to format lib/src/visitor/join_selector_visitor.dart.)
  • lib/src/visitor/set_tree_visibility_visitor.dart (Run dartfmt to format lib/src/visitor/set_tree_visibility_visitor.dart.)
  • lib/src/visitor/to_css_visitor.dart (Run dartfmt to format lib/src/visitor/to_css_visitor.dart.)
  • lib/src/visitor/visitor.dart (Run dartfmt to format lib/src/visitor/visitor.dart.)
  • lib/src/visitor/visitor_base.dart (Run dartfmt to format lib/src/visitor/visitor_base.dart.)
  • lib/src_builder/dot_html_builder.dart (Run dartfmt to format lib/src_builder/dot_html_builder.dart.)
  • lib/src_builder/entry_points.dart (Run dartfmt to format lib/src_builder/entry_points.dart.)
  • lib/src_builder/less_builder_options.dart (Run dartfmt to format lib/src_builder/less_builder_options.dart.)


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
build >=1.0.0 <2.0.0 1.1.6
build_config >=0.3.1 <0.5.0 0.4.1+1
meta >=1.0.4 <2.0.0 1.1.7
mime >=0.9.0 <0.12.0 0.9.6+3
package_resolver >=1.0.2 <2.0.0 1.0.10
path >=1.4.1 <2.0.0 1.6.4
source_maps >=0.10.2 <0.12.0 0.10.8
source_span >=1.4.0 <2.0.0 1.5.5
utf >=0.9.0 <0.12.0 0.9.0+5
Transitive dependencies
analyzer 0.38.0
args 1.5.2
async 2.3.0
charcode 1.1.2
checked_yaml 1.0.2
collection 1.14.12
convert 2.1.1
crypto 2.1.1+1
csslib 0.16.1
front_end 0.1.22
glob 1.1.7
html 0.14.0+2
http 0.12.0+2
http_parser 3.1.3
json_annotation 3.0.0
kernel 0.3.22
package_config 1.1.0
pedantic 1.8.0+1
pub_semver 1.4.2
pubspec_parse 0.1.5
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
watcher 0.9.7+12
yaml 2.1.16
Dev dependencies
logging >=0.11.0 <0.12.0 0.11.3+2
mockito >=1.0.0 <5.0.0
stack_trace >=1.7.2 <2.0.0
test >=0.12.20+2 <2.0.0