OpenAI-ChatGPT LaTeX Auto Render (with MathJax V2)

自动渲染 OpenAI 的 ChatGPT 页面上的 LaTeX 数学公式。

当前为 2022-12-12 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name OpenAI-ChatGPT LaTeX Auto Render (with MathJax V2)
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3.1
  5. // @author Scruel (https://github.com/scruel)
  6. // @description Auto typeset LaTeX math formulas on OpenAI ChatGPT page.
  7. // @description:zh-CN 自动渲染 OpenAI 的 ChatGPT 页面上的 LaTeX 数学公式。
  8. // @match https://chat.openai.com/chat
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. 'use strict';
  13.  
  14. async function addScript(url) {
  15. const scriptElement = document.createElement('script');
  16. scriptElement.src = url;
  17. scriptElement.async = true;
  18.  
  19. const headElement = document.getElementsByTagName('head')[0] || document.documentElement;
  20. headElement.appendChild(scriptElement);
  21. await waitScriptLoaded();
  22. }
  23.  
  24. function waitScriptLoaded() {
  25. return new Promise(async (resolve, reject) => {
  26. const resolver = () => {
  27. if (MathJax.hasOwnProperty('Hub')) {
  28. resolve();
  29. return;
  30. }
  31. if (window.ChatLatex.loadCount > 100) {
  32. setTipsElementText("Load MathJax failed, try refresh.");
  33. reject("Load MathJax failed, try refresh.");
  34. return;
  35. }
  36. window.ChatLatex.loadCount += 1;
  37. window.setTimeout(resolver, 200);
  38. }
  39. resolver();
  40. });
  41. }
  42.  
  43. function renderTrigger() {
  44. setTimeout(renderLatex, window.renderDelay);
  45. }
  46.  
  47. function renderLatex() {
  48. const submitButton = document.querySelector('main form textarea+button');
  49. // console.log(submitButton)
  50. if (submitButton && !submitButton.disabled) {
  51. // console.log("Rendering...")
  52. MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
  53. }
  54. renderTrigger();
  55. }
  56.  
  57. function showTipsElement() {
  58. const tipsElement = window.ChatLatex.tipsElement;
  59. tipsElement.style.position = "fixed";
  60. tipsElement.style.left = "10px";
  61. tipsElement.style.bottom = "10px";
  62. tipsElement.style.background = '#333';
  63. tipsElement.style.color = '#fff';
  64. document.body.appendChild(tipsElement);
  65. }
  66.  
  67. function setTipsElementText(text) {
  68. window.ChatLatex.tipsElement.innerHTML = text;
  69. }
  70.  
  71. function hideTipsElement(timeout=3) {
  72. window.setTimeout(() => {window.ChatLatex.tipsElement.hidden=true}, 3000);
  73. }
  74.  
  75. (async function() {
  76. window.ChatLatex = {
  77. tipsElement: document.createElement("div"),
  78. loadCount: 0
  79. }
  80. window.MathJax = {
  81. tex2jax: {
  82. inlineMath: [['$', '$']],
  83. displayMath : [['$$', '$$']]
  84. },
  85. CommonHTML: { linebreaks: { automatic: true } },
  86. "HTML-CSS": { linebreaks: { automatic: true } },
  87. SVG: { linebreaks: { automatic: true } },
  88. };
  89.  
  90. showTipsElement();
  91. setTipsElementText("Loading MathJax...");
  92. await addScript('https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS_CHTML');
  93. setTipsElementText("MathJax Loaded.");
  94. hideTipsElement();
  95.  
  96. window.renderDelay = 1000;
  97. renderTrigger();
  98. })();