flat-ui-sass 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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