activesupport 5.0.0 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +343 -590
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -4
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +11 -5
- data/lib/active_support/backtrace_cleaner.rb +33 -5
- data/lib/active_support/benchmarkable.rb +5 -3
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +45 -53
- data/lib/active_support/cache/mem_cache_store.rb +81 -79
- data/lib/active_support/cache/memory_store.rb +69 -41
- data/lib/active_support/cache/null_store.rb +11 -4
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +74 -37
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +332 -161
- data/lib/active_support/callbacks.rb +657 -586
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +59 -19
- data/lib/active_support/configurable.rb +15 -17
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +20 -18
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +3 -1
- data/lib/active_support/core_ext/array/inquiry.rb +3 -1
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +9 -7
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -49
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -26
- data/lib/active_support/core_ext/class.rb +4 -2
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +3 -1
- data/lib/active_support/core_ext/date/calculations.rb +16 -13
- data/lib/active_support/core_ext/date/conversions.rb +23 -21
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +7 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
- data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +3 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
- data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +165 -29
- data/lib/active_support/core_ext/file/atomic.rb +7 -5
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +40 -39
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
- data/lib/active_support/core_ext/hash/keys.rb +9 -36
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +10 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +3 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -4
- data/lib/active_support/core_ext/load_error.rb +2 -23
- data/lib/active_support/core_ext/marshal.rb +6 -2
- data/lib/active_support/core_ext/module/aliasing.rb +5 -48
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
- data/lib/active_support/core_ext/module/concerning.rb +16 -11
- data/lib/active_support/core_ext/module/delegation.rb +159 -44
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +23 -26
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +13 -12
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
- data/lib/active_support/core_ext/numeric/time.rb +18 -26
- data/lib/active_support/core_ext/numeric.rb +5 -4
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +14 -2
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
- data/lib/active_support/core_ext/object/duplicable.rb +13 -62
- data/lib/active_support/core_ext/object/inclusion.rb +3 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +42 -15
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +20 -8
- data/lib/active_support/core_ext/object/with_options.rb +15 -2
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +28 -6
- data/lib/active_support/core_ext/string/access.rb +9 -18
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +5 -2
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +47 -4
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +78 -29
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +10 -5
- data/lib/active_support/core_ext/string/output_safety.rb +86 -31
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +117 -45
- data/lib/active_support/core_ext/time/compatibility.rb +13 -2
- data/lib/active_support/core_ext/time/conversions.rb +18 -12
- data/lib/active_support/core_ext/time/zones.rb +9 -7
- data/lib/active_support/core_ext/time.rb +7 -5
- data/lib/active_support/core_ext/uri.rb +12 -7
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +208 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +7 -1
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +172 -98
- data/lib/active_support/deprecation/behaviors.rb +45 -13
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +32 -17
- data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
- data/lib/active_support/deprecation/reporting.rb +61 -16
- data/lib/active_support/deprecation.rb +17 -9
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +67 -66
- data/lib/active_support/duration/iso8601_serializer.rb +25 -17
- data/lib/active_support/duration.rb +349 -46
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +88 -112
- data/lib/active_support/execution_wrapper.rb +25 -13
- data/lib/active_support/executor.rb +3 -1
- data/lib/active_support/file_update_checker.rb +56 -51
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +4 -2
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +153 -49
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +30 -20
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +28 -15
- data/lib/active_support/inflector/methods.rb +120 -109
- data/lib/active_support/inflector/transliterate.rb +60 -25
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +30 -29
- data/lib/active_support/json/encoding.rb +22 -11
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +6 -36
- data/lib/active_support/lazy_load_hooks.rb +53 -20
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +11 -9
- data/lib/active_support/log_subscriber.rb +51 -18
- data/lib/active_support/logger.rb +9 -22
- data/lib/active_support/logger_silence.rb +14 -21
- data/lib/active_support/logger_thread_safe_level.rb +55 -8
- data/lib/active_support/message_encryptor.rb +170 -53
- data/lib/active_support/message_verifier.rb +91 -20
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +24 -78
- data/lib/active_support/multibyte/unicode.rb +21 -352
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +121 -19
- data/lib/active_support/notifications/instrumenter.rb +78 -14
- data/lib/active_support/notifications.rb +80 -12
- data/lib/active_support/number_helper/number_converter.rb +17 -16
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +45 -16
- data/lib/active_support/option_merger.rb +25 -4
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +23 -9
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +7 -5
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +8 -9
- data/lib/active_support/railtie.rb +62 -11
- data/lib/active_support/reloader.rb +12 -11
- data/lib/active_support/rescuable.rb +20 -11
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +12 -3
- data/lib/active_support/subscriber.rb +77 -23
- data/lib/active_support/tagged_logging.rb +52 -17
- data/lib/active_support/test_case.rb +106 -29
- data/lib/active_support/testing/assertions.rb +144 -8
- data/lib/active_support/testing/autorun.rb +5 -10
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +4 -2
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +19 -24
- data/lib/active_support/testing/method_call_assertions.rb +31 -2
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +30 -29
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +125 -24
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +142 -55
- data/lib/active_support/values/time_zone.rb +160 -53
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +115 -114
- data/lib/active_support/xml_mini/libxml.rb +15 -14
- data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
- data/lib/active_support/xml_mini/nokogiri.rb +13 -13
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
- data/lib/active_support/xml_mini/rexml.rb +18 -9
- data/lib/active_support/xml_mini.rb +44 -42
- data/lib/active_support.rb +19 -10
- metadata +79 -37
- data/lib/active_support/concurrency/latch.rb +0 -19
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -20
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/struct.rb +0 -3
- data/lib/active_support/core_ext/time/marshal.rb +0 -3
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,7 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/json"
|
4
|
+
require "active_support/core_ext/string/access"
|
5
|
+
require "active_support/core_ext/string/behavior"
|
6
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
7
|
+
require "active_support/core_ext/module/delegation"
|
5
8
|
|
6
9
|
module ActiveSupport #:nodoc:
|
7
10
|
module Multibyte #:nodoc:
|
@@ -15,7 +18,8 @@ module ActiveSupport #:nodoc:
|
|
15
18
|
# through the +mb_chars+ method. Methods which would normally return a
|
16
19
|
# String object now return a Chars object so methods can be chained.
|
17
20
|
#
|
18
|
-
# 'The Perfect String '.mb_chars.downcase.strip
|
21
|
+
# 'The Perfect String '.mb_chars.downcase.strip
|
22
|
+
# # => #<ActiveSupport::Multibyte::Chars:0x007fdc434ccc10 @wrapped_string="the perfect string">
|
19
23
|
#
|
20
24
|
# Chars objects are perfectly interchangeable with String objects as long as
|
21
25
|
# no explicit class checks are made. If certain methods do explicitly check
|
@@ -45,7 +49,7 @@ module ActiveSupport #:nodoc:
|
|
45
49
|
alias to_s wrapped_string
|
46
50
|
alias to_str wrapped_string
|
47
51
|
|
48
|
-
delegate :<=>, :=~, :acts_like_string?, :
|
52
|
+
delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
|
49
53
|
|
50
54
|
# Creates a new Chars instance by wrapping _string_.
|
51
55
|
def initialize(string)
|
@@ -56,7 +60,7 @@ module ActiveSupport #:nodoc:
|
|
56
60
|
# Forward all undefined methods to the wrapped string.
|
57
61
|
def method_missing(method, *args, &block)
|
58
62
|
result = @wrapped_string.__send__(method, *args, &block)
|
59
|
-
if method.
|
63
|
+
if method.end_with?("!")
|
60
64
|
self if result
|
61
65
|
else
|
62
66
|
result.kind_of?(String) ? chars(result) : result
|
@@ -70,12 +74,6 @@ module ActiveSupport #:nodoc:
|
|
70
74
|
@wrapped_string.respond_to?(method, include_private)
|
71
75
|
end
|
72
76
|
|
73
|
-
# Returns +true+ when the proxy class can handle the string. Returns
|
74
|
-
# +false+ otherwise.
|
75
|
-
def self.consumes?(string)
|
76
|
-
string.encoding == Encoding::UTF_8
|
77
|
-
end
|
78
|
-
|
79
77
|
# Works just like <tt>String#split</tt>, with the exception that the items
|
80
78
|
# in the resulting list are Chars instances instead of String. This makes
|
81
79
|
# chaining methods easier.
|
@@ -86,7 +84,7 @@ module ActiveSupport #:nodoc:
|
|
86
84
|
end
|
87
85
|
|
88
86
|
# Works like <tt>String#slice!</tt>, but returns an instance of
|
89
|
-
# Chars, or nil if the string was not modified. The string will not be
|
87
|
+
# Chars, or +nil+ if the string was not modified. The string will not be
|
90
88
|
# modified if the range given is out of bounds
|
91
89
|
#
|
92
90
|
# string = 'Welcome'
|
@@ -105,7 +103,7 @@ module ActiveSupport #:nodoc:
|
|
105
103
|
#
|
106
104
|
# 'Café'.mb_chars.reverse.to_s # => 'éfaC'
|
107
105
|
def reverse
|
108
|
-
chars(
|
106
|
+
chars(@wrapped_string.scan(/\X/).reverse.join)
|
109
107
|
end
|
110
108
|
|
111
109
|
# Limits the byte size of the string to a number of bytes without breaking
|
@@ -114,63 +112,24 @@ module ActiveSupport #:nodoc:
|
|
114
112
|
#
|
115
113
|
# 'こんにちは'.mb_chars.limit(7).to_s # => "こん"
|
116
114
|
def limit(limit)
|
117
|
-
|
118
|
-
end
|
119
|
-
|
120
|
-
# Converts characters in the string to uppercase.
|
121
|
-
#
|
122
|
-
# 'Laurent, où sont les tests ?'.mb_chars.upcase.to_s # => "LAURENT, OÙ SONT LES TESTS ?"
|
123
|
-
def upcase
|
124
|
-
chars Unicode.upcase(@wrapped_string)
|
125
|
-
end
|
126
|
-
|
127
|
-
# Converts characters in the string to lowercase.
|
128
|
-
#
|
129
|
-
# 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s # => "věda a výzkum"
|
130
|
-
def downcase
|
131
|
-
chars Unicode.downcase(@wrapped_string)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Converts characters in the string to the opposite case.
|
135
|
-
#
|
136
|
-
# 'El Cañón".mb_chars.swapcase.to_s # => "eL cAÑÓN"
|
137
|
-
def swapcase
|
138
|
-
chars Unicode.swapcase(@wrapped_string)
|
139
|
-
end
|
140
|
-
|
141
|
-
# Converts the first character to uppercase and the remainder to lowercase.
|
142
|
-
#
|
143
|
-
# 'über'.mb_chars.capitalize.to_s # => "Über"
|
144
|
-
def capitalize
|
145
|
-
(slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
|
115
|
+
chars(@wrapped_string.truncate_bytes(limit, omission: nil))
|
146
116
|
end
|
147
117
|
|
148
118
|
# Capitalizes the first letter of every word, when possible.
|
149
119
|
#
|
150
|
-
# "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró"
|
151
|
-
# "日本語".mb_chars.titleize
|
120
|
+
# "ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s # => "Él Que Se Enteró"
|
121
|
+
# "日本語".mb_chars.titleize.to_s # => "日本語"
|
152
122
|
def titleize
|
153
|
-
chars(downcase.to_s.gsub(/\b('?\S)/u) {
|
123
|
+
chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
|
154
124
|
end
|
155
125
|
alias_method :titlecase, :titleize
|
156
126
|
|
157
|
-
# Returns the KC normalization of the string by default. NFKC is
|
158
|
-
# considered the best normalization form for passing strings to databases
|
159
|
-
# and validations.
|
160
|
-
#
|
161
|
-
# * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
|
162
|
-
# <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
|
163
|
-
# ActiveSupport::Multibyte::Unicode.default_normalization_form
|
164
|
-
def normalize(form = nil)
|
165
|
-
chars(Unicode.normalize(@wrapped_string, form))
|
166
|
-
end
|
167
|
-
|
168
127
|
# Performs canonical decomposition on all the characters.
|
169
128
|
#
|
170
129
|
# 'é'.length # => 2
|
171
130
|
# 'é'.mb_chars.decompose.to_s.length # => 3
|
172
131
|
def decompose
|
173
|
-
chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack(
|
132
|
+
chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack("U*"))
|
174
133
|
end
|
175
134
|
|
176
135
|
# Performs composition on all the characters.
|
@@ -178,7 +137,7 @@ module ActiveSupport #:nodoc:
|
|
178
137
|
# 'é'.length # => 3
|
179
138
|
# 'é'.mb_chars.compose.to_s.length # => 2
|
180
139
|
def compose
|
181
|
-
chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack(
|
140
|
+
chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack("U*"))
|
182
141
|
end
|
183
142
|
|
184
143
|
# Returns the number of grapheme clusters in the string.
|
@@ -186,7 +145,7 @@ module ActiveSupport #:nodoc:
|
|
186
145
|
# 'क्षि'.mb_chars.length # => 4
|
187
146
|
# 'क्षि'.mb_chars.grapheme_length # => 3
|
188
147
|
def grapheme_length
|
189
|
-
|
148
|
+
@wrapped_string.scan(/\X/).length
|
190
149
|
end
|
191
150
|
|
192
151
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
|
@@ -202,28 +161,15 @@ module ActiveSupport #:nodoc:
|
|
202
161
|
to_s.as_json(options)
|
203
162
|
end
|
204
163
|
|
205
|
-
%w(
|
164
|
+
%w(reverse tidy_bytes).each do |method|
|
206
165
|
define_method("#{method}!") do |*args|
|
207
|
-
@wrapped_string =
|
166
|
+
@wrapped_string = public_send(method, *args).to_s
|
208
167
|
self
|
209
168
|
end
|
210
169
|
end
|
211
170
|
|
212
|
-
|
213
|
-
|
214
|
-
def translate_offset(byte_offset) #:nodoc:
|
215
|
-
return nil if byte_offset.nil?
|
216
|
-
return 0 if @wrapped_string == ''
|
217
|
-
|
218
|
-
begin
|
219
|
-
@wrapped_string.byteslice(0...byte_offset).unpack('U*').length
|
220
|
-
rescue ArgumentError
|
221
|
-
byte_offset -= 1
|
222
|
-
retry
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def chars(string) #:nodoc:
|
171
|
+
private
|
172
|
+
def chars(string)
|
227
173
|
self.class.new(string)
|
228
174
|
end
|
229
175
|
end
|
@@ -1,238 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
module Multibyte
|
3
5
|
module Unicode
|
4
|
-
|
5
6
|
extend self
|
6
7
|
|
7
|
-
# A list of all available normalization forms.
|
8
|
-
# See http://www.unicode.org/reports/tr15/tr15-29.html for more
|
9
|
-
# information about normalization.
|
10
|
-
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
|
11
|
-
|
12
8
|
# The Unicode version that is supported by the implementation
|
13
|
-
UNICODE_VERSION =
|
14
|
-
|
15
|
-
# The default normalization used for operations that require
|
16
|
-
# normalization. It can be set to any of the normalizations
|
17
|
-
# in NORMALIZATION_FORMS.
|
18
|
-
#
|
19
|
-
# ActiveSupport::Multibyte::Unicode.default_normalization_form = :c
|
20
|
-
attr_accessor :default_normalization_form
|
21
|
-
@default_normalization_form = :kc
|
22
|
-
|
23
|
-
# Hangul character boundaries and properties
|
24
|
-
HANGUL_SBASE = 0xAC00
|
25
|
-
HANGUL_LBASE = 0x1100
|
26
|
-
HANGUL_VBASE = 0x1161
|
27
|
-
HANGUL_TBASE = 0x11A7
|
28
|
-
HANGUL_LCOUNT = 19
|
29
|
-
HANGUL_VCOUNT = 21
|
30
|
-
HANGUL_TCOUNT = 28
|
31
|
-
HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
|
32
|
-
HANGUL_SCOUNT = 11172
|
33
|
-
HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
|
34
|
-
HANGUL_JAMO_FIRST = 0x1100
|
35
|
-
HANGUL_JAMO_LAST = 0x11FF
|
36
|
-
|
37
|
-
# All the unicode whitespace
|
38
|
-
WHITESPACE = [
|
39
|
-
(0x0009..0x000D).to_a, # White_Space # Cc [5] <control-0009>..<control-000D>
|
40
|
-
0x0020, # White_Space # Zs SPACE
|
41
|
-
0x0085, # White_Space # Cc <control-0085>
|
42
|
-
0x00A0, # White_Space # Zs NO-BREAK SPACE
|
43
|
-
0x1680, # White_Space # Zs OGHAM SPACE MARK
|
44
|
-
(0x2000..0x200A).to_a, # White_Space # Zs [11] EN QUAD..HAIR SPACE
|
45
|
-
0x2028, # White_Space # Zl LINE SEPARATOR
|
46
|
-
0x2029, # White_Space # Zp PARAGRAPH SEPARATOR
|
47
|
-
0x202F, # White_Space # Zs NARROW NO-BREAK SPACE
|
48
|
-
0x205F, # White_Space # Zs MEDIUM MATHEMATICAL SPACE
|
49
|
-
0x3000, # White_Space # Zs IDEOGRAPHIC SPACE
|
50
|
-
].flatten.freeze
|
51
|
-
|
52
|
-
# BOM (byte order mark) can also be seen as whitespace, it's a
|
53
|
-
# non-rendering character used to distinguish between little and big
|
54
|
-
# endian. This is not an issue in utf-8, so it must be ignored.
|
55
|
-
LEADERS_AND_TRAILERS = WHITESPACE + [65279] # ZERO-WIDTH NO-BREAK SPACE aka BOM
|
56
|
-
|
57
|
-
# Returns a regular expression pattern that matches the passed Unicode
|
58
|
-
# codepoints.
|
59
|
-
def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
|
60
|
-
array_of_codepoints.collect{ |e| [e].pack 'U*'.freeze }.join('|'.freeze)
|
61
|
-
end
|
62
|
-
TRAILERS_PAT = /(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+\Z/u
|
63
|
-
LEADERS_PAT = /\A(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+/u
|
64
|
-
|
65
|
-
# Detect whether the codepoint is in a certain character class. Returns
|
66
|
-
# +true+ when it's in the specified character class and +false+ otherwise.
|
67
|
-
# Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>,
|
68
|
-
# <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>.
|
69
|
-
#
|
70
|
-
# Primarily used by the grapheme cluster support.
|
71
|
-
def in_char_class?(codepoint, classes)
|
72
|
-
classes.detect { |c| database.boundary[c] === codepoint } ? true : false
|
73
|
-
end
|
74
|
-
|
75
|
-
# Unpack the string at grapheme boundaries. Returns a list of character
|
76
|
-
# lists.
|
77
|
-
#
|
78
|
-
# Unicode.unpack_graphemes('क्षि') # => [[2325, 2381], [2359], [2367]]
|
79
|
-
# Unicode.unpack_graphemes('Café') # => [[67], [97], [102], [233]]
|
80
|
-
def unpack_graphemes(string)
|
81
|
-
codepoints = string.codepoints.to_a
|
82
|
-
unpacked = []
|
83
|
-
pos = 0
|
84
|
-
marker = 0
|
85
|
-
eoc = codepoints.length
|
86
|
-
while(pos < eoc)
|
87
|
-
pos += 1
|
88
|
-
previous = codepoints[pos-1]
|
89
|
-
current = codepoints[pos]
|
90
|
-
|
91
|
-
should_break =
|
92
|
-
# GB3. CR X LF
|
93
|
-
if previous == database.boundary[:cr] and current == database.boundary[:lf]
|
94
|
-
false
|
95
|
-
# GB4. (Control|CR|LF) ÷
|
96
|
-
elsif previous and in_char_class?(previous, [:control,:cr,:lf])
|
97
|
-
true
|
98
|
-
# GB5. ÷ (Control|CR|LF)
|
99
|
-
elsif in_char_class?(current, [:control,:cr,:lf])
|
100
|
-
true
|
101
|
-
# GB6. L X (L|V|LV|LVT)
|
102
|
-
elsif database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt])
|
103
|
-
false
|
104
|
-
# GB7. (LV|V) X (V|T)
|
105
|
-
elsif in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t])
|
106
|
-
false
|
107
|
-
# GB8. (LVT|T) X (T)
|
108
|
-
elsif in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current
|
109
|
-
false
|
110
|
-
# GB8a. Regional_Indicator X Regional_Indicator
|
111
|
-
elsif database.boundary[:regional_indicator] === previous and database.boundary[:regional_indicator] === current
|
112
|
-
false
|
113
|
-
# GB9. X Extend
|
114
|
-
elsif database.boundary[:extend] === current
|
115
|
-
false
|
116
|
-
# GB9a. X SpacingMark
|
117
|
-
elsif database.boundary[:spacingmark] === current
|
118
|
-
false
|
119
|
-
# GB9b. Prepend X
|
120
|
-
elsif database.boundary[:prepend] === previous
|
121
|
-
false
|
122
|
-
# GB10. Any ÷ Any
|
123
|
-
else
|
124
|
-
true
|
125
|
-
end
|
126
|
-
|
127
|
-
if should_break
|
128
|
-
unpacked << codepoints[marker..pos-1]
|
129
|
-
marker = pos
|
130
|
-
end
|
131
|
-
end
|
132
|
-
unpacked
|
133
|
-
end
|
9
|
+
UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]
|
134
10
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
unpacked.flatten.pack('U*')
|
11
|
+
def default_normalization_form
|
12
|
+
ActiveSupport::Deprecation.warn(
|
13
|
+
"ActiveSupport::Multibyte::Unicode.default_normalization_form is deprecated and will be removed in Rails 6.2."
|
14
|
+
)
|
140
15
|
end
|
141
16
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
while pos < length do
|
147
|
-
cp1, cp2 = database.codepoints[codepoints[pos]], database.codepoints[codepoints[pos+1]]
|
148
|
-
if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
|
149
|
-
codepoints[pos..pos+1] = cp2.code, cp1.code
|
150
|
-
pos += (pos > 0 ? -1 : 1)
|
151
|
-
else
|
152
|
-
pos += 1
|
153
|
-
end
|
154
|
-
end
|
155
|
-
codepoints
|
17
|
+
def default_normalization_form=(_)
|
18
|
+
ActiveSupport::Deprecation.warn(
|
19
|
+
"ActiveSupport::Multibyte::Unicode.default_normalization_form= is deprecated and will be removed in Rails 6.2."
|
20
|
+
)
|
156
21
|
end
|
157
22
|
|
158
23
|
# Decompose composed characters to the decomposed form.
|
159
24
|
def decompose(type, codepoints)
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
ncp = [] # new codepoints
|
165
|
-
ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
|
166
|
-
ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
|
167
|
-
tindex = sindex % HANGUL_TCOUNT
|
168
|
-
ncp << (HANGUL_TBASE + tindex) unless tindex == 0
|
169
|
-
decomposed.concat ncp
|
170
|
-
# if the codepoint is decomposable in with the current decomposition type
|
171
|
-
elsif (ncp = database.codepoints[cp].decomp_mapping) and (!database.codepoints[cp].decomp_type || type == :compatibility)
|
172
|
-
decomposed.concat decompose(type, ncp.dup)
|
173
|
-
else
|
174
|
-
decomposed << cp
|
175
|
-
end
|
25
|
+
if type == :compatibility
|
26
|
+
codepoints.pack("U*").unicode_normalize(:nfkd).codepoints
|
27
|
+
else
|
28
|
+
codepoints.pack("U*").unicode_normalize(:nfd).codepoints
|
176
29
|
end
|
177
30
|
end
|
178
31
|
|
179
32
|
# Compose decomposed characters to the composed form.
|
180
33
|
def compose(codepoints)
|
181
|
-
|
182
|
-
eoa = codepoints.length - 1
|
183
|
-
starter_pos = 0
|
184
|
-
starter_char = codepoints[0]
|
185
|
-
previous_combining_class = -1
|
186
|
-
while pos < eoa
|
187
|
-
pos += 1
|
188
|
-
lindex = starter_char - HANGUL_LBASE
|
189
|
-
# -- Hangul
|
190
|
-
if 0 <= lindex and lindex < HANGUL_LCOUNT
|
191
|
-
vindex = codepoints[starter_pos+1] - HANGUL_VBASE rescue vindex = -1
|
192
|
-
if 0 <= vindex and vindex < HANGUL_VCOUNT
|
193
|
-
tindex = codepoints[starter_pos+2] - HANGUL_TBASE rescue tindex = -1
|
194
|
-
if 0 <= tindex and tindex < HANGUL_TCOUNT
|
195
|
-
j = starter_pos + 2
|
196
|
-
eoa -= 2
|
197
|
-
else
|
198
|
-
tindex = 0
|
199
|
-
j = starter_pos + 1
|
200
|
-
eoa -= 1
|
201
|
-
end
|
202
|
-
codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
|
203
|
-
end
|
204
|
-
starter_pos += 1
|
205
|
-
starter_char = codepoints[starter_pos]
|
206
|
-
# -- Other characters
|
207
|
-
else
|
208
|
-
current_char = codepoints[pos]
|
209
|
-
current = database.codepoints[current_char]
|
210
|
-
if current.combining_class > previous_combining_class
|
211
|
-
if ref = database.composition_map[starter_char]
|
212
|
-
composition = ref[current_char]
|
213
|
-
else
|
214
|
-
composition = nil
|
215
|
-
end
|
216
|
-
unless composition.nil?
|
217
|
-
codepoints[starter_pos] = composition
|
218
|
-
starter_char = composition
|
219
|
-
codepoints.delete_at pos
|
220
|
-
eoa -= 1
|
221
|
-
pos -= 1
|
222
|
-
previous_combining_class = -1
|
223
|
-
else
|
224
|
-
previous_combining_class = current.combining_class
|
225
|
-
end
|
226
|
-
else
|
227
|
-
previous_combining_class = current.combining_class
|
228
|
-
end
|
229
|
-
if current.combining_class == 0
|
230
|
-
starter_pos = pos
|
231
|
-
starter_char = codepoints[pos]
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
codepoints
|
34
|
+
codepoints.pack("U*").unicode_normalize(:nfc).codepoints
|
236
35
|
end
|
237
36
|
|
238
37
|
# Rubinius' String#scrub, however, doesn't support ASCII-incompatible chars.
|
@@ -243,7 +42,7 @@ module ActiveSupport
|
|
243
42
|
# Passing +true+ will forcibly tidy all bytes, assuming that the string's
|
244
43
|
# encoding is entirely CP1252 or ISO-8859-1.
|
245
44
|
def tidy_bytes(string, force = false)
|
246
|
-
return string if string.empty?
|
45
|
+
return string if string.empty? || string.ascii_only?
|
247
46
|
return recode_windows1252_chars(string) if force
|
248
47
|
string.scrub { |bad| recode_windows1252_chars(bad) }
|
249
48
|
end
|
@@ -259,7 +58,7 @@ module ActiveSupport
|
|
259
58
|
reader = Encoding::Converter.new(Encoding::UTF_8, Encoding::UTF_16LE)
|
260
59
|
|
261
60
|
source = string.dup
|
262
|
-
out =
|
61
|
+
out = "".force_encoding(Encoding::UTF_16LE)
|
263
62
|
|
264
63
|
loop do
|
265
64
|
reader.primitive_convert(source, out)
|
@@ -274,140 +73,10 @@ module ActiveSupport
|
|
274
73
|
end
|
275
74
|
end
|
276
75
|
|
277
|
-
# Returns the KC normalization of the string by default. NFKC is
|
278
|
-
# considered the best normalization form for passing strings to databases
|
279
|
-
# and validations.
|
280
|
-
#
|
281
|
-
# * <tt>string</tt> - The string to perform normalization on.
|
282
|
-
# * <tt>form</tt> - The form you want to normalize in. Should be one of
|
283
|
-
# the following: <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>.
|
284
|
-
# Default is ActiveSupport::Multibyte::Unicode.default_normalization_form.
|
285
|
-
def normalize(string, form=nil)
|
286
|
-
form ||= @default_normalization_form
|
287
|
-
# See http://www.unicode.org/reports/tr15, Table 1
|
288
|
-
codepoints = string.codepoints.to_a
|
289
|
-
case form
|
290
|
-
when :d
|
291
|
-
reorder_characters(decompose(:canonical, codepoints))
|
292
|
-
when :c
|
293
|
-
compose(reorder_characters(decompose(:canonical, codepoints)))
|
294
|
-
when :kd
|
295
|
-
reorder_characters(decompose(:compatibility, codepoints))
|
296
|
-
when :kc
|
297
|
-
compose(reorder_characters(decompose(:compatibility, codepoints)))
|
298
|
-
else
|
299
|
-
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
300
|
-
end.pack('U*'.freeze)
|
301
|
-
end
|
302
|
-
|
303
|
-
def downcase(string)
|
304
|
-
apply_mapping string, :lowercase_mapping
|
305
|
-
end
|
306
|
-
|
307
|
-
def upcase(string)
|
308
|
-
apply_mapping string, :uppercase_mapping
|
309
|
-
end
|
310
|
-
|
311
|
-
def swapcase(string)
|
312
|
-
apply_mapping string, :swapcase_mapping
|
313
|
-
end
|
314
|
-
|
315
|
-
# Holds data about a codepoint in the Unicode database.
|
316
|
-
class Codepoint
|
317
|
-
attr_accessor :code, :combining_class, :decomp_type, :decomp_mapping, :uppercase_mapping, :lowercase_mapping
|
318
|
-
|
319
|
-
# Initializing Codepoint object with default values
|
320
|
-
def initialize
|
321
|
-
@combining_class = 0
|
322
|
-
@uppercase_mapping = 0
|
323
|
-
@lowercase_mapping = 0
|
324
|
-
end
|
325
|
-
|
326
|
-
def swapcase_mapping
|
327
|
-
uppercase_mapping > 0 ? uppercase_mapping : lowercase_mapping
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
# Holds static data from the Unicode database.
|
332
|
-
class UnicodeDatabase
|
333
|
-
ATTRIBUTES = :codepoints, :composition_exclusion, :composition_map, :boundary, :cp1252
|
334
|
-
|
335
|
-
attr_writer(*ATTRIBUTES)
|
336
|
-
|
337
|
-
def initialize
|
338
|
-
@codepoints = Hash.new(Codepoint.new)
|
339
|
-
@composition_exclusion = []
|
340
|
-
@composition_map = {}
|
341
|
-
@boundary = {}
|
342
|
-
@cp1252 = {}
|
343
|
-
end
|
344
|
-
|
345
|
-
# Lazy load the Unicode database so it's only loaded when it's actually used
|
346
|
-
ATTRIBUTES.each do |attr_name|
|
347
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
348
|
-
def #{attr_name} # def codepoints
|
349
|
-
load # load
|
350
|
-
@#{attr_name} # @codepoints
|
351
|
-
end # end
|
352
|
-
EOS
|
353
|
-
end
|
354
|
-
|
355
|
-
# Loads the Unicode database and returns all the internal objects of
|
356
|
-
# UnicodeDatabase.
|
357
|
-
def load
|
358
|
-
begin
|
359
|
-
@codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, 'rb') { |f| Marshal.load f.read }
|
360
|
-
rescue => e
|
361
|
-
raise IOError.new("Couldn't load the Unicode tables for UTF8Handler (#{e.message}), ActiveSupport::Multibyte is unusable")
|
362
|
-
end
|
363
|
-
|
364
|
-
# Redefine the === method so we can write shorter rules for grapheme cluster breaks
|
365
|
-
@boundary.each_key do |k|
|
366
|
-
@boundary[k].instance_eval do
|
367
|
-
def ===(other)
|
368
|
-
detect { |i| i === other } ? true : false
|
369
|
-
end
|
370
|
-
end if @boundary[k].kind_of?(Array)
|
371
|
-
end
|
372
|
-
|
373
|
-
# define attr_reader methods for the instance variables
|
374
|
-
class << self
|
375
|
-
attr_reader(*ATTRIBUTES)
|
376
|
-
end
|
377
|
-
end
|
378
|
-
|
379
|
-
# Returns the directory in which the data files are stored.
|
380
|
-
def self.dirname
|
381
|
-
File.dirname(__FILE__) + '/../values/'
|
382
|
-
end
|
383
|
-
|
384
|
-
# Returns the filename for the data file for this version.
|
385
|
-
def self.filename
|
386
|
-
File.expand_path File.join(dirname, "unicode_tables.dat")
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
76
|
private
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
string.each_codepoint.map do |codepoint|
|
395
|
-
cp = database.codepoints[codepoint]
|
396
|
-
if cp and (ncp = cp.send(mapping)) and ncp > 0
|
397
|
-
ncp
|
398
|
-
else
|
399
|
-
codepoint
|
400
|
-
end
|
401
|
-
end.pack('U*')
|
402
|
-
end
|
403
|
-
|
404
|
-
def recode_windows1252_chars(string)
|
405
|
-
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
|
406
|
-
end
|
407
|
-
|
408
|
-
def database
|
409
|
-
@database ||= UnicodeDatabase.new
|
410
|
-
end
|
77
|
+
def recode_windows1252_chars(string)
|
78
|
+
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
|
79
|
+
end
|
411
80
|
end
|
412
81
|
end
|
413
82
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport #:nodoc:
|
2
4
|
module Multibyte
|
3
|
-
autoload :Chars,
|
4
|
-
autoload :Unicode,
|
5
|
+
autoload :Chars, "active_support/multibyte/chars"
|
6
|
+
autoload :Unicode, "active_support/multibyte/unicode"
|
5
7
|
|
6
8
|
# The proxy class returned when calling mb_chars. You can use this accessor
|
7
9
|
# to configure your own proxy class so you can support other encodings. See
|