Last active
March 22, 2024 15:50
-
-
Save AndyCarnevale/1d65bc61f52227692aff50af39a81e04 to your computer and use it in GitHub Desktop.
Claude Chat Formatter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Claude Chat Formatter | |
* | |
* This script is designed to enhance the readability and distinction of messages in the Claude chat interface by either | |
* prepending labels to messages or wrapping messages in custom XML-like tags. It's particularly useful for clearly | |
* distinguishing between user and AI messages, making it easier to copy and paste the conversation with clear attribution. | |
* | |
* Functionality: | |
* - `prependLabels()`: Prepends a label indicating "user:" or "ai:" at the start of each message. | |
* - `tagMessages()`: Wraps each message with custom XML-like tags, <user>...</user> for user messages and <ai>...</ai> for AI messages. | |
* - `clearUsernameDivText()`: Clears the text contained within username div elements. | |
* | |
* The script uses MutationObserver to dynamically apply these formatting options to new messages as they appear in the chat, | |
* ensuring that all messages, including those loaded or added after the initial page load, are formatted correctly. | |
* | |
* Configuration: | |
* - The script allows easy switching between the two formatting functions (`prependLabels` and `tagMessages`) through | |
* the `applyFunction` variable. By default, it is set to use `tagMessages`. To switch to `prependLabels`, simply assign | |
* it to `applyFunction` like so: `const applyFunction = prependLabels;`. | |
* | |
* Usage: | |
* - To use the script, choose the desired formatting function by setting the `applyFunction` variable. | |
* - Add this script to the webpage with the AI chat interface. | |
*/ | |
// Configuration: Directly assign the function to use | |
// const applyFunction = prependLabels; | |
const applyFunction = tagMessages; | |
// Function to prepend labels to messages | |
function prependLabels() { | |
// Select all human messages and prepend a label if not already done | |
const userMessages = document.querySelectorAll('.font-user-message:not(.label-added)'); | |
userMessages.forEach(message => { | |
const label = document.createElement('span'); // Create a new span element for the label | |
label.textContent = 'user: '; // Set text content | |
label.style.fontWeight = 'bold'; // Optional: make the label bold | |
// Insert the label at the beginning of the message div | |
message.insertBefore(label, message.firstChild); | |
// Mark this message as having a label added to avoid duplicates | |
message.classList.add('label-added'); | |
}); | |
// Select all AI messages and prepend a label if not already done | |
const aiMessages = document.querySelectorAll('.font-claude-message:not(.label-added)'); | |
aiMessages.forEach(message => { | |
const label = document.createElement('span'); // Create a new span element for the label | |
label.textContent = 'ai: '; // Set text content | |
label.style.fontWeight = 'bold'; // Optional: make the label bold | |
// Insert the label at the beginning of the message div | |
message.insertBefore(label, message.firstChild); | |
// Mark this message as having a label added to avoid duplicates | |
message.classList.add('label-added'); | |
}); | |
} | |
// Function to add opening and closing tags around messages | |
function tagMessages() { | |
// Select all human messages and tag them if not already done | |
const userMessages = document.querySelectorAll('.font-user-message:not(.tagged)'); | |
userMessages.forEach(message => { | |
// Create opening and closing tags | |
const openTag = document.createElement('div'); | |
openTag.textContent = '<user>'; | |
const closeTag = document.createElement('div'); | |
closeTag.textContent = '</user>'; | |
// Insert opening tag at the beginning | |
message.insertBefore(openTag, message.firstChild); | |
// Append closing tag at the end | |
message.appendChild(closeTag); | |
// Mark this message to avoid re-tagging | |
message.classList.add('tagged'); | |
}); | |
// Select all AI messages and tag them if not already done | |
const aiMessages = document.querySelectorAll('.font-claude-message:not(.tagged)'); | |
aiMessages.forEach(message => { | |
// Create opening and closing tags | |
const openTag = document.createElement('div'); | |
openTag.textContent = '<ai>'; | |
const closeTag = document.createElement('div'); | |
closeTag.textContent = '</ai>'; | |
// Insert opening tag at the beginning | |
message.insertBefore(openTag, message.firstChild); | |
// Append closing tag at the end | |
message.appendChild(closeTag); | |
// Mark this message to avoid re-tagging | |
message.classList.add('tagged'); | |
}); | |
} | |
function clearUsernameDivText() { | |
// Select all elements with the specific class pattern - should just be the username | |
const elements = document.querySelectorAll('.font-bold'); | |
elements.forEach(element => { | |
element.textContent = ''; // Clear the text content of each element | |
}); | |
} | |
// MutationObserver callback to prepend labels when new nodes are added | |
const observerCallback = (mutationsList, observer) => { | |
for (const mutation of mutationsList) { | |
if (mutation.type === 'childList') { | |
applyFunction(); // Directly call the function assigned to applyFunction | |
clearUsernameDivText(); // Clear text of specific divs | |
} | |
} | |
}; | |
// Options for the observer (which mutations to observe) | |
const observerOptions = { | |
childList: true, | |
subtree: true | |
}; | |
// Create an observer instance linked to the callback function | |
const observer = new MutationObserver(observerCallback); | |
// Start observing the target node for configured mutations | |
const targetNode = document.body; // You might need to target a more specific part of the page | |
observer.observe(targetNode, observerOptions); | |
// Initially apply the chosen method | |
applyFunction(); // Directly call the function assigned to applyFunction | |
clearUsernameDivText |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment