ChatGPT Export to Markdown (Named)

Adds a button to export ChatGPT conversations as Markdown with the chat's name as the file name.

  1. // ==UserScript==
  2. // @name ChatGPT Export to Markdown (Named)
  3. // @description Adds a button to export ChatGPT conversations as Markdown with the chat's name as the file name.
  4. // @author chatgpt.js
  5. // @namespace https://chatgpt.js.org
  6. // @version 1.0
  7. // @license MIT
  8. // @match *://chatgpt.com/*
  9. // @icon https://cdn.jsdelivr.net/npm/@mdi/svg/svg/content-save.svg
  10. // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.2.0/dist/chatgpt.min.js
  11. // @grant GM_getValue
  12. // @grant GM_setValue
  13. // @noframes
  14. // ==/UserScript==
  15.  
  16. (async () => {
  17. // Ensure chatgpt.js is loaded
  18. await chatgpt.isLoaded();
  19.  
  20. // Add the export button with a floppy disk icon
  21. const button = document.createElement('button');
  22. button.id = 'export-to-markdown-btn';
  23. button.style.position = 'fixed';
  24. button.style.bottom = '20px';
  25. button.style.right = '20px';
  26. button.style.zIndex = '9999';
  27. button.style.backgroundColor = '#4CAF50';
  28. button.style.border = 'none';
  29. button.style.padding = '10px';
  30. button.style.borderRadius = '50%';
  31. button.style.cursor = 'pointer';
  32.  
  33. // Add floppy disk icon to the button
  34. const floppyIcon = document.createElement('img');
  35. floppyIcon.src = 'https://cdn.jsdelivr.net/npm/@mdi/svg/svg/content-save.svg';
  36. floppyIcon.width = 24;
  37. button.appendChild(floppyIcon);
  38.  
  39. // Append the button to the body
  40. document.body.appendChild(button);
  41.  
  42. // Button click handler
  43. button.addEventListener('click', async () => {
  44. try {
  45. // Fetch the current conversation data
  46. const chatData = await chatgpt.getChatData("active", ["msg"], "both");
  47. const chatTitleData = await chatgpt.getChatData("active", "title");
  48.  
  49. // Use the chat's title or a fallback
  50. const chatTitle = chatTitleData.title || 'ChatGPT_Conversation';
  51. const sanitizedTitle = chatTitle.replace(/[<>:"/\\|?*]+/g, ''); // Remove invalid filename characters
  52.  
  53. // Convert the conversation data to a markdown format
  54. let markdownContent = `# ${chatTitle}\n\n`;
  55. chatData.forEach((msg, index) => {
  56. markdownContent += `### Message ${index + 1}\n\n`;
  57. markdownContent += `**User:** ${msg.user}\n\n`;
  58. markdownContent += `**ChatGPT:** ${msg.chatgpt}\n\n---\n`;
  59. });
  60.  
  61. // Create a Blob object from the markdown content
  62. const blob = new Blob([markdownContent], { type: 'text/markdown' });
  63.  
  64. // Create a link element to download the markdown file
  65. const link = document.createElement('a');
  66. link.href = URL.createObjectURL(blob);
  67. link.download = `${sanitizedTitle}.md`;
  68. link.click();
  69.  
  70. // Notify the user
  71. chatgpt.notify('✅ Exported to Markdown successfully!', 'topRight', 2);
  72. } catch (error) {
  73. chatgpt.notify('❌ Failed to export conversation!', 'topRight', 2);
  74. console.error('Export to Markdown failed:', error);
  75. }
  76. });
  77. })();