unicode-emoji 3.8.0 → 4.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rake_tasks +1 -0
- data/CHANGELOG.md +59 -33
- data/Gemfile.lock +2 -4
- data/README.md +32 -21
- data/data/generate_constants.rb +32 -8
- data/lib/unicode/emoji/constants.rb +6 -2
- data/lib/unicode/emoji/generated/regex.rb +1 -1
- data/lib/unicode/emoji/generated/regex_basic.rb +1 -1
- data/lib/unicode/emoji/generated/regex_emoji_keycap.rb +8 -0
- data/lib/unicode/emoji/generated/regex_include_mqe.rb +1 -1
- data/lib/unicode/emoji/generated/regex_include_mqe_uqe.rb +1 -1
- data/lib/unicode/emoji/generated/regex_include_text.rb +1 -1
- data/lib/unicode/emoji/generated/regex_prop_component.rb +8 -0
- data/lib/unicode/emoji/generated/regex_prop_emoji.rb +8 -0
- data/lib/unicode/emoji/generated/regex_prop_modifier.rb +8 -0
- data/lib/unicode/emoji/generated/regex_prop_modifier_base.rb +8 -0
- data/lib/unicode/emoji/generated/regex_prop_presentation.rb +8 -0
- data/lib/unicode/emoji/generated/regex_text_presentation.rb +8 -0
- data/lib/unicode/emoji/generated/regex_valid.rb +1 -1
- data/lib/unicode/emoji/generated/regex_valid_include_text.rb +1 -1
- data/lib/unicode/emoji/generated/regex_well_formed.rb +1 -1
- data/lib/unicode/emoji/generated/regex_well_formed_include_text.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_basic.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_emoji_keycap.rb +8 -0
- data/lib/unicode/emoji/generated_native/regex_include_mqe.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_include_mqe_uqe.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_include_text.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_picto_no_emoji.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_prop_component.rb +8 -0
- data/lib/unicode/emoji/generated_native/{regex_any.rb → regex_prop_emoji.rb} +1 -1
- data/lib/unicode/emoji/generated_native/regex_prop_modifier.rb +8 -0
- data/lib/unicode/emoji/generated_native/regex_prop_modifier_base.rb +8 -0
- data/lib/unicode/emoji/generated_native/regex_prop_presentation.rb +8 -0
- data/lib/unicode/emoji/generated_native/regex_text.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_text_presentation.rb +8 -0
- data/lib/unicode/emoji/generated_native/regex_valid.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_valid_include_text.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_well_formed.rb +1 -1
- data/lib/unicode/emoji/generated_native/regex_well_formed_include_text.rb +1 -1
- data/lib/unicode/emoji.rb +10 -5
- data/spec/unicode_emoji_spec.rb +97 -16
- data/unicode-emoji.gemspec +1 -3
- metadata +17 -21
- data/lib/unicode/emoji/generated/regex_any.rb +0 -8
- data/spec/data/emoji-test.txt +0 -5331
@@ -3,6 +3,6 @@
|
|
3
3
|
|
4
4
|
module Unicode
|
5
5
|
module Emoji
|
6
|
-
REGEX_VALID_INCLUDE_TEXT = /(?:(?:(?:(?:\p{EBase}\p{EMod}|(?:\p{Emoji}(?<!\p{EPres})️|\p{EPres}(?!︎)️?)|\p{Emoji}))+(?:\p{EBase}\p{EMod}|(?:\p{Emoji}(?<!\p{EPres})️|\p{EPres}(?!︎)️?)|\p{Emoji}))|(?:🏴(?:[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||))|(?:🇦🇨|🇦🇩|🇦🇪|🇦🇫|🇦🇬|🇦🇮|🇦🇱|🇦🇲|🇦🇴|🇦🇶|🇦🇷|🇦🇸|🇦🇹|🇦🇺|🇦🇼|🇦🇽|🇦🇿|🇧🇦|🇧🇧|🇧🇩|🇧🇪|🇧🇫|🇧🇬|🇧🇭|🇧🇮|🇧🇯|🇧🇱|🇧🇲|🇧🇳|🇧🇴|🇧🇶|🇧🇷|🇧🇸|🇧🇹|🇧🇻|🇧🇼|🇧🇾|🇧🇿|🇨🇦|🇨🇨|🇨🇩|🇨🇫|🇨🇬|🇨🇭|🇨🇮|🇨🇰|🇨🇱|🇨🇲|🇨🇳|🇨🇴|🇨🇵|🇨🇶|🇨🇷|🇨🇺|🇨🇻|🇨🇼|🇨🇽|🇨🇾|🇨🇿|🇩🇪|🇩🇬|🇩🇯|🇩🇰|🇩🇲|🇩🇴|🇩🇿|🇪🇦|🇪🇨|🇪🇪|🇪🇬|🇪🇭|🇪🇷|🇪🇸|🇪🇹|🇪🇺|🇫🇮|🇫🇯|🇫🇰|🇫🇲|🇫🇴|🇫🇷|🇬🇦|🇬🇧|🇬🇩|🇬🇪|🇬🇫|🇬🇬|🇬🇭|🇬🇮|🇬🇱|🇬🇲|🇬🇳|🇬🇵|🇬🇶|🇬🇷|🇬🇸|🇬🇹|🇬🇺|🇬🇼|🇬🇾|🇭🇰|🇭🇲|🇭🇳|🇭🇷|🇭🇹|🇭🇺|🇮🇨|🇮🇩|🇮🇪|🇮🇱|🇮🇲|🇮🇳|🇮🇴|🇮🇶|🇮🇷|🇮🇸|🇮🇹|🇯🇪|🇯🇲|🇯🇴|🇯🇵|🇰🇪|🇰🇬|🇰🇭|🇰🇮|🇰🇲|🇰🇳|🇰🇵|🇰🇷|🇰🇼|🇰🇾|🇰🇿|🇱🇦|🇱🇧|🇱🇨|🇱🇮|🇱🇰|🇱🇷|🇱🇸|🇱🇹|🇱🇺|🇱🇻|🇱🇾|🇲🇦|🇲🇨|🇲🇩|🇲🇪|🇲🇫|🇲🇬|🇲🇭|🇲🇰|🇲🇱|🇲🇲|🇲🇳|🇲🇴|🇲🇵|🇲🇶|🇲🇷|🇲🇸|🇲🇹|🇲🇺|🇲🇻|🇲🇼|🇲🇽|🇲🇾|🇲🇿|🇳🇦|🇳🇨|🇳🇪|🇳🇫|🇳🇬|🇳🇮|🇳🇱|🇳🇴|🇳🇵|🇳🇷|🇳🇺|🇳🇿|🇴🇲|🇵🇦|🇵🇪|🇵🇫|🇵🇬|🇵🇭|🇵🇰|🇵🇱|🇵🇲|🇵🇳|🇵🇷|🇵🇸|🇵🇹|🇵🇼|🇵🇾|🇶🇦|🇷🇪|🇷🇴|🇷🇸|🇷🇺|🇷🇼|🇸🇦|🇸🇧|🇸🇨|🇸🇩|🇸🇪|🇸🇬|🇸🇭|🇸🇮|🇸🇯|🇸🇰|🇸🇱|🇸🇲|🇸🇳|🇸🇴|🇸🇷|🇸🇸|🇸🇹|🇸🇻|🇸🇽|🇸🇾|🇸🇿|🇹🇦|🇹🇨|🇹🇩|🇹🇫|🇹🇬|🇹🇭|🇹🇯|🇹🇰|🇹🇱|🇹🇲|🇹🇳|🇹🇴|🇹🇷|🇹🇹|🇹🇻|🇹🇼|🇹🇿|🇺🇦|🇺🇬|🇺🇲|🇺🇳|🇺🇸|🇺🇾|🇺🇿|🇻🇦|🇻🇨|🇻🇪|🇻🇬|🇻🇮|🇻🇳|🇻🇺|🇼🇫|🇼🇸|🇽🇰|🇾🇪|🇾🇹|🇿🇦|🇿🇲|🇿🇼)|(?:[\#\*0-9]️⃣|\p{EBase}\p{EMod}|(?!\p{EComp})(?:\p{Emoji}(?<!\p{EPres})️|\p{EPres}(?!︎)️?))|(?:(?!\p{EComp})(?:\p{Emoji}(?<!\p{EPres})(?!(?:\p{EMod}|️))︎?|\p{EPres}︎)|[\#\*0-9]⃣))/
|
6
|
+
REGEX_VALID_INCLUDE_TEXT = /(?:(?:(?:(?:\p{EBase}\p{EMod}|(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?)|\p{Emoji}))+(?:\p{EBase}\p{EMod}|(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?)|\p{Emoji}))|(?:🏴(?:[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|[-]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||))|(?:🇦🇨|🇦🇩|🇦🇪|🇦🇫|🇦🇬|🇦🇮|🇦🇱|🇦🇲|🇦🇴|🇦🇶|🇦🇷|🇦🇸|🇦🇹|🇦🇺|🇦🇼|🇦🇽|🇦🇿|🇧🇦|🇧🇧|🇧🇩|🇧🇪|🇧🇫|🇧🇬|🇧🇭|🇧🇮|🇧🇯|🇧🇱|🇧🇲|🇧🇳|🇧🇴|🇧🇶|🇧🇷|🇧🇸|🇧🇹|🇧🇻|🇧🇼|🇧🇾|🇧🇿|🇨🇦|🇨🇨|🇨🇩|🇨🇫|🇨🇬|🇨🇭|🇨🇮|🇨🇰|🇨🇱|🇨🇲|🇨🇳|🇨🇴|🇨🇵|🇨🇶|🇨🇷|🇨🇺|🇨🇻|🇨🇼|🇨🇽|🇨🇾|🇨🇿|🇩🇪|🇩🇬|🇩🇯|🇩🇰|🇩🇲|🇩🇴|🇩🇿|🇪🇦|🇪🇨|🇪🇪|🇪🇬|🇪🇭|🇪🇷|🇪🇸|🇪🇹|🇪🇺|🇫🇮|🇫🇯|🇫🇰|🇫🇲|🇫🇴|🇫🇷|🇬🇦|🇬🇧|🇬🇩|🇬🇪|🇬🇫|🇬🇬|🇬🇭|🇬🇮|🇬🇱|🇬🇲|🇬🇳|🇬🇵|🇬🇶|🇬🇷|🇬🇸|🇬🇹|🇬🇺|🇬🇼|🇬🇾|🇭🇰|🇭🇲|🇭🇳|🇭🇷|🇭🇹|🇭🇺|🇮🇨|🇮🇩|🇮🇪|🇮🇱|🇮🇲|🇮🇳|🇮🇴|🇮🇶|🇮🇷|🇮🇸|🇮🇹|🇯🇪|🇯🇲|🇯🇴|🇯🇵|🇰🇪|🇰🇬|🇰🇭|🇰🇮|🇰🇲|🇰🇳|🇰🇵|🇰🇷|🇰🇼|🇰🇾|🇰🇿|🇱🇦|🇱🇧|🇱🇨|🇱🇮|🇱🇰|🇱🇷|🇱🇸|🇱🇹|🇱🇺|🇱🇻|🇱🇾|🇲🇦|🇲🇨|🇲🇩|🇲🇪|🇲🇫|🇲🇬|🇲🇭|🇲🇰|🇲🇱|🇲🇲|🇲🇳|🇲🇴|🇲🇵|🇲🇶|🇲🇷|🇲🇸|🇲🇹|🇲🇺|🇲🇻|🇲🇼|🇲🇽|🇲🇾|🇲🇿|🇳🇦|🇳🇨|🇳🇪|🇳🇫|🇳🇬|🇳🇮|🇳🇱|🇳🇴|🇳🇵|🇳🇷|🇳🇺|🇳🇿|🇴🇲|🇵🇦|🇵🇪|🇵🇫|🇵🇬|🇵🇭|🇵🇰|🇵🇱|🇵🇲|🇵🇳|🇵🇷|🇵🇸|🇵🇹|🇵🇼|🇵🇾|🇶🇦|🇷🇪|🇷🇴|🇷🇸|🇷🇺|🇷🇼|🇸🇦|🇸🇧|🇸🇨|🇸🇩|🇸🇪|🇸🇬|🇸🇭|🇸🇮|🇸🇯|🇸🇰|🇸🇱|🇸🇲|🇸🇳|🇸🇴|🇸🇷|🇸🇸|🇸🇹|🇸🇻|🇸🇽|🇸🇾|🇸🇿|🇹🇦|🇹🇨|🇹🇩|🇹🇫|🇹🇬|🇹🇭|🇹🇯|🇹🇰|🇹🇱|🇹🇲|🇹🇳|🇹🇴|🇹🇷|🇹🇹|🇹🇻|🇹🇼|🇹🇿|🇺🇦|🇺🇬|🇺🇲|🇺🇳|🇺🇸|🇺🇾|🇺🇿|🇻🇦|🇻🇨|🇻🇪|🇻🇬|🇻🇮|🇻🇳|🇻🇺|🇼🇫|🇼🇸|🇽🇰|🇾🇪|🇾🇹|🇿🇦|🇿🇲|🇿🇼)|(?:[\#\*0-9]️⃣|\p{EBase}\p{EMod}|(?!\p{EComp})(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?))|[🏻-🏿🦰-🦳]|(?:(?!\p{EComp})(?:[\p{Emoji}&&\P{EPres}](?!(?:\p{EMod}|️))︎?|\p{EPres}︎)|[\#\*0-9]⃣))/
|
7
7
|
end
|
8
8
|
end
|
@@ -3,6 +3,6 @@
|
|
3
3
|
|
4
4
|
module Unicode
|
5
5
|
module Emoji
|
6
|
-
REGEX_WELL_FORMED = /(?:(?:(?:(?:\p{EBase}\p{EMod}|(
|
6
|
+
REGEX_WELL_FORMED = /(?:(?:(?:(?:\p{EBase}\p{EMod}|(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?)|\p{Emoji}))+(?:\p{EBase}\p{EMod}|(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?)|\p{Emoji}))|(?:(?:(?!\p{EComp})(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?)|\p{EBase}\p{EMod})[--]{1,30})|\p{RI}{2}|(?:[\#\*0-9]️⃣|\p{EBase}\p{EMod}|(?!\p{EComp})(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?))|[🏻-🏿🦰-🦳])/
|
7
7
|
end
|
8
8
|
end
|
@@ -3,6 +3,6 @@
|
|
3
3
|
|
4
4
|
module Unicode
|
5
5
|
module Emoji
|
6
|
-
REGEX_WELL_FORMED_INCLUDE_TEXT = /(?:(?:(?:(?:\p{EBase}\p{EMod}|(
|
6
|
+
REGEX_WELL_FORMED_INCLUDE_TEXT = /(?:(?:(?:(?:\p{EBase}\p{EMod}|(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?)|\p{Emoji}))+(?:\p{EBase}\p{EMod}|(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?)|\p{Emoji}))|(?:(?:(?!\p{EComp})(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?)|\p{EBase}\p{EMod})[--]{1,30})|\p{RI}{2}|(?:[\#\*0-9]️⃣|\p{EBase}\p{EMod}|(?!\p{EComp})(?:[\p{Emoji}&&\P{EPres}]️|\p{EPres}(?!︎)️?))|[🏻-🏿🦰-🦳]|(?:(?!\p{EComp})(?:[\p{Emoji}&&\P{EPres}](?!(?:\p{EMod}|️))︎?|\p{EPres}︎)|[\#\*0-9]⃣))/
|
7
7
|
end
|
8
8
|
end
|
data/lib/unicode/emoji.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "unicode/version"
|
4
|
-
|
5
3
|
require_relative "emoji/constants"
|
6
4
|
|
7
5
|
module Unicode
|
@@ -17,7 +15,8 @@ module Unicode
|
|
17
15
|
EMOJI_MODIFIERS
|
18
16
|
EXTENDED_PICTOGRAPHIC
|
19
17
|
EXTENDED_PICTOGRAPHIC_NO_EMOJI
|
20
|
-
EMOJI_KEYCAPS
|
18
|
+
EMOJI_KEYCAPS
|
19
|
+
VALID_REGION_FLAGS
|
21
20
|
VALID_SUBDIVISIONS
|
22
21
|
RECOMMENDED_SUBDIVISION_FLAGS
|
23
22
|
RECOMMENDED_ZWJ_SEQUENCES
|
@@ -33,7 +32,7 @@ module Unicode
|
|
33
32
|
end
|
34
33
|
|
35
34
|
generated_constants_dirpath = File.expand_path(
|
36
|
-
EMOJI_VERSION ==
|
35
|
+
EMOJI_VERSION == RbConfig::CONFIG["UNICODE_EMOJI_VERSION"] ? "emoji/generated_native/" : "emoji/generated/",
|
37
36
|
__dir__
|
38
37
|
)
|
39
38
|
|
@@ -49,9 +48,15 @@ module Unicode
|
|
49
48
|
REGEX_POSSIBLE
|
50
49
|
REGEX_BASIC
|
51
50
|
REGEX_TEXT
|
51
|
+
REGEX_TEXT_PRESENTATION
|
52
|
+
REGEX_PROP_EMOJI
|
53
|
+
REGEX_PROP_MODIFIER
|
54
|
+
REGEX_PROP_MODIFIER_BASE
|
55
|
+
REGEX_PROP_COMPONENT
|
56
|
+
REGEX_PROP_PRESENTATION
|
52
57
|
REGEX_PICTO
|
53
58
|
REGEX_PICTO_NO_EMOJI
|
54
|
-
|
59
|
+
REGEX_EMOJI_KEYCAP
|
55
60
|
].each do |const_name|
|
56
61
|
autoload const_name, File.join(generated_constants_dirpath, const_name.downcase)
|
57
62
|
end
|
data/spec/unicode_emoji_spec.rb
CHANGED
@@ -39,8 +39,19 @@ describe Unicode::Emoji do
|
|
39
39
|
assert_equal "▶\u{FE0F}", $&
|
40
40
|
end
|
41
41
|
|
42
|
-
it "
|
42
|
+
it "matches singleton skin tone modifiers and hair components" do
|
43
43
|
"🏻 light skin tone" =~ Unicode::Emoji::REGEX
|
44
|
+
assert_equal "🏻", $&
|
45
|
+
|
46
|
+
"🦰 emoji component red hair" =~ Unicode::Emoji::REGEX
|
47
|
+
assert_equal "🦰", $&
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not match singleton components that are not skin tone modifiers or hair components" do
|
51
|
+
"1 digit one" =~ Unicode::Emoji::REGEX
|
52
|
+
assert_nil $&
|
53
|
+
|
54
|
+
"🇦 regional indicator symbol letter a" =~ Unicode::Emoji::REGEX
|
44
55
|
assert_nil $&
|
45
56
|
end
|
46
57
|
|
@@ -94,12 +105,12 @@ describe Unicode::Emoji do
|
|
94
105
|
|
95
106
|
it "does not match MQE zwj sequences" do
|
96
107
|
"🤾🏽♀ woman playing handball: medium skin tone, missing VS16" =~ Unicode::Emoji::REGEX
|
97
|
-
refute_equal
|
108
|
+
refute_equal "🤾🏽♀", $&
|
98
109
|
end
|
99
110
|
|
100
111
|
it "does not match UQE emoji" do
|
101
112
|
"🏌♂️ man golfing, missing VS16" =~ Unicode::Emoji::REGEX
|
102
|
-
refute_equal
|
113
|
+
refute_equal "🏌♂️", $&
|
103
114
|
end
|
104
115
|
|
105
116
|
it "does not match valid zwj sequences that are not recommended" do
|
@@ -153,24 +164,24 @@ describe Unicode::Emoji do
|
|
153
164
|
describe "REGEX_INCLUDE_MQE" do
|
154
165
|
it "matches MQE emoji" do
|
155
166
|
"🤾🏽♀ woman playing handball: medium skin tone, missing VS16" =~ Unicode::Emoji::REGEX_INCLUDE_MQE
|
156
|
-
assert_equal
|
167
|
+
assert_equal "🤾🏽♀", $&
|
157
168
|
end
|
158
169
|
|
159
170
|
it "does not match UQE emoji" do
|
160
171
|
"🏌♂️ man golfing, missing VS16" =~ Unicode::Emoji::REGEX_INCLUDE_MQE
|
161
|
-
refute_equal
|
172
|
+
refute_equal "🏌♂️", $&
|
162
173
|
end
|
163
174
|
end
|
164
175
|
|
165
176
|
describe "REGEX_INCLUDE_MQE_UQE" do
|
166
177
|
it "matches MQE emoji" do
|
167
178
|
"🤾🏽♀ woman playing handball: medium skin tone, missing VS16" =~ Unicode::Emoji::REGEX_INCLUDE_MQE_UQE
|
168
|
-
assert_equal
|
179
|
+
assert_equal "🤾🏽♀", $&
|
169
180
|
end
|
170
181
|
|
171
182
|
it "matches UQE emoji" do
|
172
183
|
"🏌♂️ man golfing, missing VS16" =~ Unicode::Emoji::REGEX_INCLUDE_MQE_UQE
|
173
|
-
assert_equal
|
184
|
+
assert_equal "🏌♂️", $&
|
174
185
|
end
|
175
186
|
end
|
176
187
|
|
@@ -200,8 +211,19 @@ describe Unicode::Emoji do
|
|
200
211
|
assert_equal "▶\u{FE0F}", $&
|
201
212
|
end
|
202
213
|
|
203
|
-
it "
|
214
|
+
it "matches singleton skin tone modifiers and hair components" do
|
204
215
|
"🏻 light skin tone" =~ Unicode::Emoji::REGEX_VALID
|
216
|
+
assert_equal "🏻", $&
|
217
|
+
|
218
|
+
"🦰 emoji component red hair" =~ Unicode::Emoji::REGEX_VALID
|
219
|
+
assert_equal "🦰", $&
|
220
|
+
end
|
221
|
+
|
222
|
+
it "does not match singleton components that are not skin tone modifiers or hair components" do
|
223
|
+
"1 digit one" =~ Unicode::Emoji::REGEX_VALID
|
224
|
+
assert_nil $&
|
225
|
+
|
226
|
+
"🇦 regional indicator symbol letter a" =~ Unicode::Emoji::REGEX_VALID
|
205
227
|
assert_nil $&
|
206
228
|
end
|
207
229
|
|
@@ -295,8 +317,19 @@ describe Unicode::Emoji do
|
|
295
317
|
assert_equal "▶\u{FE0F}", $&
|
296
318
|
end
|
297
319
|
|
298
|
-
it "
|
320
|
+
it "matches singleton skin tone modifiers and hair components" do
|
299
321
|
"🏻 light skin tone" =~ Unicode::Emoji::REGEX_WELL_FORMED
|
322
|
+
assert_equal "🏻", $&
|
323
|
+
|
324
|
+
"🦰 emoji component red hair" =~ Unicode::Emoji::REGEX_WELL_FORMED
|
325
|
+
assert_equal "🦰", $&
|
326
|
+
end
|
327
|
+
|
328
|
+
it "does not match singleton components that are not skin tone modifiers or hair components" do
|
329
|
+
"1 digit one" =~ Unicode::Emoji::REGEX_WELL_FORMED
|
330
|
+
assert_nil $&
|
331
|
+
|
332
|
+
"🇦 regional indicator symbol letter a" =~ Unicode::Emoji::REGEX_WELL_FORMED
|
300
333
|
assert_nil $&
|
301
334
|
end
|
302
335
|
|
@@ -395,9 +428,20 @@ describe Unicode::Emoji do
|
|
395
428
|
assert_equal "▶\u{FE0F}", $&
|
396
429
|
end
|
397
430
|
|
398
|
-
it "matches singleton
|
431
|
+
it "matches singleton skin tone modifiers and hair components" do
|
399
432
|
"🏻 light skin tone" =~ Unicode::Emoji::REGEX_POSSIBLE
|
400
433
|
assert_equal "🏻", $&
|
434
|
+
|
435
|
+
"🦰 emoji component red hair" =~ Unicode::Emoji::REGEX_POSSIBLE
|
436
|
+
assert_equal "🦰", $&
|
437
|
+
end
|
438
|
+
|
439
|
+
it "matches singleton components that are not skin tone modifiers or hair components" do
|
440
|
+
"1 digit one" =~ Unicode::Emoji::REGEX_POSSIBLE
|
441
|
+
assert_equal "1", $&
|
442
|
+
|
443
|
+
"🇦 regional indicator symbol letter a" =~ Unicode::Emoji::REGEX_POSSIBLE
|
444
|
+
assert_equal "🇦", $&
|
401
445
|
end
|
402
446
|
|
403
447
|
it "matches modified emoji if modifier base emoji is used" do
|
@@ -486,17 +530,28 @@ describe Unicode::Emoji do
|
|
486
530
|
end
|
487
531
|
|
488
532
|
it "does not match textual singleton emoji" do
|
489
|
-
"▶ play button" =~ Unicode::Emoji::
|
533
|
+
"▶ play button" =~ Unicode::Emoji::REGEX_BASIC
|
490
534
|
assert_nil $&
|
491
535
|
end
|
492
536
|
|
493
537
|
it "matches textual singleton emoji in combination with emoji variation selector" do
|
494
|
-
"▶\u{FE0F} play button" =~ Unicode::Emoji::
|
538
|
+
"▶\u{FE0F} play button" =~ Unicode::Emoji::REGEX_BASIC
|
495
539
|
assert_equal "▶\u{FE0F}", $&
|
496
540
|
end
|
497
541
|
|
498
|
-
it "
|
542
|
+
it "matches singleton skin tone modifiers and hair components" do
|
499
543
|
"🏻 light skin tone" =~ Unicode::Emoji::REGEX_BASIC
|
544
|
+
assert_equal "🏻", $&
|
545
|
+
|
546
|
+
"🦰 emoji component red hair" =~ Unicode::Emoji::REGEX_BASIC
|
547
|
+
assert_equal "🦰", $&
|
548
|
+
end
|
549
|
+
|
550
|
+
it "does not match singleton components that are not skin tone modifiers or hair components" do
|
551
|
+
"1 digit one" =~ Unicode::Emoji::REGEX_BASIC
|
552
|
+
assert_nil $&
|
553
|
+
|
554
|
+
"🇦 regional indicator symbol letter a" =~ Unicode::Emoji::REGEX_BASIC
|
500
555
|
assert_nil $&
|
501
556
|
end
|
502
557
|
|
@@ -557,9 +612,20 @@ describe Unicode::Emoji do
|
|
557
612
|
assert_nil $&
|
558
613
|
end
|
559
614
|
|
560
|
-
it "does not match singleton
|
615
|
+
it "does not match singleton skin tone modifiers and hair components" do
|
561
616
|
"🏻 light skin tone" =~ Unicode::Emoji::REGEX_TEXT
|
562
617
|
assert_nil $&
|
618
|
+
|
619
|
+
"🦰 emoji component red hair" =~ Unicode::Emoji::REGEX_TEXT
|
620
|
+
assert_nil $&
|
621
|
+
end
|
622
|
+
|
623
|
+
it "does not match singleton components that are not skin tone modifiers or hair components" do
|
624
|
+
"1 digit one" =~ Unicode::Emoji::REGEX_TEXT
|
625
|
+
assert_nil $&
|
626
|
+
|
627
|
+
"🇦 regional indicator symbol letter a" =~ Unicode::Emoji::REGEX_TEXT
|
628
|
+
assert_nil $&
|
563
629
|
end
|
564
630
|
|
565
631
|
it "does not match modified emoji" do
|
@@ -596,13 +662,28 @@ describe Unicode::Emoji do
|
|
596
662
|
end
|
597
663
|
end
|
598
664
|
|
599
|
-
describe "
|
665
|
+
describe "REGEX_PROP_EMOJI" do
|
600
666
|
it "returns any emoji-related codepoint (but no variation selectors or tags)" do
|
601
|
-
matches = "1 string 😴\u{FE0F} sleeping face with 🇵 and modifier 🏾, also 🏴 Scotland".scan(Unicode::Emoji::
|
667
|
+
matches = "1 string 😴\u{FE0F} sleeping face with 🇵 and modifier 🏾, also 🏴 Scotland".scan(Unicode::Emoji::REGEX_PROP_EMOJI)
|
602
668
|
assert_equal ["1", "😴", "🇵", "🏾", "🏴"], matches
|
603
669
|
end
|
604
670
|
end
|
605
671
|
|
672
|
+
describe "REGEX_EMOJI_KEYCAP" do
|
673
|
+
it "matches emoji keycap sequences" do
|
674
|
+
"2️⃣ keycap: 2" =~ Unicode::Emoji::REGEX_EMOJI_KEYCAP
|
675
|
+
assert_equal "2️⃣", $&
|
676
|
+
end
|
677
|
+
|
678
|
+
it "does not match non-emoji keycap sequences" do
|
679
|
+
"8⃣ text keycap: 8" =~ Unicode::Emoji::REGEX_EMOJI_KEYCAP
|
680
|
+
assert_nil $&
|
681
|
+
|
682
|
+
"#⃣ text keycap: #" =~ Unicode::Emoji::REGEX_EMOJI_KEYCAP
|
683
|
+
assert_nil $&
|
684
|
+
end
|
685
|
+
end
|
686
|
+
|
606
687
|
describe "REGEX_PICTO" do
|
607
688
|
it "matches codepoints with Extended_Pictograph property (almost all emoji are, but also others)" do
|
608
689
|
matches = "U+1F32D 🌭 HOT DOG, U+203C ‼ DOUBLE EXCLAMATION MARK, U+26E8 ⛨ BLACK CROSS ON SHIELD".scan(Unicode::Emoji::REGEX_PICTO)
|
data/unicode-emoji.gemspec
CHANGED
@@ -12,13 +12,11 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.homepage = "https://github.com/janlelis/unicode-emoji"
|
13
13
|
gem.license = "MIT"
|
14
14
|
|
15
|
-
gem.files = Dir["{**/}{.*,*}"].select{ |path| File.file?(path) && path !~ /^pkg/ }
|
15
|
+
gem.files = Dir["{**/}{.*,*}"].select{ |path| File.file?(path) && path !~ /^pkg/ && path !~ /spec\/data\/[^.]/ }
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
gem.metadata = { "rubygems_mfa_required" => "true" }
|
20
20
|
|
21
21
|
gem.required_ruby_version = ">= 2.5", "< 4.0"
|
22
|
-
|
23
|
-
gem.add_dependency "unicode-version", "~> 1.0"
|
24
22
|
end
|