less/less-plugin-clean-css

Strange less-syntax bug

Craigy- opened this issue · 10 comments

I'm trying to compile files with this code:

@isresponsive: false;
@font-size-base: 16px;
.set-value_(@property; @value; @responsive: @isresponsive) {
  // String, percentage and relative unit values
  .setter(@p; @v) when not (isnumber(@v)), (ispercentage(@v)), (isem(@v)), (isunit(@v, rem)),
                           (isunit(@v, ex)), (isunit(@v, ch)), (isunit(@v, vw)), (isunit(@v, vh)),
                           (isunit(@v, vmin)), (isunit(@v, vmax)) {
    @{p}+_: @v;
  }
  // Non-unit and pixel values
  .setter(@p; @v) when (default()) {
    & when (@responsive) {
      @{p}+_: unit((@v / @font-size-base), rem);
    }
    & when not (@responsive) {
      @{p}+_: unit(@v, px);
    }
  }
  .setter(@property; @value);
}
.set-value(@args...) when (length(@args) > 1) {
  .r(@a) when (extract(@a, length(@a)) = true), (extract(@a, length(@a)) = false) {
    @l: (length(@a) - 1);
    @responsive: extract(@a, length(@a));
  }
  .r(@a) when (default()) {
    @l: length(@a);
    @responsive: @isresponsive;
  }
  .r(@args);

  .i; .i(@i: @l) when (@i > 1) {
    .i((@i - 2));
    @property: extract(@args, (@i - 1));
    @values:   extract(@args,  @i);
    .j(@property; @values; @responsive);
  }
  .j(@p; @v; @r; @j: length(@v)) when (@j > 0) {
    .j(@p; @v; @r; (@j - 1));
    .set-value_(@p; extract(@v, @j); @r);
  }
}

and it was compiled as well.

But this (it compiled as well without clean-css enabled):

@isresponsive: false;
@font-size-base: 16px;
.set-value_(@property; @value; @responsive: @isresponsive) {
  // String, percentage and relative unit values
  .setter(@p; @v) when not (isnumber(@v)), (ispercentage(@v)), (isem(@v)), (isunit(@v, rem)),
                           (isunit(@v, ex)), (isunit(@v, ch)), (isunit(@v, vw)), (isunit(@v, vh)),
                           (isunit(@v, vmin)), (isunit(@v, vmax)) {
    @{p}+_: @v;
  }
  // Non-unit and pixel values
  .setter(@p; @v) when (default()) {
    & when (@responsive) {
      @{p}+_: unit((@v / @font-size-base), rem);
    }
    & when not (@responsive) {
      @{p}+_: unit(@v, px);
    }
  }
  .setter(@property; @value);
}
.set-value(@args...) when (length(@args) > 1) {
  @l: length(@args);
  @responsive: @isresponsive;

  .r(@a) when (extract(@a, length(@a)) = true), (extract(@a, length(@a)) = false) {
    @l: (length(@a) - 1);
    @responsive: extract(@a, length(@a));
  }
  .r(@args);

  .i; .i(@i: @l) when (@i > 1) {
    .i((@i - 2));
    @property: extract(@args, (@i - 1));
    @values:   extract(@args,  @i);
    .j(@property; @values; @responsive);
  }
  .j(@p; @v; @r; @j: length(@v)) when (@j > 0) {
    .j(@p; @v; @r; (@j - 1));
    .set-value_(@p; extract(@v, @j); @r);
  }
}

thrown an error:
111

Both examples are incomplete. (Even assuming .set-value only misses closing }, it's still impossible to tests/reproduce anything w/o knowing what parameters this mixin is invoked with).

the error looks like it is occurring in cleancss - if you create an example of the output from less and try it in cleancss, i expect it will error.. so this probably needs raising with cleancss..

My bad, it's something wrong in mixin... But first variant works as well.
I'm updated code - now it must be reproduced as well..

seven-phases-max: code is based on yours from Stackoverflow :) I wrote to you email about this but has no answer. Can you help to add support for full 'font' properties?

@CraigY

code is based on yours from Stackoverflow

(probably, though I assume it was not that bloated originally... For a use-case like above I feel I would suggest something like http://stackoverflow.com/questions/27192493)

No, here is your original mixin: http://stackoverflow.com/questions/25083818/

Here my final version of mixin. It contains all that I want, but it very terrible to look. Is it possible to optimize something here?

@isresponsive: true;
@font-size-base: 16px;

// Universal value setter
.set-value_(@property; @value; @responsive: @isresponsive) {
  // String, percentage and relative unit values
  .setter(@p; @v) when not (isnumber(@v)), (ispercentage(@v)), (isem(@v)), (isunit(@v, rem)),
                           (isunit(@v, ex)), (isunit(@v, ch)), (isunit(@v, vw)), (isunit(@v, vh)),
                           (isunit(@v, vmin)), (isunit(@v, vmax)) {
    @{p}+_: @v;
  }
  // Non-unit and pixel values
  .setter(@p; @v) when (default()) {
    & when (@responsive) {
      @{p}+_: unit((@v / @font-size-base), rem);
    }
    & when not (@responsive) {
      @{p}+_: unit(@v, px);
    }
  }
  .setter(@property; @value);

  // Font support
  & when (@property = font) {
    @check: ~`function(){var v="@{value}";return !!v.match(/\//)}()`;
    @v1-value: ~`function(){var v="@{value}";return parseFloat(v=v.replace(/^(\d+).*\/(\d+).*$/, '$1'))}()`;
    @v1-unit: ~`function(){var v="@{value}";return v=v.replace(/^\d+(.*)\/\d+(.*)$/, '$1')}()`;
    @v2-value: ~`function(){var v="@{value}";return parseFloat(v=v.replace(/^(\d+).*\/(\d+).*$/, '$2'))}()`;
    @v2-unit: ~`function(){var v="@{value}";return v=v.replace(/^\d+(.*)\/\d+(.*)$/, '$2')}()`;
    & when (@check) {
      .set-value(font-size; unit(@v1-value, @v1-unit); line-height; unit(@v2-value, @v2-unit); @responsive);
    }
  }
}
.set-value(@args...) when (length(@args) > 1) {
  .r(@a) when (extract(@a, length(@a)) = true), (extract(@a, length(@a)) = false) {
    @l: (length(@a) - 1);
    @responsive: extract(@a, length(@a));
  }
  .r(@a) when (default()) {
    @l: length(@a);
    @responsive: @isresponsive;
  }
  .r(@args);
  .i; .i(@i: @l) when (@i > 1) {
    .i((@i - 2));
    @property: extract(@args, (@i - 1));
    @values:   extract(@args,  @i);
    .j(@property; @values; @responsive);
  }
  .j(@p; @v; @r; @j: length(@v)) when (@j > 0) {
    .j(@p; @v; @r; (@j - 1));
    .set-value_(@p; extract(@v, @j); @r);
  }
}

Example:

.set-value(font; 14px/230% 'Arial'; margin: 0 16 0 0);

Output:

font: 14px/230% Arial, Helvetica, sans-serif;
font-size: 0.875rem;
line-height: 230%;
margin: 0 1rem 0 0;

Sorry for that the discussion went beyond of project "less-plugin-clean-css".

(Well, my answer in that SO topic only shows how to simplify already about to exist mixin for the particular px/rem thing. Sure If I would know you're about to develop your own DSL I would try to dissuade... Unfortunately all wrong things of such approach are just too tedious and too broad to disimantle in brief (and of course it would be too offtopic here)).

Thanks for answer.