@@ -28,10 +28,10 @@ import {
28
28
} from 'react-native' ;
29
29
import * as Truncate from './truncate' ;
30
30
import { Matchers , MatcherId , LatLngMatch } from './matchers' ;
31
- import { UserCustomMatch , UserCustomMatchSpec } from './user-custom-match ' ;
31
+ import { CustomMatch , CustomMatcher } from './CustomMatch ' ;
32
32
import { PropsOf } from './types' ;
33
33
34
- export * from './user-custom-match ' ;
34
+ export * from './CustomMatch ' ;
35
35
36
36
const tagBuilder = new AnchorTagBuilder ( ) ;
37
37
@@ -43,12 +43,12 @@ const styles = StyleSheet.create({
43
43
44
44
interface AutolinkProps < C extends React . ComponentType = React . ComponentType > {
45
45
component ?: C ;
46
- customLinks ?: UserCustomMatchSpec [ ] ;
47
46
email ?: boolean ;
48
47
hashtag ?: false | 'facebook' | 'instagram' | 'twitter' ;
49
48
latlng ?: boolean ;
50
49
linkProps ?: TextProps ;
51
50
linkStyle ?: StyleProp < TextStyle > ;
51
+ matchers ?: CustomMatcher [ ] ;
52
52
mention ?: false | 'instagram' | 'soundcloud' | 'twitter' ;
53
53
onPress ?: ( url : string , match : Match ) => void ;
54
54
onLongPress ?: ( url : string , match : Match ) => void ;
@@ -117,7 +117,10 @@ export default class Autolink<
117
117
webFallback : Platform . OS !== 'ios' , // iOS requires LSApplicationQueriesSchemes for Linking.canOpenURL
118
118
} ;
119
119
120
- onPress ( match : Match , alertShown ?: boolean ) : void {
120
+ onPress ( match : Match | CustomMatch , alertShown ?: boolean ) : void {
121
+ // Bypass default press handling if matcher has custom onPress
122
+ if ( match instanceof CustomMatch && match . getMatcher ( ) . onPress ?.( match ) ) return ;
123
+
121
124
const {
122
125
onPress,
123
126
showAlert,
@@ -157,6 +160,9 @@ export default class Autolink<
157
160
}
158
161
159
162
onLongPress ( match : Match ) : void {
163
+ // Bypass default press handling if matcher has custom onLongPress
164
+ if ( match instanceof CustomMatch && match . getMatcher ( ) . onLongPress ?.( match ) ) return ;
165
+
160
166
const { onLongPress } = this . props ;
161
167
162
168
if ( onLongPress ) {
@@ -232,31 +238,18 @@ export default class Autolink<
232
238
233
239
renderLink (
234
240
text : string ,
235
- match : Match ,
241
+ match : Match | CustomMatch ,
236
242
index : number ,
237
243
textProps : Partial < TextProps > = { } ,
238
244
) : ReactNode {
239
245
const { truncate, linkStyle } = this . props ;
240
246
const truncated = truncate ? Autolink . truncate ( text , this . props ) : text ;
241
247
242
- let style : StyleProp < TextStyle > | undefined ;
243
- let onPress : ( ( ) => void ) | undefined ;
244
- let onLongPress : ( ( ) => void ) | undefined ;
245
- if ( match . getType ( ) === 'userCustom' ) {
246
- style = ( match as UserCustomMatch ) . getStyle ( ) ;
247
- onPress = ( match as UserCustomMatch ) . getOnPress ( ) ;
248
- onLongPress = ( match as UserCustomMatch ) . getOnLongPress ( ) ;
249
- }
250
-
251
- style = style ?? linkStyle ?? styles . link ;
252
- onPress = onPress ?? ( ( ) => this . onPress ( match ) ) ;
253
- onLongPress = onLongPress ?? ( ( ) => this . onLongPress ( match ) ) ;
254
-
255
248
return (
256
249
< Text
257
- style = { style }
258
- onPress = { onPress }
259
- onLongPress = { onLongPress }
250
+ style = { ( match as CustomMatch ) . getMatcher ?. ( ) . style ?? linkStyle ?? styles . link }
251
+ onPress = { ( ) => this . onPress ( match ) }
252
+ onLongPress = { ( ) => this . onLongPress ( match ) }
260
253
// eslint-disable-next-line react/jsx-props-no-spreading
261
254
{ ...textProps }
262
255
key = { index }
@@ -270,12 +263,12 @@ export default class Autolink<
270
263
const {
271
264
children,
272
265
component = Text ,
273
- customLinks = [ ] ,
274
266
email,
275
267
hashtag,
276
268
latlng,
277
269
linkProps,
278
270
linkStyle,
271
+ matchers = [ ] ,
279
272
mention,
280
273
onPress,
281
274
onLongPress,
@@ -347,17 +340,17 @@ export default class Autolink<
347
340
} ) ;
348
341
349
342
// User-specified custom matchers
350
- customLinks . forEach ( ( spec ) => {
351
- linkedText = linkedText . replace ( spec . pattern , ( ...args ) => {
343
+ matchers . forEach ( ( matcher ) => {
344
+ linkedText = linkedText . replace ( matcher . pattern , ( ...replacerArgs ) => {
352
345
const token = generateToken ( ) ;
353
- const matchedText = args [ 0 ] ;
346
+ const matchedText = replacerArgs [ 0 ] ;
354
347
355
- matches [ token ] = new UserCustomMatch ( {
356
- ...spec ,
357
- tagBuilder,
348
+ matches [ token ] = new CustomMatch ( {
349
+ matcher,
358
350
matchedText,
359
- offset : args [ args . length - 2 ] ,
360
- replacerArgs : args ,
351
+ offset : replacerArgs [ replacerArgs . length - 2 ] ,
352
+ replacerArgs,
353
+ tagBuilder,
361
354
} ) ;
362
355
363
356
return token ;
@@ -375,23 +368,17 @@ export default class Autolink<
375
368
. map ( ( part , index ) => {
376
369
const match = matches [ part ] ;
377
370
378
- switch ( match ?. getType ( ) ) {
379
- case 'email' :
380
- case 'hashtag' :
381
- case 'latlng' :
382
- case 'mention' :
383
- case 'phone' :
384
- case 'url' :
385
- case 'userCustom' :
386
- return renderLink
387
- ? renderLink ( match . getAnchorText ( ) , match , index )
388
- : this . renderLink ( match . getAnchorText ( ) , match , index , linkProps ) ;
389
- default :
390
- return renderText
391
- ? renderText ( part , index )
392
- // eslint-disable-next-line react/jsx-props-no-spreading, react/no-array-index-key
393
- : < Text { ...textProps } key = { index } > { part } </ Text > ;
371
+ // Check if rendering link or text node
372
+ if ( match ?. getType ( ) ) {
373
+ return renderLink
374
+ ? renderLink ( match . getAnchorText ( ) , match , index )
375
+ : this . renderLink ( match . getAnchorText ( ) , match , index , linkProps ) ;
394
376
}
377
+
378
+ return renderText
379
+ ? renderText ( part , index )
380
+ // eslint-disable-next-line react/jsx-props-no-spreading, react/no-array-index-key
381
+ : < Text { ...textProps } key = { index } > { part } </ Text > ;
395
382
} ) ;
396
383
397
384
return createElement ( component , other , ...nodes ) ;
0 commit comments