-
-
Notifications
You must be signed in to change notification settings - Fork 65
/
string.js
137 lines (117 loc) · 3.74 KB
/
string.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import * as array from './array.js'
/**
* Utility module to work with strings.
*
* @module string
*/
export const fromCharCode = String.fromCharCode
export const fromCodePoint = String.fromCodePoint
/**
* The largest utf16 character.
* Corresponds to Uint8Array([255, 255]) or charcodeof(2x2^8)
*/
export const MAX_UTF16_CHARACTER = fromCharCode(65535)
/**
* @param {string} s
* @return {string}
*/
const toLowerCase = s => s.toLowerCase()
const trimLeftRegex = /^\s*/g
/**
* @param {string} s
* @return {string}
*/
export const trimLeft = s => s.replace(trimLeftRegex, '')
const fromCamelCaseRegex = /([A-Z])/g
/**
* @param {string} s
* @param {string} separator
* @return {string}
*/
export const fromCamelCase = (s, separator) => trimLeft(s.replace(fromCamelCaseRegex, match => `${separator}${toLowerCase(match)}`))
/**
* Compute the utf8ByteLength
* @param {string} str
* @return {number}
*/
export const utf8ByteLength = str => unescape(encodeURIComponent(str)).length
/**
* @param {string} str
* @return {Uint8Array}
*/
export const _encodeUtf8Polyfill = str => {
const encodedString = unescape(encodeURIComponent(str))
const len = encodedString.length
const buf = new Uint8Array(len)
for (let i = 0; i < len; i++) {
buf[i] = /** @type {number} */ (encodedString.codePointAt(i))
}
return buf
}
/* c8 ignore next */
export const utf8TextEncoder = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null)
/**
* @param {string} str
* @return {Uint8Array}
*/
export const _encodeUtf8Native = str => utf8TextEncoder.encode(str)
/**
* @param {string} str
* @return {Uint8Array}
*/
/* c8 ignore next */
export const encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill
/**
* @param {Uint8Array} buf
* @return {string}
*/
export const _decodeUtf8Polyfill = buf => {
let remainingLen = buf.length
let encodedString = ''
let bufPos = 0
while (remainingLen > 0) {
const nextLen = remainingLen < 10000 ? remainingLen : 10000
const bytes = buf.subarray(bufPos, bufPos + nextLen)
bufPos += nextLen
// Starting with ES5.1 we can supply a generic array-like object as arguments
encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes))
remainingLen -= nextLen
}
return decodeURIComponent(escape(encodedString))
}
/* c8 ignore next */
export let utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true })
/* c8 ignore start */
if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
// Safari doesn't handle BOM correctly.
// This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
// utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
// utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
// Another issue is that from then on no BOM chars are recognized anymore
/* c8 ignore next */
utf8TextDecoder = null
}
/* c8 ignore stop */
/**
* @param {Uint8Array} buf
* @return {string}
*/
export const _decodeUtf8Native = buf => /** @type {TextDecoder} */ (utf8TextDecoder).decode(buf)
/**
* @param {Uint8Array} buf
* @return {string}
*/
/* c8 ignore next */
export const decodeUtf8 = utf8TextDecoder ? _decodeUtf8Native : _decodeUtf8Polyfill
/**
* @param {string} str The initial string
* @param {number} index Starting position
* @param {number} remove Number of characters to remove
* @param {string} insert New content to insert
*/
export const splice = (str, index, remove, insert = '') => str.slice(0, index) + insert + str.slice(index + remove)
/**
* @param {string} source
* @param {number} n
*/
export const repeat = (source, n) => array.unfold(n, () => source).join('')