patternfly-sass 2.9.0 → 2.10.0

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 (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