Skip to content

Commit af9cae1

Browse files
committed
feat: custom matchers support new renderLink option for increased customization
1 parent fe8f0d9 commit af9cae1

File tree

4 files changed

+44
-2
lines changed

4 files changed

+44
-2
lines changed

src/Autolink.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ export const Autolink = React.memo(
190190
const uid = useRef(Math.floor(Math.random() * 0x10000000000).toString(16));
191191
const [generateToken, tokenRegexp] = makeTokenGenerator(uid.current);
192192

193-
const matches: { [token: string]: Match } = {};
193+
const matches: { [token: string]: Match | CustomMatch } = {};
194194
let linkedText: string;
195195

196196
try {
@@ -242,7 +242,11 @@ export const Autolink = React.memo(
242242

243243
// Check if rendering link or text node
244244
if (match?.getType()) {
245-
return (renderLinkProp || renderLink)(match.getAnchorText(), match, index);
245+
return ((match as any).getRenderFn?.() || renderLinkProp || renderLink)(
246+
match.getAnchorText(),
247+
match,
248+
index,
249+
);
246250
}
247251

248252
return renderText ? (

src/CustomMatch.ts

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Match, MatchConfig } from 'autolinker/dist/es2015';
2+
import React from 'react';
23
import { StyleProp, TextStyle } from 'react-native';
34

45
// The variadic arguments of a regex replacer function, wrapped in an array.
@@ -20,6 +21,8 @@ export interface CustomMatcher {
2021
getLinkText?: (replacerArgs: ReplacerArgs) => string;
2122
/* Custom function for extracting link URL using regex replacer args */
2223
getLinkUrl?: (replacerArgs: ReplacerArgs) => string;
24+
/* Custom function for rendering link - remember to attach press handlers! */
25+
renderLink?: (text: string, match: CustomMatch, index: number) => React.ReactNode;
2326
}
2427

2528
export interface CustomMatchConfig extends MatchConfig {
@@ -57,4 +60,8 @@ export class CustomMatch extends Match {
5760
getReplacerArgs(): ReplacerArgs {
5861
return this.replacerArgs;
5962
}
63+
64+
getRenderFn(): CustomMatcher['renderLink'] {
65+
return this.matcher.renderLink;
66+
}
6067
}

src/__tests__/Autolink.test.tsx

+21
Original file line numberDiff line numberDiff line change
@@ -342,5 +342,26 @@ describe('<Autolink />', () => {
342342
expect(onPress.mock.calls[0][0]).toBe('__LINK_URL__');
343343
expect(onPress.mock.calls[0][1]).toBeInstanceOf(CustomMatch);
344344
});
345+
346+
test('uses renderLink when rendering link', () => {
347+
const onPress = jest.fn();
348+
const renderLink = jest
349+
.fn()
350+
.mockImplementation((text: string) => <Text onPress={onPress}>{text}</Text>);
351+
const tree = renderer.create(
352+
<Autolink
353+
text="+14085550123"
354+
onPress={onPress}
355+
matchers={[{ ...IntlPhoneMatcher, renderLink }]}
356+
/>,
357+
);
358+
expect(renderLink.mock.calls.length).toBe(1);
359+
expect(renderLink.mock.calls[0][0]).toBe('+14085550123');
360+
expect(renderLink.mock.calls[0][1]).toBeInstanceOf(CustomMatch);
361+
expect(renderLink.mock.calls[0][2]).toBe(0);
362+
expect(tree).toMatchSnapshot();
363+
tree.root.findAllByType(Text)[1].props.onPress();
364+
expect(onPress.mock.calls.length).toBe(1);
365+
});
345366
});
346367
});

src/__tests__/__snapshots__/Autolink.test.tsx.snap

+10
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,16 @@ exports[`<Autolink /> matchers uses getLinkText when rendering link 1`] = `
190190
</Text>
191191
`;
192192

193+
exports[`<Autolink /> matchers uses renderLink when rendering link 1`] = `
194+
<Text>
195+
<Text
196+
onPress={[MockFunction]}
197+
>
198+
+14085550123
199+
</Text>
200+
</Text>
201+
`;
202+
193203
exports[`<Autolink /> matchers wraps text based on supplied custom matchers 1`] = `
194204
<Text>
195205
<Text

0 commit comments

Comments
 (0)