patternfly-sass 2.9.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -1
  3. data/Rakefile +17 -11
  4. data/assets/fonts/patternfly/PatternFlyIcons-webfont.eot +0 -0
  5. data/assets/fonts/patternfly/PatternFlyIcons-webfont.svg +17 -2
  6. data/assets/fonts/patternfly/PatternFlyIcons-webfont.ttf +0 -0
  7. data/assets/fonts/patternfly/PatternFlyIcons-webfont.woff +0 -0
  8. data/assets/images/patternfly/apple-touch-icon-precomposed-114.png +0 -0
  9. data/assets/images/patternfly/apple-touch-icon-precomposed-144.png +0 -0
  10. data/assets/images/patternfly/apple-touch-icon-precomposed-152.png +0 -0
  11. data/assets/images/patternfly/apple-touch-icon-precomposed-180.png +0 -0
  12. data/assets/images/patternfly/apple-touch-icon-precomposed-57.png +0 -0
  13. data/assets/images/patternfly/apple-touch-icon-precomposed-72.png +0 -0
  14. data/assets/images/patternfly/apple-touch-icon-precomposed-76.png +0 -0
  15. data/assets/images/patternfly/bg-navbar-pf-alt.svg +9 -0
  16. data/assets/images/patternfly/brand-alt.svg +88 -0
  17. data/assets/images/patternfly/favicon.ico +0 -0
  18. data/assets/images/patternfly/logo-alt.svg +18 -0
  19. data/assets/images/patternfly/logo.svg +22 -22
  20. data/assets/images/patternfly/spinner-inverse-lg.gif +0 -0
  21. data/assets/images/patternfly/spinner-inverse-sm.gif +0 -0
  22. data/assets/images/patternfly/spinner-inverse-xs.gif +0 -0
  23. data/assets/images/patternfly/spinner-inverse.gif +0 -0
  24. data/assets/javascripts/patternfly.js +70 -0
  25. data/assets/javascripts/patternfly.min.js +1 -1
  26. data/assets/stylesheets/_patternfly.scss +9 -30
  27. data/assets/stylesheets/patternfly/_dropdowns.scss +62 -0
  28. data/assets/stylesheets/patternfly/_icons.scss +45 -0
  29. data/assets/stylesheets/patternfly/_list-group.scss +1 -1
  30. data/assets/stylesheets/patternfly/_list-view.scss +230 -0
  31. data/assets/stylesheets/patternfly/_mixins.scss +6 -4
  32. data/assets/stylesheets/patternfly/_toast.scss +2 -40
  33. data/assets/stylesheets/patternfly/_variables.scss +23 -4
  34. data/assets/stylesheets/patternfly/{_ext-bootstrap-switch.scss → sass-contrib/bootstrap-switch.scss} +0 -0
  35. data/bower.json +1 -1
  36. data/lib/patternfly-sass/version.rb +2 -2
  37. data/package.json +1 -1
  38. data/patternfly-sass.gemspec +1 -0
  39. data/spec/html/accordions.html +161 -34
  40. data/spec/html/charts.html +41 -0
  41. data/spec/html/dist/css/patternfly-additions.css +300 -38
  42. data/spec/html/dist/css/patternfly-additions.css.map +1 -1
  43. data/spec/html/dist/css/patternfly-additions.min.css +1 -1
  44. data/spec/html/dist/css/patternfly-additions.min.css.map +1 -1
  45. data/spec/html/dist/css/patternfly.css +59 -1
  46. data/spec/html/dist/css/patternfly.css.map +1 -1
  47. data/spec/html/dist/css/patternfly.min.css +1 -1
  48. data/spec/html/dist/css/patternfly.min.css.map +1 -1
  49. data/spec/html/dropdowns.html +50 -0
  50. data/spec/html/icons.html +80 -0
  51. data/spec/html/index.html +3 -0
  52. data/spec/html/list-view.html +546 -0
  53. data/spec/html/toast.html +12 -20
  54. data/spec/html/toolbar.html +12 -10
  55. data/tasks/converter.rb +253 -399
  56. metadata +35 -18
  57. data/assets/images/patternfly/apple-touch-icon-114-precomposed.png +0 -0
  58. data/assets/images/patternfly/apple-touch-icon-144-precomposed.png +0 -0
  59. data/assets/images/patternfly/apple-touch-icon-57-precomposed.png +0 -0
  60. data/assets/images/patternfly/apple-touch-icon-72-precomposed.png +0 -0
  61. data/assets/images/patternfly/brand-lg.png +0 -0
  62. data/assets/images/patternfly/brand.png +0 -0
  63. data/assets/images/patternfly/logo.png +0 -0
  64. data/spec/html/dist/css/styles-additions.css +0 -1
  65. data/spec/html/dist/css/styles-additions.min.css +0 -1
  66. data/spec/html/dist/css/styles.css +0 -1
  67. data/spec/html/dist/css/styles.min.css +0 -1
@@ -74,16 +74,18 @@
74
74
  </div>
75
75
  <hr>
76
76
  <div class="toast-pf alert alert-info">
77
- <div class="dropdown btn-group">
78
- <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"><span class="fa fa-ellipsis-v"></span></button>
79
- <ul class="dropdown-menu pull-right">
80
- <li><a href="#">Action</a></li>
81
- <li><a href="#">Another action</a></li>
82
- <li><a href="#">Something else here</a></li>
83
- <li role="separator" class="divider"></li>
84
- <li><a href="#">Separated link</a></li>
85
- </ul>
86
- </div>
77
+ <div class="dropdown pull-right dropdown-kebab-pf">
78
+ <button class="btn btn-link dropdown-toggle" type="button" id="dropdownKebabRight" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
79
+ <span class="fa fa-ellipsis-v"></span>
80
+ </button>
81
+ <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownKebabRight">
82
+ <li><a href="#">Action</a></li>
83
+ <li><a href="#">Another action</a></li>
84
+ <li><a href="#">Something else here</a></li>
85
+ <li><a href="#">Separated link</a></li>
86
+ </ul>
87
+ </div>
88
+
87
89
  <div class="pull-right toast-pf-action">
88
90
  <a href="#">Reload Server</a>
89
91
  </div>
@@ -126,16 +128,6 @@
126
128
  <span class="pficon pficon-warning-triangle-o"></span>
127
129
  Max-width is set on this example.
128
130
  </div>
129
- <script>
130
- // Initialize Tooltip
131
- $(document).ready(function() {
132
- $('.toast-pf').tooltip({
133
- selector: "[data-toggle=tooltip]",
134
- container: "body"
135
- });
136
- });
137
- </script>
138
-
139
131
  </div><!-- /container -->
140
132
  </body>
141
133
  </html>
@@ -167,16 +167,18 @@
167
167
  <div class="form-group">
168
168
  <button class="btn btn-default" type="button">Action</button>
169
169
  <button class="btn btn-default" type="button">Action</button>
170
- <div class="dropdown btn-group">
171
- <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="fa fa-ellipsis-v"></span></button>
172
- <ul class="dropdown-menu">
173
- <li><a href="#">Action</a></li>
174
- <li><a href="#">Another action</a></li>
175
- <li><a href="#">Something else here</a></li>
176
- <li role="separator" class="divider"></li>
177
- <li><a href="#">Separated link</a></li>
178
- </ul>
179
- </div>
170
+ <div class="dropdown btn-group dropdown-kebab-pf">
171
+ <button class="btn btn-link dropdown-toggle" type="button" id="dropdownKebab" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
172
+ <span class="fa fa-ellipsis-v"></span>
173
+ </button>
174
+ <ul class="dropdown-menu " aria-labelledby="dropdownKebab">
175
+ <li><a href="#">Action</a></li>
176
+ <li><a href="#">Another action</a></li>
177
+ <li><a href="#">Something else here</a></li>
178
+ <li><a href="#">Separated link</a></li>
179
+ </ul>
180
+ </div>
181
+
180
182
  </div>
181
183
  <div class="form-group toolbar-pf-view-selector">
182
184
  <ul class="list-inline">
@@ -1,444 +1,298 @@
1
1
  BOOTSTRAP_GEM_ROOT = Gem::Specification.find_by_name("bootstrap-sass").gem_dir
2
- require "#{BOOTSTRAP_GEM_ROOT}/tasks/converter"
3
- require 'pathname'
4
-
5
- module Patternfly
6
- class Converter < ::Converter
7
- BOOTSTRAP_LESS_ROOT = 'bower_components/bootstrap/less'
8
- PATTERNFLY_LESS_ROOT = 'less'
9
- PATTERNFLY_COMPONENTS = "../components/patternfly/components"
10
-
11
- # Override
12
- def initialize(options)
13
- defaults = {
14
- :branch => 'master',
15
- :repo => 'patternfly/patternfly',
16
- :cache_path => 'tmp/converter-cache-patternfly',
17
- :test_dir => 'spec/html'
18
- }
19
- options = defaults.merge(options)
20
- super(:repo => options[:repo], :cache_path => options[:cache_path], :branch => options[:branch])
21
- @save_to = {
22
- :scss => 'assets/stylesheets/patternfly',
23
- :js => 'assets/javascripts',
24
- :fonts => 'assets/fonts/patternfly'
25
- }
26
- @test_dir = options[:test_dir]
27
- get_trees(PATTERNFLY_LESS_ROOT, 'tests', 'dist')
28
- end
29
-
30
- def process_patternfly
31
- log_status "Convert Patternfly LESS to SASS"
32
- puts " repo : #@repo_url"
33
- puts " branch : #@branch_sha #@repo_url/tree/#@branch"
34
- puts " save to: #{@save_to.to_json}"
35
- puts " twbs cache: #{@cache_path}"
36
- puts '-' * 60
37
-
38
- @save_to.values { |v| FileUtils.mkdir_p(v) }
39
-
40
- process_font_assets
41
- process_patternfly_less_assets
42
- process_javascript_assets
43
- store_version
44
- cache_tests
45
- end
2
+ require "#{BOOTSTRAP_GEM_ROOT}/tasks/converter/less_conversion"
3
+ require 'rugged'
4
+
5
+ class Converter
6
+ include Converter::LessConversion
7
+
8
+ TEST_DIR = File.join('spec', 'html')
9
+ TRANSFORMATIONS = [
10
+ :replace_vars,
11
+ :replace_file_imports,
12
+ :replace_mixin_definitions,
13
+ :replace_mixins,
14
+ :replace_spin,
15
+ # :replace_fadein,
16
+ :replace_image_urls,
17
+ :replace_escaping,
18
+ :convert_less_ampersand,
19
+ :deinterpolate_vararg_mixins,
20
+ :replace_calculation_semantics,
21
+ :remove_unnecessary_escaping
22
+ ]
23
+ TOP = <<-VAR.gsub(/^\s*/, '')
24
+ // PatternFly SASS
25
+ @import "patternfly/variables";
26
+ @import "bootstrap/variables";
27
+ VAR
28
+
29
+ def initialize(options={})
30
+ @repository = options.fetch(:repository, 'patternfly/patternfly')
31
+ @branch = options.fetch(:branch, 'master')
32
+ @destination = options.fetch(:destination, 'assets')
33
+ @cache_path = options.fetch(:cache_path, 'tmp')
34
+
35
+ @source = File.join(@cache_path, 'repository')
36
+ end
46
37
 
47
- def remove_xforms(transforms, *rejects)
48
- transforms.reject do |xform|
49
- rejects.include?(xform)
50
- end
51
- end
38
+ def convert
39
+ checkout_upstream
40
+ copy_non_less
41
+ process_stylesheets
42
+ store_version
43
+ FileUtils.rm_rf(@cache_path) # Clean up the repository & the cache
44
+ end
52
45
 
53
- def process_font_assets
54
- log_status 'Processing fonts...'
55
- files = read_files(get_paths_by_type('dist/fonts', /\.(eot|svg|ttf|woff2?)$/))
56
- save_to = @save_to[:fonts]
57
- files.each do |name, content|
58
- save_file File.join(save_to, name.gsub('dist/fonts/', '')), content
59
- end
60
- end
46
+ private
61
47
 
62
- def process_javascript_assets
63
- log_status 'Processing javascripts...'
64
- save_to = @save_to[:js]
65
- files = read_files(get_paths_by_type('dist/js', /\.js$/))
66
- files.each do |name, content|
67
- save_file File.join(save_to, name.gsub('dist/js/', '')), content
68
- end
69
- end
48
+ def sass_read_mixins(file)
49
+ file.scan(/@mixin\s+([^\(]+)\(/).flatten.uniq
50
+ end
70
51
 
71
- def process_image_assets
72
- log_status 'Processing images...'
73
- save_to = @save_to[:img]
74
- files = read_files(get_paths_by_type('dist/img', /\.(png|gif|jpg|svg?)$/))
75
- files.each do |name, content|
76
- save_file File.join(save_to, name.gsub('dist/img/', '')), content
77
- end
78
- end
52
+ def replace_mixins(file)
53
+ mixins = shared_mixins + sass_read_mixins(file)
54
+ super(file, mixins)
55
+ end
79
56
 
80
- def process_patternfly_less_assets
81
- log_status "Processing stylesheets..."
82
- files = read_files(bootstrap_less_files)
83
- files['less/mixin_overrides.less'] = files['less/mixins.less'].dup
84
- # Merge the two separated top level files because they will be splitted on a higher level
85
- files['less/patternfly.less'] += files.delete('less/patternfly-additions.less')
86
- save_to = @save_to[:scss]
87
-
88
- files.each do |name, file|
89
- # TODO unify the case statements. Maybe pass in two procs as
90
- # callbacks; one for before and one for after.
91
- #
92
- # TODO override replace_spin so its regex isn't so over-zealous
93
- transforms = DEFAULT_TRANSFORMS.dup
94
- name = File.basename(name)
95
- case name
96
- when 'mixin_overrides.less'
97
- button_variant = ".button-variant(.*?)"
98
- file = replace_rules(file, button_variant) do |rule, pos|
99
- ""
100
- end
101
- when 'patternfly.less', 'bootstrap-touchspin.less', 'variables.less'
102
- transforms = remove_xforms(transforms, :replace_spin)
103
- when 'spinner.less'
104
- transforms = remove_xforms(transforms, :replace_spin)
105
- end
106
-
107
- file = convert_less(file, *transforms)
108
-
109
- # Special cases go here
110
- case name
111
- when 'fonts.less', 'icons.less'
112
- file = replace_rules(file, /\s*@font-face/) do |rule|
113
- replace_asset_url rule, :font
114
- end
115
- when 'mixins.less'
116
- NESTED_MIXINS.each do |selector, prefix|
117
- file = flatten_mixins(file, selector, prefix)
118
- end
119
- file = replace_all(file, /,\s*\.open\s+\.dropdown-toggle& \{([^\{\}]*?)\}/m, " {\\1}\n .open & { &.dropdown-toggle {\\1} }")
120
- file = replace_all(file, /,\s*\.open\s+\.dropdown-toggle& \{(.*?\{.*?\}.*?)\}/m, " {\\1}\n .open & { &.dropdown-toggle {\\1} }") when 'mixin_overrides.less'
121
- NESTED_MIXINS.each do |selector, prefix|
122
- file = flatten_mixins(file, selector, prefix)
123
- end
124
- when 'variables.less'
125
- file = insert_default_vars(file)
126
- file = ['$patternfly-sass-asset-helper: false !default;', file].join("\n")
127
- file = replace_all(file, %r{"../img"}, '"../images"')
128
- file = replace_all file, %r{(\$font-path): (\s*)"(.*)" (!default);}, '\\1: \\2if($patternfly-sass-asset-helper, "patternfly", "\\3/patternfly") \\4;'
129
- file = replace_all file, %r{(\$img-path): (\s*)"(.*)" (!default);}, '\\1: \\2if($patternfly-sass-asset-helper, "patternfly", "\\3/patternfly") \\4;'
130
- file = replace_all file, %r{(\$icon-font-path): (\s*)"(.*)" (!default);\n}, ''
131
- file = replace_all file, %r{(\$fa-font-path): (\s*)"(.*)" (!default);\n}, ''
132
-
133
- when 'patternfly.less'
134
- file = fix_top_level(file)
135
- add_to_dist('bootstrap-combobox')
136
- add_to_dist('bootstrap-select')
137
- # add_to_dist('bootstrap-switch')
138
- add_to_dist('bootstrap-touchspin', 'dist/jquery.bootstrap-touchspin')
139
- add_to_dist('bootstrap-datepicker', 'bootstrap-datepicker3')
140
- add_to_dist('c3')
141
- end
142
-
143
- name_out = "#{File.basename(name, ".less")}.scss"
144
- name_out = "_#{name_out}"
145
-
146
- path = File.join(save_to, name_out)
147
- save_file(path, file)
148
- log_processed(File.basename(path))
149
- end
57
+ def remove_button_variant(file)
58
+ replace_rules(file, /.button-variant(.*?)/) { |_, _| "" }
59
+ end
150
60
 
151
- FileUtils.mv("#{save_to}/_patternfly.scss", File.expand_path("#{save_to}/../_patternfly.scss"))
152
- end
61
+ # SASS doesn't require escaping in calc()
62
+ def remove_unnecessary_escaping(file)
63
+ file.gsub(/calc\(\~\'([^\']+)\'\)/, 'calc(\1)')
64
+ end
153
65
 
154
- # Load external components from rails-assets.org
155
- def add_to_dist(gemname, file=nil)
156
- file = "app/assets/stylesheets/#{gemname}/#{file.nil? ? gemname : file}.scss"
157
- in_file = File.join(Gem::Specification.find_by_name("rails-assets-#{gemname}").gem_dir, file)
158
- puts in_file
159
- out_file = File.join(@save_to[:scss], "_ext-#{gemname}.scss")
160
- FileUtils.cp(in_file, out_file)
161
- log_processed("Moving #{in_file} to #{out_file}")
162
- end
66
+ # Override
67
+ def replace_file_imports(less, target_path='')
68
+ less.gsub!(
69
+ %r{[@\$]import\s+(?:\(\w+\)\s+)?["|']([\w\-\./]+).less["|'];},
70
+ "@import \"#{target_path}\\1\";"
71
+ )
72
+ less.gsub!(
73
+ %r{[@\$]import\s+(?:\(\w+\)\s+)?["|']([\w\-\./]+).(css)["|'];},
74
+ "@import \"#{target_path}\\1.\\2\";"
75
+ )
76
+ less
77
+ end
163
78
 
164
- def convert_less(less, *transforms)
165
- load_shared
166
- less = convert_to_scss(less, *transforms)
167
- less = yield(less) if block_given?
168
- less
169
- end
79
+ def insert_default_vars(file)
80
+ file = super(file)
81
+ file = replace_all(file, %r{"../img"}, '"../images"')
82
+ file = replace_all(file, %r{(\$icon-font-path): (\s*)"(.*)" (!default);\n}, '')
83
+ file = replace_all(file, %r{(\$fa-font-path): (\s*)"(.*)" (!default);\n}, '')
84
+ file = replace_all(
85
+ file,
86
+ %r{(\$(font|img)-path):(\s*)"(.*)" (!default);},
87
+ '\\1:\\3if($patternfly-sass-asset-helper, "patternfly", "\\4/patternfly") \\5;')
88
+ ['$patternfly-sass-asset-helper: false !default;', file].join("\n")
89
+ end
170
90
 
171
- DEFAULT_TRANSFORMS = [
172
- :replace_vars,
173
- :replace_file_imports,
174
- :replace_mixin_definitions,
175
- {:replace_mixins => ["mixins"]},
176
- :replace_spin,
177
- # :replace_fadein,
178
- :replace_image_urls,
179
- :replace_escaping,
180
- :convert_less_ampersand,
181
- :deinterpolate_vararg_mixins,
182
- :replace_calculation_semantics,
183
- ]
91
+ def flatten_mixins(file)
92
+ NESTED_MIXINS.inject(file) { |a, e| super(a, e.first, e.last) }
93
+ end
184
94
 
185
- def convert_to_scss(file, *transforms)
186
- # TODO The logging noop is to avoid a warning about an unused variable.
187
- # We actually are using mixins but we are reading it with an eval.
188
- # Possibly worth checking the arity of the method represented by xform
189
- # and send in variable in a defined order based on it? But that limits
190
- # us to a parameter order that every xform must follow.
191
- # Something like
192
- # params = [file, mixins]
193
- # arity = self.method(xform).arity
194
- # send(xform, *params[0..arity])
195
- mixins = @shared_mixins + read_mixins(file)
196
- silence_log do
197
- log_status(mixins)
198
- end
199
- transforms.each do |xform|
200
- args = ["file"]
201
- if xform.is_a?(Hash)
202
- args.concat(xform.values.first)
203
- xform = xform.keys.first
204
- end
205
- args.map! { |a| "#{eval a}" }
206
- file = send(xform, *args)
207
- end
208
- file
209
- end
95
+ def fix_dropdown_toggle(file)
96
+ replacestr = " {\\1}\n .open & { &.dropdown-toggle {\\1} }"
97
+ file = replace_all(file, /,\s*\.open\s+\.dropdown-toggle& \{([^\{\}]*?)\}/m, replacestr)
98
+ replace_all(file, /,\s*\.open\s+\.dropdown-toggle& \{(.*?\{.*?\}.*?)\}/m, replacestr)
99
+ end
210
100
 
211
- def fix_top_level(file)
212
- file = replace_all(file, %r{@import\s+"variables";}, "")
213
- file = replace_all(file, /@import "([^\.]{2})/, '@import "patternfly/\1')
214
- file = replace_all(file, %r{../components/font-awesome/less/font-awesome}, "font-awesome")
215
- file = replace_all(file, %r{../components/bootstrap-select/less/bootstrap-select}, "patternfly/ext-bootstrap-select")
216
- file = replace_all(file, %r{../components/bootstrap-touchspin/dist/jquery.bootstrap-touchspin.css}, "patternfly/ext-bootstrap-touchspin")
217
- file = replace_all(file, %r{../components/bootstrap-switch/src/less/bootstrap3/bootstrap-switch}, "patternfly/ext-bootstrap-switch")
218
- file = replace_all(file, %r{@import\s+"../components/bootstrap/less/bootstrap";}, fetch_bootstrap_sass)
219
- file = replace_all(file, %r{../components/bootstrap-combobox/less/combobox}, "patternfly/ext-bootstrap-combobox")
220
- file = replace_all(file, %r{../components/bootstrap-datepicker/less/datepicker3}, "patternfly/ext-bootstrap-datepicker")
221
- file = replace_all(file, %r{../components/c3/c3.css}, "patternfly/ext-c3")
222
-
223
-
224
- # Remove undesired lines from the merged top level file
225
- file = replace_all(file, "@import \"../components/bootstrap/less/variables\";\n", "")
226
- file = replace_all(file, "// Bootstrap variables and mixins\n@import \"../components/bootstrap/less/mixins\";\n", "")
227
- file = replace_all(file, "// Font Awesome variables\n@import \"../components/font-awesome/less/variables\";\n", "")
228
- # Remove duplicate lines
229
- file = file.split("\n").uniq.join("\n").concat("\n")
230
-
231
- # Variables need to be declared before they are used.
232
- variables = <<-VAR.gsub(/^\s*/, '')
233
- @import "patternfly/variables";
234
- @import "bootstrap/variables";
235
- VAR
236
- variables + file
237
- end
101
+ def fix_font_paths(file)
102
+ replace_rules(file, /\s*@font-face/) { |rule| replace_asset_url(rule, :font) }
103
+ end
238
104
 
239
- def fetch_bootstrap_sass
240
- bootstrap_sass = IO.read(File.join(BOOTSTRAP_GEM_ROOT, 'assets', 'stylesheets', '_bootstrap.scss'))
105
+ def fix_top_level(file)
106
+ file = replace_all(file, %r{@import\s+"variables";}, "")
107
+ file = replace_all(file, /@import "([^\.]{2})/, '@import "patternfly/\1')
241
108
 
242
- bootstrap_sass = replace_all(
243
- bootstrap_sass,
244
- %r{@import\s+"bootstrap/variables";},
245
- ""
246
- )
109
+ file = replace_all(file, "@import \"../components/bootstrap/less/bootstrap\";", fetch_bootstrap_top)
110
+ file = replace_all(file, "@import \"../components/bootstrap/less/variables\";\n", '')
111
+ file = replace_all(file, "@import \"../components/bootstrap/less/mixins\";\n", '')
247
112
 
248
- mixin_location = end_of(bootstrap_sass, %r{@import\s+"bootstrap/mixins";}).first
249
- bootstrap_sass = bootstrap_sass[0..mixin_location] + "@import \"patternfly/mixin_overrides\";\n" + bootstrap_sass[mixin_location..-1]
250
- bootstrap_sass
251
- end
113
+ file = replace_all(file, "@import \"../components/font-awesome/less/variables\";\n", '')
114
+ file = replace_all(file, '../components/font-awesome/less/font-awesome', 'font-awesome')
115
+ file = replace_all(file, '../components/bootstrap-combobox/less/combobox', 'bootstrap-combobox')
116
+ file = replace_all(file, '../components/bootstrap-select/less/bootstrap-select', 'bootstrap-select')
117
+ file = replace_all(file, '../components/bootstrap-touchspin/dist/jquery.bootstrap-touchspin.css', 'bootstrap-touchspin/dist/jquery.bootstrap-touchspin')
118
+ file = replace_all(file, '../components/c3/c3.css', 'c3')
119
+ file = replace_all(file, '../components/bootstrap-datepicker/less/datepicker3', 'bootstrap-datepicker/bootstrap-datepicker3')
252
120
 
253
- def end_of(s, regex)
254
- # Returns an array with the end position of each match
255
- s.enum_for(:scan, regex).map { Regexp.last_match.end(0) }
256
- end
121
+ sass_contrib('bootstrap-switch/src/less/bootstrap3/bootstrap-switch.less', 'bootstrap-switch.scss')
122
+ file = replace_all(file, '../components/bootstrap-switch/src/less/bootstrap3/bootstrap-switch', 'patternfly/sass-contrib/bootstrap-switch')
257
123
 
258
- # Override
259
- def replace_file_imports(less, target_path='')
260
- less.gsub!(
261
- %r([@\$]import\s+(?:\(\w+\)\s+)?["|']([\w\-\./]+).less["|'];),
262
- %Q(@import "#{target_path}\\1";)
263
- )
264
- less.gsub!(
265
- %r([@\$]import\s+(?:\(\w+\)\s+)?["|']([\w\-\./]+).(css)["|'];),
266
- %Q(@import "#{target_path}\\1.\\2";)
267
- )
268
- less
269
- end
124
+ TOP + remove_comments_and_whitespace(file)
125
+ end
270
126
 
271
- # Override - bootstrap-sass doesn't handle cases where interpolation occurs outside
272
- # double quotes and removes the curly braces too early in the replace process.
273
- def replace_escaping(less)
274
- # Get rid of ~"" escape
275
- less = less.gsub(/~"([^"]+)"/, '#{\1}')
276
- # interpolate variable in string, e.g. url("$file-1x") => url("#{$file-1x}")
277
- less.gsub!(/\$\{([\w\-]+)\}/, '#{$\1}')
278
- # less.gsub!(/(?:"|')([^"'\n]*)(\$\{[\w\-]+\})([^"'\n]*)(?:"|')/, '"\1#{\2}\3"')
279
- # Get rid of @{} escape
280
- less.gsub!(/\$\{([^}]+)\}/, '$\1')
281
- # Get rid of e(%("")) escape
282
- less.gsub(/(\W)e\(%\("?([^"]*)"?\)\)/, '\1\2')
283
- end
127
+ def sass_contrib(src, dst)
128
+ base = 'assets/stylesheets/patternfly/sass-contrib'
129
+ less = File.read(File.join('bower_components', src))
130
+ sass = less_to_sass(nil, less)
131
+ FileUtils.mkdir_p(base) unless File.exist?(base)
132
+ File.open(File.join(base, dst), 'w') { |f| f.write(sass) }
133
+ end
284
134
 
285
- def cache_tests
286
- FileUtils.mkdir_p(@test_dir)
287
- test_files = get_paths_by_directory('tests')
288
- dist_files = get_paths_by_directory('dist/css')
289
- test_contents = read_files(test_files)
290
- dist_contents = fixup_path(read_files(dist_files))
291
- test_contents.merge(dist_contents).each do |file, content|
292
- # We go through all this rigmarole so we can save the tests and their
293
- # directory structure in a root of our choosing.
294
- top = ""
295
- # Get the top level directory
296
- Pathname.new(file).ascend do |v|
297
- top = v
298
- end
299
- # Get the filename below the top directory
300
- save_path = Pathname.new(file).relative_path_from(top).to_s
301
-
302
- # Create the correct destination
303
- save_path = File.join(@test_dir, save_path)
304
- unless File.directory?(File.dirname(save_path))
305
- FileUtils.mkdir_p(File.dirname(save_path))
306
- end
307
- save_file(save_path, content)
308
- end
135
+ def shared_mixins
136
+ @shared_mixins ||= begin
137
+ mixins = retrieve_files(File.join(@source, 'components', 'bootstrap', 'less', 'mixins'), /\.less$/)
138
+ mixins.unshift File.join(@source, 'less', 'mixins.less')
139
+ read_mixins(mixins.map { |f| File.read(f) }.join("\n"), :nested => NESTED_MIXINS)
309
140
  end
141
+ end
310
142
 
311
- def fixup_path(hash)
312
- Hash[hash.map { |k, v| ["dist/#{k}", v] }]
313
- end
143
+ def fetch_bootstrap_top
144
+ path = File.join(BOOTSTRAP_GEM_ROOT, 'assets', 'stylesheets', '_bootstrap.scss')
145
+ file = replace_all(File.read(path), %r{@import\s+"bootstrap/variables";}, '')
146
+ replace_all(file, %r{^(@import\s+"bootstrap/mixins";)}, "\\1\n@import \"patternfly/mixin_overrides\";")
147
+ end
314
148
 
315
- # Override
316
- # bootstrap-sass uses this method to read in all Bootstrap's less source files
317
- # We're going to repurpose it.
318
- def bootstrap_less_files
319
- patternfly_less_files
320
- end
149
+ def remove_comments_and_whitespace(input)
150
+ input = replace_all(input, /\/\*.*?\*\//m, '')
151
+ input = replace_all(input, /\s*\/\/.*$/, '')
152
+ input.split("\n").reject { |line| line == "" }.join("\n").concat("\n")
153
+ end
321
154
 
322
- def patternfly_less_files
323
- get_paths_by_type('less', /\.less$/)
324
- end
155
+ def process_stylesheets
156
+ save_to = File.join(@destination, 'stylesheets', 'patternfly')
157
+ FileUtils.mkdir_p(save_to) unless File.exist?(save_to)
325
158
 
326
- def load_shared
327
- mixin_hash = {
328
- BOOTSTRAP_LESS_ROOT => Dir["#{BOOTSTRAP_LESS_ROOT}/**/*.*"].select { |f| f =~ /mixins(\/)|(\.less)/ }.map { |f| File.read(f) }.join("\n"),
329
- PATTERNFLY_LESS_ROOT => read_files(get_paths_by_type(PATTERNFLY_LESS_ROOT, /mixins(\/)|(\.less)/)).values.join("\n")
330
- }
331
- @shared_mixins ||= begin
332
- read_mixins(mixin_hash.values.join("\n"), :nested => NESTED_MIXINS)
159
+ patternfly_less_files.each do |path|
160
+ file = File.basename(path)
161
+ less = File.read(path)
162
+ output = File.join(save_to, "_#{file.sub(/\.less$/, '.scss')}")
163
+ File.open(output, 'w') do |f|
164
+ f.write(less_to_sass(file, less))
333
165
  end
334
166
  end
335
167
 
336
- def store_version
337
- path = 'lib/patternfly-sass/version.rb'
338
- content = File.read(path).sub(/PATTERNFLY_SHA\s*=\s*['"][\w]+['"]/, "PATTERNFLY_SHA = '#@branch_sha'")
339
- File.open(path, 'w') { |f| f.write(content) }
168
+ File.open(File.join(save_to, '..', '_patternfly.scss'), 'w') do |f|
169
+ f.write(generate_top_level)
340
170
  end
171
+ end
341
172
 
342
- protected
343
-
344
- # Override
345
- def get_trees(*args)
346
- root = get_tree(@branch_sha)['sha']
347
- @tree_paths = {}
348
- args.each do |dir|
349
- path_components = dir.split('/')
350
- dir_sha = path_components.inject(root) do |tree_sha, component|
351
- tree_sha = get_tree_sha(component, get_tree(tree_sha))
352
- end
353
- hash_list = []
354
- descend_tree(get_tree(dir_sha), dir, hash_list)
355
- dir_hash = hash_list.inject({}) do |memo, hash|
356
- memo.merge(hash)
357
- end
358
- @tree_paths.merge!(dir_hash)
359
- end
360
- @trees ||= @tree_paths.values
361
- end
173
+ def generate_top_level
174
+ less_to_sass('patternfly.less', top_level_files.map { |f| File.read(f) }.join("\n"))
175
+ end
362
176
 
363
- def descend_tree(tree, path, list)
364
- list << {path => tree}
365
- tree['tree'].map do |f|
366
- if f['type'] == 'tree'
367
- descend_tree(get_tree(f['sha']), File.join(path, f['path']), list)
368
- end
177
+ def copy_non_less
178
+ copy_config.each do |asset|
179
+ FileUtils.rm_rf(asset[:destination])
180
+ retrieve_files(asset[:source], asset[:select], asset[:reject]).each do |f|
181
+ copy_with_path(f, asset[:source], asset[:destination])
369
182
  end
370
183
  end
184
+ end
371
185
 
372
- # Override
373
- def get_paths_by_type(base_dir, regex)
374
- paths = get_paths_by_directory(base_dir)
186
+ def retrieve_files(folder, select=/.*/, reject=nil)
187
+ Dir["#{folder}/**/*"].reject { |f| File.directory?(f) || f !~ select || f =~ reject }
188
+ end
375
189
 
376
- # See http://stackoverflow.com/a/2698531 and http://stackoverflow.com/a/2552946
377
- matches = Hash.new do |h, key|
378
- h[key] = Array.new
379
- end
190
+ def copy_with_path(file, src, dst)
191
+ dst = file.sub(/^#{src}/, dst)
192
+ dir = File.dirname(dst)
193
+ FileUtils.mkdir_p(dir) unless File.exist?(dir)
194
+ FileUtils.cp(file, dst)
195
+ end
380
196
 
381
- paths.each do |dir, files|
382
- files.each do |f|
383
- matches[dir] << f if File.join(dir, f) =~ regex
384
- end
385
- end
386
- matches
197
+ def checkout_upstream
198
+ unless Dir.exist?(@source)
199
+ repo = Rugged::Repository.clone_at("https://github.com/#{@repository}.git", @source)
387
200
  end
201
+ repo ||= Rugged::Repository.new(@source)
202
+ repo.checkout(@branch)
203
+ @sha = repo.last_commit.oid
204
+
205
+ FileUtils.cp( # Mixins correction
206
+ File.join(@source, 'less', 'mixins.less'),
207
+ File.join(@source, 'less', 'mixin_overrides.less')
208
+ )
209
+ end
388
210
 
389
- def get_paths_by_directory(dir)
390
- tree = @tree_paths[dir]
391
- if tree.nil?
392
- log_status("#{dir} not found in Git tree.")
393
- return []
394
- end
211
+ def replace_escaping(less)
212
+ less = less.gsub(/~"([^"]+)"/, '#{\1}')
213
+ less.gsub!(/\$\{([\w\-]+)\}/, '#{$\1}')
214
+ less.gsub!(/\$\{([^}]+)\}/, '$\1')
215
+ less.gsub(/(\W)e\(%\("?([^"]*)"?\)\)/, '\1\2')
216
+ end
395
217
 
396
- files = {}
397
- files[dir] = []
398
- tree['tree'].map do |f|
399
- case f['type']
400
- when 'blob'
401
- files[dir] << f['path']
402
- when 'tree'
403
- loc = File.join(dir, f['path'])
404
- files.merge!(get_paths_by_directory(loc))
405
- end
406
- end
407
- files
218
+ def less_to_sass(file, input)
219
+ transforms = TRANSFORMATIONS.dup
220
+ case file
221
+ when 'fonts.less', 'icons.less'
222
+ transforms << :fix_font_paths
223
+ when 'mixins.less',
224
+ transforms << :flatten_mixins
225
+ transforms << :fix_dropdown_toggle
226
+ when 'mixin_overrides.less'
227
+ transforms.unshift(:remove_button_variant)
228
+ transforms << :flatten_mixins
229
+ when 'variables.less'
230
+ transforms.delete(:replace_spin)
231
+ transforms << :insert_default_vars
232
+ when 'patternfly.less'
233
+ transforms.delete(:replace_spin)
234
+ transforms << :fix_top_level
235
+ when 'bootstrap-touchspin.less', 'spinner.less'
236
+ transforms.delete(:replace_spin)
408
237
  end
409
238
 
410
- def get_tree(sha)
411
- get_json("https://api.github.com/repos/#@repo/git/trees/#{sha}")
412
- end
239
+ transforms.inject(input) { |a, e| send(e, a) }
240
+ end
413
241
 
414
- def get_tree_sha(dir, tree=get_trees)
415
- tree['tree'].find { |t| t['path'] == dir }['sha']
416
- end
242
+ def copy_config
243
+ [
244
+ {
245
+ :source => File.join(@source, 'dist', 'img'),
246
+ :select => /\.(png|gif|jpe?g|svg|ico)$/,
247
+ :reject => nil,
248
+ :destination => File.join(@destination, 'images', 'patternfly')
249
+ },
250
+ {
251
+ :source => File.join(@source, 'dist', 'fonts'),
252
+ :select => /\.(eot|svg|ttf|woff2?)$/,
253
+ :reject => nil,
254
+ :destination => File.join(@destination, 'fonts', 'patternfly')
255
+ },
256
+ {
257
+ :source => File.join(@source, 'dist', 'js'),
258
+ :select => /\.js$/,
259
+ :reject => nil,
260
+ :destination => File.join(@destination, 'javascripts')
261
+ },
262
+ {
263
+ :source => File.join(@source, 'tests'),
264
+ :select => /.*/,
265
+ :reject => nil,
266
+ :destination => TEST_DIR
267
+ },
268
+ {
269
+ :source => File.join(@source, 'dist', 'css'),
270
+ :select => /css/,
271
+ :reject => /styles(-additions)?(\.min)?\.css/,
272
+ :destination => File.join(TEST_DIR, 'dist', 'css')
273
+ }
274
+ ]
275
+ end
417
276
 
418
- # Override
419
- def read_files(files)
420
- contents = {}
421
- files.each do |dir, file|
422
- dir_contents = super(dir, file)
423
- full_path_contents = Hash[
424
- dir_contents.map do |k, v|
425
- [File.join(dir, k), v]
426
- end
427
- ]
428
- contents.merge!(full_path_contents)
429
- end
430
- contents
431
- end
277
+ def patternfly_less_files
278
+ retrieve_files(File.join(@source, 'less'), /\.less$/, /lib|patternfly/)
279
+ end
432
280
 
433
- # Override
434
- def get_branch_sha
435
- @branch_sha ||= begin
436
- cmd = "git ls-remote #{Shellwords.escape "https://github.com/#@repo"} #@branch"
437
- log cmd
438
- result = %x[#{cmd}]
439
- raise 'Could not get branch sha!' unless $?.success? && !result.empty?
440
- result.split(/\s+/).first
441
- end
442
- end
281
+ def top_level_files
282
+ retrieve_files(File.join(@source, 'less'), /patternfly(\-additions)?\.less$/)
443
283
  end
284
+
285
+ def store_version
286
+ path = 'lib/patternfly-sass/version.rb'
287
+ content = File.read(path).sub(/PATTERNFLY_SHA\s*=\s*['"][\w]+['"]/, "PATTERNFLY_SHA = '#{@sha}'")
288
+ File.open(path, 'w') { |f| f.write(content) }
289
+ end
290
+
291
+ def log_transform(*_opts)
292
+ end
293
+
294
+ def log_file_info(*_opts)
295
+ end
296
+
297
+ alias_method :bootstrap_less_files, :patternfly_less_files
444
298
  end