goscript 0.0.25 → 0.0.28

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 (190) hide show
  1. package/README.md +4 -4
  2. package/cmd/goscript/cmd_compile.go +0 -3
  3. package/cmd/goscript/deps.go +11 -0
  4. package/compiler/analysis.go +259 -55
  5. package/compiler/assignment.go +2 -2
  6. package/compiler/builtin_test.go +1 -1
  7. package/compiler/compiler.go +201 -49
  8. package/compiler/compiler_test.go +53 -0
  9. package/compiler/composite-lit.go +32 -8
  10. package/compiler/decl.go +6 -6
  11. package/compiler/expr-call.go +83 -0
  12. package/compiler/expr.go +1 -1
  13. package/compiler/protobuf.go +557 -0
  14. package/compiler/spec-struct.go +4 -0
  15. package/compiler/spec-value.go +11 -3
  16. package/compiler/spec.go +18 -1
  17. package/compiler/stmt-assign.go +35 -0
  18. package/compiler/type-assert.go +87 -0
  19. package/compiler/type.go +5 -2
  20. package/dist/gs/builtin/builtin.d.ts +19 -1
  21. package/dist/gs/builtin/builtin.js +85 -5
  22. package/dist/gs/builtin/builtin.js.map +1 -1
  23. package/dist/gs/builtin/channel.js.map +1 -1
  24. package/dist/gs/builtin/slice.d.ts +1 -1
  25. package/dist/gs/builtin/slice.js +59 -26
  26. package/dist/gs/builtin/slice.js.map +1 -1
  27. package/dist/gs/cmp/index.js.map +1 -1
  28. package/dist/gs/context/context.d.ts +1 -1
  29. package/dist/gs/context/context.js +20 -11
  30. package/dist/gs/context/context.js.map +1 -1
  31. package/dist/gs/errors/errors.d.ts +7 -0
  32. package/dist/gs/errors/errors.js +190 -0
  33. package/dist/gs/errors/errors.js.map +1 -0
  34. package/dist/gs/errors/index.d.ts +1 -0
  35. package/dist/gs/errors/index.js +2 -0
  36. package/dist/gs/errors/index.js.map +1 -0
  37. package/dist/gs/internal/goarch/index.js +1 -1
  38. package/dist/gs/internal/goarch/index.js.map +1 -1
  39. package/dist/gs/io/index.d.ts +1 -0
  40. package/dist/gs/io/index.js +2 -0
  41. package/dist/gs/io/index.js.map +1 -0
  42. package/dist/gs/io/io.d.ts +107 -0
  43. package/dist/gs/io/io.js +385 -0
  44. package/dist/gs/io/io.js.map +1 -0
  45. package/dist/gs/iter/iter.js.map +1 -1
  46. package/dist/gs/math/bits/index.js +34 -32
  47. package/dist/gs/math/bits/index.js.map +1 -1
  48. package/dist/gs/runtime/runtime.d.ts +1 -0
  49. package/dist/gs/runtime/runtime.js +15 -18
  50. package/dist/gs/runtime/runtime.js.map +1 -1
  51. package/dist/gs/slices/slices.d.ts +1 -1
  52. package/dist/gs/slices/slices.js +1 -1
  53. package/dist/gs/slices/slices.js.map +1 -1
  54. package/dist/gs/strings/builder.d.ts +18 -0
  55. package/dist/gs/strings/builder.js +205 -0
  56. package/dist/gs/strings/builder.js.map +1 -0
  57. package/dist/gs/strings/clone.d.ts +1 -0
  58. package/dist/gs/strings/clone.js +16 -0
  59. package/dist/gs/strings/clone.js.map +1 -0
  60. package/dist/gs/strings/compare.d.ts +1 -0
  61. package/dist/gs/strings/compare.js +14 -0
  62. package/dist/gs/strings/compare.js.map +1 -0
  63. package/dist/gs/strings/index.d.ts +2 -0
  64. package/dist/gs/strings/index.js +3 -0
  65. package/dist/gs/strings/index.js.map +1 -0
  66. package/dist/gs/strings/iter.d.ts +8 -0
  67. package/dist/gs/strings/iter.js +160 -0
  68. package/dist/gs/strings/iter.js.map +1 -0
  69. package/dist/gs/strings/reader.d.ts +34 -0
  70. package/dist/gs/strings/reader.js +418 -0
  71. package/dist/gs/strings/reader.js.map +1 -0
  72. package/dist/gs/strings/replace.d.ts +106 -0
  73. package/dist/gs/strings/replace.js +1136 -0
  74. package/dist/gs/strings/replace.js.map +1 -0
  75. package/dist/gs/strings/search.d.ts +24 -0
  76. package/dist/gs/strings/search.js +169 -0
  77. package/dist/gs/strings/search.js.map +1 -0
  78. package/dist/gs/strings/strings.d.ts +47 -0
  79. package/dist/gs/strings/strings.js +418 -0
  80. package/dist/gs/strings/strings.js.map +1 -0
  81. package/dist/gs/stringslite/index.d.ts +1 -0
  82. package/dist/gs/stringslite/index.js +2 -0
  83. package/dist/gs/stringslite/index.js.map +1 -0
  84. package/dist/gs/stringslite/strings.d.ts +11 -0
  85. package/dist/gs/stringslite/strings.js +67 -0
  86. package/dist/gs/stringslite/strings.js.map +1 -0
  87. package/dist/gs/sync/index.d.ts +1 -0
  88. package/dist/gs/sync/index.js +2 -0
  89. package/dist/gs/sync/index.js.map +1 -0
  90. package/dist/gs/sync/sync.d.ts +79 -0
  91. package/dist/gs/sync/sync.js +392 -0
  92. package/dist/gs/sync/sync.js.map +1 -0
  93. package/dist/gs/time/time.js +7 -7
  94. package/dist/gs/time/time.js.map +1 -1
  95. package/dist/gs/unicode/index.d.ts +1 -0
  96. package/dist/gs/unicode/index.js +2 -0
  97. package/dist/gs/unicode/index.js.map +1 -0
  98. package/dist/gs/unicode/unicode.d.ts +105 -0
  99. package/dist/gs/unicode/unicode.js +332 -0
  100. package/dist/gs/unicode/unicode.js.map +1 -0
  101. package/dist/gs/unicode/utf8/index.d.ts +1 -0
  102. package/dist/gs/unicode/utf8/index.js +3 -0
  103. package/dist/gs/unicode/utf8/index.js.map +1 -0
  104. package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
  105. package/dist/gs/unicode/utf8/utf8.js +196 -0
  106. package/dist/gs/unicode/utf8/utf8.js.map +1 -0
  107. package/dist/gs/unsafe/index.d.ts +1 -0
  108. package/dist/gs/unsafe/index.js +2 -0
  109. package/dist/gs/unsafe/index.js.map +1 -0
  110. package/dist/gs/unsafe/unsafe.d.ts +11 -0
  111. package/dist/gs/unsafe/unsafe.js +44 -0
  112. package/dist/gs/unsafe/unsafe.js.map +1 -0
  113. package/go.mod +2 -1
  114. package/go.sum +6 -2
  115. package/gs/README.md +6 -0
  116. package/gs/builtin/builtin.ts +158 -0
  117. package/gs/builtin/channel.ts +683 -0
  118. package/gs/builtin/defer.ts +58 -0
  119. package/gs/builtin/index.ts +1 -0
  120. package/gs/builtin/io.ts +22 -0
  121. package/gs/builtin/map.ts +50 -0
  122. package/gs/builtin/slice.ts +1030 -0
  123. package/gs/builtin/type.ts +1106 -0
  124. package/gs/builtin/varRef.ts +25 -0
  125. package/gs/cmp/godoc.txt +8 -0
  126. package/gs/cmp/index.ts +29 -0
  127. package/gs/context/context.ts +401 -0
  128. package/gs/context/godoc.txt +69 -0
  129. package/gs/context/index.ts +1 -0
  130. package/gs/errors/errors.ts +223 -0
  131. package/gs/errors/godoc.txt +63 -0
  132. package/gs/errors/index.ts +1 -0
  133. package/gs/internal/goarch/godoc.txt +39 -0
  134. package/gs/internal/goarch/index.ts +18 -0
  135. package/gs/io/godoc.txt +61 -0
  136. package/gs/io/index.ts +1 -0
  137. package/gs/io/io.go +75 -0
  138. package/gs/io/io.ts +546 -0
  139. package/gs/iter/godoc.txt +203 -0
  140. package/gs/iter/index.ts +1 -0
  141. package/gs/iter/iter.ts +117 -0
  142. package/gs/math/bits/index.ts +356 -0
  143. package/gs/math/godoc.txt +76 -0
  144. package/gs/runtime/godoc.txt +331 -0
  145. package/gs/runtime/index.ts +1 -0
  146. package/gs/runtime/runtime.ts +178 -0
  147. package/gs/slices/godoc.txt +44 -0
  148. package/gs/slices/index.ts +1 -0
  149. package/gs/slices/slices.ts +22 -0
  150. package/gs/strings/builder.test.ts +121 -0
  151. package/gs/strings/builder.ts +223 -0
  152. package/gs/strings/clone.test.ts +43 -0
  153. package/gs/strings/clone.ts +17 -0
  154. package/gs/strings/compare.test.ts +84 -0
  155. package/gs/strings/compare.ts +13 -0
  156. package/gs/strings/godoc.txt +66 -0
  157. package/gs/strings/index.ts +2 -0
  158. package/gs/strings/iter.test.ts +343 -0
  159. package/gs/strings/iter.ts +171 -0
  160. package/gs/strings/reader.test.ts +243 -0
  161. package/gs/strings/reader.ts +451 -0
  162. package/gs/strings/replace.test.ts +181 -0
  163. package/gs/strings/replace.ts +1310 -0
  164. package/gs/strings/search.test.ts +214 -0
  165. package/gs/strings/search.ts +213 -0
  166. package/gs/strings/strings.test.ts +477 -0
  167. package/gs/strings/strings.ts +510 -0
  168. package/gs/stringslite/godoc.txt +17 -0
  169. package/gs/stringslite/index.ts +1 -0
  170. package/gs/stringslite/strings.ts +82 -0
  171. package/gs/sync/godoc.txt +21 -0
  172. package/gs/sync/index.ts +1 -0
  173. package/gs/sync/sync.go +64 -0
  174. package/gs/sync/sync.ts +449 -0
  175. package/gs/time/godoc.md +116 -0
  176. package/gs/time/godoc.txt +116 -0
  177. package/gs/time/index.ts +1 -0
  178. package/gs/time/time.ts +272 -0
  179. package/gs/unicode/godoc.txt +52 -0
  180. package/gs/unicode/index.ts +1 -0
  181. package/gs/unicode/unicode.go +38 -0
  182. package/gs/unicode/unicode.ts +418 -0
  183. package/gs/unicode/utf8/godoc.txt +22 -0
  184. package/gs/unicode/utf8/index.ts +2 -0
  185. package/gs/unicode/utf8/utf8.ts +227 -0
  186. package/gs/unsafe/godoc.txt +19 -0
  187. package/gs/unsafe/index.ts +1 -0
  188. package/gs/unsafe/unsafe.test.ts +68 -0
  189. package/gs/unsafe/unsafe.ts +77 -0
  190. package/package.json +6 -4
@@ -0,0 +1,477 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import * as $ from '../builtin/index.js'
3
+ import {
4
+ Clone,
5
+ Compare,
6
+ Contains,
7
+ ContainsAny,
8
+ ContainsFunc,
9
+ ContainsRune,
10
+ Count,
11
+ Cut,
12
+ CutPrefix,
13
+ CutSuffix,
14
+ EqualFold,
15
+ Fields,
16
+ FieldsFunc,
17
+ HasPrefix,
18
+ HasSuffix,
19
+ Index,
20
+ IndexAny,
21
+ IndexByte,
22
+ IndexFunc,
23
+ IndexRune,
24
+ Join,
25
+ LastIndex,
26
+ LastIndexAny,
27
+ LastIndexByte,
28
+ LastIndexFunc,
29
+ Map,
30
+ Repeat,
31
+ Replace,
32
+ ReplaceAll,
33
+ Split,
34
+ SplitAfter,
35
+ SplitAfterN,
36
+ SplitN,
37
+ Title,
38
+ ToLower,
39
+ ToTitle,
40
+ ToUpper,
41
+ Trim,
42
+ TrimFunc,
43
+ TrimLeft,
44
+ TrimLeftFunc,
45
+ TrimPrefix,
46
+ TrimRight,
47
+ TrimRightFunc,
48
+ TrimSpace,
49
+ TrimSuffix,
50
+ } from './strings.js'
51
+
52
+ describe('strings', () => {
53
+ describe('Clone', () => {
54
+ it('should return a copy of the string', () => {
55
+ expect(Clone('hello')).toBe('hello')
56
+ expect(Clone('')).toBe('')
57
+ expect(Clone('unicode: 🌟')).toBe('unicode: 🌟')
58
+ })
59
+ })
60
+
61
+ describe('Compare', () => {
62
+ it('should compare strings lexicographically', () => {
63
+ expect(Compare('a', 'b')).toBe(-1)
64
+ expect(Compare('b', 'a')).toBe(1)
65
+ expect(Compare('hello', 'hello')).toBe(0)
66
+ expect(Compare('', '')).toBe(0)
67
+ expect(Compare('abc', 'abcd')).toBe(-1)
68
+ })
69
+ })
70
+
71
+ describe('Contains', () => {
72
+ it('should check if substr is within s', () => {
73
+ expect(Contains('hello world', 'world')).toBe(true)
74
+ expect(Contains('hello world', 'xyz')).toBe(false)
75
+ expect(Contains('', '')).toBe(true)
76
+ expect(Contains('abc', '')).toBe(true)
77
+ expect(Contains('', 'a')).toBe(false)
78
+ })
79
+ })
80
+
81
+ describe('ContainsAny', () => {
82
+ it('should check if any chars are within s', () => {
83
+ expect(ContainsAny('hello', 'aeiou')).toBe(true)
84
+ expect(ContainsAny('hello', 'xyz')).toBe(false)
85
+ expect(ContainsAny('', 'abc')).toBe(false)
86
+ expect(ContainsAny('abc', '')).toBe(false)
87
+ })
88
+ })
89
+
90
+ describe('ContainsFunc', () => {
91
+ it('should check if any rune satisfies predicate', () => {
92
+ expect(ContainsFunc('hello', (r) => r === 101)).toBe(true) // 'e'
93
+ expect(ContainsFunc('hello', (r) => r === 120)).toBe(false) // 'x'
94
+ expect(ContainsFunc('', (r) => true)).toBe(false)
95
+ expect(ContainsFunc('abc', null)).toBe(false)
96
+ })
97
+ })
98
+
99
+ describe('ContainsRune', () => {
100
+ it('should check if rune is within s', () => {
101
+ expect(ContainsRune('hello', 101)).toBe(true) // 'e'
102
+ expect(ContainsRune('hello', 120)).toBe(false) // 'x'
103
+ expect(ContainsRune('', 97)).toBe(false) // 'a'
104
+ })
105
+ })
106
+
107
+ describe('Count', () => {
108
+ it('should count non-overlapping instances', () => {
109
+ expect(Count('hello', 'l')).toBe(2)
110
+ expect(Count('hello', 'll')).toBe(1)
111
+ expect(Count('hello', 'x')).toBe(0)
112
+ expect(Count('', '')).toBe(1)
113
+ expect(Count('abc', '')).toBe(4)
114
+ })
115
+ })
116
+
117
+ describe('Cut', () => {
118
+ it('should cut string around first instance of sep', () => {
119
+ expect(Cut('hello-world', '-')).toEqual(['hello', 'world', true])
120
+ expect(Cut('hello', '-')).toEqual(['hello', '', false])
121
+ expect(Cut('', '-')).toEqual(['', '', false])
122
+ expect(Cut('a-b-c', '-')).toEqual(['a', 'b-c', true])
123
+ })
124
+ })
125
+
126
+ describe('CutPrefix', () => {
127
+ it('should cut prefix and report if found', () => {
128
+ expect(CutPrefix('hello world', 'hello ')).toEqual(['world', true])
129
+ expect(CutPrefix('hello world', 'hi ')).toEqual(['hello world', false])
130
+ expect(CutPrefix('', '')).toEqual(['', true])
131
+ expect(CutPrefix('abc', '')).toEqual(['abc', true])
132
+ })
133
+ })
134
+
135
+ describe('CutSuffix', () => {
136
+ it('should cut suffix and report if found', () => {
137
+ expect(CutSuffix('hello world', ' world')).toEqual(['hello', true])
138
+ expect(CutSuffix('hello world', ' universe')).toEqual([
139
+ 'hello world',
140
+ false,
141
+ ])
142
+ expect(CutSuffix('', '')).toEqual(['', true])
143
+ expect(CutSuffix('abc', '')).toEqual(['abc', true])
144
+ })
145
+ })
146
+
147
+ describe('EqualFold', () => {
148
+ it('should compare strings case-insensitively', () => {
149
+ expect(EqualFold('hello', 'HELLO')).toBe(true)
150
+ expect(EqualFold('Hello', 'hello')).toBe(true)
151
+ expect(EqualFold('hello', 'world')).toBe(false)
152
+ expect(EqualFold('', '')).toBe(true)
153
+ })
154
+ })
155
+
156
+ describe('Fields', () => {
157
+ it('should split around whitespace', () => {
158
+ const result = Fields(' hello world ')
159
+ expect($.asArray(result)).toEqual(['hello', 'world'])
160
+
161
+ const empty = Fields(' ')
162
+ expect($.asArray(empty)).toEqual([])
163
+
164
+ const single = Fields('hello')
165
+ expect($.asArray(single)).toEqual(['hello'])
166
+ })
167
+ })
168
+
169
+ describe('FieldsFunc', () => {
170
+ it('should split around runes satisfying predicate', () => {
171
+ const result = FieldsFunc('a,b,c', (r) => r === 44) // comma
172
+ expect($.asArray(result)).toEqual(['a', 'b', 'c'])
173
+
174
+ const empty = FieldsFunc('', (r) => true)
175
+ expect($.asArray(empty)).toEqual([])
176
+
177
+ const noSplit = FieldsFunc('abc', null)
178
+ expect($.asArray(noSplit)).toEqual(['abc'])
179
+ })
180
+ })
181
+
182
+ describe('HasPrefix', () => {
183
+ it('should check if string begins with prefix', () => {
184
+ expect(HasPrefix('hello world', 'hello')).toBe(true)
185
+ expect(HasPrefix('hello world', 'world')).toBe(false)
186
+ expect(HasPrefix('', '')).toBe(true)
187
+ expect(HasPrefix('abc', '')).toBe(true)
188
+ })
189
+ })
190
+
191
+ describe('HasSuffix', () => {
192
+ it('should check if string ends with suffix', () => {
193
+ expect(HasSuffix('hello world', 'world')).toBe(true)
194
+ expect(HasSuffix('hello world', 'hello')).toBe(false)
195
+ expect(HasSuffix('', '')).toBe(true)
196
+ expect(HasSuffix('abc', '')).toBe(true)
197
+ })
198
+ })
199
+
200
+ describe('Index', () => {
201
+ it('should find first index of substr', () => {
202
+ expect(Index('hello world', 'world')).toBe(6)
203
+ expect(Index('hello world', 'xyz')).toBe(-1)
204
+ expect(Index('hello', 'hello')).toBe(0)
205
+ expect(Index('', '')).toBe(0)
206
+ })
207
+ })
208
+
209
+ describe('IndexAny', () => {
210
+ it('should find first index of any char from chars', () => {
211
+ expect(IndexAny('hello', 'aeiou')).toBe(1) // 'e'
212
+ expect(IndexAny('hello', 'xyz')).toBe(-1)
213
+ expect(IndexAny('', 'abc')).toBe(-1)
214
+ })
215
+ })
216
+
217
+ describe('IndexByte', () => {
218
+ it('should find first index of byte', () => {
219
+ expect(IndexByte('hello', 101)).toBe(1) // 'e'
220
+ expect(IndexByte('hello', 120)).toBe(-1) // 'x'
221
+ expect(IndexByte('', 97)).toBe(-1) // 'a'
222
+ })
223
+ })
224
+
225
+ describe('IndexFunc', () => {
226
+ it('should find first index where predicate is true', () => {
227
+ expect(IndexFunc('hello', (r) => r === 101)).toBe(1) // 'e'
228
+ expect(IndexFunc('hello', (r) => r === 120)).toBe(-1) // 'x'
229
+ expect(IndexFunc('', (r) => true)).toBe(-1)
230
+ expect(IndexFunc('abc', null)).toBe(-1)
231
+ })
232
+ })
233
+
234
+ describe('IndexRune', () => {
235
+ it('should find first index of rune', () => {
236
+ expect(IndexRune('hello', 101)).toBe(1) // 'e'
237
+ expect(IndexRune('hello', 120)).toBe(-1) // 'x'
238
+ expect(IndexRune('', 97)).toBe(-1) // 'a'
239
+ })
240
+ })
241
+
242
+ describe('Join', () => {
243
+ it('should join slice elements with separator', () => {
244
+ const slice = $.arrayToSlice(['hello', 'world'])
245
+ expect(Join(slice, ' ')).toBe('hello world')
246
+
247
+ const empty = $.arrayToSlice([])
248
+ expect(Join(empty, ',')).toBe('')
249
+
250
+ const single = $.arrayToSlice(['hello'])
251
+ expect(Join(single, ',')).toBe('hello')
252
+ })
253
+ })
254
+
255
+ describe('LastIndex', () => {
256
+ it('should find last index of substr', () => {
257
+ expect(LastIndex('hello world hello', 'hello')).toBe(12)
258
+ expect(LastIndex('hello world', 'xyz')).toBe(-1)
259
+ expect(LastIndex('hello', 'hello')).toBe(0)
260
+ })
261
+ })
262
+
263
+ describe('LastIndexAny', () => {
264
+ it('should find last index of any char from chars', () => {
265
+ expect(LastIndexAny('hello', 'aeiou')).toBe(4) // 'o'
266
+ expect(LastIndexAny('hello', 'xyz')).toBe(-1)
267
+ expect(LastIndexAny('', 'abc')).toBe(-1)
268
+ })
269
+ })
270
+
271
+ describe('LastIndexByte', () => {
272
+ it('should find last index of byte', () => {
273
+ expect(LastIndexByte('hello', 108)).toBe(3) // 'l'
274
+ expect(LastIndexByte('hello', 120)).toBe(-1) // 'x'
275
+ expect(LastIndexByte('', 97)).toBe(-1) // 'a'
276
+ })
277
+ })
278
+
279
+ describe('LastIndexFunc', () => {
280
+ it('should find last index where predicate is true', () => {
281
+ expect(LastIndexFunc('hello', (r) => r === 108)).toBe(3) // 'l'
282
+ expect(LastIndexFunc('hello', (r) => r === 120)).toBe(-1) // 'x'
283
+ expect(LastIndexFunc('', (r) => true)).toBe(-1)
284
+ expect(LastIndexFunc('abc', null)).toBe(-1)
285
+ })
286
+ })
287
+
288
+ describe('Map', () => {
289
+ it('should apply mapping function to each rune', () => {
290
+ expect(Map((r) => r + 1, 'abc')).toBe('bcd')
291
+ expect(Map((r) => 65, 'hello')).toBe('AAAAA') // all to 'A'
292
+ expect(Map(null, 'hello')).toBe('hello')
293
+ expect(Map((r) => r, '')).toBe('')
294
+ })
295
+ })
296
+
297
+ describe('Repeat', () => {
298
+ it('should repeat string count times', () => {
299
+ expect(Repeat('abc', 3)).toBe('abcabcabc')
300
+ expect(Repeat('hello', 0)).toBe('')
301
+ expect(Repeat('', 5)).toBe('')
302
+ expect(() => Repeat('abc', -1)).toThrow()
303
+ })
304
+ })
305
+
306
+ describe('Replace', () => {
307
+ it('should replace first n instances of old with new', () => {
308
+ expect(Replace('hello world hello', 'hello', 'hi', 1)).toBe(
309
+ 'hi world hello',
310
+ )
311
+ expect(Replace('hello world hello', 'hello', 'hi', 2)).toBe('hi world hi')
312
+ expect(Replace('hello world', 'xyz', 'abc', 1)).toBe('hello world')
313
+ expect(Replace('hello', '', 'x', 1)).toBe('hello')
314
+ })
315
+ })
316
+
317
+ describe('ReplaceAll', () => {
318
+ it('should replace all instances of old with new', () => {
319
+ expect(ReplaceAll('hello world hello', 'hello', 'hi')).toBe('hi world hi')
320
+ expect(ReplaceAll('hello world', 'xyz', 'abc')).toBe('hello world')
321
+ expect(ReplaceAll('hello', '', 'x')).toBe('hello')
322
+ })
323
+ })
324
+
325
+ describe('Split', () => {
326
+ it('should split string by separator', () => {
327
+ const result = Split('a,b,c', ',')
328
+ expect($.asArray(result)).toEqual(['a', 'b', 'c'])
329
+
330
+ const empty = Split('', ',')
331
+ expect($.asArray(empty)).toEqual([''])
332
+
333
+ const explode = Split('abc', '')
334
+ expect($.asArray(explode)).toEqual(['a', 'b', 'c'])
335
+ })
336
+ })
337
+
338
+ describe('SplitAfter', () => {
339
+ it('should split after each instance of sep', () => {
340
+ const result = SplitAfter('a,b,c', ',')
341
+ expect($.asArray(result)).toEqual(['a,', 'b,', 'c'])
342
+
343
+ const noSep = SplitAfter('abc', ',')
344
+ expect($.asArray(noSep)).toEqual(['abc'])
345
+ })
346
+ })
347
+
348
+ describe('SplitAfterN', () => {
349
+ it('should split after each instance of sep up to n times', () => {
350
+ const result = SplitAfterN('a,b,c,d', ',', 2)
351
+ expect($.asArray(result)).toEqual(['a,', 'b,c,d'])
352
+
353
+ const zero = SplitAfterN('a,b,c', ',', 0)
354
+ expect($.asArray(zero)).toEqual([])
355
+ })
356
+ })
357
+
358
+ describe('SplitN', () => {
359
+ it('should split string by separator up to n times', () => {
360
+ const result = SplitN('a,b,c,d', ',', 2)
361
+ expect($.asArray(result)).toEqual(['a', 'b,c,d'])
362
+
363
+ const zero = SplitN('a,b,c', ',', 0)
364
+ expect($.asArray(zero)).toEqual([])
365
+
366
+ const one = SplitN('a,b,c', ',', 1)
367
+ expect($.asArray(one)).toEqual(['a,b,c'])
368
+ })
369
+ })
370
+
371
+ describe('Title', () => {
372
+ it('should convert to title case', () => {
373
+ expect(Title('hello world')).toBe('Hello World')
374
+ expect(Title('HELLO WORLD')).toBe('Hello World')
375
+ expect(Title('')).toBe('')
376
+ })
377
+ })
378
+
379
+ describe('ToLower', () => {
380
+ it('should convert to lowercase', () => {
381
+ expect(ToLower('HELLO WORLD')).toBe('hello world')
382
+ expect(ToLower('Hello World')).toBe('hello world')
383
+ expect(ToLower('')).toBe('')
384
+ })
385
+ })
386
+
387
+ describe('ToTitle', () => {
388
+ it('should convert to title case', () => {
389
+ expect(ToTitle('hello world')).toBe('Hello World')
390
+ expect(ToTitle('HELLO WORLD')).toBe('Hello World')
391
+ expect(ToTitle('')).toBe('')
392
+ })
393
+ })
394
+
395
+ describe('ToUpper', () => {
396
+ it('should convert to uppercase', () => {
397
+ expect(ToUpper('hello world')).toBe('HELLO WORLD')
398
+ expect(ToUpper('Hello World')).toBe('HELLO WORLD')
399
+ expect(ToUpper('')).toBe('')
400
+ })
401
+ })
402
+
403
+ describe('Trim', () => {
404
+ it('should trim cutset from both ends', () => {
405
+ expect(Trim('!hello!', '!')).toBe('hello')
406
+ expect(Trim(' hello ', ' ')).toBe('hello')
407
+ expect(Trim('hello', 'x')).toBe('hello')
408
+ expect(Trim('', 'x')).toBe('')
409
+ })
410
+ })
411
+
412
+ describe('TrimFunc', () => {
413
+ it('should trim runes satisfying predicate from both ends', () => {
414
+ expect(TrimFunc(' hello ', (r) => r === 32)).toBe('hello') // space
415
+ expect(TrimFunc('hello', (r) => r === 120)).toBe('hello') // 'x'
416
+ expect(TrimFunc('', (r) => true)).toBe('')
417
+ expect(TrimFunc('abc', null)).toBe('abc')
418
+ })
419
+ })
420
+
421
+ describe('TrimLeft', () => {
422
+ it('should trim cutset from left end', () => {
423
+ expect(TrimLeft('!hello!', '!')).toBe('hello!')
424
+ expect(TrimLeft(' hello ', ' ')).toBe('hello ')
425
+ expect(TrimLeft('hello', 'x')).toBe('hello')
426
+ })
427
+ })
428
+
429
+ describe('TrimLeftFunc', () => {
430
+ it('should trim runes satisfying predicate from left end', () => {
431
+ expect(TrimLeftFunc(' hello ', (r) => r === 32)).toBe('hello ') // space
432
+ expect(TrimLeftFunc('hello', (r) => r === 120)).toBe('hello') // 'x'
433
+ expect(TrimLeftFunc('abc', null)).toBe('abc')
434
+ })
435
+ })
436
+
437
+ describe('TrimPrefix', () => {
438
+ it('should remove prefix if present', () => {
439
+ expect(TrimPrefix('hello world', 'hello ')).toBe('world')
440
+ expect(TrimPrefix('hello world', 'hi ')).toBe('hello world')
441
+ expect(TrimPrefix('', '')).toBe('')
442
+ })
443
+ })
444
+
445
+ describe('TrimRight', () => {
446
+ it('should trim cutset from right end', () => {
447
+ expect(TrimRight('!hello!', '!')).toBe('!hello')
448
+ expect(TrimRight(' hello ', ' ')).toBe(' hello')
449
+ expect(TrimRight('hello', 'x')).toBe('hello')
450
+ })
451
+ })
452
+
453
+ describe('TrimRightFunc', () => {
454
+ it('should trim runes satisfying predicate from right end', () => {
455
+ expect(TrimRightFunc(' hello ', (r) => r === 32)).toBe(' hello') // space
456
+ expect(TrimRightFunc('hello', (r) => r === 120)).toBe('hello') // 'x'
457
+ expect(TrimRightFunc('abc', null)).toBe('abc')
458
+ })
459
+ })
460
+
461
+ describe('TrimSpace', () => {
462
+ it('should trim whitespace from both ends', () => {
463
+ expect(TrimSpace(' hello ')).toBe('hello')
464
+ expect(TrimSpace('\t\nhello\r\n')).toBe('hello')
465
+ expect(TrimSpace('hello')).toBe('hello')
466
+ expect(TrimSpace('')).toBe('')
467
+ })
468
+ })
469
+
470
+ describe('TrimSuffix', () => {
471
+ it('should remove suffix if present', () => {
472
+ expect(TrimSuffix('hello world', ' world')).toBe('hello')
473
+ expect(TrimSuffix('hello world', ' universe')).toBe('hello world')
474
+ expect(TrimSuffix('', '')).toBe('')
475
+ })
476
+ })
477
+ })