diff --git a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx index 0ea56522f74cf..d03eea02beb40 100755 --- a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx +++ b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx @@ -1,12 +1,11 @@ import React, {useMemo} from 'react'; import type {TextProps} from 'react-native'; import {HTMLContentModel, HTMLElementModel, RenderHTMLConfigProvider, TRenderEngineProvider} from 'react-native-render-html'; -import type {TNode} from 'react-native-render-html'; import useThemeStyles from '@hooks/useThemeStyles'; import convertToLTR from '@libs/convertToLTR'; import FontUtils from '@styles/utils/FontUtils'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; -import {computeEmbeddedMaxWidth, isChildOfTaskTitle} from './htmlEngineUtils'; +import * as HTMLEngineUtils from './htmlEngineUtils'; import htmlRenderers from './HTMLRenderers'; type BaseHTMLEngineProviderProps = ChildrenProps & { @@ -80,17 +79,7 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim }), strong: HTMLElementModel.fromCustomModel({ tagName: 'strong', - getMixedUAStyles: (tnode) => (isChildOfTaskTitle(tnode as TNode) ? {} : styles.strong), - contentModel: HTMLContentModel.textual, - }), - em: HTMLElementModel.fromCustomModel({ - tagName: 'em', - getMixedUAStyles: (tnode) => (isChildOfTaskTitle(tnode as TNode) ? styles.taskTitleMenuItemItalic : styles.em), - contentModel: HTMLContentModel.textual, - }), - h1: HTMLElementModel.fromCustomModel({ - tagName: 'h1', - getMixedUAStyles: (tnode) => (isChildOfTaskTitle(tnode as TNode) ? {} : styles.h1), + mixedUAStyles: {whiteSpace: 'pre'}, contentModel: HTMLContentModel.textual, }), 'mention-user': HTMLElementModel.fromCustomModel({tagName: 'mention-user', contentModel: HTMLContentModel.textual}), @@ -137,10 +126,6 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim styles.onlyEmojisText, styles.onlyEmojisTextLineHeight, styles.taskTitleMenuItem, - styles.taskTitleMenuItemItalic, - styles.em, - styles.strong, - styles.h1, ], ); /* eslint-enable @typescript-eslint/naming-convention */ @@ -167,7 +152,7 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim defaultTextProps={defaultTextProps} defaultViewProps={defaultViewProps} renderers={htmlRenderers} - computeEmbeddedMaxWidth={computeEmbeddedMaxWidth} + computeEmbeddedMaxWidth={HTMLEngineUtils.computeEmbeddedMaxWidth} enableExperimentalBRCollapsing={enableExperimentalBRCollapsing} > {children} diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/EMRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/EMRenderer.tsx new file mode 100644 index 0000000000000..c1f044384fbe1 --- /dev/null +++ b/src/components/HTMLEngineProvider/HTMLRenderers/EMRenderer.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html'; +import {TNodeChildrenRenderer} from 'react-native-render-html'; +import * as HTMLEngineUtils from '@components/HTMLEngineProvider/htmlEngineUtils'; +import Text from '@components/Text'; +import useThemeStyles from '@hooks/useThemeStyles'; + +function EMRenderer({tnode}: CustomRendererProps) { + const styles = useThemeStyles(); + const isChildOfTaskTitle = HTMLEngineUtils.isChildOfTaskTitle(tnode); + + return 'data' in tnode ? ( + {tnode.data} + ) : ( + { + return ( + + {props.childElement} + + ); + }} + /> + ); +} + +EMRenderer.displayName = 'EMRenderer'; + +export default EMRenderer; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/HeadingRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/HeadingRenderer.tsx new file mode 100644 index 0000000000000..9d7c402e17fda --- /dev/null +++ b/src/components/HTMLEngineProvider/HTMLRenderers/HeadingRenderer.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html'; +import {TNodeChildrenRenderer} from 'react-native-render-html'; +import * as HTMLEngineUtils from '@components/HTMLEngineProvider/htmlEngineUtils'; +import Text from '@components/Text'; +import useThemeStyles from '@hooks/useThemeStyles'; + +function HeadingRenderer({tnode}: CustomRendererProps) { + const styles = useThemeStyles(); + const isChildOfTaskTitle = HTMLEngineUtils.isChildOfTaskTitle(tnode); + + return ( + { + return ( + + {props.childElement} + + ); + }} + /> + ); +} + +HeadingRenderer.displayName = 'HeadingRenderer'; + +export default HeadingRenderer; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/index.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/index.tsx index f517489191fd1..12dec12b2dfd0 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/index.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/index.tsx @@ -60,7 +60,7 @@ function MentionReportRenderer({style, tnode, TDefaultRenderer, ...defaultRender style={ isGroupPolicyReport && (!exactlyMatch || navigationRoute) ? [styles.link, styleWithoutColor, StyleUtils.getMentionStyle(isCurrentRoomMention), {color: StyleUtils.getMentionTextColor(isCurrentRoomMention)}] - : [flattenStyle] + : [] } suppressHighlighting onPress={ diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/StrongRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/StrongRenderer.tsx new file mode 100644 index 0000000000000..5a9f7ca652554 --- /dev/null +++ b/src/components/HTMLEngineProvider/HTMLRenderers/StrongRenderer.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import type {StyleProp, TextStyle} from 'react-native'; +import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html'; +import * as HTMLEngineUtils from '@components/HTMLEngineProvider/htmlEngineUtils'; +import useThemeStyles from '@hooks/useThemeStyles'; + +function StrongRenderer({tnode, TDefaultRenderer, style, ...props}: CustomRendererProps) { + const styles = useThemeStyles(); + const isChildOfTaskTitle = HTMLEngineUtils.isChildOfTaskTitle(tnode); + + return ( + , isChildOfTaskTitle && styles.taskTitleMenuItem, {fontStyle: (style.fontStyle as TextStyle['fontStyle']) ?? 'normal'}]} + /> + ); +} + +StrongRenderer.displayName = 'StrongRenderer'; + +export default StrongRenderer; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/index.ts b/src/components/HTMLEngineProvider/HTMLRenderers/index.ts index c59c9675ec87d..2ac2e85919155 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/index.ts +++ b/src/components/HTMLEngineProvider/HTMLRenderers/index.ts @@ -4,6 +4,8 @@ import CodeRenderer from './CodeRenderer'; import DeletedActionRenderer from './DeletedActionRenderer'; import EditedRenderer from './EditedRenderer'; import EmojiRenderer from './EmojiRenderer'; +import EMRenderer from './EMRenderer'; +import HeadingRenderer from './HeadingRenderer'; import ImageRenderer from './ImageRenderer'; import MentionHereRenderer from './MentionHereRenderer'; import MentionReportRenderer from './MentionReportRenderer'; @@ -11,6 +13,7 @@ import MentionUserRenderer from './MentionUserRenderer'; import NextStepEmailRenderer from './NextStepEmailRenderer'; import PreRenderer from './PreRenderer'; import ShortMentionRenderer from './ShortMentionRenderer'; +import StrongRenderer from './StrongRenderer'; import TaskTitleRenderer from './TaskTitleRenderer'; import VideoRenderer from './VideoRenderer'; @@ -23,6 +26,9 @@ const HTMLEngineProviderComponentList: CustomTagRendererRecord = { code: CodeRenderer, img: ImageRenderer, video: VideoRenderer, + h1: HeadingRenderer, + strong: StrongRenderer, + em: EMRenderer, // Custom tag renderers edited: EditedRenderer, diff --git a/src/styles/index.ts b/src/styles/index.ts index f9e7f93977b01..beaa81a9436fe 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -150,6 +150,18 @@ const webViewStyles = (theme: ThemeColors) => // styles from the renderer, just pass the "style" prop to the underlying // component. tagStyles: { + em: { + // We set fontFamily and fontStyle directly in order to avoid overriding fontWeight. + fontFamily: FontUtils.fontFamily.platform.EXP_NEUE_ITALIC.fontFamily, + fontStyle: FontUtils.fontFamily.platform.EXP_NEUE_ITALIC.fontStyle, + }, + + strong: { + // We set fontFamily and fontWeight directly in order to avoid overriding fontStyle. + fontFamily: FontUtils.fontFamily.platform.EXP_NEUE_BOLD.fontFamily, + fontWeight: FontUtils.fontFamily.platform.EXP_NEUE_BOLD.fontWeight, + }, + del: { textDecorationLine: 'line-through', textDecorationStyle: 'solid', @@ -217,6 +229,8 @@ const webViewStyles = (theme: ThemeColors) => marginBottom: 0, }, h1: { + fontSize: undefined, + fontWeight: undefined, marginBottom: 8, }, }, @@ -275,11 +289,6 @@ const styles = (theme: ThemeColors) => fontWeight: FontUtils.fontFamily.platform.EXP_NEUE_BOLD.fontWeight, }, - em: { - fontFamily: FontUtils.fontFamily.platform.EXP_NEUE_ITALIC.fontFamily, - fontStyle: FontUtils.fontFamily.platform.EXP_NEUE_ITALIC.fontStyle, - }, - autoCompleteSuggestionContainer: { flexDirection: 'row', alignItems: 'center',