strings-case 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +317 -0
- data/Rakefile +8 -0
- data/lib/strings-case.rb +1 -0
- data/lib/strings/case.rb +304 -0
- data/lib/strings/case/extensions.rb +50 -0
- data/lib/strings/case/version.rb +7 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/unit/camelcase_spec.rb +51 -0
- data/spec/unit/constcase_spec.rb +44 -0
- data/spec/unit/extensions_spec.rb +75 -0
- data/spec/unit/headercase_spec.rb +50 -0
- data/spec/unit/kebabcase_spec.rb +48 -0
- data/spec/unit/pascalcase_spec.rb +51 -0
- data/spec/unit/pathcase_spec.rb +51 -0
- data/spec/unit/sentencecase_spec.rb +51 -0
- data/spec/unit/snakecase_spec.rb +51 -0
- data/spec/unit/titlecase_spec.rb +51 -0
- data/strings-case.gemspec +32 -0
- data/tasks/console.rake +11 -0
- data/tasks/coverage.rake +11 -0
- data/tasks/spec.rake +29 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5985a29d7cd211560f31949ea90cacd559ec100cc993c12cd2d5c2a6c0fdb683
|
4
|
+
data.tar.gz: 9e542cd6473627f1f5bad0b05ec47a0e8b667bcbf00377cac5a918da13524fad
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9e73e4189c6af4a9458022af07b20a8863e9fb344dadd223a1e86ba16c44a2a798c7d8fd5f663b556e89f7c8577d060791eb05c59bc967c9d9e07faa39d07ac6
|
7
|
+
data.tar.gz: 7052e5e1fffd616a6c00fb92cb2869586a21232d062f1625c09503c79b396a21e645e432d63a648f479465ac99b25f25dfc83b1284009bff79a230d662ee7711
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Piotr Murach
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
<div align="center">
|
2
|
+
<img width="225" src="https://github.com/piotrmurach/strings/blob/master/assets/strings_logo.png" alt="strings logo" />
|
3
|
+
</div>
|
4
|
+
|
5
|
+
# Strings::Case
|
6
|
+
|
7
|
+
[![Gem Version](https://badge.fury.io/rb/strings-case.svg)][gem]
|
8
|
+
[![Build Status](https://secure.travis-ci.org/piotrmurach/strings-case.svg?branch=master)][travis]
|
9
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/yr87c96wxp1cw2ep?svg=true)][appveyor]
|
10
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/7938258c4af196a19843/maintainability)][codeclimate]
|
11
|
+
[![Coverage Status](https://coveralls.io/repos/github/piotrmurach/strings-case/badge.svg?branch=master)][coverage]
|
12
|
+
[![Inline docs](http://inch-ci.org/github/piotrmurach/strings-case.svg?branch=master)][inchpages]
|
13
|
+
|
14
|
+
[gem]: http://badge.fury.io/rb/strings-case
|
15
|
+
[travis]: http://travis-ci.org/piotrmurach/strings-case
|
16
|
+
[appveyor]: https://ci.appveyor.com/project/piotrmurach/strings-case
|
17
|
+
[codeclimate]: https://codeclimate.com/github/piotrmurach/strings-case/maintainability
|
18
|
+
[coverage]: https://coveralls.io/github/piotrmurach/strings-case?branch=master
|
19
|
+
[inchpages]: http://inch-ci.org/github/piotrmurach/strings-case
|
20
|
+
|
21
|
+
> Convert strings to different cases.
|
22
|
+
|
23
|
+
**Strings::Case** provides string case conversions for [Strings](https://github.com/piotrmurach/strings) utilities.
|
24
|
+
|
25
|
+
## Motivation
|
26
|
+
|
27
|
+
Popular solutions that deal with transforming string cases work well in simple cases.(Sorry ;-) With more complex strings you may get unexpected results:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
ActiveSupport::Inflector.underscore("supports IPv6 on iOS?")
|
31
|
+
# => "supports i_pv6 on i_os?"
|
32
|
+
```
|
33
|
+
|
34
|
+
In contrast, `Strings::Case` aims to be able to transform any string to expected case:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
Strings::Case.underscore("supports IPv6 on iOS?")
|
38
|
+
# => "supports_ipv6_on_ios"
|
39
|
+
```
|
40
|
+
|
41
|
+
## Installation
|
42
|
+
|
43
|
+
Add this line to your application's Gemfile:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
gem 'strings-case'
|
47
|
+
```
|
48
|
+
|
49
|
+
And then execute:
|
50
|
+
|
51
|
+
$ bundle
|
52
|
+
|
53
|
+
Or install it yourself as:
|
54
|
+
|
55
|
+
$ gem install strings-case
|
56
|
+
|
57
|
+
|
58
|
+
## Features
|
59
|
+
|
60
|
+
* No monkey-patching String class
|
61
|
+
* Converts any string to specified case
|
62
|
+
* Supports Unicode characters
|
63
|
+
* Provides many common case transformations
|
64
|
+
* Allows to preserve casing of acronyms
|
65
|
+
|
66
|
+
## Contents
|
67
|
+
|
68
|
+
* [1. Usage](#1-usage)
|
69
|
+
* [2. API](#2-api)
|
70
|
+
* [2.1 camelcase](#21-camelcase)
|
71
|
+
* [2.2 constcase](#22-constcase)
|
72
|
+
* [2.3 headercase](#23-headercase)
|
73
|
+
* [2.4 kebabcase | dashcase](#24-kebabcase--dashcase)
|
74
|
+
* [2.5 pascalcase](#25-pascalcase)
|
75
|
+
* [2.6 pathcase](#26-pathcase)
|
76
|
+
* [2.7 sentencecase](#27-sentencecase)
|
77
|
+
* [2.8 snakecase | underscore](#28-snakecase--underscore)
|
78
|
+
* [2.9 titlecase](#29-titlecase)
|
79
|
+
* [3. Extending String class](#3-extending-string-class)
|
80
|
+
|
81
|
+
## 1. Usage
|
82
|
+
|
83
|
+
The `Strings::Case` is a module with functions for transforming between string cases:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
Strings::Case.snakecase("foo bar baz")
|
87
|
+
# => "foo_bar_baz"
|
88
|
+
````
|
89
|
+
|
90
|
+
It will transform any string into expected case:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Strings::Case.snake_case("supports IPv6 on iOS?")
|
94
|
+
# => "supports_ipv6_on_ios"
|
95
|
+
```
|
96
|
+
|
97
|
+
You can apply case transformations to Unicode characters:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
Strings::Case.snake_case("ЗдравствуйтеПривет")
|
101
|
+
# => "здравствуйте_привет"
|
102
|
+
```
|
103
|
+
|
104
|
+
Here is a quick summary of available transformations:
|
105
|
+
|
106
|
+
| Case Type | Result |
|
107
|
+
| --------- | ------- |
|
108
|
+
| ```Strings::Case.camelcase("foo bar baz")``` | `"fooBarBaz"` |
|
109
|
+
| ```Strings::Case.constcase("foo bar baz")``` | `"FOO_BAR_BAZ"` |
|
110
|
+
| ```Strings::Case.headercase("foo bar baz")``` | `"Foo-Bar-Baz"` |
|
111
|
+
| ```Strings::Case.kebabcase("foo bar baz")``` | `"foo-bar-baz"` |
|
112
|
+
| ```Strings::Case.pascalcase("foo bar baz")``` | `"FooBarBaz"` |
|
113
|
+
| ```Strings::Case.pathcase("foo bar baz")``` | `"foo/bar/baz"` |
|
114
|
+
| ```Strings::Case.sentencecase("foo bar baz")``` | `"Foo bar baz"` |
|
115
|
+
| ```Strings::Case.snakecase("foo bar baz")``` | `"foo_bar_baz"` |
|
116
|
+
| ```Strings::Case.titlecase("foo bar baz")``` | `"Foo Bar Baz"` |
|
117
|
+
|
118
|
+
## 2. API
|
119
|
+
|
120
|
+
### 2.1 camelcase
|
121
|
+
|
122
|
+
To convert a string into a camel case, that is, a case with all the words capitilized apart from the first one and compouned together without any space use `camelase` method. For example:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
Strings::Case.camelcase("HTTP Response Code")
|
126
|
+
# => "httpResponseCode"
|
127
|
+
```
|
128
|
+
|
129
|
+
To preserve the acronyms use the `:acronyms` option:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
Strings::Case.camelcase("HTTP Response Code", acronyms: ["HTTP"])
|
133
|
+
# => "HTTPResponseCode"
|
134
|
+
```
|
135
|
+
|
136
|
+
### 2.2 constcase
|
137
|
+
|
138
|
+
To convert a string into a constant case, that is, a case with all the words uppercased and separated by underscore character use `constcase`. For example:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
Strings::Case.constcase("HTTP Response Code")
|
142
|
+
# => "HTTP_RESPONSE_CODE"
|
143
|
+
```
|
144
|
+
|
145
|
+
### 2.3 headercase
|
146
|
+
|
147
|
+
To covert a string into a header case, that is, a case with all the words capitalized and separated by a hypen use `headercase`. For example:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
Strings::Case.headercase("HTTP Response Code")
|
151
|
+
# => "Http-Response-Code"
|
152
|
+
```
|
153
|
+
|
154
|
+
To preserve the acronyms use the `:acronyms` option:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
Strings::Case.headercase("HTTP Response Code", acronyms: ["HTTP"])
|
158
|
+
# => "HTTP-Response-Code"
|
159
|
+
```
|
160
|
+
### 2.4 kebabcase | dashcase
|
161
|
+
|
162
|
+
To convert a string into a kebab case, that is, a case with all the words lowercased and separted by a dash, like a words kebabab on a skewer, use `kebabcase` or `dashcase` methods. For example:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
Strings::Case.kebabcase("HTTP Response Code")
|
166
|
+
# => "http-response-code"
|
167
|
+
```
|
168
|
+
|
169
|
+
To preserve the acronyms use the `:acronyms` option:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
Strings::Case.dashcase("HTTP Response Code", acronyms: ["HTTP"])
|
173
|
+
|
174
|
+
expect(dashed).to eq("HTTP-response-code")
|
175
|
+
```
|
176
|
+
|
177
|
+
### 2.5 pascalcase
|
178
|
+
|
179
|
+
To convert a string into a pascal case, that is, a case with all the words capitilized and compounded together without a space, use `pascalcase` method. For example:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
Strings::Case.pascalcase("HTTP Response Code")
|
183
|
+
# => "HttpResponseCode"
|
184
|
+
```
|
185
|
+
|
186
|
+
To preserve the acronyms use the `:acronyms` option:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
Strings::Case.pascalcase("HTTP Response Code")
|
190
|
+
# => "HTTPResponseCode"
|
191
|
+
```
|
192
|
+
|
193
|
+
### 2.6 pathcase
|
194
|
+
|
195
|
+
To convert a string into a file path use `pathcase`:
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
Strings::Case.pathcase("HTTP Response Code")
|
199
|
+
# => "http/response/code"
|
200
|
+
````
|
201
|
+
|
202
|
+
To preserve the acronyms use the `:acronyms` option:
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
Strings::Case.pathcase("HTTP Response Code", acronyms: ["HTTP"])
|
206
|
+
# => "HTTP/response/code"
|
207
|
+
```
|
208
|
+
|
209
|
+
By default the `/` is used as a path separator. To change this use a `:sep` option. For example, on Windows the file path separator is `\`:
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
Strings::Case.pathcase("HTTP Response Code", separator: "\\")
|
213
|
+
# => "http\response\code"
|
214
|
+
```
|
215
|
+
|
216
|
+
### 2.7 `sentencecase`
|
217
|
+
|
218
|
+
To turn a string into a sentence use `sentencecase`:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
Strings::Case.sentencecase("HTTP Response Code")
|
222
|
+
# => "Http response code"
|
223
|
+
```
|
224
|
+
|
225
|
+
To preserve the `HTTP` acronym use the `:acronyms` option:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
Strings::Case.sentencecase("HTTP Response Code", acronyms: ["HTTP"])
|
229
|
+
# => "HTTP response code"
|
230
|
+
```
|
231
|
+
|
232
|
+
### 2.8 `snakecase` | `underscore`
|
233
|
+
|
234
|
+
To convert a string into a snake case by lowercasing all the characters and separating them with an `_` use `snakecase` or `underscore` methods. For example:
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
Strings::Case.snakecase("HTTP Response Code")
|
238
|
+
# => "http_response_code"
|
239
|
+
```
|
240
|
+
|
241
|
+
To preserve acronyms in your string use the `:acronyms` option. For example:
|
242
|
+
|
243
|
+
```ruby
|
244
|
+
Strings::Case.snakecase("HTTP Response Code", acronyms: ["HTTP"])
|
245
|
+
# => "HTTP_response_code"
|
246
|
+
```
|
247
|
+
|
248
|
+
### 2.9 `titlecase`
|
249
|
+
|
250
|
+
To convert a string into a space delimited words that have their first letter capitalized use `titlecase`. For example:
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
Strings::Case.titlecase("HTTPResponseCode")
|
254
|
+
# => "Http Response Code"
|
255
|
+
```
|
256
|
+
|
257
|
+
To preserve the `HTTP` acronym use the `:acronyms` option:
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
Strings::Case.titlecase("HTTP response code", acronyms: ["HTTP"])
|
261
|
+
# => "HTTP Response Code"
|
262
|
+
```
|
263
|
+
|
264
|
+
## 3. Extending String class
|
265
|
+
|
266
|
+
Though it is highly discouraged to pollute core Ruby classes, you can add the required methods to `String` class by using refinements.
|
267
|
+
|
268
|
+
For example, if you wish to only extend strings with `wrap` method do:
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
module MyStringExt
|
272
|
+
refine String do
|
273
|
+
def snakecase(*args)
|
274
|
+
Strings::Case.snakecase(self, *args)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
```
|
279
|
+
|
280
|
+
Then `snakecase` method will be available for any strings where refinement is applied:
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
using MyStringExt
|
284
|
+
|
285
|
+
"foo bar baz".snakecase
|
286
|
+
# => "foo_bar_baz"
|
287
|
+
```
|
288
|
+
|
289
|
+
However, if you want to include all the **Strings::Case** methods, you can use provided extensions file:
|
290
|
+
|
291
|
+
```ruby
|
292
|
+
require "strings/case/extensions"
|
293
|
+
|
294
|
+
using Strings::Case::Extensions
|
295
|
+
```
|
296
|
+
|
297
|
+
## Development
|
298
|
+
|
299
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
300
|
+
|
301
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
302
|
+
|
303
|
+
## Contributing
|
304
|
+
|
305
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/piotrmurach/strings-case. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
306
|
+
|
307
|
+
## License
|
308
|
+
|
309
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
310
|
+
|
311
|
+
## Code of Conduct
|
312
|
+
|
313
|
+
Everyone interacting in the Strings::Case project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/piotrmurach/strings-case/blob/master/CODE_OF_CONDUCT.md).
|
314
|
+
|
315
|
+
## Copyright
|
316
|
+
|
317
|
+
Copyright (c) 2019 Piotr Murach. See LICENSE for further details.
|
data/Rakefile
ADDED
data/lib/strings-case.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "strings/case"
|
data/lib/strings/case.rb
ADDED
@@ -0,0 +1,304 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "case/version"
|
4
|
+
|
5
|
+
module Strings
|
6
|
+
module Case
|
7
|
+
DIGITS = ("0".."9").freeze
|
8
|
+
UP_LETTERS = ("A".."Z").freeze
|
9
|
+
DOWN_LETTERS = ("a".."z").freeze
|
10
|
+
DELIMITERS = [" ", "\n", "\t", "_", ".", "-", "#", "?", "!"].freeze
|
11
|
+
NONALPHANUMERIC = (32..127).map(&:chr) -
|
12
|
+
(DIGITS.to_a + DOWN_LETTERS.to_a + UP_LETTERS.to_a + DELIMITERS)
|
13
|
+
UPCASE = /(?<!\p{Lu})\p{Lu}$/.freeze
|
14
|
+
LOWERCASE = /\p{Lu}(?=\p{Ll})/.freeze
|
15
|
+
|
16
|
+
class Error < StandardError; end
|
17
|
+
|
18
|
+
# Prevent changing case
|
19
|
+
module NullCase
|
20
|
+
def downcase
|
21
|
+
self
|
22
|
+
end
|
23
|
+
alias upcase downcase
|
24
|
+
alias capitalize downcase
|
25
|
+
end
|
26
|
+
|
27
|
+
# Convert string to camel case:
|
28
|
+
# * start with a lowercase character
|
29
|
+
# * every subsequent word has its first character uppercased
|
30
|
+
# * all words are compounded together
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# camelcase("foo bar baz") # => "fooBarBaz"
|
34
|
+
#
|
35
|
+
# @param [String] string
|
36
|
+
# the string to camelcase
|
37
|
+
# @param [Array[String]] acronyms
|
38
|
+
# the acronyms to use to prevent modifications
|
39
|
+
# @param [String] separator
|
40
|
+
# the separator for linking words, by default none
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
def camelcase(string, acronyms: [], separator: "")
|
44
|
+
res = parsecase(string, acronyms: acronyms, sep: separator, casing: :capitalize)
|
45
|
+
|
46
|
+
return res if res.to_s.empty?
|
47
|
+
|
48
|
+
acronyms_regex = /^(#{acronyms.join("|")})/
|
49
|
+
if !acronyms.empty? && (res =~ acronyms_regex)
|
50
|
+
res
|
51
|
+
else
|
52
|
+
res[0].downcase + res[1..-1]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
module_function :camelcase
|
56
|
+
|
57
|
+
alias lower_camelcase camelcase
|
58
|
+
module_function :lower_camelcase
|
59
|
+
|
60
|
+
# Converts string to a constant
|
61
|
+
#
|
62
|
+
# @example
|
63
|
+
# constantcase("foo bar baz") # => "FOO_BAR_BAZ"
|
64
|
+
#
|
65
|
+
# @param [String] string
|
66
|
+
# the string to turn into constant
|
67
|
+
# @param [Array[String]] acronyms
|
68
|
+
# the acronyms to use to prevent modifications
|
69
|
+
# @param [String] separator
|
70
|
+
# the words separator, by default "_"
|
71
|
+
#
|
72
|
+
# @api public
|
73
|
+
def constcase(string, separator: "_")
|
74
|
+
parsecase(string, sep: separator, casing: :upcase)
|
75
|
+
end
|
76
|
+
module_function :constcase
|
77
|
+
|
78
|
+
alias constantcase constcase
|
79
|
+
module_function :constantcase
|
80
|
+
|
81
|
+
# Convert string to a HTTP Header
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# headercase("foo bar baz") # = "Foo-Bar-Baz"
|
85
|
+
#
|
86
|
+
# @param [String] string
|
87
|
+
# the string to turn into header
|
88
|
+
# @param [Array[String]] acronyms
|
89
|
+
# the acronyms to use to prevent modifications
|
90
|
+
# @param [String] separator
|
91
|
+
# the words separator, by default "-"
|
92
|
+
#
|
93
|
+
# @api public
|
94
|
+
def headercase(string, acronyms: [], separator: "-")
|
95
|
+
parsecase(string, acronyms: acronyms, sep: separator, casing: :capitalize)
|
96
|
+
end
|
97
|
+
module_function :headercase
|
98
|
+
|
99
|
+
# Converts string to lower case words linked by hyphenes
|
100
|
+
#
|
101
|
+
# @example
|
102
|
+
# kebabcase("fooBarBaz") # => "foo-bar-baz"
|
103
|
+
#
|
104
|
+
# kebabcase("__FOO_BAR__") # => "foo-bar"
|
105
|
+
#
|
106
|
+
# @param [String] string
|
107
|
+
# the string to convert to dashed string
|
108
|
+
# @param [Array[String]] acronyms
|
109
|
+
# the acronyms to use to prevent modifications
|
110
|
+
# @param [String] separator
|
111
|
+
# the separator for linking words, by default hyphen
|
112
|
+
#
|
113
|
+
# @return [String]
|
114
|
+
#
|
115
|
+
# @api public
|
116
|
+
def kebabcase(string, acronyms: [], separator: "-")
|
117
|
+
parsecase(string, acronyms: acronyms, sep: separator)
|
118
|
+
end
|
119
|
+
module_function :kebabcase
|
120
|
+
|
121
|
+
alias dashcase kebabcase
|
122
|
+
module_function :dashcase
|
123
|
+
|
124
|
+
# Convert string to pascal case:
|
125
|
+
# * every word has its first character uppercased
|
126
|
+
# * all words are compounded together
|
127
|
+
#
|
128
|
+
# @example
|
129
|
+
# pascalcase("foo bar baz") # => "FooBarBaz"
|
130
|
+
#
|
131
|
+
# @param [String] string
|
132
|
+
# the string to convert to camel case with capital letter
|
133
|
+
# @param [Array[String]] acronyms
|
134
|
+
# the acronyms to use to prevent modifications
|
135
|
+
# @param [String] separator
|
136
|
+
# the separator for linking words, by default none
|
137
|
+
#
|
138
|
+
# @api public
|
139
|
+
def pascalcase(string, acronyms: [], separator: "")
|
140
|
+
parsecase(string, acronyms: acronyms, sep: separator, casing: :capitalize)
|
141
|
+
end
|
142
|
+
module_function :pascalcase
|
143
|
+
|
144
|
+
alias upper_camelcase pascalcase
|
145
|
+
module_function :upper_camelcase
|
146
|
+
|
147
|
+
# Convert string into a file path.
|
148
|
+
#
|
149
|
+
# By default uses `/` as a path separator.
|
150
|
+
#
|
151
|
+
# @example
|
152
|
+
# pathcase("foo bar baz") # => "foo/bar/baz"
|
153
|
+
#
|
154
|
+
# pathcase("FooBarBaz") # => "foo/bar/baz"
|
155
|
+
#
|
156
|
+
# @param [String] string
|
157
|
+
# the string to convert to file path
|
158
|
+
# @param [Array[String]] acronyms
|
159
|
+
# the acronyms to use to prevent modifications
|
160
|
+
# @param [String] separator
|
161
|
+
# the separator for linking words, by default `/`
|
162
|
+
#
|
163
|
+
# @api public
|
164
|
+
def pathcase(string, acronyms: [], separator: "/")
|
165
|
+
parsecase(string, acronyms: acronyms, sep: separator)
|
166
|
+
end
|
167
|
+
module_function :pathcase
|
168
|
+
|
169
|
+
# Convert string int a sentence
|
170
|
+
#
|
171
|
+
# @example
|
172
|
+
# sentencecase("foo bar baz") # => "Foo bar baz"
|
173
|
+
#
|
174
|
+
# @param [String] string
|
175
|
+
# the string to convert to sentence
|
176
|
+
# @param [Array[String]] acronyms
|
177
|
+
# the acronyms to use to prevent modifications
|
178
|
+
# @param [String] separator
|
179
|
+
# the separator for linking words, by default a space
|
180
|
+
#
|
181
|
+
# @api public
|
182
|
+
def sentencecase(string, acronyms: [], separator: " ")
|
183
|
+
res = parsecase(string, acronyms: acronyms, sep: separator, casing: :downcase)
|
184
|
+
|
185
|
+
return res if res.to_s.empty?
|
186
|
+
|
187
|
+
res[0].upcase + res[1..-1]
|
188
|
+
end
|
189
|
+
module_function :sentencecase
|
190
|
+
|
191
|
+
# Convert string into a snake_case
|
192
|
+
#
|
193
|
+
# @example
|
194
|
+
# snakecase("foo bar baz") # => "foo_bar_baz"
|
195
|
+
#
|
196
|
+
# snakecase("ЗдравствуйтеПривет") # => "здравствуйте_привет"
|
197
|
+
#
|
198
|
+
# snakecase("HTTPResponse") # => "http_response"
|
199
|
+
#
|
200
|
+
# @param [String] string
|
201
|
+
# the string to convert to snake case
|
202
|
+
# @param [Array[String]] acronyms
|
203
|
+
# the acronyms to use to prevent modifications
|
204
|
+
# @param [String] separator
|
205
|
+
# the separator for linking words, by default `_`
|
206
|
+
#
|
207
|
+
# @api public
|
208
|
+
def snakecase(string, acronyms: [], separator: "_")
|
209
|
+
parsecase(string, acronyms: acronyms, sep: separator)
|
210
|
+
end
|
211
|
+
module_function :snakecase
|
212
|
+
|
213
|
+
alias underscore snakecase
|
214
|
+
module_function :underscore
|
215
|
+
|
216
|
+
# Convert string into a title case
|
217
|
+
#
|
218
|
+
# @example
|
219
|
+
# titlecase("foo bar baz") # => "Foo Bar Baz"
|
220
|
+
#
|
221
|
+
# @param [String] string
|
222
|
+
# the string to convert to title case
|
223
|
+
# @param [Array[String]] acronyms
|
224
|
+
# the acronyms to use to prevent modifications
|
225
|
+
# @param [String] separator
|
226
|
+
# the separator for linking words, by default a space
|
227
|
+
#
|
228
|
+
# @api public
|
229
|
+
def titlecase(string, acronyms: [], separator: " ")
|
230
|
+
parsecase(string, acronyms: acronyms, sep: separator, casing: :capitalize)
|
231
|
+
end
|
232
|
+
module_function :titlecase
|
233
|
+
|
234
|
+
# Parse string and transform to desired case
|
235
|
+
#
|
236
|
+
# @api private
|
237
|
+
def parsecase(string, acronyms: [], sep: "_", casing: :downcase)
|
238
|
+
return if string.nil?
|
239
|
+
|
240
|
+
words = split_into_words(string, sep: sep)
|
241
|
+
|
242
|
+
no_case = ->(w) { acronyms.include?(w) ? w.extend(NullCase) : w }
|
243
|
+
|
244
|
+
words
|
245
|
+
.map(&no_case)
|
246
|
+
.map(&casing)
|
247
|
+
.join(sep)
|
248
|
+
end
|
249
|
+
module_function :parsecase
|
250
|
+
private_class_method :parsecase
|
251
|
+
|
252
|
+
# Split string into words
|
253
|
+
#
|
254
|
+
# @return [Array[String]]
|
255
|
+
# the split words
|
256
|
+
#
|
257
|
+
# @api private
|
258
|
+
def split_into_words(string, sep: nil)
|
259
|
+
words = []
|
260
|
+
word = []
|
261
|
+
last = string.length - 1
|
262
|
+
|
263
|
+
string.each_char.with_index do |char, i|
|
264
|
+
combine = word[-1].to_s + char
|
265
|
+
|
266
|
+
if combine =~ UPCASE
|
267
|
+
if word.size <= 1 # don't allow single letter words
|
268
|
+
word << char
|
269
|
+
else
|
270
|
+
words << word.join
|
271
|
+
word = [char]
|
272
|
+
end
|
273
|
+
elsif combine =~ LOWERCASE
|
274
|
+
letter = word.pop
|
275
|
+
if word.size <= 1 # don't allow single letter words
|
276
|
+
word << letter << char
|
277
|
+
else
|
278
|
+
words << word.join
|
279
|
+
word = [letter, char]
|
280
|
+
end
|
281
|
+
elsif DELIMITERS.include?(char)
|
282
|
+
words << word.join unless word.empty?
|
283
|
+
if i.zero? && char == sep
|
284
|
+
words << ""
|
285
|
+
else
|
286
|
+
word = []
|
287
|
+
end
|
288
|
+
elsif NONALPHANUMERIC.include?(char)
|
289
|
+
# noop
|
290
|
+
else
|
291
|
+
word << char
|
292
|
+
end
|
293
|
+
|
294
|
+
if last == i
|
295
|
+
word = [""] if char == sep
|
296
|
+
words << word.join unless word.empty?
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
words
|
301
|
+
end
|
302
|
+
module_function :split_into_words
|
303
|
+
end # Case
|
304
|
+
end # Strings
|