// ==UserScript== // @name ChatGPT LaTeX Auto Render (OpenAI, you, bing, etc.) // @namespace http://tampermonkey.net/ // @version 0.4.1 // @author Scruel // @homepage https://github.com/scruel/tampermonkey-scripts // @description Auto typeset LaTeX math formulas on ChatGPT pages (OpenAI, you, bing, etc.). // @description:zh-CN 自动渲染 ChatGPT 页面 (OpenAI, you, bing 等) 上的 LaTeX 数学公式。 // @match https://chat.openai.com/* // @match https://you.com/search?*&tbm=youchat* // @match https://www.bing.com/search?* // @grant none // @downloadURL none // ==/UserScript== 'use strict'; async function addScript(url) { const scriptElement = document.createElement('script'); const headElement = document.getElementsByTagName('head')[0] || document.documentElement; if (!headElement.appendChild(scriptElement)) { // Prevent appendChild overwritten problem. headElement.append(scriptElement); } scriptElement.src = url; await waitScriptLoaded(); } function waitScriptLoaded() { return new Promise(async (resolve, reject) => { const resolver = () => { if (MathJax.hasOwnProperty('typeset')) { resolve(); return; } if (window._sc_ChatLatex.loadCount > 100) { setTipsElementText("Failed to load MathJax, try refresh."); reject("Failed to load MathJax, try refresh."); return; } window._sc_ChatLatex.loadCount += 1; window.setTimeout(resolver, 200); } resolver(); }); } function prepareLoadingCheckFn() { window._sc_typeset = () => { MathJax.typeset(); } const commonCheck = (query) => { const submitButton = document.querySelector(query); return submitButton && !submitButton.disabled; } if (window.location.host == 'www.bing.com') { window._sc_typeset = () => { try { const allChatTurn = document.querySelector("#b_sydConvCont > cib-serp").shadowRoot.querySelector("#cib-conversation-main").shadowRoot.querySelectorAll("#cib-chat-main > cib-chat-turn"); if (allChatTurn.length == 0) { return; } const allCibMeg = allChatTurn[allChatTurn.length - 1].shadowRoot.querySelector("cib-message-group.response-message-group").shadowRoot.querySelectorAll("cib-message"); allCibMeg.forEach((cibMeg) => { const element = cibMeg.shadowRoot.querySelector("cib-shared"); const mathjaxElement = cibMeg.shadowRoot.querySelector("mjx-container"); if (element && !mathjaxElement) { MathJax.typeset([element]); } }); } catch (ignore) { } } window._sc_isAnswerPrepared = () => { const actionBarParent = document.querySelector("#b_sydConvCont > cib-serp"); if (!actionBarParent) { return false; } const actionBar = actionBarParent.shadowRoot.querySelector("#cib-action-bar-main"); return actionBar && !actionBar.hasAttribute('cancelable'); } } // TODO: typeset only last dialog. else if (window.location.host == 'you.com') { window._sc_typeset = () => { MathJax.typeset([document.querySelector("#chatHistory")]); } window._sc_isAnswerPrepared = () => { return commonCheck('main div[data-testid="youchat-input"] textarea+button'); } } else if (window.location.host == 'chat.openai.com') { window._sc_isAnswerPrepared = () => { return commonCheck('main form textarea+button'); } } } function renderTrigger() { setTimeout(renderLatex, window.renderDelay); } function renderLatex() { if (window._sc_isAnswerPrepared()) { // console.log("Rendering...") window._sc_typeset(); } renderTrigger(); } function setTipsElementText(text) { window._sc_ChatLatex.tipsElement.innerHTML = text; } function showTipsElement() { const tipsElement = window._sc_ChatLatex.tipsElement; tipsElement.style.position = "fixed"; tipsElement.style.left = "10px"; tipsElement.style.bottom = "10px"; tipsElement.style.background = '#333'; tipsElement.style.color = '#fff'; document.body.appendChild(tipsElement); } function hideTipsElement(timeout=3) { window.setTimeout(() => {window._sc_ChatLatex.tipsElement.hidden=true}, 3000); } (async function() { window._sc_ChatLatex = { tipsElement: document.createElement("div"), loadCount: 0 } window.MathJax = { tex: { inlineMath: [['$', '$'], ['\\(', '\\)']], displayMath : [['$$', '$$']] } }; showTipsElement(); setTipsElementText("Loading MathJax..."); await addScript('https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'); setTipsElementText("MathJax Loaded."); hideTipsElement(); prepareLoadingCheckFn(); window.renderDelay = 1000; renderTrigger(); })();