latex for chatgpt
// ==UserScript== // @name 🚀🚀LatexForChatGPT🚀🚀 // @namespace https://github.com/linkedlist771/ChatGPT-Latex // @supportURL https://github.com/linkedlist771/ChatGPT-Latex // @version 0.0.5 // @description latex for chatgpt // @author LLinkedList771 // @run-at document-start // @match https://chat.openai.com/* // @match https://chatgpt.com/* // @license MIT // @icon data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" stroke-width="2" fill="none" stroke="currentColor"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg> // ==/UserScript== (function() { 'use strict'; // ----------------- Constants ----------------- let latexConversionInjectionInterval; const conversionInjectionIntervalTime = 1000; // 5 seconds, adjust as needed let currentGPT4Model = "gpt-4"; // Default model let gpt4InjectionInterval; function replaceLatexBlock(inputString) { const inputSize = inputString.length; let newString = inputString.split(''); for (let i = 0; i < inputSize - 1; i++) { if(inputString[i] == '\\' && inputString[i+1] == '[') { newString[i] = '$'; newString[i+1] = '$'; } else if(inputString[i] == '\\' && inputString[i+1] == ']') { newString[i] = '$'; newString[i+1] = '$'; } } return newString.join(''); } function chatgptOutputStringToLatex(inputString) { // Convert \( ... \) to $ // do it one by one // 1.replace \( with $ // 2.replace \) with $ // 3.replace \[ with $$ // 4.replace \] with $$ let r###lt = inputString.replace(/\\\(/g, '$').replace(/\\\)/g, '$'); // Convert \[ ... \] to $$ // r###lt = r###lt.replace(/\\\[/g, '$$').replace(/\\\]/g, '$$'); r###lt = replaceLatexBlock(r###lt); return r###lt; } function findAllCopyButtons() { // class : flex ml-auto const copyButtons = document.querySelectorAll('button'); //flex items-center return copyButtons; } function InjectLatexConversionForCopyButtons() { const buttons = findAllCopyButtons(); buttons.forEach(button => { button.addEventListener('click', function() { // Delay the custom logic to ensure it runs after the default behavior setTimeout(() => { // Read the current content of the clipboard navigator.clipboard.readText().then(clipText => { // Transform the LaTeX delimiters const modifiedText = chatgptOutputStringToLatex(clipText); // Copy the modified text back to the clipboard navigator.clipboard.writeText(modifiedText); }); }, 100); // 100ms delay, adjust if needed }); }); } function startLatexConversionInjectionTimer() { if (!latexConversionInjectionInterval) { latexConversionInjectionInterval = setInterval(InjectLatexConversionForCopyButtons, conversionInjectionIntervalTime); console.log("Latex conversion timer started."); } else { console.log("Latex conversion timer is already running."); } } function stopLatexConversionInjectionTimer() { if (latexConversionInjectionInterval) { clearInterval(latexConversionInjectionInterval); latexConversionInjectionInterval = null; console.log("Latex conversion timer stopped."); } else { console.log("Latex conversion timer is not running."); } } // startLatexConversionTimer(); // ----------------- Styles for the new UI ----------------- function addLatexConversionStyles() { const styles = ` .latex-conversion-panel { position: fixed; top: 10%; right: 2%; background-color: white; padding: 10px; border: 1px solid #ccc; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); z-index: 9999; width: 250px; } .latex-conversion-panel.minimized { width: auto; padding: 5px; } .latex-head { font-weight: bold; margin-bottom: 10px; } .latex-title { display: inline-block; } .latex-toggle { cursor: pointer; float:right; margin-right:5px; } .latex-toggle.minimized::before { content: "[+]"; } .latex-toggle.maximized::before { content: "[-]"; } /* Toggle Switch Styles */ .switch { position: relative; display: inline-block; width: 60px; height: 34px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; } .slider:before { position: absolute; content: ""; height: 26px; width: 26px; left: 4px; bottom: 4px; background-color: white; transition: .4s; } input:checked + .slider { background-color: #2196F3; } input:checked + .slider:before { transform: translateX(26px); } .slider.round { border-radius: 34px; } .slider.round:before { border-radius: 50%; } `; const styleSheet = document.createElement("style"); styleSheet.type = "text/css"; styleSheet.innerText = styles; document.head.appendChild(styleSheet); } // ----------------- Rewrite the post function ----------------- function injectGPTPost(){ let realFetch = window.fetch; window.fetch = function(url, init) { if (!isScriptEnabled) { return realFetch(url, init); } try { if (init && init.method === 'POST') { let data = JSON.parse(init.body); if (data.hasOwnProperty('model')) { data.model = currentGPT4Model; init.body = JSON.stringify(data); } } return realFetch(url, init); } catch (e) { console.error('在处理请求时出现错误:', e); return realFetch(url, init); } }; } function startGPT4InjectionTimer() { if (!gpt4InjectionInterval) { gpt4InjectionInterval = setInterval(injectGPTPost, conversionInjectionIntervalTime); console.log("GPT4 timer started."); } else { console.log("GPT4 timer is already running."); } } function stopGPT4InjectionTimer() { if (gpt4InjectionInterval) { clearInterval(gpt4InjectionInterval); gpt4InjectionInterval = null; console.log("GPT4 timer stopped."); } else { console.log("GPT4 timer is not running."); } } // ----------------- UI Creation for the new functions ----------------- function addListenerToLatexConversionToggleSwitch(controlDiv) { document.getElementById("latexToggleSwitch").addEventListener("change", function() { if (this.checked) { startLatexConversionInjectionTimer(); } else { stopLatexConversionInjectionTimer(); } saveSettings(controlDiv); // Save settings when changed }); } function addListenerToGPT4ToggleSwitch(controlDiv) { let modelToggleSwitchList = { "gpt4ToggleSwitch": "gpt-4", "gpt4BrowsingToggleSwitch": "gpt-4-browsing", "gpt4PluginToggleSwitch": "gpt-4-plugin", "gpt4CodeInterpreterToggleSwitch": "gpt-4-code-interpreter", "gpt4DalleToggleSwitch": "gpt-4-dalle" }; for (let modelToggleSwitch in modelToggleSwitchList) { let modelKey = modelToggleSwitch; let modelValue = modelToggleSwitchList[modelToggleSwitch]; document.getElementById(modelKey).addEventListener("change", function() { if (this.checked) { currentGPT4Model = modelValue; startGPT4InjectionTimer(); } else { stopGPT4InjectionTimer(); } saveSettings(controlDiv); // Save settings when changed }); } } function createLatexConversionUI() { const controlDiv = document.createElement('div'); controlDiv.className = 'latex-conversion-panel'; controlDiv.innerHTML = ` <div class="latex-head"> <span class="latex-title">LaTeX Conversion Control</span> <span class="latex-toggle maximized"></span> </div> <div class="main"> <label class="switch"> <input type="checkbox" id="latexToggleSwitch"> <span class="slider round"></span> </label> <span style="margin-left: 5px;">Start/Stop </span> <br> </div> `; document.body.appendChild(controlDiv); const toggleIcon = controlDiv.querySelector(".latex-toggle"); const title = controlDiv.querySelector(".latex-title"); toggleIcon.onclick = function() { if (toggleIcon.classList.contains("maximized")) { controlDiv.querySelector(".main").style.display = "none"; title.style.display = "none"; toggleIcon.classList.remove("maximized"); toggleIcon.classList.add("minimized"); controlDiv.classList.add("minimized"); } else { controlDiv.querySelector(".main").style.display = "block"; title.style.display = "inline-block"; toggleIcon.classList.remove("minimized"); toggleIcon.classList.add("maximized"); controlDiv.classList.remove("minimized"); } saveSettings(controlDiv); // Save settings when panel state is changed }; // Add event listener to the toggle switch addListenerToLatexConversionToggleSwitch(controlDiv); loadSettings(controlDiv); // Load saved settings after UI is created } // ----------------- Save and Load Settings ----------------- function saveSettings(controlDiv) { const isChecked = document.getElementById("latexToggleSwitch").checked; localStorage.setItem('latexToggleSwitchState', isChecked); localStorage.setItem('latexPanelState', controlDiv.classList.contains("minimized") ? "minimized" : "maximized"); } function loadSettings(controlDiv) { const isChecked = localStorage.getItem('latexToggleSwitchState') === 'true'; const panelState = localStorage.getItem('latexPanelState'); document.getElementById("latexToggleSwitch").checked = isChecked; if (isChecked) { startLatexConversionInjectionTimer(); } else { stopLatexConversionInjectionTimer(); } const toggleIcon = controlDiv.querySelector(".latex-toggle"); const title = controlDiv.querySelector(".latex-title"); if (panelState === "minimized") { controlDiv.querySelector(".main").style.display = "none"; title.style.display = "none"; toggleIcon.classList.remove("maximized"); toggleIcon.classList.add("minimized"); controlDiv.classList.add("minimized"); } else { controlDiv.querySelector(".main").style.display = "block"; title.style.display = "inline-block"; toggleIcon.classList.remove("minimized"); toggleIcon.classList.add("maximized"); controlDiv.classList.remove("minimized"); } } // ----------------- Initialization ----------------- if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { addLatexConversionStyles(); createLatexConversionUI(); }); } else { addLatexConversionStyles(); createLatexConversionUI(); } })();