document.addEventListener('DOMContentLoaded', function() { // DOM Elements const inputText = document.getElementById('inputText'); const outputContainer = document.getElementById('outputContainer'); const formatBtn = document.getElementById('formatBtn'); const copyBtn = document.getElementById('copyBtn'); const downloadBtn = document.getElementById('downloadBtn'); const clearBtn = document.getElementById('clearBtn'); const languageSelect = document.getElementById('languageSelect'); const uppercaseCheck = document.getElementById('uppercaseCheck'); // Tabu words for each language (expanded lists) const tabuWords = { PT: ['o', 'a', 'os', 'as', 'um', 'uma', 'me', 'te', 'se', 'lhe', 'nos', 'de', 'do', 'da', 'em', 'no', 'na', 'por', 'para', 'com', 'ao', 'e', 'ou', 'mas', 'que', 'como', 'porque', 'quando', 'então', 'só', 'já', 'também', 'tipo', 'nosso', 'nossa', 'até', 'sem', 'sob', 'sobre', 'trás', 'ante', 'após', 'entre', 'durante', 'desde', 'perante', 'mal', 'bem', 'muito', 'pouco', 'tão', 'mais', 'menos', 'tal', 'qual', 'seu', 'sua', 'seus', 'suas', 'meu', 'minha', 'meus', 'minhas', 'teu', 'tua', 'teus', 'tuas', 'nosso', 'nossa', 'nossos', 'nossas', 'vosso', 'vossa', 'vossos', 'vossas', 'este', 'esta', 'estes', 'estas', 'isto', 'esse', 'essa', 'esses', 'essas', 'isso', 'aquele', 'aquela', 'aqueles', 'aquelas', 'aquilo', 'cada', 'todo', 'toda', 'todos', 'todas', 'outro', 'outra', 'outros', 'outras', 'mesmo', 'mesma', 'mesmos', 'mesmas', 'próprio', 'própria', 'próprios', 'próprias', 'demais', 'demais', 'certo', 'certa', 'certos', 'certas', 'diverso', 'diversa', 'diversos', 'diversas', 'algum', 'alguma', 'alguns', 'algumas', 'nenhum', 'nenhuma', 'nenhuns', 'nenhumas', 'muito', 'muita', 'muitos', 'muitas', 'pouco', 'pouca', 'poucos', 'poucas', 'tanto', 'tanta', 'tantos', 'tantas', 'quanto', 'quanta', 'quantos', 'quantas', 'varios', 'varias', 'bastante', 'suficiente', 'demais', 'demasiado', 'menos', 'mais', 'melhor', 'pior', 'maior', 'menor', 'talvez', 'acaso', 'caso', 'vez', 'vezes', 'hora', 'horas', 'dia', 'dias', 'noite', 'noites', 'manhã', 'tarde', 'tarde', 'ano', 'anos', 'mês', 'meses', 'semana', 'semanas', 'hoje', 'ontem', 'amanhã', 'antes', 'depois', 'agora', 'sempre', 'nunca', 'ainda', 'já', 'logo', 'depois', 'cedo', 'tarde', 'cedo', 'tarde', 'longe', 'perto', 'acima', 'abaixo', 'dentro', 'fora', 'atrás', 'diante', 'frente', 'meio', 'lado', 'outro', 'mesmo', 'próximo', 'distante', 'junto', 'separado', 'certo', 'duro', 'fácil', 'difícil', 'possível', 'impossível', 'necessário', 'importante', 'grande', 'pequeno', 'alto', 'baixo', 'comprido', 'curto', 'largo', 'estreito', 'grosso', 'fino', 'cheio', 'vazio', 'claro', 'escuro', 'quente', 'frio', 'seco', 'molhado', 'limpo', 'sujo', 'novo', 'velho', 'antigo', 'moderno', 'bonito', 'feio', 'bom', 'mau', 'melhor', 'pior', 'caro', 'barato', 'rápido', 'lento', 'certo', 'errado', 'verdadeiro', 'falso', 'real', 'fictício', 'verdade', 'mentira', 'verdadeiro', 'falso', 'certo', 'incerto', 'seguro', 'perigoso', 'tranquilo', 'agitado', 'calmo', 'nervoso', 'alegre', 'triste', 'feliz', 'infeliz', 'contente', 'descontente', 'satisfeito', 'insatisfeito', 'orgulhoso', 'envergonhado', 'surpreso', 'indiferente', 'interessado', 'entediado', 'cansado', 'descansado', 'faminto', 'satisfeito', 'sede', 'satisfeito', 'com fome', 'com sede', 'com sono', 'acordado', 'dormindo', 'vivo', 'morto', 'nascendo', 'morrendo', 'crescendo', 'diminuindo', 'aumentando', 'diminuindo', 'subindo', 'descendo', 'entrando', 'saindo', 'chegando', 'partindo', 'indo', 'vindo', 'ficando', 'saindo', 'voltando', 'retornando', 'continuando', 'parando', 'começando', 'terminando', 'iniciando', 'finalizando', 'abrindo', 'fechando', 'ligando', 'desligando', 'acendendo', 'apagando', 'acendendo', 'apagando', 'aquecendo', 'esfriando', 'secando', 'molhando', 'limpando', 'sujando', 'enchendo', 'esvaziando', 'cheio', 'vazio', 'claro', 'escuro', 'quente', 'frio', 'seco', 'molhado', 'limpo', 'sujo', 'novo', 'velho', 'antigo', 'moderno', 'bonito', 'feio', 'bom', 'mau', 'melhor', 'pior', 'caro', 'barato', 'rápido', 'lento', 'certo', 'errado', 'verdadeiro', 'falso', 'real', 'fictício', 'verdade', 'mentira', 'verdadeiro', 'falso', 'certo', 'incerto', 'seguro', 'perigoso', 'tranquilo', 'agitado', 'calmo', 'nervoso', 'alegre', 'triste', 'feliz', 'infeliz', 'contente', 'descontente', 'satisfeito', 'insatisfeito', 'orgulhoso', 'envergonhado', 'surpreso', 'indiferente', 'interessado', 'entediado', 'cansado', 'descansado', 'faminto', 'satisfeito', 'sede', 'satisfeito', 'com fome', 'com sede', 'com sono', 'acordado', 'dormindo', 'vivo', 'morto', 'nascendo', 'morrendo', 'crescendo', 'diminuindo', 'aumentando', 'diminuindo', 'subindo', 'descendo', 'entrando', 'saindo', 'chegando', 'partindo', 'indo', 'vindo', 'ficando', 'saindo', 'voltando', 'retornando', 'continuando', 'parando', 'começando', 'terminando', 'iniciando', 'finalizando', 'abrindo', 'fechando', 'ligando', 'desligando', 'acendendo', 'apagando', 'acendendo', 'apagando', 'aquecendo', 'esfriando', 'secando', 'molhando', 'limpando', 'sujando', 'enchendo', 'esvaziando'], EN: ['a', 'an', 'the', 'of', 'in', 'on', 'at', 'to', 'for', 'with', 'from', 'by', 'and', 'or', 'but', 'that', 'me', 'you', 'it', 'he', 'she', 'we', 'they', 'us', 'them', 'his', 'her', 'its', 'our', 'their', 'myself', 'yourself', 'himself', 'herself', 'itself', 'ourselves', 'yourselves', 'themselves', 'this', 'that', 'these', 'those', 'some', 'any', 'many', 'much', 'few', 'little', 'more', 'most', 'other', 'another', 'such', 'same', 'different', 'own', 'main', 'only', 'very', 'quite', 'rather', 'fairly', 'pretty', 'really', 'extremely', 'incredibly', 'absolutely', 'totally', 'completely', 'entirely', 'fully', 'wholly', 'altogether', 'exceedingly', 'intensely', 'highly', 'greatly', 'seriously', 'badly', 'terribly', 'awfully', 'horribly', 'dreadfully', 'frightfully', 'terribly', 'awfully', 'horribly', 'dreadfully', 'frightfully', 'badly', 'seriously', 'greatly', 'highly', 'intensely', 'exceedingly', 'altogether', 'wholly', 'fully', 'entirely', 'completely', 'totally', 'absolutely', 'incredibly', 'extremely', 'really', 'pretty', 'fairly', 'rather', 'quite', 'very', 'only', 'main', 'own', 'different', 'same', 'such', 'another', 'other', 'most', 'more', 'little', 'few', 'much', 'many', 'any', 'some', 'those', 'these', 'that', 'this', 'themselves', 'yourselves', 'ourselves', 'itself', 'herself', 'himself', 'yourself', 'myself', 'their', 'our', 'its', 'her', 'his', 'them', 'us', 'they', 'we', 'she', 'he', 'it', 'you', 'me', 'but', 'or', 'and', 'by', 'from', 'with', 'for', 'to', 'at', 'on', 'in', 'of', 'the', 'an', 'a'], ES: ['de', 'en', 'a', 'por', 'para', 'con', 'y', 'que', 'el', 'la', 'los', 'las', 'un', 'una', 'unos', 'unas', 'me', 'te', 'se', 'nos', 'os', 'le', 'les', 'lo', 'la', 'los', 'las', 'mi', 'tu', 'su', 'nuestro', 'vuestra', 'este', 'ese', 'aquel', 'esta', 'esa', 'aquella', 'estos', 'esos', 'aquellos', 'estas', 'esas', 'aquellas', 'esto', 'eso', 'aquello', 'cada', 'todo', 'toda', 'todos', 'todas', 'otro', 'otra', 'otros', 'otras', 'mismo', 'misma', 'mismos', 'mismas', 'próximo', 'próxima', 'próximos', 'próximas', 'distante', 'distantes', 'junto', 'juntos', 'junta', 'juntas', 'separado', 'separados', 'separada', 'separadas', 'cierto', 'cierta', 'ciertos', 'ciertas', 'duro', 'duros', 'dura', 'duras', 'fácil', 'fáciles', 'difícil', 'difíciles', 'posible', 'posibles', 'imposible', 'imposibles', 'necesario', 'necesarios', 'necesaria', 'necesarias', 'importante', 'importantes', 'grande', 'grandes', 'pequeño', 'pequeña', 'pequeños', 'pequeñas', 'alto', 'altos', 'alta', 'altas', 'bajo', 'bajos', 'baja', 'bajas', 'comprido', 'compridos', 'comprida', 'compridas', 'largo', 'largos', 'larga', 'largas', 'corto', 'cortos', 'corta', 'cortas', 'estrecho', 'estrechos', 'estrecha', 'estrechas', 'grosso', 'grueso', 'grosa', 'gruesa', 'grosos', 'gruesos', 'finos', 'fino', 'fina', 'finas', 'cheio', 'lleno', 'cheios', 'llenos', 'cheia', 'llena', 'cheias', 'llenas', 'vazio', 'vacío', 'vazios', 'vacíos', 'vazia', 'vacía', 'vazias', 'vacías', 'claro', 'clara', 'claros', 'claras', 'escuro', 'oscuro', 'escura', 'oscura', 'escuros', 'oscuros', 'escuras', 'oscuras', 'quente', 'caliente', 'quentes', 'calientes', 'frio', 'frío', 'fria', 'fría', 'frios', 'fríos', 'frias', 'frías', 'seco', 'secos', 'seca', 'secas', 'molhado', 'mojado', 'molhados', 'mojados', 'molhada', 'mojada', 'molhadas', 'mojadas', 'limpo', 'limpios', 'limpia', 'limpias', 'sujo', 'sucio', 'sujos', 'sucios', 'suja', 'sucia', 'sujas', 'sucias', 'novo', 'nuevo', 'nuevos', 'nueva', 'nuevas', 'velho', 'viejo', 'viejos', 'vieja', 'viejas', 'antigo', 'antiguo', 'antiguos', 'antigua', 'antiguas', 'moderno', 'modernos', 'moderna', 'modernas', 'bonito', 'bonitos', 'bonita', 'bonitas', 'feio', 'feo', 'feos', 'fea', 'feas', 'bom', 'bueno', 'buenos', 'buena', 'buenas', 'mau', 'malo', 'malos', 'mala', 'malas', 'melhor', 'mejor', 'melhores', 'mejores', 'pior', 'peor', 'piores', 'peores', 'caro', 'caros', 'cara', 'caras', 'barato', 'baratos', 'barata', 'baratas', 'rápido', 'rápidos', 'rápida', 'rápidas', 'lento', 'lentos', 'lenta', 'lentas', 'certo', 'cierto', 'ciertos', 'cierta', 'ciertas', 'errado', 'equivocado', 'equivocados', 'equivocada', 'equivocadas', 'verdadeiro', 'verdadero', 'verdaderos', 'verdadera', 'verdaderas', 'falso', 'falsos', 'falsa', 'falsas', 'real', 'reales', 'fictício', 'ficticio', 'ficticios', 'ficticia', 'ficticias', 'verdade', 'verdad', 'mentira', 'mentiras', 'seguro', 'seguros', 'segura', 'seguras', 'perigoso', 'peligroso', 'peligrosos', 'peligrosa', 'peligrosas', 'tranquilo', 'tranquilos', 'tranquila', 'tranquilas', 'agitado', 'agitados', 'agitada', 'agitadas', 'calmo', 'calmos', 'calma', 'calmas', 'nervoso', 'nerviosos', 'nerviosa', 'nerviosas', 'alegre', 'alegres', 'triste', 'tristes', 'feliz', 'felices', 'infeliz', 'infelices', 'contente', 'contentos', 'contenta', 'contentas', 'descontente', 'descontentos', 'descontenta', 'descontentas', 'satisfeito', 'satisfecho', 'satisfechos', 'satisfecha', 'satisfechas', 'insatisfeito', 'insatisfecho', 'insatisfechos', 'insatisfecha', 'insatisfechas', 'orgulhoso', 'orgulloso', 'orgullosos', 'orgullosa', 'orgullosas', 'envergonhado', 'avergonzado', 'avergonzados', 'avergonzada', 'avergonzadas', 'surpreso', 'sorprendido', 'sorprendidos', 'sorprendida', 'sorprendidas', 'indiferente', 'indiferentes', 'interessado', 'interesado', 'interesados', 'interesada', 'interesadas', 'entediado', 'aburrido', 'aburridos', 'aburrida', 'aburridas', 'cansado', 'cansados', 'cansada', 'cansadas', 'descansado', 'descansados', 'descansada', 'descansadas', 'faminto', 'hambriento', 'hambrientos', 'hambrienta', 'hambrientas', 'satisfeito', 'satisfecho', 'satisfechos', 'satisfecha', 'satisfechas', 'sede', 'sed', 'satisfeito', 'satisfecho', 'satisfechos', 'satisfecha', 'satisfechas', 'com fome', 'con hambre', 'com sede', 'con sed', 'com sono', 'con sueño', 'acordado', 'despierto', 'despiertos', 'despierta', 'despiertas', 'dormindo', 'durmiendo', 'vivo', 'vivos', 'viva', 'vivas', 'morto', 'muerto', 'muertos', 'muerta', 'muertas', 'nascendo', 'naciendo', 'morrendo', 'muriendo', 'crescendo', 'creciendo', 'diminuindo', 'disminuyendo', 'aumentando', 'aumentando', 'subindo', 'subiendo', 'descendo', 'bajando', 'entrando', 'entrando', 'saindo', 'saliendo', 'chegando', 'llegando', 'partindo', 'partiendo', 'indo', 'yendo', 'vindo', 'viniendo', 'ficando', 'quedando', 'saindo', 'saliendo', 'voltando', 'volviendo', 'retornando', 'retornando', 'continuando', 'continuando', 'parando', 'parando', 'começando', 'comenzando', 'terminando', 'terminando', 'iniciando', 'iniciando', 'finalizando', 'finalizando', 'abrindo', 'abriendo', 'fechando', 'cerrando', 'ligando', 'encendiendo', 'desligando', 'apagando', 'acendendo', 'encendiendo', 'apagando', 'apagando', 'aquecendo', 'calentando', 'esfriando', 'enfriando', 'secando', 'secando', 'molhando', 'mojando', 'limpando', 'limpiando', 'sujando', 'ensuciando', 'enchendo', 'llenando', 'esvaziando', 'vaciando'] }; // Connectives - MUST always start new blocks, never end them const connectives = { PT: ['E', 'É', 'QUE'], EN: ['AND', 'IS', 'THAT'], ES: ['Y', 'ES', 'QUE'] }; // Negation words - must be isolated in short blocks const negationWords = { PT: ['NÃO', 'NUNCA'], EN: ['NOT', 'NEVER'], ES: ['NO', 'NUNCA'] }; // Format text function function formatText() { const text = inputText.value.trim(); if (!text) { outputContainer.innerHTML = '
Please enter some text to format
'; return; } const language = languageSelect.value; const uppercaseMode = uppercaseCheck.checked; try { const formatted = processText(text, language, uppercaseMode); outputContainer.innerHTML = `${formatted}`;
} catch (error) {
outputContainer.innerHTML = `Error formatting text: ${error.message}
`; } } // Text processing function function processText(text, language, uppercaseMode) { // PRE-PROCESSING & NORMALIZATION // Clean whitespace: Remove duplicate spaces and normalize line breaks let normalized = text.replace(/\s+/g, ' ').trim(); // Convert commas to "!" (attached to preceding word without space) normalized = normalized.replace(/,/g, '!'); // Normalize exclamation marks: Convert all "!!" or "!!!" sequences to single "!" normalized = normalized.replace(/!+/g, '!'); // Preserve all original punctuation exactly as positioned in source text // (already handled by above steps) // DETERMINISTIC SPLITTING (STRONG RULES - HIGHEST PRIORITY) // Split immediately after every "!", "?", or "." (punctuation stays with preceding word) const sentences = normalized.split(/([.!?]+)/).filter(s => s.trim() !== ''); let blocks = []; for (let i = 0; i < sentences.length; i += 2) { const sentence = sentences[i]; const punctuation = sentences[i + 1] || ''; // Process each sentence const sentenceBlocks = processSentence(sentence + punctuation, language); blocks = blocks.concat(sentenceBlocks); } // Apply heuristic optimizations blocks = applyHeuristics(blocks, language); // Apply uppercase if needed if (uppercaseMode) { blocks = blocks.map(block => block.toUpperCase()); } return blocks.join('\n'); } // Process individual sentence with zero-error tolerance function processSentence(sentence, language) { const words = sentence.trim().split(/\s+/); const blocks = []; let currentBlock = ''; let i = 0; while (i < words.length) { const word = words[i]; const cleanWord = word.replace(/[.!?!,]/g, ''); // STRONG RULE: Connectives must start new blocks, never end them if (isConnective(cleanWord, language)) { if (currentBlock) { blocks.push(resolveBlockEnding(currentBlock.trim(), language)); } currentBlock = word; i++; continue; } // Handle negation - isolate in short blocks if (isNegation(cleanWord, language)) { if (currentBlock) { blocks.push(resolveBlockEnding(currentBlock.trim(), language)); } blocks.push(word); currentBlock = ''; i++; continue; } // Calculate character count (excluding spaces and punctuation) const testBlock = currentBlock ? `${currentBlock} ${word}` : word; const charCount = testBlock.replace(/\s/g, '').replace(/[.!?!,]/g, '').length; // EXCEPTION: Single word blocks can exceed 11 characters if (!currentBlock && charCount > 11) { blocks.push(word); currentBlock = ''; i++; continue; } // Check if adding word would exceed 11 character limit if (currentBlock && charCount > 11) { // Resolve current block with anti-weakening principle const resolvedBlock = resolveBlockEnding(currentBlock.trim(), language); if (resolvedBlock) { blocks.push(resolvedBlock); } currentBlock = word; } else { currentBlock = testBlock; } i++; } // Handle remaining block with anti-weakening principle if (currentBlock) { const resolvedBlock = resolveBlockEnding(currentBlock.trim(), language); if (resolvedBlock) { blocks.push(resolvedBlock); } } return blocks; } // Resolve block ending - ZERO ERROR TOLERANCE for tabu endings function resolveBlockEnding(block, language) { if (!block) return ''; const words = block.split(/\s+/); if (words.length === 0) return ''; const lastWord = words[words.length - 1].replace(/[.!?!,]/g, ''); const lastWordClean = lastWord; // STRONG RULE: Never end with tabu words if (isTabu(lastWordClean, language)) { if (words.length === 1) { // Single word is tabu - this shouldn't happen, but return as-is return block; } // Move tabu word to next block const newBlock = words.slice(0, -1).join(' '); return newBlock; } // STRONG RULE: Never end with 2-3 character words if (lastWordClean.length >= 2 && lastWordClean.length <= 3) { if (words.length === 1) { return block; // Single word exception } // Move short word to next block const newBlock = words.slice(0, -1).join(' '); return newBlock; } return block; } // Check if word is a connective function isConnective(word, language) { if (!word) return false; const upperWord = word.toUpperCase(); return connectives[language].includes(upperWord); } // Check if word is tabu function isTabu(word, language) { if (!word) return false; return tabuWords[language].includes(word.toLowerCase()); } // Check if word is a negation function isNegation(word, language) { if (!word) return false; const upperWord = word.toUpperCase(); return negationWords[language].includes(upperWord); } // Apply heuristic optimizations AFTER strong rules are satisfied function applyHeuristics(blocks, language) { const optimizedBlocks = []; for (let i = 0; i < blocks.length; i++) { let block = blocks[i]; const cleanBlock = block.replace(/[.!?!,]/g, '').toUpperCase(); // Price formatting: Isolate "POR/AND/YFormatted text will appear here
'; inputText.focus(); } // Event Listeners formatBtn.addEventListener('click', formatText); copyBtn.addEventListener('click', copyToClipboard); downloadBtn.addEventListener('click', downloadText); clearBtn.addEventListener('click', clearInput); // Format on Ctrl+Enter inputText.addEventListener('keydown', (e) => { if (e.ctrlKey && e.key === 'Enter') { formatText(); } }); // Initialize Feather icons feather.replace(); });