Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for converting Bootstrap 4 to less #1

Open
mediafreakch opened this issue Jan 7, 2017 · 13 comments

Comments

Projects
None yet
5 participants
@mediafreakch
Copy link
Owner

commented Jan 7, 2017

Currently the plugin cannot convert all of Bootstrap 4 (v4.0.0-alpha.6). They are using some quite advanced SASS functions that the plugin doesn't convert yet. The LESS compiler will throw errors if you try to compile the converted files.

Here's a list of what I found so far:

  • @each
  • comparable()
  • @warn - afaik there's no equivalent in LESS, maybe just strip it?
  • @else if (not) - this one might be tricky
  • map-values()
  • ( 0: ( x: 0, y: 0)) (maps) - there is no map data-type in less. maybe this can help: https://github.com/seven-phases-max/less-plugin-lists

I'll start working from the top. Ideas about how to convert / support the map data-type in LESS would be appreciated.

@matthew-dean

This comment has been minimized.

Copy link

commented Jan 7, 2017

Would this help you as a starting point? https://github.com/Crunch/Granola/blob/master/lib/map.js

It's a work-in-progress, so there might be some edge cases where the value doesn't evaluate IIRC (haven't worked on it in a while). But I got it to a point where it was working pretty well for most uses.

I could probably release it as a separate Less.js plugin at some point.

It allows definitions like this:

@set {
        options {
            ui: default;
            elements: default;
            theme: default;
        }
        colors {
        	dark {
        	    color: black;
        	}
        	light {
        	    color: white;
        	}
        }
    }

And then you can get a value with a get() function.

.box {
  color: get('colors.dark.color');
}
@matthew-dean

This comment has been minimized.

Copy link

commented Jan 7, 2017

Btw, something like maps might come to native Less. See the discussion at: less/less-meta#12

The thread is long, but the proposal is to allow accessing variables / properties of namespaces & mixins, with a syntax like:

#namespace {
  prop1: value;
  @var1: value;
}
.box {
  value1: #namespace['prop1'];
  value2: #namespace['@var1'];
}

That would effectively turn ANY single-selector ruleset into a map, so there'd be no need for another "data type".

@matthew-dean

This comment has been minimized.

Copy link

commented Jan 7, 2017

And I wrote an "each" function here: less/less.js@f52b073

Yes, @warn has no equivalent or current value in Less.

Elseif is a little trickier. There's an order of evaluation, but not an order of operations, since the languages are dissimilar in their approach. See: https://getcrunch.co/2015/10/08/less-the-worlds-most-misunderstood-css-pre-processor/ (Not trying to be showy, just hoping these links will help you, because I think this is a great project to have working.

Mixins match based on guards, but guards don't carry forward the result of the previous test.

So you can do:

@if($a = 1) { }
@if($a = 2) { }

But it's much trickier to do this:

@if($a = 1) { }
@elseif($a > 0) { }

...because Less is not a program like Sass is. Each block is independently evaluated by evaluation rules. However... maybe you could do it like:

.mixin() when (@a = 1) { }
.mixin() when (not (@a = 1)) and (@a > 0) { }

So, you have to exclusively negate the first condition if you want to only evaluate the second if the first doesn't match. And, of course, you'd have to negate two conditions if there are multiple elseifs. (And then you immediately call the mixin.)

So, an if / elseif / else would be like:

.mixin() when (@a = 1) { }
.mixin() when (not (@a = 1)) and (@a > 0) { }
.mixin() when (default()) { }
.mixin();

(Or you do these things in a plugin.)

@matthew-dean

This comment has been minimized.

Copy link

commented Jan 7, 2017

The one thing you're going to need to be careful about is variable scope and lazy-loading. Sass's variable scope is different, and in Sass, variables can't be referenced before they're defined (unlike Less).

So, in Sass, you get:

$var: 1;
.box {
  $var: 2;
  val: $var; // value is 2
  $var: 3;
}
$new_var: $var;  // value is 3

In Less, you get:

@var: 1;
.box {
  @var: 2;
  val: @var; // value is 3
  @var: 3;
}
@new_var: @var;  // value is 1
@mediafreakch

This comment has been minimized.

Copy link
Owner Author

commented Jan 9, 2017

Thanks, those inputs definitely help! Regarding maps I will also look into re-using https://github.com/seven-phases-max/less-plugin-lists .

Btw your proposal on @elseif is exactly what I already did for @if and @else, just that this one is a bit harder to write a regex for ;)

I should find time this week and will keep you posted about the progress!

@elliottcrush

This comment has been minimized.

Copy link

commented Aug 8, 2018

Hi @mediafreakch - 👋

I (and my company, Holidayextras) are very interested in seeing bootstrap 4 support within this module. Can I offer any of our support in seeing this issue resolved? We currently use Bootstrap 3 (Less) for a number of different brands (using subtle variable overrides) but would like to benefit from extending our brands to hand pick BS4 components (via a module like this).

@mediafreakch

This comment has been minimized.

Copy link
Owner Author

commented Aug 8, 2018

@elliottcrush Support is more than welcome 😀. You see an (outdated?) list of issues with converting BS4 with this module on top in the first post. LESS has evolved in the meantime as well, so you might find it easier to implement a conversion algorithm these days...

@matthew-dean

This comment has been minimized.

Copy link

commented Aug 9, 2018

Yes, there's a native if() and each() function now in Less, along with maps and lookups! And there's also this: https://github.com/seanCodes/bootstrap-less-port, but that doesn't use some of Less's newer functions / features.

@elliottcrush

This comment has been minimized.

Copy link

commented Aug 13, 2018

Awesome thanks @mediafreakch & @matthew-dean - I'll try and get to that as soon as.

@Jany-M

This comment has been minimized.

Copy link

commented Aug 21, 2018

@elliottcrush could this package help for map-merge and other issues?

@Jany-M

This comment has been minimized.

Copy link

commented Aug 21, 2018

Also, these conversions throw an error (from _variables.scss).

SASS

$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px
) !default;

@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
@include _assert-starts-at-zero($grid-breakpoints);

$link-hover-color:          darken($link-color, 15%) !default;
$table-dark-accent-bg:        rgba($white, .05) !default;
$table-dark-hover-bg:         rgba($white, .075) !default;
$table-dark-border-color:     lighten($gray-900, 7.5%) !default;

$custom-file-text: (
  en: "Browse"
) !default;

Converted LESS

@grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px
);

._assert-ascending(@grid-breakpoints, "@grid-breakpoints");
._assert-starts-at-zero(@grid-breakpoints);

@input-btn-focus-color:       fade(@component-active-bg, (.25*100)); // error evaluating function `fade`: color.toHSL is not a function
@link-hover-color:          darken(@link-color, 15%); // error evaluating function `darken`: color.toHSL is not a function
@table-dark-border-color:     lighten(@gray-900, 7.5%); // same type as above
// & several others of the same type

@custom-file-text: (
  en: "Browse"
);

I'm available for testing!

@calvinjuarez

This comment has been minimized.

Copy link

commented Dec 7, 2018

For those looking for Bootstrap 4 for Less that's ready to use right now, there's https://github.com/seanCodes/bootstrap-less-port.

@matthew-dean

This comment has been minimized.

Copy link

commented Dec 7, 2018

@Jany-M I think the color.toHSL is not a function error is an internal Less bug that happens when there's not a valid color value, I've seen it pop up more than once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.