ChatGPT: SVG Image

Process code.language-xml elements and add buttons

  1. // ==UserScript==
  2. // @name ChatGPT: SVG Image
  3. // @namespace UserScript
  4. // @version 0.1.0
  5. // @description Process code.language-xml elements and add buttons
  6. // @author You
  7. // @match https://chat.openai.com/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. function changeButtonTextContent(button, newText) {
  16. for (const child of button.childNodes) {
  17. if (child.nodeType === Node.TEXT_NODE) {
  18. child.textContent = newText;
  19. return;
  20. }
  21. }
  22. }
  23.  
  24. function processCodeElement(codeElem) {
  25.  
  26.  
  27. const preElem = codeElem.closest('pre');
  28. if (!preElem) return;
  29.  
  30. const spanElem = preElem.querySelector('span');
  31. if (!spanElem) return;
  32.  
  33. const spanContent = spanElem.textContent.toLowerCase();
  34. if (spanContent !== 'xml' && spanContent !== 'svg') return;
  35.  
  36.  
  37.  
  38. const spanParent = spanElem.parentNode;
  39. if (!spanParent) return;
  40.  
  41. const button = spanParent.querySelector('button');
  42. if (!button) return;
  43.  
  44. spanElem.style.flexGrow = "1";
  45. spanParent.style.columnGap = "16px";
  46. button.classList.remove('ml-auto');
  47.  
  48. spanElem.style.order = "-4";
  49. button.style.order = "0";
  50.  
  51. const button1 = button.cloneNode(true);
  52. changeButtonTextContent(button1, 'View base64');
  53. button1.style.order = "-1";
  54. button.parentNode.insertBefore(button1, button.nextSibling);
  55.  
  56. button1.addEventListener('click', () => {
  57. const svgText = codeElem.textContent;
  58. const base64Svg = btoa(unescape(encodeURIComponent(svgText)));
  59. const dataUri = 'data:image/svg+xml;base64,' + base64Svg;
  60. navigator.clipboard.writeText(dataUri).catch(err => console.error(err));
  61. });
  62.  
  63. const button2 = button.cloneNode(true);
  64. changeButtonTextContent(button2, 'View Image');
  65. button2.style.order = "-1";
  66. button1.parentNode.insertBefore(button2, button1.nextSibling);
  67.  
  68. button2.addEventListener('click', () => {
  69. const svgText = codeElem.textContent;
  70.  
  71. const previewDiv = document.createElement('div');
  72. previewDiv.style.position = 'fixed';
  73. previewDiv.style.top = '50%';
  74. previewDiv.style.left = '50%';
  75. previewDiv.style.transform = 'translate(-50%, -50%)';
  76. previewDiv.style.zIndex = 1000;
  77. previewDiv.style.width = '64px';
  78. previewDiv.style.height = '64px';
  79. previewDiv.style.display = 'flex';
  80. previewDiv.style.alignItems = 'center';
  81. previewDiv.style.justifyContent = 'center';
  82. previewDiv.style.overflow = 'hidden';
  83. previewDiv.style.fill = 'initial';
  84. previewDiv.style.stroke = 'initial';
  85. previewDiv.style.color = 'initial';
  86. previewDiv.style.backgroundColor = 'inherit';
  87. previewDiv.style.padding = '24px';
  88.  
  89.  
  90.  
  91.  
  92. const svgElem = new DOMParser().parseFromString(svgText, 'image/svg+xml').documentElement;
  93. const svgWidth = svgElem.getAttribute('width') || svgElem.viewBox.baseVal.width;
  94. const svgHeight = svgElem.getAttribute('height') || svgElem.viewBox.baseVal.height;
  95.  
  96. // Ensure there are valid dimensions before proceeding
  97. if (!svgWidth || !svgHeight) {
  98. console.error("SVG doesn't have valid dimensions");
  99. return;
  100. }
  101.  
  102. previewDiv.style.boxSizing = 'content-box';
  103. // ... existing styles ...
  104.  
  105. // Create a wrapper SVG with a 64x64 viewbox
  106. const wrapperSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  107. wrapperSvg.setAttribute('viewBox', `0 0 ${svgWidth} ${svgHeight}`);
  108. wrapperSvg.style.width = '64px';
  109. wrapperSvg.style.height = '64px';
  110.  
  111. // Append the parsed SVG element to the wrapper
  112. wrapperSvg.appendChild(svgElem);
  113.  
  114. previewDiv.appendChild(wrapperSvg);
  115.  
  116.  
  117.  
  118. const overlay = document.createElement('div');
  119. overlay.style.position = 'fixed';
  120. overlay.style.top = 0;
  121. overlay.style.left = 0;
  122. overlay.style.width = '100%';
  123. overlay.style.height = '100%';
  124. overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  125. overlay.style.zIndex = 999;
  126. overlay.addEventListener('click', () => {
  127. document.body.removeChild(previewDiv);
  128. document.body.removeChild(overlay);
  129. });
  130.  
  131. document.body.appendChild(overlay);
  132. document.body.appendChild(previewDiv);
  133. });
  134.  
  135. }
  136.  
  137. const observer = new MutationObserver((mutationsList) => {
  138. for (let mutation of mutationsList) {
  139. if (mutation.addedNodes.length) {
  140. mutation.addedNodes.forEach((node) => {
  141. if (node.nodeType === 1) { // ELEMENT_NODE
  142. const codes = node.querySelectorAll('code.language-xml:not([w372]), code.language-svg:not([w372])');
  143. codes.forEach(code => {
  144. code.setAttribute('w372', '');
  145. processCodeElement(code);
  146. });
  147. }
  148. });
  149. }
  150. }
  151. });
  152.  
  153. observer.observe(document, { childList: true, subtree: true });
  154. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址