feat(core): Introduce native implementations for Base64, random generation and normalization; remove runtime plugin dependencies; update tests, docs and package metadata

This commit is contained in:
2025-09-12 18:57:31 +00:00
parent 6a7570de7b
commit 1f3e170a88
17 changed files with 7585 additions and 4795 deletions

View File

@@ -1,10 +1,89 @@
import * as plugins from './smartstring.plugins.js';
/**
* the type for base 64
*/
export type TStringInputType = 'string' | 'base64' | 'base64uri';
/**
* Cross-platform base64 implementation
* Works in both Node.js and browser environments
*/
const universalBase64 = {
encode: (str: string): string => {
if (typeof Buffer !== 'undefined') {
// Node.js environment
return Buffer.from(str, 'utf8').toString('base64');
} else if (typeof btoa !== 'undefined') {
// Browser environment
// Handle Unicode properly
const utf8Bytes = new TextEncoder().encode(str);
const binaryString = Array.from(utf8Bytes, byte => String.fromCharCode(byte)).join('');
return btoa(binaryString);
} else {
// Fallback pure JS implementation
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const bytes = new TextEncoder().encode(str);
let result = '';
let i = 0;
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;
}
},
decode: (str: string): string => {
// Handle base64uri by converting back to standard base64
const base64String = str
.replace(/-/g, '+')
.replace(/_/g, '/')
.padEnd(str.length + ((4 - (str.length % 4)) % 4), '=');
if (typeof Buffer !== 'undefined') {
// Node.js environment
return Buffer.from(base64String, 'base64').toString('utf8');
} else if (typeof atob !== 'undefined') {
// Browser environment
const binaryString = atob(base64String);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return new TextDecoder().decode(bytes);
} else {
// Fallback pure JS implementation
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let bytes: number[] = [];
let i = 0;
while (i < base64String.length) {
const encoded1 = chars.indexOf(base64String.charAt(i++));
const encoded2 = chars.indexOf(base64String.charAt(i++));
const encoded3 = chars.indexOf(base64String.charAt(i++));
const encoded4 = chars.indexOf(base64String.charAt(i++));
const bitmap = (encoded1 << 18) | (encoded2 << 12) | (encoded3 << 6) | encoded4;
bytes.push((bitmap >> 16) & 255);
if (encoded3 !== 64) bytes.push((bitmap >> 8) & 255);
if (encoded4 !== 64) bytes.push(bitmap & 255);
}
return new TextDecoder().decode(new Uint8Array(bytes));
}
}
};
/**
* handle base64 strings
*/
@@ -50,21 +129,24 @@ export let base64 = {
* encodes the string
*/
encode: (stringArg: string) => {
return plugins.jsBase64.encode(stringArg);
return universalBase64.encode(stringArg);
},
/**
* encodes a stringArg to base64 uri style
*/
encodeUri: (stringArg: string) => {
return plugins.jsBase64.encodeURI(stringArg);
return universalBase64.encode(stringArg)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
},
/**
* decodes a base64 encoded string
*/
decode: (stringArg: string) => {
return plugins.jsBase64.decode(stringArg);
return universalBase64.decode(stringArg);
},
/**