Consider this simple code below
When I parse the content and get the "txt" with JSON.parse(e.data).choices[0].delta.content;
then it works fine if it is plain text. However, there are some simple HTML tags in the response like <strong>
etc. which don't render as HTML in the browser.
I don't know how to render it as it is. I realize that the chunks of data, when they arrive, may not have closing HTML tags in them and may also have incomplete HTML tags, but when the stream ends, then all is well usually.
How do I ensure that the browser treats the "txt" content as HTML and not as text? The variable thisWebPath is well set and does get streamed data back in JSON
Thanks in advance
function sendMsg(msg) {
var formData = new FormData();
formData.append('msg', msg);
formData.append('user_id', USER_ID);
fetch(thisWebPath + '/send-message.php', {method: 'POST', body: formData})
.then(response => response.json())
.then(data => {
let uuid = uuidv4()
const eventSource = new EventSource(thisWebPath + `/event-stream.php?chat_history_id=${data.id}&id=${encodeURIComponent(USER_ID)}`);
appendMessage(BOT_NAME, BOT_IMG, "left", "", uuid);
const div = document.getElementById(uuid);
eventSource.onmessage = function (e) {
if (e.data == "[DONE]") {
msgerSendBtn.disabled = false;
document.getElementById("userSendButtonAV").value="Send";
var elemB = document.getElementById("userSendButtonAV");
elemB.value = "Send";
document.getElementById('userMessageAV').placeholder='Enter your message now...';
document.getElementById('userMessageAV').disabled = false;
eventSource.close();
} else {
//original code let txt = JSON.parse(e.data).choices[0].delta.content
if (isJsonString(e.data)) {
let txt = JSON.parse(e.data).choices[0].delta.content;
if (txt !== undefined) {
div.innerHTML += txt.replace(/(?:\r\n|\r|\n)/g, '<br>');
}
}
}
};
eventSource.onerror = function (e) {
var elemC = document.getElementById("userSendButtonAV");
elemC.value = "Send";
msgerSendBtn.disabled = false;
document.getElementById('userMessageAV').placeholder='Enter your message now...';
document.getElementById('userMessageAV').disabled = false;
//console.log(e);
eventSource.close();
};
})
.catch(error => console.error(error));
}
I am expecting the text to be handled like HTML
Edit: this is how I am currently adding the message
function appendMessage(name, img, side, text, id) {
// Simple solution for small apps
const msgHTML = `
<div class="msg ${side}-msg">
<!--- div class="msg-img" style="background-image: url(${img})"></div --->
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">${name}</div>
<div class="msg-info-time">${formatDate(new Date())}</div>
</div>
<div class="msg-text" id=${id}>${text}</div>
</div>
</div>
`;
if ( typeof(text) !== "undefined" && text !== null ) {
msgerChat.insertAdjacentHTML("beforeend", msgHTML);
msgerChat.scrollTop += 500;
}
}
insertAdjacentText is a function, but that is even worse... it just writes out the entire text including the html code
Edited again:
The entire new div gets inside a main tag such as
<main class="msger-chat">
</main>
And even that gets dynamically generated, along with a bunch of other stuff, which is why insertAdjacentHtml is used
How can i simply append the content using innerHtml so that the new div that starts with the following gets added at the end of the "main" element"?
<div class="msg ${side}-msg">
Yet another edit. The issue is text/event-stream content type, so obviously the browser treats it as text :-( I saw the inspect network in chrome
Even if i add a utf-8 suffix to it, the browser still treats it as text and not as html. I think this is the main issue....
You can append your HTML to innerHTML
via the +=
operator and it will be evaluated as HTML:
function getTemplate() {
return "<p style='background-color: green;'>something</p>";
}
function addTemplate(div) {
let txt = getTemplate();
div.innerHTML += txt;
}
<div id="foo"></div>
<input type="button" onclick="addTemplate(document.getElementById('foo'))" value="add">
If it does not happen like that for you, then you would need to provide a snippet where we can reproduce it.