Skip to content

Commit

Permalink
feat: add repeat, base64
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Oct 10, 2018
1 parent 42ff9eb commit 2d4759a
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/base64Decode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* 返回 base64 解码后的字符串。
*
* @param str 要解码的字符串
* @returns 解码后的字符串
* @see https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem#Solution_1_%E2%80%93_escaping_the_string_before_encoding_it
*/
export default function base64Decode(str: string): string {
return decodeURIComponent(
atob(str)
.split('')
.map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)) // tslint:disable-line
.join('')
)
}
18 changes: 18 additions & 0 deletions src/base64Encode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* 返回 base64 编码后的字符串。
*
* @param str 要编码的字符串
* @returns 编码后的字符串
* @see https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem#Solution_1_%E2%80%93_escaping_the_string_before_encoding_it
*/
export default function base64Encode(str: string | number): string {
return btoa(
encodeURIComponent(str as string)
.replace(
/%([0-9A-F]{2})/g,
function toSolidBytes(match, p1) {
return String.fromCharCode(`0x${p1}` as any)
}
)
)
}
17 changes: 17 additions & 0 deletions src/base64UrlDecode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import base64Decode from './base64Decode'
import repeat from './repeat'

/**
* 返回 base64url 解码后的字符串。
*
* @param str 要解码的字符串
* @returns 解码后的字符串
* @see http://www.ietf.org/rfc/rfc4648.txt
*/
export default function base64UrlDecode(str: string): string {
const remainder = str.length % 4
if (str !== '' && remainder > 0) {
str += repeat('=', 4 - remainder)
}
return base64Decode(str.replace(/-/g, '+').replace(/_/g, '/'))
}
15 changes: 15 additions & 0 deletions src/base64UrlEncode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import base64Encode from './base64Encode'

/**
* 返回 base64url 编码后的字符串。
*
* @param str 要编码的字符串
* @returns 编码后的字符串
* @see http://www.ietf.org/rfc/rfc4648.txt
*/
export default function base64UrlEncode(str: string | number): string {
return base64Encode(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '')
}
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export { default as base64Decode } from './base64Decode'
export { default as base64Encode } from './base64Encode'
export { default as base64UrlDecode } from './base64UrlDecode'
export { default as base64UrlEncode } from './base64UrlEncode'
export { default as bindEvent } from './bindEvent'
export { default as castArray } from './castArray'
export { default as clamp } from './clamp'
Expand All @@ -6,3 +10,4 @@ export { default as inBrowser } from './inBrowser'
export { default as isFunction } from './isFunction'
export { default as noop } from './noop'
export { default as reduce } from './reduce'
export { default as repeat } from './repeat'
15 changes: 15 additions & 0 deletions src/repeat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* 重复 N 次给定字符串。
*
* @param str 要重复的字符串
* @param [n=1] 重复的次数
* @returns 结果字符串
*/
export default function repeat(str: string | number, n: number = 1) {
n = Math.round(n <= 0 ? 1 : n)
let result = ''
while (n--) {
result += str
}
return result
}
60 changes: 60 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,63 @@ describe('isFunction', () => {
expect(vtils.isFunction(null)).toBeFalsy()
})
})

describe('repeat', () => {
test('空字符串', () => {
expect(vtils.repeat('')).toBe('')
expect(vtils.repeat('', 20)).toBe('')
})
test('字符串', () => {
expect(vtils.repeat('我们')).toBe('我们')
expect(vtils.repeat('我们', 2)).toBe('我们我们')
})
test('数字', () => {
expect(vtils.repeat(1)).toBe('1')
expect(vtils.repeat(1, 2)).toBe('11')
})
test('负数、0、1', () => {
expect(vtils.repeat(1, -1)).toBe('1')
expect(vtils.repeat('我们', -2)).toBe('我们')
expect(vtils.repeat(1, 0)).toBe('1')
expect(vtils.repeat('我们', 0)).toBe('我们')
expect(vtils.repeat(1, 1)).toBe('1')
expect(vtils.repeat('我们', 1)).toBe('我们')
})
})

describe('base64', () => {
const data: Array<[string | number, string, string]> = [
['', '', ''],
['v', 'dg==', 'dg'],
['vtils', 'dnRpbHM=', 'dnRpbHM'],
['vtils.base64Encode', 'dnRpbHMuYmFzZTY0RW5jb2Rl', 'dnRpbHMuYmFzZTY0RW5jb2Rl'],
['JavaScript 工具库', 'SmF2YVNjcmlwdCDlt6XlhbflupM=', 'SmF2YVNjcmlwdCDlt6XlhbflupM'],
['JavaScript\n工具库', 'SmF2YVNjcmlwdArlt6XlhbflupM=', 'SmF2YVNjcmlwdArlt6XlhbflupM'],
['\0', 'AA==', 'AA'],
[1, 'MQ==', 'MQ'],
[-1, 'LTE=', 'LTE'],
['abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#0^&*();:<>,. []{}', 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==', 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODkhQCMwXiYqKCk7Ojw-LC4gW117fQ'],
['😁😎=-#@`.,?/|{*+😁', '8J+YgfCfmI49LSNAYC4sPy98eyor8J+YgQ==', '8J-YgfCfmI49LSNAYC4sPy98eyor8J-YgQ'],
['❥(ゝω・✿ฺ)※▓●²♠⑲Ⅲ∵molÇùㄡεətsフぽㅚ㉢д╢┉(๑╹◡╹)ノ"""', '4p2lKOOCnc+J44O74py/4Li6KeKAu+KWk+KXj8Ky4pmg4pGy4oWi4oi1bW9sw4fDueOEoc61yZl0c+ODleOBveOFmuOJotC04pWi4pSJKOC5keKVueKXoeKVuSnvvokiIiI=', '4p2lKOOCnc-J44O74py_4Li6KeKAu-KWk-KXj8Ky4pmg4pGy4oWi4oi1bW9sw4fDueOEoc61yZl0c-ODleOBveOFmuOJotC04pWi4pSJKOC5keKVueKXoeKVuSnvvokiIiI']
]
test('encode', () => {
data.forEach(([str, encodedStr]) => {
expect(vtils.base64Encode(str)).toBe(encodedStr)
})
})
test('decode', () => {
data.forEach(([str, encodedStr]) => {
expect(vtils.base64Decode(encodedStr)).toBe(String(str))
})
})
test('url encode', () => {
data.forEach(([str, encodedStr, encodedUrlStr]) => {
expect(vtils.base64UrlEncode(str)).toBe(encodedUrlStr)
})
})
test('url decode', () => {
data.forEach(([str, encodedStr, encodedUrlStr]) => {
expect(vtils.base64UrlDecode(encodedUrlStr)).toBe(String(str))
})
})
})

0 comments on commit 2d4759a

Please sign in to comment.