javascriptasync-awaitbookmarklet

JS-code with newline character `%0A` works in console, but fails as a bookmarklet


I am writing a bookmarklet, and I wish it works in browser console as well.

To make it easier to understand, the code makes an async API-call (imitates real; which is perfectly legit) to the server. It is supposed to change the message I clicked edit on, add "Text-1" at the beginning of the message, and save the message.

javascript:(async function(){
    var msgIdInChange = '';
    var targetNode = '';
    var textOfMsgInChange = '';
    var textToInsert = '';
    
    msgIdInChange = document.getElementsByClassName('editing-message')[0].getAttribute('msg-id'); /*getting msg-id of the actively editing message*/
    
    targetNode = document.querySelector("[node-id=" +CSS.escape(msgIdInChange)+ "]"); /*getting targetNode by msg-id from DOM*/
    textOfMsgInChange = targetNode.innerText;
    
    textToInsert = 'Text-1: ' + textOfMsgInChange;
    
    
    var currentChatId = '';
    var myToken = '';
    currentChatId = document.getElementById('currentChat').getAttribute('mail');
    myToken = JSON.parse(window.localStorage._connectData).aimsid; /*session token*/
    
    
    var encodifyText = function(txt){
        var temp = [];
        var returnVal = '';
        temp = txt.split('\n');
        for (i=0; i<temp.length; i++){
            returnVal += encodeURIComponent(txt.split('\n')[i]) + '%0A';
        }
        return returnVal.slice(0,-3); /*Delete last newline*/
    };
    
    
    var changeMessageFunc = async function(){
        const response = await fetch('https://needed.site/api/sendIM', {
            'headers': {
                'accept': '*/*',
                'content-type': 'application/x-www-form-urlencoded',
                'sec-fetch-dest': 'empty',
                'sec-fetch-mode': 'cors',
                'sec-fetch-site': 'same-site'
            },
            'referrer': 'https://needed.site/',
            'referrerPolicy': 'strict-origin-when-cross-origin',
            'body': 't=' +encodeURIComponent(currentChatId)+ '&message=' +encodifyText(textToInsert)+ '&updateMsgId=' +msgIdInChange+ '&f=json&aimsid=' +encodeURIComponent(myToken),
            'method': 'POST',
            'mode': 'cors',
            'credentials': 'omit'
        });
    };
    
    await changeMessageFunc();
})();

The problem is that new lines of the message in API-call are written like %0A. But this %0A breaks the bookmarklet, putting some of its code to the second line.

Addition: I've tried replacing %A0 with %25A0 which works in the bookmarklet, but fails in the browswer console. Moreover, sometimes the code deletes two symbols at the end of the message. What shall I do to make it work everywhere?


Solution

  • To make it work both in the bookmarklet and the browser console, you could use decodeURI('%250A'):

        var encodifyText = function(txt){
            var temp = [];
            var returnVal = '';
            temp = txt.split('\n');
            for (i=0; i<temp.length; i++){
                returnVal += encodeURIComponent(txt.split('\n')[i]) + decodeURI('%250A');
            }
            return returnVal.slice(0, returnVal.lastIndexOf(decodeURI('%250A'))); /*Delete last newline*/
        };
    

    Since %25 doesn't break the bookmarklet, decodeURI('%250A') is supposed to work as %0A.

    And in order to delete the last newline, instead of returnVal.slice(0,-3), it might be better to use returnVal.slice(0, returnVal.lastIndexOf(decodeURI('%250A'))).