wrap_it 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/.yardopts +3 -0
- data/README.md +67 -66
- data/lib/wrap_it.rb +16 -16
- data/lib/wrap_it/arguments.rb +368 -0
- data/lib/wrap_it/base.rb +56 -47
- data/lib/wrap_it/callbacks.rb +24 -5
- data/lib/wrap_it/capture_array.rb +140 -0
- data/lib/wrap_it/container.rb +69 -25
- data/lib/wrap_it/derived_attributes.rb +22 -6
- data/lib/wrap_it/enums.rb +44 -34
- data/lib/wrap_it/frameworks.rb +7 -3
- data/lib/wrap_it/helpers.rb +66 -1
- data/lib/wrap_it/html.rb +149 -0
- data/lib/wrap_it/html_class.rb +164 -183
- data/lib/wrap_it/html_data.rb +28 -15
- data/lib/wrap_it/link.rb +40 -17
- data/lib/wrap_it/sections.rb +90 -2
- data/lib/wrap_it/switches.rb +33 -29
- data/lib/wrap_it/text_container.rb +83 -10
- data/lib/wrap_it/version.rb +2 -1
- data/spec/frameworks/log/development.log +2108 -0
- data/spec/integration/base_spec.rb +2 -2
- data/spec/integration/container_spec.rb +3 -3
- data/spec/integration/examples_spec.rb +16 -15
- data/spec/integration/text_container_spec.rb +3 -3
- data/spec/lib/arguments_array_spec.rb +37 -27
- data/spec/lib/arguments_spec.rb +153 -0
- data/spec/lib/base_spec.rb +2 -25
- data/spec/lib/callbacks_spec.rb +1 -1
- data/spec/lib/container_spec.rb +1 -1
- data/spec/lib/derived_attributes_spec.rb +1 -1
- data/spec/lib/enums_spec.rb +2 -3
- data/spec/lib/html_class_spec.rb +269 -80
- data/spec/lib/html_data_spec.rb +18 -12
- data/spec/lib/html_spec.rb +124 -0
- data/spec/lib/link_spec.rb +2 -2
- data/spec/lib/sections_spec.rb +1 -1
- data/spec/lib/switches_spec.rb +3 -3
- data/spec/lib/text_container_spec.rb +2 -2
- data/spec/support/example_groups/{wrap_it_example_group.rb → wrapped_example_group.rb} +5 -5
- data/wrap_it.gemspec +2 -0
- metadata +15 -8
- data/lib/wrap_it/arguments_array.rb +0 -128
- data/lib/wrap_it/module_helpers.rb +0 -23
@@ -5,33 +5,49 @@ module WrapIt
|
|
5
5
|
# @author Alexey Ovchinnikov <alexiss@cybernetlab.ru>
|
6
6
|
#
|
7
7
|
module DerivedAttributes
|
8
|
+
# Documentation includes
|
9
|
+
# @!parse extend DerivedAttributes::ClassMethods
|
10
|
+
|
11
|
+
# module implementation
|
12
|
+
|
13
|
+
#
|
8
14
|
def self.included(base)
|
9
15
|
base.extend ClassMethods
|
10
16
|
end
|
11
17
|
|
12
18
|
#
|
13
|
-
#
|
19
|
+
# {DerivedAttributes} class methods
|
14
20
|
#
|
15
21
|
module ClassMethods
|
22
|
+
#
|
23
|
+
# retrieves first founded derived variable or nil
|
24
|
+
# @param name [Symbol] variable name (should contain `@` sign)
|
25
|
+
#
|
26
|
+
# @return [Object, nil] founded variable or nil
|
16
27
|
def get_derived(name)
|
17
28
|
return instance_variable_get(name) if instance_variable_defined?(name)
|
18
29
|
ancestors.each do |ancestor|
|
19
|
-
break if ancestor == Object
|
20
30
|
next unless ancestor.instance_variable_defined?(name)
|
31
|
+
break if ancestor == Base
|
21
32
|
return ancestor.instance_variable_get(name)
|
22
33
|
end
|
23
34
|
nil
|
24
35
|
end
|
25
36
|
|
37
|
+
#
|
38
|
+
# Collects all derived variables with specified name
|
39
|
+
# @param name [Symbol] variable name (should contain `@` sign)
|
40
|
+
# @param initial [Object] initial collection object
|
41
|
+
# @param method [Symbol] collection's method name to concatinate
|
42
|
+
# founded variable with collection
|
43
|
+
#
|
44
|
+
# @return [Object] collection of variables
|
26
45
|
def collect_derived(name, initial = [], method = :concat)
|
27
46
|
result = initial
|
28
|
-
# if instance_variable_defined?(name)
|
29
|
-
# result = result.send(method, instance_variable_get(name))
|
30
|
-
# end
|
31
47
|
ancestors.each do |ancestor|
|
32
|
-
break if ancestor == Object
|
33
48
|
next unless ancestor.instance_variable_defined?(name)
|
34
49
|
result = result.send(method, ancestor.instance_variable_get(name))
|
50
|
+
break if ancestor == Base
|
35
51
|
end
|
36
52
|
result
|
37
53
|
end
|
data/lib/wrap_it/enums.rb
CHANGED
@@ -5,47 +5,38 @@ module WrapIt
|
|
5
5
|
# @author Alexey Ovchinnikov <alexiss@cybernetlab.ru>
|
6
6
|
#
|
7
7
|
module Enums
|
8
|
+
# Documentation includes
|
9
|
+
# @!parse extend Enums::ClassMethods
|
10
|
+
|
11
|
+
# module implementation
|
12
|
+
|
8
13
|
extend DerivedAttributes
|
9
14
|
|
15
|
+
#
|
10
16
|
def self.included(base)
|
11
17
|
base == Base || fail(
|
12
18
|
TypeError,
|
13
19
|
"#{self.class.name} can be included only into WrapIt::Base"
|
14
20
|
)
|
15
|
-
base.
|
16
|
-
|
17
|
-
end
|
21
|
+
base.class_eval do
|
22
|
+
extend ClassMethods
|
18
23
|
|
19
|
-
|
24
|
+
before_initialize { @enums = {} }
|
20
25
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
names = [name] + [opts[:aliases] || []].flatten
|
27
|
-
opt_keys.select { |o| names.include? o }.each do |key|
|
28
|
-
tmp = @options.delete(key)
|
29
|
-
value ||= tmp
|
30
|
-
!value.nil? && !opts[:values].include?(value) && value = nil
|
31
|
-
end
|
32
|
-
@arguments.extract!(Symbol, and: [opts[:values]]).each do |key|
|
33
|
-
value ||= key
|
26
|
+
before_capture do
|
27
|
+
self.class.collect_derived(:@enums, {}, :merge).each do |name, e|
|
28
|
+
next unless e.key?(:default) && !@enums.key?(name)
|
29
|
+
send("#{name}=", e[:default])
|
30
|
+
end
|
34
31
|
end
|
35
|
-
send("#{name}=", value)
|
36
32
|
end
|
37
33
|
end
|
38
34
|
|
39
|
-
def enums
|
40
|
-
@enums_hash ||= self.class.collect_derived(:@enums, {}, :merge)
|
41
|
-
end
|
42
|
-
|
43
35
|
#
|
44
|
-
#
|
36
|
+
# {Enums} class methods
|
45
37
|
#
|
46
38
|
module ClassMethods
|
47
39
|
#
|
48
|
-
# @dsl
|
49
40
|
# Adds `enum`. When element created, creation arguments will be scanned
|
50
41
|
# for `Symbol`, that included contains in `values`. If it founded, enum
|
51
42
|
# takes this value. Also creation options inspected. If its contains
|
@@ -60,16 +51,26 @@ module WrapIt
|
|
60
51
|
#
|
61
52
|
# This method also adds getter and setter for this enum.
|
62
53
|
#
|
54
|
+
# @example
|
55
|
+
# class Button < WrapIt::Base
|
56
|
+
# enum :style, %i(red green black), html_class_prefix: 'btn-'
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# btn = Button.new(template, :green)
|
60
|
+
# btn.render # => '<div class="btn-green">'
|
61
|
+
# btn = Button.new(template, style: :red)
|
62
|
+
# btn.render # => '<div class="btn-red">'
|
63
|
+
#
|
63
64
|
# @param name [String, Symbol] Enum name. Converted to `Symbol`.
|
64
|
-
# @param
|
65
|
-
# @
|
65
|
+
# @param opts [Hash] Enum options
|
66
|
+
# @option opts [String, Symbol] :html_class_prefix prefix of HTML
|
66
67
|
# class that will automatically added to element if enum changes its
|
67
68
|
# value.
|
68
|
-
# @
|
69
|
+
# @option opts [Boolean] :html_class whether this enum changes
|
69
70
|
# should affect to html class.
|
70
|
-
# @
|
71
|
+
# @option opts [Symbol, Array<Symbol>] :aliases list of enum aliases.
|
71
72
|
# Warning! Values are not converted - pass only `Symbols` here.
|
72
|
-
# @
|
73
|
+
# @option opts [String, Symbol] :default default value for enum,
|
73
74
|
# if nil or wrong value given. Converted to `Symbol`.
|
74
75
|
# @yield [value] Runs block when enum value changed, gives it to block.
|
75
76
|
# @yieldparam value [Symbol] New enum value.
|
@@ -90,25 +91,34 @@ module WrapIt
|
|
90
91
|
opts[:regexp] = /\A#{prefix}(?:#{values.join('|')})\z/
|
91
92
|
opts[:html_class_prefix] = prefix
|
92
93
|
end
|
93
|
-
define_method("#{name}") { @enums[name] }
|
94
|
+
define_method("#{name}") { @enums[name] ||= opts[:default] }
|
94
95
|
define_method("#{name}=", &Enums.setter(name, &block))
|
95
96
|
@enums ||= {}
|
97
|
+
|
98
|
+
o_params = {}
|
99
|
+
if opts.key?(:aliases)
|
100
|
+
aliases = [opts[:aliases]].flatten.compact
|
101
|
+
o_params[:if] = [name] + aliases
|
102
|
+
end
|
103
|
+
|
96
104
|
@enums[name] = opts
|
105
|
+
option(name, **o_params) { |_, v| send("#{name}=", v) }
|
106
|
+
argument(name, if: Symbol, and: values) { |_, v| send("#{name}=", v) }
|
97
107
|
end
|
98
108
|
end
|
99
109
|
|
100
110
|
private
|
101
111
|
|
102
112
|
def self.setter(name, &block)
|
103
|
-
|
104
|
-
opts = enums[name]
|
113
|
+
->(value) do
|
114
|
+
opts = self.class.collect_derived(:@enums, {}, :merge)[name]
|
105
115
|
v = value if opts[:values].include?(value)
|
106
116
|
v ||= opts[:default] if opts.key?(:default)
|
107
117
|
@enums[name] = v
|
108
118
|
block.nil? || instance_exec(v, &block)
|
109
119
|
if opts.key?(:regexp)
|
110
|
-
|
111
|
-
v.nil? ||
|
120
|
+
html_class.delete(opts[:regexp])
|
121
|
+
v.nil? || html_class << "#{opts[:html_class_prefix]}#{v}"
|
112
122
|
end
|
113
123
|
end
|
114
124
|
end
|
data/lib/wrap_it/frameworks.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
#
|
2
|
-
# Framework detection methods
|
3
|
-
#
|
4
1
|
module WrapIt
|
2
|
+
#
|
3
|
+
# Framework detection methods
|
4
|
+
#
|
5
|
+
|
6
|
+
# @private
|
5
7
|
def self.framework
|
6
8
|
return @framework unless @framework.nil?
|
7
9
|
gems = Gem.loaded_specs.keys
|
@@ -14,10 +16,12 @@ module WrapIt
|
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
19
|
+
# @private
|
17
20
|
def self.rails?
|
18
21
|
framework == :rails
|
19
22
|
end
|
20
23
|
|
24
|
+
# @private
|
21
25
|
def self.sinatra?
|
22
26
|
framework == :sinatra
|
23
27
|
end
|
data/lib/wrap_it/helpers.rb
CHANGED
@@ -1,9 +1,64 @@
|
|
1
1
|
#
|
2
|
-
#
|
2
|
+
# Registering helpers
|
3
|
+
#
|
4
|
+
# To use your classes and helpers in templates you should register your
|
5
|
+
# library. First, in your framework initialization, you should register
|
6
|
+
# your library in WrapIt. You can have separate module for it or WrapIt
|
7
|
+
# will make anonymous one. After this, your module will have `register`
|
8
|
+
# and `unregister` methods to register your classes.
|
9
|
+
#
|
10
|
+
# @example usual case - library in separate module
|
11
|
+
# # initialization time
|
12
|
+
# module Library
|
13
|
+
# module Helpers; end
|
14
|
+
# end
|
15
|
+
# WrapIt.register_module Library::Helpers, prefix: 'lib_'
|
16
|
+
#
|
17
|
+
# # controller
|
18
|
+
# class MyController < ApplicationController
|
19
|
+
# helper Library::Helpers
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # implementation
|
23
|
+
# module Library
|
24
|
+
# module Helpers
|
25
|
+
# class Button < WrapIt::Base
|
26
|
+
# ...
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# register :super_button, Button
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# # in template:
|
34
|
+
# <%= lib_super_button 'text' %>
|
35
|
+
#
|
36
|
+
# @example anonymous module
|
37
|
+
# helpers = WrapIt.register_module prefix: 'lib_'
|
38
|
+
#
|
39
|
+
# class Button < WrapIt::Base
|
40
|
+
# ...
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# helpers.register :super_button, Button
|
44
|
+
#
|
45
|
+
# class MyController
|
46
|
+
# helper helpers
|
47
|
+
# end
|
3
48
|
#
|
4
49
|
# @author Alexey Ovchinnikov <alexiss@cybernetlab.ru>
|
5
50
|
#
|
6
51
|
module WrapIt
|
52
|
+
#
|
53
|
+
# Registers helpers module
|
54
|
+
#
|
55
|
+
# @overload register_module(mod = nil, opts = {})
|
56
|
+
# @param mod [Module] module for register. Anonymous module will be
|
57
|
+
# created if ommited.
|
58
|
+
# @param opts [Hash] options
|
59
|
+
# @option opts [String] :prefix prefix for helper methods
|
60
|
+
#
|
61
|
+
# @return [void]
|
7
62
|
def self.register_module(*args)
|
8
63
|
options = args.extract_options!
|
9
64
|
options.symbolize_keys!
|
@@ -17,6 +72,16 @@ module WrapIt
|
|
17
72
|
mod
|
18
73
|
end
|
19
74
|
|
75
|
+
# @!method register([name, ...], class_name)
|
76
|
+
# adds to template list of helpers for creating elements of specified class
|
77
|
+
# @param name [Symbol, String] name of helper. Will be prefixed with prefix
|
78
|
+
# option, specified in {WrapIt#register_module} call.
|
79
|
+
# @param class_name [String, Class] element class
|
80
|
+
|
81
|
+
# @!method unregister([name, ...])
|
82
|
+
# removes list of helpers from template
|
83
|
+
# @param name [Symbol, String] name of helper to remove from tampate
|
84
|
+
|
20
85
|
private
|
21
86
|
|
22
87
|
def self.register_block(options)
|
data/lib/wrap_it/html.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require File.join %w(wrap_it html_class)
|
2
|
+
require File.join %w(wrap_it html_data)
|
3
|
+
|
4
|
+
module WrapIt
|
5
|
+
#
|
6
|
+
# Methods for manipulationg with HTML class. For internal usage.
|
7
|
+
# You should not include this class directly - subclass from
|
8
|
+
# `WrapIt::Base` instead.
|
9
|
+
#
|
10
|
+
# @author Alexey Ovchinnikov <alexiss@cybernetlab.ru>
|
11
|
+
#
|
12
|
+
module HTML
|
13
|
+
# Documentation includes
|
14
|
+
# @!parse extend HTML::ClassMethods
|
15
|
+
|
16
|
+
# module implementation
|
17
|
+
|
18
|
+
extend DerivedAttributes
|
19
|
+
|
20
|
+
#
|
21
|
+
def self.included(base)
|
22
|
+
base == Base || fail(
|
23
|
+
TypeError,
|
24
|
+
"#{self.class.name} can be included only into WrapIt::Base"
|
25
|
+
)
|
26
|
+
base.class_eval do
|
27
|
+
extend ClassMethods
|
28
|
+
|
29
|
+
option(:class) { |_, v| self.html_class << v }
|
30
|
+
|
31
|
+
# TODO: extend hashes for html_attr and html_data
|
32
|
+
before_initialize do
|
33
|
+
html_class
|
34
|
+
@html_attr ||= {}
|
35
|
+
@html_data ||= {}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO: actually we should have separate setter and merge (see Base)
|
41
|
+
#
|
42
|
+
# Sets HTML attributes hash.
|
43
|
+
#
|
44
|
+
# Actually it merges its with current
|
45
|
+
# attributes. To remove some attributes use `html_attr.delete(:attr)`.
|
46
|
+
# extracts HTML class and data from provided hash and places its to
|
47
|
+
# appropriate holder
|
48
|
+
#
|
49
|
+
# @param hash [Hash] attributes
|
50
|
+
#
|
51
|
+
# @return [Hash] resulting attributes
|
52
|
+
def html_attr=(hash)
|
53
|
+
return unless hash.is_a?(Hash)
|
54
|
+
hash.symbolize_keys!
|
55
|
+
html_class << hash.delete(:class)
|
56
|
+
html_data.merge(hash.delete(:data) || {})
|
57
|
+
(@html_attr ||= {}).merge!(hash)
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Retrieves HTML attributes hash (without HTML class and HTML data)
|
62
|
+
#
|
63
|
+
# @return [Hash] attributes
|
64
|
+
def html_attr
|
65
|
+
@html_attr ||= {}
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Retrieves HTML data hash
|
70
|
+
#
|
71
|
+
# @return [Hash] data
|
72
|
+
def html_data
|
73
|
+
@html_data ||= {}
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# HTML class prefix getter
|
78
|
+
#
|
79
|
+
# This prefix used in enums to combine HTML classes.
|
80
|
+
#
|
81
|
+
# @return [String] HTML class prefix.
|
82
|
+
def html_class_prefix
|
83
|
+
@html_class_prefix ||= self.class.html_class_prefix
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Sets HTML class(es) for element
|
88
|
+
#
|
89
|
+
# @example
|
90
|
+
# element.html_class = [:a, 'b', ['c', :d, 'a']]
|
91
|
+
# element.html_class #=> ['a', 'b', 'c', 'd']
|
92
|
+
#
|
93
|
+
# @param value [Symbol, String, Array<Symbol, String>] HTML class or list
|
94
|
+
# of classes. All classes will be converted to Strings, duplicates are
|
95
|
+
# removed. Refer to {HTMLClass} description for details.
|
96
|
+
# @return [HTMLClass] resulting html class
|
97
|
+
def html_class=(value)
|
98
|
+
@html_class = HTMLClass.new(value)
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Retrieves HTML class of element
|
103
|
+
#
|
104
|
+
# See {HTMLClass} for details
|
105
|
+
#
|
106
|
+
# @return [HTMLClass] HTML class of element
|
107
|
+
def html_class
|
108
|
+
@html_class ||= HTMLClass.new
|
109
|
+
end
|
110
|
+
|
111
|
+
protected
|
112
|
+
|
113
|
+
def add_default_classes
|
114
|
+
html_class << self.class.collect_derived(
|
115
|
+
:@html_class, HTMLClass.new, :<<
|
116
|
+
)
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# {HTML} class methods
|
121
|
+
#
|
122
|
+
module ClassMethods
|
123
|
+
#
|
124
|
+
# Adds default html classes, thats are automatically added when element
|
125
|
+
# created.
|
126
|
+
# @overload html_class([html_class, ...])
|
127
|
+
# @param html_class [String, Symbol, Array<String, Symbol>] HTML class.
|
128
|
+
# Converted to `String`
|
129
|
+
#
|
130
|
+
# @return [void]
|
131
|
+
def html_class(*args)
|
132
|
+
(@html_class ||= HTMLClass.new) << args
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# Sets HTML class prefix. It used in switchers and enums
|
137
|
+
# @param prefix [String] HTML class prefix
|
138
|
+
#
|
139
|
+
# @return [void]
|
140
|
+
def html_class_prefix(prefix = nil)
|
141
|
+
return(get_derived(:@html_class_prefix) || '') if prefix.nil?
|
142
|
+
prefix.is_a?(Symbol) && prefix = prefix.to_s
|
143
|
+
prefix.is_a?(String) || fail(ArgumentError,
|
144
|
+
'prefix should be a String or Symbol')
|
145
|
+
@html_class_prefix = prefix
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|