(contentEl, processedContent)
| 970 | */ |
| 971 | getMessageTextFromDOM(messageId) { |
| 972 | const messageEl = document.querySelector(`[data-message-id="${messageId}"]`); |
| 973 | if (!messageEl) return null; |
| 974 | |
| 975 | const contentEl = messageEl.querySelector('.message-content'); |
| 976 | if (contentEl) { |
| 977 | const contentClone = contentEl.cloneNode(true); |
| 978 | contentClone.querySelectorAll('.code-block-copy-btn').forEach(el => el.remove()); |
| 979 | return contentClone.innerText || contentClone.textContent; |
| 980 | } |
| 981 | return null; |
| 982 | } |
| 983 | |
| 984 | /** |
| 985 | * Checks whether a message is actively streaming in the current DOM. |
| 986 | * @param {string} messageId - The message ID |
| 987 | * @returns {boolean} True when the DOM is still in a streaming state |
| 988 | */ |
| 989 | isMessageStreamingInDOM(messageId) { |
| 990 | const messageEl = document.querySelector(`[data-message-id="${messageId}"]`); |
| 991 | if (!messageEl) return false; |
| 992 | |
| 993 | return !!( |
| 994 | messageEl.querySelector('.message-content.streaming, .reasoning-content.streaming') || |
| 995 | messageEl.querySelector('.pending-response-label') |
| 996 | ); |
| 997 | } |
| 998 | |
| 999 | /** |
| 1000 | * Gets raw message content from a data attribute (sync, Safari-safe). |
| 1001 | * @param {string} messageId - The message ID |
| 1002 | * @returns {string|null} The raw content or null |
| 1003 | */ |
| 1004 | getMessageRawFromDOM(messageId) { |
| 1005 | if (!RAW_CLIPBOARD_ATTRIBUTE_ENABLED) return null; |
no test coverage detected