flat-ui-sass 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +256 -0
  7. data/Rakefile +14 -0
  8. data/app/helpers/flat_ui/rails/icon_helper.rb +60 -0
  9. data/bin/fui_convert +9 -0
  10. data/flat-ui-sass.gemspec +28 -0
  11. data/lib/flat-ui-sass.rb +98 -0
  12. data/lib/flat-ui-sass/cli.rb +56 -0
  13. data/lib/flat-ui-sass/engine.rb +13 -0
  14. data/lib/flat-ui-sass/sass_functions.rb +56 -0
  15. data/lib/flat-ui-sass/version.rb +4 -0
  16. data/lib/tasks/converter.rb +99 -0
  17. data/lib/tasks/converter/filesystem.rb +16 -0
  18. data/lib/tasks/converter/flat_ui_fonts_conversion.rb +19 -0
  19. data/lib/tasks/converter/flat_ui_images_conversion.rb +19 -0
  20. data/lib/tasks/converter/flat_ui_js_conversion.rb +28 -0
  21. data/lib/tasks/converter/flat_ui_less_conversion.rb +328 -0
  22. data/lib/tasks/converter/logger.rb +61 -0
  23. data/lib/tasks/flat-ui-sass.rake +8 -0
  24. data/templates/project/_variables.scss.erb +5 -0
  25. data/templates/project/manifest.rb +57 -0
  26. data/templates/project/styles.scss +4 -0
  27. data/vendor/assets/fonts/flat-ui/flat-ui-icons-regular.eot +0 -0
  28. data/vendor/assets/fonts/flat-ui/flat-ui-icons-regular.svg +140 -0
  29. data/vendor/assets/fonts/flat-ui/flat-ui-icons-regular.ttf +0 -0
  30. data/vendor/assets/fonts/flat-ui/flat-ui-icons-regular.woff +0 -0
  31. data/vendor/assets/images/flat-ui/icons/png/Book.png +0 -0
  32. data/vendor/assets/images/flat-ui/icons/png/Calendar.png +0 -0
  33. data/vendor/assets/images/flat-ui/icons/png/Chat.png +0 -0
  34. data/vendor/assets/images/flat-ui/icons/png/Clipboard.png +0 -0
  35. data/vendor/assets/images/flat-ui/icons/png/Compas.png +0 -0
  36. data/vendor/assets/images/flat-ui/icons/png/Gift-Box.png +0 -0
  37. data/vendor/assets/images/flat-ui/icons/png/Infinity-Loop.png +0 -0
  38. data/vendor/assets/images/flat-ui/icons/png/Mail.png +0 -0
  39. data/vendor/assets/images/flat-ui/icons/png/Map.png +0 -0
  40. data/vendor/assets/images/flat-ui/icons/png/Pensils.png +0 -0
  41. data/vendor/assets/images/flat-ui/icons/png/Pocket.png +0 -0
  42. data/vendor/assets/images/flat-ui/icons/png/Retina-Ready.png +0 -0
  43. data/vendor/assets/images/flat-ui/icons/png/Toilet-Paper.png +0 -0
  44. data/vendor/assets/images/flat-ui/icons/png/Watches.png +0 -0
  45. data/vendor/assets/images/flat-ui/icons/svg/book.svg +1 -0
  46. data/vendor/assets/images/flat-ui/icons/svg/calendar.svg +1 -0
  47. data/vendor/assets/images/flat-ui/icons/svg/chat.svg +1 -0
  48. data/vendor/assets/images/flat-ui/icons/svg/clipboard.svg +1 -0
  49. data/vendor/assets/images/flat-ui/icons/svg/clocks.svg +9 -0
  50. data/vendor/assets/images/flat-ui/icons/svg/compas.svg +1 -0
  51. data/vendor/assets/images/flat-ui/icons/svg/gift-box.svg +1 -0
  52. data/vendor/assets/images/flat-ui/icons/svg/loop.svg +5 -0
  53. data/vendor/assets/images/flat-ui/icons/svg/mail.svg +1 -0
  54. data/vendor/assets/images/flat-ui/icons/svg/map.svg +1 -0
  55. data/vendor/assets/images/flat-ui/icons/svg/paper-bag.svg +1 -0
  56. data/vendor/assets/images/flat-ui/icons/svg/pencils.svg +1 -0
  57. data/vendor/assets/images/flat-ui/icons/svg/retina.svg +1 -0
  58. data/vendor/assets/images/flat-ui/icons/svg/toilet-paper.svg +1 -0
  59. data/vendor/assets/images/flat-ui/login/icon.png +0 -0
  60. data/vendor/assets/images/flat-ui/login/imac-2x.png +0 -0
  61. data/vendor/assets/images/flat-ui/login/imac.png +0 -0
  62. data/vendor/assets/images/flat-ui/switch/mask-square.png +0 -0
  63. data/vendor/assets/images/flat-ui/switch/mask.png +0 -0
  64. data/vendor/assets/images/flat-ui/tile/ribbon-2x.png +0 -0
  65. data/vendor/assets/images/flat-ui/tile/ribbon.png +0 -0
  66. data/vendor/assets/images/flat-ui/todo/done-2x.png +0 -0
  67. data/vendor/assets/images/flat-ui/todo/done.png +0 -0
  68. data/vendor/assets/images/flat-ui/todo/search-2x.png +0 -0
  69. data/vendor/assets/images/flat-ui/todo/search.png +0 -0
  70. data/vendor/assets/images/flat-ui/todo/todo-2x.png +0 -0
  71. data/vendor/assets/images/flat-ui/todo/todo.png +0 -0
  72. data/vendor/assets/images/flat-ui/video/fullscreen-2x.png +0 -0
  73. data/vendor/assets/images/flat-ui/video/fullscreen.png +0 -0
  74. data/vendor/assets/images/flat-ui/video/pause-2x.png +0 -0
  75. data/vendor/assets/images/flat-ui/video/pause.png +0 -0
  76. data/vendor/assets/images/flat-ui/video/play-2x.png +0 -0
  77. data/vendor/assets/images/flat-ui/video/play.png +0 -0
  78. data/vendor/assets/images/flat-ui/video/poster.jpg +0 -0
  79. data/vendor/assets/images/flat-ui/video/volume-full-2x.png +0 -0
  80. data/vendor/assets/images/flat-ui/video/volume-full.png +0 -0
  81. data/vendor/assets/images/flat-ui/video/volume-off-2x.png +0 -0
  82. data/vendor/assets/images/flat-ui/video/volume-off.png +0 -0
  83. data/vendor/assets/javascripts/flat-ui.js +2 -0
  84. data/vendor/assets/javascripts/flat-ui/flatui-checkbox.js +112 -0
  85. data/vendor/assets/javascripts/flat-ui/flatui-radio.js +139 -0
  86. data/vendor/assets/stylesheets/flat-ui.scss +1 -0
  87. data/vendor/assets/stylesheets/flat-ui/_mixins.scss +878 -0
  88. data/vendor/assets/stylesheets/flat-ui/_spaces.scss +172 -0
  89. data/vendor/assets/stylesheets/flat-ui/_variables.scss +509 -0
  90. data/vendor/assets/stylesheets/flat-ui/flat-ui.scss +45 -0
  91. data/vendor/assets/stylesheets/flat-ui/modules/_button-groups.scss +110 -0
  92. data/vendor/assets/stylesheets/flat-ui/modules/_buttons.scss +151 -0
  93. data/vendor/assets/stylesheets/flat-ui/modules/_caret.scss +30 -0
  94. data/vendor/assets/stylesheets/flat-ui/modules/_checkbox-and-radio.scss +143 -0
  95. data/vendor/assets/stylesheets/flat-ui/modules/_code.scss +49 -0
  96. data/vendor/assets/stylesheets/flat-ui/modules/_dropdown.scss +223 -0
  97. data/vendor/assets/stylesheets/flat-ui/modules/_footer.scss +76 -0
  98. data/vendor/assets/stylesheets/flat-ui/modules/_forms.scss +188 -0
  99. data/vendor/assets/stylesheets/flat-ui/modules/_glyphicons.scss +135 -0
  100. data/vendor/assets/stylesheets/flat-ui/modules/_input-groups.scss +153 -0
  101. data/vendor/assets/stylesheets/flat-ui/modules/_input-icons.scss +72 -0
  102. data/vendor/assets/stylesheets/flat-ui/modules/_local-fonts.scss +69 -0
  103. data/vendor/assets/stylesheets/flat-ui/modules/_login.scss +111 -0
  104. data/vendor/assets/stylesheets/flat-ui/modules/_navbar.scss +876 -0
  105. data/vendor/assets/stylesheets/flat-ui/modules/_pager.scss +51 -0
  106. data/vendor/assets/stylesheets/flat-ui/modules/_pagination.scss +166 -0
  107. data/vendor/assets/stylesheets/flat-ui/modules/_palette.scss +71 -0
  108. data/vendor/assets/stylesheets/flat-ui/modules/_progress-bars.scss +34 -0
  109. data/vendor/assets/stylesheets/flat-ui/modules/_scaffolding.scss +64 -0
  110. data/vendor/assets/stylesheets/flat-ui/modules/_select.scss +145 -0
  111. data/vendor/assets/stylesheets/flat-ui/modules/_share.scss +44 -0
  112. data/vendor/assets/stylesheets/flat-ui/modules/_slider.scss +105 -0
  113. data/vendor/assets/stylesheets/flat-ui/modules/_switch.scss +150 -0
  114. data/vendor/assets/stylesheets/flat-ui/modules/_tagsinput.scss +121 -0
  115. data/vendor/assets/stylesheets/flat-ui/modules/_thumbnails.scss +38 -0
  116. data/vendor/assets/stylesheets/flat-ui/modules/_tile.scss +54 -0
  117. data/vendor/assets/stylesheets/flat-ui/modules/_todo.scss +110 -0
  118. data/vendor/assets/stylesheets/flat-ui/modules/_tooltip.scss +56 -0
  119. data/vendor/assets/stylesheets/flat-ui/modules/_type.scss +208 -0
  120. data/vendor/assets/stylesheets/flat-ui/modules/_typeahead.scss +41 -0
  121. data/vendor/assets/stylesheets/flat-ui/modules/_video.scss +458 -0
  122. metadata +251 -0
@@ -0,0 +1,56 @@
1
+ require 'optparse'
2
+ require 'tasks/converter'
3
+ require 'flat-ui-sass/version'
4
+
5
+ module FlatUI
6
+ class CLI
7
+ class << self
8
+ def start(*args)
9
+ options = parse_options!(*args)
10
+ Converter.new(options[:type], options[:input], options).process_flat_ui!
11
+ end
12
+
13
+ private
14
+
15
+ def parse_options!(*args)
16
+ options = {
17
+ type: :pro,
18
+ input: 'flat-ui-pro',
19
+ log_level: 1
20
+ }
21
+
22
+ opt_parser = OptionParser.new do |opts|
23
+ opts.banner = "Usage: fui_convert [options]"
24
+ opts.separator ""
25
+ opts.separator "Options:"
26
+
27
+ opts.on("--type [TYPE]", "-t", [:free, :pro], "Specify the type of conversion to perform (free or pro).","Default is pro") do |type|
28
+ if type
29
+ options[:type] = type.to_sym
30
+ options[:input] = "flat-ui" if type == :free
31
+ end
32
+ end
33
+ opts.on("--log_level [LEVEL]", "-l", OptionParser::DecimalInteger, "Specify the verbosity of the log output", "Default is 1. Levels are 0-3.") do |level|
34
+ options[:log_level] = level if level
35
+ end
36
+ opts.on("--input [DIR]", "-i", "The Flat-UI root directory.","Default is flat-ui-pro") do |dir|
37
+ options[:input] = dir if dir
38
+ end
39
+ opts.on_tail("-h", "--help", "Show help") do
40
+ puts opts
41
+ exit
42
+ end
43
+ opts.on_tail("--version", "Show version") do
44
+ puts "Flat-UI Compatibility:"
45
+ puts " Free v#{FlatUI::VERSION}"
46
+ puts " Pro v#{FlatUI::PRO_VERSION}"
47
+ exit
48
+ end
49
+ end
50
+
51
+ opt_parser.parse!(args)
52
+ options
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,13 @@
1
+ module FlatUI
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ initializer "flat-ui-sass.assets.precompile" do |app|
5
+ if Dir.exist? File.join(::Rails.root, 'vendor', 'assets', 'fonts', 'flat-ui-pro')
6
+ app.config.assets.precompile << %r(flat-ui-pro/flat-ui-icons-regular\.(?:eot|svg|ttf|woff)$)
7
+ else
8
+ app.config.assets.precompile << %r(flat-ui/flat-ui-icons-regular\.(?:eot|svg|ttf|woff)$)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,56 @@
1
+ # Based on bootstrap-sass
2
+ # https://github.com/twbs/bootstrap-sass/blob/master/lib/bootstrap-sass/sass_functions.rb
3
+
4
+ require 'sass'
5
+
6
+ module Sass::Script::Functions
7
+ def flat_ui_font_path(source)
8
+ flat_ui_asset_path source, :font
9
+ end
10
+ declare :flat_ui_font_path, [:source]
11
+
12
+ def flat_ui_image_path(source)
13
+ flat_ui_asset_path source, :image
14
+ end
15
+ declare :flat_ui_image_path, [:source]
16
+
17
+ def flat_ui_asset_path(source, type)
18
+ return Sass::Script::String.new('', :string) if source.to_s.empty?
19
+ url = if FlatUI.asset_pipeline? && (context = sprockets_context)
20
+ context.send(:"#{type}_path", source.value)
21
+ elsif FlatUI.compass?
22
+ send(:"#{type}_url", source, Sass::Script::Bool.new(true)).value.sub /url\((.*)\)$/, '\1'
23
+ end
24
+
25
+ # sass-only
26
+ url ||= source.value.gsub('"', '')
27
+ Sass::Script::String.new(url, :string)
28
+ end
29
+ declare :flat_ui_asset_path, [:source, :type]
30
+
31
+ unless Sass::Script::Functions.instance_methods.include?(:tint)
32
+ def tint(color, percentage)
33
+ assert_type color, :Color
34
+ assert_type percentage, :Number
35
+ white = Sass::Script::Color.new([255, 255, 255])
36
+ mix(white, color, percentage)
37
+ end
38
+ end
39
+
40
+ unless Sass::Script::Functions.instance_methods.include?(:fade)
41
+ def fade(color, amount)
42
+ if amount.is_a?(Sass::Script::Number) && amount.unit_str == "%"
43
+ amount = Sass::Script::Number.new(1 - amount.value / 100.0)
44
+ end
45
+ fade_out(color, amount)
46
+ end
47
+ declare :fade, [:color, :amount]
48
+ end
49
+
50
+ # Based on https://github.com/edwardoriordan/sass-utilities/blob/master/lib/sass-utilities.rb
51
+ # For Sass < 3.3.0, just echo back the variable since we can't interpolate it
52
+ def interpolate_variable(name)
53
+ assert_type name, :String
54
+ ::Sass::VERSION >= '3.3.0' ? environment.var(name.value) : name
55
+ end
56
+ end
@@ -0,0 +1,4 @@
1
+ module FlatUI
2
+ VERSION = '2.1.3'
3
+ PRO_VERSION = '1.2.5'
4
+ end
@@ -0,0 +1,99 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Based on the conversion script used for bootstrap-sass
4
+ # https://github.com/twbs/bootstrap-sass/blob/master/tasks/converter.rb
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this work except in compliance with the License.
8
+ # You may obtain a copy of the License in the LICENSE file, or at:
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'json'
19
+ require 'fileutils'
20
+ require 'forwardable'
21
+ require 'sass'
22
+
23
+ # Pull in stuff from bootstrap-sass
24
+ spec = Gem::Specification.find_by_name('bootstrap-sass')
25
+ %w{char_string_scanner less_conversion}.each do |file|
26
+ require File.join(spec.gem_dir, 'tasks', 'converter', file)
27
+ end
28
+
29
+ require_relative 'converter/flat_ui_less_conversion'
30
+ require_relative 'converter/flat_ui_js_conversion'
31
+ require_relative 'converter/flat_ui_fonts_conversion'
32
+ require_relative 'converter/flat_ui_images_conversion'
33
+ require_relative 'converter/filesystem'
34
+ require_relative 'converter/logger'
35
+
36
+ class Converter
37
+ extend Forwardable
38
+ include FileSystem
39
+ include FlatUILessConversion
40
+ include FlatUIJsConversion
41
+ include FlatUIFontsConversion
42
+ include FlatUIImageConversion
43
+
44
+ def initialize(type = :free, src_path = './flat-ui', options = {})
45
+ @logger = Logger.new(options[:log_level])
46
+ @src_path = File.expand_path(src_path)
47
+ @type = type
48
+ @output_dir = type == :free ? 'flat-ui' : 'flat-ui-pro'
49
+ @dest_path = {
50
+ js: File.join('vendor/assets/javascripts', @output_dir),
51
+ scss: File.join('vendor/assets/stylesheets', @output_dir),
52
+ fonts: File.join('vendor/assets/fonts', @output_dir),
53
+ images: File.join('vendor/assets/images', @output_dir)
54
+ }
55
+ end
56
+
57
+ def_delegators :@logger, :log, :log_status, :log_processing, :log_transform, :log_file_info, :log_processed
58
+
59
+ def process_flat_ui!
60
+ log_status 'Convert Flat UI from LESS to SASS'
61
+ log " type: #{@output_dir}"
62
+ log " input: #{@src_path}"
63
+ log " output:"
64
+ log " js: #{@dest_path[:js]}"
65
+ log " scss: #{@dest_path[:scss]}"
66
+ log " fonts: #{@dest_path[:fonts]}"
67
+ log " images: #{@dest_path[:images]}"
68
+
69
+ setup_file_structure!
70
+
71
+ process_flat_ui_stylesheet_assets!
72
+ process_flat_ui_javascript_assets!
73
+ process_flat_ui_font_assets!
74
+ process_flat_ui_image_assets!
75
+ end
76
+
77
+ def save_file(path, content, mode='w')
78
+ File.open(path, mode) { |file| file.write(content) }
79
+ end
80
+
81
+ def free?
82
+ !pro?
83
+ end
84
+
85
+ def pro?
86
+ @type == :pro
87
+ end
88
+
89
+ private
90
+
91
+ def setup_file_structure!
92
+ @dest_path.each do |_, v|
93
+ FileUtils.rm_rf(v)
94
+ FileUtils.mkdir_p(v)
95
+ end
96
+
97
+ FileUtils.mkdir_p("#{@dest_path[:scss]}/modules")
98
+ end
99
+ end
@@ -0,0 +1,16 @@
1
+ class Converter
2
+ module FileSystem
3
+ def read_files(path, files)
4
+ contents = {}
5
+
6
+ full_path = File.join(@src_path, path)
7
+
8
+ if File.directory?(full_path)
9
+ files.each do |file|
10
+ contents[file] = File.read(File.join(full_path, file), mode: 'rb') || ''
11
+ end
12
+ contents
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+
3
+ class Converter
4
+ module FlatUIFontsConversion
5
+ def process_flat_ui_font_assets!
6
+ log_status 'Processing fonts...'
7
+ save_to = @dest_path[:fonts]
8
+ flat_ui_font_files.each do |file|
9
+ FileUtils.cp "#{@src_path}/fonts/#{file}", "#{save_to}/#{file}"
10
+ end
11
+ end
12
+
13
+ def flat_ui_font_files
14
+ @flat_ui_font_files ||= Dir.chdir "#{@src_path}/fonts" do
15
+ Dir['*.{eot,svg,ttf,woff}'].reject{|f| f =~ /\.dev/}
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ class Converter
2
+ module FlatUIImageConversion
3
+ def process_flat_ui_image_assets!
4
+ log_status 'Processing images...'
5
+ save_to = @dest_path[:images]
6
+ flat_ui_image_files.each do |file|
7
+ new_file = "#{save_to}/#{file}"
8
+ FileUtils.mkdir_p(File.dirname(new_file))
9
+ FileUtils.cp "#{@src_path}/images/#{file}", new_file
10
+ end
11
+ end
12
+
13
+ def flat_ui_image_files
14
+ @flat_ui_image_files ||= Dir.chdir "#{@src_path}/images" do
15
+ Dir['{switch,tile,todo,icons,login,video}/**/*.*']
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ class Converter
2
+ module FlatUIJsConversion
3
+ def process_flat_ui_javascript_assets!
4
+ log_status 'Processing javascripts...'
5
+ save_to = @dest_path[:js]
6
+ read_files('js', flat_ui_js_files).each do |name, file|
7
+ save_file("#{save_to}/#{name}", file)
8
+ end
9
+ log_processed "#{flat_ui_js_files * ' '}"
10
+
11
+ log_status 'Updating javascript manifest'
12
+ content = ''
13
+ flat_ui_js_files.each do |name|
14
+ name = name.gsub(/\.js$/, '')
15
+ content << "//= require #{@output_dir}/#{name}\n"
16
+ end
17
+ manifest = File.expand_path(File.join(@dest_path[:js], '..', "#{@output_dir}.js"))
18
+ save_file(manifest, content)
19
+ log_processed manifest
20
+ end
21
+
22
+ def flat_ui_js_files
23
+ @flat_ui_js_files ||= Dir.chdir "#{@src_path}/js" do
24
+ Dir['flatui-*.js']
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,328 @@
1
+ class Converter
2
+ module FlatUILessConversion
3
+ include Converter::LessConversion
4
+
5
+ # Mixins that are added by FlatUI
6
+ FLAT_UI_MIXINS = %w{placeholder-height mask background-clip dropdown-arrow form-controls-corners-reset
7
+ label-variant navbar-vertical-align social-button-variant}
8
+
9
+ # Mixins that FlatUI has modified
10
+ FLAT_UI_OVERRIDE_MIXINS = %w{placeholder text-hide scale animation horizontal
11
+ vertical directional horizontal-three-colors vertical-three-colors
12
+ radial striped button-variant input-size form-control
13
+ form-control-focus}
14
+
15
+ # Modules missing from Flat UI Pro that are in Flat UI Free
16
+ FLAT_UI_PRO_MISSING_MODULES = %w{}
17
+
18
+ # This is similar to the process_stylesheet_assets
19
+ # utilized by bootstrap-sass except it is specific to
20
+ # flatui
21
+ def process_flat_ui_stylesheet_assets!
22
+ log_status 'Processing stylesheets...'
23
+ files = read_files('less', flat_ui_less_files)
24
+
25
+ log_status ' Converting LESS files to Scss:'
26
+ files.each do |name, file|
27
+ log_processing name
28
+
29
+ # apply common conversions
30
+ # icon-font bombs on this so skip it
31
+ file = convert_less(file) unless name =~ /flat-ui|glyphicons/
32
+ file = replace_file_imports(file)
33
+ file = cleanup_whitespace(file)
34
+ case name
35
+ when 'flat-ui.less'
36
+ lines = file.split "\n"
37
+ lines.reject! {|line|
38
+ #kill the fonts lines, those are up to the user
39
+ #kill variables since those need to be manually imported before bootstrap
40
+ line =~ /fonts|url|variables/
41
+ }
42
+
43
+ # Add a comment for the icon font
44
+ icon_font_import = lines.index {|line| line =~ /glyphicons/}
45
+ lines.insert(icon_font_import, '// Flat-UI-Icons')
46
+ lines.delete_at(icon_font_import+2)
47
+
48
+ file = lines.join "\n"
49
+ when 'mixins.less'
50
+ NESTED_MIXINS.each do |selector, prefix|
51
+ file = flatten_mixins(file, selector, prefix)
52
+ end
53
+ file = varargify_mixin_definitions(file, *VARARG_MIXINS)
54
+ file = deinterpolate_vararg_mixins(file)
55
+ %w(responsive-(in)?visibility input-size text-emphasis-variant bg-variant).each do |mixin|
56
+ file = parameterize_mixin_parent_selector file, mixin
57
+ end
58
+ file = replace_ms_filters(file)
59
+ if pro?
60
+ file = replace_all file, /(?<=[.-])\$state/, '#{$state}'
61
+ else
62
+ # calc-color mixin only exists in Flat-UI free
63
+ file = replace_all file, /-(\$.+-color)/, '-#{\1}'
64
+ file = replace_all file, /#\{\$\$\{(.+)\}\}/, 'interpolate_variable($\1)'
65
+ end
66
+ file = replace_rules(file, ' .list-group-item-') { |rule| extract_nested_rule rule, 'a&' }
67
+ file = replace_all file, /,\s*\.open \.dropdown-toggle& \{(.*?)\}/m,
68
+ " {\\1}\n .open & { &.dropdown-toggle {\\1} }"
69
+ file = replace_all file, '$ratio, $ratio-y', '$scale-args'
70
+ file = convert_grid_mixins file
71
+ when 'variables.less'
72
+ file = insert_default_vars(file)
73
+ if ::Sass::VERSION >= '3.3.0'
74
+ file = unindent <<-SCSS + file, 14
75
+ // a flag to toggle asset pipeline / compass integration
76
+ $flat-ui-sass-asset-helper: function-exists(flat-ui-font-path) !default;
77
+
78
+ SCSS
79
+ else
80
+ file = unindent <<-SCSS + file, 14
81
+ // a flag to toggle asset pipeline / compass integration
82
+ // defaults to true if flat-ui-font-path function is present (no function => twbs-font-path('') parsed as string == right side)
83
+ $flat-ui-sass-asset-helper: (flat-ui-font-path("") != unquote('flat-ui-font-path("")')) !default;
84
+
85
+ SCSS
86
+ end
87
+ file = fix_variable_declaration_order file
88
+ file = replace_all file, /(\$icon-font-path:\s+).*(!default)/, '\1"'+@output_dir+'/" \2'
89
+ when 'modules/buttons.less'
90
+ file = extract_nested_rule file, '.btn-xs&'
91
+ file = extract_nested_rule file, '.btn-hg&'
92
+ when 'modules/forms.less'
93
+ # Fix mixin regex not supporting non-variable arguments
94
+ file.gsub! /@include input-size\((?:\$.+)\);/ do |match|
95
+ match.gsub /; /, ', '
96
+ end
97
+ file = apply_mixin_parent_selector(file, '\.input-(?:sm|lg|hg)')
98
+ when 'modules/input-groups.less'
99
+ file = replace_rules(file, '.input-group-rounded') do |rule|
100
+ extract_and_combine_nested_rules rule
101
+ end
102
+ when 'modules/glyphicons.less'
103
+ file = replace_vars(file)
104
+ file = replace_escaping(file)
105
+ file = replace_all file, /\#\{(url\(.*?\))}/, '\1'
106
+ file = replace_rules(file, '@font-face') { |rule|
107
+ rule = replace_all rule, /(\$icon-font(?:-\w+)+)/, '#{\1}'
108
+ replace_asset_url rule, :font
109
+ }
110
+ when 'modules/login.less'
111
+ file = fix_flat_ui_image_assets file
112
+ when 'modules/navbar.less'
113
+ # Fix mixin regex not supporting non-variable arguments
114
+ file.gsub! /@include input-size\((?:\$.+)\);/ do |match|
115
+ match.gsub /; /, ', '
116
+ end
117
+ file = apply_mixin_parent_selector(file, '\.navbar-input')
118
+ when 'modules/palette.less'
119
+ file.gsub! /@include calc-color\((.+)\);/ do |match|
120
+ match.gsub /#\{([\w\-]+)\}/, '"\1"'
121
+ end
122
+ when 'modules/select.less'
123
+ # Fix the include that the converter makes an extend
124
+ file = replace_all file, /@extend \.caret/, '@include caret'
125
+ when 'modules/spinner.less'
126
+ # Fix mixin regex not supporting non-variable arguments
127
+ file.gsub! /@include spinner-variant\((?:\$?.+)\);/ do |match|
128
+ match.gsub /; /, ', '
129
+ end
130
+ when 'modules/switch.less'
131
+ file = fix_flat_ui_image_assets file
132
+ when 'modules/tile.less'
133
+ file = fix_flat_ui_image_assets file
134
+ when 'modules/todo.less'
135
+ file = fix_flat_ui_image_assets file
136
+ when 'modules/thumbnails.less'
137
+ file = extract_nested_rule file, 'a&'
138
+ when 'modules/type.less'
139
+ # Since .bg-primary has a color associated with it we need to divide it into
140
+ # two selectors
141
+ file = replace_rules(file, '.bg-primary') do |rule|
142
+ parts = rule.split "\n"
143
+ selector = parts.index {|line| line =~ /\.bg-primary/}
144
+ mixin = parts.index {|line| line =~ /@include/}
145
+ parts.insert(mixin, "}\n#{parts[selector]}")
146
+ rule = parts.join "\n"
147
+ end
148
+ file = apply_mixin_parent_selector(file, '\.(text|bg)-(success|primary|info|warning|danger)')
149
+ when 'modules/video.less'
150
+ file = replace_rules(file, /\s*\.vjs(?:-(?:control|time))?(?!-\w+)/) do |rule|
151
+ selector = get_selector(rule).scan(/\.vjs(?:-(?:control|time))?(?!-\w+)/).first
152
+ convert_arbitrary_less_ampersand(rule, selector)
153
+ end
154
+ file = fix_flat_ui_image_assets file
155
+ end
156
+
157
+ name = name.sub(/\.less$/, '.scss')
158
+ base = File.basename(name)
159
+ name.gsub!(base, "_#{base}") unless base == 'flat-ui.scss'
160
+ path = File.join(@dest_path[:scss], name)
161
+ save_file(path, file)
162
+ log_processed File.basename(path)
163
+ end
164
+
165
+ manifest = File.join(@dest_path[:scss], '..', "#{@output_dir}.scss")
166
+ save_file(manifest, "@import \"#{@output_dir}/flat-ui\";")
167
+ end
168
+
169
+ def flat_ui_less_files
170
+ @flat_ui_less_files ||= Dir.chdir "#{@src_path}/less" do
171
+ Dir['**/*.less'].reject{|f| f =~ /(?:demo|docs)\.less$/ }
172
+ end
173
+ end
174
+
175
+ # Set load_shared to read from mixins.less again since bootstrap converted to
176
+ # modular mixins.
177
+ def load_shared
178
+ @shared_mixins ||= begin
179
+ log_status ' Reading shared mixins from mixins.less'
180
+ read_mixins read_files('less', ['mixins.less'])['mixins.less'], nested: NESTED_MIXINS
181
+ end
182
+ end
183
+
184
+ def extract_and_combine_nested_rules(file)
185
+ matches = Hash.new {|k,v| k[v] = []}
186
+ file = file.dup
187
+ file.scan(/\.[\w-]+&/x) do |selector|
188
+ #first find the rules, and remove them
189
+ file = replace_rules(file, "\s*#{selector}") do |rule, pos, css|
190
+ selector = selector.gsub(/&$/, '')
191
+ styles = rule.split(/[{}]/).last.strip
192
+ parent = selector_for_pos(css, pos.begin).split('{').last.strip
193
+ matches[selector] << create_rule(parent, styles)
194
+
195
+ # Return an empty string to blank out this rule
196
+ ""
197
+ end
198
+ end
199
+
200
+ # Generate the combined nested rules
201
+ rules = matches.inject("") do |s, (rule, children)|
202
+ s += create_rule "&#{rule}", *children
203
+ end
204
+ close = close_brace_pos file, 0
205
+
206
+ file.insert(close, indent(rules))
207
+ end
208
+
209
+ def create_rule(name, *styles)
210
+ rule = "#{unindent(name)} {\n"
211
+ styles.each {|s| rule += indent "#{s}\n"}
212
+ rule += "}\n"
213
+ end
214
+
215
+ # TODO this method is on the brittle side
216
+ # look into make it more robust
217
+ def fix_variable_declaration_order(file)
218
+ # Spinner needs to be moved after Buttons
219
+ # since it depends on $btn-default-bg
220
+ #
221
+ # also spinner-btn-hover-bg needs to be
222
+ # before spinner-up-btn-border
223
+ if file.include? 'Spinner'
224
+ lines = file.split "\n"
225
+ spinner_start = lines.index {|l| l =~ /Spinner/}
226
+ spinner_end = lines.index {|l| l =~ /Pagination/} - 1
227
+ buttons_end = lines.index {|l| l =~ /Navs/} - 1
228
+
229
+ (spinner_end - spinner_start).times do
230
+ lines.insert(buttons_end, lines.delete_at(spinner_start))
231
+ end
232
+
233
+ spinner_btn_bg = lines.index {|l| l =~ /spinner-btn-bg:/}-1
234
+ 3.times do
235
+ lines.insert(spinner_btn_bg+5, lines.delete_at(spinner_btn_bg))
236
+ end
237
+
238
+ file = lines.join("\n")
239
+ end
240
+ file
241
+ end
242
+
243
+ def fix_relative_asset_url(rule, type)
244
+ # Use a really naive pluralization
245
+ replace_all rule, /url\(['"]?\.\.\/#{type}s\/([a-zA-Z0-9\-\/\.\?#]+)['"]?\)/, "url(\"#{@output_dir}/\\1\")"
246
+ end
247
+
248
+ def fix_flat_ui_image_assets(file)
249
+ file = replace_all file, /\#\{(url\(.*?\).*?)}/, '\1'
250
+ file = fix_relative_asset_url file, :image
251
+ file = replace_asset_url file, :image
252
+ end
253
+
254
+ def cleanup_whitespace(file)
255
+ file.gsub(/\r|\t/, "")
256
+ end
257
+
258
+ # Based on the original convert_less_ampersand but modified
259
+ # for flat_ui_sass
260
+ def convert_arbitrary_less_ampersand(less, selector)
261
+ return less unless less.include?(selector)
262
+
263
+ styles = less.dup
264
+ tmp = "\n"
265
+ less.scan(/^(\s*&)(-[\w\[\]-]+\s*\{.+?})/m) do |ampersand, css|
266
+ tmp << "#{selector}#{unindent(css)}\n"
267
+ styles.gsub! "#{ampersand}#{css}", ""
268
+ end
269
+
270
+ if tmp.length > 1
271
+ styles.gsub!(/\s*#{"\\"+selector}\s*\{\s*}/m, '')
272
+ styles << tmp
273
+ else
274
+ styles = less
275
+ end
276
+
277
+ styles
278
+ end
279
+
280
+ #
281
+ # Methods overridden from the bootstrap-sass converter
282
+ #
283
+
284
+ def replace_asset_url(rule, type)
285
+ replace_all rule, /url\((.*?)\)/, "url(if($flat-ui-sass-asset-helper, flat-ui-#{type}-path(\\1), \\1))"
286
+ end
287
+
288
+ # @import "file" to "#{@output_dir)}/file"
289
+ def replace_file_imports(file)
290
+ file.gsub %r([@\$]import ["|'](.*)["|'];),
291
+ %Q(@import "#{@output_dir}/\\1";)
292
+ end
293
+
294
+ # Regex will match things like spinner-input-width
295
+ # by default.
296
+ #
297
+ # Fix the first lookaround to be a positive
298
+ # lookaround and also check for word chars
299
+ # after the word 'spin'
300
+ def replace_spin(less)
301
+ less.gsub(/(?<![\-$@.])spin(?![\-\w])/, 'adjust-hue')
302
+ end
303
+
304
+ # Fix to support replacing mixin definitions with default args
305
+ # https://github.com/twbs/bootstrap-sass/blob/master/tasks/converter/less_conversion.rb#L293
306
+ #
307
+ # @mixin a() { tr& { color:white } }
308
+ # to:
309
+ # @mixin a($parent) { tr#{$parent} { color: white } }
310
+ def parameterize_mixin_parent_selector(file, rule_sel)
311
+ log_transform rule_sel
312
+ param = '$parent'
313
+ replace_rules(file, '^\s*@mixin\s*' + rule_sel) do |mxn_css|
314
+ mxn_css.sub! /(?=@mixin)/, "// [converter] $parent hack\n"
315
+ # insert param into mixin def
316
+ mxn_css.sub!(/(@mixin [\w-]+)\(([\$\w\-:,\s]*)\)/) { "#{$1}(#{param}#{', ' if $2 && !$2.empty?}#{$2})" }
317
+ # wrap properties in #{$parent} { ... }
318
+ replace_properties(mxn_css) { |props|
319
+ next props if props.strip.empty?
320
+ spacer = ' ' * indent_width(props)
321
+ "#{spacer}\#{#{param}} {\n#{indent(props.sub(/\s+\z/, ''), 2)}\n#{spacer}}"
322
+ }
323
+ # change nested& rules to nested#{$parent}
324
+ replace_rules(mxn_css, /.*&[ ,:]/) { |rule| replace_in_selector rule, /&/, "\#{#{param}}" }
325
+ end
326
+ end
327
+ end
328
+ end