voog-kit 0.2.3 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 36f989cd5ef93ad83de52a35f6529bc233f186e1
4
- data.tar.gz: 98924d5947e7ceca25172f763aed37e5de5cebce
3
+ metadata.gz: 6a2272da9fd83bf225e3f78ae2b1cab6efb6823f
4
+ data.tar.gz: f070ed157d1e875e409e47887d86b15acaa43111
5
5
  SHA512:
6
- metadata.gz: 2a36764dfa04dc9d3df2ab23483a0928fb0c93891c15b3083f2a2f357f4684e5f23086423c43a849417574d0c7bb37f361025c548f3881f86c96948603faac8b
7
- data.tar.gz: b1dadd5e5a7ea43b7a43f2c53245ad33488b44c1766724fa04ca07eaf74ea1b0ec4be369fbaa9277a502775fe9b3e1be262efd62830858b9db1a4b2c62b34740
6
+ metadata.gz: b9fe5dd1a8b2871e254bf1b2550d1d11a6e9d6a6a18706f93ae2ff316dc89b18c5cd73add73c90ec77152e2aa06e5040cb4783d9d04cd5f6ba3f4ca5558a0b7f
7
+ data.tar.gz: efdcffbc79f82d2f38a2f19888d749b15a16ba34e19ad0d6bb3ff002f84ceb7e0c8fbbfed4bbba3f27225d94b6c07c76ff25ddd19131c9b686bf7a344d46d934
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ guard :rspec, cmd: 'bundle exec rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/voog/dtk/(.+)\.rb$}) { |m| puts m.inspect;"spec/models/dtk/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { 'spec' }
5
+ end
6
+
data/README.markdown CHANGED
@@ -107,6 +107,7 @@ same as before. To stop watching, just type "exit" or press Ctrl+D.
107
107
  * `check` - Cross-checks the generated manifest to your local files to see if anything is missing
108
108
  * `pull` - Fetches the layout and layout asset files for the given site
109
109
  * `push` - Synchronizes your local changes with Voog
110
+ * `remove` - Removes both local and remote files
110
111
  * `watch` - Watches for file changes in the current directory
111
112
  * `help` - Shows a list of commands or help for one command
112
113
 
@@ -159,6 +160,11 @@ and the *MainMenu* component.
159
160
  site, overwriting existing files. Although `pull` searches by filename, `push` arguments need to be local file paths.
160
161
  For example, `kit push images/shadow.png layouts/mainmenu.tpl` works, `kit push shadow.png MainMenu` does not.
161
162
 
163
+ ### remove
164
+ `kit remove` first checks if the provided filename is valid, then removes it from the manifest. After that it deletes
165
+ the local file and sends an API request to delete the remote file as well. The directory name must be included in the
166
+ file name, e.g **assets/icon.svg** is valid, but **assets/** or **search.svg** is not.
167
+
162
168
  ### watch
163
169
 
164
170
  This command starts a watcher that monitors the current folder and its subfolders and triggers `kit push` every time
data/bin/kit CHANGED
@@ -55,11 +55,15 @@ command :init do |c|
55
55
  c.flag *hostname_args
56
56
  c.flag *api_token_args
57
57
  c.flag *site_args
58
+
59
+ c.desc 'Initializes the local project folder with remote layout files'
58
60
  c.action do |global_options, options, args|
59
61
  @filemanager.create_folders
60
62
  @filemanager.create_files
63
+ @filemanager.generate_remote_manifest
61
64
  end
62
65
 
66
+ c.desc 'Creates empty folders for a new project'
63
67
  c.command :empty do |e|
64
68
  e.action do |e|
65
69
  Voog::Dtk.write_config('','',false)
@@ -67,9 +71,14 @@ command :init do |c|
67
71
  end
68
72
  end
69
73
 
74
+ c.desc 'Initializes the local project folder with boilerplate files and folders'
70
75
  c.command :new do |n|
71
- n.action do |n|
72
- @filemanager.fetch_boilerplate
76
+ n.action do |global_options, options, args|
77
+ if args.size
78
+ @filemanager.clone_design args.first
79
+ else
80
+ @filemanager.clone_design
81
+ end
73
82
  end
74
83
  end
75
84
  end
@@ -133,7 +142,7 @@ command :push do |c|
133
142
  end
134
143
 
135
144
  desc 'Removes a specific file and syncs it with the remote site'
136
- long_desc 'This command removes a local file, removes it from the manifest and sends a deleted
145
+ long_desc 'This command removes a local file, removes it from the manifest and sends a delete
137
146
  request to remove it from the remote site as well.'
138
147
  command :remove do |c|
139
148
  c.switch *debug_args
@@ -147,6 +156,21 @@ command :remove do |c|
147
156
  end
148
157
  end
149
158
 
159
+ desc 'Adds a specific file to the manifest and syncs it with the remote site'
160
+ long_desc 'This command creates a new file, adds it to the manifest and creates
161
+ a new file on the remote site as well.'
162
+ command :add do |c|
163
+ c.switch *debug_args
164
+ c.switch *verbose_args
165
+ c.switch *silent_args
166
+ c.flag *hostname_args
167
+ c.flag *api_token_args
168
+ c.flag *site_args
169
+ c.action do |global_options, options, args|
170
+ @filemanager.add_files args
171
+ end
172
+ end
173
+
150
174
  desc "Generates a manifest.json file from the site's layout and asset files."
151
175
  long_desc "This looks through the current directory's subdirectories and files
152
176
  within them to compile a 'manifest.json' file. This is used for keeping
@@ -178,11 +202,29 @@ command :manifest do |c|
178
202
  end
179
203
  end
180
204
 
205
+ desc "Displays a list of all known sites that are defined in .voog files"
206
+ long_desc "The 'sites' command displays a list of all sites that are defined in
207
+ .voog files, either in the local project folder, or in the user's hostname
208
+ folder. Local sites are preferred over global ones."
209
+ command :sites do |c|
210
+ c.switch *debug_args
211
+ c.switch *verbose_args
212
+ c.switch *silent_args
213
+ c.switch *overwrite_args
214
+ c.flag *hostname_args
215
+ c.flag *api_token_args
216
+ c.flag *site_args
217
+ c.action do |global_options, options, args|
218
+ @filemanager.display_sites(Voog::Dtk.read_config(:all))
219
+ end
220
+ end
221
+
181
222
  desc 'Watches for file changes and pushes them automatically'
182
223
  long_desc "This starts watching the current folder and its subfolders for file
183
224
  changes and tries to push them to the remote site. When new files are
184
225
  added or old ones removed, it also adds or removes them from the manifest
185
- file, respectively. You can exit by pressing Ctrl+D or typing 'q' or 'exit'."
226
+ file, respectively. When local files are deleted, their remote counterparts
227
+ are also deleted. You can exit by pressing Ctrl+D or typing 'q' or 'exit'."
186
228
  command :watch do |c|
187
229
  c.switch *debug_args
188
230
  c.switch *verbose_args
@@ -8,6 +8,9 @@ require 'mime/types'
8
8
  module Voog::Dtk
9
9
  class FileManager
10
10
  attr_accessor :notifier
11
+
12
+ BOILERPLATE_URL = 'git@github.com:Edicy/design-boilerplate.git'
13
+
11
14
  def initialize(client, opts = {})
12
15
  @client = client
13
16
  @silent = opts.fetch(:silent, false)
@@ -18,35 +21,79 @@ module Voog::Dtk
18
21
  end
19
22
 
20
23
  def read_manifest
21
- JSON.parse(File.read('manifest.json', :encoding => 'UTF-8')).to_h
24
+ JSON.parse(File.read('manifest.json', encoding: 'UTF-8')).to_h
22
25
  end
23
26
 
24
27
  def write_manifest(manifest)
25
- File.open('manifest.json', 'w+', :encoding => 'UTF-8') do |file|
28
+ File.open('manifest.json', 'w+', encoding: 'UTF-8') do |file|
26
29
  file << JSON.pretty_generate(manifest)
27
30
  end
28
31
  end
29
32
 
30
- def in_manifest?(file, manifest=nil)
33
+ def in_manifest?(file, manifest = nil)
31
34
  @manifest = manifest || read_manifest
32
- filenames = @manifest['layouts'].map{|l| l.fetch('file', '')}
33
- filenames += @manifest['assets'].map{|a| a.fetch('filename', '')}
35
+ filenames = @manifest['layouts'].map { |l| l.fetch('file', '') }
36
+ filenames += @manifest['assets'].map { |a| a.fetch('filename', '') }
34
37
  filenames.include? file
35
38
  end
36
39
 
40
+ def valid_for_folder?(filename, folder)
41
+ return false unless (filename && folder)
42
+
43
+ # discard dotfiles
44
+ return false if filename.match(/\A[\.]{1}.+\z/)
45
+
46
+ mimetype = MIME::Types.of(filename).first
47
+ media_type = mimetype.media_type if mimetype
48
+ sub_type = mimetype.sub_type if mimetype
49
+
50
+ case folder
51
+ when 'images'
52
+ # SVG files are assets, not images
53
+ (media_type == 'image') && (sub_type != 'svg+xml')
54
+ when 'javascripts'
55
+ # Allow only pure JS files
56
+ (media_type == 'application') && (sub_type == 'javascript')
57
+ when 'stylesheets'
58
+ # Only pure CSS files, not SCSS/LESS etc.
59
+ (media_type == 'text') && (sub_type == 'css')
60
+ when 'layouts'
61
+ # Allow only files with .tpl extension
62
+ /\A[^\.]+\.tpl\z/.match(filename) && true
63
+ when 'components'
64
+ # Allow only files with .tpl extension
65
+ /\A[^\.]+\.tpl\z/.match(filename) && true
66
+ else
67
+ true
68
+ end
69
+ end
70
+
37
71
  def add_to_manifest(files = nil)
38
72
  return if files.nil?
39
73
  @manifest = read_manifest
74
+
75
+ new_layouts = []
76
+ new_assets = []
77
+
40
78
  files = (files.is_a? String) ? [files] : files
41
79
  files.uniq.each do |file|
42
80
  next if in_manifest?(file, @manifest)
81
+
43
82
  match = /^(component|layout|image|javascript|asset|stylesheet)s\/(.*)/.match(file)
44
83
  next if match.nil?
84
+
45
85
  type, filename = match[1], match[2]
86
+
87
+ unless valid_for_folder?(filename, "#{type}s")
88
+ @notifier.error "Invalid filename '#{filename}' for '#{type}s' folder. Skipping.\n"
89
+ next
90
+ end
91
+
46
92
  if %w(component layout).include? type
47
93
  component = type == 'component'
48
94
  name = filename.split('.').first
49
95
  title = component ? name : name.gsub('_', ' ').capitalize
96
+
50
97
  layout = {
51
98
  'title' => component ? name : title,
52
99
  'layout_name' => name,
@@ -54,7 +101,8 @@ module Voog::Dtk
54
101
  'component' => component,
55
102
  'file' => file
56
103
  }
57
- @manifest['layouts'] << layout
104
+
105
+ new_layouts << layout
58
106
  elsif %w(image javascript asset stylesheet).include? type
59
107
  asset = {
60
108
  'content_type' => begin
@@ -66,13 +114,21 @@ module Voog::Dtk
66
114
  'file' => file,
67
115
  'filename' => filename
68
116
  }
69
- @manifest['assets'] << asset
117
+
118
+ new_assets << asset
70
119
  end
71
- @notifier.newline
120
+
72
121
  @notifier.info "Added #{file} to manifest.json"
122
+ @notifier.newline
73
123
  end
124
+
125
+ new_layouts.map { |l| @manifest['layouts'] << l }
126
+ new_assets.map { |a| @manifest['assets'] << a }
127
+
74
128
  write_manifest @manifest
75
- @notifier.newline
129
+
130
+ # returns all successfully added files
131
+ new_layouts + new_assets
76
132
  end
77
133
 
78
134
  def remove_from_manifest(files = nil)
@@ -102,11 +158,11 @@ module Voog::Dtk
102
158
  end
103
159
 
104
160
  def get_layouts
105
- @client.layouts(per_page: 10000)
161
+ @client.layouts(per_page: 10_000)
106
162
  end
107
163
 
108
164
  def get_layout_assets
109
- @client.layout_assets(per_page: 10000)
165
+ @client.layout_assets(per_page: 10_000)
110
166
  end
111
167
 
112
168
  def get_layout(id)
@@ -163,53 +219,53 @@ module Voog::Dtk
163
219
  end
164
220
  end
165
221
 
166
- def generate_local_manifest(verbose=false, silent=false)
167
- unless %w(layouts components).map { |f| Dir.exists? f }.all?
168
- @notifier.error 'Cannot find any local layout files! (See `kit help init`)'
222
+ def generate_local_manifest(verbose = false, silent=false)
223
+ unless %w(layouts components).map { |f| Dir.exist? f }.all?
224
+ @notifier.error 'Missing local layout folders! (See `kit help init`)'
169
225
  return false
170
226
  end
171
227
 
172
228
  begin
173
- @old_manifest = JSON.parse(File.read('manifest.json', :encoding => 'UTF-8')).to_h if File.exists? 'manifest.json'
174
- rescue JSON::ParserError => e
175
- @notifier.error "Invalid JSON in current manifest file!"
229
+ @old_manifest = JSON.parse(File.read('manifest.json', encoding: 'UTF-8')).to_h if File.exist? 'manifest.json'
230
+ rescue JSON::ParserError
231
+ @notifier.error 'Invalid JSON in current manifest file!'
176
232
  @notifier.newline
177
233
  end
178
234
 
179
235
  @notifier.info 'Reading local files...'
180
236
  layouts_dir = Dir.new('layouts')
181
237
  layouts = layouts_dir.entries.select do |file|
182
- file =~ /(.*)\.tpl/
238
+ (file =~ /(.*)\.tpl/ && !File.directory?(File.join(layouts_dir, file)))
183
239
  end
184
240
  layouts = layouts.map do |l|
185
241
  attrs = {
186
- "content_type" => "page",
187
- "component" => false,
188
- "file" => "layouts/#{l}",
189
- "layout_name" => "page_default",
190
- "title" => l.split(".").first.gsub('_', " ").capitalize
242
+ 'content_type' => 'page',
243
+ 'component' => false,
244
+ 'file' => "layouts/#{l}",
245
+ 'layout_name' => 'page_default',
246
+ 'title' => l.split('.').first.gsub('_', ' ').capitalize
191
247
  }
192
248
  if @old_manifest && @old_manifest.fetch('layouts')
193
- old_layout = @old_manifest.fetch('layouts').reject(&:nil?).select { |ol| ol.fetch('file').include? l}.first || {}
249
+ old_layout = @old_manifest.fetch('layouts').reject(&:nil?).select { |ol| ol.fetch('file').include? l }.first || {}
194
250
  attrs.merge! old_layout
195
251
  end
196
252
  attrs
197
253
  end
198
254
  components_dir = Dir.new('components')
199
255
  components = components_dir.entries.select do |file|
200
- file =~/(.*)\.tpl/
256
+ (file =~ /(.*)\.tpl/ && !File.directory?(File.join(components_dir, file)))
201
257
  end
202
258
  components = components.map do |c|
203
- name = c.split(".").first.gsub('_', ' ')
259
+ name = c.split('.').first.gsub('_', ' ')
204
260
  attrs = {
205
- "content_type" => "component",
206
- "component" => true,
207
- "file" => "components/#{c}",
208
- "layout_name" => name,
209
- "title" => name
261
+ 'content_type' => 'component',
262
+ 'component' => true,
263
+ 'file' => "components/#{c}",
264
+ 'layout_name' => name,
265
+ 'title' => name
210
266
  }
211
267
  if @old_manifest && @old_manifest.fetch('layouts')
212
- old_component = @old_manifest.fetch('layouts').reject(&:nil?).select { |ol| ol.fetch('file').include? c}.first || {}
268
+ old_component = @old_manifest.fetch('layouts').reject(&:nil?).select { |ol| ol.fetch('file').include? c }.first || {}
213
269
  attrs.merge! old_component
214
270
  end
215
271
  attrs
@@ -217,38 +273,39 @@ module Voog::Dtk
217
273
  assets = []
218
274
  asset_dirs = %w(assets images javascripts stylesheets)
219
275
  asset_dirs.each do |dir|
220
- next unless Dir.exists? dir
276
+ next unless Dir.exist? dir
221
277
  current_dir = Dir.new(dir)
222
278
  current_dir.entries.each do |file|
223
- next if file =~ /^\.\.?$/
279
+ next if File.directory?(File.join(current_dir, file))
224
280
  attrs = {
225
- "content_type" => begin
281
+ 'content_type' => begin
226
282
  MIME::Types.type_for(file).first.content_type
227
283
  rescue
228
284
  'text/unknown'
229
285
  end,
230
- "file" => "#{dir}/#{file}",
231
- "kind" => dir,
232
- "filename" => file
286
+ 'file' => "#{dir}/#{file}",
287
+ 'kind' => dir,
288
+ 'filename' => file
233
289
  }
234
290
  if @old_manifest && @old_manifest.fetch('assets')
235
- old_asset = @old_manifest.fetch('assets').reject(&:nil?).select { |ol| ol.fetch('file').include? file}.first || {}
291
+ old_asset = @old_manifest.fetch('assets').reject(&:nil?).select { |ol| ol.fetch('file').include? file }.first || {}
236
292
  attrs.merge! old_asset
237
293
  end
238
294
  assets << attrs
239
295
  end
240
296
  end
297
+
241
298
  manifest = {
242
- "description" => "New design",
243
- "name" => "New design",
244
- "preview_medium" => "",
245
- "preview_small" => "",
246
- "author" => "",
247
- "layouts" => layouts + components,
248
- "assets" => assets
299
+ 'description' => "New design",
300
+ 'name' => "New design",
301
+ 'preview_medium' => "",
302
+ 'preview_small' => "",
303
+ 'author' => "",
304
+ 'layouts' => sort_layouts_by_content_type(layouts + components),
305
+ 'assets' => assets
249
306
  }
250
307
  if @old_manifest
251
- old_meta = @old_manifest.tap{ |m| m.delete("assets") }.tap{ |m| m.delete("layouts") }
308
+ old_meta = @old_manifest.tap{ |m| m.delete('assets') }.tap{ |m| m.delete('layouts') }
252
309
  manifest.merge! old_meta
253
310
  end
254
311
  @notifier.newline
@@ -256,18 +313,35 @@ module Voog::Dtk
256
313
  write_manifest(manifest)
257
314
  @notifier.success 'Done!'
258
315
  @notifier.newline
259
- return true
316
+ true
260
317
  end
261
318
 
262
319
  def generate_remote_manifest
263
320
  generate_manifest get_layouts, get_layout_assets
264
321
  end
265
322
 
323
+ def sort_layouts_by_content_type(layouts)
324
+ # make sure that 'blog' is before 'blog_article' and 'elements' is before 'element'
325
+ preferred_order = %w(page blog blog_article elements element error_401 error_404 photoset component)
326
+
327
+ layouts.sort do |a, b|
328
+ preferred_order.index(a.fetch('content_type')) <=> preferred_order.index(b.fetch('content_type'))
329
+ end
330
+ end
331
+
266
332
  def generate_manifest(layouts = nil, layout_assets = nil)
267
- layouts = layouts || get_layouts
268
- layout_assets = layout_assets || get_layout_assets
333
+ layouts ||= get_layouts
334
+ layout_assets ||= get_layout_assets
269
335
 
270
- unless (layouts && layout_assets && !layouts.empty? && !layout_assets.empty?)
336
+ # type->folder map for layout assets
337
+ asset_folders = {
338
+ 'asset' => 'assets',
339
+ 'javascript' => 'javascripts',
340
+ 'stylesheet' => 'stylesheets',
341
+ 'image' => 'images'
342
+ }
343
+
344
+ if (layouts.empty? && layout_assets.empty?)
271
345
  @notifier.error 'No remote layouts found to generate manifest from!'
272
346
  @notifier.newline
273
347
  return false
@@ -280,7 +354,9 @@ module Voog::Dtk
280
354
  end
281
355
 
282
356
  @notifier.info 'Writing remote layouts to new manifest.json file...'
283
- manifest = Hash.new
357
+
358
+ manifest = {}
359
+
284
360
  manifest[:layouts] = layouts.inject(Array.new) do |memo, l|
285
361
  memo << {
286
362
  title: l.title,
@@ -291,14 +367,16 @@ module Voog::Dtk
291
367
  }
292
368
  end
293
369
 
370
+ manifest[:layouts] = sort_layouts_by_content_type(manifest[:layouts])
371
+
294
372
  manifest[:assets] = layout_assets.inject(Array.new) do |memo, a|
295
- folder = if %w(unknown font).include? a.asset_type
296
- "assets"
297
- else
298
- "#{a.asset_type}s"
299
- end
373
+
374
+ # kind is same as asset_type for kinds that are represented in the asset_folders hash, defaults to 'asset'
375
+ kind = asset_folders.key?(kind.to_s) ? a.asset_type : 'asset'
376
+ folder = asset_folders.fetch(kind, 'assets')
377
+
300
378
  memo << {
301
- kind: a.asset_type,
379
+ kind: kind,
302
380
  filename: a.filename,
303
381
  file: "#{folder}/#{a.filename}",
304
382
  content_type: a.content_type
@@ -314,7 +392,7 @@ module Voog::Dtk
314
392
  @notifier.newline
315
393
  @notifier.info 'Creating folder structure...'
316
394
  folders = %w(stylesheets images assets javascripts components layouts)
317
- folders.each { |folder| Dir.mkdir(folder) unless Dir.exists?(folder) }
395
+ folders.each { |folder| Dir.mkdir(folder) unless Dir.exist?(folder) }
318
396
  @notifier.success 'Done!'
319
397
  @notifier.newline
320
398
  end
@@ -353,12 +431,12 @@ module Voog::Dtk
353
431
  }
354
432
 
355
433
  if valid
356
- folder = folder_names.fetch(asset.asset_type, 'assets')
434
+ folder = folder_names.fetch(asset.asset_type, 'assets')
357
435
 
358
- Dir.mkdir(folder) unless Dir.exists?(folder)
436
+ Dir.mkdir(folder) unless Dir.exist?(folder)
359
437
  Dir.chdir(folder)
360
438
 
361
- overwritten = File.exists? asset.filename
439
+ overwritten = File.exist? asset.filename
362
440
 
363
441
  if @verbose
364
442
  @notifier.newline
@@ -382,9 +460,7 @@ module Voog::Dtk
382
460
  end
383
461
  Dir.chdir('..')
384
462
  else
385
- unless @verbose
386
- @notifier.error '!'
387
- end
463
+ @notifier.error '!' unless @verbose
388
464
  end
389
465
  end
390
466
 
@@ -408,7 +484,7 @@ module Voog::Dtk
408
484
  folder = layout.component ? 'components' : 'layouts'
409
485
  filename = "#{layout.title.gsub(/[^\w\.\-]/, '_').downcase}.tpl"
410
486
  Dir.chdir(folder)
411
- overwritten = File.exists? filename
487
+ overwritten = File.exist? filename
412
488
 
413
489
  if @verbose
414
490
  @notifier.newline
@@ -425,18 +501,16 @@ module Voog::Dtk
425
501
 
426
502
  Dir.chdir('..')
427
503
  else
428
- unless @verbose
429
- @notifier.error '!'
430
- end
504
+ @notifier.error '!' unless @verbose
431
505
  end
432
506
  end
433
507
 
434
508
  def check
435
- ok_char = "."
436
- not_ok_char = "!"
437
- @notifier.info "Checking manifest.json..."
509
+ ok_char = '.'
510
+ not_ok_char = '!'
511
+ @notifier.info 'Checking manifest.json...'
438
512
 
439
- if File.exists? 'manifest.json'
513
+ if File.exist? 'manifest.json'
440
514
  @manifest = read_manifest
441
515
  @notifier.success 'OK!'
442
516
  else
@@ -449,9 +523,9 @@ module Voog::Dtk
449
523
  missing_layouts = %w()
450
524
 
451
525
  @notifier.newline
452
- @notifier.info "Checking layouts and components"
526
+ @notifier.info 'Checking layouts and components'
453
527
  layouts.reject(&:nil?).each do |layout|
454
- if File.exists? layout['file']
528
+ if File.exist? layout['file']
455
529
  @notifier.success ok_char
456
530
  else
457
531
  missing_layouts << layout['file']
@@ -474,9 +548,9 @@ module Voog::Dtk
474
548
  missing_assets = %w()
475
549
 
476
550
  @notifier.newline
477
- @notifier.info "Checking assets"
551
+ @notifier.info 'Checking assets'
478
552
  assets.reject(&:nil?).each do |asset|
479
- if File.exists? asset['file']
553
+ if File.exist? asset['file']
480
554
  @notifier.success ok_char
481
555
  else
482
556
  missing_assets << asset['file']
@@ -495,29 +569,42 @@ module Voog::Dtk
495
569
  @notifier.success 'OK!'
496
570
  end
497
571
 
498
- return (missing_assets.count + missing_layouts.count == 0)
572
+ (missing_assets.count + missing_layouts.count == 0)
499
573
  end
500
574
 
501
- def fetch_boilerplate(dst='tmp')
502
- @notifier.info 'Fetching design boilerplate...'
503
- @notifier.newline
575
+ def clone_design(url = BOILERPLATE_URL, dst = 'tmp')
576
+ # Allow only design repositories from Edicy/Voog for now
577
+ pattern = /\Ahttps?:\/\/github.com\/(?:Voog|Edicy)\/design-(\w+)\.git\z/ # HTTPS clone URL
578
+ pattern2 = /\Agit@github.com:(?:Voog|Edicy)\/design-(\w+)\.git\z/ # SSH clone URL
579
+
580
+ match = url.match(pattern) || url.match(pattern2)
504
581
 
505
- FileUtils.rm_r 'tmp' if Dir.exists? 'tmp'
582
+ unless match.nil?
583
+ @notifier.info "Fetching the #{match[1].capitalize} design..."
584
+ @notifier.newline
585
+ else
586
+ # default to the boilerplate URL if given URL doesn't match the Regex pattern
587
+ @notifier.info 'Fetching design boilerplate...'
588
+ @notifier.newline
589
+ url = BOILERPLATE_URL
590
+ end
591
+
592
+ FileUtils.rm_r 'tmp' if Dir.exist? 'tmp'
506
593
 
507
594
  begin
508
- Git.clone 'git@github.com:Edicy/design-boilerplate.git', dst
595
+ Git.clone url, dst
509
596
  rescue
510
597
  @notifier.error 'An error occurred!'
511
598
  return false
512
599
  end
513
600
 
514
- if Dir.exists? 'tmp'
601
+ if Dir.exist? 'tmp'
515
602
  Dir.chdir 'tmp'
516
- @notifier.info 'Copying boilerplate files to working directory...'
603
+ @notifier.info 'Copying template files to working directory...'
517
604
  @notifier.newline
518
605
  Dir.new('.').entries.each do |f|
519
606
  unless f =~ /^\..*$/
520
- if Dir.exists?('../' + f) || File.exists?('../' + f)
607
+ if Dir.exist?('../' + f) || File.exist?('../' + f)
521
608
  FileUtils.rm_r '../' + f
522
609
  end
523
610
  FileUtils.mv f, '..'
@@ -528,11 +615,11 @@ module Voog::Dtk
528
615
  end
529
616
  @notifier.success 'Done!'
530
617
  @notifier.newline
531
- return true
618
+ true
532
619
  end
533
620
 
534
621
  # Returns filename=>id hash for layout files
535
- def layout_id_map(layouts=nil)
622
+ def layout_id_map(layouts = nil)
536
623
  layouts ||= get_layouts
537
624
  remote_layouts = layouts.inject(Hash.new) do |memo, l|
538
625
  memo[l.title.downcase] = l.id
@@ -540,11 +627,11 @@ module Voog::Dtk
540
627
  end
541
628
 
542
629
  @manifest = read_manifest
543
- fail "Manifest not found! (See `kit help push` for more info)".red unless @manifest
630
+ fail 'Manifest not found! (See `kit help push` for more info)'.red unless @manifest
544
631
  layouts = @manifest.fetch('layouts').reject(&:nil?)
545
632
  layouts.inject(Hash.new) do |memo, l|
546
- remote_exists = remote_layouts.key?(l.fetch('title').downcase)
547
- memo[l.fetch('file')] = remote_layouts.fetch(l.fetch('title').downcase, nil) if remote_exists
633
+ remote_exist = remote_layouts.key?(l.fetch('title').downcase)
634
+ memo[l.fetch('file')] = remote_layouts.fetch(l.fetch('title').downcase, nil) if remote_exist
548
635
  memo
549
636
  end
550
637
  end
@@ -570,9 +657,9 @@ module Voog::Dtk
570
657
  # Find if provided file is a directory instead
571
658
  files.each_with_index do |file, index|
572
659
  next if file.is_a? Array
573
- if Dir.exists? file
660
+ if Dir.exist? file
574
661
  subfiles = Dir.new(file).entries.reject{|e| e =~ /^(\.|\.\.)$/ } # Keep only normal subfiles
575
- subfiles.map!{ |subfile| subfile = "#{file[/[^\/]*/]}/#{subfile}"} # Prepend folder name
662
+ subfiles.map! { |subfile| subfile = "#{file[/[^\/]*/]}/#{subfile}" } # Prepend folder name
576
663
  files[index] = subfiles # Insert as Array so sub-subfolders won't get processed again
577
664
  end
578
665
  end
@@ -590,7 +677,7 @@ module Voog::Dtk
590
677
  if local_layouts.include?(file)
591
678
  if layouts.key?(file)
592
679
  @notifier.info "Updating layout file #{file}..."
593
- if update_layout(layouts[file], File.read(file, :encoding => 'UTF-8'))
680
+ if update_layout(layouts[file], File.read(file, encoding: 'UTF-8'))
594
681
  @notifier.success 'OK!'
595
682
  else
596
683
  @notifier.error "Cannot update layout file #{file}!"
@@ -612,7 +699,7 @@ module Voog::Dtk
612
699
  if layout_assets.key? file
613
700
  if is_editable?(file)
614
701
  @notifier.info "Updating layout asset file #{file}..."
615
- if update_layout_asset(layout_assets[file], File.read(file, :encoding => 'UTF-8'))
702
+ if update_layout_asset(layout_assets[file], File.read(file, encoding: 'UTF-8'))
616
703
  @notifier.success 'OK!'
617
704
  else
618
705
  @notifier.error "Unable to update file #{file}!"
@@ -641,7 +728,7 @@ module Voog::Dtk
641
728
  else
642
729
  @notifier.warning "Asset file #{file} not found in manifest! Skipping."
643
730
  end
644
- elsif Dir.exists? file
731
+ elsif Dir.exist? file
645
732
  @notifier.warning "Not allowed to push subfolder #{file}!"
646
733
  else
647
734
  @notifier.warning "Not allowed to push file #{file}!"
@@ -673,7 +760,7 @@ module Voog::Dtk
673
760
  end
674
761
  else
675
762
  if folder == 'images'
676
- "image/#{file.split("/").last.split(".").last}"
763
+ "image/#{file.split('/').last.split('.').last}"
677
764
  elsif folder == 'assets'
678
765
  'unknown/unknown'
679
766
  end
@@ -681,7 +768,7 @@ module Voog::Dtk
681
768
  end
682
769
 
683
770
  def create_remote_layout(file)
684
- @manifest = read_manifest if File.exists? 'manifest.json'
771
+ @manifest = read_manifest if File.exist? 'manifest.json'
685
772
  layouts = @manifest.fetch('layouts', []).reject(&:nil?)
686
773
  layout = layouts.select { |l| file == l.fetch('file') }.first
687
774
 
@@ -690,12 +777,12 @@ module Voog::Dtk
690
777
  title: layout.fetch('title'),
691
778
  content_type: layout.fetch('content_type'),
692
779
  component: layout.fetch('component'),
693
- body: File.exists?(layout.fetch('file')) ? File.read(layout.fetch('file'), :encoding => 'UTF-8') : ''
780
+ body: File.exist?(layout.fetch('file')) ? File.read(layout.fetch('file'), encoding: 'UTF-8') : ''
694
781
  }
695
782
  else
696
783
  name = file.split('/').last.split('.').first
697
784
  component = (file.split('/').first =~ /^layouts$/).nil?
698
- body = File.read(file, :encoding => 'UTF-8')
785
+ body = File.read(file, encoding: 'UTF-8')
699
786
  data = {
700
787
  title: component ? name : name.capitalize,
701
788
  content_type: 'page',
@@ -714,7 +801,7 @@ module Voog::Dtk
714
801
  }
715
802
 
716
803
  if is_editable?(file)
717
- data[:data] = File.read(file, :encoding => 'UTF-8')
804
+ data[:data] = File.read(file, encoding: 'UTF-8')
718
805
  else
719
806
  data[:file] = file
720
807
  end
@@ -724,43 +811,28 @@ module Voog::Dtk
724
811
 
725
812
  def is_asset?(filename)
726
813
  asset_folders = %w(assets images stylesheets javascripts)
727
- return File.file?(filename) && asset_folders.include?(filename.split('/').first)
814
+ asset_folders.include?(filename.split('/').first)
728
815
  end
729
816
 
730
817
  def is_layout?(filename)
731
818
  layout_folders = %w(components layouts)
732
- return File.file?(filename) && layout_folders.include?(filename.split('/').first)
819
+ layout_folders.include?(filename.split('/').first)
733
820
  end
734
821
 
735
822
  def remove_files(names)
736
- asset_ids = layout_asset_id_map
737
- layout_ids = layout_id_map
738
823
  names.each do |name|
739
- if is_asset? name
740
- remove_from_manifest(name)
741
- remove_local_file(name)
742
- id = asset_ids.fetch(name, nil)
743
- if id && delete_layout_asset(id)
744
- @notifier.info "Removed remote file #{name}." unless @silent
745
- else
746
- @notifier.error "Failed to remove remote file #{name}!" unless @silent
747
- end
748
- elsif is_layout? name
749
- remove_from_manifest(name)
750
- remove_local_file(name)
751
- id = layout_ids.fetch(name, nil)
752
- if id && delete_layout( id )
753
- @notifier.info "Removed remote file #{name}." unless @silent
754
- else
755
- @notifier.error "Failed to remove remote file #{name}!" unless @silent
756
- end
757
- else
758
- @notifier.error "Invalid filename: \"#{name}\""
759
- end
824
+ remove_local_file(name) if File.file?(name)
825
+ remove_remote_file(name)
826
+ remove_from_manifest(name)
760
827
  @notifier.newline
761
828
  end
762
829
  end
763
830
 
831
+ def add_files(names)
832
+ new_files = add_to_manifest names
833
+ upload_files new_files.map { |f| f.fetch('file') } unless new_files.empty?
834
+ end
835
+
764
836
  def remove_local_file(file)
765
837
  if File.exist?(file) && File.delete(file)
766
838
  @notifier.info "Removed local file #{file}." unless @silent
@@ -773,6 +845,40 @@ module Voog::Dtk
773
845
  end
774
846
  end
775
847
 
848
+ def remove_remote_file(file)
849
+ folder, filename = file.split('/')
850
+ return unless (folder && filename)
851
+
852
+ asset_ids = layout_asset_id_map
853
+ layout_ids = layout_id_map
854
+
855
+ if is_asset? file
856
+ id = asset_ids.fetch(file, nil)
857
+
858
+ unless id.nil?
859
+ if delete_layout_asset(id)
860
+ @notifier.info "Removed remote asset '#{filename}'." unless @silent
861
+ else
862
+ @notifier.error "Failed to remove remote asset '#{filename}'!" unless @silent
863
+ end
864
+ end
865
+ elsif is_layout? file
866
+ filename = filename.gsub('.tpl', '')
867
+ id = layout_ids.fetch(file, nil)
868
+
869
+ unless id.nil?
870
+ if delete_layout(id)
871
+ @notifier.info "Removed remote layout '#{filename}'." unless @silent
872
+ else
873
+ @notifier.error "Failed to remove remote layout '#{file}'!" unless @silent
874
+ end
875
+ end
876
+ else
877
+ @notifier.error "Invalid filename: '#{file}'"
878
+ end
879
+ @notifier.newline
880
+ end
881
+
776
882
  def uploadable?(file)
777
883
  if file.is_a? String
778
884
  !(file =~ /^(component|layout|image|asset|javascript|stylesheet)s\/([^\s]+)/).nil?
@@ -780,7 +886,7 @@ module Voog::Dtk
780
886
  begin
781
887
  uploadable? file.try(:to_s)
782
888
  rescue
783
- fail "Cannot upload file '#{file}'!".red
889
+ raise "Cannot upload file '#{file}'!".red
784
890
  end
785
891
  end
786
892
  end
@@ -795,9 +901,9 @@ module Voog::Dtk
795
901
  if @manifest
796
902
  layout = @manifest.fetch('layouts', []).reject(&:nil?).find{ |l| l['file'].split('/').last.split('.').first == name }
797
903
  if layout # layout file is in manifest
798
- layout = layouts.find{ |l| l.title == layout['title'] }
904
+ layout = layouts.find { |l| l.title == layout['title'] }
799
905
  else # not found in manifest
800
- layout = layouts.find{ |l| l.title == name }
906
+ layout = layouts.find { |l| l.title == name }
801
907
  end
802
908
  id = layout.id if layout
803
909
  else
@@ -828,13 +934,13 @@ module Voog::Dtk
828
934
 
829
935
  found = layout_ids.length + asset_ids.length
830
936
  if found > 0 && found < names.length
831
- @notifier.warning "Unable to find some specified files!"
937
+ @notifier.warning 'Unable to find some specified files!'
832
938
  @notifier.newline
833
939
  ret = true
834
940
  elsif found == names.length
835
941
  ret = true
836
942
  elsif found == 0
837
- @notifier.error "Unable to find any specified files!"
943
+ @notifier.error 'Unable to find any specified files!'
838
944
  ret = false
839
945
  end
840
946
 
@@ -843,5 +949,17 @@ module Voog::Dtk
843
949
 
844
950
  ret
845
951
  end
952
+ def display_sites(sites)
953
+ sites.each_with_index do |site, index|
954
+ @notifier.info "#{site.fetch(:name)} #{'(default)' if index == 0}"
955
+ if @verbose
956
+ @notifier.newline
957
+ @notifier.info " host: #{site.fetch(:host)}"
958
+ @notifier.newline
959
+ @notifier.info " token: #{site.fetch(:api_token)}"
960
+ end
961
+ @notifier.newline
962
+ end
963
+ end
846
964
  end
847
965
  end
@@ -97,8 +97,7 @@ module Voog::Dtk
97
97
  # @return [Object] the task result
98
98
  #
99
99
  def run_on_additions(paths)
100
- @filemanager.add_to_manifest paths
101
- @filemanager.upload_files paths
100
+ @filemanager.add_files paths
102
101
  rescue => e
103
102
  @filemanager.notifier.newline
104
103
  Voog::Dtk.handle_exception e, @debug, @filemanager.notifier
@@ -111,8 +110,7 @@ module Voog::Dtk
111
110
  # @return [Object] the task result
112
111
  #
113
112
  def run_on_removals(paths)
114
- @filemanager.remove_from_manifest paths
115
- # @filemanager.delete_remote_files paths
113
+ @filemanager.remove_files paths
116
114
  rescue => e
117
115
  @filemanager.notifier.newline
118
116
  Voog::Dtk.handle_exception e, @debug, @filemanager.notifier
@@ -1,5 +1,5 @@
1
1
  module Voog
2
2
  module Dtk
3
- VERSION = '0.2.3'
3
+ VERSION = '0.3'
4
4
  end
5
5
  end
data/lib/voog/dtk.rb CHANGED
@@ -25,11 +25,14 @@ module Voog
25
25
  local_config = config_exists?(file) ? ParseConfig.new(File.expand_path(file)).params : {}
26
26
  global_config = global_config_exists?(file) ? ParseConfig.new(File.expand_path([ENV['HOME'], file].join('/'))).params : {}
27
27
 
28
- options = global_config.merge(local_config)
28
+ options = local_config.merge(global_config)
29
29
 
30
30
  unless options.empty?
31
- @block = if block.nil?
31
+ @block = case block
32
+ when nil
32
33
  options.keys.first
34
+ when :all
35
+ options.keys
33
36
  else
34
37
  if options.key?(block)
35
38
  block
@@ -38,9 +41,20 @@ module Voog
38
41
  end
39
42
  end
40
43
 
41
- config[:host] = options[@block].fetch("host")
42
- config[:api_token] = options[@block].fetch("api_token")
43
- config[:overwrite] = options[@block].fetch("overwrite", false) == 'true' ? true : false
44
+ if @block.is_a?(Array) && @block.size
45
+ config = []
46
+ @block.each do |site|
47
+ config << {
48
+ name: site,
49
+ host: options[site].fetch('host'),
50
+ api_token: options[site].fetch('api_token')
51
+ }
52
+ end
53
+ else
54
+ config[:host] = options[@block].fetch("host")
55
+ config[:api_token] = options[@block].fetch("api_token")
56
+ config[:overwrite] = options[@block].fetch("overwrite", false) == 'true' ? true : false
57
+ end
44
58
  end
45
59
  config
46
60
  end
@@ -7,7 +7,7 @@ describe Voog::Dtk::FileManager do
7
7
  before :all do
8
8
  Dir.mkdir 'TEST'
9
9
  Dir.chdir 'TEST'
10
- @filemanager = Voog::Dtk::FileManager.new(nil, {silent: true, verbose: true, overwrite: false})
10
+ @filemanager = Voog::Dtk::FileManager.new(nil, {silent: false, verbose: true, overwrite: false})
11
11
  @dir = Dir.new('.')
12
12
  end
13
13
 
@@ -283,7 +283,7 @@ describe Voog::Dtk::FileManager do
283
283
  end
284
284
  end
285
285
 
286
- describe '#is_asset?', focus: true do
286
+ describe '#is_asset?' do
287
287
  before :all do
288
288
  @filemanager.create_folders
289
289
  @filemanager.create_asset get_layout_asset
@@ -302,7 +302,7 @@ describe Voog::Dtk::FileManager do
302
302
  end
303
303
  end
304
304
 
305
- describe '#is_layout?', focus: true do
305
+ describe '#is_layout?' do
306
306
  before :all do
307
307
  @filemanager.create_layout get_layout
308
308
  end
@@ -319,7 +319,7 @@ describe Voog::Dtk::FileManager do
319
319
  end
320
320
  end
321
321
 
322
- describe '#remove_local_file', focus: true do
322
+ describe '#remove_local_file' do
323
323
  before :each do
324
324
  @filemanager.create_asset get_layout_asset
325
325
  end
@@ -417,11 +417,11 @@ describe Voog::Dtk::FileManager do
417
417
  @manifest = File.open('manifest.json', 'w+') do |file|
418
418
  file << {
419
419
  'layouts' => [{
420
- "component" => false,
421
- "content_type" => "page",
422
- "file" => "layouts/front_page.tpl",
423
- "layout_name" => "page_front",
424
- "title" => "Front page"
420
+ 'component' => false,
421
+ 'content_type' => 'page',
422
+ 'file' => "layouts/front_page.tpl",
423
+ 'layout_name' => 'page_front',
424
+ 'title' => "Front page"
425
425
  }],
426
426
  'assets' => []
427
427
  }.to_json
@@ -527,7 +527,7 @@ describe Voog::Dtk::FileManager do
527
527
  end
528
528
  end
529
529
 
530
- describe '#fetch_boilerplate' do
530
+ describe '#clone_design' do
531
531
  context 'with no files in the working directory' do
532
532
  before :each do
533
533
  @prev_files = Dir['*']
@@ -540,7 +540,7 @@ describe Voog::Dtk::FileManager do
540
540
  end
541
541
 
542
542
  it 'downloads and copies the boilerplate files' do
543
- @filemanager.fetch_boilerplate
543
+ @filemanager.clone_design
544
544
  @files = Dir['*']
545
545
  expected_files = [
546
546
  'assets', 'images',
@@ -552,13 +552,13 @@ describe Voog::Dtk::FileManager do
552
552
  end
553
553
 
554
554
  it 'removes the \'tmp\' directory' do
555
- @filemanager.fetch_boilerplate
555
+ @filemanager.clone_design
556
556
  @files = Dir['*']
557
557
  expect(@files.include? 'tmp').to eq(false)
558
558
  end
559
559
 
560
560
  it 'returns true' do
561
- expect(@filemanager.fetch_boilerplate).to eq(true)
561
+ expect(@filemanager.clone_design).to eq(true)
562
562
  end
563
563
  end
564
564
 
@@ -569,7 +569,7 @@ describe Voog::Dtk::FileManager do
569
569
  File.open('manifest.json', 'w+') do |file| file << "[]" end
570
570
  @old_manifest = File.open('manifest.json')
571
571
  Dir.mkdir('test')
572
- @return_value = @filemanager.fetch_boilerplate
572
+ @return_value = @filemanager.clone_design
573
573
  @manifest = File.open('manifest.json')
574
574
  end
575
575
 
@@ -593,6 +593,42 @@ describe Voog::Dtk::FileManager do
593
593
  end
594
594
  end
595
595
 
596
+ describe '#valid_for_folder?' do
597
+ it 'returns true for valid folder+filename combinations' do
598
+ testfiles = {
599
+ 'stylesheets' => ['style.css', 'style.min.css'],
600
+ 'javascripts' => ['script.js', 'script.min.js'],
601
+ 'images' => ['image.jpg', 'image.png'],
602
+ 'assets' => ['icon.svg', 'text.txt'],
603
+ 'components' => ['menu.tpl'],
604
+ 'layouts' => ['front_page.tpl']
605
+ }
606
+
607
+ testfiles.each do |folder, files|
608
+ files.each do |filename|
609
+ expect(@filemanager.valid_for_folder? filename, folder).to be_true
610
+ end
611
+ end
612
+ end
613
+
614
+ it 'returns false for invalid folder+filename combinations' do
615
+ testfiles = {
616
+ 'stylesheets' => ['style.css.map', 'style.scss', 'style.less'],
617
+ 'javascripts' => ['script.js.map', 'script.coffee'],
618
+ 'images' => ['icon.svg'],
619
+ 'assets' => ['.gitignore'],
620
+ 'components' => ['test', 'style.css'],
621
+ 'layouts' => ['test', 'script.js']
622
+ }
623
+
624
+ testfiles.each do |folder, files|
625
+ files.each do |filename|
626
+ expect(@filemanager.valid_for_folder? filename, folder).to be_false
627
+ end
628
+ end
629
+ end
630
+ end
631
+
596
632
  after :all do
597
633
  Dir.chdir '..'
598
634
  FileUtils.rm_r 'TEST'
data/spec/spec_helper.rb CHANGED
@@ -3,7 +3,7 @@ require_relative '../lib/voog/dtk/filemanager.rb'
3
3
  require_relative '../lib/voog/dtk/notifier.rb'
4
4
 
5
5
  RSpec.configure do |c|
6
- c.filter_run focus: true
6
+ # c.filter_run focus: true
7
7
  end
8
8
 
9
9
  FIXTURE_PATH = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
data/voog-kit.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency 'bundler', '~> 1.3'
23
23
  spec.add_development_dependency 'rake'
24
24
  spec.add_development_dependency 'rspec'
25
+ spec.add_development_dependency 'guard-rspec'
25
26
 
26
27
  spec.add_runtime_dependency 'gli', '2.10.0'
27
28
  spec.add_runtime_dependency 'pry', '~> 0.9.12'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: voog-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: '0.3'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikk Pristavka
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-09-09 00:00:00.000000000 Z
12
+ date: 2015-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: guard-rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: gli
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -191,6 +205,7 @@ files:
191
205
  - ".gitignore"
192
206
  - ".rspec"
193
207
  - Gemfile
208
+ - Guardfile
194
209
  - LICENSE.txt
195
210
  - README.markdown
196
211
  - Rakefile