diff --git a/api_webchat/messagesArea.js b/api_webchat/messagesArea.js index 8e0b0832..2ecf0572 100644 --- a/api_webchat/messagesArea.js +++ b/api_webchat/messagesArea.js @@ -268,15 +268,16 @@ class MessagesArea extends HTMLElement { const messageElement = document.createElement('div'); messageElement.classList.add('message', type); // Replace \n with
for correct HTML display - messageElement.textContent = messageText; - // Replace \n with
elements for correct HTML display - messageElement.innerHTML = ''; - messageText.split('\n').forEach((line, idx, arr) => { - messageElement.appendChild(document.createTextNode(line)); - if (idx < arr.length - 1) { - messageElement.appendChild(document.createElement('br')); - } - }); + messageElement.appendChild(htmlStringToFragment(messageText)); + // messageElement.textContent = messageText; + // // Replace \n with
elements for correct HTML display + // messageElement.innerHTML = ''; + // messageText.split('\n').forEach((line, idx, arr) => { + // messageElement.appendChild(document.createTextNode(line)); + // if (idx < arr.length - 1) { + // messageElement.appendChild(document.createElement('br')); + // } + // }); this.messages.appendChild(messageElement); this.scrollToBottom(); } @@ -337,10 +338,10 @@ class MessagesArea extends HTMLElement { if(promptData.mailMessageId == -1) { // we are using the reply from the compose window! promptData.action = "2"; // replace text } - let finalText = fullTextHTMLAtAssignment; + let finalText = removeAloneBRs(fullTextHTMLAtAssignment); const selectedHTML = this.getCurrentSelectionHTML(); if(selectedHTML != "") { - finalText = selectedHTML; + finalText = removeAloneBRs(selectedHTML); } switch(promptData.action) { @@ -521,9 +522,11 @@ class MessagesArea extends HTMLElement { // Convert Markdown to DOM nodes using the markdown-it library const md = window.markdownit(); - const html = md.render(fullText); + const html = convertNewlinesToBr(md.render(fullText)); this.fullTextHTML += html; + + // console.log(">>>>>>>>>>>>>>>> flushAccumulatingMessage this.fullTextHTML: " + this.fullTextHTML); // Create a new DOM parser const parser = new DOMParser(); @@ -557,4 +560,46 @@ class MessagesArea extends HTMLElement { } -customElements.define('messages-area', MessagesArea); \ No newline at end of file +customElements.define('messages-area', MessagesArea); + + +function htmlStringToFragment(htmlString) { +// console.log(">>>>>>>>>>>>>>>> htmlStringToFragment htmlString: " + htmlString); + const normalizedHtml = htmlString.replace(/\n/g, '
'); +// console.log(">>>>>>>>>>>>>>>> htmlStringToFragment normalizedHtml: " + normalizedHtml); + const parser = new DOMParser(); + const doc = parser.parseFromString(normalizedHtml, 'text/html'); + const fragment = document.createDocumentFragment(); + Array.from(doc.body.childNodes).forEach(node => fragment.appendChild(node)); + return fragment; +} + +function convertNewlinesToBr(text) { + return text.replace(/\n/g, '
'); +} + +function removeAloneBRs(htmlString) { + const parser = new DOMParser(); + const doc = parser.parseFromString(htmlString, 'text/html'); + + const brElements = Array.from(doc.querySelectorAll('br')); + + brElements.forEach(br => { + let current = br; + let isInsideP = false; + + while (current.parentElement) { + if (current.parentElement.tagName.toLowerCase() === 'p') { + isInsideP = true; + break; + } + current = current.parentElement; + } + + if (!isInsideP) { + br.remove(); + } + }); + + return doc.body.innerHTML; +} \ No newline at end of file diff --git a/js/mzta-menus.js b/js/mzta-menus.js index f22bc5ea..01e94a8d 100644 --- a/js/mzta-menus.js +++ b/js/mzta-menus.js @@ -19,7 +19,7 @@ // Some original methods are derived from https://github.com/ali-raheem/Aify/blob/cfadf52f576b7be3720b5b73af7c8d3129c054da/plugin/html/actions.js import { getPrompts } from './mzta-prompts.js'; -import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject, getTagsList, extractJsonObject } from './mzta-utils.js' +import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject, getTagsList, extractJsonObject, convertNewlinesToBr } from './mzta-utils.js' import { taPromptUtils } from './mzta-utils-prompt.js'; import { taLogger } from './mzta-logger.js'; import { placeholdersUtils } from './mzta-placeholders.js'; @@ -81,12 +81,12 @@ export class mzta_Menus { const getMailBody = async (tabs, do_autoselect = false) => { //const tabs = await browser.tabs.query({ active: true, currentWindow: true }); return {tabId: tabs[0].id, - selection: await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedText" }), - selection_html: await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedHtml" }), - text: await browser.tabs.sendMessage(tabs[0].id, { command: "getTextOnly" }), - html: await browser.tabs.sendMessage(tabs[0].id, { command: "getFullHtml" }), - only_typed_text: await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyTypedText", do_autoselect: do_autoselect }), - only_quoted_text: await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyQuotedText" }) + selection: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedText" })), + selection_html: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedHtml" })), + text: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getTextOnly" })), + html: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getFullHtml" })), + only_typed_text: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyTypedText", do_autoselect: do_autoselect })), + only_quoted_text: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyQuotedText" })) }; }; @@ -94,7 +94,7 @@ export class mzta_Menus { taWorkingStatus.startWorking(); const tabs = await browser.tabs.query({ active: true, currentWindow: true }); const msg_text = await getMailBody(tabs, placeholdersUtils.hasPlaceholder(curr_prompt.text,'mail_typed_text')); - + // console.log(">>>>>>>>>>>>> msg_text: " + JSON.stringify(msg_text)); //check if a selection is needed if(String(curr_prompt.need_selected) == "1" && (msg_text.selection==='')){ //A selection is needed, but nothing is selected! diff --git a/js/mzta-utils.js b/js/mzta-utils.js index da7c6b94..48b68a4c 100644 --- a/js/mzta-utils.js +++ b/js/mzta-utils.js @@ -192,13 +192,21 @@ export function sanitizeHtml(input) { export function stripHtmlKeepLines(htmlString) { // Replaces

tags with a newline at the beginning // and removes all other HTML tags - return htmlString + return convertBrToNewlines(htmlString) .replace(/

/gi, '') // removes

tags .replace(/<\/p>/gi, '\n') // replaces

tags with newline .replace(/<[^>]*>/g, '') // removes any other HTML tags .trim(); // removes leading/trailing whitespace } +export function convertNewlinesToBr(text) { + return text.replace(/\n/g, '
'); +} + +function convertBrToNewlines(html) { + return html.replace(//gi, '\n'); +} + // This method is used to convert the model string id used in the URL // to the model string used in the webpage export function getGPTWebModelString(model) {