massimo 0.7.5 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.document +5 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +88 -0
  5. data/README.md +3 -1
  6. data/Rakefile +8 -0
  7. data/bin/massimo +1 -17
  8. data/lib/massimo/cli.rb +63 -0
  9. data/lib/massimo/config.rb +8 -5
  10. data/lib/massimo/javascript.rb +10 -2
  11. data/lib/massimo/reloader.rb +37 -0
  12. data/lib/massimo/site.rb +24 -21
  13. data/lib/massimo/templates/site/config.rb +18 -0
  14. data/lib/massimo/templates/site/javascripts/main.js +0 -0
  15. data/lib/massimo/templates/site/pages/index.erb +5 -0
  16. data/lib/massimo/templates/site/public/.empty_directory +0 -0
  17. data/lib/massimo/templates/site/stylesheets/main.scss +0 -0
  18. data/lib/massimo/templates/site/views/layouts/main.erb +12 -0
  19. data/lib/massimo/ui.rb +2 -2
  20. data/lib/massimo/version.rb +1 -1
  21. data/lib/massimo/watcher.rb +22 -7
  22. data/lib/massimo.rb +3 -11
  23. data/massimo.gemspec +40 -0
  24. data/spec/massimo/cli_spec.rb +254 -0
  25. data/spec/massimo/config_spec.rb +97 -0
  26. data/spec/massimo/helpers_spec.rb +26 -0
  27. data/spec/massimo/javascript_spec.rb +120 -0
  28. data/spec/massimo/massimo_spec.rb +23 -0
  29. data/spec/massimo/page_spec.rb +224 -0
  30. data/spec/massimo/reloader_spec.rb +135 -0
  31. data/spec/massimo/resource_spec.rb +208 -0
  32. data/spec/massimo/server_spec.rb +35 -0
  33. data/spec/massimo/site_spec.rb +299 -0
  34. data/spec/massimo/stylesheet_spec.rb +77 -0
  35. data/spec/massimo/ui_spec.rb +109 -0
  36. data/spec/massimo/view_spec.rb +46 -0
  37. data/spec/massimo/watcher_spec.rb +122 -0
  38. data/spec/spec_helper.rb +65 -0
  39. data/spec/support/matchers/be_a_directory_matcher.rb +5 -0
  40. data/spec/support/matchers/be_a_file_matcher.rb +26 -0
  41. metadata +74 -20
  42. data/lib/massimo/commands/base.rb +0 -85
  43. data/lib/massimo/commands/build.rb +0 -19
  44. data/lib/massimo/commands/generate.rb +0 -62
  45. data/lib/massimo/commands/help.rb +0 -34
  46. data/lib/massimo/commands/server.rb +0 -24
  47. data/lib/massimo/commands/version.rb +0 -9
  48. data/lib/massimo/commands/watch.rb +0 -16
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle
2
+ .rvmrc
3
+ .sass-cache
4
+ .yardoc
5
+ doc
6
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,88 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ massimo (0.7.5)
5
+ activesupport (~> 3.0.0)
6
+ i18n (~> 0.4.0)
7
+ rack (~> 1.2.0)
8
+ sinatra_more (~> 0.3.0)
9
+ thor (~> 0.14.0)
10
+ tilt (~> 1.2.0)
11
+ tzinfo (~> 0.3.0)
12
+
13
+ GEM
14
+ remote: http://rubygems.org/
15
+ specs:
16
+ activesupport (3.0.3)
17
+ closure-compiler (0.3.3)
18
+ coffee-script (0.3.2)
19
+ diff-lcs (1.1.2)
20
+ growl (1.0.3)
21
+ haml (3.0.25)
22
+ i18n (0.4.2)
23
+ jsmin (1.0.1)
24
+ less (1.2.21)
25
+ mutter (>= 0.4.2)
26
+ treetop (>= 1.4.2)
27
+ mutter (0.5.3)
28
+ oyster (0.9.4)
29
+ packr (3.1.0)
30
+ oyster
31
+ polyglot (0.3.1)
32
+ rack (1.2.1)
33
+ rack-test (0.5.7)
34
+ rack (>= 1.0)
35
+ rr (1.0.2)
36
+ rspec (2.4.0)
37
+ rspec-core (~> 2.4.0)
38
+ rspec-expectations (~> 2.4.0)
39
+ rspec-mocks (~> 2.4.0)
40
+ rspec-core (2.4.0)
41
+ rspec-expectations (2.4.0)
42
+ diff-lcs (~> 1.1.2)
43
+ rspec-mocks (2.4.0)
44
+ sinatra (1.1.2)
45
+ rack (~> 1.1)
46
+ tilt (~> 1.2)
47
+ sinatra_more (0.3.40)
48
+ activesupport (>= 2.2.2)
49
+ bundler (>= 0.9.2)
50
+ sinatra (>= 0.9.2)
51
+ thor (>= 0.11.8)
52
+ tilt (>= 0.2)
53
+ sprockets (1.0.2)
54
+ test-construct (1.2.0)
55
+ thor (0.14.6)
56
+ tilt (1.2.2)
57
+ treetop (1.4.9)
58
+ polyglot (>= 0.3.1)
59
+ tzinfo (0.3.24)
60
+ unindent (0.9)
61
+ yui-compressor (0.9.3)
62
+
63
+ PLATFORMS
64
+ ruby
65
+
66
+ DEPENDENCIES
67
+ activesupport (~> 3.0.0)
68
+ closure-compiler (~> 0.3.0)
69
+ coffee-script (~> 0.3.0)
70
+ growl (~> 1.0.0)
71
+ haml (~> 3.0.0)
72
+ i18n (~> 0.4.0)
73
+ jsmin (~> 1.0.0)
74
+ less (~> 1.2.0)
75
+ massimo!
76
+ packr (~> 3.1.0)
77
+ rack (~> 1.2.0)
78
+ rack-test (~> 0.5.0)
79
+ rr (~> 1.0.0)
80
+ rspec (~> 2.4.0)
81
+ sinatra_more (~> 0.3.0)
82
+ sprockets (~> 1.0.0)
83
+ test-construct (~> 1.2.0)
84
+ thor (~> 0.14.0)
85
+ tilt (~> 1.2.0)
86
+ tzinfo (~> 0.3.0)
87
+ unindent (~> 0.9.0)
88
+ yui-compressor (~> 0.9.0)
data/README.md CHANGED
@@ -21,7 +21,9 @@ Massimo is a static website builder that allows you to use dynamic technologies
21
21
  cd my-site
22
22
  massimo build
23
23
 
24
- For more information, visit http://petebrowne.github.com/massimo/.
24
+ For more information, visit [http://massimo.petebrowne.com/](http://massimo.petebrowne.com/).
25
+
26
+ For an example of a site built by massimo, visit [http://github.com/petebrowne/massimo-site](http://github.com/petebrowne/massimo-site).
25
27
 
26
28
  ## Copyright
27
29
 
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ task :default => :spec
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rspec/core'
7
+ require 'rspec/core/rake_task'
8
+ RSpec::Core::RakeTask.new
data/bin/massimo CHANGED
@@ -1,20 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'massimo'
4
-
5
- case ARGV.shift
6
- when 'b', 'build'
7
- Massimo::Commands::Build
8
- when 'g', 'generate'
9
- Massimo::Commands::Generate
10
- when nil, '-h', '--help', 'help'
11
- Massimo::Commands::Help
12
- when 's', 'server'
13
- Massimo::Commands::Server
14
- when '-v', '--version', 'version'
15
- Massimo::Commands::Version
16
- when 'w', 'watch'
17
- Massimo::Commands::Watch
18
- else
19
- Massimo::Commands::Help
20
- end.run
4
+ Massimo::CLI.start
@@ -0,0 +1,63 @@
1
+ require 'active_support/core_ext/hash/keys'
2
+ require 'thor'
3
+
4
+ module Massimo
5
+ class CLI < Thor
6
+ include Thor::Actions
7
+
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ default_task :help
11
+
12
+ class_option 'config_path', :desc => 'Path to the config file', :aliases => '-c'
13
+ class_option 'source_path', :desc => 'Path to the source dir', :aliases => '-s'
14
+ class_option 'output_path', :desc => 'Path to the output dir', :aliases => '-o'
15
+ class_option 'environment', :desc => 'Sets the environment', :aliases => '-e'
16
+ class_option 'production', :desc => "Sets the environment to 'production'", :aliases => '-p', :type => :boolean
17
+
18
+ desc 'build', 'Builds the site from the source files'
19
+ def build
20
+ Kernel.exit Massimo::UI.report_errors {
21
+ site.process
22
+ Massimo::UI.say 'massimo has built your site', :growl => true
23
+ }
24
+ end
25
+ map 'b' => :build
26
+
27
+ desc 'generate SITE_NAME', 'Generates a new site with the give name'
28
+ def generate(site_name)
29
+ directory 'site', site_name
30
+ end
31
+ map 'g' => :generate
32
+
33
+ desc 'server [PORT]', 'Runs a local Rack based web server on the given port'
34
+ def server(port = 3000)
35
+ Massimo::Server.start(site, port.to_i)
36
+ end
37
+ map 's' => :server
38
+
39
+ desc 'watch', 'Watches your files for changes and automatically builds the site'
40
+ def watch
41
+ Massimo::Watcher.start(site)
42
+ end
43
+ map 'w' => :watch
44
+
45
+ desc 'version', 'Prints out the version'
46
+ def version
47
+ puts Massimo::VERSION
48
+ end
49
+ map %w(v -v --version) => :version
50
+
51
+ protected
52
+
53
+ def site
54
+ @site ||= Massimo::Site.new(site_options)
55
+ end
56
+
57
+ def site_options
58
+ config = {}.merge(options).symbolize_keys
59
+ config[:environment] = 'production' if config.delete(:production) == true
60
+ config
61
+ end
62
+ end
63
+ end
@@ -6,6 +6,7 @@ require 'yaml'
6
6
  module Massimo
7
7
  class Config < OpenStruct
8
8
  DEFAULT_OPTIONS = {
9
+ :config_path => 'config.rb',
9
10
  :source_path => '.',
10
11
  :output_path => 'public',
11
12
  :environment => 'development',
@@ -20,19 +21,21 @@ module Massimo
20
21
  # or a file path to a .yaml file.
21
22
  def initialize(options = nil)
22
23
  hash = DEFAULT_OPTIONS.dup
23
-
24
- options = YAML.load_file(options) if options.is_a? String
25
24
  hash.merge!(options.symbolize_keys) if options.is_a? Hash
26
-
27
25
  super hash
28
26
  end
29
27
 
30
- # The full, expanded path to the source path.
28
+ # The full, expanded path to the config file
29
+ def config_path
30
+ File.expand_path super
31
+ end
32
+
33
+ # The full, expanded path to the source directory.
31
34
  def source_path
32
35
  File.expand_path super
33
36
  end
34
37
 
35
- # The full, expanded path to the output path.
38
+ # The full, expanded path to the output directory.
36
39
  def output_path
37
40
  File.expand_path super
38
41
  end
@@ -31,14 +31,22 @@ module Massimo
31
31
  case Massimo.config.javascripts_compressor.to_s
32
32
  when 'min', 'jsmin'
33
33
  require 'jsmin' unless defined?(JSMin)
34
- JSMin.minify(javascript).strip
34
+ JSMin.minify(javascript)
35
35
  when 'pack', 'packr'
36
36
  require 'packr' unless defined?(Packr)
37
37
  options = { :shrink_vars => true }.merge Massimo.config.options_for(:packr)
38
38
  Packr.pack(javascript, options)
39
+ when 'yui', 'yui-compressor', 'yui/compressor'
40
+ require 'yui/compressor' unless defined?(YUI)
41
+ options = { :munge => true }.merge Massimo.config.options_for(:yui)
42
+ YUI::JavaScriptCompressor.new(options).compress(javascript)
43
+ when 'closure', 'closure-compiler', 'closure/compiler'
44
+ require 'closure-compiler' unless defined?(Closure)
45
+ options = Massimo.config.options_for(:closure)
46
+ Closure::Compiler.new(options).compile(javascript)
39
47
  else
40
48
  javascript
41
- end
49
+ end.strip
42
50
  end
43
51
  end
44
52
  end
@@ -0,0 +1,37 @@
1
+ module Massimo
2
+ module Reloader
3
+ extend self
4
+
5
+ def load(name = :default)
6
+ cache[name] ||= {}
7
+
8
+ previous_constants = Object.constants
9
+ previous_features = $LOADED_FEATURES.dup
10
+ yield if block_given?
11
+ cache[name][:constants] = (Object.constants - previous_constants).uniq
12
+ cache[name][:features] = ($LOADED_FEATURES - previous_features).uniq
13
+
14
+ cache[name]
15
+ end
16
+
17
+ def unload(name = :default)
18
+ return unless cache.key?(name)
19
+ cache[name][:constants].reject! do |const|
20
+ Object.send(:remove_const, const) if Object.const_defined?(const)
21
+ end if cache[name].key?(:constants)
22
+ cache[name][:features].reject! do |feature|
23
+ $LOADED_FEATURES.delete(feature)
24
+ end if cache[name].key?(:features)
25
+ cache[name]
26
+ end
27
+
28
+ def reload(name = :default, &block)
29
+ unload(name)
30
+ load(name, &block)
31
+ end
32
+
33
+ def cache
34
+ @cache ||= {}
35
+ end
36
+ end
37
+ end
data/lib/massimo/site.rb CHANGED
@@ -5,21 +5,27 @@ require 'tilt'
5
5
  module Massimo
6
6
  class Site
7
7
  attr_accessor :config
8
+ attr_reader :resources
8
9
 
9
10
  # Creates a new Site, passing the given options to a new configuration.
10
11
  # If a block is given, it is evaluated in the scope of the new Site.
11
12
  def initialize(options = nil, &block)
13
+ @original_options ||= options
12
14
  @config = Config.new(options)
15
+ @resources = [ Massimo::Page, Massimo::Javascript, Massimo::Stylesheet, Massimo::View ]
13
16
  @template_scope_blocks = []
14
17
  @template_scope_extensions = []
15
18
  Massimo.site = self
16
19
 
17
- instance_eval(&block) if block_given?
20
+ Massimo::Reloader.reload(:config) do
21
+ instance_eval File.read(config.config_path) if File.exist?(config.config_path)
22
+ instance_eval(&block) if block_given?
23
+ end
18
24
  end
19
25
 
20
- # The resources used in this Site.
21
- def resources
22
- @resources ||= [ Massimo::Page, Massimo::Javascript, Massimo::Stylesheet, Massimo::View ]
26
+ # Sets up the Site from scratch again. Also Reloads the config file again.
27
+ def reload(&block)
28
+ initialize @original_options, &block
23
29
  end
24
30
 
25
31
  # Adds a new, custom resource to the Site. If a Class constant is given,
@@ -78,30 +84,27 @@ module Massimo
78
84
  end
79
85
 
80
86
  def add_template_scope_helpers(scope)
81
- config.files_in(:helpers, :rb).each do |file|
82
- load(file)
83
- if helper = (class_name_of_file(file).constantize rescue nil)
84
- scope.extend(helper)
87
+ cache = Massimo::Reloader.reload(:helpers) do
88
+ config.files_in(:helpers, :rb).each do |file|
89
+ load(file)
90
+ end
91
+ end
92
+
93
+ if constants = cache[:constants]
94
+ constants.each do |const|
95
+ if (helper = const.to_s.constantize rescue nil)
96
+ scope.extend(helper)
97
+ end
85
98
  end
86
99
  end
87
100
  end
88
101
 
89
102
  def reload_libs
90
- if defined? @previous_libs
91
- @previous_libs.each do |lib|
92
- class_name = class_name_of_file(lib)
93
- Object.class_eval do
94
- remove_const(class_name) if const_defined?(class_name)
95
- end
103
+ Massimo::Reloader.reload(:libs) do
104
+ config.files_in(:lib, :rb).each do |file|
105
+ load(file)
96
106
  end
97
107
  end
98
- @previous_libs = config.files_in(:lib, :rb).each do |file|
99
- load(file)
100
- end
101
- end
102
-
103
- def class_name_of_file(file)
104
- File.basename(file).sub(/\.[^\.]+$/, '').classify
105
108
  end
106
109
  end
107
110
  end
@@ -0,0 +1,18 @@
1
+ require 'sass'
2
+ require 'sprockets'
3
+
4
+ # This is an example configuration File
5
+ # Look here for all the available options:
6
+ # http://petebrowne.github.com/massimo/configuration/
7
+
8
+ if config.environment.production?
9
+ # Use JSMin for javascript compression
10
+ # config.javascripts_compressor = :min
11
+
12
+ # Compress the output of Sass stylesheets
13
+ # config.sass = { :style => :compressed }
14
+ end
15
+
16
+ helpers do
17
+ # Define helper methods here
18
+ end
File without changes
@@ -0,0 +1,5 @@
1
+ ---
2
+ title: Home Page
3
+ ---
4
+ <h1><%= title %></h1>
5
+ <p>Find me in pages/index.erb</p>
File without changes
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head lang="en">
4
+ <meta charset="utf-8">
5
+ <title><%= page.title %></title>
6
+ <%= stylesheet_link_tag 'main' %>
7
+ <%= javascript_include_tag 'main' %>
8
+ </head>
9
+ <body>
10
+ <%= yield %>
11
+ </body>
12
+ </html>
data/lib/massimo/ui.rb CHANGED
@@ -35,7 +35,7 @@ module Massimo
35
35
  def report_errors
36
36
  begin
37
37
  yield
38
- 0
38
+ true
39
39
  rescue Exception => error
40
40
  say 'massimo had a problem', :red
41
41
  indent do
@@ -43,7 +43,7 @@ module Massimo
43
43
  say error.backtrace.first, :magenta
44
44
  end
45
45
  growl "#{error.message}\n#{error.backtrace.first}", 'massimo problem'
46
- 1
46
+ false
47
47
  end
48
48
  end
49
49
 
@@ -1,3 +1,3 @@
1
1
  module Massimo
2
- VERSION = '0.7.5'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -8,8 +8,9 @@ module Massimo
8
8
  end
9
9
 
10
10
  def initialize(site)
11
- @site = site
12
- @files = []
11
+ @site = site
12
+ @previous_files = []
13
+ check_config
13
14
  end
14
15
 
15
16
  # Runs a loop, processing the Site whenever files have changed.
@@ -26,8 +27,13 @@ module Massimo
26
27
 
27
28
  # Processes the Site if any of the files have changed.
28
29
  def process
29
- if changed?
30
- Massimo::UI.report_errors do
30
+ Massimo::UI.report_errors do
31
+ if config_changed?
32
+ Massimo::UI.say 'massimo is reloading your site'
33
+ @site.reload
34
+ @site.process
35
+ Massimo::UI.say 'massimo has built your site', :growl => true
36
+ elsif changed?
31
37
  Massimo::UI.say 'massimo has noticed a change'
32
38
  @site.process
33
39
  Massimo::UI.say 'massimo has built your site', :growl => true
@@ -37,13 +43,22 @@ module Massimo
37
43
 
38
44
  # Determine if any of the Site's files have changed.
39
45
  def changed?
40
- @files != files
46
+ @previous_files != check_files
47
+ end
48
+
49
+ # Determine if the Site's config file has chanaged.
50
+ def config_changed?
51
+ @previous_config != check_config
41
52
  end
42
53
 
43
54
  protected
44
55
 
45
- def files
46
- @files = Dir[*glob].map { |file| File.mtime(file) }
56
+ def check_config
57
+ @previous_config = File.exist?(@site.config.config_path) && File.mtime(@site.config.config_path)
58
+ end
59
+
60
+ def check_files
61
+ @previous_files = Dir[*glob].map { |file| File.mtime(file) }
47
62
  end
48
63
 
49
64
  def glob
data/lib/massimo.rb CHANGED
@@ -1,27 +1,19 @@
1
1
  module Massimo
2
2
  autoload :Config, 'massimo/config'
3
+ autoload :CLI, 'massimo/cli'
3
4
  autoload :Helpers, 'massimo/helpers'
4
5
  autoload :Javascript, 'massimo/javascript'
5
6
  autoload :Page, 'massimo/page'
7
+ autoload :Reloader, 'massimo/reloader'
6
8
  autoload :Resource, 'massimo/resource'
7
9
  autoload :Server, 'massimo/server'
8
10
  autoload :Site, 'massimo/site'
9
11
  autoload :Stylesheet, 'massimo/stylesheet'
10
12
  autoload :UI, 'massimo/ui'
11
- autoload :Version, 'massimo/version'
13
+ autoload :VERSION, 'massimo/version'
12
14
  autoload :View, 'massimo/view'
13
15
  autoload :Watcher, 'massimo/watcher'
14
16
 
15
- module Commands
16
- autoload :Base, 'massimo/commands/base'
17
- autoload :Build, 'massimo/commands/build'
18
- autoload :Generate, 'massimo/commands/generate'
19
- autoload :Help, 'massimo/commands/help'
20
- autoload :Server, 'massimo/commands/server'
21
- autoload :Version, 'massimo/commands/version'
22
- autoload :Watch, 'massimo/commands/watch'
23
- end
24
-
25
17
  class << self
26
18
  def site
27
19
  @site ||= Site.new
data/massimo.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/massimo/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'massimo'
6
+ s.version = Massimo::VERSION
7
+ s.summary = 'Massimo is a static website builder.'
8
+ s.description = 'Massimo builds HTML, Javascript, and CSS Files from your source.'
9
+
10
+ s.authors = 'Pete Browne'
11
+ s.email = 'me@petebrowne.com'
12
+ s.homepage = 'http://petebrowne.github.com/massimo/'
13
+ s.rubyforge_project = 'massimo'
14
+
15
+ s.add_dependency 'activesupport', '~> 3.0.0'
16
+ s.add_dependency 'i18n', '~> 0.4.0'
17
+ s.add_dependency 'rack', '~> 1.2.0'
18
+ s.add_dependency 'sinatra_more', '~> 0.3.0'
19
+ s.add_dependency 'thor', '~> 0.14.0'
20
+ s.add_dependency 'tilt', '~> 1.2.0'
21
+ s.add_dependency 'tzinfo', '~> 0.3.0'
22
+ s.add_development_dependency 'rspec', '~> 2.4.0'
23
+ s.add_development_dependency 'rr', '~> 1.0.0'
24
+ s.add_development_dependency 'test-construct', '~> 1.2.0'
25
+ s.add_development_dependency 'rack-test', '~> 0.5.0'
26
+ s.add_development_dependency 'unindent', '~> 0.9.0'
27
+ s.add_development_dependency 'haml', '~> 3.0.0'
28
+ s.add_development_dependency 'less', '~> 1.2.0'
29
+ s.add_development_dependency 'coffee-script', '~> 0.3.0'
30
+ s.add_development_dependency 'sprockets', '~> 1.0.0'
31
+ s.add_development_dependency 'jsmin', '~> 1.0.0'
32
+ s.add_development_dependency 'packr', '~> 3.1.0'
33
+ s.add_development_dependency 'yui-compressor', '~> 0.9.0'
34
+ s.add_development_dependency 'closure-compiler', '~> 0.3.0'
35
+ s.add_development_dependency 'growl', '~> 1.0.0'
36
+
37
+ s.files = `git ls-files`.split("\n")
38
+ s.executables = `git ls-files`.split("\n").map{ |f| f =~ /^bin\/(.*)/ ? $1 : nil }.compact
39
+ s.require_path = 'lib'
40
+ end