UNPKG

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