// 为 bot 消息添加复制与切换显示按钮 以及最新消息加上重新生成,删除最新消息,嗯。 function convertBotMessage(gradioButtonMsg) { return; // should use old version with raw-message applied in python function clipRawMessage(message) { const hrPattern = /
([\s\S]*?)/; const hrMatch = message.match(hrPattern); let finalMessage = ""; let suffixMessage = ""; let rawMessage = message; if (hrMatch) { message = rawMessage.substring(0, hrMatch.index).trim(); suffixMessage = rawMessage.substring(hrMatch.index).trim(); } const agentPrefixPattern = new RegExp('([\\s\\S]*?)', 'g'); const agentParts = message.split(agentPrefixPattern); for (let i = 0; i < agentParts.length; i++) { const part = agentParts[i]; if (i % 2 === 0) { if (part !== "" && part !== "\n") { finalMessage += `
${escapeMarkdown(part.trim())}
`; } } else { finalMessage += part.replace(' data-fancybox="gallery"', ''); // 避免 raw message 中的图片被 fancybox 处理 } } finalMessage += suffixMessage return finalMessage; } var insertChild = gradioButtonMsg.querySelector('.md'); var rawMessageStr = gradioButtonMsg.getAttribute('aria-label'); rawMessageStr = rawMessageStr.replace(/^bot's message: /, ''); // 去掉开头的“bot's message: ”,删去结尾可能的多余的空行 var rawMessage = document.createElement('div'); rawMessage.classList.add('raw-message'); rawMessage.classList.add('hideM'); rawMessage.innerHTML = clipRawMessage(rawMessageStr); var mdMessage = document.createElement('div'); mdMessage.classList.add('md-message'); mdMessage.innerHTML = insertChild.innerHTML; insertChild.innerHTML = ''; insertChild.appendChild(rawMessage); insertChild.appendChild(mdMessage); } function addChuanhuButton(botElement) { // botElement = botRow.querySelector('.message.bot'); var isLatestMessage = botElement.classList.contains('latest'); var gradioButtonMsg = botElement.querySelector('button[data-testid="bot"]'); var rawMessage = botElement.querySelector('.raw-message'); var mdMessage = botElement.querySelector('.md-message'); // if (!rawMessage && !mdMessage) { // // 现在动态更新会导致 svelte.js 的 flush 出错,所以生成时不更新 // if (chatbotIndicator.classList.contains('generating')) return; // // convertBotMessage(gradioButtonMsg); // rawMessage = botElement.querySelector('.raw-message'); // mdMessage = botElement.querySelector('.md-message'); // } if (!rawMessage) { // 如果没有 raw message,说明是早期历史记录,去除按钮 // var buttons = botElement.querySelectorAll('button.chuanhu-btn'); // for (var i = 0; i < buttons.length; i++) { // buttons[i].parentNode.removeChild(buttons[i]); // } botElement.querySelector('.message-btn-row')?.remove(); botElement.querySelector('.message-btn-column')?.remove(); return; } // if (!isLatestMessage) botElement.querySelector('.message-btn-row')?.remove(); setLatestMessage(); // 改成生成时不添加按钮好了…… if (chatbotIndicator.classList.contains('generating')) return; botElement.querySelector('.message-btn-column')?.remove(); // Copy bot button var copyButton = document.createElement('button'); copyButton.classList.add('chuanhu-btn'); copyButton.classList.add('copy-bot-btn'); copyButton.setAttribute('aria-label', 'Copy'); copyButton.innerHTML = copyIcon; copyButton.addEventListener('click', async () => { let textToCopyHTML = rawMessage.innerHTML; let textToCopyTMP = textToCopyHTML.replace(//gi, '\n'); let textToCopyDOM = document.createElement('div'); textToCopyDOM.innerHTML = textToCopyTMP; let textToCopy = textToCopyDOM.textContent; try { if ("clipboard" in navigator) { await navigator.clipboard.writeText(textToCopy); // console.log("Copied to clipboard: \n", textToCopy); copyButton.innerHTML = copiedIcon; setTimeout(() => { copyButton.innerHTML = copyIcon; }, 1500); } else { const textArea = document.createElement("textarea"); textArea.value = textToCopy; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); copyButton.innerHTML = copiedIcon; setTimeout(() => { copyButton.innerHTML = copyIcon; }, 1500); } catch (error) { console.error("Copy failed: ", error); } document.body.removeChild(textArea); } } catch (error) { console.error("Copy failed: ", error); } }); // botElement.appendChild(copyButton); // Toggle button var toggleButton = document.createElement('button'); toggleButton.classList.add('chuanhu-btn'); toggleButton.classList.add('toggle-md-btn'); toggleButton.setAttribute('aria-label', 'Toggle'); var renderMarkdown = mdMessage.classList.contains('hideM'); toggleButton.innerHTML = renderMarkdown ? mdIcon : rawIcon; toggleButton.addEventListener('click', () => { renderMarkdown = mdMessage.classList.contains('hideM'); if (renderMarkdown) { renderMarkdownText(botElement); toggleButton.innerHTML=rawIcon; } else { removeMarkdownText(botElement); toggleButton.innerHTML=mdIcon; } chatbotContentChanged(1); // to set md or raw in read-only history html }); // botElement.insertBefore(toggleButton, copyButton); var messageBtnColumn = document.createElement('div'); messageBtnColumn.classList.add('message-btn-column'); messageBtnColumn.appendChild(toggleButton); messageBtnColumn.appendChild(copyButton); botElement.appendChild(messageBtnColumn); function renderMarkdownText(message) { var mdDiv = message.querySelector('.md-message'); if (mdDiv) mdDiv.classList.remove('hideM'); var rawDiv = message.querySelector('.raw-message'); if (rawDiv) rawDiv.classList.add('hideM'); } function removeMarkdownText(message) { var rawDiv = message.querySelector('.raw-message'); if (rawDiv) { // 判断pre是否存在fake-pre类,如果不存在,则为20231118之前的历史记录格式,需要转换,增加fake-pre类用于适配 if (!rawDiv.querySelector('pre')?.classList.contains('fake-pre')) { rawDiv.innerHTML = rawDiv.innerHTML.replace(/
/g, '
');
            }
            // rawDiv.innerHTML = rawDiv.querySelector('pre')?.innerHTML || rawDiv.innerHTML;
            rawDiv.classList.remove('hideM');
        }
        var mdDiv = message.querySelector('.md-message');
        if (mdDiv) mdDiv.classList.add('hideM');
    }
}

function setLatestMessage() {
    // var latestMessage = gradioApp().querySelector('#chuanhu-chatbot > .wrapper .message-wrap .message.bot:last-of-type');
    var botMessages = gradioApp().querySelectorAll('#chuanhu-chatbot .message-wrap .message.bot');
    var messageCount = botMessages.length;
    var latestMessage = botMessages[messageCount - 1];
    botMessages.forEach((message, index) => {
        if (index === messageCount -1) {
            message.classList.add('latest');
        } else {
            message.classList.remove('latest');
            message.querySelector('.message-btn-row')?.remove();
        }
    });
    if (latestMessage) addLatestMessageButtons(latestMessage);
}

function addLatestMessageButtons(botElement) {
    // botElement.querySelector('.message-btn-row')?.remove();
    if (botElement.querySelector('.message-btn-row')) return;

    var messageBtnRow = document.createElement('div');
    messageBtnRow.classList.add('message-btn-row');
    var messageBtnRowLeading = document.createElement('div');
    messageBtnRowLeading.classList.add('message-btn-row-leading');
    var messageBtnRowTrailing = document.createElement('div');
    messageBtnRowTrailing.classList.add('message-btn-row-trailing');

    messageBtnRow.appendChild(messageBtnRowLeading);
    messageBtnRow.appendChild(messageBtnRowTrailing);

    botElement.appendChild(messageBtnRow);

    //leading
    var regenerateButton = document.createElement('button');
    regenerateButton.classList.add('chuanhu-btn');
    regenerateButton.classList.add('regenerate-btn');
    regenerateButton.setAttribute('aria-label', 'Regenerate');
    regenerateButton.innerHTML = regenIcon + `${i18n(regenerate_i18n)}`;

    var gradioRetryBtn = gradioApp().querySelector('#gr-retry-btn');
    regenerateButton.addEventListener('click', () => {
        gradioRetryBtn.click();
    });

    var deleteButton = document.createElement('button');
    deleteButton.classList.add('chuanhu-btn');
    deleteButton.classList.add('delete-latest-btn');
    deleteButton.setAttribute('aria-label', 'Delete');
    deleteButton.innerHTML = deleteIcon + `${i18n(deleteRound_i18n)}`;

    var gradioDelLastBtn = gradioApp().querySelector('#gr-dellast-btn');
    deleteButton.addEventListener('click', () => {
        gradioDelLastBtn.click();
    });

    messageBtnRowLeading.appendChild(regenerateButton);
    messageBtnRowLeading.appendChild(deleteButton);

    // trailing
    var likeButton = document.createElement('button');
    likeButton.classList.add('chuanhu-btn');
    likeButton.classList.add('like-latest-btn');
    likeButton.setAttribute('aria-label', 'Like');
    likeButton.innerHTML = likeIcon;

    var gradioLikeBtn = gradioApp().querySelector('#gr-like-btn');
    likeButton.addEventListener('click', () => {
        gradioLikeBtn.click();
    });

    var dislikeButton = document.createElement('button');
    dislikeButton.classList.add('chuanhu-btn');
    dislikeButton.classList.add('dislike-latest-btn');
    dislikeButton.setAttribute('aria-label', 'Dislike');
    dislikeButton.innerHTML = dislikeIcon;

    var gradioDislikeBtn = gradioApp().querySelector('#gr-dislike-btn');
    dislikeButton.addEventListener('click', () => {
        gradioDislikeBtn.click();
    });

    messageBtnRowTrailing.appendChild(likeButton);
    messageBtnRowTrailing.appendChild(dislikeButton);
}


// button svg code
const copyIcon   = '';
const copiedIcon = '';
const mdIcon     = '';
const rawIcon    = '';

const regenIcon  = '';
const deleteIcon = '';
    // const deleteIcon = ''

const likeIcon   = '';
const dislikeIcon= ''