Module: StringWizard
- Defined in:
- lib/string_wizard.rb,
lib/string_wizard/version.rb,
lib/string_wizard/validator.rb,
lib/string_wizard/encryption.rb,
lib/string_wizard/transformer.rb,
lib/string_wizard/pattern_matcher.rb
Defined Under Namespace
Modules: Encryption, PatternMatcher, Transformer, Validator
Classes: EncryptionError, Error, PatternMatchError
Constant Summary
collapse
- VERSION =
"0.1.1"
Class Method Summary
collapse
-
.alternating_case(str) ⇒ Object
-
.analyze(str) ⇒ Object
Advanced string analysis.
-
.character_frequency(str) ⇒ Object
Memoized character frequency analysis.
-
.clear_cache ⇒ Object
-
.decrypt(encrypted_str, key, algorithm: 'AES-256-CBC') ⇒ Object
-
.encrypt(str, key, algorithm: 'AES-256-CBC') ⇒ Object
-
.hash(str, algorithm: :sha256) ⇒ Object
-
.match_pattern(str, pattern) ⇒ Object
-
.palindrome?(str) ⇒ Boolean
-
.remove_consonants(str) ⇒ Object
-
.remove_vowels(str) ⇒ Object
-
.reverse_words(str) ⇒ Object
-
.secure_compare(str1, str2) ⇒ Object
-
.similarity(str1, str2) ⇒ Object
String similarity methods.
-
.titleize(str) ⇒ Object
-
.transform(str, *transformations) ⇒ Object
String transformation chain.
-
.valid_credit_card?(str) ⇒ Boolean
-
.valid_date?(str, format: '%Y-%m-%d') ⇒ Boolean
-
.valid_email?(str) ⇒ Boolean
-
.valid_hex_color?(str) ⇒ Boolean
-
.valid_ip?(str) ⇒ Boolean
-
.valid_json?(str) ⇒ Boolean
-
.valid_phone?(str) ⇒ Boolean
-
.valid_time?(str) ⇒ Boolean
-
.valid_url?(str) ⇒ Boolean
-
.valid_xml?(str) ⇒ Boolean
Class Method Details
.alternating_case(str) ⇒ Object
37
38
39
40
41
|
# File 'lib/string_wizard.rb', line 37
def alternating_case(str)
str.chars.each_with_index.map do |char, index|
index.even? ? char.upcase : char.downcase
end.join
end
|
.analyze(str) ⇒ Object
48
49
50
51
52
53
54
55
56
57
58
59
60
|
# File 'lib/string_wizard.rb', line 48
def analyze(str)
{
length: str.length,
word_count: str.split.size,
character_frequency: character_frequency(str),
vowel_count: str.scan(/[aeiouAEIOU]/).size,
consonant_count: str.scan(/[^aeiouAEIOU\s\W]/).size,
digit_count: str.scan(/\d/).size,
special_char_count: str.scan(/[^a-zA-Z0-9\s]/).size,
entropy: calculate_entropy(str),
readability_score: calculate_readability(str)
}
end
|
.character_frequency(str) ⇒ Object
Memoized character frequency analysis
95
96
97
98
99
100
101
|
# File 'lib/string_wizard.rb', line 95
def character_frequency(str)
@memo_cache["frequency_#{str}"] ||= begin
frequency = Hash.new(0)
str.each_char { |char| frequency[char] += 1 }
frequency
end
end
|
.clear_cache ⇒ Object
104
105
106
|
# File 'lib/string_wizard.rb', line 104
def clear_cache
@memo_cache.clear
end
|
.decrypt(encrypted_str, key, algorithm: 'AES-256-CBC') ⇒ Object
124
125
126
|
# File 'lib/string_wizard.rb', line 124
def decrypt(encrypted_str, key, algorithm: 'AES-256-CBC')
Encryption.decrypt(encrypted_str, key, algorithm: algorithm)
end
|
.encrypt(str, key, algorithm: 'AES-256-CBC') ⇒ Object
120
121
122
|
# File 'lib/string_wizard.rb', line 120
def encrypt(str, key, algorithm: 'AES-256-CBC')
Encryption.encrypt(str, key, algorithm: algorithm)
end
|
.hash(str, algorithm: :sha256) ⇒ Object
128
129
130
|
# File 'lib/string_wizard.rb', line 128
def hash(str, algorithm: :sha256)
Encryption.hash(str, algorithm: algorithm)
end
|
.match_pattern(str, pattern) ⇒ Object
63
64
65
66
67
68
69
70
71
72
73
|
# File 'lib/string_wizard.rb', line 63
def match_pattern(str, pattern)
regex = pattern.is_a?(Regexp) ? pattern : Regexp.new(pattern)
match = regex.match(str)
return nil unless match
if match.named_captures.any?
match.named_captures
else
match.captures
end
end
|
.palindrome?(str) ⇒ Boolean
32
33
34
35
|
# File 'lib/string_wizard.rb', line 32
def palindrome?(str)
normalized = str.downcase.gsub(/[^a-z0-9]/, '')
normalized == normalized.reverse
end
|
.remove_consonants(str) ⇒ Object
28
29
30
|
# File 'lib/string_wizard.rb', line 28
def remove_consonants(str)
str.gsub(/[^aeiouAEIOU\s]/, '')
end
|
.remove_vowels(str) ⇒ Object
24
25
26
|
# File 'lib/string_wizard.rb', line 24
def remove_vowels(str)
str.gsub(/[aeiouAEIOU]/, '')
end
|
.reverse_words(str) ⇒ Object
43
44
45
|
# File 'lib/string_wizard.rb', line 43
def reverse_words(str)
str.split.reverse.join(' ')
end
|
.secure_compare(str1, str2) ⇒ Object
132
133
134
|
# File 'lib/string_wizard.rb', line 132
def secure_compare(str1, str2)
Encryption.secure_compare(str1, str2)
end
|
.similarity(str1, str2) ⇒ Object
String similarity methods
109
110
111
112
113
114
115
116
117
|
# File 'lib/string_wizard.rb', line 109
def similarity(str1, str2)
return 1.0 if str1 == str2
return 0.0 if str1.empty? || str2.empty?
distance = levenshtein_distance(str1, str2)
max_length = [str1.length, str2.length].max
1.0 - (distance.to_f / max_length)
end
|
.titleize(str) ⇒ Object
20
21
22
|
# File 'lib/string_wizard.rb', line 20
def titleize(str)
str.split.map(&:capitalize).join(' ')
end
|
String transformation chain
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/string_wizard.rb', line 76
def transform(str, *transformations)
transformations.inject(str) do |result, transformation|
case transformation
when :titleize then titleize(result)
when :upcase then result.upcase
when :downcase then result.downcase
when :reverse then result.reverse
when :strip then result.strip
when :remove_vowels then remove_vowels(result)
when :remove_consonants then remove_consonants(result)
when :alternating_case then alternating_case(result)
when :reverse_words then reverse_words(result)
else
raise Error, "Unknown transformation: #{transformation}"
end
end
end
|
.valid_credit_card?(str) ⇒ Boolean
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
# File 'lib/string_wizard.rb', line 165
def valid_credit_card?(str)
digits = str.gsub(/\D/, '').chars.map(&:to_i)
return false if digits.empty?
sum = 0
digits.reverse.each_with_index do |digit, index|
if index.odd?
doubled = digit * 2
sum += doubled > 9 ? doubled - 9 : doubled
else
sum += digit
end
end
(sum % 10).zero?
end
|
.valid_date?(str, format: '%Y-%m-%d') ⇒ Boolean
149
150
151
152
153
154
|
# File 'lib/string_wizard.rb', line 149
def valid_date?(str, format: '%Y-%m-%d')
Date.strptime(str, format)
true
rescue Date::Error
false
end
|
.valid_email?(str) ⇒ Boolean
137
138
139
|
# File 'lib/string_wizard.rb', line 137
def valid_email?(str)
str.match?(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i)
end
|
.valid_hex_color?(str) ⇒ Boolean
184
185
186
|
# File 'lib/string_wizard.rb', line 184
def valid_hex_color?(str)
str.match?(/\A#[0-9A-Fa-f]{6}\z/)
end
|
.valid_ip?(str) ⇒ Boolean
160
161
162
163
|
# File 'lib/string_wizard.rb', line 160
def valid_ip?(str)
str.match?(/\A(\d{1,3}\.){3}\d{1,3}\z/) &&
str.split('.').all? { |octet| octet.to_i.between?(0, 255) }
end
|
.valid_json?(str) ⇒ Boolean
188
189
190
191
192
193
|
# File 'lib/string_wizard.rb', line 188
def valid_json?(str)
JSON.parse(str)
true
rescue JSON::ParserError
false
end
|
.valid_phone?(str) ⇒ Boolean
145
146
147
|
# File 'lib/string_wizard.rb', line 145
def valid_phone?(str)
str.match?(/\A\+?[\d\s\-()]+\z/)
end
|
.valid_time?(str) ⇒ Boolean
156
157
158
|
# File 'lib/string_wizard.rb', line 156
def valid_time?(str)
str.match?(/\A([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?\z/)
end
|
.valid_url?(str) ⇒ Boolean
141
142
143
|
# File 'lib/string_wizard.rb', line 141
def valid_url?(str)
str.match?(/\Ahttps?:\/\/[\w\-]+(\.[\w\-]+)+[\/#?]?.*\z/i)
end
|
.valid_xml?(str) ⇒ Boolean
195
196
197
198
199
200
|
# File 'lib/string_wizard.rb', line 195
def valid_xml?(str)
Nokogiri::XML(str) { |config| config.strict }
true
rescue Nokogiri::XML::SyntaxError
false
end
|