🏠 Home 

🚀🚀LatexForChatGPT🚀🚀

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();
}
})();