Skip to content

Commit bbb33ff

Browse files
authored
Merge pull request #6 from github/add-string-replaceall
add string#replaceAll
2 parents d8546ff + 0992c34 commit bbb33ff

3 files changed

Lines changed: 58 additions & 1 deletion

File tree

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const baseSupport =
3636
//'allSettled' in Promise && // Polyfilled
3737
'matchAll' in String.prototype &&
3838
// ES2021
39-
'replaceAll' in String.prototype &&
39+
//'replaceAll' in String.prototype && // Polyfilled
4040
// 'any' in Promise && // Polyfilled
4141
// ES2022
4242
// 'at' in String.prototype && // Polyfilled

src/string-replaceall.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
export function stringReplaceAll(
2+
this: string,
3+
searchValue: RegExp | string,
4+
replaceValue: ((substring: string, ...args: unknown[]) => string) | string
5+
): string {
6+
if (searchValue instanceof RegExp) return this.replace(searchValue, replaceValue as unknown as string)
7+
let pos = -1
8+
let endOfLastMatch = 0
9+
let result = ''
10+
if (typeof replaceValue === 'function') {
11+
const unwrapped = replaceValue
12+
replaceValue = () => unwrapped(searchValue, pos, this)
13+
}
14+
pos = this.indexOf(searchValue, pos + 1)
15+
while (pos !== -1) {
16+
result += this.substring(endOfLastMatch, pos)
17+
result += searchValue.replace(searchValue, replaceValue as string)
18+
endOfLastMatch = pos + searchValue.length
19+
pos = this.indexOf(searchValue, pos + 1)
20+
}
21+
return result + this.substring(endOfLastMatch)
22+
}
23+
24+
/*#__PURE__*/
25+
export function isSupported(): boolean {
26+
return 'replaceAll' in String.prototype && typeof String.prototype.replaceAll === 'function'
27+
}
28+
29+
/*#__PURE__*/
30+
export function isPolyfilled(): boolean {
31+
return String.prototype.replaceAll === stringReplaceAll
32+
}
33+
34+
export function apply(): void {
35+
if (!isSupported()) {
36+
String.prototype.replaceAll = stringReplaceAll
37+
}
38+
}

test/string-replaceall.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {apply, isPolyfilled, isSupported, stringReplaceAll} from '../lib/string-replaceall.js'
2+
3+
describe('String#replaceAll', () => {
4+
it('has standard isSupported, isPolyfilled, apply API', () => {
5+
expect(isSupported).to.be.a('function')
6+
expect(isPolyfilled).to.be.a('function')
7+
expect(apply).to.be.a('function')
8+
expect(isSupported()).to.be.a('boolean')
9+
expect(isPolyfilled()).to.equal(false)
10+
})
11+
12+
it('replaces all ocurrences of a string', async () => {
13+
expect(stringReplaceAll.call('aaa', 'a', 'bbb')).to.equal('bbbbbbbbb')
14+
expect(stringReplaceAll.call('aaa', 'a', 'aba')).to.equal('abaabaaba')
15+
expect(stringReplaceAll.call('_a_a_a_', 'a', 'b')).to.equal('_b_b_b_')
16+
expect(stringReplaceAll.call('aaa', 'a', (match, i, whole) => match + i + whole)).to.equal('a0aaaa1aaaa2aaa')
17+
expect(stringReplaceAll.call('aaa', /a/g, 'bbb')).to.equal('bbbbbbbbb')
18+
})
19+
})

0 commit comments

Comments
 (0)