#language = "V8" #async = "on" // This macro retrieves ChatGPT search results using a word at the cursor or the selection. // It demonstrates the use of the WebBar object and the "web" keyword to // access the Document Object Model (DOM) using the EmEditor's Web Browser. It requires // EmEditor v23.0 or later. The macro also uses the MutationObserver interface to monitor // HTML elements. // // Disclaimer: The format of ChatGPT results may change at any time in the future, which // could affect the functionality of this macro. The macro is intended solely to demonstrate // the new features of EmEditor v23.0. const sURL = "https://chat.openai.com/"; var sText = ""; function textObserverCallback( records ) { for( const record of records ) { if( record.type === "characterData" ) { var sNewText = record.target.data if( sText.length == 0 || sNewText.indexOf( sText ) == 0 ) { document.write( sNewText.substring( sText.length ) ); sText = record.target.data; } else { document.writeln( "" ); document.writeln( "" ); sText = record.target.data; document.write( sText ); } } } } function innerObserverCallback( records ) { for( const record of records ) { if( record.addedNodes ) { for( const node of record.addedNodes ) { const nodes = node.getElementsByTagName( "p" ); if( nodes.length > 0 ) { // Monitor paragraph tag if( window.textObserver ) { window.textObserver.disconnect(); } window.textObserver = new MutationObserver( textObserverCallback ); window.textObserver.observe( node, { characterData: true, subtree: true } ); } } } } } function observerCallback( records ) { for( const record of records ) { if( record.addedNodes ) { for( const node of record.addedNodes ) { if( node.dataset && node.dataset['testid'] && node.dataset['testid'].startsWith('conversation-turn') ) { // Monitor latest chat element if( window.innerObserver ) { window.innerObserver.disconnect(); } window.innerObserver = new MutationObserver( innerObserverCallback ); window.innerObserver.observe( node, { childList: true, subtree: true } ); } } } } } if( !WebBar.Visible ) { // use "WebBar" to open the URL using the EmEditor's Web Browser WebBar.Open( sURL ); alert( "Please run this macro again" ); Quit(); } if( !web.window.location.href.startsWith( sURL ) ) { web.window.location.href = sURL; alert( "Please run this macro again" ); Quit(); } if( document.selection.IsEmpty ) { document.selection.SelectWord(); } if( !document.selection.IsEmpty ) { var elem = web.document.getElementById( "prompt-textarea" ); if( elem == null ) { alert( "cannot find search box" ); Quit(); } elem.value = document.selection.Text; // Simulate input to refresh UI elem.dispatchEvent( new Event( 'input', { bubbles: true } ) ); // Uncomment the following two lines to submit the text automatically //var elemBtn = web.document.querySelector("[data-testid='send-button']"); //elemBtn.dispatchEvent(new MouseEvent('click', {bubbles: true})); editor.NewFile(); // Monitor container element if( window.outerObserver ) { window.outerObserver.disconnect(); } window.outerObserver = new MutationObserver( observerCallback ); const mainElements = web.document.getElementsByTagName( "main" ); if( mainElements.length === 0 ) { alert( "cannot find main element" ); Quit(); } outerObserver.observe( mainElements[0], { childList: true, subtree: true } ); }