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)
This commit is contained in:
Dustin Farley
2025-12-02 20:26:32 -08:00
parent 105084437a
commit dc10a90851
146 changed files with 12712 additions and 8171 deletions
+39
View File
@@ -0,0 +1,39 @@
// elder-futhark transform
import BaseTransformer from '../BaseTransformer.js';
export default new BaseTransformer({
name: 'Elder Futhark',
priority: 100,
map: {
'a': 'ᚨ', 'b': 'ᛒ', 'c': 'ᚳ', 'd': 'ᛞ', 'e': 'ᛖ', 'f': 'ᚠ', 'g': 'ᚷ', 'h': 'ᚺ', 'i': 'ᛁ',
'j': 'ᛃ', 'k': 'ᚲ', 'l': 'ᛚ', 'm': 'ᛗ', 'n': 'ᚾ', 'o': 'ᛟ', 'p': 'ᛈ', 'q': 'ᚲᚹ', 'r': 'ᚱ',
's': 'ᛋ', 't': 'ᛏ', 'u': 'ᚢ', 'v': 'ᚡ', 'w': 'ᚹ', 'x': 'ᚳᛋ', 'y': 'ᚤ', 'z': 'ᛉ'
},
// Create reverse map for decoding
reverseMap: function() {
const revMap = {};
for (const [key, value] of Object.entries(this.map)) {
revMap[value] = key;
}
return revMap;
},
func: function(text) {
return [...text.toLowerCase()].map(c => this.map[c] || c).join('');
},
preview: function(text) {
if (!text) return '[runes]';
return this.func(text.slice(0, 5));
},
reverse: function(text) {
const revMap = this.reverseMap();
return [...text].map(c => revMap[c] || c).join('');
},
// Detector: Check for Elder Futhark runes
detector: function(text) {
// Elder Futhark runes (U+16A0-U+16F8)
// Check for the unique runes used in this transform
return /[ᚨᚳᚲᛟᚤᛒᛞᛖᚠᚷᚺᛁᛃᛚᛗᚾᛈᛩᚱᛋᛏᚢᚡᚹᛉ]/.test(text);
}
});
+32
View File
@@ -0,0 +1,32 @@
// hieroglyphics transform
import BaseTransformer from '../BaseTransformer.js';
export default new BaseTransformer({
name: 'Hieroglyphics',
priority: 70,
map: {
'a': '𓃭', 'b': '𓃮', 'c': '𓃯', 'd': '𓃰', 'e': '𓃱', 'f': '𓃲', 'g': '𓃳', 'h': '𓃴', 'i': '𓃵',
'j': '𓃶', 'k': '𓃷', 'l': '𓃸', 'm': '𓃹', 'n': '𓃺', 'o': '𓃻', 'p': '𓃼', 'q': '𓃽', 'r': '𓃾',
's': '𓃿', 't': '𓄀', 'u': '𓄁', 'v': '𓄂', 'w': '𓄃', 'x': '𓄄', 'y': '𓄅', 'z': '𓄆',
'A': '𓄇', 'B': '𓄈', 'C': '𓄉', 'D': '𓄊', 'E': '𓄋', 'F': '𓄌', 'G': '𓄍', 'H': '𓄎', 'I': '𓄏',
'J': '𓄐', 'K': '𓄑', 'L': '𓄒', 'M': '𓄓', 'N': '𓄔', 'O': '𓄕', 'P': '𓄖', 'Q': '𓄗', 'R': '𓄘',
'S': '𓄙', 'T': '𓄚', 'U': '𓄛', 'V': '𓄜', 'W': '𓄝', 'X': '𓄞', 'Y': '𓄟', 'Z': '𓄠'
},
func: function(text) {
return [...text.toLowerCase()].map(c => this.map[c] || c).join('');
},
reverse: function(text) {
const revMap = {};
for (const [key, value] of Object.entries(this.map)) {
revMap[value] = key;
}
return [...text].map(c => revMap[c] || c).join('');
},
// Detector: Check for Egyptian hieroglyphic characters
detector: function(text) {
// Egyptian hieroglyphs - check for presence of any hieroglyphic character
return /[\u{13000}-\u{1342F}]/u.test(text);
}
});
+32
View File
@@ -0,0 +1,32 @@
// ogham transform
import BaseTransformer from '../BaseTransformer.js';
export default new BaseTransformer({
name: 'Ogham (Celtic)',
priority: 70,
map: {
'a': 'ᚐ', 'b': 'ᚁ', 'c': 'ᚉ', 'd': 'ᚇ', 'e': 'ᚓ', 'f': 'ᚃ', 'g': 'ᚌ', 'h': 'ᚆ', 'i': 'ᚔ',
'j': 'ᚈ', 'k': 'ᚊ', 'l': 'ᚂ', 'm': 'ᚋ', 'n': 'ᚅ', 'o': 'ᚑ', 'p': 'ᚚ', 'q': 'ᚊ', 'r': 'ᚏ',
's': 'ᚄ', 't': 'ᚈ', 'u': 'ᚒ', 'v': 'ᚃ', 'w': 'ᚃ', 'x': 'ᚊ', 'y': 'ᚔ', 'z': 'ᚎ',
'A': 'ᚐ', 'B': 'ᚁ', 'C': 'ᚉ', 'D': 'ᚇ', 'E': 'ᚓ', 'F': 'ᚃ', 'G': 'ᚌ', 'H': 'ᚆ', 'I': 'ᚔ',
'J': 'ᚈ', 'K': 'ᚊ', 'L': 'ᚂ', 'M': 'ᚋ', 'N': 'ᚅ', 'O': 'ᚑ', 'P': 'ᚚ', 'Q': 'ᚊ', 'R': 'ᚏ',
'S': 'ᚄ', 'T': 'ᚈ', 'U': 'ᚒ', 'V': 'ᚃ', 'W': 'ᚃ', 'X': 'ᚊ', 'Y': 'ᚔ', 'Z': 'ᚎ'
},
func: function(text) {
return [...text.toLowerCase()].map(c => this.map[c] || c).join('');
},
reverse: function(text) {
const revMap = {};
for (const [key, value] of Object.entries(this.map)) {
revMap[value] = key;
}
return [...text].map(c => revMap[c] || c).join('');
},
// Detector: Check for Ogham characters
detector: function(text) {
// Ogham alphabet (U+1680-U+169C)
return /[ᚐᚁᚉᚇᚓᚃᚌᚆᚔᚈᚊᚂᚋᚅᚑᚚᚏᚄᚒᚎ]/.test(text);
}
});
@@ -0,0 +1,44 @@
// roman-numerals transform
import BaseTransformer from '../BaseTransformer.js';
export default new BaseTransformer({
name: 'Roman Numerals',
priority: 70,
numerals: [
['M',1000],['CM',900],['D',500],['CD',400],
['C',100],['XC',90],['L',50],['XL',40],
['X',10],['IX',9],['V',5],['IV',4],['I',1]
],
func: function(text) {
return text.replace(/\b\d+\b/g, m => {
let num = parseInt(m,10);
if (num <= 0 || num > 3999 || isNaN(num)) return m;
let out = '';
for (const [sym,val] of this.numerals) {
while (num >= val) { out += sym; num -= val; }
}
return out;
});
},
preview: function(text) {
return this.func(text || '2024');
},
reverse: function(text) {
// Greedy parse roman numerals to digits
const map = {I:1,V:5,X:10,L:50,C:100,D:500,M:1000};
const tokenize = s => s.match(/[IVXLCDM]+|[^IVXLCDM]+/gi) || [s];
return tokenize(text).map(tok => {
if (!/^[IVXLCDM]+$/i.test(tok)) return tok;
const s = tok.toUpperCase();
let total = 0;
for (let i=0;i<s.length;i++) {
const v = map[s[i]] || 0;
const n = map[s[i+1]] || 0;
total += v < n ? -v : v;
}
return String(total);
}).join('');
}
});