├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── src └── str │ ├── init.lua │ └── utils.lua ├── str-1.5.0-0.rockspec └── test.lua /.gitignore: -------------------------------------------------------------------------------- 1 | *.rock 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: false 3 | 4 | env: 5 | - LUA="lua=5.1" 6 | - LUA="lua=5.2" 7 | - LUA="lua=5.3" 8 | 9 | before_install: 10 | - pip install hererocks 11 | - hererocks lua_install -r^ --$LUA 12 | - export PATH=$PATH:$PWD/lua_install/bin 13 | 14 | install: 15 | - make install 16 | - make install_dev 17 | 18 | script: 19 | - make test 20 | 21 | notifications: 22 | email: 23 | on_success: change 24 | on_failure: always 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Evandro Leopoldino Gonçalves 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .SILENT: 2 | 3 | test: 4 | LUA_PATH="./src/?.lua;./src/?/init.lua;./src/str/?.lua;;" lua test.lua 5 | 6 | install: 7 | luarocks install luautf8 8 | 9 | install_dev: 10 | luarocks install simple_test 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # str 2 | str is a string module with useful methods that don't exist in Lua's core
3 | For docs, see: https://evandrolg.github.io/str/ 4 | 5 | [![Build 6 | Status](https://travis-ci.org/EvandroLG/str.svg?branch=master)](https://travis-ci.org/EvandroLG/str) 7 | 8 | ## Installation 9 | To install str, run: 10 | ```sh 11 | $ luarocks install str 12 | ``` 13 | 14 | ## See too: 15 | * [array.lua](http://www.github.com/evandrolg/array.lua) 16 | * [Hash.lua](https://github.com/EvandroLG/Hash.lua) 17 | 18 | ## LICENSE 19 | [MIT](https://github.com/EvandroLG/str/tree/master/LICENSE) 20 | -------------------------------------------------------------------------------- /src/str/init.lua: -------------------------------------------------------------------------------- 1 | local utf8 = require 'lua-utf8' 2 | local utils = require 'str.utils' 3 | 4 | local str 5 | 6 | str = { 7 | __VERSION = '1.5.0', 8 | __DESCRIPTION = "str is a string module with useful methods that don't exist in Lua's core", 9 | __LICENCE = [[ 10 | The MIT License (MIT) 11 | 12 | Copyright (c) 2017 Evandro Leopoldino Gonçalves 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | ]], 32 | 33 | -- extracts a part of the string and returns a new string 34 | -- @param s {string} 35 | -- @param start {number} 36 | -- @param finish {number | nil} 37 | -- @return {string} 38 | slice = function(s, start, finish) 39 | return string.sub(s, start, finish or #s) 40 | end, 41 | 42 | -- checks whether string starts with the value passed by parameter 43 | -- @param s {string} 44 | -- @param start {number} 45 | -- @return {string} 46 | starts_with = function(s, start) 47 | return string.sub(s, 1, #start) == start 48 | end, 49 | 50 | -- checks whether string ends with the value passed by parameter 51 | -- @param s {string} 52 | -- @param finish {number} 53 | -- @return {string} 54 | ends_with = function(s, finish) 55 | return string.sub(s, -#finish) == finish 56 | end, 57 | 58 | -- returns how many times the substring was found 59 | -- @param s {string} 60 | -- @param substr {string} 61 | -- @return {number} 62 | count = function(s, substr) 63 | local total = 0 64 | local start = nil 65 | local finish = 1 66 | 67 | repeat 68 | start, finish = string.find(s, substr, finish, true) 69 | if start then total = total + 1 end 70 | until start == nil 71 | 72 | return total 73 | end, 74 | 75 | -- splits the string into substring using the specified separator and return them as a table 76 | -- @param s {string} 77 | -- @param pattern {string} 78 | -- @return {table} 79 | split = function(s, pattern) 80 | local output = {} 81 | local fpat = '(.-)' .. pattern 82 | local last_end = 1 83 | local _s, e, cap = s:find(fpat, 1) 84 | 85 | while _s do 86 | if _s ~= 1 or cap ~= '' then 87 | table.insert(output, cap) 88 | end 89 | 90 | last_end = e+1 91 | _s, e, cap = s:find(fpat, last_end) 92 | end 93 | 94 | if last_end <= #s then 95 | cap = s:sub(last_end) 96 | table.insert(output, cap) 97 | end 98 | 99 | return output 100 | end, 101 | 102 | -- returns a new string with trailing whitespace removed 103 | -- @param s {string} 104 | -- @return {string} 105 | trim_right = function(s) 106 | return string.match(s, '(.-)%s*$') 107 | end, 108 | 109 | -- returns a new string with leading whitespace removed 110 | -- @param s {string} 111 | -- @return {string} 112 | trim_left = function(s) 113 | return string.match(s, '[^%s+].*') 114 | end, 115 | 116 | -- returns a copy of string leading and trailing whitespace removed 117 | -- @param s {string} 118 | -- @return {string} 119 | trim = function(s) 120 | return str.trim_right( 121 | str.trim_left(s) 122 | ) 123 | end, 124 | 125 | -- returns a new string with the first character converted to uppercase and the remainder to lowercase 126 | -- @param s {string} 127 | -- @return {string} 128 | capitalize = function(s) 129 | if #s == 0 then 130 | return s 131 | end 132 | 133 | local function upperFirst() 134 | return string.upper( 135 | string.sub(s, 1, 1) 136 | ) 137 | end 138 | 139 | local function lowerRest() 140 | return string.lower( 141 | string.sub(s, 2) 142 | ) 143 | end 144 | 145 | return upperFirst() .. lowerRest() 146 | end, 147 | 148 | -- returns a copy of the string passed as parameter centralized with spaces passed in size parameter 149 | -- @param s {string} 150 | -- @param n {number} 151 | -- @return {string} 152 | center = function(s, n) 153 | local aux = '' 154 | 155 | for i=1, n do 156 | aux = aux .. ' ' 157 | end 158 | 159 | return aux .. s .. aux 160 | end, 161 | 162 | -- converts string to slug and returns it as a new string 163 | -- @param s {string} 164 | -- @return {string} 165 | slug = function(s) 166 | local splited = utils.get_list_chars(s) 167 | local output = {} 168 | local accents = [[ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîï 169 | ÙÚÛÜùúûüÑñŠšŸÿýŽž~"\'~^!?.:@#$%&*]] 170 | local accents_out = [[AAAAAAaaaaaaOOOOOOOooooooEEEEeeeeeCcDIIIIiiii 171 | UUUUuuuuNnSsYyyZz---------------]] 172 | 173 | for key, value in pairs(splited) do 174 | local index_of = utf8.find(accents, value) 175 | 176 | if index_of then 177 | output[key] = utf8.sub(accents_out, index_of, index_of) 178 | else 179 | output[key] = value 180 | end 181 | end 182 | 183 | return utf8.lower(table.concat(output, ''):gsub('%s', '-')) 184 | end, 185 | 186 | -- checks whether the string has only ascii characters 187 | -- @param s {string} 188 | -- @return {boolean} 189 | is_ascii = function(s) 190 | for i=1, #s do 191 | if string.byte(s:sub(i, i)) > 126 then return false end 192 | end 193 | 194 | return true 195 | end, 196 | 197 | -- checks whether the string has only numbers characters 198 | -- @param s {string} 199 | -- @return {boolean} 200 | is_number = function(s) 201 | return utils.to_bool( 202 | string.find(s, '^%d+$') 203 | ) 204 | end, 205 | 206 | -- executes a provided function once for each character of the string 207 | -- @param s {string} 208 | -- @param callback {function} 209 | -- @return {void} 210 | each_char = function(s, callback) 211 | for i=1, #s do 212 | callback(s:sub(i, i), i) 213 | end 214 | end, 215 | 216 | -- passes every byte in string to the given function 217 | -- @param s {string} 218 | -- @param callback {function} 219 | -- @return {void} 220 | each_byte = function(s, callback) 221 | str.each_char(s, function(char, i) 222 | callback(char:byte(), i) 223 | end) 224 | end, 225 | 226 | -- executes a provided function once for each line of the string 227 | -- @param s {string} 228 | -- @param callback {function} 229 | -- @return {void} 230 | each_line = function(s, callback) 231 | for line in string.gmatch(s, '[^\n]+') do 232 | callback(line) 233 | end 234 | end, 235 | 236 | -- returns a table with the byte of every string's character 237 | -- @param s {string} 238 | -- @return {table} 239 | bytes = function(s) 240 | local output = {} 241 | 242 | str.each_char(s, function(s) 243 | table.insert(output, string.byte(s)) 244 | end) 245 | 246 | return output 247 | end, 248 | 249 | -- returns a copy of the string passed by parameter without the specified characters 250 | -- @param s {string} 251 | -- @param chars {table} 252 | -- @return {table} 253 | delete = function(s, chars) 254 | local output = s 255 | 256 | for i=1, #chars do 257 | output = output:gsub(chars[i], '') 258 | end 259 | 260 | return output 261 | end, 262 | 263 | -- returns the index within the given string of the last occurrence of the specified value; 264 | -- returns nil if the value is not found 265 | -- @param s {string} 266 | -- @param match {string} 267 | -- @return {table} 268 | find_last = function(s, match) 269 | local i = s:match('.*' .. match .. '()') 270 | 271 | if not i then 272 | return nil 273 | end 274 | 275 | return i - 1 276 | end, 277 | 278 | -- truncates string if it's longer than the given maximum size 279 | -- @param s {string} 280 | -- @param options {table} 281 | -- @return {table} 282 | truncate = function(s, options) 283 | local _options = options or {} 284 | local omission = _options.omission or '...' 285 | local size = _options.size or 30 286 | local separator = _options.separator 287 | local cutted = str.slice(s, 1, size - #omission) 288 | 289 | if separator then 290 | local i = str.find_last(cutted, separator) - 1 291 | return str.slice(s, 1, i) .. omission 292 | end 293 | 294 | return cutted .. omission 295 | end, 296 | 297 | -- converts string to `camel case` 298 | -- @param s {string} 299 | -- @return {string} 300 | camel_case = function(s) 301 | return utils.match_case(s, str.capitalize) 302 | end, 303 | 304 | -- converts string to `kebab case` 305 | -- @param s {string} 306 | -- @return {string} 307 | kebab_case = function(s) 308 | return utils.match_case(s, function(w) 309 | return '-' .. w 310 | end) 311 | end, 312 | 313 | -- converts string to `snake case` 314 | -- @param s {string} 315 | -- @return {string} 316 | snake_case = function(s) 317 | return utils.match_case(s, function(w) 318 | return '_' .. w 319 | end) 320 | end, 321 | 322 | -- determines wether the substring was found within the string 323 | -- @param s {string} 324 | -- @param substr {string} 325 | -- @return {boolean} 326 | includes = function(s, substr) 327 | return utils.includes(s, substr) 328 | end, 329 | 330 | -- converts the characters "&", "<", ">", '"', and "'" in string to their corresponding html entities. 331 | -- @param s {string} 332 | -- @return {string} 333 | escape = function(s) 334 | local match = { 335 | ['<'] = '<', 336 | ['>'] = '>', 337 | ['"'] = '"', 338 | ["'"] = ''', 339 | ['&'] = '&' 340 | } 341 | 342 | local keys = utils.hash_keys(match) 343 | local output = {} 344 | 345 | for i=1, #s do 346 | local char = string.sub(s, i, i) 347 | local is_special = utils.includes_item(char, keys) 348 | 349 | table.insert(output, is_special and match[char] or char) 350 | end 351 | 352 | return table.concat(output, '') 353 | end, 354 | 355 | -- returns the position of the first occurrence of a specific substring 356 | -- @param s {string} 357 | -- @param substr {string} 358 | -- @return {number} 359 | index_of = function(s, substr) 360 | local index = string.find(s, substr, 1, true) 361 | return index or -1 362 | end, 363 | 364 | -- converts the HTML entities `&`, `<`, `>`, `"` and `'` in string to their corresponding characters. 365 | -- @param s {string} 366 | -- @return {string} 367 | unescape = function(s) 368 | local match = { 369 | ['<'] = '<', 370 | ['>'] = '>', 371 | ['"'] = '"', 372 | ['''] = "'", 373 | ['&'] = '&' 374 | } 375 | 376 | local result = s 377 | 378 | for k, v in pairs(match) do 379 | result = str.replace(result, k, v) 380 | end 381 | 382 | return result 383 | end, 384 | 385 | -- returns a new string replacing the specific values from the original string 386 | -- @param s {string} 387 | -- @param substr {string} 388 | -- @param new_substr {string} 389 | -- @return {number} 390 | replace = function(s, substr, new_substr) 391 | local result = string.gsub(s, substr, new_substr) 392 | return result 393 | end 394 | } 395 | 396 | return str 397 | -------------------------------------------------------------------------------- /src/str/utils.lua: -------------------------------------------------------------------------------- 1 | local utf8 = require 'lua-utf8' 2 | 3 | -- convert value passed by parameter to boolean 4 | -- @param value {*} 5 | -- @return {boolean} 6 | local function to_bool(value) 7 | return not not value 8 | end 9 | 10 | -- return a array-like table with each character from a given string 11 | -- @param s {string} 12 | -- @return {table} 13 | local function get_list_chars(s) 14 | local output = {} 15 | 16 | for k, c in utf8.codes(s) do 17 | table.insert(output, utf8.char(c)) 18 | end 19 | 20 | return output 21 | end 22 | 23 | -- convert all characters to lowercase and apply a `transformer` over each word 24 | -- @param s {string} 25 | -- @param transformer {function} 26 | -- @return {table} 27 | local function match_case(s, transformer) 28 | local lower = string.lower(s) 29 | local result = {} 30 | local is_first_word = true 31 | 32 | for w in string.gmatch(lower, '%w+') do 33 | if is_first_word then 34 | table.insert(result, w) 35 | is_first_word = false 36 | else 37 | table.insert(result, transformer(w)) 38 | end 39 | end 40 | 41 | return table.concat(result, '') 42 | end 43 | 44 | -- returns an array-line table with the keys from a given hash-like table 45 | -- @param obj {table} 46 | -- @return {table} 47 | local function hash_keys(obj) 48 | local output = {} 49 | 50 | for k in pairs(obj) do 51 | table.insert(output, k) 52 | end 53 | 54 | return output 55 | end 56 | 57 | -- determines wether the substring was found within the string 58 | -- @param s {string} 59 | -- @param substr {string} 60 | -- @return {boolean} 61 | local function includes(s, substr) 62 | for i=1, #s do 63 | local value = string.sub(s, i, i+#substr-1) 64 | if value == substr then return true end 65 | end 66 | 67 | return false 68 | end 69 | 70 | -- determines wether one of the items intot he array was found within the string 71 | -- @param s {string} 72 | -- @param array {table} 73 | -- @return {boolean} 74 | local function includes_item(s, array) 75 | for i, v in pairs(array) do 76 | local result = includes(s, v) 77 | if result then return true end 78 | end 79 | 80 | return false 81 | end 82 | 83 | return { 84 | to_bool = to_bool, 85 | get_list_chars = get_list_chars, 86 | match_case = match_case, 87 | hash_keys = hash_keys, 88 | includes = includes, 89 | includes_item = includes_item 90 | } 91 | -------------------------------------------------------------------------------- /str-1.5.0-0.rockspec: -------------------------------------------------------------------------------- 1 | package = 'str' 2 | version = '1.5.0-0' 3 | 4 | source = { 5 | url = 'git://github.com/evandrolg/str.git', 6 | tag = 'v1.5.0' 7 | } 8 | 9 | description = { 10 | summary = 'str is an string module with useful methods that do not exist in Lua core', 11 | homepage = 'https://github.com/EvandroLG/str', 12 | maintainer = 'Evandro Leopoldino Gonçalves (@evandrolg) ', 13 | license = 'MIT ' 14 | } 15 | 16 | dependencies = { 17 | "lua >= 5.1", 18 | "luautf8 >= 0.1.1-1" 19 | } 20 | 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ['str'] = "src/str/init.lua", 25 | ['str.utils'] = "src/str/utils.lua" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | local test = require 'simple_test' 2 | local str = require 'str' 3 | 4 | test('meta infos', function(a) 5 | a.equal(str.__VERSION, '1.5.0') 6 | a.equal(str.__DESCRIPTION, "str is a string module with useful methods that don't exist in Lua's core") 7 | end) 8 | 9 | test('slice', function(a) 10 | a.equal( 11 | str.slice('lua, javascript, python', 6, 15), 12 | 'javascript' 13 | ) 14 | 15 | a.equal( 16 | str.slice('lua, javascript, python', 6), 17 | 'javascript, python' 18 | ) 19 | end) 20 | 21 | test('starts_with', function(a) 22 | a.ok( 23 | str.starts_with('lua is a great language', 'lua') 24 | ) 25 | 26 | a.not_ok( 27 | str.starts_with('lua is a great language', 'ruby') 28 | ) 29 | end) 30 | 31 | test('ends_with', function(a) 32 | a.ok( 33 | str.ends_with('lua is a great language', 'language') 34 | ) 35 | 36 | a.not_ok( 37 | str.ends_with('lua is a great language', 'programming') 38 | ) 39 | end) 40 | 41 | test('is_ascii', function(a) 42 | a.ok( 43 | str.is_ascii('lua is a great language') 44 | ) 45 | 46 | a.not_ok( 47 | str.is_ascii('á') 48 | ) 49 | end) 50 | 51 | test('capitalize', function(a) 52 | a.equal( 53 | str.capitalize('lua is a great language'), 54 | 'Lua is a great language' 55 | ) 56 | end) 57 | 58 | test('count', function(a) 59 | a.equal( 60 | str.count('lua is a great language. lua is a brazilian language', 'python'), 61 | 0 62 | ) 63 | 64 | a.equal( 65 | str.count('lua is a great language. lua is a brazilian language', 'lua'), 66 | 2 67 | ) 68 | end) 69 | 70 | test('trim_left', function(a) 71 | a.equal( 72 | str.trim_left(' lua is a great language'), 73 | 'lua is a great language' 74 | ) 75 | end) 76 | 77 | test('trim_right', function(a) 78 | a.equal( 79 | str.trim_right('lua is a great language '), 80 | 'lua is a great language' 81 | ) 82 | end) 83 | 84 | test('trim', function(a) 85 | a.equal( 86 | str.trim(' lua is a great language '), 87 | 'lua is a great language' 88 | ) 89 | end) 90 | 91 | test('is_number', function(a) 92 | a.ok( 93 | str.is_number('12345') 94 | ) 95 | 96 | a.not_ok( 97 | str.is_number('1234a5') 98 | ) 99 | 100 | a.not_ok( 101 | str.is_number('') 102 | ) 103 | end) 104 | 105 | test('center', function(a) 106 | a.equal( 107 | str.center('lua', 3), 108 | ' lua ' 109 | ) 110 | end) 111 | 112 | test('split', function(a) 113 | a.deep_equal( 114 | str.split('lua is a great language', ' '), 115 | { 'lua', 'is', 'a', 'great', 'language' } 116 | ) 117 | end) 118 | 119 | test('slug', function(a) 120 | a.equal( 121 | str.slug('Lua is a great language'), 122 | 'lua-is-a-great-language' 123 | ) 124 | 125 | a.equal( 126 | str.slug('Lua é uma ótima linguagem'), 127 | 'lua-e-uma-otima-linguagem' 128 | ) 129 | end) 130 | 131 | test('each_char', function(a) 132 | local result = {} 133 | str.each_char('lua', function(char) 134 | table.insert(result, char) 135 | end) 136 | 137 | a.deep_equal(result, { 'l', 'u', 'a' }) 138 | end) 139 | 140 | test('each_byte', function(a) 141 | local result = {} 142 | str.each_byte('lua', function(char) 143 | table.insert(result, char) 144 | end) 145 | 146 | a.deep_equal(result, { 108, 117, 97 }) 147 | end) 148 | 149 | test('each_line', function(a) 150 | local result = {} 151 | str.each_line('lua\nruby\npython', function(line) 152 | table.insert(result, line) 153 | end) 154 | 155 | a.deep_equal(result, { 'lua', 'ruby', 'python' }) 156 | end) 157 | 158 | test('bytes', function(a) 159 | a.deep_equal(str.bytes('lua'), { 108, 117, 97 }) 160 | end) 161 | 162 | test('delete', function(a) 163 | a.equal( 164 | str.delete('hello world!', {'h', 'o'}), 165 | 'ell wrld!' 166 | ) 167 | end) 168 | 169 | test('truncate', function(a) 170 | local value = string.rep('Lorem ipsum ', 10) 171 | 172 | a.equal( 173 | str.truncate(value), 174 | 'Lorem ipsum Lorem ipsum Lor...' 175 | ) 176 | 177 | a.equal( 178 | str.truncate(value, { size = 10 }), 179 | 'Lorem i...' 180 | ) 181 | 182 | a.equal( 183 | str.truncate(value, { size = 10, omission = '.' }), 184 | 'Lorem ips.' 185 | ) 186 | 187 | a.equal( 188 | str.truncate(value, { separator = ' ' }), 189 | 'Lorem ipsum Lorem ipsum...' 190 | ) 191 | end) 192 | 193 | test('find_last', function(a) 194 | local value = 'Lua is great' 195 | 196 | a.equal( 197 | str.find_last(value, 'good'), 198 | nil 199 | ) 200 | 201 | a.equal( 202 | str.find_last(value, 'great'), 203 | 12 204 | ) 205 | end) 206 | 207 | test('camel_case', function(a) 208 | local expected = 'luaIsGreat' 209 | a.equal( 210 | str.camel_case('Lua is great'), 211 | expected 212 | ) 213 | 214 | a.equal( 215 | str.camel_case('Lua-is-great'), 216 | expected 217 | ) 218 | 219 | a.equal( 220 | str.camel_case('Lua_is_great'), 221 | expected 222 | ) 223 | end) 224 | 225 | test('kebab_case', function(a) 226 | local expected = 'lua-is-great' 227 | 228 | a.equal( 229 | str.kebab_case('Lua is great'), 230 | expected 231 | ) 232 | 233 | a.equal( 234 | str.kebab_case('Lua-is-great'), 235 | expected 236 | ) 237 | 238 | a.equal( 239 | str.kebab_case('Lua_is_great'), 240 | expected 241 | ) 242 | end) 243 | 244 | test('snake_case', function(a) 245 | local expected = 'lua_is_great' 246 | 247 | a.equal( 248 | str.snake_case('Lua is great'), 249 | expected 250 | ) 251 | 252 | a.equal( 253 | str.snake_case('Lua-is-great'), 254 | expected 255 | ) 256 | 257 | a.equal( 258 | str.snake_case('Lua_is_great'), 259 | expected 260 | ) 261 | end) 262 | 263 | test('includes', function(a) 264 | local value = 'Lua is great' 265 | 266 | a.not_ok( 267 | str.includes(value, 'greata') 268 | ) 269 | 270 | a.ok( 271 | str.includes(value, 'great') 272 | ) 273 | 274 | a.ok( 275 | str.includes(value, 'is') 276 | ) 277 | 278 | a.ok( 279 | str.includes(value, 'Lua ') 280 | ) 281 | end) 282 | 283 | test('escape', function(a) 284 | a.equal( 285 | str.escape('"tom & jerry" <>'), 286 | '"tom & jerry" <>' 287 | ) 288 | 289 | a.equal( 290 | str.escape("'tom & jerry' <>"), 291 | ''tom & jerry' <>' 292 | ) 293 | end) 294 | 295 | test('index_of', function(a) 296 | a.equal( 297 | str.index_of('lua and js', 'lua'), 298 | 1 299 | ) 300 | 301 | a.equal( 302 | str.index_of('lua and js', 'js'), 303 | 9 304 | ) 305 | 306 | a.equal( 307 | str.index_of('lua and js', 'javascript'), 308 | -1 309 | ) 310 | end) 311 | 312 | test('unescape', function(a) 313 | a.equal( 314 | str.unescape('"tom & jerry" <>'), 315 | '"tom & jerry" <>' 316 | ) 317 | 318 | a.equal( 319 | str.unescape(''tom & jerry' <>'), 320 | "'tom & jerry' <>" 321 | ) 322 | end) 323 | 324 | test('replace', function(a) 325 | a.equal( 326 | str.replace('Lua is cute. Lua is cute too', 'cute', 'great'), 327 | 'Lua is great. Lua is great too' 328 | ) 329 | end) 330 | --------------------------------------------------------------------------------