const inputText = document.getElementById('input-text'); const bubbleContainer = document.getElementById('bubble-container'); const replaceSpacesButton = document.getElementById('replace-spaces-button'); const replaceUnderscoreButton = document.getElementById('replace-underscore-button'); const revertUnderscoreButton = document.getElementById('revert-underscore-button'); const replaceLineBreaksButton = document.getElementById('replace-linebreaks-button'); const replaceCommasButton = document.getElementById('replace-commas-button'); const removeDuplicatesButton = document.getElementById('remove-duplicates-button'); const revertSpacesButton = document.getElementById('revert-spaces-button'); const copyButton = document.getElementById('copy-button'); const undoButton = document.getElementById('undo-button'); const redoButton = document.getElementById('redo-button'); const deleteModeButton = document.getElementById('delete-mode-button'); const emphasisModeButton = document.getElementById('emphasis-mode-button'); const mitigateModeButton = document.getElementById('mitigate-mode-button'); const literalParenthesisButton = document.getElementById('literal-parenthesis-button'); const fictionalParenthesisButton = document.getElementById('fictional-parenthesis-button'); const bubbleColors = {}; let history = []; let historyIndex = -1; let deleteModeEnabled = false; let emphasisModeEnabled = false; let mitigateModeEnabled = false; inputText.addEventListener('input', handleTextChange); replaceSpacesButton.addEventListener('click', replaceSpaces); replaceUnderscoreButton.addEventListener('click', replaceUnderscores); revertUnderscoreButton.addEventListener('click', revertUnderscores); replaceLineBreaksButton.addEventListener('click', replaceLineBreaks); replaceCommasButton.addEventListener('click', replaceCommas); removeDuplicatesButton.addEventListener('click', removeDuplicates); revertSpacesButton.addEventListener('click', revertSpaces); copyButton.addEventListener('click', copyToClipboard); undoButton.addEventListener('click', undoChanges); redoButton.addEventListener('click', redoChanges); deleteModeButton.addEventListener('click', toggleDeleteMode); emphasisModeButton.addEventListener('click', toggleEmphasisMode); mitigateModeButton.addEventListener('click', toggleMitigateMode); literalParenthesisButton.addEventListener('click', literalParenthesis); fictionalParenthesisButton.addEventListener('click', fictionalParenthesis); const sortable = new Sortable(bubbleContainer, { animation: 250, ghostClass: 'ghost', onEnd: handleBubbleChange, disabled: deleteModeEnabled || emphasisModeEnabled || mitigateModeEnabled }); function handleTextChange() { const text = inputText.value; if (history.length === 0) { history.push(''); historyIndex++; } if (text !== history[historyIndex]) { if (historyIndex < history.length - 1) { history.splice(historyIndex + 1); } history.push(text); historyIndex++; updateBubbles(); updateButtonStates(); } } function handleBubbleChange() { const conceptList = Array.from(bubbleContainer.getElementsByClassName('bubble')).map(bubble => bubble.textContent.trim()); inputText.value = conceptList.join(', '); handleTextChange(); } function updateBubbles() { bubbleContainer.innerHTML = ''; const text = inputText.value.trim(); if (text === '') return; const concepts = text.split(', '); concepts.forEach(concept => { const bubble = createBubble(concept); bubbleContainer.appendChild(bubble); }); } function createBubble(text) { const bubble = document.createElement('div'); bubble.classList.add('bubble'); if (!bubbleColors.hasOwnProperty(text)) { bubbleColors[text] = getRandomColor(); } bubble.style.backgroundColor = bubbleColors[text]; const bubbleText = document.createElement('span'); bubbleText.classList.add('bubble-text'); bubbleText.innerText = text; bubble.appendChild(bubbleText); if (deleteModeEnabled) { bubble.classList.add('delete-mode'); bubble.addEventListener('click', deleteBubble); } if (emphasisModeEnabled) { bubble.classList.add('emphasis-mode'); bubble.addEventListener('click', emphasizeBubble); } if (mitigateModeEnabled) { bubble.classList.add('mitigate-mode'); bubble.addEventListener('click', mitigateBubble); } return bubble; } function getRandomColor() { const h = Math.floor(Math.random() * 360); const s = Math.floor(Math.random() * 30) + 50; const l = Math.floor(Math.random() * 40) + 30; return `hsl(${h}, ${s}%, ${l}%)`; } function updateButtonStates() { undoButton.disabled = historyIndex === 0; redoButton.disabled = historyIndex === history.length - 1; } function replaceSpaces() { const text = inputText.value; const replacedText = text.replace(/ /g, ', '); inputText.value = replacedText; handleTextChange(); } function revertSpaces() { const text = inputText.value; const replacedText = text.replace(/, /g, ' '); inputText.value = replacedText; handleTextChange(); } function replaceUnderscores() { const text = inputText.value; const replacedText = text.replace(/_/g, ' '); inputText.value = replacedText; handleTextChange(); } function revertUnderscores() { const text = inputText.value; const replacedText = text.replace(/([^,]) /g, '$1_'); inputText.value = replacedText; handleTextChange(); } function replaceLineBreaks() { const text = inputText.value; const replacedText = text.replace(/\n/g, ', '); inputText.value = replacedText; handleTextChange(); } function replaceCommas() { const text = inputText.value; const step1 = text.replace(/,,/g, ','); const step2 = step1.replace(/, ,/g, ', '); const step3 = step2.trimRight(); const step4 = step3.replace(/,$/, ''); const step5 = step4.replace(/^,/, ''); const step6 = step5.replace(/, /g, ', '); const replacedText = step6.replace(/^ /, ''); inputText.value = replacedText; handleTextChange(); } function removeDuplicates() { const text = inputText.value; const concepts = text.split(', '); const uniqueConcepts = [...new Set(concepts)]; inputText.value = uniqueConcepts.join(', '); handleTextChange(); } function copyToClipboard() { inputText.select(); inputText.setSelectionRange(0, 99999); document.execCommand('copy'); } function literalParenthesis() { const inputText = document.getElementById('input-text'); const text = inputText.value; // Reemplazar ' (' que no estén precedidos por una ',' y el paréntesis de cierre siguiente más cercano let replacedText = text.replace(/([^,]) \((.*?)\)/g, '$1 \\($2\\)'); // Reemplazar '_(' y el paréntesis de cierre siguiente más cercano replacedText = replacedText.replace(/_\((.*?)\)/g, '_\\($1\\)'); inputText.value = replacedText; handleTextChange(); } function fictionalParenthesis() { const inputText = document.getElementById('input-text'); const text = inputText.value; // Reemplazar '\(' por '(' let replacedText = text.replace(/\\\(/g, '('); // Reemplazar '\)' por ')' replacedText = replacedText.replace(/\\\)/g, ')'); inputText.value = replacedText; handleTextChange(); } document.getElementById('download-text-file-button').addEventListener('click', showFilenameInput); function showFilenameInput() { const inputText = document.getElementById('input-text').value; const currentDate = new Date(); const year = currentDate.getFullYear(); const month = String(currentDate.getMonth() + 1).padStart(2, '0'); const day = String(currentDate.getDate()).padStart(2, '0'); const hours = String(currentDate.getHours()).padStart(2, '0'); const minutes = String(currentDate.getMinutes()).padStart(2, '0'); const formattedDate = `${year}-${month}-${day}_${hours}-${minutes}`; const defaultFileName = `Bubble Prompter_${formattedDate}.txt`; let container = document.getElementById('custom-filename-container'); if (!container) { container = document.createElement('div'); container.id = 'custom-filename-container'; document.body.appendChild(container); const input = document.createElement('input'); input.type = 'text'; input.id = 'custom-filename'; container.appendChild(input); const confirmButton = document.createElement('button'); confirmButton.innerText = '✅'; confirmButton.classList.add('confirm-button'); // Agregar clase confirmButton.addEventListener('click', downloadTextFile); container.appendChild(confirmButton); const cancelButton = document.createElement('button'); cancelButton.innerText = '❌'; cancelButton.classList.add('cancel-button'); // Agregar clase cancelButton.addEventListener('click', hideFilenameInput); container.appendChild(cancelButton); document.addEventListener('click', function(event) { if (!container.contains(event.target) && event.target !== document.getElementById('download-text-file-button')) { hideFilenameInput(); } }); input.addEventListener('keydown', function(event) { if (event.key === 'Enter') { downloadTextFile(); } }); } container.style.display = 'block'; container.style.top = `${document.getElementById('download-text-file-button').offsetTop + document.getElementById('download-text-file-button').offsetHeight}px`; container.style.left = `${document.getElementById('download-text-file-button').offsetLeft}px`; const input = document.getElementById('custom-filename'); input.value = defaultFileName; input.select(); input.focus(); } function hideFilenameInput() { const container = document.getElementById('custom-filename-container'); if (container) { container.style.display = 'none'; } } function downloadTextFile() { const inputText = document.getElementById('input-text').value; let customFilename = document.getElementById('custom-filename').value.trim(); // Añadir .txt si no está presente if (!customFilename.endsWith('.txt')) { customFilename += '.txt'; } const fileName = customFilename ? customFilename : 'Bubble Prompter.txt'; const blob = new Blob([inputText], { type: 'text/plain' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); hideFilenameInput(); } document.getElementById('load-text-file-button').addEventListener('click', loadTextFile); function loadTextFile() { const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = '.txt'; fileInput.addEventListener('change', (event) => { const file = event.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (e) => { const inputText = document.getElementById('input-text'); let currentText = inputText.value; // Añadir una coma y un espacio si el campo de texto no está vacío if (currentText) { currentText += ', '; } // Añadir el contenido del archivo inputText.value = currentText + e.target.result; handleTextChange(); }; reader.readAsText(file); } }); // Simular un clic en el input de archivo para abrir el cuadro de diálogo de archivo fileInput.click(); } document.addEventListener('DOMContentLoaded', function() { const inputText = document.getElementById('input-text'); // Evitar comportamiento por defecto de arrastrar y soltar ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { inputText.addEventListener(eventName, preventDefaults, false); document.body.addEventListener(eventName, preventDefaults, false); }); // Añadir clases para los estilos de arrastrar y soltar ['dragenter', 'dragover'].forEach(eventName => { inputText.addEventListener(eventName, () => inputText.classList.add('highlight'), false); }); ['dragleave', 'drop'].forEach(eventName => { inputText.addEventListener(eventName, () => inputText.classList.remove('highlight'), false); }); // Manejar el evento de soltar inputText.addEventListener('drop', handleDrop, false); function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } function handleDrop(e) { const dt = e.dataTransfer; const files = dt.files; if (files.length) { const file = files[0]; if (file.type === "text/plain") { const reader = new FileReader(); reader.onload = (e) => { let currentText = inputText.value; // Añadir una coma y un espacio si el campo de texto no está vacío if (currentText) { currentText += ', '; } // Añadir el contenido del archivo inputText.value = currentText + e.target.result; handleTextChange(); }; reader.readAsText(file); } else { alert("Please drop a valid .txt file."); } } } }); function undoChanges() { if (historyIndex > 0) { historyIndex--; inputText.value = history[historyIndex]; updateBubbles(); updateButtonStates(); } } function redoChanges() { if (historyIndex < history.length - 1) { historyIndex++; inputText.value = history[historyIndex]; updateBubbles(); updateButtonStates(); } } function toggleDeleteMode() { deleteModeEnabled = !deleteModeEnabled; deleteModeButton.classList.toggle('active'); if (deleteModeEnabled) { emphasisModeEnabled = false; emphasisModeButton.classList.remove('active'); mitigateModeEnabled = false; mitigateModeButton.classList.remove('active'); } sortable.option('disabled', deleteModeEnabled); bubbleContainer.classList.toggle('delete-mode-container'); const bubbles = bubbleContainer.getElementsByClassName('bubble'); for (let i = 0; i < bubbles.length; i++) { const bubble = bubbles[i]; bubble.classList.remove('emphasis-mode'); bubble.classList.remove('mitigate-mode'); if (deleteModeEnabled) { bubble.classList.add('delete-mode'); bubble.removeEventListener('click', emphasizeBubble); bubble.removeEventListener('click', mitigateBubble); bubble.addEventListener('click', deleteBubble); } else { bubble.classList.remove('delete-mode'); bubble.removeEventListener('click', deleteBubble); } } } function toggleEmphasisMode() { emphasisModeEnabled = !emphasisModeEnabled; emphasisModeButton.classList.toggle('active'); if (emphasisModeEnabled) { deleteModeEnabled = false; deleteModeButton.classList.remove('active'); mitigateModeEnabled = false; mitigateModeButton.classList.remove('active'); } sortable.option('disabled', emphasisModeEnabled); bubbleContainer.classList.toggle('emphasis-mode-container'); const bubbles = bubbleContainer.getElementsByClassName('bubble'); for (let i = 0; i < bubbles.length; i++) { const bubble = bubbles[i]; bubble.classList.remove('delete-mode'); bubble.classList.remove('mitigate-mode'); if (emphasisModeEnabled) { bubble.classList.add('emphasis-mode'); bubble.removeEventListener('click', deleteBubble); bubble.removeEventListener('click', mitigateBubble); bubble.addEventListener('click', emphasizeBubble); } else { bubble.classList.remove('emphasis-mode'); bubble.removeEventListener('click', emphasizeBubble); } } } function toggleMitigateMode() { mitigateModeEnabled = !mitigateModeEnabled; mitigateModeButton.classList.toggle('active'); if (mitigateModeEnabled) { deleteModeEnabled = false; deleteModeButton.classList.remove('active'); emphasisModeEnabled = false; emphasisModeButton.classList.remove('active'); } sortable.option('disabled', mitigateModeEnabled); bubbleContainer.classList.toggle('mitigate-mode-container'); const bubbles = bubbleContainer.getElementsByClassName('bubble'); for (let i = 0; i < bubbles.length; i++) { const bubble = bubbles[i]; bubble.classList.remove('delete-mode'); bubble.classList.remove('emphasis-mode'); if (mitigateModeEnabled) { bubble.classList.add('mitigate-mode'); bubble.removeEventListener('click', deleteBubble); bubble.removeEventListener('click', emphasizeBubble); bubble.addEventListener('click', mitigateBubble); } else { bubble.classList.remove('mitigate-mode'); bubble.removeEventListener('click', mitigateBubble); } } } function deleteBubble(event) { const bubble = event.target.closest('.bubble'); const bubbleText = bubble.querySelector('.bubble-text'); const nextComma = bubbleText.nextSibling; bubble.remove(); if (nextComma && nextComma.nodeType === Node.TEXT_NODE && nextComma.textContent.trim() === ',') { nextComma.remove(); } handleBubbleChange(); } function emphasizeBubble(event) { const bubble = event.target.closest('.bubble'); const bubbleText = bubble.querySelector('.bubble-text'); const text = bubbleText.innerText.trim(); if (text.startsWith('[') && text.endsWith(']')) { bubbleText.innerText = text.slice(1, -1); } else { bubbleText.innerText = `(${text})`; } handleBubbleChange(); } function mitigateBubble(event) { const bubble = event.target.closest('.bubble'); const bubbleText = bubble.querySelector('.bubble-text'); const text = bubbleText.innerText.trim(); if (text.startsWith('(') && text.endsWith(')')) { bubbleText.innerText = text.slice(1, -1); } else { bubbleText.innerText = `[${text}]`; } handleBubbleChange(); } document.addEventListener('DOMContentLoaded', function() { let words = []; let categoriesData = {}; // Datos de respaldo const backupData = { 'Composition and Style': { 'Style': [ { type: 'subcategory', name: 'Classic', items: [ { type: 'word', name: 'Elegant' }, { type: 'word', name: 'Traditional' } ] }, { type: 'subcategory', name: 'Modern', items: [ { type: 'word', name: 'Sleek' }, { type: 'word', name: 'Minimalist' } ] } ], 'Composition': [ { type: 'word', name: 'Balanced' }, { type: 'word', name: 'Dynamic' } ] }, 'Body': { 'Head': [ { type: 'subcategory', name: 'Facial Features', items: [ { type: 'word', name: 'Eyes' }, { type: 'word', name: 'Nose' } ] }, { type: 'subcategory', name: 'Hair', items: [ { type: 'word', name: 'Curly' }, { type: 'word', name: 'Straight' } ] } ], 'Torso': [ { type: 'word', name: 'Chest' }, { type: 'word', name: 'Back' } ] } }; // Archivos CSV a cargar const csvFiles = [ 'Composition.csv', 'Body.csv', 'Clothes.csv', 'Activity.csv', 'Objects.csv', 'Creatures.csv', 'Plants.csv', 'World.csv', 'NSFW.csv', 'More.csv' ]; const categoryEmojis = { 'Composition': '🖼️', 'Body': '🧏🏻♀️', 'Clothes': '👒', 'Activity': '🤺', 'Objects': '🎸', 'Creatures': '🐈', 'Plants': '☘️', 'World': '🌍', 'NSFW': '🍑', 'More': '📚' }; const categoryDropdownButton = document.getElementById('category-dropdown-button'); const categoryDropdown = document.getElementById('category-dropdown'); const randomWordButton = document.getElementById('random-word-button'); categoryDropdownButton.addEventListener('click', toggleCategoryDropdown); randomWordButton.addEventListener('click', addRandomWordToInput); document.addEventListener('click', closeDropdownOutsideClick); function toggleCategoryDropdown() { categoryDropdown.classList.toggle('hidden'); } function closeDropdownOutsideClick(event) { if (!categoryDropdown.contains(event.target) && event.target !== categoryDropdownButton) { categoryDropdown.classList.add('hidden'); } } async function loadCSVFiles() { for (const file of csvFiles) { try { const response = await fetch(file); if (!response.ok) throw new Error(`Error al cargar ${file}`); const text = await response.text(); processCSVData(file.split('.csv')[0], text); } catch (error) { console.error(error); // Usa datos de respaldo en caso de error const categoryName = file.split('.csv')[0]; if (backupData[categoryName]) { categoriesData[categoryName] = backupData[categoryName]; } } } renderCategories(); populateWordsForAutocomplete(); } function processCSVData(categoryName, csvText) { const lines = csvText.split('\n').map(line => line.trim()).filter(line => line.length > 0); const headers = lines[0].split(','); if (!categoriesData[categoryName]) { categoriesData[categoryName] = {}; } headers.forEach((header, index) => { if (!categoriesData[categoryName][header]) { categoriesData[categoryName][header] = []; } let currentSubcategory = null; let currentSubSubcategory = null; for (let i = 1; i < lines.length; i++) { const wordsInLine = lines[i].split(','); const word = wordsInLine[index].trim(); if (word) { // Si la palabra tiene una celda vacía directamente sobre ella en la misma columna if (i > 1 && lines[i - 1].split(',')[index].trim() === '') { if (currentSubcategory) { currentSubSubcategory = { type: 'subsubcategory', name: word, items: [] }; currentSubcategory.items.push(currentSubSubcategory); } else { currentSubcategory = { type: 'subcategory', name: word, items: [] }; categoriesData[categoryName][header].push(currentSubcategory); } } else if (currentSubSubcategory) { currentSubSubcategory.items.push({ type: 'word', name: word }); } else if (currentSubcategory) { currentSubcategory.items.push({ type: 'word', name: word }); } else { categoriesData[categoryName][header].push({ type: 'word', name: word }); } } else { if (currentSubSubcategory) { currentSubSubcategory = null; } else { currentSubcategory = null; } } } }); } function renderCategories() { categoryDropdown.innerHTML = ''; for (const [categoryName, subcategories] of Object.entries(categoriesData)) { const categoryItem = document.createElement('div'); categoryItem.classList.add('category-item'); const emojiSpan = document.createElement('span'); emojiSpan.classList.add('category-emoji'); emojiSpan.innerText = categoryEmojis[categoryName] || ''; const nameSpan = document.createElement('span'); nameSpan.innerText = categoryName; categoryItem.appendChild(emojiSpan); categoryItem.appendChild(nameSpan); categoryItem.addEventListener('click', () => toggleSubcategory(categoryItem, subcategories)); categoryDropdown.appendChild(categoryItem); } } function toggleSubcategory(categoryItem, subcategories) { if (categoryItem.nextElementSibling && categoryItem.nextElementSibling.classList.contains('subcategory-container')) { categoryItem.nextElementSibling.remove(); } else { const subcategoryContainer = document.createElement('div'); subcategoryContainer.classList.add('subcategory-container'); for (const [subcategoryName, items] of Object.entries(subcategories)) { const subcategoryItem = document.createElement('div'); subcategoryItem.classList.add('subcategory-item'); subcategoryItem.innerText = subcategoryName; // Crear botón para añadir palabra aleatoria const randomButton = document.createElement('button'); randomButton.innerText = '🎲'; randomButton.classList.add('random-word-button'); randomButton.addEventListener('click', (e) => { e.stopPropagation(); addRandomWordFromSubcategory(items); handleTextChange(); }); subcategoryItem.appendChild(randomButton); subcategoryItem.addEventListener('click', (e) => { e.stopPropagation(); toggleItems(subcategoryItem, items); }); subcategoryContainer.appendChild(subcategoryItem); } categoryItem.insertAdjacentElement('afterend', subcategoryContainer); } } function toggleItems(subcategoryItem, items) { if (subcategoryItem.nextElementSibling && subcategoryItem.nextElementSibling.classList.contains('item-container')) { subcategoryItem.nextElementSibling.remove(); } else { const itemContainer = document.createElement('div'); itemContainer.classList.add('item-container'); items.forEach(item => { const itemElement = document.createElement('div'); itemElement.classList.add(item.type === 'subcategory' || item.type === 'subsubcategory' ? 'subcategory-item' : 'word-item'); itemElement.innerText = item.name; // Si es subcategoría o sub-subcategoría, añadir botón de palabra aleatoria if (item.type === 'subcategory' || item.type === 'subsubcategory') { const randomButton = document.createElement('button'); randomButton.innerText = '🎲'; randomButton.classList.add('random-word-button'); randomButton.addEventListener('click', (e) => { e.stopPropagation(); addRandomWordFromSubcategory(item.items); handleTextChange(); }); itemElement.appendChild(randomButton); } if (item.type === 'subcategory' || item.type === 'subsubcategory') { itemElement.addEventListener('click', (e) => { e.stopPropagation(); toggleItems(itemElement, item.items); }); } else { itemElement.addEventListener('click', () => addItemToInput(item.name)); } itemContainer.appendChild(itemElement); }); subcategoryItem.insertAdjacentElement('afterend', itemContainer); } } function addItemToInput(word) { const inputText = document.getElementById('input-text'); inputText.value += (inputText.value ? ', ' : '') + word; updateBubbles(); } function populateWordsForAutocomplete() { words = []; for (const category of Object.values(categoriesData)) { for (const subcategory of Object.values(category)) { for (const item of subcategory) { if (item.type === 'word') { words.push(item.name); } else if (item.type === 'subcategory' || item.type === 'subsubcategory') { item.items.forEach(subItem => { if (subItem.type === 'word') { words.push(subItem.name); } }); } } } } console.log('Palabras cargadas para autocompletador:', words); } function addRandomWordToInput() { if (words.length === 0) return; const randomWord = words[Math.floor(Math.random() * words.length)]; addItemToInput(randomWord); } function addRandomWordFromSubcategory(subcategoryItems) { const subcategoryWords = subcategoryItems.flatMap(item => item.type === 'word' ? [item.name] : item.items.map(subItem => subItem.name)); if (subcategoryWords.length === 0) return; const randomWord = subcategoryWords[Math.floor(Math.random() * subcategoryWords.length)]; addItemToInput(randomWord); } const input = document.getElementById('autocomplete-input'); const autocompleteList = document.getElementById('autocomplete-list'); // Función que maneja tanto el evento de 'input' como de 'focus' function handleAutocomplete() { const value = input.value.toLowerCase(); console.log('Valor de entrada:', value); // Verifica el valor de entrada if (!value) { autocompleteList.innerHTML = ''; return; } // Filtra y ordena las palabras que empiezan con el valor ingresado, sin distinguir mayúsculas const startsWith = words .filter(word => word.toLowerCase().startsWith(value)) .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); // Filtra y ordena las palabras que contienen el valor ingresado pero no empiezan con él, sin distinguir mayúsculas const contains = words .filter(word => word.toLowerCase().includes(value) && !word.toLowerCase().startsWith(value)) .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); // Crear un conjunto para filtrar palabras únicas const uniqueSuggestions = new Set([...startsWith, ...contains]); // Convertir el conjunto a un array y tomar las primeras 20 sugerencias const suggestions = Array.from(uniqueSuggestions).slice(0, 20); console.log('Sugerencias encontradas:', suggestions); // Verifica las sugerencias encontradas autocompleteList.innerHTML = suggestions.map(suggestion => `