bootstrap-sass 3.3.0.1 → 3.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +8 -14
  4. data/CHANGELOG.md +64 -0
  5. data/CONTRIBUTING.md +8 -1
  6. data/Gemfile +1 -4
  7. data/LICENSE +2 -1
  8. data/README.md +135 -114
  9. data/Rakefile +58 -12
  10. data/assets/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  11. data/assets/fonts/bootstrap/glyphicons-halflings-regular.svg +273 -214
  12. data/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  13. data/assets/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  14. data/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  15. data/assets/javascripts/bootstrap/affix.js +11 -9
  16. data/assets/javascripts/bootstrap/alert.js +6 -5
  17. data/assets/javascripts/bootstrap/button.js +25 -16
  18. data/assets/javascripts/bootstrap/carousel.js +25 -18
  19. data/assets/javascripts/bootstrap/collapse.js +13 -12
  20. data/assets/javascripts/bootstrap/dropdown.js +51 -47
  21. data/assets/javascripts/bootstrap/modal.js +112 -35
  22. data/assets/javascripts/bootstrap/popover.js +31 -27
  23. data/assets/javascripts/bootstrap/scrollspy.js +19 -22
  24. data/assets/javascripts/bootstrap/tab.js +14 -12
  25. data/assets/javascripts/bootstrap/tooltip.js +255 -56
  26. data/assets/javascripts/bootstrap/transition.js +5 -5
  27. data/assets/javascripts/bootstrap-sprockets.js +2 -2
  28. data/assets/javascripts/bootstrap.js +1282 -962
  29. data/assets/javascripts/bootstrap.min.js +6 -0
  30. data/assets/stylesheets/_bootstrap-compass.scss +2 -0
  31. data/assets/stylesheets/_bootstrap-mincer.scss +4 -2
  32. data/assets/stylesheets/_bootstrap-sprockets.scss +2 -0
  33. data/assets/stylesheets/_bootstrap.scss +6 -0
  34. data/assets/stylesheets/bootstrap/_alerts.scss +8 -3
  35. data/assets/stylesheets/bootstrap/_badges.scss +16 -5
  36. data/assets/stylesheets/bootstrap/_breadcrumbs.scss +3 -1
  37. data/assets/stylesheets/bootstrap/_button-groups.scss +11 -14
  38. data/assets/stylesheets/bootstrap/_buttons.scss +18 -10
  39. data/assets/stylesheets/bootstrap/_carousel.scss +40 -36
  40. data/assets/stylesheets/bootstrap/_close.scss +2 -0
  41. data/assets/stylesheets/bootstrap/_code.scss +3 -3
  42. data/assets/stylesheets/bootstrap/_component-animations.scss +2 -2
  43. data/assets/stylesheets/bootstrap/_dropdowns.scss +24 -24
  44. data/assets/stylesheets/bootstrap/_forms.scss +149 -103
  45. data/assets/stylesheets/bootstrap/_glyphicons.scss +85 -12
  46. data/assets/stylesheets/bootstrap/_grid.scss +10 -0
  47. data/assets/stylesheets/bootstrap/_input-groups.scss +10 -5
  48. data/assets/stylesheets/bootstrap/_jumbotron.scss +11 -5
  49. data/assets/stylesheets/bootstrap/_labels.scss +1 -1
  50. data/assets/stylesheets/bootstrap/_list-group.scss +30 -34
  51. data/assets/stylesheets/bootstrap/_media.scss +19 -0
  52. data/assets/stylesheets/bootstrap/_mixins.scss +1 -0
  53. data/assets/stylesheets/bootstrap/_modals.scss +9 -8
  54. data/assets/stylesheets/bootstrap/_navbar.scss +77 -82
  55. data/assets/stylesheets/bootstrap/_navs.scss +4 -6
  56. data/assets/stylesheets/bootstrap/_normalize.scss +13 -13
  57. data/assets/stylesheets/bootstrap/_pager.scss +2 -2
  58. data/assets/stylesheets/bootstrap/_pagination.scss +15 -17
  59. data/assets/stylesheets/bootstrap/_panels.scss +16 -6
  60. data/assets/stylesheets/bootstrap/_popovers.scss +50 -58
  61. data/assets/stylesheets/bootstrap/_print.scss +90 -98
  62. data/assets/stylesheets/bootstrap/_progress-bars.scss +3 -3
  63. data/assets/stylesheets/bootstrap/_responsive-embed.scss +10 -10
  64. data/assets/stylesheets/bootstrap/_responsive-utilities.scss +11 -6
  65. data/assets/stylesheets/bootstrap/_scaffolding.scss +18 -7
  66. data/assets/stylesheets/bootstrap/_tables.scss +24 -24
  67. data/assets/stylesheets/bootstrap/_theme.scss +57 -22
  68. data/assets/stylesheets/bootstrap/_thumbnails.scss +1 -1
  69. data/assets/stylesheets/bootstrap/_tooltip.scss +49 -32
  70. data/assets/stylesheets/bootstrap/_type.scss +12 -12
  71. data/assets/stylesheets/bootstrap/_utilities.scss +0 -1
  72. data/assets/stylesheets/bootstrap/_variables.scss +27 -17
  73. data/assets/stylesheets/bootstrap/_wells.scss +2 -2
  74. data/assets/stylesheets/bootstrap/mixins/_alerts.scss +2 -1
  75. data/assets/stylesheets/bootstrap/mixins/_background-variant.scss +2 -1
  76. data/assets/stylesheets/bootstrap/mixins/_border-radius.scss +4 -4
  77. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +20 -11
  78. data/assets/stylesheets/bootstrap/mixins/_center-block.scss +1 -1
  79. data/assets/stylesheets/bootstrap/mixins/_clearfix.scss +1 -1
  80. data/assets/stylesheets/bootstrap/mixins/_forms.scss +4 -4
  81. data/assets/stylesheets/bootstrap/mixins/_gradients.scss +6 -8
  82. data/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +2 -2
  83. data/assets/stylesheets/bootstrap/mixins/_grid.scss +8 -8
  84. data/assets/stylesheets/bootstrap/mixins/_hide-text.scss +3 -3
  85. data/assets/stylesheets/bootstrap/mixins/_image.scss +5 -10
  86. data/assets/stylesheets/bootstrap/mixins/_list-group.scss +3 -2
  87. data/assets/stylesheets/bootstrap/mixins/_opacity.scss +2 -3
  88. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +2 -1
  89. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +18 -0
  90. data/assets/stylesheets/bootstrap/mixins/_resize.scss +1 -1
  91. data/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss +1 -5
  92. data/assets/stylesheets/bootstrap/mixins/_tab-focus.scss +3 -3
  93. data/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +2 -1
  94. data/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +4 -4
  95. data/bootstrap-sass.gemspec +10 -9
  96. data/bower.json +6 -20
  97. data/composer.json +2 -2
  98. data/eyeglass-exports.js +7 -0
  99. data/lib/bootstrap-sass/engine.rb +6 -1
  100. data/lib/bootstrap-sass/version.rb +2 -2
  101. data/lib/bootstrap-sass.rb +32 -13
  102. data/package-lock.json +1611 -0
  103. data/package.json +21 -7
  104. data/sache.json +1 -1
  105. data/tasks/bower.rake +2 -5
  106. data/tasks/converter/fonts_conversion.rb +1 -1
  107. data/tasks/converter/js_conversion.rb +7 -5
  108. data/tasks/converter/less_conversion.rb +48 -37
  109. data/tasks/converter/network.rb +12 -7
  110. data/tasks/converter.rb +1 -1
  111. data/templates/project/_bootstrap-variables.sass +27 -18
  112. data/templates/project/styles.sass +3 -0
  113. data/test/compilation_test.rb +24 -12
  114. data/test/dummy_rails/app/assets/stylesheets/{application.css.sass → application.sass} +0 -0
  115. data/test/dummy_rails/app/views/pages/root.html.slim +43 -0
  116. data/test/dummy_rails/config/application.rb +2 -1
  117. data/test/dummy_rails/config/boot.rb +1 -1
  118. data/test/dummy_rails/config/environments/development.rb +0 -3
  119. data/test/dummy_rails/config/environments/production.rb +7 -1
  120. data/test/dummy_rails/config/environments/test.rb +9 -1
  121. data/test/dummy_sass_only/Gemfile +1 -1
  122. data/test/dummy_sass_only/compile.rb +14 -7
  123. data/test/dummy_sass_only/import_all.scss +2 -0
  124. data/test/gemfiles/default.gemfile +3 -0
  125. data/test/node_mincer_test.rb +2 -3
  126. data/test/node_sass_compile_test.sh +4 -3
  127. data/test/sass_test.rb +10 -7
  128. data/test/sprockets_rails_test.rb +12 -8
  129. data/test/support/dummy_rails_integration.rb +1 -1
  130. data/test/support/reporting.rb +10 -0
  131. data/test/test_helper.rb +3 -2
  132. metadata +56 -46
  133. data/test/compass_test.rb +0 -9
  134. data/test/dummy_rails/log/development.log +0 -0
  135. data/test/dummy_sass_only/import_all.sass +0 -2
  136. data/test/gemfiles/sass_3_2.gemfile +0 -6
  137. data/test/gemfiles/sass_3_3.gemfile +0 -6
  138. data/test/gemfiles/sass_3_4.gemfile +0 -7
  139. data/test/gemfiles/sass_head.gemfile +0 -6
data/package.json CHANGED
@@ -1,8 +1,17 @@
1
1
  {
2
2
  "name": "bootstrap-sass",
3
- "version": "3.3.0",
4
- "description": "bootstrap-sass is a Sass-powered version of Bootstrap, ready to drop right into your Sass powered applications.",
5
- "main": "index.js",
3
+ "version": "3.4.1",
4
+ "description": "bootstrap-sass is a Sass-powered version of Bootstrap 3, ready to drop right into your Sass powered applications.",
5
+ "main": "assets/javascripts/bootstrap.js",
6
+ "style": "assets/stylesheets/_bootstrap.scss",
7
+ "sass": "assets/stylesheets/_bootstrap.scss",
8
+ "files": [
9
+ "assets",
10
+ "eyeglass-exports.js",
11
+ "CHANGELOG.md",
12
+ "LICENSE",
13
+ "README.md"
14
+ ],
6
15
  "repository": {
7
16
  "type": "git",
8
17
  "url": "git://github.com/twbs/bootstrap-sass"
@@ -10,7 +19,8 @@
10
19
  "keywords": [
11
20
  "bootstrap",
12
21
  "sass",
13
- "css"
22
+ "css",
23
+ "eyeglass-module"
14
24
  ],
15
25
  "contributors": [
16
26
  "Thomas McDonald",
@@ -23,8 +33,12 @@
23
33
  "url": "https://github.com/twbs/bootstrap-sass/issues"
24
34
  },
25
35
  "devDependencies": {
26
- "node-sass": "~1.0",
27
- "mincer": "~1.1",
28
- "ejs": "~1.0"
36
+ "node-sass": "^4.9.3",
37
+ "mincer": "~1.4.0",
38
+ "ejs": "~2.6.1"
39
+ },
40
+ "eyeglass": {
41
+ "exports": "eyeglass-exports.js",
42
+ "needs": "^0.7.1"
29
43
  }
30
44
  }
data/sache.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "bootstrap-sass",
3
- "description": "bootstrap-sass is a Sass-powered version of Bootstrap, ready to drop right into your Sass powered applications",
3
+ "description": "bootstrap-sass is a Sass-powered version of Bootstrap 3, ready to drop right into your Sass powered applications.",
4
4
  "tags": ["bootstrap", "grid", "typography", "buttons", "ui", "responsive-web-design"]
5
5
  }
data/tasks/bower.rake CHANGED
@@ -15,16 +15,13 @@ namespace :bower do
15
15
  require 'bootstrap-sass'
16
16
  Dir.chdir Bootstrap.gem_path do
17
17
  spec = JSON.parse(File.read 'bower.json')
18
- js_paths = File.read(File.join Bootstrap.javascripts_path, 'bootstrap-sprockets.js').lines.map do |line|
19
- line.strip if line.sub!(%r(//\s*=\s*require\s*(?:./)?(.*)\s*), 'assets/javascripts/\1.js')
20
- end.compact
21
18
 
22
19
  spec['main'] =
23
20
  find_files.(File.join(Bootstrap.stylesheets_path, '_bootstrap.scss')) +
24
21
  find_files.(Bootstrap.fonts_path) +
25
- js_paths
22
+ %w(assets/javascripts/bootstrap.js)
26
23
 
27
- spec['version'] = Bootstrap::VERSION[0..-3]
24
+ spec['version'] = Bootstrap::VERSION
28
25
 
29
26
  File.open('bower.json', 'w') do |f|
30
27
  f.puts JSON.pretty_generate(spec)
@@ -10,7 +10,7 @@ class Converter
10
10
  end
11
11
 
12
12
  def bootstrap_font_files
13
- @bootstrap_font_files ||= get_paths_by_type('fonts', /\.(eot|svg|ttf|woff)$/)
13
+ @bootstrap_font_files ||= get_paths_by_type('fonts', /\.(eot|svg|ttf|woff2?)$/)
14
14
  end
15
15
  end
16
16
  end
@@ -12,14 +12,16 @@ class Converter
12
12
 
13
13
  log_status 'Updating javascript manifest'
14
14
  manifest = ''
15
- cat = ''
16
15
  bootstrap_js_files.each do |name|
17
- cat << contents[name] + "\n"
18
16
  name = name.gsub(/\.js$/, '')
19
17
  manifest << "//= require ./bootstrap/#{name}\n"
20
18
  end
21
- {'assets/javascripts/bootstrap-sprockets.js' => manifest,
22
- 'assets/javascripts/bootstrap.js' => cat}.each do |path, content|
19
+ dist_js = read_files('dist/js', %w(bootstrap.js bootstrap.min.js))
20
+ {
21
+ 'assets/javascripts/bootstrap-sprockets.js' => manifest,
22
+ 'assets/javascripts/bootstrap.js' => dist_js['bootstrap.js'],
23
+ 'assets/javascripts/bootstrap.min.js' => dist_js['bootstrap.min.js'],
24
+ }.each do |path, content|
23
25
  save_file path, content
24
26
  log_processed path
25
27
  end
@@ -27,7 +29,7 @@ class Converter
27
29
 
28
30
  def bootstrap_js_files
29
31
  @bootstrap_js_files ||= begin
30
- files = get_paths_by_type 'js', /\.js$/
32
+ files = get_paths_by_type('js', /\.js$/).reject { |path| path =~ %r(^tests/) }
31
33
  files.sort_by { |f|
32
34
  case f
33
35
  # tooltip depends on popover and must be loaded earlier
@@ -1,4 +1,5 @@
1
1
  require_relative 'char_string_scanner'
2
+ require 'bootstrap-sass/version'
2
3
 
3
4
  # This is the script used to automatically convert all of twbs/bootstrap LESS to Sass.
4
5
  #
@@ -66,6 +67,7 @@ class Converter
66
67
  log_processing name
67
68
  # apply common conversions
68
69
  file = convert_less(file)
70
+ file = replace_all file, %r{// stylelint-disable.*?\n+}, '', optional: true
69
71
  if name.start_with?('mixins/')
70
72
  file = varargify_mixin_definitions(file, *VARARG_MIXINS)
71
73
  %w(responsive-(in)?visibility input-size text-emphasis-variant bg-variant).each do |mixin|
@@ -95,16 +97,17 @@ class Converter
95
97
  file = apply_mixin_parent_selector file, '\.(?:visible|hidden)'
96
98
  when 'variables.less'
97
99
  file = insert_default_vars(file)
98
- file = unindent <<-SCSS + "\n" + file, 14
99
- // When true, asset path helpers are used, otherwise the regular CSS `url()` is used.
100
- // When there no function is defined, `fn('')` is parsed as string that equals the right hand side
101
- // NB: in Sass 3.3 there is a native function: function-exists(twbs-font-path)
102
- $bootstrap-sass-asset-helper: #{sass_fn_exists('twbs-font-path')} !default;
103
- SCSS
100
+ file = ['$bootstrap-sass-asset-helper: false !default;', file].join("\n")
104
101
  file = replace_all file, %r{(\$icon-font-path): \s*"(.*)" (!default);}, "\n" + unindent(<<-SCSS, 14)
105
- // [converter] Asset helpers such as Sprockets and Node.js Mincer do not resolve relative paths
102
+ // [converter] If $bootstrap-sass-asset-helper if used, provide path relative to the assets load path.
103
+ // [converter] This is because some asset helpers, such as Sprockets, do not work with file-relative paths.
106
104
  \\1: if($bootstrap-sass-asset-helper, "bootstrap/", "\\2bootstrap/") \\3;
107
105
  SCSS
106
+ when 'breadcrumbs.less'
107
+ file = replace_all file, /(.*)(\\00a0)/, unindent(<<-SCSS, 8) + "\\1\#{$nbsp}"
108
+ // [converter] Workaround for https://github.com/sass/libsass/issues/1115
109
+ $nbsp: "\\2";
110
+ SCSS
108
111
  when 'close.less'
109
112
  # extract .close { button& {...} } rule
110
113
  file = extract_nested_rule file, 'button&'
@@ -114,17 +117,17 @@ class Converter
114
117
  when 'forms.less'
115
118
  file = extract_nested_rule file, 'textarea&'
116
119
  file = apply_mixin_parent_selector(file, '\.input-(?:sm|lg)')
120
+ file = replace_rules file, /\.form-group-(?:sm|lg)/ do |rule|
121
+ apply_mixin_parent_selector rule, '.form-control'
122
+ end
117
123
  when 'navbar.less'
118
124
  file = replace_all file, /(\s*)\.navbar-(right|left)\s*\{\s*@extend\s*\.pull-(right|left);\s*/, "\\1.navbar-\\2 {\\1 float: \\2 !important;\\1"
119
125
  when 'tables.less'
120
126
  file = replace_all file, /(@include\s*table-row-variant\()(\w+)/, "\\1'\\2'"
121
- when 'thumbnails.less', 'labels.less', 'badges.less'
127
+ when 'thumbnails.less', 'labels.less', 'badges.less', 'buttons.less'
122
128
  file = extract_nested_rule file, 'a&'
123
129
  when 'glyphicons.less'
124
- file = replace_rules(file, '@font-face') { |rule|
125
- rule = replace_all rule, /(\$icon-font(?:-\w+)+)/, '#{\1}'
126
- replace_asset_url rule, :font
127
- }
130
+ file = replace_rules(file, /\s*@font-face/) { |rule| replace_asset_url rule, :font }
128
131
  when 'type.less'
129
132
  file = apply_mixin_parent_selector(file, '\.(text|bg)-(success|primary|info|warning|danger)')
130
133
  # .bg-primary will not get patched automatically as it includes an additional rule. fudge for now
@@ -145,14 +148,12 @@ class Converter
145
148
 
146
149
  # generate variables template
147
150
  save_file 'templates/project/_bootstrap-variables.sass',
148
- "// Override Bootstrap variables here (defaults from bootstrap-sass v<%= Bootstrap::VERSION %>):\n\n" +
149
- File.read("#{save_to}/_variables.scss").gsub(/^(?=\$)/, '// ').gsub(/ !default;/, '')
151
+ "// Override Bootstrap variables here (defaults from bootstrap-sass v#{Bootstrap::VERSION}):\n\n" +
152
+ File.read("#{save_to}/_variables.scss").lines[1..-1].join.gsub(/^(?=\$)/, '// ').gsub(/ !default;/, '')
150
153
  end
151
154
 
152
155
  def bootstrap_less_files
153
- @bootstrap_less_files ||= get_paths_by_type('less', /\.less$/) +
154
- get_paths_by_type('mixins', /\.less$/,
155
- get_tree(get_tree_sha('mixins', get_tree(get_tree_sha('less'))))).map { |p| "mixins/#{p}" }
156
+ @bootstrap_less_files ||= get_paths_by_type('less', /\.less$/)
156
157
  end
157
158
 
158
159
  # apply general less to scss conversion
@@ -171,9 +172,16 @@ class Converter
171
172
  file = deinterpolate_vararg_mixins(file)
172
173
  file = replace_calculation_semantics(file)
173
174
  file = replace_file_imports(file)
175
+ file = wrap_at_groups_with_at_root(file)
174
176
  file
175
177
  end
176
178
 
179
+ def wrap_at_groups_with_at_root(file)
180
+ replace_rules(file, /@(?:font-face|-ms-viewport)/) { |rule, _pos|
181
+ %Q(@at-root {\n#{indent rule, 2}\n})
182
+ }
183
+ end
184
+
177
185
  def sass_fn_exists(fn)
178
186
  %Q{(#{fn}("") != unquote('#{fn}("")'))}
179
187
  end
@@ -206,7 +214,7 @@ class Converter
206
214
  SASS
207
215
  end
208
216
 
209
- # convert grid mixins LESS when => SASS @if
217
+ # convert grid mixins LESS when => Sass @if
210
218
  def convert_grid_mixins(file)
211
219
  file = replace_rules file, /@mixin make-grid-columns/, comments: false do |css, pos|
212
220
  mixin_all_grid_columns css, selector: '.col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}', to: '$grid-columns'
@@ -263,8 +271,8 @@ SASS
263
271
 
264
272
  # margin: a -b
265
273
  # LESS: sets 2 values
266
- # SASS: sets 1 value (a-b)
267
- # This wraps a and -b so they evaluates to 2 values in SASS
274
+ # Sass: sets 1 value (a-b)
275
+ # This wraps a and -b so they evaluates to 2 values in Sass
268
276
  def replace_calculation_semantics(file)
269
277
  # split_prop_val.call('(@navbar-padding-vertical / 2) -@navbar-padding-horizontal')
270
278
  # #=> ["(navbar-padding-vertical / 2)", "-navbar-padding-horizontal"]
@@ -315,10 +323,10 @@ SASS
315
323
  %Q(@import "#{target_path}\\1";)
316
324
  end
317
325
 
318
- def replace_all(file, regex, replacement = nil, &block)
326
+ def replace_all(file, regex, replacement = nil, optional: false, &block)
319
327
  log_transform regex, replacement
320
328
  new_file = file.gsub(regex, replacement, &block)
321
- raise "replace_all #{regex}, #{replacement} NO MATCH" if file == new_file
329
+ raise "replace_all #{regex}, #{replacement} NO MATCH" if !optional && file == new_file
322
330
  new_file
323
331
  end
324
332
 
@@ -384,8 +392,10 @@ SASS
384
392
  end
385
393
  # unwrap, and replace @include
386
394
  unindent unwrap_rule_block(rule).gsub(/(@include [\w-]+)\(?([\$\w\-,\s]*)\)?/) {
387
- args = $2
388
- "#{cmt}#{$1}('#{sel.gsub(/\s+/, ' ')}'#{', ' if args && !args.empty?}#{args})"
395
+ name, args = $1, $2
396
+ sel.gsub(/\s+/, ' ').split(/,\s*/ ).map { |sel_part|
397
+ "#{cmt}#{name}('#{sel_part}'#{', ' if args && !args.empty?}#{args})"
398
+ }.join(";\n")
389
399
  }
390
400
  end
391
401
  end
@@ -424,16 +434,16 @@ SASS
424
434
  # #scope > .mixin() -> @include scope-mixin()
425
435
  # &:extend(.mixin all) -> @include mixin()
426
436
  def replace_mixins(less, mixin_names)
427
- mixin_pattern = /(\s+)(([#|\.][\w-]+\s*>\s*)*)\.([\w-]+\(.*\))(?!\s\{)/
428
-
429
- less = less.gsub(mixin_pattern) do |match|
430
- matches = match.scan(mixin_pattern).flatten
431
- scope = matches[1] && matches[1] != '' ? matches[1].scan(/[\w-]+/).join('-') + '-' : ''
432
- mixin_name = match.scan(/\.([\w-]+)\(.*\)\s?\{?/).first
433
- if mixin_name && mixin_names.include?("#{scope}#{mixin_name.first}")
434
- "#{matches.first}@include #{scope}#{matches.last.gsub(/;\s*\$/, ', $').sub(/;\)$/, ')').sub(/\(\)$/, '')}"
437
+ mixin_pattern = /(?<=^|\s)((?:[#|\.][\w-]+\s*>\s*)*)\.([\w-]+)\((.*)\)(?!\s\{)/
438
+
439
+ less = less.gsub(mixin_pattern) do |_|
440
+ scope, name, args = $1, $2, $3
441
+ scope = scope.scan(/[\w-]+/).join('-') + '-' unless scope.empty?
442
+ args = "(#{args.tr(';', ',')})" unless args.empty?
443
+ if name && mixin_names.include?("#{scope}#{name}")
444
+ "@include #{scope}#{name}#{args}"
435
445
  else
436
- "#{matches.first}@extend .#{scope}#{matches.last.gsub(/\(\)/, '')}"
446
+ "@extend .#{scope}#{name}"
437
447
  end
438
448
  end
439
449
 
@@ -449,11 +459,11 @@ SASS
449
459
  end
450
460
  end
451
461
 
452
- # change Microsoft filters to SASS calling convention
462
+ # change Microsoft filters to Sass calling convention
453
463
  def replace_ms_filters(file)
454
464
  log_transform
455
465
  file.gsub(
456
- /filter: e\(%\("progid:DXImageTransform.Microsoft.gradient\(startColorstr='%d', endColorstr='%d', GradientType=(\d)\)",argb\(([\-$\w]+)\),argb\(([\-$\w]+)\)\)\);/,
466
+ /filter: e\(%\("progid:DXImageTransform.Microsoft.gradient\(startColorstr='%d', endColorstr='%d', GradientType=(\d)\)", ?argb\(([\-$\w]+)\), ?argb\(([\-$\w]+)\)\)\);/,
457
467
  %Q(filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='\#{ie-hex-str(\\2)}', endColorstr='\#{ie-hex-str(\\3)}', GradientType=\\1);)
458
468
  )
459
469
  end
@@ -497,9 +507,10 @@ SASS
497
507
  end
498
508
 
499
509
  def replace_escaping(less)
500
- less = less.gsub(/~"([^"]+)"/, '#{\1}') # Get rid of ~"" escape
510
+ less = less.gsub(/~"([^"]+)"/, '\1').gsub(/~'([^']+)'/, '\1') # Get rid of ~"" escape
501
511
  less.gsub!(/\$\{([^}]+)\}/, '$\1') # Get rid of @{} escape
502
- less.gsub!(/"([^"\n]*)(\$[\w\-]+)([^"\n]*)"/, '"\1#{\2}\3"') # interpolate variable in string, e.g. url("$file-1x") => url("#{$file-1x}")
512
+ # interpolate variables in strings, e.g. url("$file-1x") => url("#{$file-1x}")
513
+ less.gsub!(/"[^"\n]*"/) { |str| str.gsub(/\$[^"\n$.\\]+/, '#{\0}') }
503
514
  less.gsub(/(\W)e\(%\("?([^"]*)"?\)\)/, '\1\2') # Get rid of e(%("")) escape
504
515
  end
505
516
 
@@ -3,8 +3,12 @@ class Converter
3
3
  module Network
4
4
  protected
5
5
 
6
- def get_paths_by_type(dir, file_re, tree = get_tree(get_tree_sha(dir)))
7
- tree['tree'].select { |f| f['type'] == 'blob' && f['path'] =~ file_re }.map { |f| f['path'] }
6
+ def get_paths_by_type(dir, file_re, recursive = true)
7
+ get_file_paths(dir, recursive).select { |path| path =~ file_re }
8
+ end
9
+
10
+ def get_file_paths(dir, recursive = true)
11
+ get_tree(get_tree_sha(dir), recursive)['tree'].select { |f| f['type'] == 'blob' }.map { |f| f['path'] }
8
12
  end
9
13
 
10
14
  def read_files(path, files)
@@ -28,7 +32,7 @@ class Converter
28
32
  if File.directory?(full_path)
29
33
  files.each do |name|
30
34
  path = "#{full_path}/#{name}"
31
- contents[name] = File.read(path, mode: 'rb') if File.exists?(path)
35
+ contents[name] = File.read(path, mode: 'rb') if File.exist?(path)
32
36
  end
33
37
  end
34
38
  contents
@@ -44,9 +48,10 @@ class Converter
44
48
 
45
49
 
46
50
  def get_file(url)
47
- cache_path = "./#@cache_path#{URI(url).path}"
51
+ uri = URI(url)
52
+ cache_path = "./#@cache_path#{uri.path}#{uri.query.tr('?&=', '-') if uri.query}"
48
53
  FileUtils.mkdir_p File.dirname(cache_path)
49
- if File.exists?(cache_path)
54
+ if File.exist?(cache_path)
50
55
  log_http_get_file url, true
51
56
  File.read(cache_path, mode: 'rb')
52
57
  else
@@ -81,8 +86,8 @@ class Converter
81
86
  @trees ||= get_tree(@branch_sha)
82
87
  end
83
88
 
84
- def get_tree(sha)
85
- get_json("https://api.github.com/repos/#@repo/git/trees/#{sha}")
89
+ def get_tree(sha, recursive = true)
90
+ get_json("https://api.github.com/repos/#@repo/git/trees/#{sha}#{'?recursive=1' if recursive}")
86
91
  end
87
92
 
88
93
  def get_json(url)
data/tasks/converter.rb CHANGED
@@ -50,7 +50,7 @@ class Converter
50
50
  def_delegators :@logger, :log, :log_status, :log_processing, :log_transform, :log_file_info, :log_processed, :log_http_get_file, :log_http_get_files, :silence_log
51
51
 
52
52
  def process_bootstrap
53
- log_status "Convert Bootstrap LESS to SASS"
53
+ log_status "Convert Bootstrap LESS to Sass"
54
54
  puts " repo : #@repo_url"
55
55
  puts " branch : #@branch_sha #@repo_url/tree/#@branch"
56
56
  puts " save to: #{@save_to.to_json}"
@@ -1,9 +1,4 @@
1
- // Override Bootstrap variables here (defaults from bootstrap-sass v<%= Bootstrap::VERSION %>):
2
-
3
- // When true, asset path helpers are used, otherwise the regular CSS `url()` is used.
4
- // When there no function is defined, `fn('')` is parsed as string that equals the right hand side
5
- // NB: in Sass 3.3 there is a native function: function-exists(twbs-font-path)
6
- // $bootstrap-sass-asset-helper: (twbs-font-path("") != unquote('twbs-font-path("")'))
1
+ // Override Bootstrap variables here (defaults from bootstrap-sass v3.4.0):
7
2
 
8
3
  //
9
4
  // Variables
@@ -21,7 +16,7 @@
21
16
  // $gray-light: lighten($gray-base, 46.7%) // #777
22
17
  // $gray-lighter: lighten($gray-base, 93.5%) // #eee
23
18
 
24
- // $brand-primary: #428bca
19
+ // $brand-primary: darken(#428bca, 6.5%) // #337ab7
25
20
  // $brand-success: #5cb85c
26
21
  // $brand-info: #5bc0de
27
22
  // $brand-warning: #f0ad4e
@@ -57,14 +52,14 @@
57
52
 
58
53
  // $font-size-base: 14px
59
54
  // $font-size-large: ceil(($font-size-base * 1.25)) // ~18px
60
- // $font-size-small: ceil(($font-size-base * 0.85)) // ~12px
55
+ // $font-size-small: ceil(($font-size-base * .85)) // ~12px
61
56
 
62
57
  // $font-size-h1: floor(($font-size-base * 2.6)) // ~36px
63
58
  // $font-size-h2: floor(($font-size-base * 2.15)) // ~30px
64
59
  // $font-size-h3: ceil(($font-size-base * 1.7)) // ~24px
65
60
  // $font-size-h4: ceil(($font-size-base * 1.25)) // ~18px
66
61
  // $font-size-h5: $font-size-base
67
- // $font-size-h6: ceil(($font-size-base * 0.85)) // ~12px
62
+ // $font-size-h6: ceil(($font-size-base * .85)) // ~12px
68
63
 
69
64
  //** Unit-less `line-height` for use in components like buttons.
70
65
  // $line-height-base: 1.428571429 // 20/14
@@ -84,7 +79,8 @@
84
79
 
85
80
  //** Load fonts from this directory.
86
81
 
87
- // [converter] Asset helpers such as Sprockets and Node.js Mincer do not resolve relative paths
82
+ // [converter] If $bootstrap-sass-asset-helper if used, provide path relative to the assets load path.
83
+ // [converter] This is because some asset helpers, such as Sprockets, do not work with file-relative paths.
88
84
  // $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/")
89
85
 
90
86
  //** File name for all font files.
@@ -109,7 +105,7 @@
109
105
  // $padding-xs-vertical: 1px
110
106
  // $padding-xs-horizontal: 5px
111
107
 
112
- // $line-height-large: 1.33
108
+ // $line-height-large: 1.3333333 // extra decimals for Win 8.1 Chrome
113
109
  // $line-height-small: 1.5
114
110
 
115
111
  // $border-radius-base: 4px
@@ -121,7 +117,7 @@
121
117
  //** Global background color for active items (e.g., navs or dropdowns).
122
118
  // $component-active-bg: $brand-primary
123
119
 
124
- //** Width of the `border` for generating carets that indicator dropdowns.
120
+ //** Width of the `border` for generating carets that indicate dropdowns.
125
121
  // $caret-width-base: 4px
126
122
  //** Carets increase slightly in size for larger components.
127
123
  // $caret-width-large: 5px
@@ -180,6 +176,11 @@
180
176
 
181
177
  // $btn-link-disabled-color: $gray-light
182
178
 
179
+ // Allows for customizing button radius independently from global border radius
180
+ // $btn-border-radius-base: $border-radius-base
181
+ // $btn-border-radius-large: $border-radius-large
182
+ // $btn-border-radius-small: $border-radius-small
183
+
183
184
 
184
185
  //== Forms
185
186
  //
@@ -197,6 +198,7 @@
197
198
 
198
199
  // TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
199
200
  //** Default `.form-control` border radius
201
+ // This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
200
202
  // $input-border-radius: $border-radius-base
201
203
  //** Large `.form-control` border radius
202
204
  // $input-border-radius-large: $border-radius-large
@@ -216,6 +218,9 @@
216
218
  //** Small `.form-control` height
217
219
  // $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2)
218
220
 
221
+ //** `.form-group` margin
222
+ // $form-group-margin-bottom: 15px
223
+
219
224
  // $legend-color: $gray-dark
220
225
  // $legend-border-color: #e5e5e5
221
226
 
@@ -235,7 +240,7 @@
235
240
  //** Background for the dropdown menu.
236
241
  // $dropdown-bg: #fff
237
242
  //** Dropdown menu `border-color`.
238
- // $dropdown-border: rgba(0,0,0,.15)
243
+ // $dropdown-border: rgba(0, 0, 0, .15)
239
244
  //** Dropdown menu `border-color` **for IE8**.
240
245
  // $dropdown-fallback-border: #ccc
241
246
  //** Divider color for between dropdown items.
@@ -275,7 +280,8 @@
275
280
  // $zindex-popover: 1060
276
281
  // $zindex-tooltip: 1070
277
282
  // $zindex-navbar-fixed: 1030
278
- // $zindex-modal: 1040
283
+ // $zindex-modal-background: 1040
284
+ // $zindex-modal: 1050
279
285
 
280
286
 
281
287
  //== Media queries breakpoints
@@ -388,7 +394,7 @@
388
394
  // $navbar-default-toggle-border-color: #ddd
389
395
 
390
396
 
391
- // Inverted navbar
397
+ //=== Inverted navbar
392
398
  // Reset inverted navbar basics
393
399
  // $navbar-inverse-color: lighten($gray-light, 15%)
394
400
  // $navbar-inverse-bg: #222
@@ -489,6 +495,7 @@
489
495
  // $jumbotron-bg: $gray-lighter
490
496
  // $jumbotron-heading-color: inherit
491
497
  // $jumbotron-font-size: ceil(($font-size-base * 1.5))
498
+ // $jumbotron-heading-font-size: ceil(($font-size-base * 4.5))
492
499
 
493
500
 
494
501
  //== Form states and alerts
@@ -539,7 +546,7 @@
539
546
  //** Popover maximum width
540
547
  // $popover-max-width: 276px
541
548
  //** Popover border color
542
- // $popover-border-color: rgba(0,0,0,.2)
549
+ // $popover-border-color: rgba(0, 0, 0, .2)
543
550
  //** Popover fallback border color
544
551
  // $popover-fallback-border-color: #ccc
545
552
 
@@ -597,7 +604,7 @@
597
604
  //** Background color of modal content area
598
605
  // $modal-content-bg: #fff
599
606
  //** Modal content border color
600
- // $modal-content-border-color: rgba(0,0,0,.2)
607
+ // $modal-content-border-color: rgba(0, 0, 0, .2)
601
608
  //** Modal content border color **for IE8**
602
609
  // $modal-content-fallback-border-color: #999
603
610
 
@@ -802,7 +809,7 @@
802
809
  //
803
810
  //##
804
811
 
805
- // $carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6)
812
+ // $carousel-text-shadow: 0 1px 2px rgba(0, 0, 0, .6)
806
813
 
807
814
  // $carousel-control-color: #fff
808
815
  // $carousel-control-width: 15%
@@ -862,5 +869,7 @@
862
869
  // $page-header-border-color: $gray-lighter
863
870
  //** Width of horizontal description list titles
864
871
  // $dl-horizontal-offset: $component-offset-horizontal
872
+ //** Point at which .dl-horizontal becomes horizontal
873
+ // $dl-horizontal-breakpoint: $grid-float-breakpoint
865
874
  //** Horizontal line color.
866
875
  // $hr-border: $gray-lighter
@@ -1,3 +1,6 @@
1
+ // Import Bootstrap Compass integration
1
2
  @import "bootstrap-compass"
3
+ // Import custom Bootstrap variables
2
4
  @import "bootstrap-variables"
5
+ // Import Bootstrap for Sass
3
6
  @import "bootstrap"
@@ -1,18 +1,30 @@
1
1
  require 'test_helper'
2
2
  require 'fileutils'
3
- require 'sass'
3
+ require 'sassc'
4
4
 
5
5
  class CompilationTest < Minitest::Test
6
- def test_compilation
7
- path = 'assets/stylesheets'
8
- %w(_bootstrap bootstrap/_theme).each do |file|
9
- FileUtils.rm_rf('.sass-cache', secure: true)
10
- engine = Sass::Engine.for_file("#{path}/#{file}.scss", syntax: :scss, load_paths: [path])
11
- FileUtils.mkdir_p("tmp/#{File.dirname(file)}")
12
- File.open("tmp/#{file}.css", 'w') { |f|
13
- f.write engine.render
14
- }
15
- assert true # nothing was raised
16
- end
6
+ def test_compilation_bootstrap
7
+ compile 'bootstrap'
8
+ assert true # nothing was raised
9
+ end
10
+
11
+ def test_compilation_bootstrap_theme
12
+ compile 'bootstrap/theme'
13
+ assert true # nothing was raised
14
+ end
15
+
16
+ private
17
+
18
+ def compile(file)
19
+ path = File.expand_path('../assets/stylesheets', __dir__)
20
+ FileUtils.rm_rf('.sass-cache', secure: true)
21
+ engine = SassC::Engine.new(
22
+ %Q{@import "#{path}/#{file}"},
23
+ syntax: :scss, load_paths: ['.']
24
+ )
25
+ FileUtils.mkdir_p("tmp/#{File.dirname(file)}")
26
+ File.open("tmp/#{file}.css", 'w') { |f|
27
+ f.write engine.render
28
+ }
17
29
  end
18
30
  end
@@ -1,3 +1,46 @@
1
+ .navbar.navbar-inverse: .container-fluid
2
+ .navbar-header
3
+ button.navbar-toggle.collapsed type="button" data-toggle="collapse" data-target="#c1"
4
+ span.sr-only Toggle navigation
5
+ span.icon-bar
6
+ span.icon-bar
7
+ span.icon-bar
8
+ a.navbar-brand href="#" Bootstrap for Sass Test Rails App
9
+ .collapse.navbar-collapse#c1
10
+ ul.nav.navbar-nav
11
+ li.active: a href="#"
12
+ ' Home
13
+ span.sr-only (current)
14
+ li: a href="#" Link
15
+ li.dropdown
16
+ a.dropdown-toggle href="#" data-toggle="dropdown" role="button" aria-expanded="false"
17
+ ' Dropdown
18
+ span.caret
19
+ ul.dropdown-menu role="menu"
20
+ li: a href="#" Action
21
+ li: a href="#" Another action
22
+ li: a href="#" Something else here
23
+ li.divider
24
+ li: a href="#" Separated link
25
+ li.divider
26
+ li: a href="#" One more separated link
27
+ form.navbar-form.navbar-left role="search"
28
+ .input-group
29
+ input.form-control type="search" placeholder="Search..."
30
+ .input-group-btn: button.btn.btn-primary type="submit" Go
31
+ ul.nav.navbar-nav.navbar-right
32
+ li: a href="#" Link
33
+ li.dropdown
34
+ a.dropdown-toggle href="#" data-toggle="dropdown" role="button" aria-expanded="false"
35
+ ' Dropdown
36
+ span.caret
37
+ ul.dropdown-menu role="menu"
38
+ li: a href="#" Action
39
+ li: a href="#" Another action
40
+ li: a href="#" Something else here
41
+ li.divider
42
+ li: a href="#" Separated link
43
+
1
44
  .container
2
45
  .panel.panel-primary
3
46
  .panel-heading: h1 Dummy App
@@ -12,13 +12,14 @@ end
12
12
 
13
13
  require 'slim-rails'
14
14
  require 'jquery-rails'
15
- require 'compass'
15
+ require 'sassc-rails'
16
16
  require 'bootstrap-sass'
17
17
  require 'uglifier'
18
18
 
19
19
  module Dummy
20
20
  class Application < Rails::Application
21
21
  config.assets.enabled = true if config.assets.respond_to?(:enabled)
22
+ config.assets.precompile += %w( application.css application.js )
22
23
  config.to_prepare do
23
24
  if ENV['VERBOSE']
24
25
  STDERR.puts "Loaded Rails #{Rails::VERSION::STRING}, Sprockets #{Sprockets::VERSION}",
@@ -1,5 +1,5 @@
1
1
  # Set up gems listed in the Gemfile.
2
2
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
3
3
 
4
- require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
5
5
  $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)