diff --git a/CHANGELOG.md b/CHANGELOG.md index 928c8d87f3..54b810597c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 3.4.3 (non-ruby only) + +* Fix malformed `math.div` expressions. [#1225](https://github.com/twbs/bootstrap-sass/pull/1225) + +## 3.4.2 (non-ruby only) + +* Compatibility with Sass 1.33. [#1221](https://github.com/twbs/bootstrap-sass/pull/1221) + ## 3.4.0 * Bootstrap rubygem now depends on SassC instead of Sass. diff --git a/assets/javascripts/bootstrap-sprockets.js b/assets/javascripts/bootstrap-sprockets.js index 37468b35d4..fb01d63f04 100644 --- a/assets/javascripts/bootstrap-sprockets.js +++ b/assets/javascripts/bootstrap-sprockets.js @@ -1,12 +1,12 @@ -//= require ./bootstrap/affix +//= require ./bootstrap/transition //= require ./bootstrap/alert //= require ./bootstrap/button //= require ./bootstrap/carousel //= require ./bootstrap/collapse //= require ./bootstrap/dropdown //= require ./bootstrap/modal -//= require ./bootstrap/scrollspy //= require ./bootstrap/tab -//= require ./bootstrap/transition +//= require ./bootstrap/affix +//= require ./bootstrap/scrollspy //= require ./bootstrap/tooltip //= require ./bootstrap/popover diff --git a/assets/stylesheets/bootstrap/_carousel.scss b/assets/stylesheets/bootstrap/_carousel.scss index 52a1f7bff0..684360ff88 100644 --- a/assets/stylesheets/bootstrap/_carousel.scss +++ b/assets/stylesheets/bootstrap/_carousel.scss @@ -1,3 +1,4 @@ +@use "sass:math"; // // Carousel // -------------------------------------------------- @@ -244,16 +245,16 @@ .icon-next { width: ($carousel-control-font-size * 1.5); height: ($carousel-control-font-size * 1.5); - margin-top: ($carousel-control-font-size / -2); + margin-top: math.div($carousel-control-font-size, -2); font-size: ($carousel-control-font-size * 1.5); } .glyphicon-chevron-left, .icon-prev { - margin-left: ($carousel-control-font-size / -2); + margin-left: math.div($carousel-control-font-size, -2); } .glyphicon-chevron-right, .icon-next { - margin-right: ($carousel-control-font-size / -2); + margin-right: math.div($carousel-control-font-size, -2); } } diff --git a/assets/stylesheets/bootstrap/_code.scss b/assets/stylesheets/bootstrap/_code.scss index 8e2b2a7f43..6299ddbf3f 100644 --- a/assets/stylesheets/bootstrap/_code.scss +++ b/assets/stylesheets/bootstrap/_code.scss @@ -1,3 +1,4 @@ +@use "sass:math"; // // Code (inline and block) // -------------------------------------------------- @@ -40,8 +41,8 @@ kbd { // Blocks of code pre { display: block; - padding: (($line-height-computed - 1) / 2); - margin: 0 0 ($line-height-computed / 2); + padding: math.div(($line-height-computed - 1), 2); + margin: 0 0 math.div($line-height-computed, 2); font-size: ($font-size-base - 1); // 14px to 13px line-height: $line-height-base; color: $pre-color; diff --git a/assets/stylesheets/bootstrap/_forms.scss b/assets/stylesheets/bootstrap/_forms.scss index d2e2bac5cd..00951b3f27 100644 --- a/assets/stylesheets/bootstrap/_forms.scss +++ b/assets/stylesheets/bootstrap/_forms.scss @@ -1,3 +1,4 @@ +@use "sass:math"; // // Forms // -------------------------------------------------- @@ -581,7 +582,7 @@ textarea.form-control { // Reposition the icon because it's now within a grid column and columns have // `position: relative;` on them. Also accounts for the grid gutter padding. .has-feedback .form-control-feedback { - right: floor(($grid-gutter-width / 2)); + right: floor(math.div($grid-gutter-width, 2)); } // Form group sizes diff --git a/assets/stylesheets/bootstrap/_jumbotron.scss b/assets/stylesheets/bootstrap/_jumbotron.scss index 7215b99131..07a0f98ff7 100644 --- a/assets/stylesheets/bootstrap/_jumbotron.scss +++ b/assets/stylesheets/bootstrap/_jumbotron.scss @@ -1,3 +1,4 @@ +@use "sass:math"; // // Jumbotron // -------------------------------------------------- @@ -16,7 +17,7 @@ } p { - margin-bottom: ($jumbotron-padding / 2); + margin-bottom: math.div($jumbotron-padding, 2); font-size: $jumbotron-font-size; font-weight: 200; } @@ -27,8 +28,8 @@ .container &, .container-fluid & { - padding-right: ($grid-gutter-width / 2); - padding-left: ($grid-gutter-width / 2); + padding-right: math.div($grid-gutter-width, 2); + padding-left: math.div($grid-gutter-width, 2); border-radius: $border-radius-large; // Only round corners at higher resolutions if contained in a container } diff --git a/assets/stylesheets/bootstrap/_navbar.scss b/assets/stylesheets/bootstrap/_navbar.scss index 5d9093a93c..135aba0aed 100644 --- a/assets/stylesheets/bootstrap/_navbar.scss +++ b/assets/stylesheets/bootstrap/_navbar.scss @@ -1,3 +1,4 @@ +@use "sass:math"; // // Navbars // -------------------------------------------------- @@ -228,7 +229,7 @@ // the nav the full height of the horizontal nav (above 768px). .navbar-nav { - margin: ($navbar-padding-vertical / 2) (-$navbar-padding-horizontal); + margin: math.div($navbar-padding-vertical, 2) (-$navbar-padding-horizontal); > li > a { padding-top: 10px; diff --git a/assets/stylesheets/bootstrap/_type.scss b/assets/stylesheets/bootstrap/_type.scss index c63cc4c071..ac2eccdc97 100644 --- a/assets/stylesheets/bootstrap/_type.scss +++ b/assets/stylesheets/bootstrap/_type.scss @@ -1,3 +1,4 @@ +@use "sass:math"; // // Typography // -------------------------------------------------- @@ -25,7 +26,7 @@ h1, .h1, h2, .h2, h3, .h3 { margin-top: $line-height-computed; - margin-bottom: ($line-height-computed / 2); + margin-bottom: math.div($line-height-computed, 2); small, .small { @@ -35,8 +36,8 @@ h3, .h3 { h4, .h4, h5, .h5, h6, .h6 { - margin-top: ($line-height-computed / 2); - margin-bottom: ($line-height-computed / 2); + margin-top: math.div($line-height-computed, 2); + margin-bottom: math.div($line-height-computed, 2); small, .small { @@ -56,7 +57,7 @@ h6, .h6 { font-size: $font-size-h6; } // ------------------------- p { - margin: 0 0 ($line-height-computed / 2); + margin: 0 0 math.div($line-height-computed, 2); } .lead { @@ -74,10 +75,10 @@ p { // Emphasis & misc // ------------------------- -// Ex: (12px small font / 14px base font) * 100% = about 85% +// Ex: math.div(12px small font, 14px base font) * 100% = about 85% small, .small { - font-size: floor((100% * $font-size-small / $font-size-base)); + font-size: floor(math.div(100% * $font-size-small, $font-size-base)); } mark, @@ -136,7 +137,7 @@ mark, // ------------------------- .page-header { - padding-bottom: (($line-height-computed / 2) - 1); + padding-bottom: (math.div($line-height-computed, 2) - 1); margin: ($line-height-computed * 2) 0 $line-height-computed; border-bottom: 1px solid $page-header-border-color; } @@ -149,7 +150,7 @@ mark, ul, ol { margin-top: 0; - margin-bottom: ($line-height-computed / 2); + margin-bottom: math.div($line-height-computed, 2); ul, ol { margin-bottom: 0; @@ -239,7 +240,7 @@ abbr[data-original-title] { // Blockquotes blockquote { - padding: ($line-height-computed / 2) $line-height-computed; + padding: math.div($line-height-computed, 2) $line-height-computed; margin: 0 0 $line-height-computed; font-size: $blockquote-font-size; border-left: 5px solid $blockquote-border-color; diff --git a/assets/stylesheets/bootstrap/_variables.scss b/assets/stylesheets/bootstrap/_variables.scss index 898ef14adc..02fe1f43b7 100644 --- a/assets/stylesheets/bootstrap/_variables.scss +++ b/assets/stylesheets/bootstrap/_variables.scss @@ -1,4 +1,5 @@ $bootstrap-sass-asset-helper: false !default; +@use "sass:math"; // // Variables // -------------------------------------------------- @@ -365,8 +366,8 @@ $container-lg: $container-large-desktop !default; $navbar-height: 50px !default; $navbar-margin-bottom: $line-height-computed !default; $navbar-border-radius: $border-radius-base !default; -$navbar-padding-horizontal: floor(($grid-gutter-width / 2)) !default; -$navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2) !default; +$navbar-padding-horizontal: floor(math.div($grid-gutter-width, 2)) !default; +$navbar-padding-vertical: math.div(($navbar-height - $line-height-computed), 2) !default; $navbar-collapse-max-height: 340px !default; $navbar-default-color: #777 !default; diff --git a/assets/stylesheets/bootstrap/mixins/_grid-framework.scss b/assets/stylesheets/bootstrap/mixins/_grid-framework.scss index 2b84cb13c8..6160a048e3 100644 --- a/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +++ b/assets/stylesheets/bootstrap/mixins/_grid-framework.scss @@ -1,3 +1,4 @@ +@use "sass:math"; // Framework grid generation // // Used only by Bootstrap to generate the correct number of grid classes given @@ -13,8 +14,8 @@ // Prevent columns from collapsing when empty min-height: 1px; // Inner gutter via padding - padding-right: floor(($grid-gutter-width / 2)); - padding-left: ceil(($grid-gutter-width / 2)); + padding-right: floor(math.div($grid-gutter-width, 2)); + padding-left: ceil(math.div($grid-gutter-width, 2)); } } @@ -33,12 +34,12 @@ @mixin calc-grid-column($index, $class, $type) { @if ($type == width) and ($index > 0) { .col-#{$class}-#{$index} { - width: percentage(($index / $grid-columns)); + width: percentage(math.div($index, $grid-columns)); } } @if ($type == push) and ($index > 0) { .col-#{$class}-push-#{$index} { - left: percentage(($index / $grid-columns)); + left: percentage(math.div($index, $grid-columns)); } } @if ($type == push) and ($index == 0) { @@ -48,7 +49,7 @@ } @if ($type == pull) and ($index > 0) { .col-#{$class}-pull-#{$index} { - right: percentage(($index / $grid-columns)); + right: percentage(math.div($index, $grid-columns)); } } @if ($type == pull) and ($index == 0) { @@ -58,7 +59,7 @@ } @if ($type == offset) { .col-#{$class}-offset-#{$index} { - margin-left: percentage(($index / $grid-columns)); + margin-left: percentage(math.div($index, $grid-columns)); } } } diff --git a/assets/stylesheets/bootstrap/mixins/_grid.scss b/assets/stylesheets/bootstrap/mixins/_grid.scss index 884ac4f5b0..0cee189a97 100644 --- a/assets/stylesheets/bootstrap/mixins/_grid.scss +++ b/assets/stylesheets/bootstrap/mixins/_grid.scss @@ -1,11 +1,12 @@ +@use "sass:math"; // Grid system // // Generate semantic grid columns with these mixins. // Centered container element @mixin container-fixed($gutter: $grid-gutter-width) { - padding-right: ceil(($gutter / 2)); - padding-left: floor(($gutter / 2)); + padding-right: ceil(math.div($gutter, 2)); + padding-left: floor(math.div($gutter, 2)); margin-right: auto; margin-left: auto; @include clearfix; @@ -13,8 +14,8 @@ // Creates a wrapper for a series of columns @mixin make-row($gutter: $grid-gutter-width) { - margin-right: floor(($gutter / -2)); - margin-left: ceil(($gutter / -2)); + margin-right: floor(math.div($gutter, -2)); + margin-left: ceil(math.div($gutter, -2)); @include clearfix; } @@ -22,46 +23,46 @@ @mixin make-xs-column($columns, $gutter: $grid-gutter-width) { position: relative; float: left; - width: percentage(($columns / $grid-columns)); + width: percentage(math.div($columns, $grid-columns)); min-height: 1px; - padding-right: ($gutter / 2); - padding-left: ($gutter / 2); + padding-right: math.div($gutter, 2); + padding-left: math.div($gutter, 2); } @mixin make-xs-column-offset($columns) { - margin-left: percentage(($columns / $grid-columns)); + margin-left: percentage(math.div($columns, $grid-columns)); } @mixin make-xs-column-push($columns) { - left: percentage(($columns / $grid-columns)); + left: percentage(math.div($columns, $grid-columns)); } @mixin make-xs-column-pull($columns) { - right: percentage(($columns / $grid-columns)); + right: percentage(math.div($columns, $grid-columns)); } // Generate the small columns @mixin make-sm-column($columns, $gutter: $grid-gutter-width) { position: relative; min-height: 1px; - padding-right: ($gutter / 2); - padding-left: ($gutter / 2); + padding-right: math.div($gutter, 2); + padding-left: math.div($gutter, 2); @media (min-width: $screen-sm-min) { float: left; - width: percentage(($columns / $grid-columns)); + width: percentage(math.div($columns, $grid-columns)); } } @mixin make-sm-column-offset($columns) { @media (min-width: $screen-sm-min) { - margin-left: percentage(($columns / $grid-columns)); + margin-left: percentage(math.div($columns, $grid-columns)); } } @mixin make-sm-column-push($columns) { @media (min-width: $screen-sm-min) { - left: percentage(($columns / $grid-columns)); + left: percentage(math.div($columns, $grid-columns)); } } @mixin make-sm-column-pull($columns) { @media (min-width: $screen-sm-min) { - right: percentage(($columns / $grid-columns)); + right: percentage(math.div($columns, $grid-columns)); } } @@ -69,27 +70,27 @@ @mixin make-md-column($columns, $gutter: $grid-gutter-width) { position: relative; min-height: 1px; - padding-right: ($gutter / 2); - padding-left: ($gutter / 2); + padding-right: math.div($gutter, 2); + padding-left: math.div($gutter, 2); @media (min-width: $screen-md-min) { float: left; - width: percentage(($columns / $grid-columns)); + width: percentage(math.div($columns, $grid-columns)); } } @mixin make-md-column-offset($columns) { @media (min-width: $screen-md-min) { - margin-left: percentage(($columns / $grid-columns)); + margin-left: percentage(math.div($columns, $grid-columns)); } } @mixin make-md-column-push($columns) { @media (min-width: $screen-md-min) { - left: percentage(($columns / $grid-columns)); + left: percentage(math.div($columns, $grid-columns)); } } @mixin make-md-column-pull($columns) { @media (min-width: $screen-md-min) { - right: percentage(($columns / $grid-columns)); + right: percentage(math.div($columns, $grid-columns)); } } @@ -97,26 +98,26 @@ @mixin make-lg-column($columns, $gutter: $grid-gutter-width) { position: relative; min-height: 1px; - padding-right: ($gutter / 2); - padding-left: ($gutter / 2); + padding-right: math.div($gutter, 2); + padding-left: math.div($gutter, 2); @media (min-width: $screen-lg-min) { float: left; - width: percentage(($columns / $grid-columns)); + width: percentage(math.div($columns, $grid-columns)); } } @mixin make-lg-column-offset($columns) { @media (min-width: $screen-lg-min) { - margin-left: percentage(($columns / $grid-columns)); + margin-left: percentage(math.div($columns, $grid-columns)); } } @mixin make-lg-column-push($columns) { @media (min-width: $screen-lg-min) { - left: percentage(($columns / $grid-columns)); + left: percentage(math.div($columns, $grid-columns)); } } @mixin make-lg-column-pull($columns) { @media (min-width: $screen-lg-min) { - right: percentage(($columns / $grid-columns)); + right: percentage(math.div($columns, $grid-columns)); } } diff --git a/assets/stylesheets/bootstrap/mixins/_nav-divider.scss b/assets/stylesheets/bootstrap/mixins/_nav-divider.scss index 2e6da02a47..80a39d43ad 100644 --- a/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +++ b/assets/stylesheets/bootstrap/mixins/_nav-divider.scss @@ -1,10 +1,11 @@ +@use "sass:math"; // Horizontal dividers // // Dividers (basically an hr) within dropdowns and nav lists @mixin nav-divider($color: #e5e5e5) { height: 1px; - margin: (($line-height-computed / 2) - 1) 0; + margin: (math.div($line-height-computed, 2) - 1) 0; overflow: hidden; background-color: $color; } diff --git a/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss b/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss index c8fbf1a7d6..146d9961c4 100644 --- a/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss +++ b/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss @@ -1,9 +1,10 @@ +@use "sass:math"; // Navbar vertical align // // Vertically center elements in the navbar. // Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin. @mixin navbar-vertical-align($element-height) { - margin-top: (($navbar-height - $element-height) / 2); - margin-bottom: (($navbar-height - $element-height) / 2); + margin-top: math.div(($navbar-height - $element-height), 2); + margin-bottom: math.div(($navbar-height - $element-height), 2); } diff --git a/package.json b/package.json index d947d8f9a5..88f432110d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bootstrap-sass", - "version": "3.4.1", + "version": "3.4.3", "description": "bootstrap-sass is a Sass-powered version of Bootstrap 3, ready to drop right into your Sass powered applications.", "main": "assets/javascripts/bootstrap.js", "style": "assets/stylesheets/_bootstrap.scss", @@ -33,7 +33,7 @@ "url": "https://github.com/twbs/bootstrap-sass/issues" }, "devDependencies": { - "node-sass": "^4.9.3", + "sass": "^1.33", "mincer": "~1.4.0", "ejs": "~2.6.1" }, diff --git a/tasks/converter/less_conversion.rb b/tasks/converter/less_conversion.rb index c6cd7e03de..d87a6d0d6a 100644 --- a/tasks/converter/less_conversion.rb +++ b/tasks/converter/less_conversion.rb @@ -173,6 +173,7 @@ def convert_to_scss(file) file = replace_calculation_semantics(file) file = replace_file_imports(file) file = wrap_at_groups_with_at_root(file) + file = replace_division(file) file end @@ -182,6 +183,44 @@ def wrap_at_groups_with_at_root(file) } end + def replace_division(less) + re = %r{ + (? + (?[[:alpha:]\.]+)? + \( + (?: + (?> + (? + [^()/]+ + | + \([^/]+\) + ) + \s+ + / + \s+ + (? + [^()/]+ + | + \([^/]+\) + ) + ) + | + \g + ) + \) + ) + }x + return less if less !~ re + "@use \"sass:math\";\n" + less.gsub(re) do + named_captures = $~.named_captures + callee = named_captures['callee'] + dividend = named_captures['dividend'] + divisor = named_captures['divisor'] + expression = "math.div(#{dividend}, #{divisor})" + callee.nil? ? expression : "#{callee}(#{expression})" + end + end + def sass_fn_exists(fn) %Q{(#{fn}("") != unquote('#{fn}("")'))} end @@ -691,13 +730,13 @@ def open_brace_pos(css, from, depth = 0) from - s.pos + 1 end - # insert substitutions into text at positions (Range or Fixnum) + # insert substitutions into text at positions (Range or Integer) # substitutions can be passed as array or as yields from the &block called with |substring, position, text| # position is a range (begin..end) def replace_substrings_at(text, positions, replacements = nil, &block) offset = 0 positions.each_with_index do |p, i| - p = (p...p) if p.is_a?(Fixnum) + p = (p...p) if p.is_a?(Integer) from = p.begin + offset to = p.end + offset p = p.exclude_end? ? (from...to) : (from..to) diff --git a/tasks/converter/network.rb b/tasks/converter/network.rb index aa62be5e3e..cef78d4377 100644 --- a/tasks/converter/network.rb +++ b/tasks/converter/network.rb @@ -19,7 +19,7 @@ def read_files(path, files) log_http_get_files files, full_path, false files.map do |name| Thread.start { - contents[name] = open("#{full_path}/#{name}").read + contents[name] = URI.open("#{full_path}/#{name}").read Thread.exclusive { write_cached_files path, name => contents[name] } } end.each(&:join) @@ -56,7 +56,7 @@ def get_file(url) File.read(cache_path, mode: 'rb') else log_http_get_file url, false - content = open(url).read + content = URI.open(url).read File.open(cache_path, 'wb') { |f| f.write content } content end diff --git a/templates/project/_bootstrap-variables.sass b/templates/project/_bootstrap-variables.sass index 8777e1149c..d5bc1a14fa 100644 --- a/templates/project/_bootstrap-variables.sass +++ b/templates/project/_bootstrap-variables.sass @@ -1,5 +1,6 @@ -// Override Bootstrap variables here (defaults from bootstrap-sass v3.4.0): +// Override Bootstrap variables here (defaults from bootstrap-sass v3.4.1): +@use "sass:math"; // // Variables // -------------------------------------------------- @@ -366,8 +367,8 @@ // $navbar-height: 50px // $navbar-margin-bottom: $line-height-computed // $navbar-border-radius: $border-radius-base -// $navbar-padding-horizontal: floor(($grid-gutter-width / 2)) -// $navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2) +// $navbar-padding-horizontal: floor(math.div($grid-gutter-width, 2)) +// $navbar-padding-vertical: math.div(($navbar-height - $line-height-computed), 2) // $navbar-collapse-max-height: 340px // $navbar-default-color: #777