15193

$4000 reward
Set diamond
Variant ic_swe

Title

[HOLD for payment 2023-04-20] [$4000] Using a header (#) and a space or bold (*), then adding a code block results in the code block being bolded for a moment

Description

If you haven’t already, check out our [contributing guidelines](https://github.com/Expensify/ReactNativeChat/blob/main/contributingGuides/CONTRIBUTING.md) for onboarding and email contributors@expensify.com to request to join our Slack channel!
___

## Action Performed:

1. Open a chat
2. Start a message with # then a space
3. Add a code block using three backticks

You should see the code block go bold, then normal.

## Expected Result:
A code block should not show bold text.

## Actual Result:
Bold text appears temporarily, then reverts to normal text.

## Workaround:
unknown

## Platforms:
<!---
Check off any platforms that are affected by this issue
--->
Which of our officially supported platforms is this issue occurring on?
- [x] Android / native
- [x] Android / Chrome
- [ ] iOS / native
- [ ] iOS / Safari
- [x] MacOS / Chrome / Safari
- [x] MacOS / Desktop

**Version Number:** 1.2.72-0
**Reproducible in staging?:** y
**Reproducible in production?:** y
**If this was caught during regression testing, add the test name, ID and link from TestRail:**
**Email or phone of affected tester (no customers):**
**Logs:** https://stackoverflow.com/c/expensify/questions/4856
**Notes/Photos/Videos:** 

https://user-images.githubusercontent.com/43996225/219246458-0b133e30-c65b-49bf-a7c4-d631f67d62c1.mov


https://user-images.githubusercontent.com/43996225/219246502-d75faa2f-fe7c-4105-bc62-bedbc19de6d6.mp4


**Expensify/Expensify Issue URL:**
**Issue reported by:** @gadhiyamanan 
**Slack conversation:** https://expensify.slack.com/archives/C049HHMV9SM/p1672998135151449

[View all open jobs on GitHub](https://github.com/Expensify/App/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22)

<details><summary>Upwork Automation - Do Not Edit</summary>
    <ul>
        <li>Upwork Job URL: https://www.upwork.com/jobs/~014c5422ceeae647ae</li>
        <li>Upwork Job ID: 1626059997054926848</li>
        <li>Last Price Increase: 2023-03-13</li>
    </ul>
</details>

CLI Command

bun src/index.ts --dataset v2 --agent <YOUR_AGENT> --task 15193
test.py
import os
import sys
import uuid

from utils.online_guard import install_online_guard_sync
from utils.trace_cleaner import trace_cleaner

base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, base_path)
from playwright.sync_api import expect, sync_playwright

NEWDOT_URL = "https://dev.new.expensify.com:8082/"
EMAIL_A = "expensify87+15193E@gmail.com"
EMAIL_B = "expensify87+12@gmail.com"


def new_dot_signup(page, email):
    page.locator('input[type="email"]').fill(email)
    page.wait_for_timeout(2000)
    page.get_by_role("button", name="Continue").nth(0).click()
    page.get_by_role("button", name="Join").nth(0).click()
    page.get_by_label("Track and budget expenses").click()
    page.get_by_role("textbox", name="First name").fill("Test")
    page.get_by_role("textbox", name="Last name").click()
    page.get_by_role("textbox", name="Last name").fill("Bud")
    page.get_by_role("button", name="Continue").click()


def test_issue_15193(pytestconfig):
    trace_enabled = pytestconfig.getoption("--user-tool-trace")
    with sync_playwright() as p:
        browser = p.chromium.launch(
            proxy={"server": "http://localhost:8080"},
            headless=False,
            args=[
                "--no-sandbox",
                "--disable-dev-shm-usage",
                "--ignore-certificate-errors",
                "--disable-web-security",
                "--disable-features=IsolateOrigins,site-per-process",
            ],
            slow_mo=500,
            channel="chromium",
        )
        context = browser.new_context(ignore_https_errors=True)

        # Start tracing immediately after context creation if enabled
        if trace_enabled:
            context.tracing.start(screenshots=True, snapshots=True, sources=True)

        try:
            page = context.new_page()
            install_online_guard_sync(context, page)  # Installed online guard
            page.goto(NEWDOT_URL, timeout=60000)
            new_dot_signup(page, EMAIL_A)
            page.wait_for_timeout(2000)
            page.get_by_label("Start chat (Floating action)").click()
            page.get_by_text("Start chat").click()
            page.get_by_test_id("selection-list-text-input").fill(EMAIL_B)
            page.get_by_label(EMAIL_B).click()
            page.get_by_role("textbox").click()
            page.get_by_role("textbox").fill("# ```\n\ntest\n\n```")
            context.set_offline(True)
            page.get_by_role("button", name="Send").click()
            report_id = page.url.split("/r/")[-1]
            message = (
                page.get_by_test_id(f"report-screen-{report_id}")
                .get_by_test_id("pre")
                .get_by_text("test")
            )
            expect(message).to_have_css("font-weight", "400", timeout=2000)
        finally:
            if trace_enabled:
                trace_path = f"/app/expensify/user_tool/output_{uuid.uuid4().hex}.zip"
                os.makedirs(os.path.dirname(trace_path), exist_ok=True)
                context.tracing.stop(path=trace_path)
                trace_cleaner(trace_path)
            context.close()  # Ensuring context is closed before browser
            browser.close()
bug_reintroduce.patch
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 78ebdd92751..0509a26e042 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -4188,6 +4188,17 @@ function getPolicyDescriptionText(policy: OnyxEntry<Policy>): string {
     return Parser.htmlToText(policy.description);
 }
 
+function makeInnerTextBold(text: string) {
+    const htmlTagRegex = /<([^>]+)>(.*?)<\/\1>/g;
+    const textWithoutHash = text.replace(/^#+\s/, '');
+    const modifiedText = textWithoutHash.replace(htmlTagRegex, (_, tag, innerText) => {
+        return `<${tag}><b>${innerText}</b></${tag}>`;
+    });
+
+    return modifiedText;
+}
+
+
 function buildOptimisticAddCommentReportAction(
     text?: string,
     file?: FileObject,
@@ -4199,7 +4210,11 @@ function buildOptimisticAddCommentReportAction(
     const commentText = getParsedComment(text ?? '', {shouldEscapeText, reportID});
     const attachmentHtml = getUploadingAttachmentHtml(file);
 
-    const htmlForNewComment = `${commentText}${commentText && attachmentHtml ? '<br /><br />' : ''}${attachmentHtml}`;
+    let htmlForNewComment = `${commentText}${commentText && attachmentHtml ? '<br /><br />' : ''}${attachmentHtml}`;    
+    // If text starts with any number of # and a space, make the text inside the html tags bold
+    if (/^#+\s/.test(htmlForNewComment)) {
+        htmlForNewComment = makeInnerTextBold(htmlForNewComment)
+    }
     const textForNewComment = Parser.htmlToText(htmlForNewComment);
 
     const isAttachmentOnly = file && !text;