diff --git a/__tests__/ExpensiMark-Markdown-test.js b/__tests__/ExpensiMark-Markdown-test.js index bb1baf1ff..896b3f189 100644 --- a/__tests__/ExpensiMark-Markdown-test.js +++ b/__tests__/ExpensiMark-Markdown-test.js @@ -23,6 +23,18 @@ test('Test multi-line bold HTML replacement', () => { expect(parser.htmlToMarkdown(testString)).toBe(replacedString); }); +test('Converts tags with font-weight 700 inline style in between to markdown bold', () => { + const input = 'This is a text with nested bold content'; + const expected = 'This is a text with *nested bold* content'; + expect(parser.htmlToMarkdown(input)).toBe(expected); +}); + +test('Does not convert tags with font-weight normal inline style to markdown bold', () => { + const input = 'This is a text with no bold content'; + const expected = 'This is a text with no bold content'; + expect(parser.htmlToMarkdown(input)).toBe(expected); +}); + test('Test italic HTML replacement', () => { const italicTestStartString = 'This is a sentence, and it has some punctuation, words, and spaces. test _ testing_ test_test_test. _ test _ _test _ ' + 'This is a sentence, and it has some punctuation, words, and spaces. test _ testing_ test_test_test. _ test _ _test _'; diff --git a/lib/ExpensiMark.ts b/lib/ExpensiMark.ts index 04735ce2a..74e76dcd6 100644 --- a/lib/ExpensiMark.ts +++ b/lib/ExpensiMark.ts @@ -546,14 +546,33 @@ export default class ExpensiMark { }, { name: 'bold', - regex: /<(b|strong)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi, - replacement: (match, tagContent, innerContent) => { - const fontWeightMatch = innerContent.match(/style="(.*?)"/); - const isFontWeightBold = fontWeightMatch - ? fontWeightMatch[1].replaceAll(/\s/g, '').includes('font-weight:bold;') || fontWeightMatch[1].replaceAll(/\s/g, '').includes('font-weight:700;') - : false; - const isBold = fontWeightMatch ? isFontWeightBold : true; - return isBold ? `*${innerContent}*` : innerContent; + regex: /<(b|strong|span)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi, + replacement: (extras, match, tagName, innerContent) => { + // To check if style attribute contains bold font-weight + const isBoldFromStyle = (style: string | null) => { + return style ? style.replace(/\s/g, '').includes('font-weight:bold;') || style.replace(/\s/g, '').includes('font-weight:700;') : false; + }; + + const updateSpacesAndWrapWithAsterisksIfBold = (content: string, isBold: boolean) => { + const trimmedContent = content.trim(); + const leadingSpace = content.startsWith(' ') ? ' ' : ''; + const trailingSpace = content.endsWith(' ') ? ' ' : ''; + return isBold ? `${leadingSpace}*${trimmedContent}*${trailingSpace}` : content; + }; + + // Determine if the outer tag is bold + const styleAttributeMatch = match.match(/style="(.*?)"/); + const isFontWeightBold = isBoldFromStyle(styleAttributeMatch ? styleAttributeMatch[1] : null); + const isBold = styleAttributeMatch ? isFontWeightBold : tagName === 'b' || tagName === 'strong'; + + // Process nested spans with potential bold style + const processedInnerContent = innerContent.replace(/])*>([\s\S]*?)<\/span>/gi, (nestedMatch, nestedContent) => { + const nestedStyleMatch = nestedMatch.match(/style="(.*?)"/); + const isNestedBold = isBoldFromStyle(nestedStyleMatch ? nestedStyleMatch[1] : null); + return updateSpacesAndWrapWithAsterisksIfBold(nestedContent, isNestedBold); + }); + + return updateSpacesAndWrapWithAsterisksIfBold(processedInnerContent, isBold); }, }, {