Files
P4RS3LT0NGV3/src/transformers/encoding/ascii85.js
T
Dustin Farley dc10a90851 refactor: migrate to modular tool-based architecture
- Implement tool registry system with individual tool modules
- Reorganize transformers into categorized source modules
- Remove emojiLibrary.js, consolidate into EmojiUtils and emojiData
- Fix mobile close button and tooltip functionality
- Add build system for transforms and emoji data
- Migrate from Python backend to pure JavaScript
- Add comprehensive documentation and testing
- Improve code organization and maintainability
- Ignore generated files (transforms-bundle.js, emojiData.js)
2025-12-02 20:26:32 -08:00

111 lines
4.0 KiB
JavaScript

// ascii85 transform
import BaseTransformer from '../BaseTransformer.js';
export default new BaseTransformer({
name: 'ASCII85',
priority: 290,
// Detector: ASCII85 has distinctive <~ ~> wrapper
detector: function(text) {
return text.startsWith('<~') && text.endsWith('~>');
},
func: function(text) {
// Simple ASCII85 encoding implementation
// Use TextEncoder to properly handle multi-byte UTF-8 characters
const bytes = new TextEncoder().encode(text);
let result = '<~';
let buffer = 0;
let bufferLength = 0;
for (let i = 0; i < bytes.length; i++) {
buffer = (buffer << 8) | bytes[i];
bufferLength += 8;
if (bufferLength >= 32) {
let value = buffer >>> (bufferLength - 32);
buffer &= (1 << (bufferLength - 32)) - 1;
bufferLength -= 32;
if (value === 0) {
result += 'z';
} else {
for (let j = 4; j >= 0; j--) {
const digit = (value / Math.pow(85, j)) % 85;
result += String.fromCharCode(digit + 33);
}
}
}
}
// Handle remaining bits
if (bufferLength > 0) {
buffer <<= (32 - bufferLength);
let value = buffer;
const bytes = Math.ceil(bufferLength / 8);
for (let j = 4; j >= (4 - bytes); j--) {
const digit = (value / Math.pow(85, j)) % 85;
result += String.fromCharCode(digit + 33);
}
}
return result + '~>';
},
preview: function(text) {
if (!text) return '[ascii85]';
const full = this.func(text);
return full.substring(0, 16) + (full.length > 16 ? '...' : '');
},
reverse: function(text) {
// Check if it's a valid ASCII85 string
if (!text.startsWith('<~') || !text.endsWith('~>')) {
return text;
}
// Remove delimiters and whitespace
text = text.substring(2, text.length - 2).replace(/\s+/g, '');
const bytes = [];
let i = 0;
while (i < text.length) {
// Handle 'z' special case (represents 4 zero bytes)
if (text[i] === 'z') {
bytes.push(0, 0, 0, 0);
i++;
continue;
}
// Process a group of 5 characters
if (i < text.length) {
let value = 0;
const groupSize = Math.min(5, text.length - i);
// Convert the group to a 32-bit value
for (let j = 0; j < groupSize; j++) {
value = value * 85 + (text.charCodeAt(i + j) - 33);
}
// Pad with 'u' (84) if needed for partial groups
for (let j = groupSize; j < 5; j++) {
value = value * 85 + 84;
}
// Extract bytes from the value
// groupSize chars encodes (groupSize - 1) bytes
const bytesToWrite = groupSize - 1;
for (let j = 0; j < bytesToWrite; j++) {
bytes.push((value >>> ((3 - j) * 8)) & 0xFF);
}
i += groupSize;
} else {
break;
}
}
// Use TextDecoder to properly handle UTF-8 multi-byte characters
return new TextDecoder().decode(new Uint8Array(bytes));
}
});