roda-tags 0.1.1 → 0.2.0
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.
- checksums.yaml +5 -5
- 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 -11
- 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 +532 -276
- data/lib/roda/tags/version.rb +2 -3
- data/lib/roda/tags.rb +2 -0
- data/roda-tags.gemspec +30 -32
- metadata +44 -128
- data/.travis.yml +0 -4
data/Rakefile
CHANGED
@@ -1,21 +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
24
|
end
|
17
|
-
|
18
|
-
desc "Run Rubocop report"
|
19
|
-
task :rubocop do
|
20
|
-
`rubocop -f html -o ./Rubocop-report.html lib/`
|
21
|
-
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
|