sass 3.3.0.rc.1 → 3.3.0.rc.2

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 (78) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/VERSION_DATE +1 -1
  4. data/lib/sass.rb +5 -0
  5. data/lib/sass/engine.rb +3 -5
  6. data/lib/sass/plugin.rb +0 -1
  7. data/lib/sass/plugin/compiler.rb +1 -2
  8. data/lib/sass/script/functions.rb +16 -2
  9. data/lib/sass/script/lexer.rb +22 -12
  10. data/lib/sass/script/parser.rb +27 -14
  11. data/lib/sass/script/tree/variable.rb +1 -1
  12. data/lib/sass/script/value/base.rb +1 -1
  13. data/lib/sass/script/value/color.rb +29 -17
  14. data/lib/sass/script/value/list.rb +1 -1
  15. data/lib/sass/script/value/number.rb +8 -1
  16. data/lib/sass/scss/parser.rb +2 -2
  17. data/lib/sass/selector/sequence.rb +18 -19
  18. data/lib/sass/selector/simple_sequence.rb +5 -5
  19. data/lib/sass/source/map.rb +1 -1
  20. data/lib/sass/tree/node.rb +25 -0
  21. data/lib/sass/tree/variable_node.rb +5 -0
  22. data/lib/sass/tree/visitors/base.rb +4 -7
  23. data/lib/sass/tree/visitors/check_nesting.rb +2 -2
  24. data/lib/sass/tree/visitors/perform.rb +12 -7
  25. data/lib/sass/util.rb +95 -50
  26. data/lib/sass/util/normalized_map.rb +63 -14
  27. data/lib/sass/util/ordered_hash.rb +9 -5
  28. data/lib/sass/version.rb +10 -12
  29. data/test/sass/engine_test.rb +37 -0
  30. data/test/sass/functions_test.rb +9 -2
  31. data/test/sass/importer_test.rb +3 -3
  32. data/test/sass/script_test.rb +12 -10
  33. data/test/sass/source_map_test.rb +8 -8
  34. data/test/sass/util/normalized_map_test.rb +22 -1
  35. data/test/sass/util_test.rb +18 -0
  36. data/test/test_helper.rb +16 -0
  37. data/vendor/listen/CHANGELOG.md +228 -0
  38. data/vendor/listen/CONTRIBUTING.md +38 -0
  39. data/vendor/listen/Gemfile +30 -0
  40. data/vendor/listen/Guardfile +8 -0
  41. data/vendor/listen/LICENSE +20 -0
  42. data/vendor/listen/README.md +315 -0
  43. data/vendor/listen/Rakefile +47 -0
  44. data/vendor/listen/Vagrantfile +96 -0
  45. data/vendor/listen/lib/listen.rb +40 -0
  46. data/vendor/listen/lib/listen/adapter.rb +214 -0
  47. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  48. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  49. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  50. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  51. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  52. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  53. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  54. data/vendor/listen/lib/listen/listener.rb +225 -0
  55. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  56. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  57. data/vendor/listen/lib/listen/version.rb +3 -0
  58. data/vendor/listen/listen.gemspec +22 -0
  59. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  60. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  61. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  62. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  63. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  64. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  65. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  66. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  67. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  68. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  69. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  70. data/vendor/listen/spec/listen_spec.rb +73 -0
  71. data/vendor/listen/spec/spec_helper.rb +21 -0
  72. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  73. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  74. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  75. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  76. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  77. metadata +318 -300
  78. data/test/Gemfile.lock +0 -10
@@ -0,0 +1,47 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
6
+
7
+ require 'rbconfig'
8
+ namespace(:spec) do
9
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i
10
+ desc "Run all specs on multiple ruby versions (requires pik)"
11
+ task(:portability) do
12
+ %w[187 192 161].each do |version|
13
+ system "cmd /c echo -----------#{version}------------ & " +
14
+ "pik use #{version} & " +
15
+ "bundle install & " +
16
+ "bundle exec rspec spec"
17
+ end
18
+ end
19
+ else
20
+ desc "Run all specs on multiple ruby versions (requires rvm)"
21
+ task(:portability) do
22
+ travis_config_file = File.expand_path("../.travis.yml", __FILE__)
23
+ begin
24
+ travis_options ||= YAML::load_file(travis_config_file)
25
+ rescue => ex
26
+ puts "Travis config file '#{travis_config_file}' could not be found: #{ex.message}"
27
+ return
28
+ end
29
+
30
+ travis_options['rvm'].each do |version|
31
+ system <<-BASH
32
+ bash -c 'source ~/.rvm/scripts/rvm;
33
+ rvm #{version};
34
+ ruby_version_string_size=`ruby -v | wc -m`
35
+ echo;
36
+ for ((c=1; c<$ruby_version_string_size; c++)); do echo -n "="; done
37
+ echo;
38
+ echo "`ruby -v`";
39
+ for ((c=1; c<$ruby_version_string_size; c++)); do echo -n "="; done
40
+ echo;
41
+ RBXOPT="-Xrbc.db" bundle install;
42
+ RBXOPT="-Xrbc.db" bundle exec rspec spec -f doc 2>&1;'
43
+ BASH
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,96 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant::Config.run do |config|
5
+ # All Vagrant configuration is done here. The most common configuration
6
+ # options are documented and commented below. For a complete reference,
7
+ # please see the online documentation at vagrantup.com.
8
+
9
+ # Every Vagrant virtual environment requires a box to build off of.
10
+ config.vm.box = "lucid32"
11
+
12
+ # The url from where the 'config.vm.box' box will be fetched if it
13
+ # doesn't already exist on the user's system.
14
+ # config.vm.box_url = "http://domain.com/path/to/above.box"
15
+
16
+ # Boot with a GUI so you can see the screen. (Default is headless)
17
+ # config.vm.boot_mode = :gui
18
+
19
+ # Assign this VM to a host-only network IP, allowing you to access it
20
+ # via the IP. Host-only networks can talk to the host machine as well as
21
+ # any other machines on the same network, but cannot be accessed (through this
22
+ # network interface) by any external networks.
23
+ # config.vm.network :hostonly, "33.33.33.10"
24
+
25
+ # Assign this VM to a bridged network, allowing you to connect directly to a
26
+ # network using the host's network device. This makes the VM appear as another
27
+ # physical device on your network.
28
+ # config.vm.network :bridged
29
+
30
+ # Forward a port from the guest to the host, which allows for outside
31
+ # computers to access the VM, whereas host only networking does not.
32
+ # config.vm.forward_port 80, 8080
33
+
34
+ # Share an additional folder to the guest VM. The first argument is
35
+ # an identifier, the second is the path on the guest to mount the
36
+ # folder, and the third is the path on the host to the actual folder.
37
+ # config.vm.share_folder "v-data", "/vagrant_data", "../data"
38
+
39
+ # Enable provisioning with Puppet stand alone. Puppet manifests
40
+ # are contained in a directory path relative to this Vagrantfile.
41
+ # You will need to create the manifests directory and a manifest in
42
+ # the file lucid32.pp in the manifests_path directory.
43
+ #
44
+ # An example Puppet manifest to provision the message of the day:
45
+ #
46
+ # # group { "puppet":
47
+ # # ensure => "present",
48
+ # # }
49
+ # #
50
+ # # File { owner => 0, group => 0, mode => 0644 }
51
+ # #
52
+ # # file { '/etc/motd':
53
+ # # content => "Welcome to your Vagrant-built virtual machine!
54
+ # # Managed by Puppet.\n"
55
+ # # }
56
+ #
57
+ # config.vm.provision :puppet do |puppet|
58
+ # puppet.manifests_path = "manifests"
59
+ # puppet.manifest_file = "lucid32.pp"
60
+ # end
61
+
62
+ # Enable provisioning with chef solo, specifying a cookbooks path (relative
63
+ # to this Vagrantfile), and adding some recipes and/or roles.
64
+ #
65
+ # config.vm.provision :chef_solo do |chef|
66
+ # chef.cookbooks_path = "cookbooks"
67
+ # chef.add_recipe "mysql"
68
+ # chef.add_role "web"
69
+ #
70
+ # # You may also specify custom JSON attributes:
71
+ # chef.json = { :mysql_password => "foo" }
72
+ # end
73
+
74
+ # Enable provisioning with chef server, specifying the chef server URL,
75
+ # and the path to the validation key (relative to this Vagrantfile).
76
+ #
77
+ # The Opscode Platform uses HTTPS. Substitute your organization for
78
+ # ORGNAME in the URL and validation key.
79
+ #
80
+ # If you have your own Chef Server, use the appropriate URL, which may be
81
+ # HTTP instead of HTTPS depending on your configuration. Also change the
82
+ # validation key to validation.pem.
83
+ #
84
+ # config.vm.provision :chef_client do |chef|
85
+ # chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
86
+ # chef.validation_key_path = "ORGNAME-validator.pem"
87
+ # end
88
+ #
89
+ # If you're using the Opscode platform, your validator client is
90
+ # ORGNAME-validator, replacing ORGNAME with your organization name.
91
+ #
92
+ # IF you have your own Chef Server, the default validation client name is
93
+ # chef-validator, unless you changed the configuration.
94
+ #
95
+ # chef.validation_client_name = "ORGNAME-validator"
96
+ end
@@ -0,0 +1,40 @@
1
+ module Listen
2
+
3
+ autoload :Turnstile, 'listen/turnstile'
4
+ autoload :Listener, 'listen/listener'
5
+ autoload :MultiListener, 'listen/multi_listener'
6
+ autoload :DirectoryRecord, 'listen/directory_record'
7
+ autoload :DependencyManager, 'listen/dependency_manager'
8
+ autoload :Adapter, 'listen/adapter'
9
+
10
+ module Adapters
11
+ autoload :Darwin, 'listen/adapters/darwin'
12
+ autoload :Linux, 'listen/adapters/linux'
13
+ autoload :BSD, 'listen/adapters/bsd'
14
+ autoload :Windows, 'listen/adapters/windows'
15
+ autoload :Polling, 'listen/adapters/polling'
16
+ end
17
+
18
+ # Listens to filesystem modifications on a either single directory or multiple directories.
19
+ #
20
+ # @param (see Listen::Listener#new)
21
+ # @param (see Listen::MultiListener#new)
22
+ #
23
+ # @yield [modified, added, removed] the changed files
24
+ # @yieldparam [Array<String>] modified the list of modified files
25
+ # @yieldparam [Array<String>] added the list of added files
26
+ # @yieldparam [Array<String>] removed the list of removed files
27
+ #
28
+ # @return [Listen::Listener] the file listener if no block given
29
+ #
30
+ def self.to(*args, &block)
31
+ listener = if args.length == 1 || ! args[1].is_a?(String)
32
+ Listener.new(*args, &block)
33
+ else
34
+ MultiListener.new(*args, &block)
35
+ end
36
+
37
+ block ? listener.start : listener
38
+ end
39
+
40
+ end
@@ -0,0 +1,214 @@
1
+ require 'rbconfig'
2
+ require 'thread'
3
+ require 'set'
4
+ require 'fileutils'
5
+
6
+ module Listen
7
+ class Adapter
8
+ attr_accessor :directories, :latency, :paused
9
+
10
+ # The default delay between checking for changes.
11
+ DEFAULT_LATENCY = 0.25
12
+
13
+ # The default warning message when there is a missing dependency.
14
+ MISSING_DEPENDENCY_MESSAGE = <<-EOS.gsub(/^\s*/, '')
15
+ For a better performance, it's recommended that you satisfy the missing dependency.
16
+ EOS
17
+
18
+ # The default warning message when falling back to polling adapter.
19
+ POLLING_FALLBACK_MESSAGE = <<-EOS.gsub(/^\s*/, '')
20
+ Listen will be polling changes. Learn more at https://github.com/guard/listen#polling-fallback.
21
+ EOS
22
+
23
+ # Selects the appropriate adapter implementation for the
24
+ # current OS and initializes it.
25
+ #
26
+ # @param [String, Array<String>] directories the directories to watch
27
+ # @param [Hash] options the adapter options
28
+ # @option options [Boolean] force_polling to force polling or not
29
+ # @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
30
+ # @option options [Float] latency the delay between checking for changes in seconds
31
+ #
32
+ # @yield [changed_dirs, options] callback Callback called when a change happens
33
+ # @yieldparam [Array<String>] changed_dirs the changed directories
34
+ # @yieldparam [Hash] options callback options (like :recursive => true)
35
+ #
36
+ # @return [Listen::Adapter] the chosen adapter
37
+ #
38
+ def self.select_and_initialize(directories, options = {}, &callback)
39
+ return Adapters::Polling.new(directories, options, &callback) if options.delete(:force_polling)
40
+
41
+ warning = ''
42
+
43
+ begin
44
+ if Adapters::Darwin.usable_and_works?(directories, options)
45
+ return Adapters::Darwin.new(directories, options, &callback)
46
+ elsif Adapters::Linux.usable_and_works?(directories, options)
47
+ return Adapters::Linux.new(directories, options, &callback)
48
+ elsif Adapters::BSD.usable_and_works?(directories, options)
49
+ return Adapters::BSD.new(directories, options, &callback)
50
+ elsif Adapters::Windows.usable_and_works?(directories, options)
51
+ return Adapters::Windows.new(directories, options, &callback)
52
+ end
53
+ rescue DependencyManager::Error => e
54
+ warning += e.message + "\n" + MISSING_DEPENDENCY_MESSAGE
55
+ end
56
+
57
+ unless options[:polling_fallback_message] == false
58
+ warning += options[:polling_fallback_message] || POLLING_FALLBACK_MESSAGE
59
+ Kernel.warn "[Listen warning]:\n" + warning.gsub(/^(.*)/, ' \1')
60
+ end
61
+
62
+ Adapters::Polling.new(directories, options, &callback)
63
+ end
64
+
65
+ # Initializes the adapter.
66
+ #
67
+ # @param [String, Array<String>] directories the directories to watch
68
+ # @param [Hash] options the adapter options
69
+ # @option options [Float] latency the delay between checking for changes in seconds
70
+ # @option options [Boolean] report_changes whether or not to automatically report changes (run the callback)
71
+ #
72
+ # @yield [changed_dirs, options] callback Callback called when a change happens
73
+ # @yieldparam [Array<String>] changed_dirs the changed directories
74
+ # @yieldparam [Hash] options callback options (like :recursive => true)
75
+ #
76
+ # @return [Listen::Adapter] the adapter
77
+ #
78
+ def initialize(directories, options = {}, &callback)
79
+ @directories = Array(directories)
80
+ @callback = callback
81
+ @paused = false
82
+ @mutex = Mutex.new
83
+ @changed_dirs = Set.new
84
+ @turnstile = Turnstile.new
85
+ @latency ||= DEFAULT_LATENCY
86
+ @latency = options[:latency] if options[:latency]
87
+ @report_changes = options[:report_changes].nil? ? true : options[:report_changes]
88
+ end
89
+
90
+ # Starts the adapter.
91
+ #
92
+ # @param [Boolean] blocking whether or not to block the current thread after starting
93
+ #
94
+ def start(blocking = true)
95
+ @stop = false
96
+ end
97
+
98
+ # Stops the adapter.
99
+ #
100
+ def stop
101
+ @stop = true
102
+ @turnstile.signal # ensure no thread is blocked
103
+ end
104
+
105
+ # Returns whether the adapter is statred or not
106
+ #
107
+ # @return [Boolean] whether the adapter is started or not
108
+ #
109
+ def started?
110
+ @stop.nil? ? false : !@stop
111
+ end
112
+
113
+ # Blocks the main thread until the poll thread
114
+ # runs the callback.
115
+ #
116
+ def wait_for_callback
117
+ @turnstile.wait unless @paused
118
+ end
119
+
120
+ # Blocks the main thread until N changes are
121
+ # detected.
122
+ #
123
+ def wait_for_changes(goal = 0)
124
+ changes = 0
125
+
126
+ loop do
127
+ @mutex.synchronize { changes = @changed_dirs.size }
128
+
129
+ return if @paused || @stop
130
+ return if changes >= goal
131
+
132
+ sleep(@latency)
133
+ end
134
+ end
135
+
136
+ # Checks if the adapter is usable on the current OS.
137
+ #
138
+ # @return [Boolean] whether usable or not
139
+ #
140
+ def self.usable?
141
+ load_depenencies
142
+ dependencies_loaded?
143
+ end
144
+
145
+ # Checks if the adapter is usable and works on the current OS.
146
+ #
147
+ # @param [String, Array<String>] directories the directories to watch
148
+ # @param [Hash] options the adapter options
149
+ # @option options [Float] latency the delay between checking for changes in seconds
150
+ #
151
+ # @return [Boolean] whether usable and work or not
152
+ #
153
+ def self.usable_and_works?(directories, options = {})
154
+ usable? && Array(directories).all? { |d| works?(d, options) }
155
+ end
156
+
157
+ # Runs a tests to determine if the adapter can actually pick up
158
+ # changes in a given directory and returns the result.
159
+ #
160
+ # @note This test takes some time depending the adapter latency.
161
+ #
162
+ # @param [String, Pathname] directory the directory to watch
163
+ # @param [Hash] options the adapter options
164
+ # @option options [Float] latency the delay between checking for changes in seconds
165
+ #
166
+ # @return [Boolean] whether the adapter works or not
167
+ #
168
+ def self.works?(directory, options = {})
169
+ work = false
170
+ test_file = "#{directory}/.listen_test"
171
+ callback = lambda { |*| work = true }
172
+ adapter = self.new(directory, options, &callback)
173
+ adapter.start(false)
174
+
175
+ FileUtils.touch(test_file)
176
+
177
+ t = Thread.new { sleep(adapter.latency * 5); adapter.stop }
178
+
179
+ adapter.wait_for_callback
180
+ work
181
+ ensure
182
+ Thread.kill(t) if t
183
+ FileUtils.rm(test_file) if File.exists?(test_file)
184
+ adapter.stop if adapter && adapter.started?
185
+ end
186
+
187
+ # Runs the callback and passes it the changes if there are any.
188
+ #
189
+ def report_changes
190
+ changed_dirs = nil
191
+
192
+ @mutex.synchronize do
193
+ return if @changed_dirs.empty?
194
+ changed_dirs = @changed_dirs.to_a
195
+ @changed_dirs.clear
196
+ end
197
+
198
+ @callback.call(changed_dirs, {})
199
+ @turnstile.signal
200
+ end
201
+
202
+ private
203
+
204
+ # Polls changed directories and reports them back
205
+ # when there are changes.
206
+ #
207
+ def poll_changed_dirs
208
+ until @stop
209
+ sleep(@latency)
210
+ report_changes
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,112 @@
1
+ module Listen
2
+ module Adapters
3
+
4
+ # Listener implementation for BSD's `kqueue`.
5
+ #
6
+ class BSD < Adapter
7
+ extend DependencyManager
8
+
9
+ # Declare the adapter's dependencies
10
+ dependency 'rb-kqueue', '~> 0.2'
11
+
12
+ # Watched kqueue events
13
+ #
14
+ # @see http://www.freebsd.org/cgi/man.cgi?query=kqueue
15
+ # @see https://github.com/nex3/rb-kqueue/blob/master/lib/rb-kqueue/queue.rb
16
+ #
17
+ EVENTS = [ :delete, :write, :extend, :attrib, :link, :rename, :revoke ]
18
+
19
+ # Initializes the Adapter. See {Listen::Adapter#initialize} for
20
+ # more info.
21
+ #
22
+ def initialize(directories, options = {}, &callback)
23
+ super
24
+ @kqueue = init_kqueue
25
+ end
26
+
27
+ # Starts the adapter.
28
+ #
29
+ # @param [Boolean] blocking whether or not to block the current thread after starting
30
+ #
31
+ def start(blocking = true)
32
+ @mutex.synchronize do
33
+ return if @stop == false
34
+ super
35
+ end
36
+
37
+ @kqueue_thread = Thread.new do
38
+ until @stop
39
+ @kqueue.poll
40
+ sleep(@latency)
41
+ end
42
+ end
43
+ @poll_thread = Thread.new { poll_changed_dirs } if @report_changes
44
+
45
+ @kqueue_thread.join if blocking
46
+ end
47
+
48
+ # Stops the adapter.
49
+ #
50
+ def stop
51
+ @mutex.synchronize do
52
+ return if @stop == true
53
+ super
54
+ end
55
+
56
+ @kqueue.stop
57
+ Thread.kill(@kqueue_thread) if @kqueue_thread
58
+ @poll_thread.join if @poll_thread
59
+ end
60
+
61
+ # Checks if the adapter is usable on the current OS.
62
+ #
63
+ # @return [Boolean] whether usable or not
64
+ #
65
+ def self.usable?
66
+ return false unless RbConfig::CONFIG['target_os'] =~ /freebsd/i
67
+ super
68
+ end
69
+
70
+ private
71
+
72
+ # Initializes a kqueue Queue and adds a watcher for each files in
73
+ # the directories passed to the adapter.
74
+ #
75
+ # @return [INotify::Notifier] initialized kqueue
76
+ #
77
+ def init_kqueue
78
+ require 'find'
79
+
80
+ callback = lambda do |event|
81
+ path = event.watcher.path
82
+ @mutex.synchronize do
83
+ # kqueue watches everything, but Listen only needs the
84
+ # directory where stuffs happens.
85
+ @changed_dirs << (File.directory?(path) ? path : File.dirname(path))
86
+
87
+ # If it is a directory, and it has a write flag, it means a
88
+ # file has been added so find out which and deal with it.
89
+ # No need to check for removed file, kqueue will forget them
90
+ # when the vfs does..
91
+ if File.directory?(path) && !(event.flags & [:write]).empty?
92
+ queue = event.watcher.queue
93
+ Find.find(path) do |file|
94
+ unless queue.watchers.detect {|k,v| v.path == file.to_s}
95
+ queue.watch_file(file, *EVENTS, &callback)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ KQueue::Queue.new.tap do |queue|
103
+ @directories.each do |directory|
104
+ Find.find(directory) do |path|
105
+ queue.watch_file(path, *EVENTS, &callback)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end