Skip to content

Instantly share code, notes, and snippets.

@rf5860
Created April 23, 2025 01:48
Show Gist options
  • Save rf5860/c1c91b5d58f75eadf4eaddc1d0281160 to your computer and use it in GitHub Desktop.
Save rf5860/c1c91b5d58f75eadf4eaddc1d0281160 to your computer and use it in GitHub Desktop.
Added LaTeX support to BetterGPT
// ==UserScript==
// @name BetterGPT LaTeX
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Added LaTeX support to BetterGPT
// @author rjf89
// @match https://animalnots.github.io/BetterChatGPT-PLUS/
// @grant none
// ==/UserScript==
// --- 1. Configure MathJax ---
// Set up configuration *before* loading the MathJax script.
// Use the window.MathJax object for configuration.
window.MathJax = {
extensions: ["tex2jax.js"],
tex2jax: {
inlineMath: [
['[;',';]'],
['$$','$$']
],
displayMath: [
['[(;',';)]'],
['[',']']
],
skipTags: ["script", "noscript", "style", "textarea", "pre", "code"],
processEscapes: true
},
jax: ["input/TeX", "output/HTML-CSS"],
messageStyle: "none", // Optional: Hides the "Processing Math..." messages
"HTML-CSS": {
availableFonts: ["TeX"], // Use TeX fonts for better consistency
linebreaks: { automatic: true } // Enable automatic line breaking
},
// --- Hook to run code after MathJax is fully loaded and ready ---
AuthorInit: function () {
console.log("MathJax is initialized and ready.");
// --- 3. Setup MutationObserver after MathJax is ready ---
setupMathJaxMutationObserver();
}
};
// --- Function to Set Up the Mutation Observer ---
function setupMathJaxMutationObserver() {
// Check if MathJax Hub is available
if (!window.MathJax || !window.MathJax.Hub) {
console.warn("MathJax Hub not ready yet for MutationObserver setup. Retrying in 200ms.");
// Retry shortly, MathJax might still be initializing
setTimeout(setupMathJaxMutationObserver, 200);
return;
}
const targetNode = document.body; // Observe the entire body, or a more specific container element if possible
const observerConfig = {
childList: true, // Watch for direct children changes (nodes added/removed)
subtree: true // Watch descendants as well
};
const observerCallback = function(mutationsList, observer) {
// Use a flag to avoid queueing multiple times for a single batch of mutations
let nodesAdded = false;
for (const mutation of mutationsList) {
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
nodesAdded = true;
}
}
// If any nodes were added in this batch of mutations, tell MathJax to typeset
if (nodesAdded) {
console.log("Detected added content, queueing MathJax Typeset.");
// --- 4. Tell MathJax to process the content ---
// Queue a command to typeset the *entire targetNode*.
// While typesetting only mutation.addedNodes is more granular,
// typesetting the container (targetNode) is often simpler and more robust,
// especially if math spans across multiple added elements.
// Adjust targetNode if you know changes only happen within a specific div.
MathJax.Hub.Queue(["Typeset", MathJax.Hub, targetNode]);
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(observerCallback);
// Start observing the target node for configured mutations
observer.observe(targetNode, observerConfig);
console.log("MutationObserver is watching for dynamic content to apply MathJax.");
window.addEventListener('unload', () => {
if (observer) {
observer.disconnect();
console.log("MutationObserver disconnected.");
}
});
}
// --- 2. Load MathJax ---
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML";
script.async = true; // Load asynchronously without blocking page rendering
document.getElementsByTagName("head")[0].appendChild(script);
console.log("MathJax loading initiated.");
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment