wrap_it 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +5 -0
- data/Gemfile +7 -0
- data/README.md +277 -0
- data/Rakefile +14 -0
- data/config.ru +4 -0
- data/lib/wrap_it/arguments_array.rb +128 -0
- data/lib/wrap_it/base.rb +108 -0
- data/lib/wrap_it/callbacks.rb +63 -0
- data/lib/wrap_it/container.rb +84 -0
- data/lib/wrap_it/derived_attributes.rb +37 -0
- data/lib/wrap_it/enums.rb +89 -0
- data/lib/wrap_it/html_class.rb +193 -0
- data/lib/wrap_it/no_rails.rb +66 -0
- data/lib/wrap_it/rails.rb +51 -0
- data/lib/wrap_it/switches.rb +82 -0
- data/lib/wrap_it/text_container.rb +25 -0
- data/lib/wrap_it/version.rb +3 -0
- data/lib/wrap_it.rb +74 -0
- data/spec/internal/log/test.log +619 -0
- data/spec/lib/arguments_array_spec.rb +83 -0
- data/spec/lib/base_spec.rb +48 -0
- data/spec/lib/callbacks_spec.rb +5 -0
- data/spec/lib/container_spec.rb +9 -0
- data/spec/lib/derived_attributes_spec.rb +51 -0
- data/spec/lib/enums_spec.rb +79 -0
- data/spec/lib/html_class_spec.rb +98 -0
- data/spec/lib/switches_spec.rb +66 -0
- data/spec/rails/base_spec.rb +20 -0
- data/spec/rails/container_spec.rb +30 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/example_groups/rails_example_group.rb +79 -0
- data/spec/support/example_groups/wrap_it_example_group.rb +39 -0
- data/wrap_it.gemspec +30 -0
- metadata +179 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7f693b3a5912624587905a8f0ed50eed00090900
|
4
|
+
data.tar.gz: 454f1f68671d59f445b878c52b0cbc690f9e5dfb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 045a82e459f67f7883c5609789c8bdbb74714eabeae1cf174e9b5979963e62fb24818db29d3d3e8652197705dd2d71110c75a84866907fc78f844604c91b6723
|
7
|
+
data.tar.gz: 650c0ecd43f82eaefe4075d4bb3828fc0dd76774b6fa533b5a7e7965b6b60324dc386eab34417524f806f65edcfba5592c3ca3639a7ce54e5903e24011312042
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,277 @@
|
|
1
|
+
# WrapIt
|
2
|
+
|
3
|
+
This library provides set of classes and modules with simple DSL for quick and easy creating html helpers with your own DSL. It's usefull for implementing CSS frameworks, or making your own.
|
4
|
+
|
5
|
+
For example, your designer makes perfect button style for some site. This element will appears in many places of site in some variations. The button have `danger`, `success` and `default` look, and can have `active` state. Button can have some icon. So, you make some CSS styles, and now you should place HTML markup of this element in many places of site. With `wrap_it` library you can do it with following code:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
class PerfectButton < WrapIt::Container
|
9
|
+
include TextContainer
|
10
|
+
html_class 'button'
|
11
|
+
enum :look, [:default, :success, :danger], html_class_prefix: 'button-'
|
12
|
+
switch :active, html_class: 'button-active'
|
13
|
+
child :icon, [tag: 'img', class: 'button-icon']
|
14
|
+
end
|
15
|
+
|
16
|
+
WrapIt.register :p_button, 'PerfectButton'
|
17
|
+
```
|
18
|
+
|
19
|
+
Now, include this helper into you template engine. For Rails:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
class MyController < ApplicationController
|
23
|
+
helper WrapIt.helpers
|
24
|
+
...
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
And you can use it in you ERB:
|
29
|
+
|
30
|
+
```html
|
31
|
+
<%= p_button %>button 1<% end %>
|
32
|
+
<%= p_button 'button 2', :active, :success %>
|
33
|
+
<%= p_button active: true, look: :success, body: 'button 3' %>
|
34
|
+
<%= p_button :danger do |b| %>
|
35
|
+
<%= b.icon src: '/path/to/icon.png' %>
|
36
|
+
button 4
|
37
|
+
<% end %>
|
38
|
+
```
|
39
|
+
|
40
|
+
This will produce following code:
|
41
|
+
|
42
|
+
```html
|
43
|
+
<div class="button">button 1</div>
|
44
|
+
<div class="button button-active button-success">button 2</div>
|
45
|
+
<div class="button button-active button-success">button 3</div>
|
46
|
+
<div class="button button-danger">
|
47
|
+
<img class="button-icon" src="/path/to/icon.png">
|
48
|
+
button 4
|
49
|
+
</div>
|
50
|
+
```
|
51
|
+
|
52
|
+
Note, that lines 2 and 3 produces same html markup.
|
53
|
+
|
54
|
+
# Status
|
55
|
+
|
56
|
+
Project in pre-release state. First release version `1.0.0` planned to February of 2014.
|
57
|
+
|
58
|
+
# Installation
|
59
|
+
|
60
|
+
Library have a gem. So, just install it:
|
61
|
+
|
62
|
+
```sh
|
63
|
+
gem install wrap_it
|
64
|
+
```
|
65
|
+
|
66
|
+
or include in your `Gemfile`
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
gem 'wrap_it'
|
70
|
+
```
|
71
|
+
|
72
|
+
and run
|
73
|
+
|
74
|
+
```sh
|
75
|
+
bundle install
|
76
|
+
```
|
77
|
+
|
78
|
+
# Configuration
|
79
|
+
|
80
|
+
Library have no specific configuration.
|
81
|
+
|
82
|
+
# Usage
|
83
|
+
|
84
|
+
All helpers classes derived from `WrapIt::Base` class, that provides allmost all functionality. For helpers, thats includes other helpers, use `WrapIt::Container` class. Where are some library-specific methods, defined directly in `WrapIt` module.
|
85
|
+
|
86
|
+
Simple example explained above. More complex usage is to provide some logic to initalization, capturing and rendering process. To do this, use `after` or `before` `initialize`, `capture` and `reder` callbacks respectively. Usually `after` callbacks used. `initialize` callbacks runs around arguments and optioins parsed, `capture` callbacks runs around capturing content of element and `render` callbacks runs around wrapping content into element tag.
|
87
|
+
|
88
|
+
Inside callbacks some usefull instance variables available.
|
89
|
+
|
90
|
+
`@tag` contains tag name for element.
|
91
|
+
|
92
|
+
`@options` contains creation options hash. This hash also contains `:class` key with current set of HTML classes. But its recommended to use class-aware methods to manipulate html classes (see below). **Warning!** You **MUST** remove from this hash all your class-specific user options, because this hash will be used as list of HTML attributes of element.
|
93
|
+
|
94
|
+
`@arguments` array available only in `after_initialize` callback and contains creation arguments. Its recommended to extract arguments, related to your class from this array if you plan to subclass your helper in future, so when subclasses `after_initialize` called these arguments will not available there.
|
95
|
+
|
96
|
+
`@content` string available in `capture` and `render` callbacks and contains captured content. You can change it to any value. If you want to render some html markup with `@content`, use `html_safe` method (see below) to prevent HTML escaping.
|
97
|
+
|
98
|
+
`@template` contains rendering template. Use this variable carefully, so if you call `@template.content_tag` or something else Rails-related, your library will not be portable to other frameworks. So, if you use this gem in user-end application, or Rails-only library, you are free to use all of `@template` methods.
|
99
|
+
|
100
|
+
*Examples*
|
101
|
+
|
102
|
+
Prevent user from changing element tag:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
class Helper < WrapIt::Base
|
106
|
+
after_initialize { @tag = 'table' }
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
Including some simple HTML into content
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
class Helper < WrapIt::Base
|
114
|
+
after_initialize do
|
115
|
+
@icon = optioins.delete(:icon)
|
116
|
+
end
|
117
|
+
|
118
|
+
after_capture do
|
119
|
+
unless @icon.nil?
|
120
|
+
@content = html_safe("<i class=\"#{@icon}\"></i>") + @content
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
## WrapIt
|
126
|
+
|
127
|
+
#### WrapIt.register(*args)
|
128
|
+
|
129
|
+
Registers helper class. In arguments, first specify helper method names as `Symbols` and in last argument fully qualified helper class name as `String`.
|
130
|
+
|
131
|
+
#### WrapIt.unregister(*args)
|
132
|
+
|
133
|
+
Unregisters helper class. Just pass list of method names as `Symbols`.
|
134
|
+
|
135
|
+
#### WrapIt.helpers
|
136
|
+
|
137
|
+
Returns a module, that contains all registered helpers. Usefull to provide all helpers to template engine.
|
138
|
+
|
139
|
+
## WrapIt::Base
|
140
|
+
|
141
|
+
### DSL methods
|
142
|
+
|
143
|
+
#### default_tag(name)
|
144
|
+
|
145
|
+
Use `default_tag` DSL method inside your class to specify HTML tag name for element. This tag can be changed soon by you or user. `name` can be `Symbol` or `String` and it converted to `String`.
|
146
|
+
|
147
|
+
#### html_class(*args)
|
148
|
+
|
149
|
+
Use `html_class` DSL method to add default html classes, thats are automatically added when element created.
|
150
|
+
|
151
|
+
#### omit_content
|
152
|
+
|
153
|
+
Once this method called from class, this class will ommit any text content, captured from template. For example, `<%= element do %><p>Any content</p><% end %>` normally will produce `<div><p>Any content</p></div>`. In some cases you whant to drop `<p>Any content</p>`, for exmaple, inside tables.
|
154
|
+
|
155
|
+
#### switch(name, options = {}, &block)
|
156
|
+
|
157
|
+
Adds `switch`. Switch is a boolean flag. When element created, creation arguments will be scanned for `Symbol`, that equals to `name`. If it founded, switch turned on. Also creation options inspected. If its contains `name: true` key-value pair, this pair removed from options and switch also turned on. `name` can be `Symbol` or `String` and it converted to `Symbol`.
|
158
|
+
|
159
|
+
This method also adds getter and setter for this switch in form `name?` and `name=` respectively.
|
160
|
+
|
161
|
+
You can pass `html_class` option. If it presend, this class will be added or removed to element when switch changes its state.
|
162
|
+
|
163
|
+
Also `aliases` option available. So if some of aliases founded in arguments it also changes switch state. You should pass only `Symbol` or `Array` if symbols to this optioin.
|
164
|
+
|
165
|
+
If block given, it will be called each time switch changes its state in context of element with the switch state as argument.
|
166
|
+
|
167
|
+
#### enum(name, options = {}, &block)
|
168
|
+
|
169
|
+
Adds `enum`. When element created, creation arguments will be scanned for `Symbol`, that included contains in `values`. If it founded, enum takes this value. Also creation options inspected. If its contains `name: value` key-value pair with valid value, this pair removed from options and enum takes this value.
|
170
|
+
|
171
|
+
This method also adds getter and setter for this enum.
|
172
|
+
|
173
|
+
You can pass `html_class_prefix` option. If it present, HTML class will be combined from it and enum value and added or removed from element HTML class.
|
174
|
+
|
175
|
+
Also `aliases` option available. So if some of aliases founded in creation options keys it also changes enum value. You should pass only `Symbol` or `Array` if symbols to this optioin.
|
176
|
+
|
177
|
+
`default` option sets default value for enum. This value will used if nil or invalid value assigned to enum.
|
178
|
+
|
179
|
+
If block given, it will be called each time enum changes its value in context of element with the new value as argument.
|
180
|
+
|
181
|
+
### Instance methods
|
182
|
+
|
183
|
+
#### html_class
|
184
|
+
|
185
|
+
Returns array of html classes
|
186
|
+
|
187
|
+
#### html_class=(*args)
|
188
|
+
|
189
|
+
Sets html class(es) for element. Arguments can be `String`, `Symbol` or `Array` of it. All converted to plain array of `Symbols`. Duplicated classes removed.
|
190
|
+
|
191
|
+
#### add_html_class(*args)
|
192
|
+
|
193
|
+
Adds html class. For args see `#html_class=`
|
194
|
+
|
195
|
+
#### remove_html_class(*args)
|
196
|
+
|
197
|
+
Removes html class. For args see `#html_class=`
|
198
|
+
|
199
|
+
#### html_class?(*args, &block)
|
200
|
+
|
201
|
+
Determines whether element contains class, satisfied by conditions, specified in method arguments.
|
202
|
+
|
203
|
+
There are two forms of method call: with list of conditions as arguments and with block for comparing. Method makes comparison with html class untill first `true` return value or end of list. All conditions should be satisfied for `true` return of this method.
|
204
|
+
|
205
|
+
In first form, each argument treated as condition. Condition can be a `Regexp`, so html classes of element tested for matching to that regular expression. If condition is an `Array` then every class will be tested for presence in this array. If condition is `Symbol` or `String` classes will be compared with it via equality operator `==`.
|
206
|
+
|
207
|
+
In second form all arguments are ignored and for each comparison given block called with html class as argument. Block return value then used.
|
208
|
+
|
209
|
+
*Examples*
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
# with `Symbol` or `String` conditions
|
213
|
+
element.html_class = [:a, :b, :c]
|
214
|
+
element.html_class?(:a) #=> true
|
215
|
+
element.html_class?(:d) #=> false
|
216
|
+
element.html_class?(:a, 'b') #=> true
|
217
|
+
element.html_class?(:a, :d) #=> false
|
218
|
+
|
219
|
+
# with `Regexp` conditions
|
220
|
+
element.html_class = [:some, :test]
|
221
|
+
element.html_class?(/some/) #=> true
|
222
|
+
element.html_class?(/some/, /bad/) #=> false
|
223
|
+
element.html_class?(/some/, :test) #=> true
|
224
|
+
|
225
|
+
# with `Array` conditions
|
226
|
+
element.html_class = [:a, :b, :c]
|
227
|
+
element.html_class?(%w(a d)) #=> true
|
228
|
+
element.html_class?(%w(e d)) #=> false
|
229
|
+
|
230
|
+
# with block
|
231
|
+
element.html_class = [:a, :b, :c]
|
232
|
+
element.html_class? { |x| x == 'a' } #=> true
|
233
|
+
```
|
234
|
+
|
235
|
+
#### no_html_class?(*args, &block)
|
236
|
+
|
237
|
+
Determines whether element doesn't contains class, satisfied by conditions, specified in method arguments. See `html_class?`.
|
238
|
+
|
239
|
+
## WrapIt::Container
|
240
|
+
|
241
|
+
### DSL methods
|
242
|
+
|
243
|
+
#### child(*args, &block)
|
244
|
+
|
245
|
+
Creates your own DSL method to create child items. In arguments, you should specify list of method names (aliases if more that one). Then you can specify class name for shild. If ommited, `WrapIt::Base` will be used. and as last argument you can specify array of arguments, that will be passed to child constructor. This array will be mixed with arguments, specified by user, with higher priority. At last, you can define block, that will be called after creating child, but before its rendering. This child passed as argument to block.
|
246
|
+
|
247
|
+
# Todo
|
248
|
+
|
249
|
+
* Enlarge library functionality
|
250
|
+
* Strong testing
|
251
|
+
* Finish Sinatra integration
|
252
|
+
* Rubydoc documentation
|
253
|
+
|
254
|
+
# License
|
255
|
+
|
256
|
+
The MIT License (MIT)
|
257
|
+
|
258
|
+
Copyright (c) 2014 Alexey Ovchinnikov
|
259
|
+
|
260
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
261
|
+
of this software and associated documentation files (the "Software"), to deal
|
262
|
+
in the Software without restriction, including without limitation the rights
|
263
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
264
|
+
copies of the Software, and to permit persons to whom the Software is
|
265
|
+
furnished to do so, subject to the following conditions:
|
266
|
+
|
267
|
+
The above copyright notice and this permission notice shall be included in
|
268
|
+
all copies or substantial portions of the Software.
|
269
|
+
|
270
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
271
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
272
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
273
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
274
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
275
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
276
|
+
THE SOFTWARE.
|
277
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
# require 'yard'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
# require 'rake/testtask'
|
5
|
+
|
6
|
+
# Rake::TestTask.new do |t|
|
7
|
+
# t.name = :spec_rails
|
8
|
+
# t.libs.push "spec_rails"
|
9
|
+
# t.test_files = FileList['spec_rails/**/*_spec.rb']
|
10
|
+
# t.verbose = true
|
11
|
+
# end
|
12
|
+
|
13
|
+
#YARD::Rake::YardocTask.new
|
14
|
+
RSpec::Core::RakeTask.new
|
data/config.ru
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
module WrapIt
|
2
|
+
#
|
3
|
+
# Adds #extract! and #extarct_first! methods to array. Theese methods are
|
4
|
+
# extracts items from array by some condirions and returns its as separate
|
5
|
+
# array for #extract! and as first item for #extract_first!.
|
6
|
+
#
|
7
|
+
# @author Alexey Ovchinnikov <alexiss@cybernetlab.ru>
|
8
|
+
#
|
9
|
+
module ArgumentsArray
|
10
|
+
REQUIRED_METHODS = %i(reject! find_index delete_at)
|
11
|
+
|
12
|
+
def self.included(base)
|
13
|
+
methods = base.methods
|
14
|
+
# avoid including in classes thats doen't have methods, used in
|
15
|
+
# inplementation
|
16
|
+
REQUIRED_METHODS.all? { |m| methods.include?(m) } || fail(
|
17
|
+
TypeError,
|
18
|
+
"#{self.class.name} can't be included into #{base.class.name}"
|
19
|
+
)
|
20
|
+
end
|
21
|
+
#
|
22
|
+
# Extracts elements from array by conditions, passed in arguments nad
|
23
|
+
# returns theese elements as new array.
|
24
|
+
#
|
25
|
+
# Condition can be Regexp, class, Array and any other value. If condition
|
26
|
+
# is `Regexp`, all elements of array are tested for matching to this
|
27
|
+
# regexp, previously converted to String by their `to_s` method. If
|
28
|
+
# condition is an `Array`, all elements tested if it included in these
|
29
|
+
# array. If the condition is a class, then elements are tested via `is_a?`
|
30
|
+
# method for this class. For any other value, elements are tested with
|
31
|
+
# equality operator `==`.
|
32
|
+
#
|
33
|
+
# You can provide a block. In this case, all arguments are ignored, and
|
34
|
+
# block yielded for each element of array. If block returns `true`,
|
35
|
+
# element extracted from array.
|
36
|
+
#
|
37
|
+
# All conditions, passed as arguments are `or`-ed so `String, Symbol` means
|
38
|
+
# select Symbol or String elements.
|
39
|
+
#
|
40
|
+
# @overload extract!([condition, ..., options])
|
41
|
+
# @param [Object] condition one of `or`-ed conditions for comparing
|
42
|
+
# @param [Hash] options options for axtracting
|
43
|
+
# @options options [Object, Array] :and one or array of `and`-ed conditions
|
44
|
+
#
|
45
|
+
# @overload extract!(&block)
|
46
|
+
# @yield [element] Gives each element of array to block. You should return
|
47
|
+
# `true` to extract this element or `false` to keep it in array.
|
48
|
+
# @yieldparam [Object] element element of array to inspect
|
49
|
+
# @yieldreturn [Boolean] whether exclude this element or not
|
50
|
+
#
|
51
|
+
# @return [Array] array of extracted elements
|
52
|
+
#
|
53
|
+
# @example extract by class
|
54
|
+
# arr = [1, 2, 3, 'and', 'string']
|
55
|
+
# arr.extend WrapIt::ArgumentsArray
|
56
|
+
# arr.extract(String) #=> ['and', 'string']
|
57
|
+
# arr #=> [1, 2, 3]
|
58
|
+
#
|
59
|
+
# @example extract by value
|
60
|
+
# arr = [1, 2, 3, 'and', 'string']
|
61
|
+
# arr.extend WrapIt::ArgumentsArray
|
62
|
+
# arr.extract(1, 2) #=> [1, 2]
|
63
|
+
# arr #=> [3, 'and', 'string']
|
64
|
+
#
|
65
|
+
# @example extract by Regexp
|
66
|
+
# arr = [1, 2, 3, 'and', 'string', :str]
|
67
|
+
# arr.extend WrapIt::ArgumentsArray
|
68
|
+
# arr.extract(/^str/) #=> ['string', :str]
|
69
|
+
# arr #=> [1, 2, 3, 'and']
|
70
|
+
#
|
71
|
+
# @example extract by Array
|
72
|
+
# arr = [1, 2, 3, 'and', 'string']
|
73
|
+
# arr.extend WrapIt::ArgumentsArray
|
74
|
+
# arr.extract([1, 10, 'and']) #=> [1, 'and']
|
75
|
+
# arr #=> [2, 3, 'string']
|
76
|
+
#
|
77
|
+
# @example extract by block
|
78
|
+
# arr = [1, 2, 3, 'and', 'string']
|
79
|
+
# arr.extend WrapIt::ArgumentsArray
|
80
|
+
# arr.extract {|x| x < 3} #=> [1, 2]
|
81
|
+
# arr #=> [3, 'and', 'string']
|
82
|
+
#
|
83
|
+
# @example extract with `and` condition
|
84
|
+
# arr = [1, 2, 3, 'and', 'string', :str]
|
85
|
+
# arr.extend WrapIt::ArgumentsArray
|
86
|
+
# arr.extract(String, and: [/^str/]) #=> ['string']
|
87
|
+
# arr #=> [1, 2, 3, 'and', :str]
|
88
|
+
def extract!(*args, &block)
|
89
|
+
extracted = []
|
90
|
+
reject! do |arg|
|
91
|
+
do_compare(arg, *args, &block) && extracted << arg && true
|
92
|
+
end
|
93
|
+
extracted
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Extracts first element from array that is satisfy conditions, passed in
|
98
|
+
# arguments and returns these element.
|
99
|
+
#
|
100
|
+
# @see #extract!
|
101
|
+
def extract_first!(*args, &block)
|
102
|
+
index = find_index { |arg| do_compare(arg, *args, &block) }
|
103
|
+
index.nil? ? nil : delete_at(index)
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def do_compare(target, *compare_args)
|
109
|
+
if block_given?
|
110
|
+
yield target
|
111
|
+
else
|
112
|
+
options = compare_args.extract_options!
|
113
|
+
result = compare_args.any? do |dest|
|
114
|
+
case
|
115
|
+
when dest.is_a?(Array) then dest.include?(target)
|
116
|
+
when dest.is_a?(Regexp) then dest.match(target.to_s)
|
117
|
+
when dest.is_a?(Class) then target.is_a?(dest)
|
118
|
+
else dest == target
|
119
|
+
end
|
120
|
+
end
|
121
|
+
if options[:and].is_a?(Array)
|
122
|
+
result &&= do_compare(target, *options[:and])
|
123
|
+
end
|
124
|
+
result
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/wrap_it/base.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
module WrapIt
|
2
|
+
#
|
3
|
+
# Base class for all HTML helper classes
|
4
|
+
#
|
5
|
+
# @author Alexey Ovchinnikov <alexiss@cybernetlab.ru>
|
6
|
+
#
|
7
|
+
class Base
|
8
|
+
include DerivedAttributes
|
9
|
+
include Callbacks
|
10
|
+
|
11
|
+
callback :initialize, :capture, :render
|
12
|
+
|
13
|
+
include HTMLClass
|
14
|
+
include Switches
|
15
|
+
include Enums
|
16
|
+
include Renderer
|
17
|
+
|
18
|
+
@omit_content = false
|
19
|
+
|
20
|
+
attr_reader :tag
|
21
|
+
attr_reader :options
|
22
|
+
|
23
|
+
def initialize(template, *args, &block)
|
24
|
+
@template, @arguments, @block = template, args, block
|
25
|
+
self.options = @arguments.extract_options!
|
26
|
+
@arguments.extend ArgumentsArray
|
27
|
+
add_default_classes
|
28
|
+
run_callbacks :initialize do
|
29
|
+
@tag = @options.delete(:tag) ||
|
30
|
+
self.class.get_derived(:@default_tag) || 'div'
|
31
|
+
@helper_name = @options.delete(:helper_name)
|
32
|
+
@helper_name.is_a?(String) && @helper_name = @helper_name.to_sym
|
33
|
+
end
|
34
|
+
@argument = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def omit_content?
|
38
|
+
self.class.get_derived(:@omit_content)
|
39
|
+
end
|
40
|
+
|
41
|
+
def render(*args, &render_block)
|
42
|
+
# return cached copy if it available
|
43
|
+
return @content unless @content.nil?
|
44
|
+
@content = empty_html
|
45
|
+
|
46
|
+
# capture content from block
|
47
|
+
do_capture
|
48
|
+
# add to content string args and block result if its present
|
49
|
+
args.flatten.each { |a| @content << a if a.is_a? String }
|
50
|
+
block_given? && @content << instance_exec(self, &render_block)
|
51
|
+
|
52
|
+
# cleanup options from empty values
|
53
|
+
@options.select! { |k, v| !v.nil? && !v.empty? }
|
54
|
+
# render element
|
55
|
+
run_callbacks :render do
|
56
|
+
@content = content_tag(@tag, @content, @options)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @content = @wrapper.render(@content.html_safe) if @wrapper.is_a?(Base)
|
60
|
+
if @template.output_buffer.nil?
|
61
|
+
# when render called from code, just return content as a String
|
62
|
+
@content
|
63
|
+
else
|
64
|
+
# in template context, write content to templates buffer
|
65
|
+
concat(@content)
|
66
|
+
empty_html
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
#
|
73
|
+
# @dsl
|
74
|
+
# Defines default tag name for element. This tag can be changed soon.
|
75
|
+
# @param name [<Symbol, String>] Tag name. Converted to `String`.
|
76
|
+
#
|
77
|
+
# @return [void]
|
78
|
+
def self.default_tag(name)
|
79
|
+
name.is_a?(String) || name.is_a?(Symbol) ||
|
80
|
+
fail(ArgumentError, 'Tag name should be a String or Symbol')
|
81
|
+
@default_tag = name.to_s
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.omit_content
|
85
|
+
@omit_content = true
|
86
|
+
end
|
87
|
+
|
88
|
+
def options=(hash)
|
89
|
+
hash.is_a?(Hash) || return
|
90
|
+
hash.symbolize_keys!
|
91
|
+
|
92
|
+
# sanitize class
|
93
|
+
hash[:class] ||= []
|
94
|
+
hash[:class] = [hash[:class]] unless hash[:class].is_a?(Array)
|
95
|
+
hash[:class] = hash[:class].map { |c| c.to_s }.uniq
|
96
|
+
@options = hash
|
97
|
+
end
|
98
|
+
|
99
|
+
def do_capture
|
100
|
+
run_callbacks :capture do
|
101
|
+
@content ||= empty_html
|
102
|
+
unless @block.nil? || omit_content?
|
103
|
+
@content << (capture(self, &@block) || empty_html)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module WrapIt
|
2
|
+
#
|
3
|
+
# Callbacks implementation
|
4
|
+
#
|
5
|
+
# @author Alexey Ovchinnikov <alexiss@cybernetlab.ru>
|
6
|
+
#
|
7
|
+
module Callbacks
|
8
|
+
def self.included(base)
|
9
|
+
extend DerivedAttributes
|
10
|
+
base.extend ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
def run_callbacks(name)
|
14
|
+
self.class.collect_derived("@before_#{name}".to_sym).each do |cb|
|
15
|
+
if cb.is_a?(Symbol)
|
16
|
+
send(cb)# if respond_to?(cb)
|
17
|
+
else
|
18
|
+
instance_eval(&cb)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
yield if block_given?
|
22
|
+
self.class.collect_derived("@after_#{name}".to_sym).reverse.each do |cb|
|
23
|
+
if cb.is_a?(Symbol)
|
24
|
+
send(cb)# if respond_to?(cb)
|
25
|
+
else
|
26
|
+
instance_eval(&cb)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Class methods to include
|
33
|
+
#
|
34
|
+
module ClassMethods
|
35
|
+
def callback(*args)
|
36
|
+
args.each do |name|
|
37
|
+
instance_eval(&Callbacks.define_callback(:before, name))
|
38
|
+
instance_eval(&Callbacks.define_callback(:after, name))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def self.define_callback(time, name)
|
46
|
+
m_name = "#{time}_#{name}".to_sym
|
47
|
+
var = "@#{m_name}".to_sym
|
48
|
+
proc do
|
49
|
+
define_singleton_method(m_name) do |method = nil, &block|
|
50
|
+
return if block.nil? && !method.is_a?(Symbol)
|
51
|
+
arr =
|
52
|
+
if instance_variable_defined?(var)
|
53
|
+
instance_variable_get(var)
|
54
|
+
else
|
55
|
+
instance_variable_set(var, [])
|
56
|
+
end
|
57
|
+
arr << (block || method)
|
58
|
+
instance_variable_set(var, arr)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|