diff --git a/packages/render-html/src/TNodeRenderer.tsx b/packages/render-html/src/TNodeRenderer.tsx
index 968fd5a90..9f17f6828 100644
--- a/packages/render-html/src/TNodeRenderer.tsx
+++ b/packages/render-html/src/TNodeRenderer.tsx
@@ -10,6 +10,7 @@ import TPhrasingRenderer from './TPhrasingRenderer';
import TTextRenderer from './TTextRenderer';
import { Markers, TNodeRendererProps } from './shared-types';
import { getMarkersFromTNode } from './helpers/getMarkersFromTNode';
+import { useSharedProps } from './context/SharedPropsContext';
export type { TNodeRendererProps } from './shared-types';
@@ -17,8 +18,21 @@ const TNodeRenderer = function TNodeRenderer(
props: Omit, 'markers'> & { parentMarkers: Markers }
) {
const { tnode } = props;
+ const { setMarkersForTNode } = useSharedProps();
const markers = getMarkersFromTNode(tnode, props.parentMarkers);
- const tnodeProps = { ...props, markers: markers || props.parentMarkers };
+ const customMarkers = setMarkersForTNode(tnode, props.parentMarkers);
+ const resolvedMarkers =
+ markers && !customMarkers
+ ? markers
+ : !markers && customMarkers
+ ? { ...props.parentMarkers, ...customMarkers }
+ : markers && customMarkers
+ ? ({ ...markers, ...customMarkers } as Markers)
+ : null;
+ const tnodeProps = {
+ ...props,
+ markers: resolvedMarkers || props.parentMarkers
+ };
if (tnode instanceof TBlock) {
return React.createElement(TBlockRenderer, tnodeProps);
}
diff --git a/packages/render-html/src/__tests__/component.render-html.test.tsx b/packages/render-html/src/__tests__/component.render-html.test.tsx
index f9f208427..c10fdfc46 100644
--- a/packages/render-html/src/__tests__/component.render-html.test.tsx
+++ b/packages/render-html/src/__tests__/component.render-html.test.tsx
@@ -129,6 +129,22 @@ describe('RenderHTML', () => {
const em = UNSAFE_getByType(EmRenderer);
expect(em.props.markers.lang).toBe('test');
});
+ it('should handle setMarkersForTNode prop', () => {
+ const { UNSAFE_getByType } = render(
+ Two'
+ }}
+ debug={false}
+ setMarkersForTNode={(tnode) =>
+ tnode.tagName === 'em' ? { em: true } : null
+ }
+ contentWidth={100}
+ />
+ );
+ const em = UNSAFE_getByType(TTextRenderer);
+ expect(em.props.markers.em).toBe(true);
+ });
});
describe('regarding propsFromParent', () => {
it('should pass propsForChildren to children', () => {
diff --git a/packages/render-html/src/context/SharedPropsContext.ts b/packages/render-html/src/context/SharedPropsContext.ts
index aabf038a4..84777b93b 100644
--- a/packages/render-html/src/context/SharedPropsContext.ts
+++ b/packages/render-html/src/context/SharedPropsContext.ts
@@ -28,7 +28,8 @@ export const defaultSharedPropsContext: Required = {
return null;
},
defaultWebViewProps: {},
- renderersProps: {}
+ renderersProps: {},
+ setMarkersForTNode: () => null
};
const SharedPropsContext = React.createContext>(
diff --git a/packages/render-html/src/shared-types.ts b/packages/render-html/src/shared-types.ts
index 5d14bcacc..7d722bbae 100644
--- a/packages/render-html/src/shared-types.ts
+++ b/packages/render-html/src/shared-types.ts
@@ -119,6 +119,20 @@ export interface RenderHTMLSharedProps<
* See [@native-html/plugins](https://github.com/native-html/plugins).
*/
WebView?: ComponentType;
+ /**
+ * Set custom markers from a TNode and all its descendants. Markers will be
+ * accessible in custom renderers via `markers` prop.
+ *
+ * @param tnode - The TNode to inspect
+ * @param parentMarkers - Markers from the parent TNode.
+ *
+ * @returns a record of markers if one or many markers should be added,
+ * `null` otherwise.
+ */
+ setMarkersForTNode?: (
+ tnode: TNode,
+ parentMarkers: Markers
+ ) => Partial | null;
}
export interface TransientRenderEngineConfig {
@@ -377,10 +391,9 @@ export interface FallbackFontsDefinitions {
/**
* Markers form an abstraction in which one node provides semantic information
- * to itself and all its descendants by the mean of its name or attributes. For
- * example, `ins` elements, which stand for "insertion" of content in the
- * context of an edit will provide the { edits: 'ins' } marker to all its
- * descendants.
+ * to itself and all its descendants. For example, `ins` elements, which stand
+ * for "insertion" of content in the context of an edit will provide the {
+ * edits: 'ins' } marker to all its descendants.
*
* Custom renderers can use markers to change their layout and convey their
* semantic meaning. Markers can be derived from attributes, such as `lang` and