roda-tags 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +24 -0
- data/.github/workflows/ruby.yml +45 -0
- data/.gitignore +1 -1
- data/.rubocop.yml +33 -0
- data/.rubocop_todo.yml +7 -0
- data/CODE_OF_CONDUCT.md +22 -16
- data/Gemfile +86 -0
- data/Guardfile +25 -0
- data/README.md +234 -236
- data/Rakefile +14 -18
- data/lib/core_ext/blank.rb +37 -36
- data/lib/core_ext/hash.rb +39 -16
- data/lib/core_ext/object.rb +2 -2
- data/lib/core_ext/string.rb +290 -116
- data/lib/roda/plugins/tag_helpers.rb +795 -575
- data/lib/roda/plugins/tags.rb +531 -275
- data/lib/roda/tags/version.rb +2 -3
- data/lib/roda/tags.rb +2 -0
- data/roda-tags.gemspec +22 -26
- metadata +44 -141
- data/.travis.yml +0 -4
data/Rakefile
CHANGED
@@ -1,28 +1,24 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rubocop/rake_task'
|
5
|
+
require 'rake/testtask'
|
6
|
+
|
7
|
+
RuboCop::RakeTask.new
|
3
8
|
|
4
9
|
Rake::TestTask.new(:spec) do |t|
|
5
|
-
t.libs <<
|
6
|
-
t.libs <<
|
10
|
+
t.libs << 'spec'
|
11
|
+
t.libs << 'lib'
|
7
12
|
t.test_files = FileList['spec/**/*_spec.rb']
|
8
13
|
end
|
9
14
|
|
10
|
-
task :
|
15
|
+
task default: %i[rubocop coverage]
|
16
|
+
|
17
|
+
desc 'alias for spec task'
|
18
|
+
task test: :spec
|
11
19
|
|
12
|
-
desc
|
20
|
+
desc 'Run specs with coverage'
|
13
21
|
task :coverage do
|
14
22
|
ENV['COVERAGE'] = '1'
|
15
23
|
Rake::Task['spec'].invoke
|
16
|
-
# `open coverage/index.html` # if OSX
|
17
|
-
end
|
18
|
-
|
19
|
-
desc 'Run Rubocop report'
|
20
|
-
task :rubocop do
|
21
|
-
res = `which rubocop`
|
22
|
-
if res != ""
|
23
|
-
`rubocop -f html -o ./rubocop/report.html lib/`
|
24
|
-
# `open rubocop/report.html` # if OSX
|
25
|
-
else
|
26
|
-
puts "\nERROR: 'rubocop' gem is not installed or available. Please install with 'gem install rubocop'."
|
27
|
-
end
|
28
24
|
end
|
data/lib/core_ext/blank.rb
CHANGED
@@ -1,33 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
# reopening Object class
|
3
4
|
class Object
|
4
|
-
#
|
5
|
-
#
|
5
|
+
# Checks if an object is blank or not.
|
6
|
+
# An object is blank if it does not respond to empty? or if it returns false on calling empty?.
|
7
|
+
# If it does not respond to empty?, then it will check if the object is truthy.
|
6
8
|
#
|
7
|
-
# This simplifies
|
9
|
+
# This simplifies `!address || address.empty?` to `address.blank?`
|
8
10
|
#
|
9
|
-
#
|
11
|
+
# @return [true, false] false if object responds to empty? and
|
12
|
+
# empty? returns false, true otherwise
|
10
13
|
#
|
11
|
-
# to
|
12
|
-
#
|
13
|
-
# address.blank?
|
14
|
-
#
|
15
|
-
# @return [true, false]
|
16
14
|
def blank?
|
17
15
|
respond_to?(:empty?) ? !!empty? : !self
|
18
16
|
end
|
19
|
-
|
20
|
-
#
|
17
|
+
|
18
|
+
# Returns true if the object is not blank.
|
19
|
+
# An object is considered not blank if it has meaningful content.
|
20
|
+
#
|
21
|
+
# @return [true, false] true if object is not blank, false otherwise
|
21
22
|
#
|
22
|
-
# @return [true, false]
|
23
23
|
def present?
|
24
24
|
!blank?
|
25
25
|
end
|
26
|
-
|
27
|
-
# Returns the
|
28
|
-
#
|
26
|
+
|
27
|
+
# Returns self if the object is present, otherwise returns nil.
|
28
|
+
#
|
29
|
+
# @return [Object, nil] self if present?, nil otherwise
|
29
30
|
#
|
30
|
-
#
|
31
|
+
# `object.presence` is equivalent to `object.present? ? object : nil`
|
31
32
|
#
|
32
33
|
# For example, something like
|
33
34
|
#
|
@@ -39,7 +40,6 @@ class Object
|
|
39
40
|
#
|
40
41
|
# region = params[:state].presence || params[:country].presence || 'US'
|
41
42
|
#
|
42
|
-
# @return [Object]
|
43
43
|
def presence
|
44
44
|
self if present?
|
45
45
|
end
|
@@ -55,7 +55,6 @@ class NilClass
|
|
55
55
|
def blank?
|
56
56
|
true
|
57
57
|
end
|
58
|
-
|
59
58
|
end
|
60
59
|
|
61
60
|
# reopening FalseClass class
|
@@ -68,7 +67,6 @@ class FalseClass
|
|
68
67
|
def blank?
|
69
68
|
true
|
70
69
|
end
|
71
|
-
|
72
70
|
end
|
73
71
|
|
74
72
|
# reopening TrueClass class
|
@@ -81,7 +79,6 @@ class TrueClass
|
|
81
79
|
def blank?
|
82
80
|
false
|
83
81
|
end
|
84
|
-
|
85
82
|
end
|
86
83
|
|
87
84
|
# reopening Array class
|
@@ -92,8 +89,7 @@ class Array
|
|
92
89
|
# [1,2,3].blank? # => false
|
93
90
|
#
|
94
91
|
# @return [true, false]
|
95
|
-
|
96
|
-
|
92
|
+
alias blank? empty?
|
97
93
|
end
|
98
94
|
|
99
95
|
# reopening Hash class
|
@@ -104,55 +100,60 @@ class Hash
|
|
104
100
|
# { key: 'value' }.blank? # => false
|
105
101
|
#
|
106
102
|
# @return [true, false]
|
107
|
-
|
108
|
-
|
103
|
+
alias blank? empty?
|
109
104
|
end
|
110
105
|
|
111
106
|
# reopening String class
|
112
107
|
class String
|
113
108
|
BLANK_RE = /\A[[:space:]]*\z/
|
114
109
|
|
115
|
-
#
|
110
|
+
# Returns true if the string consists entirely of whitespace characters
|
111
|
+
#
|
112
|
+
# @return [true, false] true if string is empty or only whitespace, false otherwise
|
113
|
+
#
|
114
|
+
# @example A basic example
|
116
115
|
#
|
117
116
|
# ''.blank? # => true
|
118
117
|
# ' '.blank? # => true
|
119
118
|
# "\t\n\r".blank? # => true
|
120
119
|
# ' blah '.blank? # => false
|
121
120
|
#
|
122
|
-
# Unicode whitespace
|
121
|
+
# @example Unicode whitespace support
|
123
122
|
#
|
124
123
|
# "\u00a0".blank? # => true
|
125
124
|
#
|
126
|
-
# @return [true, false]
|
127
125
|
def blank?
|
128
126
|
BLANK_RE === self
|
129
127
|
end
|
130
|
-
|
131
128
|
end
|
132
129
|
|
133
130
|
# reopening Numeric class
|
134
|
-
class Numeric
|
135
|
-
# No
|
131
|
+
class Numeric # :nodoc:
|
132
|
+
# No numeric value is blank:
|
133
|
+
#
|
134
|
+
# @return [false]
|
135
|
+
#
|
136
|
+
# @example A basic example
|
136
137
|
#
|
137
138
|
# 1.blank? # => false
|
138
139
|
# 0.blank? # => false
|
139
140
|
#
|
140
|
-
# @return [false]
|
141
141
|
def blank?
|
142
142
|
false
|
143
143
|
end
|
144
|
-
|
145
144
|
end
|
146
145
|
|
147
146
|
# reopening Time class
|
148
|
-
class Time
|
149
|
-
# No Time is blank
|
147
|
+
class Time # :nodoc:
|
148
|
+
# No Time is blank
|
149
|
+
#
|
150
|
+
# @return [false]
|
151
|
+
#
|
152
|
+
# @example A basic example
|
150
153
|
#
|
151
154
|
# Time.now.blank? # => false
|
152
155
|
#
|
153
|
-
# @return [false]
|
154
156
|
def blank?
|
155
157
|
false
|
156
158
|
end
|
157
|
-
|
158
159
|
end
|
data/lib/core_ext/hash.rb
CHANGED
@@ -1,23 +1,40 @@
|
|
1
|
-
# :
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
# :stopdoc:
|
2
4
|
class Hash
|
3
|
-
|
4
5
|
# remove any other version of #to_html_attributes
|
5
6
|
undef_method :to_html_attributes if method_defined?(:to_html_attributes)
|
6
|
-
|
7
|
+
|
8
|
+
# Converts a hash into HTML attribute string representation.
|
9
|
+
#
|
10
|
+
# @param empties [Boolean, nil] If provided and not nil, will exclude keys with blank values
|
11
|
+
#
|
12
|
+
# @return [String] HTML attribute string with keys sorted alphabetically
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# {class: 'button', id: 'submit'}.to_html_attributes #=> 'class="button" id="submit"'
|
16
|
+
# {name: nil, id: 'test'}.to_html_attributes(true) #=> 'id="test"'
|
17
|
+
#
|
7
18
|
def to_html_attributes(empties = nil)
|
8
|
-
hash =
|
19
|
+
hash = dup
|
9
20
|
hash.reject! { |_k, v| v.blank? } unless empties.nil?
|
10
21
|
out = ''
|
11
|
-
hash.keys.sort.each do |key|
|
22
|
+
hash.keys.sort.each do |key| # NB!! sorting output order of attributes alphabetically
|
12
23
|
val = hash[key].is_a?(Array) ? hash[key].join('_') : hash[key].to_s
|
13
24
|
out << "#{key}=\"#{val}\" "
|
14
25
|
end
|
15
26
|
out.strip
|
16
27
|
end
|
17
|
-
|
18
|
-
|
28
|
+
|
19
29
|
unless method_defined?(:reverse_merge)
|
20
|
-
#
|
30
|
+
# Performs a non-destructive reverse merge with another hash
|
31
|
+
# This is particularly useful for initializing an options hash with default values.
|
32
|
+
#
|
33
|
+
# @param other_hash [Hash] The hash to merge into
|
34
|
+
#
|
35
|
+
# @return [Hash] A new hash with other_hash merged into self
|
36
|
+
#
|
37
|
+
# @example A basic example
|
21
38
|
#
|
22
39
|
# options = options.reverse_merge(size: 25, velocity: 10)
|
23
40
|
#
|
@@ -25,23 +42,29 @@ class Hash
|
|
25
42
|
#
|
26
43
|
# options = { size: 25, velocity: 10 }.merge(options)
|
27
44
|
#
|
28
|
-
# This is particularly useful for initializing an options hash
|
29
|
-
# with default values.
|
30
45
|
def reverse_merge(other_hash)
|
31
46
|
other_hash.merge(self)
|
32
47
|
end
|
33
48
|
end
|
34
|
-
|
49
|
+
|
35
50
|
unless method_defined?(:reverse_merge!)
|
36
|
-
|
37
|
-
#
|
51
|
+
# Performs a destructive reverse merge with another hash.
|
52
|
+
# Modifies the original hash by merging in the provided hash while keeping existing values.
|
53
|
+
#
|
54
|
+
# @param other_hash [Hash] The hash to merge into self
|
55
|
+
#
|
56
|
+
# @return [Hash] The modified hash with other_hash merged in
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
# options = { size: 10 }
|
60
|
+
# options.reverse_merge!(size: 25, velocity: 10)
|
61
|
+
# # => { size: 10, velocity: 10 }
|
62
|
+
#
|
38
63
|
def reverse_merge!(other_hash)
|
39
64
|
# right wins if there is no left
|
40
65
|
merge!(other_hash) { |_key, left, _right| left }
|
41
66
|
end
|
42
|
-
|
43
|
-
|
67
|
+
alias reverse_update reverse_merge!
|
44
68
|
end
|
45
|
-
|
46
69
|
end
|
47
70
|
# :startdoc:
|
data/lib/core_ext/object.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
|
2
3
|
# reopening Object class
|
3
4
|
class Object
|
@@ -25,7 +26,6 @@ class Object
|
|
25
26
|
#
|
26
27
|
# @return [Object]
|
27
28
|
def presence_in(another_object)
|
28
|
-
|
29
|
+
in?(another_object) ? self : nil
|
29
30
|
end
|
30
|
-
|
31
31
|
end
|