UNPKG

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