diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 35f5848f..ac9ba167 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -2019,6 +2019,14 @@ "message": "Maximum number of characters to display in the inline summary. Set to 0 for no limit.", "description": "" }, + "prefs_OptionText_summarize_strip_formatting": { + "message": "Strip formatting", + "description": "" + }, + "prefs_OptionText_summarize_strip_formatting_Info": { + "message": "Remove HTML and Markdown formatting from the AI-generated summary, showing plain text only.", + "description": "" + }, "summarize_see_more": { "message": "See more", "description": "" diff --git a/claude-spec/05-options.md b/claude-spec/05-options.md index d8d14ef3..0c968c88 100644 --- a/claude-spec/05-options.md +++ b/claude-spec/05-options.md @@ -98,6 +98,7 @@ These are generated programmatically at the bottom of `mzta-options-default.js` | `summarize_auto` | `1` | Auto-summarize mode: `0` = disabled, `1` = manual (show "click to generate" button), `2` = automatic (generate on message open), `3` = generate on email receive (background pre-cache via `onNewMailReceived`, no UI during generation) | | `summarize_display_mode` | `'inline'` | Where to display summaries: `'inline'` = message pane banner, `'webchat'` = AI chat window. Note: `summarize_auto = 2` and `summarize_auto = 3` always use inline regardless of this setting. | | `summarize_max_display_length` | `0` | Maximum characters shown in inline summary before truncation. `0` = no limit (show full text). When set, text is truncated at a word boundary and a "See more"/"See less" toggle link is shown. | +| `summarize_strip_formatting` | `false` | Strip HTML and Markdown formatting from AI-generated summaries, showing plain text only. | | `translate` | `true` | Enable email translation | | `translate_auto` | `0` | Auto-translate mode: `0` = disabled, `1` = manual (show button), `2` = automatic (translate on message open), `3` = generate on email receive (background pre-cache via `onNewMailReceived`, no UI during generation) | | `translate_max_display_length` | `0` | Maximum characters shown in inline translation before truncation. `0` = no limit (show full text). When set, text is truncated at a word boundary and a "See more"/"See less" toggle link is shown. | @@ -117,7 +118,8 @@ The summarize settings page provides: - `'webchat'` — opens the AI chat window - Note: `summarize_auto = 2` always generates inline regardless of this setting. Context menu summarize with multiple messages always falls back to webchat. 4. **Max display length** (`summarize_max_display_length`) — number input, limits inline summary text to N characters. `0` = no limit. When truncated, a "See more"/"See less" toggle link is appended. -5. **Three editable prompts** (used by context menu summarize and webchat mode): +5. **Strip formatting** (`summarize_strip_formatting`) — checkbox, removes HTML/Markdown formatting from AI summary responses, displaying plain text only. Default: off. +6. **Three editable prompts** (used by context menu summarize and webchat mode): - Summarize instruction prompt (`prompt_summarize`) - Email template prompt (`prompt_summarize_email_template`) - Email separator prompt (`prompt_summarize_email_separator`) diff --git a/js/mzta-compose-script.js b/js/mzta-compose-script.js index 849d514c..8d178b04 100644 --- a/js/mzta-compose-script.js +++ b/js/mzta-compose-script.js @@ -1032,7 +1032,7 @@ switch (message.command) { const summaryText = document.createElement('div'); summaryText.className = 'thunderai-summary-content'; - const hasHtml = !!summaryData.summary_html; + const hasHtml = !!summaryData.summary_html && !summaryData.stripFormatting; function setSummaryHtml(element, html) { element.textContent = ''; diff --git a/mzta-background.js b/mzta-background.js index 7a4b0a27..b4a66bc7 100644 --- a/mzta-background.js +++ b/mzta-background.js @@ -223,7 +223,7 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => { async function _initSummary() { try { let tabId = sender.tab.id; - let prefs = await browser.storage.sync.get({ summarize: prefs_default.summarize, summarize_auto: prefs_default.summarize_auto, summarize_display_mode: prefs_default.summarize_display_mode, summarize_max_display_length: prefs_default.summarize_max_display_length }); + let prefs = await browser.storage.sync.get({ summarize: prefs_default.summarize, summarize_auto: prefs_default.summarize_auto, summarize_display_mode: prefs_default.summarize_display_mode, summarize_max_display_length: prefs_default.summarize_max_display_length, summarize_strip_formatting: prefs_default.summarize_strip_formatting }); if (!prefs.summarize) return; @@ -233,7 +233,7 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => { // Always show cached summary if available, regardless of summarize_auto let cachedSummary = await summaryStore.loadSummary(message.headerMessageId); if (cachedSummary && !cachedSummary.error) { - browser.tabs.sendMessage(tabId, { command: "showSummary", data: { ...cachedSummary, maxDisplayLength: prefs.summarize_max_display_length } }); + browser.tabs.sendMessage(tabId, { command: "showSummary", data: { ...cachedSummary, maxDisplayLength: prefs.summarize_max_display_length, stripFormatting: prefs.summarize_strip_formatting } }); return; } @@ -312,12 +312,13 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => { }; await summaryStore.saveSummary(summaryData, msg.headerMessageId); let prefs_summary = await browser.storage.sync.get({ - summarize_max_display_length: prefs_default.summarize_max_display_length + summarize_max_display_length: prefs_default.summarize_max_display_length, + summarize_strip_formatting: prefs_default.summarize_strip_formatting }); try { browser.tabs.sendMessage(msg.tabId, { command: "showSummary", - data: { ...summaryData, maxDisplayLength: prefs_summary.summarize_max_display_length } + data: { ...summaryData, maxDisplayLength: prefs_summary.summarize_max_display_length, stripFormatting: prefs_summary.summarize_strip_formatting } }); } catch (e) { taLog.error("Error sending showSummary to tab: " + e); @@ -586,12 +587,13 @@ async function _generateSummaryForMessage(headerMessageId, tabId = null, options do_debug: prefs_default.do_debug, default_chatgpt_lang: prefs_default.default_chatgpt_lang, summarize_max_display_length: prefs_default.summarize_max_display_length, + summarize_strip_formatting: prefs_default.summarize_strip_formatting, ...getDynamicSettingsDefaults(['use_specific_integration', 'connection_type']) }); let cachedSummary = await summaryStore.loadSummary(headerMessageId); if (cachedSummary && !cachedSummary.error) { - if (tabId) browser.tabs.sendMessage(tabId, { command: "showSummary", data: { ...cachedSummary, maxDisplayLength: prefs.summarize_max_display_length } }); + if (tabId) browser.tabs.sendMessage(tabId, { command: "showSummary", data: { ...cachedSummary, maxDisplayLength: prefs.summarize_max_display_length, stripFormatting: prefs.summarize_strip_formatting } }); return; } @@ -652,7 +654,7 @@ async function _generateSummaryForMessage(headerMessageId, tabId = null, options headerMessageId: headerMessageId }; await summaryStore.saveSummary(summaryData, headerMessageId); - if (tabId) browser.tabs.sendMessage(tabId, { command: "showSummary", data: { ...summaryData, maxDisplayLength: prefs.summarize_max_display_length } }); + if (tabId) browser.tabs.sendMessage(tabId, { command: "showSummary", data: { ...summaryData, maxDisplayLength: prefs.summarize_max_display_length, stripFormatting: prefs.summarize_strip_formatting } }); taWorkingStatus.stopWorking(); } catch (error) { diff --git a/options/mzta-options-default.js b/options/mzta-options-default.js index e1f2eddb..7c176f5a 100644 --- a/options/mzta-options-default.js +++ b/options/mzta-options-default.js @@ -142,6 +142,7 @@ export const prefs_default = { summarize_auto: 1, // 0: disabled, 1: manual button, 2: automatic on message open, 3: generate on email receive summarize_display_mode: 'inline', // 'inline' or 'webchat' summarize_max_display_length: 0, // 0 = no limit, otherwise max chars shown inline + summarize_strip_formatting: false, // strip HTML/markdown formatting from AI summary translate: true, translate_auto: 0, // 0: disabled, 1: manual button, 2: automatic on message open, 3: generate on email receive translate_max_display_length: 0, // 0 = no limit, otherwise max chars shown inline diff --git a/pages/summarize/mzta-summarize.html b/pages/summarize/mzta-summarize.html index f5f369c3..6ddfce9b 100644 --- a/pages/summarize/mzta-summarize.html +++ b/pages/summarize/mzta-summarize.html @@ -61,6 +61,15 @@ + + __MSG_prefs_OptionText_summarize_strip_formatting__ + + + +