restify 2.0.1 โ†’ 2.1.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.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/README.md +1 -1
  4. data/lib/restify/adapter/base.rb +1 -1
  5. data/lib/restify/cache.rb +1 -1
  6. data/lib/restify/relation.rb +7 -11
  7. data/lib/restify/response.rb +2 -2
  8. data/lib/restify/version.rb +2 -2
  9. data/spec/restify/adapter/base_spec.rb +33 -0
  10. data/spec/restify/context_spec.rb +2 -2
  11. data/spec/restify/features/opentelemetry_spec.rb +1 -1
  12. data/spec/restify/global_spec.rb +50 -1
  13. data/spec/restify/link_spec.rb +13 -3
  14. data/spec/restify/relation_spec.rb +79 -7
  15. data/spec/restify/resource_spec.rb +6 -0
  16. data/spec/restify_spec.rb +1 -1
  17. data/spec/spec_helper.rb +0 -1
  18. data/vendor/bundle/ruby/4.0.0/bundler/gems/my-rubocop-2b861962124a/LICENSE +21 -0
  19. data/vendor/bundle/ruby/4.0.0/bundler/gems/my-rubocop-2b861962124a/README.md +23 -0
  20. data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/CHANGELOG.md +561 -0
  21. data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/MIT-LICENSE +20 -0
  22. data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/README.rdoc +40 -0
  23. data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/CHANGELOG.md +326 -0
  24. data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/LICENSE.txt +202 -0
  25. data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/README.md +121 -0
  26. data/vendor/bundle/ruby/4.0.0/gems/ast-2.4.3/LICENSE.MIT +20 -0
  27. data/vendor/bundle/ruby/4.0.0/gems/ast-2.4.3/README.YARD.md +12 -0
  28. data/vendor/bundle/ruby/4.0.0/gems/base64-0.3.0/README.md +48 -0
  29. data/vendor/bundle/ruby/4.0.0/gems/bigdecimal-4.1.2/LICENSE +56 -0
  30. data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/CHANGELOG.md +615 -0
  31. data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/LICENSE.txt +21 -0
  32. data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/README.md +409 -0
  33. data/vendor/bundle/ruby/4.0.0/gems/connection_pool-3.0.2/LICENSE +20 -0
  34. data/vendor/bundle/ruby/4.0.0/gems/connection_pool-3.0.2/README.md +182 -0
  35. data/vendor/bundle/ruby/4.0.0/gems/crack-1.0.1/LICENSE +20 -0
  36. data/vendor/bundle/ruby/4.0.0/gems/crack-1.0.1/README.md +43 -0
  37. data/vendor/bundle/ruby/4.0.0/gems/diff-lcs-1.6.2/CHANGELOG.md +518 -0
  38. data/vendor/bundle/ruby/4.0.0/gems/diff-lcs-1.6.2/README.md +92 -0
  39. data/vendor/bundle/ruby/4.0.0/gems/docile-1.4.1/LICENSE +21 -0
  40. data/vendor/bundle/ruby/4.0.0/gems/docile-1.4.1/README.md +409 -0
  41. data/vendor/bundle/ruby/4.0.0/gems/drb-2.2.3/LICENSE.txt +22 -0
  42. data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/CHANGELOG.md +417 -0
  43. data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/LICENSE +20 -0
  44. data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/README.md +118 -0
  45. data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/CHANGELOG.md +507 -0
  46. data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/LICENSE +24 -0
  47. data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/LICENSE.SPECS +22 -0
  48. data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/README.md +138 -0
  49. data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/LICENSE +19 -0
  50. data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/README.md +323 -0
  51. data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/changelog.md +127 -0
  52. data/vendor/bundle/ruby/4.0.0/gems/hitimes-3.2.0/LICENSE.txt +16 -0
  53. data/vendor/bundle/ruby/4.0.0/gems/hitimes-3.2.0/README.md +187 -0
  54. data/vendor/bundle/ruby/4.0.0/gems/i18n-1.15.2/MIT-LICENSE +20 -0
  55. data/vendor/bundle/ruby/4.0.0/gems/i18n-1.15.2/README.md +139 -0
  56. data/vendor/bundle/ruby/4.0.0/gems/json-2.19.9/README.md +310 -0
  57. data/vendor/bundle/ruby/4.0.0/gems/language_server-protocol-3.17.0.5/LICENSE.txt +21 -0
  58. data/vendor/bundle/ruby/4.0.0/gems/language_server-protocol-3.17.0.5/README.md +88 -0
  59. data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/CHANGELOG.md +15 -0
  60. data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/LICENSE.txt +21 -0
  61. data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/README.md +173 -0
  62. data/vendor/bundle/ruby/4.0.0/gems/little-plugger-1.1.4/README.rdoc +53 -0
  63. data/vendor/bundle/ruby/4.0.0/gems/logger-1.7.0/README.md +104 -0
  64. data/vendor/bundle/ruby/4.0.0/gems/logging-2.4.0/LICENSE +22 -0
  65. data/vendor/bundle/ruby/4.0.0/gems/logging-2.4.0/README.md +140 -0
  66. data/vendor/bundle/ruby/4.0.0/gems/minitest-6.0.6/README.rdoc +763 -0
  67. data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/ChangeLog +383 -0
  68. data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/LICENSE +177 -0
  69. data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/README.md +302 -0
  70. data/vendor/bundle/ruby/4.0.0/gems/multi_json-1.21.1/LICENSE.md +20 -0
  71. data/vendor/bundle/ruby/4.0.0/gems/multi_json-1.21.1/README.md +281 -0
  72. data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/ext/libev/LICENSE +37 -0
  73. data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/ext/libev/README +59 -0
  74. data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/license.md +80 -0
  75. data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/readme.md +91 -0
  76. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/CHANGELOG.md +219 -0
  77. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/LICENSE +201 -0
  78. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/README.md +68 -0
  79. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/CHANGELOG.md +110 -0
  80. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/LICENSE +201 -0
  81. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/README.md +62 -0
  82. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/CHANGELOG.md +97 -0
  83. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/LICENSE +201 -0
  84. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/README.md +155 -0
  85. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/CHANGELOG.md +192 -0
  86. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/LICENSE +201 -0
  87. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/README.md +66 -0
  88. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/CHANGELOG.md +31 -0
  89. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/LICENSE +201 -0
  90. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/README.md +40 -0
  91. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/CHANGELOG.md +302 -0
  92. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/LICENSE +201 -0
  93. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/README.md +101 -0
  94. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/CHANGELOG.md +65 -0
  95. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/LICENSE +201 -0
  96. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/README.md +115 -0
  97. data/vendor/bundle/ruby/4.0.0/gems/parallel-2.1.0/MIT-LICENSE.txt +20 -0
  98. data/vendor/bundle/ruby/4.0.0/gems/parser-3.3.11.1/LICENSE.txt +26 -0
  99. data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/CHANGELOG.md +786 -0
  100. data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/LICENSE.md +7 -0
  101. data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/README.md +143 -0
  102. data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/CHANGELOG.md +649 -0
  103. data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/LICENSE.txt +22 -0
  104. data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/README.md +231 -0
  105. data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/LICENSE +29 -0
  106. data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/README.md +484 -0
  107. data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/docs/jungle/README.md +9 -0
  108. data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/docs/jungle/rc.d/README.md +74 -0
  109. data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/ChangeLog +846 -0
  110. data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/README.ja.rdoc +58 -0
  111. data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/README.rdoc +60 -0
  112. data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/CHANGELOG.md +1346 -0
  113. data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/MIT-LICENSE +20 -0
  114. data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/README.md +384 -0
  115. data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/Changelog.md +101 -0
  116. data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/LICENSE +20 -0
  117. data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/README.markdown +227 -0
  118. data/vendor/bundle/ruby/4.0.0/gems/rake-13.4.2/MIT-LICENSE +21 -0
  119. data/vendor/bundle/ruby/4.0.0/gems/rake-13.4.2/README.rdoc +155 -0
  120. data/vendor/bundle/ruby/4.0.0/gems/rake-release-1.4.0/LICENSE +21 -0
  121. data/vendor/bundle/ruby/4.0.0/gems/rake-release-1.4.0/README.md +107 -0
  122. data/vendor/bundle/ruby/4.0.0/gems/regexp_parser-2.12.0/LICENSE +22 -0
  123. data/vendor/bundle/ruby/4.0.0/gems/rexml-3.4.4/LICENSE.txt +22 -0
  124. data/vendor/bundle/ruby/4.0.0/gems/rexml-3.4.4/README.md +57 -0
  125. data/vendor/bundle/ruby/4.0.0/gems/rspec-3.13.2/LICENSE.md +27 -0
  126. data/vendor/bundle/ruby/4.0.0/gems/rspec-3.13.2/README.md +47 -0
  127. data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/Changelog.md +2447 -0
  128. data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/LICENSE.md +26 -0
  129. data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/README.md +389 -0
  130. data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/Changelog.md +1366 -0
  131. data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/LICENSE.md +25 -0
  132. data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/README.md +326 -0
  133. data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/Changelog.md +1351 -0
  134. data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/LICENSE.md +25 -0
  135. data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/README.md +465 -0
  136. data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/Changelog.md +444 -0
  137. data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/LICENSE.md +23 -0
  138. data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/README.md +40 -0
  139. data/vendor/bundle/ruby/4.0.0/gems/rubocop-1.88.0/LICENSE.txt +20 -0
  140. data/vendor/bundle/ruby/4.0.0/gems/rubocop-1.88.0/README.md +255 -0
  141. data/vendor/bundle/ruby/4.0.0/gems/rubocop-ast-1.49.1/LICENSE.txt +20 -0
  142. data/vendor/bundle/ruby/4.0.0/gems/rubocop-ast-1.49.1/README.md +54 -0
  143. data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/CHANGELOG.md +116 -0
  144. data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/MIT-LICENSE.md +21 -0
  145. data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/README.md +91 -0
  146. data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/CHANGELOG.md +135 -0
  147. data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/MIT-LICENSE.md +21 -0
  148. data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/README.md +91 -0
  149. data/vendor/bundle/ruby/4.0.0/gems/rubocop-performance-1.26.1/LICENSE.txt +20 -0
  150. data/vendor/bundle/ruby/4.0.0/gems/rubocop-performance-1.26.1/README.md +100 -0
  151. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/CHANGELOG.md +1136 -0
  152. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/MIT-LICENSE.md +21 -0
  153. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/README.md +112 -0
  154. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/CHANGELOG.md +98 -0
  155. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/MIT-LICENSE.md +21 -0
  156. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/README.md +93 -0
  157. data/vendor/bundle/ruby/4.0.0/gems/ruby-progressbar-1.13.0/LICENSE.txt +19 -0
  158. data/vendor/bundle/ruby/4.0.0/gems/ruby-progressbar-1.13.0/README.md +131 -0
  159. data/vendor/bundle/ruby/4.0.0/gems/securerandom-0.4.1/README.md +72 -0
  160. data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/CHANGELOG.md +191 -0
  161. data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/LICENSE +20 -0
  162. data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/README.md +974 -0
  163. data/vendor/bundle/ruby/4.0.0/gems/simplecov-cobertura-3.2.0/LICENSE +202 -0
  164. data/vendor/bundle/ruby/4.0.0/gems/simplecov-cobertura-3.2.0/README.md +65 -0
  165. data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/CHANGELOG.md +114 -0
  166. data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/LICENSE +20 -0
  167. data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/README.md +30 -0
  168. data/vendor/bundle/ruby/4.0.0/gems/simplecov_json_formatter-0.1.4/CHANGELOG.md +13 -0
  169. data/vendor/bundle/ruby/4.0.0/gems/simplecov_json_formatter-0.1.4/README.md +29 -0
  170. data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/CHANGELOG.md +465 -0
  171. data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/LICENSE +22 -0
  172. data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/README.md +588 -0
  173. data/vendor/bundle/ruby/4.0.0/gems/tzinfo-2.0.6/LICENSE +19 -0
  174. data/vendor/bundle/ruby/4.0.0/gems/tzinfo-2.0.6/README.md +406 -0
  175. data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/CHANGELOG.md +299 -0
  176. data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/MIT-LICENSE.txt +22 -0
  177. data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/README.md +194 -0
  178. data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/CHANGELOG.md +202 -0
  179. data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/MIT-LICENSE.txt +20 -0
  180. data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/README.md +205 -0
  181. data/vendor/bundle/ruby/4.0.0/gems/uri-1.1.1/README.md +55 -0
  182. data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/CHANGELOG.md +2148 -0
  183. data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/LICENSE +20 -0
  184. data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/README.md +1229 -0
  185. metadata +171 -4
  186. data/doc/file.README.html +0 -192
@@ -0,0 +1,22 @@
1
+ The MIT LICENSE
2
+
3
+ Copyright (c) 2011, 2015-2024 Jan Lelis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,194 @@
1
+ # Unicode::DisplayWidth [![[version]](https://badge.fury.io/rb/unicode-display_width.svg)](https://badge.fury.io/rb/unicode-display_width) [<img src="https://github.com/janlelis/unicode-display_width/workflows/Test/badge.svg" />](https://github.com/janlelis/unicode-display_width/actions?query=workflow%3ATest)
2
+
3
+ Determines the monospace display width of a string in Ruby, which is useful for all kinds of terminal-based applications. The implementation is based on [EastAsianWidth.txt](https://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt), the [Emoji specfication](https://www.unicode.org/reports/tr51/) and other data, 100% in Ruby. It does not rely on the OS vendor ([wcwidth](https://github.com/janlelis/wcswidth-ruby)) to provide an up-to-date method for measuring string width in terminals.
4
+
5
+ Unicode version: **17.0.0** (September 2025)
6
+
7
+ ## Gem Version 3 โ€” Improved Emoji Support
8
+
9
+ **Emoji support is now enabled by default.** See below for description and configuration possibilities.
10
+
11
+ **Unicode::DisplayWidth.of now takes keyword arguments:** { ambiguous:, emoji:, overwrite: }
12
+
13
+ See [CHANGELOG](/CHANGELOG.md) for details.
14
+
15
+ ## Gem Version 2.4.2 โ€” Performance Updates
16
+
17
+ **If you use this gem, you should really upgrade to 2.4.2 or newer. It's often 100x faster, sometimes even 1000x and more!**
18
+
19
+ This is possible because the gem now detects if you use very basic (and common) characters, like ASCII characters. Furthermore, the character width lookup code has been optimized, so even when the string involves full-width or ambiguous characters, the gem is much faster now.
20
+
21
+ ## Introduction to Character Widths
22
+
23
+ Guessing the correct space a character will consume on terminals is not easy. There is no single standard. Most implementations combine data from [East Asian Width](https://www.unicode.org/reports/tr11/), some [General Categories](https://en.wikipedia.org/wiki/Unicode_character_property#General_Category), and hand-picked adjustments.
24
+
25
+ ### How this Library Handles Widths
26
+
27
+ Further at the top means higher precedence. Please expect changes to this algorithm with every MINOR version update (the X in 1.X.0)!
28
+
29
+ Width | Characters | Comment
30
+ -------|------------------------------|--------------------------------------------------
31
+ ? | (user defined) | Overwrites any other values
32
+ ? | Emoji | See "How this Library Handles Emoji Width" below
33
+ -1 | `"\b"` | Backspace (total width never below 0)
34
+ 0 | `"\0"`, `"\x05"`, `"\a"`, `"\n"`, `"\v"`, `"\f"`, `"\r"`, `"\x0E"`, `"\x0F"` | [C0 control codes](https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C0_.28ASCII_and_derivatives.29) which do not change horizontal width
35
+ 1 | `"\u{00AD}"` | SOFT HYPHEN
36
+ 2 | `"\u{2E3A}"` | TWO-EM DASH
37
+ 3 | `"\u{2E3B}"` | THREE-EM DASH
38
+ 0 | General Categories: Mn, Me, Zl, Zp, Cf (non-arabic)| Excludes ARABIC format characters
39
+ 0 | Derived Property: Default_Ignorable_Code_Point | Ignorable ranges
40
+ 0 | `"\u{1160}".."\u{11FF}"`, `"\u{D7B0}".."\u{D7FF}"` | HANGUL JUNGSEONG
41
+ 2 | East Asian Width: F, W | Full-width characters
42
+ 2 | `"\u{3400}".."\u{4DBF}"`, `"\u{4E00}".."\u{9FFF}"`, `"\u{F900}".."\u{FAFF}"`, `"\u{20000}".."\u{2FFFD}"`, `"\u{30000}".."\u{3FFFD}"` | Full-width ranges
43
+ 1 or 2 | East Asian Width: A | Ambiguous characters, user defined, default: 1
44
+ 1 | All other codepoints | -
45
+
46
+ ## Install
47
+
48
+ Install the gem with:
49
+
50
+ $ gem install unicode-display_width
51
+
52
+ Or add to your Gemfile:
53
+
54
+ gem 'unicode-display_width'
55
+
56
+ ## Usage
57
+
58
+ ```ruby
59
+ require 'unicode/display_width'
60
+
61
+ Unicode::DisplayWidth.of("โš€") # => 1
62
+ Unicode::DisplayWidth.of("ไธ€") # => 2
63
+ ```
64
+
65
+ ### Ambiguous Characters
66
+
67
+ The second parameter defines the value returned by characters defined as ambiguous:
68
+
69
+ ```ruby
70
+ Unicode::DisplayWidth.of("ยท", 1) # => 1
71
+ Unicode::DisplayWidth.of("ยท", 2) # => 2
72
+ ```
73
+
74
+ ### Encoding Notes
75
+
76
+ - Data with *BINARY* encoding is interpreted as UTF-8, if possible
77
+ - Non-UTF-8 strings are converted to UTF-8 before measuring, using the [`{invalid: :replace, undef: :replace}`) options](https://ruby-doc.org/3.3.5/encodings_rdoc.html#label-Encoding+Options)
78
+
79
+ ### Custom Overwrites
80
+
81
+ You can overwrite how to handle specific code points by passing a hash (or even a proc) as `overwrite:` parameter:
82
+
83
+ ```ruby
84
+ Unicode::DisplayWidth.of("a\tb", 1, overwrite: { "\t".ord => 10 })) # => TAB counted as 10, result is 12
85
+ ```
86
+
87
+ Please note that using overwrites disables some perfomance optimizations of this gem.
88
+
89
+ ### Emoji
90
+
91
+ If your terminal supports it, the gem detects Emoji and Emoji sequences and adjusts the width of the measured string. This can be disabled by passing `emoji: false` as an argument:
92
+
93
+ ```ruby
94
+ Unicode::DisplayWidth.of "๐Ÿคพ๐Ÿฝโ€โ™€๏ธ", emoji: :all # => 2
95
+ Unicode::DisplayWidth.of "๐Ÿคพ๐Ÿฝโ€โ™€๏ธ", emoji: false # => 5
96
+ ```
97
+
98
+ #### How this Library Handles Emoji Width
99
+
100
+ There are many Emoji which get constructed by combining other Emoji in a sequence. This makes measuring the width complicated, since terminals might either display the combined Emoji or the separate parts of the Emoji individually.
101
+
102
+ Another aspect where terminals disagree is whether Emoji characters which have a text presentation by default (width 1) should be turned into full-width (width 2) when combined with Variation Selector 16 (*U+FEOF*).
103
+
104
+ Finally, it varies if Skin Tone Modifiers can be applied to all characters or just to those with the "Emoji Base" property.
105
+
106
+ Emoji Type | Width / Comment
107
+ ------------|----------------
108
+ Basic/Single Emoji character without Variation Selector | No special handling
109
+ Basic/Single Emoji character with VS15 (Text) | No special handling
110
+ Basic/Single Emoji character with VS16 (Emoji) | 2 or East Asian Width (see table below)
111
+ Single Emoji character with Skin Tone Modifier | 2 unless Emoji mode is `:none` or `vs16`
112
+ Skin Tone Modifier used in isolation or with invalid base | 2 if Emoji mode is `:rgi` / `:rgi_at`
113
+ Emoji Sequence | 2 if Emoji belongs to configured Emoji set (see table below)
114
+
115
+ #### Emoji Modes
116
+
117
+ The `emoji:` option can be used to configure which type of Emoji should be considered to have a width of 2 and if VS16-Emoji should be widened. Other sequences are treated as non-combined Emoji, so the widths of all partial Emoji add up (e.g. width of one basic Emoji + one skin tone modifier + another basic Emoji). The following Emoji settings can be used:
118
+
119
+ `emoji:` Option | VS16-Emoji Width | Emoji Sequences Width / Comment | Example Terminals
120
+ ----------------|------------------|---------------------------------|------------------
121
+ `true` or `:auto` | - | Automatically use recommended Emoji setting for your terminal | -
122
+ `:all` | 2 | 2 for all ZWJ/modifier/keycap sequences, even if they are not well-formed Emoji sequences | iTerm, foot
123
+ `:all_no_vs16` | EAW (1 or 2) | 2 for all ZWJ/modifier/keycap sequences, even if they are not well-formed Emoji sequences | WezTerm
124
+ `:possible`| 2 | 2 for all possible/well-formed Emoji sequences | ?
125
+ `:rgi` | 2 | 2 for all [RGI Emoji](https://www.unicode.org/reports/tr51/#def_rgi_set) sequences | ?
126
+ `:rgi_at` | EAW (1 or 2) | 1 or 2: Like `:rgi`, but Emoji sequences starting with a default-text Emoji have EAW | Apple Terminal
127
+ `:vs16` | 2 | 2 * number of partial Emoji (sequences never considered to represent a combined Emoji) | kitty?
128
+ `false` or `:none` | EAW (1 or 2) | No Emoji adjustments | gnome-terminal, many older terminals
129
+
130
+ - *EAW:* East Asian Width
131
+ - *RGI Emoji:* Emoji Recommended for General Interchange
132
+ - *ZWJ:* Zero-width Joiner: Codepoint `U+200D`,used in many Emoji sequences
133
+
134
+ #### Emoji Support in Terminals
135
+
136
+ Unfortunately, the level of Emoji support varies a lot between terminals. While some of them are able to display (almost) all Emoji sequences correctly, others fall back to displaying sequences of basic Emoji. When `emoji: true` or `emoji: :auto` is used, the gem will attempt to set the best fitting Emoji setting for you (e.g. `:rgi_at` on "Apple_Terminal" or `false` on Gnome's terminal widget).
137
+
138
+ Please note that Emoji display and number of terminal columns used might differs a lot. For example, it might be the case that a terminal does not understand which Emoji to display, but still manages to calculate the proper amount of terminal cells. The automatic Emoji support level per terminal only considers the latter (cursor position), not the actual Emoji image(s) displayed. Please [open an issue](https://github.com/janlelis/unicode-display_width/issues/new) if you notice your terminal application could use a better default value. Also see the [ucs-detect project](https://ucs-detect.readthedocs.io/results.html), which is a great resource that compares various terminal's Unicode/Emoji capabilities. You can visually check how your terminals renders different kind of Emoji types with the [terminal-emoji-width.rb script](https://github.com/janlelis/unicode-display_width/blob/main/misc/terminal-emoji-width.rb).
139
+
140
+ **To terminal implementors reading this:** Although the practice of giving all Emoji/ZWJ sequences a width of 2 (`:all` mode described above) has some advantages, it does not lead to a particularly good developer experience. Since there is always the possibility of well-formed Emoji that are currently not supported (non-RGI / future Unicode) appearing, those sequences will take more cells. Instead of overflowing, cutting off sequences or displaying placeholder-Emoji, could it be worthwile to implement the `:rgi` option (only known Emoji get width 2) and give those unknown Emoji the space they need? This would support the idea that the meaning of an unknown Emoji sequence can still be conveyed (without messing up the terminal at the same time). Just a thoughtโ€ฆ
141
+
142
+ ### Usage with String Extension
143
+
144
+ ```ruby
145
+ require 'unicode/display_width/string_ext'
146
+
147
+ "โš€".display_width # => 1
148
+ 'ไธ€'.display_width # => 2
149
+ ```
150
+
151
+ ### Usage with Config Object
152
+
153
+ You can use a config object that allows you to save your configuration for later-reuse. This requires an extra line of code, but has the advantage that you'll need to define your string-width options only once:
154
+
155
+ ```ruby
156
+ require 'unicode/display_width'
157
+
158
+ display_width = Unicode::DisplayWidth.new(
159
+ # ambiguous: 1,
160
+ overwrite: { "A".ord => 100 },
161
+ emoji: :all,
162
+ )
163
+
164
+ display_width.of "โš€" # => 1
165
+ display_width.of "๐Ÿค โ€๐Ÿคข" # => 2
166
+ display_width.of "A" # => 100
167
+ ```
168
+
169
+ ### Usage from the Command-Line
170
+
171
+ Use this one-liner to print out display widths for strings from the command-line:
172
+
173
+ ```
174
+ $ gem install unicode-display_width
175
+ $ ruby -r unicode/display_width -e 'puts Unicode::DisplayWidth.of $*[0]' -- "ไธ€"
176
+ ```
177
+ Replace "ไธ€" with the actual string to measure
178
+
179
+ ## Other Implementations & Discussion
180
+
181
+ - Python: https://github.com/jquast/wcwidth
182
+ - JavaScript: https://github.com/mycoboco/wcwidth.js
183
+ - C: https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
184
+ - C for Julia: https://github.com/JuliaLang/utf8proc/issues/2
185
+ - Golang: https://github.com/rivo/uniseg
186
+
187
+ See [unicode-x](https://github.com/janlelis/unicode-x) for more Unicode related micro libraries.
188
+
189
+ ## Copyright & Info
190
+
191
+ - Copyright (c) 2011, 2015-2025 Jan Lelis, https://janlelis.com, released under the MIT
192
+ license
193
+ - Early versions based on runpaint's unicode-data interface: Copyright (c) 2009 Run Paint Run Run
194
+ - Unicode data: https://www.unicode.org/copyright.html#Exhibit1
@@ -0,0 +1,202 @@
1
+ # CHANGELOG
2
+
3
+ ## 4.2.0
4
+
5
+ - Allow Ruby 4.0
6
+ - Remove Non-Emoji pictographs from spec, since they have been removed in Unicode 17
7
+ - Update valid subdivisions to CLDR 48 (no changes)
8
+
9
+ ## 4.1.0
10
+
11
+ - Unicode 17
12
+ - Update valid subdivisions to CLDR 47 (no changes)
13
+
14
+ ## 4.0.4
15
+
16
+ - Add `REGEX_TEXT_PRESENTATION` to be able to match for raw default-text Emoji codepoints
17
+
18
+ ## 4.0.3
19
+
20
+ - Remove emoji-test.txt from Rubygems package
21
+
22
+ ## 4.0.2
23
+
24
+ - Directly use `RbConfig::CONFIG["UNICODE_EMOJI_VERSION"]` to detect Ruby's Emoji version,
25
+ drop unicode-version dependency
26
+
27
+ ## 4.0.0
28
+
29
+ - **Breaking change:** Regexes now include single skin tone modifiers (`๐Ÿป`) and hair components (`๐Ÿฆฐ`).
30
+ They were previously considered to be invalid partial Emoji, however since they are supposed to be
31
+ displayed as Emoji in isolation, they are now part of the regexes (see *ED-20* in UTS51).
32
+ - **Breaking change:** Drop `REGEX_ANY` in favor of `REGEX_PROP_EMOJI`
33
+ - Expose regexes for Emoji props (`REGEX_PROP_*`). The advantage over using the native regex properties
34
+ directly is that you will be able to use the Emoji support level of this gem instead of Ruby's.
35
+ For example, as of releasing this, the current Emoji version is 16.0, while Ruby is at 15.0.
36
+ Also see README for a table listing the regexes that match Emoji properties.
37
+ - Add `REGEX_EMOJI_KEYCAP` for matching specifically Emoji keycaps
38
+ - Use character class instead of lookbehind for native text emoji and non-emoji pictographic regexes
39
+
40
+ ## 3.8.0
41
+
42
+ - Add new RGI-based regexes `REGEX_INCLUDE_MQE` and `REGEX_INCLUDE_MQE_UQE` which allows to match
43
+ for minimally-qualified and unqualified RGI sequences (Emoji that lack some VS16)
44
+ - Add specs running through `emoji-text.txt` and classify qualification statuses per regex
45
+ - Improve documentation and add detailed table about which regex has which features
46
+ - Native regexes: Use native Emoji props for Emoji text presentation
47
+ - Update CLDR to v46 (valid subdivisions)
48
+ - Further improvements (see commit log)
49
+
50
+ ## 3.7.0
51
+
52
+ - Bump required Ruby slightly to 2.5
53
+ - Introduce new `REGEX_POSSIBLE` which contains the regex described in
54
+ https://www.unicode.org/reports/tr51/#EBNF_and_Regex
55
+ - Fix that some valid subdivisions were not decompressed (`REGEX_VALID`)
56
+ - Be stricter about selection of tag characters in `REGEX_WELL_FORMED`
57
+ - Only U+E0030..U+E0039, U+E0061..U+E007A allowed
58
+ - Max tag sequence length
59
+ - Use native `/\p{RI}/` regex for regional indicators
60
+ - Separately autoload emoji list, so it can be loaded when other indexes
61
+ are not needed
62
+
63
+ ## 3.6.0
64
+
65
+ - `Unicode::Emoji::REGEX_TEXT` now matches non-emoji keycaps like "3โƒฃ" (U+0033 U+20E3)
66
+ - Minor refactorings
67
+
68
+ ## 3.5.0
69
+
70
+ - Emoji 16.0
71
+
72
+ ## 3.4.0
73
+
74
+ - Emoji 15.1
75
+
76
+ ## 3.3.2
77
+
78
+ - Update valid subdivisions to CLDR 43 (no changes)
79
+ -> there won't be any new RGI subdivision flags in Emoji
80
+
81
+ ## 3.3.1
82
+
83
+ - Update valid subdivisions to CLDR 42 (no changes)
84
+
85
+ ## 3.3.0
86
+
87
+ - Emoji 15.0
88
+
89
+ ## 3.2.0
90
+
91
+ - Update valid subdivisions to CLDR 41
92
+
93
+ ## 3.1.1
94
+
95
+ - Fix `REGEX` to be able to match complete family emoji, instead of
96
+ sub-matching partial families, thanks @matt17r
97
+
98
+ ## 3.1.0
99
+
100
+ - Update valid subdivisions to CLDR 40
101
+
102
+ ## 3.0.0
103
+
104
+ - Vastly improve memory usage, patch by @radarek
105
+ - Emoji regexes are now pre-generated and bundled with the release
106
+ - Regexes use character classes instead of unions when possible
107
+ - Most constants (e.g. regexes) now get autoloaded
108
+ - See https://github.com/janlelis/unicode-emoji/pull/9 for more details
109
+
110
+ ## 2.9.0
111
+
112
+ - Emoji 14.0
113
+
114
+ ## 2.8.0
115
+
116
+ - Update valid subdivisions to CLDR 39
117
+
118
+ ## 2.7.1
119
+
120
+ - Update valid subdivisions to CLDR 38.1
121
+
122
+ ## 2.7.0
123
+
124
+ - Update valid subdivisions to CLDR 38
125
+ - Loosen Ruby dependency to allow Ruby 3.0
126
+
127
+ ## 2.6.0
128
+
129
+ - Emoji 13.1
130
+
131
+ ## 2.5.0
132
+
133
+ - Use native Emoji regex properties when current Ruby's Emoji support is the same as our current Emoji version
134
+ - Update valid subdivisions to CLDR 37
135
+
136
+ ## 2.4.0
137
+
138
+ - Emoji 13.0
139
+
140
+ ## 2.3.1
141
+
142
+ - Fix index to actually include Emoji 12.1
143
+
144
+ ## 2.3.0
145
+
146
+ - Emoji 12.1
147
+
148
+ ## 2.2.0
149
+
150
+ - Update subdivisions to CLDR 36
151
+
152
+ ## 2.1.0
153
+
154
+ - Add `REGEX_PICTO` which matches codepoints with the **Extended_Pictographic** property
155
+ - Add `REGEX_PICTO_NO_EMOJI` which matches codepoints with the **Extended_Pictographic** property, but no **Emoji** property
156
+
157
+ ## 2.0.0
158
+
159
+ - Emoji 12.0 data (including valid subdivisions)
160
+ - Introduce new `REGEX_WELL_FORMED` to be able to match for invalid tag and region sequences
161
+ - Introduce new `*_INCLUDE_TEXT` regexes which include matching for textual presentation emoji
162
+ - Refactoring: Update Emoji matching to latest standard while keeping naming close to standard
163
+ - Issue warning when using `#list` method to retrieve outdated category
164
+ - Change matching for ZWJ sequences: Do not limit sequence to a maximum of 3 ZWJs
165
+
166
+ ## 1.1.0
167
+
168
+ - Emoji 11.0
169
+ - Do not depend on rubygems (only use zlib stdlib for unzipping)
170
+
171
+ ## 1.0.3
172
+
173
+ - Explicitly load rubygems/util, fixes regression in 1.2.1
174
+
175
+ ## 1.0.2
176
+
177
+ - Use `Gem::Util` for `gunzip`, removes deprecation warning
178
+
179
+ ## 1.0.1
180
+
181
+ - Actually set required Ruby version to 2.3 in gemspec
182
+
183
+ ## 1.0.0
184
+
185
+ - Drop support for Ruby below 2.3, use 0.9 if you need to
186
+ - Internal refactorings, no API change
187
+
188
+ ## 0.9.3
189
+
190
+ - Implement native Emoji regex matchers, but do not activate or document, yet
191
+
192
+ ## 0.9.2
193
+
194
+ - REGEX_TEXT: Do not match if the text emoji is followed by a emoji modifier
195
+
196
+ ## 0.9.1
197
+
198
+ - Include a categorized list of recommended Emoji
199
+
200
+ ## 0.9.0
201
+
202
+ - Initial release (Emoji version 5.0)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2017-2024 Jan Lelis, https://janlelis.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,205 @@
1
+ # Unicode::Emoji [![[version]](https://badge.fury.io/rb/unicode-emoji.svg)](https://badge.fury.io/rb/unicode-emoji) [![[ci]](https://github.com/janlelis/unicode-emoji/workflows/Test/badge.svg)](https://github.com/janlelis/unicode-emoji/actions?query=workflow%3ATest)
2
+
3
+ Provides various sophisticated regular expressions to work with Emoji in strings,
4
+ incorporating the latest Unicode / Emoji standards.
5
+
6
+ Additional features:
7
+
8
+ - A categorized list of Emoji (RGI: Recommended for General Interchange)
9
+ - Retrieve Emoji properties info about specific codepoints (Emoji_Modifier, Emoji_Presentation, etc.)
10
+
11
+ Emoji version: **17.0** (September 2025)
12
+
13
+ CLDR version (used for sub-region flags): **47** (March 2025)
14
+
15
+ ## Gemfile
16
+
17
+ ```ruby
18
+ gem "unicode-emoji"
19
+ ```
20
+
21
+ ## Usage โ€“ Regex Matching
22
+
23
+ The gem includes multiple Emoji regexes, which are compiled out of various Emoji Unicode data sources.
24
+
25
+ ```ruby
26
+ require "unicode/emoji"
27
+
28
+ string = "String which contains all types of Emoji sequences:
29
+
30
+ - Basic Emoji: ๐Ÿ˜ด
31
+ - Textual Emoji with Emoji variation (VS16): โ–ถ๏ธ
32
+ - Emoji with skin tone modifier: ๐Ÿ›Œ๐Ÿฝ
33
+ - Region flag: ๐Ÿ‡ต๐Ÿ‡น
34
+ - Sub-Region flag: ๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ
35
+ - Keycap sequence: 2๏ธโƒฃ
36
+ - Skin tone modifier: ๐Ÿป
37
+ - Sequence using ZWJ (zero width joiner): ๐Ÿคพ๐Ÿฝโ€โ™€๏ธ
38
+ "
39
+
40
+ string.scan(Unicode::Emoji::REGEX) # => ["๐Ÿ˜ด", "โ–ถ๏ธ", "๐Ÿ›Œ๐Ÿฝ", "๐Ÿ‡ต๐Ÿ‡น", "๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ", "2๏ธโƒฃ", "๐Ÿป", "๐Ÿคพ๐Ÿฝโ€โ™€๏ธ"]
41
+ ```
42
+
43
+ Depending on your exact usecase, you can choose between multiple levels of Emoji detection:
44
+
45
+ ### Main Regexes
46
+
47
+ Regex | Description | Example Matches | Example Non-Matches
48
+ ------------------------------|-------------|-----------------|--------------------
49
+ `Unicode::Emoji::REGEX` | **Use this one if unsure!** Matches (non-textual) Basic Emoji and all kinds of *recommended* Emoji sequences (RGI/FQE) | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿป` | `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `๐Ÿ‡ต๐Ÿ‡ต`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿค โ€๐Ÿคข`, `1`, `1โƒฃ`
50
+ `Unicode::Emoji::REGEX_VALID` | Matches (non-textual) Basic Emoji and all kinds of *valid* Emoji sequences | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€` ,`๐ŸŒโ€โ™‚๏ธ`, `๐Ÿค โ€๐Ÿคข`, `๐Ÿป` | `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `๐Ÿ‡ต๐Ÿ‡ต`, `1`, `1โƒฃ`
51
+ `Unicode::Emoji::REGEX_WELL_FORMED` | Matches (non-textual) Basic Emoji and all kinds of *well-formed* Emoji sequences | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€`,`๐ŸŒโ€โ™‚๏ธ` , `๐Ÿค โ€๐Ÿคข`, `๐Ÿ‡ต๐Ÿ‡ต`, `๐Ÿป` | `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `1`, `1โƒฃ`
52
+ `Unicode::Emoji::REGEX_POSSIBLE` | Matches all singleton Emoji, all kinds of Emoji sequences, and even non-Emoji singleton components like digits. Only exception: Unqualified keycap sequences are not matched | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿค โ€๐Ÿคข`, `๐Ÿ‡ต๐Ÿ‡ต`, `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `๐Ÿป`, `1` | `1โƒฃ`
53
+
54
+ #### Include Text Emoji
55
+
56
+ By default, textual Emoji (emoji characters with text variation selector or those that have a default text presentation) will not be included in the default regexes (except in `REGEX_POSSIBLE`). However, if you wish to match for them too, you can include them in your regex by appending the `_INCLUDE_TEXT` suffix:
57
+
58
+ Regex | Description | Example Matches | Example Non-Matches
59
+ ------------------------------|-------------|-----------------|--------------------
60
+ `Unicode::Emoji::REGEX_INCLUDE_TEXT` | `REGEX` + `REGEX_TEXT` | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `1โƒฃ` , `๐Ÿป`| `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿ‡ต๐Ÿ‡ต`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿค โ€๐Ÿคข`, `1`
61
+ `Unicode::Emoji::REGEX_VALID_INCLUDE_TEXT` | `REGEX_VALID` + `REGEX_TEXT` | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿค โ€๐Ÿคข`, `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `1โƒฃ` , `๐Ÿป` | `๐Ÿ‡ต๐Ÿ‡ต`, `1`
62
+ `Unicode::Emoji::REGEX_WELL_FORMED_INCLUDE_TEXT` | `REGEX_WELL_FORMED` + `REGEX_TEXT` | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿค โ€๐Ÿคข`, `๐Ÿ‡ต๐Ÿ‡ต`, `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `1โƒฃ` , `๐Ÿป` | `1`
63
+
64
+ #### Minimally-qualified and Unqualified Sequences
65
+
66
+ Regex | Description | Example Matches | Example Non-Matches
67
+ ------------------------------|-------------|-----------------|--------------------
68
+ `Unicode::Emoji::REGEX_INCLUDE_MQE` | Like `REGEX`, but additionally includes Emoji with missing Emoji Presentation Variation Selectors, where the first partial Emoji has all required Variation Selectors | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐Ÿป` | `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `๐Ÿ‡ต๐Ÿ‡ต`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿค โ€๐Ÿคข`, `1`, `1โƒฃ`
69
+ `Unicode::Emoji::REGEX_INCLUDE_MQE_UQE` | Like `REGEX`, but additionally includes Emoji with missing Emoji Presentation Variation Selectors | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿป` | `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `๐Ÿ‡ต๐Ÿ‡ต`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿค โ€๐Ÿคข`, `1`, `1โƒฃ`
70
+
71
+ [List of MQE and UQE Emoji sequences](https://character.construction/unqualified-emoji)
72
+
73
+ #### Singleton Regexes
74
+
75
+ Matches only simple one-codepoint (+ optional variation selector) Emoji:
76
+
77
+ Regex | Description | Example Matches | Example Non-Matches
78
+ ------------------------------|-------------|-----------------|--------------------
79
+ `Unicode::Emoji::REGEX_BASIC` | Matches (non-textual) Basic Emoji, but no sequences at all | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿป` | `๐Ÿ˜ด๏ธŽ`, `โ–ถ`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `๐Ÿ‡ต๐Ÿ‡ต`,`2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿค โ€๐Ÿคข`, `1`
80
+ `Unicode::Emoji::REGEX_TEXT` | Matches only textual singleton Emoji | `๐Ÿ˜ด๏ธŽ`, `โ–ถ` | `๐Ÿ˜ด`, `โ–ถ๏ธ`, `๐Ÿป`, `๐Ÿ›Œ๐Ÿฝ`, `๐Ÿ‡ต๐Ÿ‡น`, `๐Ÿ‡ต๐Ÿ‡ต`,`2๏ธโƒฃ`, `๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ`, `๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ`, `๐Ÿคพ๐Ÿฝโ€โ™€๏ธ`, `๐Ÿคพ๐Ÿฝโ€โ™€`, `๐ŸŒโ€โ™‚๏ธ`, `๐Ÿค โ€๐Ÿคข`, `1`
81
+
82
+ Here is a list of all Emoji that can be matched using the two regexes: [character.construction/emoji-vs-text](https://character.construction/emoji-vs-text). The `REGEX_BASIC` regex also matches [visual Emoji components](https://character.construction/emoji-components) (skin tone modifiers and hair components).
83
+
84
+ While `REGEX_BASIC` is part of the above regexes, `REGEX_TEXT` is only included in the `*_INCLUDE_TEXT` or `*_UQE` variants.
85
+
86
+ ### Comparison
87
+
88
+ 1) Fully-qualified RGI Emoji ZWJ sequence
89
+ 2) Minimally-qualified RGI Emoji ZWJ sequence (lacks Emoji Presentation Selectors, but not in the first Emoji character)
90
+ 3) Unqualified RGI Emoji ZWJ sequence (lacks Emoji Presentation Selector, including in the first Emoji character). Unqualified Emoji include all basic Emoji in Text Presentation (see column 11/12).
91
+ 4) Non-RGI Emoji ZWJ sequence
92
+ 5) Valid Region made from a pair of Regional Indicators
93
+ 6) Any Region made from a pair of Regional Indicators
94
+ 7) RGI Flag Emoji Tag Sequences (England, Scotland, Wales)
95
+ 8) Valid Flag Emoji Tag Sequences (any known subdivision)
96
+ 9) Any Emoji Tag Sequences (any tag sequence with any base)
97
+ 10) Basic Default Emoji Presentation Characters or Text characters with Emoji Presentation Selector
98
+ 11) Basic Default Text Presentation Characters or Basic Emoji with Text Presentation Selector
99
+ 12) Non-Emoji (unqualified) keycap
100
+
101
+ Regex | 1 RGI/FQE | 2 RGI/MQE | 3 RGI/UQE | 4 Non-RGI | 5 Valid Reยญgion | 6 Any Reยญgion | 7 RGI Tag | 8 Valid Tag | 9 Any Tag | 10 Basic Emoji | 11 Basic Text | 12 Text Keyยญcap
102
+ -|-|-|-|-|-|-|-|-|-|-|-|-
103
+ REGEX | โœ… | โŒ | โŒ | โŒ | โœ… | โŒ | โœ… | โŒ | โŒ | โœ… | โŒ | โŒ
104
+ REGEX INCLUDE TEXT | โœ… | โŒ | โŒ | โŒ | โœ… | โŒ | โœ… | โŒ | โŒ | โœ… | โœ… | โœ…
105
+ REGEX INCLUDE MQE | โœ… | โœ… | โŒ | โŒ | โœ… | โŒ | โœ… | โŒ | โŒ | โœ… | โŒ | โŒ
106
+ REGEX INCLUDE MQE UQE | โœ… | โœ… | โœ… | โŒ | โœ… | โŒ | โœ… | โŒ | โŒ | โœ… | โœ… | โœ…
107
+ REGEX VALID | โœ… | โœ… | (โœ…)ยน | โœ… | โœ… | โŒ | โœ… | โœ… | โŒ | โœ… | โŒ | โŒ
108
+ REGEX VALID INCLUDE TEXT | โœ… | โœ… | โœ… | โœ… | โœ… | โŒ | โœ… | โœ… | โŒ | โœ… | โœ… | โœ…
109
+ REGEX WELL FORMED | โœ… | โœ… | (โœ…)ยน | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โŒ | โŒ
110
+ REGEX WELL FORMED INCLUDE TEXT | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ…
111
+ REGEX POSSIBLE | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โœ… | โŒ
112
+ REGEX BASIC | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โœ… | โŒ | โŒ
113
+ REGEX TEXT | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โŒ | โœ… | โœ…
114
+
115
+ ยน Matches all unqualified Emoji, except for textual singleton Emoji (see columns 11, 12)
116
+
117
+ See [spec files](/spec) for detailed examples about which regex matches which kind of Emoji.
118
+
119
+ ### Picking the Right Emoji Regex
120
+
121
+ - Usually you just want `REGEX` (recommended Emoji set, RGI)
122
+ - Use `REGEX_INCLUDE_MQE` or `REGEX_INCLUDE_MQE_UQE` if you want to catch Emoji sequences with missing Variation Selectors.
123
+ - If you want broader matching (any ZWJ sequences, more sub-region flags), choose `REGEX_VALID`
124
+ - If you need to match any region flag and any tag sequence, choose `REGEX_WELL_FORMED`
125
+ - Use the `_INCLUDE_TEXT` suffix with any of the above base regexes, if you want to also match basic textual Emoji
126
+ - And finally, there is also the option to use `REGEX_POSSIBLE`, which is a simplified test for possible Emoji, comparable to `REGEX_WELL_FORMED*`. It might contain false positives, however, the regex is less complex and [suggested in the Unicode standard itself](https://www.unicode.org/reports/tr51/#EBNF_and_Regex) as a first check.
127
+
128
+ ### Examples
129
+
130
+ Desc | Emoji | Escaped | `REGEX` (RGI/FQE) | `REGEX_INCLUDE_MQE` (RGI/MQE) | `REGEX_VALID` | `REGEX_WELL_FORMED` / `REGEX_POSSIBLE`
131
+ -----|-------|---------|---------------|-----------------------|-----------------------------------|-----------------
132
+ RGI ZWJ Sequence | ๐Ÿคพ๐Ÿฝโ€โ™€๏ธ | `\u{1F93E 1F3FD 200D 2640 FE0F}` | โœ… | โœ… | โœ… | โœ…
133
+ RGI ZWJ Sequence MQE | ๐Ÿคพ๐Ÿฝโ€โ™€ | `\u{1F93E 1F3FD 200D 2640}` | โŒ | โœ… | โœ… | โœ…
134
+ Valid ZWJ Sequence, Non-RGI | ๐Ÿค โ€๐Ÿคข | `\u{1F920 200D 1F922}` | โŒ | โŒ | โœ… | โœ…
135
+ Known Region | ๐Ÿ‡ต๐Ÿ‡น | `\u{1F1F5 1F1F9}` | โœ… | โœ… | โœ… | โœ…
136
+ Unknown Region | ๐Ÿ‡ต๐Ÿ‡ต | `\u{1F1F5 1F1F5}` | โŒ | โŒ | โŒ | โœ…
137
+ RGI Tag Sequence | ๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ | `\u{1F3F4 E0067 E0062 E0073 E0063 E0074 E007F}` | โœ… | โœ… | โœ… | โœ…
138
+ Valid Tag Sequence | ๐Ÿด๓ ง๓ ข๓ ก๓ ง๓ ข๓ ฟ | `\u{1F3F4 E0067 E0062 E0061 E0067 E0062 E007F}` | โŒ | โŒ | โœ… | โœ…
139
+ Well-formed Tag Sequence | ๐Ÿ˜ด๓ ง๓ ข๓ ก๓ ก๓ ก๓ ฟ | `\u{1F634 E0067 E0062 E0061 E0061 E0061 E007F}` | โŒ | โŒ | โŒ | โœ…
140
+
141
+ Please see [the standard](https://www.unicode.org/reports/tr51/#Emoji_Sets) for more details, examples, explanations.
142
+
143
+ More info about valid vs. recommended Emoji can also be found in this [blog article on Emojipedia](https://blog.emojipedia.org/unicode-behind-the-curtain/).
144
+
145
+ ### Emoji Property Regexes
146
+
147
+ Ruby includes native regex Emoji properties, as listed in the following table. You can also opt-in to use the `*_PROP_*` regexes to get the Emoji support level of this gem (instead of Ruby's). [Which Emoji version does Ruby support?](https://idiosyncratic-ruby.com/73-unicode-version-mapping.html#ruby--emoji)
148
+
149
+ Gem Regex (`Unicode::Emoji`'s Emoji support level) | Native Regex (Ruby's Emoji support level)
150
+ ---------------------------------------------------|------------------------------------------
151
+ `Unicode::Emoji::REGEX_PROP_EMOJI` | `/\p{Emoji}/`
152
+ `Unicode::Emoji::REGEX_PROP_MODIFIER` | `/\p{EMod}/`
153
+ `Unicode::Emoji::REGEX_PROP_MODIFIER_BASE` | `/\p{EBase}/`
154
+ `Unicode::Emoji::REGEX_PROP_COMPONENT` | `/\p{EComp}/`
155
+ `Unicode::Emoji::REGEX_PROP_PRESENTATION` | `/\p{EPres}/`
156
+ `Unicode::Emoji::REGEX_TEXT_PRESENTATION` | `/[\p{Emoji}&&\P{EPres}]/`
157
+
158
+ #### Extended Pictographic Regex
159
+
160
+ `Unicode::Emoji::REGEX_PICTO` matches single codepoints with the **Extended_Pictographic** property. For example, it will match `โœ€` BLACK SAFETY SCISSORS.
161
+
162
+ `Unicode::Emoji::REGEX_PICTO_NO_EMOJI` matches single codepoints with the **Extended_Pictographic** property, but excludes Emoji characters.
163
+
164
+ See [character.construction/picto](https://character.construction/picto) for a list of all non-Emoji pictographic characters.
165
+
166
+ ## Usage โ€“ List
167
+
168
+ Use `Unicode::Emoji::LIST` or the **list** method to get a ordered and categorized list of Emoji:
169
+
170
+ ```ruby
171
+ Unicode::Emoji.list.keys
172
+ # => ["Smileys & Emotion", "People & Body", "Component", "Animals & Nature", "Food & Drink", "Travel & Places", "Activities", "Objects", "Symbols", "Flags"]
173
+
174
+ Unicode::Emoji.list("Food & Drink").keys
175
+ # => ["food-fruit", "food-vegetable", "food-prepared", "food-asian", "food-marine", "food-sweet", "drink", "dishware"]
176
+
177
+ Unicode::Emoji.list("Food & Drink", "food-asian")
178
+ => ["๐Ÿฑ", "๐Ÿ˜", "๐Ÿ™", "๐Ÿš", "๐Ÿ›", "๐Ÿœ", "๐Ÿ", "๐Ÿ ", "๐Ÿข", "๐Ÿฃ", "๐Ÿค", "๐Ÿฅ", "๐Ÿฅฎ", "๐Ÿก", "๐ŸฅŸ", "๐Ÿฅ ", "๐Ÿฅก"]
179
+ ```
180
+
181
+ Please note that categories might change with future versions of the Emoji standard, although this has not happened often.
182
+
183
+ A list of all Emoji (generated from this gem) can be found at [character.construction/emoji](https://character.construction/emoji).
184
+
185
+ ## Usage โ€“ Properties Data
186
+
187
+ Allows you to access the codepoint data for a single character form Unicode's [emoji-data.txt](https://www.unicode.org/Public/16.0.0/ucd/emoji/emoji-data.txt) file:
188
+
189
+ ```ruby
190
+ require "unicode/emoji"
191
+
192
+ Unicode::Emoji.properties "โ˜" # => ["Emoji", "Emoji_Modifier_Base"]
193
+ ```
194
+
195
+ ## Also See
196
+
197
+ - [Unicodeยฎ Technical Standard #51](https://www.unicode.org/reports/tr51/)
198
+ - [Emoji categories](https://unicode.org/emoji/charts/emoji-ordering.html)
199
+ - Ruby gem which displays [Emoji sequence names](https://github.com/janlelis/unicode-sequence_name) ([as website](https://character.construction/name))
200
+ - Part of [unicode-x](https://github.com/janlelis/unicode-x)
201
+
202
+ ## MIT
203
+
204
+ - Copyright (C) 2017-2025 Jan Lelis <https://janlelis.com>. Released under the MIT license.
205
+ - Unicode data: https://www.unicode.org/copyright.html#Exhibit1