@oxog/string
Version:
Comprehensive string manipulation utilities with zero dependencies
139 lines (138 loc) • 4.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeBase64 = encodeBase64;
exports.decodeBase64 = decodeBase64;
exports.encodeHex = encodeHex;
exports.decodeHex = decodeHex;
exports.encodeHtml = encodeHtml;
exports.decodeHtml = decodeHtml;
exports.encodeUri = encodeUri;
exports.decodeUri = decodeUri;
function encodeBase64(str) {
if (typeof Buffer !== 'undefined') {
return Buffer.from(str, 'utf8').toString('base64');
}
if (typeof btoa !== 'undefined') {
return btoa(unescape(encodeURIComponent(str)));
}
return base64Encode(str);
}
function decodeBase64(str) {
if (typeof Buffer !== 'undefined') {
return Buffer.from(str, 'base64').toString('utf8');
}
if (typeof atob !== 'undefined') {
return decodeURIComponent(escape(atob(str)));
}
return base64Decode(str);
}
function encodeHex(str) {
const encoder = new TextEncoder();
const bytes = encoder.encode(str);
return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
}
function decodeHex(str) {
if (str.length % 2 !== 0) {
throw new Error('Invalid hex string');
}
const bytes = new Uint8Array(str.length / 2);
for (let i = 0; i < str.length; i += 2) {
bytes[i / 2] = parseInt(str.slice(i, i + 2), 16);
}
// For single bytes, use String.fromCharCode for raw byte values
if (bytes.length === 1) {
return String.fromCharCode(bytes[0]);
}
// For multi-byte sequences, try UTF-8 decoding first
try {
const decoder = new TextDecoder('utf-8', { fatal: true });
return decoder.decode(bytes);
}
catch (_a) {
// Fall back to latin-1 for raw bytes
return Array.from(bytes, byte => String.fromCharCode(byte)).join('');
}
}
function encodeHtml(str) {
const htmlEntities = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/'
};
return str.replace(/[&<>"'/]/g, char => htmlEntities[char] || char);
}
function decodeHtml(str) {
const htmlEntities = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
''': "'",
'/': '/',
''': "'",
' ': ' ',
'©': '©',
'®': '®',
'™': '™'
};
return str.replace(/&[#\w]+;/g, entity => htmlEntities[entity] || entity);
}
function encodeUri(str) {
return encodeURIComponent(str);
}
function decodeUri(str) {
try {
return decodeURIComponent(str);
}
catch (_a) {
// Return original string if decoding fails
return str;
}
}
// Pure JavaScript Base64 implementation
function base64Encode(str) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let result = '';
let i = 0;
const encoder = new TextEncoder();
const bytes = encoder.encode(str);
while (i < bytes.length) {
const a = bytes[i++];
const b = i < bytes.length ? bytes[i++] : 0;
const c = i < bytes.length ? bytes[i++] : 0;
const bitmap = (a << 16) | (b << 8) | c;
result += chars.charAt((bitmap >> 18) & 63);
result += chars.charAt((bitmap >> 12) & 63);
result += i - 2 < bytes.length ? chars.charAt((bitmap >> 6) & 63) : '=';
result += i - 1 < bytes.length ? chars.charAt(bitmap & 63) : '=';
}
return result;
}
function base64Decode(str) {
var _a, _b, _c, _d;
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const lookup = new Map();
for (let i = 0; i < chars.length; i++) {
lookup.set(chars[i], i);
}
str = str.replace(/[^A-Za-z0-9+/]/g, '');
const bytes = [];
let i = 0;
while (i < str.length) {
const encoded1 = (_a = lookup.get(str[i++])) !== null && _a !== void 0 ? _a : 0;
const encoded2 = (_b = lookup.get(str[i++])) !== null && _b !== void 0 ? _b : 0;
const encoded3 = (_c = lookup.get(str[i++])) !== null && _c !== void 0 ? _c : 0;
const encoded4 = (_d = lookup.get(str[i++])) !== null && _d !== void 0 ? _d : 0;
const bitmap = (encoded1 << 18) | (encoded2 << 12) | (encoded3 << 6) | encoded4;
bytes.push((bitmap >> 16) & 255);
if ((str[i - 2] || '') !== '=')
bytes.push((bitmap >> 8) & 255);
if ((str[i - 1] || '') !== '=')
bytes.push(bitmap & 255);
}
const decoder = new TextDecoder();
return decoder.decode(new Uint8Array(bytes));
}