From 2b365a87365dc94a14034a19b400120fc551ae0a Mon Sep 17 00:00:00 2001 From: Aldimensch Date: Sat, 21 Jun 2025 04:56:45 +0200 Subject: [PATCH 1/9] Add chat quote emphasis color and weight settings to UI --- common/types/ui.ts | 8 ++++++ web/pages/Chat/components/Message.css | 9 ++++++- web/pages/Chat/components/Message.tsx | 38 ++++++++++++++++++++------- web/pages/Settings/UISettings.tsx | 26 ++++++++++++++++++ web/store/user.ts | 3 +++ web/variables.css | 2 ++ 6 files changed, 76 insertions(+), 10 deletions(-) diff --git a/common/types/ui.ts b/common/types/ui.ts index e7be7c367..c7949b326 100644 --- a/common/types/ui.ts +++ b/common/types/ui.ts @@ -40,6 +40,8 @@ export type CustomUI = { chatTextColor: string chatEmphasisColor: string chatQuoteColor: string + chatQuoteEmphasisColor: string + chatQuoteEmphasisWeight: string } export type MessageOption = @@ -93,6 +95,8 @@ const customUiGuard = { chatTextColor: 'string', chatEmphasisColor: 'string', chatQuoteColor: 'string', + chatQuoteEmphasisColor: 'string', + chatQuoteEmphasisWeight: 'string', } as const export const uiGuard = { @@ -142,6 +146,8 @@ export const defaultUIsettings: UISettings = { chatTextColor: '--text-800', chatEmphasisColor: '--text-600', chatQuoteColor: '--text-800', + chatQuoteEmphasisColor: '--text-800', + chatQuoteEmphasisWeight: 'unset', }, dark: { @@ -150,6 +156,8 @@ export const defaultUIsettings: UISettings = { chatTextColor: '--text-800', chatEmphasisColor: '--text-600', chatQuoteColor: '--text-800', + chatQuoteEmphasisColor: '--text-800', + chatQuoteEmphasisWeight: 'unset', }, msgOptsInline: { diff --git a/web/pages/Chat/components/Message.css b/web/pages/Chat/components/Message.css index 41cd2765f..37d6be2db 100644 --- a/web/pages/Chat/components/Message.css +++ b/web/pages/Chat/components/Message.css @@ -13,6 +13,13 @@ em { color: var(--text-quote-color); } +qem { /* quote emphasis; "I like *that*" */ + color: var(--text-800); + color: var(--text-quote-emphasis-color); + font-style: italic; + font-weight: var(--text-quote-emphasis-weight); +} + .rendered-markdown img { display: inline-block; /* markdown images are expected to be inline-block */ } @@ -20,7 +27,7 @@ em { .rendered-markdown q::before, .rendered-markdown q::after { content: ''; - border: none; /* necessary for th escreenshot feature or we see weird white borders */ + border: none; /* necessary for the screenshot feature or we see weird white borders */ } .rendered-markdown p:not(:last-child) { diff --git a/web/pages/Chat/components/Message.tsx b/web/pages/Chat/components/Message.tsx index d820ce557..df559cfa7 100644 --- a/web/pages/Chat/components/Message.tsx +++ b/web/pages/Chat/components/Message.tsx @@ -886,21 +886,30 @@ function renderMessage(ctx: ContextState, text: string, isUser: boolean, adapter // it also encodes the ampersand, which results in them actually being rendered as `&nbsp;` // https://github.com/showdownjs/showdown/issues/669 + // we sanizize user input to prevent XSS attacks, allowing only following HTML Tags see ALLOWED_TAGS below const html = Purify.sanitize( wrapWithQuoteElement( markdown.makeHtml(parseMessage(text, ctx, isUser, adapter)).replace(/&nbsp;/g, ' ') - ) + ), {ALLOWED_TAGS: ['q', 'qem', 'em', 'strong', 'b', 'i', 'br', 'p', 'span', 'div', 'code', 'pre']} ) return html } +/** Markup beautification. Lets us control color of diffrent HTML tags, expands on the markdown functionality + * Especially useful for quotes, which are wrapped in tags + * and emphasis, which is wrapped in tags. + */ function wrapWithQuoteElement(str: string) { + // Replace all non-regular double quotes with double regular quotes + // Unicode double quote characters: https://en.wikipedia.org/wiki/Quotation_mark#Unicode_code_point_table + str = str.replace(/[\u201C\u201D\u201E\u201F]/g,'"') + return str.replace( // we first match code blocks AND html tags // to ensure we do NOTHING to what's inside them - // then we match "regular quotes" and“'pretty quotes” as capture group - /<[\s\S]*?>|```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`|(\".+?\")|(\u201C.+?\u201D)/gm, + // then we match "regular quotes" as capture group + /<[\s\S]*?>|```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`|(\".+?\")/gm, wrapCaptureGroups ) } @@ -908,16 +917,27 @@ function wrapWithQuoteElement(str: string) { /** For use as a String#replace(str, cb) callback */ function wrapCaptureGroups( match: string, - regularQuoted?: string /** regex capture group 1 */, - curlyQuoted?: string /** regex capture group 2 */ + regularQuoted?: string ) { if (regularQuoted) { + regularQuoted = regularQuoted.replace( + /([\s\S]*?)<\/em>|<[\s\S]*?>|```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`/gm, + wrapCaptureGroupEmphasis + ) return '"' + regularQuoted.replace(/\"/g, '') + '"' - } else if (curlyQuoted) { - return '“' + curlyQuoted.replace(/\u201C|\u201D/g, '') + '”' - } else { - return match } + return match + } + +/** Replaces all tags within a tag with tags*/ +function wrapCaptureGroupEmphasis( + match: string, + emphasisQuote?: string +) { + if (emphasisQuote) { + return '' + emphasisQuote.replace(/\"/g, '') + '' + } + return match } function sendAction(_send: MessageProps['sendMessage'], action: AppSchema.ChatAction) { diff --git a/web/pages/Settings/UISettings.tsx b/web/pages/Settings/UISettings.tsx index 1f69dd01f..3d959fcb1 100644 --- a/web/pages/Settings/UISettings.tsx +++ b/web/pages/Settings/UISettings.tsx @@ -368,6 +368,32 @@ const UISettings: Component<{}> = () => { value={state.current.chatQuoteColor || '--text-800'} /> + userStore.saveCustomUI({ chatQuoteEmphasisColor: 'text-800' })}> + Reset to Default + + } + onInput={(color) => tryCustomUI({ chatQuoteEmphasisColor: color })} + onChange={(color) => userStore.saveCustomUI({ chatQuoteEmphasisColor: color })} + value={state.current.chatQuoteEmphasisColor || '--text-800'} + /> + + Date: Sat, 21 Jun 2025 17:24:57 +0200 Subject: [PATCH 2/9] Modified the UI Settings exmple Text to show the new feature. Added comments. Removed unneccesery RegEx --- web/pages/Chat/components/Message.tsx | 26 +++++++++++++++++++------- web/pages/Settings/UISettings.tsx | 2 +- web/store/user.ts | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/web/pages/Chat/components/Message.tsx b/web/pages/Chat/components/Message.tsx index df559cfa7..35ab4b20a 100644 --- a/web/pages/Chat/components/Message.tsx +++ b/web/pages/Chat/components/Message.tsx @@ -906,22 +906,34 @@ function wrapWithQuoteElement(str: string) { str = str.replace(/[\u201C\u201D\u201E\u201F]/g,'"') return str.replace( - // we first match code blocks AND html tags - // to ensure we do NOTHING to what's inside them - // then we match "regular quotes" as capture group + /* + Regex magic explained: + <[\s\S]*?> - skip all HTML tags eg. + ```[\s\S]*?``` - skip all code blocks eg.
/``` markdown transform 
 to ```
+    ``[\s\S]*?``    - skip all inline code eg. /`` markdown transform  to `` | this is a non standard markup 
+    `[\s\S]*?`      - skip all inline code eg. /` markdown transform  to `
+
+    (\".+?\")       - capture all regular double quotes, which are not part of HTML tags or code blocks
+    All captured groups are passed to the wrapCaptureGroupQuotes function
+    */
     /<[\s\S]*?>|```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`|(\".+?\")/gm,
-    wrapCaptureGroups
+    wrapCaptureGroupQuotes
   )
 }
 
-/** For use as a String#replace(str, cb) callback */
-function wrapCaptureGroups(
+/** Processes capture group from above*/
+function wrapCaptureGroupQuotes(
   match: string,
   regularQuoted?: string
 ) {
   if (regularQuoted) {
+  /*If we have a valid string then we are within a quote
+    ([\s\S]*?) - we ignore all characters between  and 
+    a valid capure will look like this: "lets have some fun"
+    we then pass the capture group to wrapCaptureGroupEmphasis function, which will replace  with 
+    */
     regularQuoted = regularQuoted.replace(
-      /([\s\S]*?)<\/em>|<[\s\S]*?>|```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`/gm,
+      /([\s\S]*?)<\/em>/gm,
       wrapCaptureGroupEmphasis
     )
     return '"' + regularQuoted.replace(/\"/g, '') + '"'
diff --git a/web/pages/Settings/UISettings.tsx b/web/pages/Settings/UISettings.tsx
index 3d959fcb1..722bc1a87 100644
--- a/web/pages/Settings/UISettings.tsx
+++ b/web/pages/Settings/UISettings.tsx
@@ -445,7 +445,7 @@ const UISettings: Component<{}> = () => {
               editing={false}
               msg={toUserMsg(
                 state.profile!,
-                '*I wave back* Hi {{char}}!\nFancy meeting you here! I heard someone say "The weather is great today!"',
+                '*I wave back* Hi {{char}}!\nFancy meeting you here! I heard someone say "The weather is great today!"\n"How abot we have some *fun* today?"',
                 { _id: '2' }
               )}
               onRemove={noop}
diff --git a/web/store/user.ts b/web/store/user.ts
index 0fb8428cc..aa3fbdfd7 100644
--- a/web/store/user.ts
+++ b/web/store/user.ts
@@ -1011,7 +1011,7 @@ async function updateTheme(ui: UI.UISettings) {
   setRootVariable('text-quote-emphasis-color', getSettingColor(mode.chatQuoteEmphasisColor || 'text-800'))
   setRootVariable('bot-background', getSettingColor(mode.botBackground || 'bg-800'))
   
-  setRootVariable('text-quote-emphasis-weight', mode.chatQuoteEmphasisWeight)
+  setRootVariable('text-quote-emphasis-weight', mode.chatQuoteEmphasisWeight) /*Controls the thickness of the font. default: 'unset'*/
   root.style.setProperty(`--sitewide-font`, fontFaces[ui.font])
 }
 

From 22d1a522e4564aa7cf66c20482850549fab2fcec Mon Sep 17 00:00:00 2001
From: Aldimensch 
Date: Sun, 22 Jun 2025 10:20:07 +0200
Subject: [PATCH 3/9] Fixes odd prettier issue

---
 web/pages/Chat/components/Message.css | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/web/pages/Chat/components/Message.css b/web/pages/Chat/components/Message.css
index 37d6be2db..e0818cae0 100644
--- a/web/pages/Chat/components/Message.css
+++ b/web/pages/Chat/components/Message.css
@@ -13,7 +13,8 @@ em {
   color: var(--text-quote-color);
 }
 
-qem { /* quote emphasis; "I like *that*" */
+qem {
+  /* quote emphasis; "I like *that*" */
   color: var(--text-800);
   color: var(--text-quote-emphasis-color);
   font-style: italic;

From d1d7c7dc307e413118019201c75daedba13cedf2 Mon Sep 17 00:00:00 2001
From: Aldimensch 
Date: Sun, 22 Jun 2025 10:43:09 +0200
Subject: [PATCH 4/9] Who is formmating this so badly?

---
 web/pages/Chat/components/Message.tsx | 26 ++++++++++----------------
 web/pages/Settings/UISettings.tsx     | 12 ++++++++----
 web/store/user.ts                     | 12 +++++++++---
 3 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/web/pages/Chat/components/Message.tsx b/web/pages/Chat/components/Message.tsx
index 35ab4b20a..e5f5cdf34 100644
--- a/web/pages/Chat/components/Message.tsx
+++ b/web/pages/Chat/components/Message.tsx
@@ -890,7 +890,10 @@ function renderMessage(ctx: ContextState, text: string, isUser: boolean, adapter
   const html = Purify.sanitize(
     wrapWithQuoteElement(
       markdown.makeHtml(parseMessage(text, ctx, isUser, adapter)).replace(/&nbsp;/g, ' ')
-    ), {ALLOWED_TAGS: ['q', 'qem', 'em', 'strong', 'b', 'i', 'br', 'p', 'span', 'div', 'code', 'pre']}
+    ),
+    {
+      ALLOWED_TAGS: ['q', 'qem', 'em', 'strong', 'b', 'i', 'br', 'p', 'span', 'div', 'code', 'pre'],
+    }
   )
 
   return html
@@ -903,7 +906,7 @@ function renderMessage(ctx: ContextState, text: string, isUser: boolean, adapter
 function wrapWithQuoteElement(str: string) {
   // Replace all non-regular double quotes with double regular quotes
   // Unicode double quote characters: https://en.wikipedia.org/wiki/Quotation_mark#Unicode_code_point_table
-  str = str.replace(/[\u201C\u201D\u201E\u201F]/g,'"')
+  str = str.replace(/[\u201C\u201D\u201E\u201F]/g, '"')
 
   return str.replace(
     /*
@@ -922,30 +925,21 @@ function wrapWithQuoteElement(str: string) {
 }
 
 /** Processes capture group from above*/
-function wrapCaptureGroupQuotes(
-  match: string,
-  regularQuoted?: string
-) {
+function wrapCaptureGroupQuotes(match: string, regularQuoted?: string) {
   if (regularQuoted) {
-  /*If we have a valid string then we are within a quote
+    /*If we have a valid string then we are within a quote
     ([\s\S]*?) - we ignore all characters between  and 
     a valid capure will look like this: "lets have some fun"
     we then pass the capture group to wrapCaptureGroupEmphasis function, which will replace  with 
     */
-    regularQuoted = regularQuoted.replace(
-      /([\s\S]*?)<\/em>/gm,
-      wrapCaptureGroupEmphasis
-    )
+    regularQuoted = regularQuoted.replace(/([\s\S]*?)<\/em>/gm, wrapCaptureGroupEmphasis)
     return '"' + regularQuoted.replace(/\"/g, '') + '"'
   }
   return match
-  }
+}
 
 /** Replaces all  tags within a  tag with  tags*/
-function wrapCaptureGroupEmphasis(
-  match: string,
-  emphasisQuote?: string
-) {
+function wrapCaptureGroupEmphasis(match: string, emphasisQuote?: string) {
   if (emphasisQuote) {
     return '' + emphasisQuote.replace(/\"/g, '') + ''
   }
diff --git a/web/pages/Settings/UISettings.tsx b/web/pages/Settings/UISettings.tsx
index 722bc1a87..beeb174df 100644
--- a/web/pages/Settings/UISettings.tsx
+++ b/web/pages/Settings/UISettings.tsx
@@ -372,7 +372,10 @@ const UISettings: Component<{}> = () => {
         label="Chat Quote Emphasis Color"
         fieldName="chatQuoteEmphasisColor"
         helperText={
-           userStore.saveCustomUI({ chatQuoteEmphasisColor: 'text-800' })}>
+           userStore.saveCustomUI({ chatQuoteEmphasisColor: 'text-800' })}
+          >
             Reset to Default
           
         }
@@ -380,7 +383,7 @@ const UISettings: Component<{}> = () => {
         onChange={(color) => userStore.saveCustomUI({ chatQuoteEmphasisColor: color })}
         value={state.current.chatQuoteEmphasisColor || '--text-800'}
       />
-      
+
       
Date: Sun, 29 Jun 2025 15:50:12 +0800
Subject: [PATCH 6/9] Disable allowed_tags

---
 web/pages/Chat/components/Message.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/web/pages/Chat/components/Message.tsx b/web/pages/Chat/components/Message.tsx
index e5f5cdf34..1349ed6ec 100644
--- a/web/pages/Chat/components/Message.tsx
+++ b/web/pages/Chat/components/Message.tsx
@@ -890,10 +890,10 @@ function renderMessage(ctx: ContextState, text: string, isUser: boolean, adapter
   const html = Purify.sanitize(
     wrapWithQuoteElement(
       markdown.makeHtml(parseMessage(text, ctx, isUser, adapter)).replace(/&nbsp;/g, ' ')
-    ),
-    {
-      ALLOWED_TAGS: ['q', 'qem', 'em', 'strong', 'b', 'i', 'br', 'p', 'span', 'div', 'code', 'pre'],
-    }
+    )
+    // {
+    //   ALLOWED_TAGS: ['q', 'qem', 'em', 'strong', 'b', 'i', 'br', 'p', 'span', 'div', 'code', 'pre'],
+    // }
   )
 
   return html

From 84ae2e9cd82b128044a81ca65d9b5dbc97fec056 Mon Sep 17 00:00:00 2001
From: agnaidev 
Date: Sun, 29 Jun 2025 15:51:50 +0800
Subject: [PATCH 7/9] neaten comments

---
 web/pages/Chat/components/Message.tsx | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/web/pages/Chat/components/Message.tsx b/web/pages/Chat/components/Message.tsx
index 1349ed6ec..d294c8cf7 100644
--- a/web/pages/Chat/components/Message.tsx
+++ b/web/pages/Chat/components/Message.tsx
@@ -899,9 +899,10 @@ function renderMessage(ctx: ContextState, text: string, isUser: boolean, adapter
   return html
 }
 
-/** Markup beautification. Lets us control color of diffrent HTML tags, expands on the markdown functionality
- *  Especially useful for quotes, which are wrapped in  tags
- *  and emphasis, which is wrapped in  tags.
+/**
+ * Markup beautification. Lets us control color of diffrent HTML tags, expands on the markdown functionality
+ * Especially useful for quotes, which are wrapped in  tags
+ * and emphasis, which is wrapped in  tags.
  */
 function wrapWithQuoteElement(str: string) {
   // Replace all non-regular double quotes with double regular quotes
@@ -924,7 +925,7 @@ function wrapWithQuoteElement(str: string) {
   )
 }
 
-/** Processes capture group from above*/
+/** Processes capture group from above */
 function wrapCaptureGroupQuotes(match: string, regularQuoted?: string) {
   if (regularQuoted) {
     /*If we have a valid string then we are within a quote
@@ -938,7 +939,7 @@ function wrapCaptureGroupQuotes(match: string, regularQuoted?: string) {
   return match
 }
 
-/** Replaces all  tags within a  tag with  tags*/
+/** Replaces all  tags within a  tag with  tags */
 function wrapCaptureGroupEmphasis(match: string, emphasisQuote?: string) {
   if (emphasisQuote) {
     return '' + emphasisQuote.replace(/\"/g, '') + ''

From 019dcf1eb726b5f670f7fd3579774dd95dd2883d Mon Sep 17 00:00:00 2001
From: Aldimensch 
Date: Mon, 30 Jun 2025 10:03:12 +0200
Subject: [PATCH 8/9] saving non-progress

---
 web/pages/Chat/components/Message.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/web/pages/Chat/components/Message.tsx b/web/pages/Chat/components/Message.tsx
index a297e923a..8f6aa7471 100644
--- a/web/pages/Chat/components/Message.tsx
+++ b/web/pages/Chat/components/Message.tsx
@@ -889,10 +889,10 @@ function renderMessage(ctx: ContextState, text: string, isUser: boolean, adapter
   const html = Purify.sanitize(
     wrapWithQuoteElement(
       markdown.makeHtml(parseMessage(text, ctx, isUser, adapter)).replace(/&nbsp;/g, ' ')
-    )
-    // {
-    //   ALLOWED_TAGS: ['q', 'qem', 'em', 'strong', 'b', 'i', 'br', 'p', 'span', 'div', 'code', 'pre'],
-    // }
+    ),
+    {
+      ADD_TAGS: ['qem'],
+    }
   )
 
   return html

From 3aca31e91635645d8b589d2eae427a020d007c27 Mon Sep 17 00:00:00 2001
From: Aldimensch 
Date: Wed, 2 Jul 2025 06:09:36 +0200
Subject: [PATCH 9/9] Progress towards more customizable Redering of Markdown
 format: - Added new  css class, with Colorpicker and Bold toggle -
 Nested assteriks are now represented by  - - Outer Asteriks are still
  - Nested asteriks are now correclty paired. - Claude found a nice way to
 wrap qoutes. Should be more efficent now.

---
 common/types/ui.ts                    |  10 +-
 web/pages/Chat/components/Message.css |   8 ++
 web/pages/Chat/components/Message.tsx | 135 +++++++++++++++++---------
 web/pages/Settings/UISettings.tsx     |  30 ++++++
 web/store/user.ts                     |   8 ++
 web/variables.css                     |   2 +
 6 files changed, 144 insertions(+), 49 deletions(-)

diff --git a/common/types/ui.ts b/common/types/ui.ts
index c7949b326..381b70444 100644
--- a/common/types/ui.ts
+++ b/common/types/ui.ts
@@ -42,6 +42,8 @@ export type CustomUI = {
   chatQuoteColor: string
   chatQuoteEmphasisColor: string
   chatQuoteEmphasisWeight: string
+  chatEmphasisEmphasisColor: string
+  chatEmphasisEmphasisWeight: string
 }
 
 export type MessageOption =
@@ -97,6 +99,8 @@ const customUiGuard = {
   chatQuoteColor: 'string',
   chatQuoteEmphasisColor: 'string',
   chatQuoteEmphasisWeight: 'string',
+  chatEmphasisEmphasisColor: 'string',
+  chatEmphasisEmphasisWeight: 'string',
 } as const
 
 export const uiGuard = {
@@ -148,6 +152,8 @@ export const defaultUIsettings: UISettings = {
     chatQuoteColor: '--text-800',
     chatQuoteEmphasisColor: '--text-800',
     chatQuoteEmphasisWeight: 'unset',
+    chatEmphasisEmphasisColor: '--text-800',
+    chatEmphasisEmphasisWeight: 'unset',
   },
 
   dark: {
@@ -157,7 +163,9 @@ export const defaultUIsettings: UISettings = {
     chatEmphasisColor: '--text-600',
     chatQuoteColor: '--text-800',
     chatQuoteEmphasisColor: '--text-800',
-    chatQuoteEmphasisWeight: 'unset',    
+    chatQuoteEmphasisWeight: 'unset',
+    chatEmphasisEmphasisColor: '--text-800',
+    chatEmphasisEmphasisWeight: 'unset',
   },
 
   msgOptsInline: {
diff --git a/web/pages/Chat/components/Message.css b/web/pages/Chat/components/Message.css
index e0818cae0..ba759559e 100644
--- a/web/pages/Chat/components/Message.css
+++ b/web/pages/Chat/components/Message.css
@@ -21,6 +21,14 @@ qem {
   font-weight: var(--text-quote-emphasis-weight);
 }
 
+eem {
+  /* emphasis emphasis; *inner* emphasis within  tags */
+  color: var(--text-800);
+  color: var(--text-emphasis-emphasis-color);
+  font-style: italic;
+  font-weight: var(--text-emphasis-emphasis-weight);
+}
+
 .rendered-markdown img {
   display: inline-block; /* markdown images are expected to be inline-block */
 }
diff --git a/web/pages/Chat/components/Message.tsx b/web/pages/Chat/components/Message.tsx
index 8f6aa7471..9cd29c05b 100644
--- a/web/pages/Chat/components/Message.tsx
+++ b/web/pages/Chat/components/Message.tsx
@@ -881,69 +881,108 @@ function retryJsonSchema(original: AppSchema.ChatMessage, split: SplitMessage) {
 }
 
 function renderMessage(ctx: ContextState, text: string, isUser: boolean, adapter?: string) {
+  // Iam getting pissed of by showdown effing up Asteriks, I just do this myself - @Aldimensch
+  // Escape single asterisks but not double asterisks
+  text = text.replace(/(? tags
- * and emphasis, which is wrapped in  tags.
- */
-function wrapWithQuoteElement(str: string) {
-  // Replace all non-regular double quotes with double regular quotes
-  // Unicode double quote characters: https://en.wikipedia.org/wiki/Quotation_mark#Unicode_code_point_table
-  str = str.replace(/[\u201C\u201D\u201E\u201F]/g, '"')
-
-  return str.replace(
-    /*
-    Regex magic explained:
-    <[\s\S]*?>      - skip all HTML tags   eg. 
-    ```[\s\S]*?```  - skip all code blocks eg. 
/``` markdown transform 
 to ```
-    ``[\s\S]*?``    - skip all inline code eg. /`` markdown transform  to `` | this is a non standard markup 
-    `[\s\S]*?`      - skip all inline code eg. /` markdown transform  to `
-
-    (\".+?\")       - capture all regular double quotes, which are not part of HTML tags or code blocks
-    All captured groups are passed to the wrapCaptureGroupQuotes function
-    */
-    /<[\s\S]*?>|```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`|(\".+?\")/gm,
-    wrapCaptureGroupQuotes
-  )
+function asterikPairing(text: string) {
+  const lines = text.split(/((?:<\/p>|<\/pre>|||<\/q>))/i);
+  let accum = '';
+  let tempLine = '';
+  for (let line of lines) {
+    if (/(?:<\/p>|<\/pre>|||<\/q>)/i.test(line)) {
+      accum += line;
+    } else {
+      tempLine = outerAsterikPairing(line);
+      accum += innerAsterikPairing(tempLine);
+    }
+  }
+  return accum;
 }
 
-/** Processes capture group from above */
-function wrapCaptureGroupQuotes(match: string, regularQuoted?: string) {
-  if (regularQuoted) {
-    /*If we have a valid string then we are within a quote
-    ([\s\S]*?) - we ignore all characters between  and 
-    a valid capure will look like this: "lets have some fun"
-    we then pass the capture group to wrapCaptureGroupEmphasis function, which will replace  with 
-    */
-    regularQuoted = regularQuoted.replace(/([\s\S]*?)<\/em>/gm, wrapCaptureGroupEmphasis)
-    return '"' + regularQuoted.replace(/\"/g, '') + '"'
+function outerAsterikPairing(line: string) {
+  // Check if the line contains any 
 or  tags, we dont mess with the content of these tags.
+  if (/<(?:pre|code)(?:\s[^>]*)?>/i.test(line)) return line
+
+  const firstAsterisk = line.indexOf('*')
+  const lastAsterisk = line.lastIndexOf('*')
+  if (firstAsterisk !== -1 && lastAsterisk !== -1 && firstAsterisk !== lastAsterisk) {
+    return line.slice(0, firstAsterisk) + '' + line.slice(firstAsterisk + 1, lastAsterisk) + '' + line.slice(lastAsterisk + 1)
   }
-  return match
+  return line
 }
 
-/** Replaces all  tags within a  tag with  tags */
-function wrapCaptureGroupEmphasis(match: string, emphasisQuote?: string) {
-  if (emphasisQuote) {
-    return '' + emphasisQuote.replace(/\"/g, '') + ''
-  }
-  return match
+function innerAsterikPairing(line: string) {
+  // Check if the line contains any 
 or  tags, we dont mess with the content of these tags.
+  if (/<(?:pre|code)(?:\s[^>]*)?>/i.test(line)) return line
+
+  // Count asterisks in the line
+  const asteriskCount = (line.match(/\*/g) || []).length
+  
+  // If odd number of asterisks, we can't properly pair them
+  if (asteriskCount % 2 !== 0) return line
+  
+  // If even number of asterisks, replace all * pairs with  tags
+  return line.replace(/\*(.*?)\*/g, '$1')
+}
+
+/**
+ * Beautifies the markup by handling custom quote and emphasis formatting in a single pass.
+ * This function replaces a series of sequential replacements with a single, more efficient
+ * regular expression. It processes:
+ * - Escaped asterisks inside `` blocks.
+ * - Double-quoted sections `"..."` into `...` tags.
+ * - Asterisk-based emphasis inside quotes into `...` tags.
+ * (Asterisk emphasis is now handled after HTML generation)
+ */
+function makeTextLookNice(str: string) {
+  // First, normalize all Unicode double quotes to standard double quotes.
+  // Unicode double quote characters: https://en.wikipedia.org/wiki/Quotation_mark#Unicode_code_point_table
+  const normalizedStr = str.replace(/[\u201C\u201D\u201E\u201F]/g, '"')
+
+  // This regex handles two cases, in order of priority:
+  // 1. `...` blocks, 2. quoted sections `"..."`
+  return normalizedStr.replace(
+    /([\s\S]*?<\/code>)|(".*?")/gm,
+    (match, codeBlock, quoted) => {
+      // Case 1: A code block was matched.
+      if (codeBlock) {
+        // Un-escape any `\*` back to `*` inside a code block.
+        return codeBlock.replace(/\\\*/g, '*')
+      }
+
+      // Case 2: A quoted string was matched.
+      if (quoted) {
+        // Find any asterisk-wrapped text *inside* the quote and
+        // convert it to a custom emphasis tag ``.
+        const innerContent = quoted.slice(1, -1).replace(/\*(.*?)\*/g, '$1')
+        return `"${innerContent}"`
+      }
+
+      return match
+    }
+  )
 }
 
 function sendAction(_send: MessageProps['sendMessage'], action: AppSchema.ChatAction) {
diff --git a/web/pages/Settings/UISettings.tsx b/web/pages/Settings/UISettings.tsx
index b1a7efd9a..59754d6a9 100644
--- a/web/pages/Settings/UISettings.tsx
+++ b/web/pages/Settings/UISettings.tsx
@@ -398,6 +398,36 @@ const UISettings: Component<{}> = () => {
         value={state.current.chatQuoteEmphasisWeight || 'unset'}
       />
 
+       userStore.saveCustomUI({ chatEmphasisEmphasisColor: 'text-800' })}
+          >
+            Reset to Default
+          
+        }
+        onInput={(color) => tryCustomUI({ chatEmphasisEmphasisColor: color })}
+        onChange={(color) => userStore.saveCustomUI({ chatEmphasisEmphasisColor: color })}
+        value={state.current.chatEmphasisEmphasisColor || '--text-800'}
+      />
+
+