forked from joshswan/react-native-autolink
-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from Georepublic/update-repo-link
Fix path url
- Loading branch information
Showing
10 changed files
with
381 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
artifacts/ | ||
dist/ | ||
|
||
### Node ### | ||
# Logs | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/*! | ||
* React Native Autolink | ||
* | ||
* Copyright 2016-2020 Josh Swan | ||
* Released under the MIT license | ||
* https://github.com/joshswan/react-native-autolink/blob/master/LICENSE | ||
*/ | ||
import React, { PureComponent, ReactNode } from 'react'; | ||
import { Match } from 'autolinker/dist/es2015'; | ||
import { StyleProp, Text, TextStyle, TextProps } from 'react-native'; | ||
import { PropsOf } from './types'; | ||
interface AutolinkProps<C extends React.ComponentType = React.ComponentType> { | ||
component?: C; | ||
email?: boolean; | ||
hashtag?: false | 'facebook' | 'instagram' | 'twitter'; | ||
latlng?: boolean; | ||
linkProps?: TextProps; | ||
linkStyle?: StyleProp<TextStyle>; | ||
mention?: false | 'instagram' | 'soundcloud' | 'twitter'; | ||
onPress?: (url: string, match: Match) => void; | ||
onLongPress?: (url: string, match: Match) => void; | ||
phone?: boolean | 'text' | 'sms'; | ||
renderLink?: (text: string, match: Match, index: number) => React.ReactNode; | ||
renderText?: (text: string, index: number) => React.ReactNode; | ||
showAlert?: boolean; | ||
stripPrefix?: boolean; | ||
stripTrailingSlash?: boolean; | ||
text: string; | ||
textProps?: TextProps; | ||
truncate?: number; | ||
truncateChars?: string; | ||
truncateLocation?: 'end' | 'middle' | 'smart'; | ||
url?: boolean | { | ||
schemeMatches?: boolean; | ||
wwwMatches?: boolean; | ||
tldMatches?: boolean; | ||
}; | ||
webFallback?: boolean; | ||
} | ||
declare type Props<C extends React.ComponentType> = AutolinkProps<C> & Omit<PropsOf<C>, keyof AutolinkProps>; | ||
export default class Autolink<C extends React.ComponentType = typeof Text> extends PureComponent<Props<C>> { | ||
static truncate(text: string, { truncate, truncateChars, truncateLocation, }?: { | ||
truncate?: number | undefined; | ||
truncateChars?: string | undefined; | ||
truncateLocation?: string | undefined; | ||
}): string; | ||
static defaultProps: { | ||
email: boolean; | ||
hashtag: boolean; | ||
latlng: boolean; | ||
linkProps: {}; | ||
mention: boolean; | ||
phone: boolean; | ||
showAlert: boolean; | ||
stripPrefix: boolean; | ||
stripTrailingSlash: boolean; | ||
textProps: {}; | ||
truncate: number; | ||
truncateChars: string; | ||
truncateLocation: string; | ||
url: boolean; | ||
webFallback: boolean; | ||
}; | ||
onPress(match: Match, alertShown?: boolean): void; | ||
onLongPress(match: Match): void; | ||
getUrl(match: Match): string[]; | ||
renderLink(text: string, match: Match, index: number, textProps?: Partial<TextProps>): ReactNode; | ||
render(): ReactNode; | ||
} | ||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
/*! | ||
* React Native Autolink | ||
* | ||
* Copyright 2016-2020 Josh Swan | ||
* Released under the MIT license | ||
* https://github.com/joshswan/react-native-autolink/blob/master/LICENSE | ||
*/ | ||
import React, { PureComponent, createElement } from 'react'; | ||
import { Autolinker, AnchorTagBuilder, } from 'autolinker/dist/es2015'; | ||
import { Alert, Linking, Platform, StyleSheet, Text, } from 'react-native'; | ||
import * as Truncate from './truncate'; | ||
import { Matchers } from './matchers'; | ||
const tagBuilder = new AnchorTagBuilder(); | ||
const styles = StyleSheet.create({ | ||
link: { | ||
color: '#0E7AFE', | ||
}, | ||
}); | ||
export default class Autolink extends PureComponent { | ||
static truncate(text, { truncate = 32, truncateChars = '..', truncateLocation = 'smart', } = {}) { | ||
let fn; | ||
switch (truncateLocation) { | ||
case 'end': | ||
fn = Truncate.end; | ||
break; | ||
case 'middle': | ||
fn = Truncate.middle; | ||
break; | ||
default: | ||
fn = Truncate.smart; | ||
} | ||
return fn(text, truncate, truncateChars); | ||
} | ||
onPress(match, alertShown) { | ||
const { onPress, showAlert, webFallback, } = this.props; | ||
// Check if alert needs to be shown | ||
if (showAlert && !alertShown) { | ||
Alert.alert('Leaving App', 'Do you want to continue?', [ | ||
{ text: 'Cancel', style: 'cancel' }, | ||
{ text: 'OK', onPress: () => this.onPress(match, true) }, | ||
]); | ||
return; | ||
} | ||
// Get url(s) for match | ||
const [url, fallback,] = this.getUrl(match); | ||
// Call custom onPress handler or open link/fallback | ||
if (onPress) { | ||
onPress(url, match); | ||
} | ||
else if (webFallback) { | ||
Linking.canOpenURL(url).then((supported) => { | ||
Linking.openURL(!supported && fallback ? fallback : url); | ||
}); | ||
} | ||
else { | ||
Linking.openURL(url); | ||
} | ||
} | ||
onLongPress(match) { | ||
const { onLongPress } = this.props; | ||
if (onLongPress) { | ||
// Get url for match | ||
const [url] = this.getUrl(match); | ||
onLongPress(url, match); | ||
} | ||
} | ||
getUrl(match) { | ||
const { hashtag, mention, phone } = this.props; | ||
const type = match.getType(); | ||
switch (type) { | ||
case 'email': { | ||
return [`mailto:${encodeURIComponent(match.getEmail())}`]; | ||
} | ||
case 'hashtag': { | ||
const tag = encodeURIComponent(match.getHashtag()); | ||
switch (hashtag) { | ||
case 'facebook': | ||
return [`fb://hashtag/${tag}`, `https://www.facebook.com/hashtag/${tag}`]; | ||
case 'instagram': | ||
return [`instagram://tag?name=${tag}`, `https://www.instagram.com/explore/tags/${tag}/`]; | ||
case 'twitter': | ||
return [`twitter://search?query=%23${tag}`, `https://twitter.com/hashtag/${tag}`]; | ||
default: | ||
return [match.getMatchedText()]; | ||
} | ||
} | ||
case 'latlng': { | ||
const latlng = match.getLatLng(); | ||
const query = latlng.replace(/\s/g, ''); | ||
return [Platform.OS === 'ios' ? `http://maps.apple.com/?q=${encodeURIComponent(latlng)}&ll=${query}` : `https://www.google.com/maps/search/?api=1&query=${query}`]; | ||
} | ||
case 'mention': { | ||
const username = match.getMention(); | ||
switch (mention) { | ||
case 'instagram': | ||
return [`instagram://user?username=${username}`, `https://www.instagram.com/${username}/`]; | ||
case 'soundcloud': | ||
return [`https://soundcloud.com/${username}`]; | ||
case 'twitter': | ||
return [`twitter://user?screen_name=${username}`, `https://twitter.com/${username}`]; | ||
default: | ||
return [match.getMatchedText()]; | ||
} | ||
} | ||
case 'phone': { | ||
const number = match.getNumber(); | ||
switch (phone) { | ||
case 'sms': | ||
case 'text': | ||
return [`sms:${number}`]; | ||
default: | ||
return [`tel:${number}`]; | ||
} | ||
} | ||
case 'url': { | ||
return [match.getAnchorHref()]; | ||
} | ||
default: { | ||
return [match.getMatchedText()]; | ||
} | ||
} | ||
} | ||
renderLink(text, match, index, textProps = {}) { | ||
const { truncate, linkStyle } = this.props; | ||
const truncated = truncate ? Autolink.truncate(text, this.props) : text; | ||
return (React.createElement(Text, Object.assign({ style: linkStyle || styles.link, onPress: () => this.onPress(match), onLongPress: () => this.onLongPress(match) }, textProps, { key: index }), truncated)); | ||
} | ||
render() { | ||
const { children, component = Text, email, hashtag, latlng, linkProps, linkStyle, mention, onPress, onLongPress, phone, renderLink, renderText, showAlert, stripPrefix, stripTrailingSlash, text, textProps, truncate, truncateChars, truncateLocation, url, webFallback, ...other } = this.props; | ||
// Creates a token with a random UID that should not be guessable or | ||
// conflict with other parts of the string. | ||
const uid = Math.floor(Math.random() * 0x10000000000).toString(16); | ||
const tokenRegexp = new RegExp(`(@__ELEMENT-${uid}-\\d+__@)`, 'g'); | ||
const generateToken = (() => { | ||
let counter = 0; | ||
return () => `@__ELEMENT-${uid}-${counter++}__@`; // eslint-disable-line no-plusplus | ||
})(); | ||
const matches = {}; | ||
let linkedText; | ||
try { | ||
linkedText = Autolinker.link(text || '', { | ||
email, | ||
hashtag, | ||
mention, | ||
phone: !!phone, | ||
urls: url, | ||
stripPrefix, | ||
stripTrailingSlash, | ||
replaceFn: (match) => { | ||
const token = generateToken(); | ||
matches[token] = match; | ||
return token; | ||
}, | ||
}); | ||
// Custom matchers | ||
Matchers.forEach((matcher) => { | ||
// eslint-disable-next-line react/destructuring-assignment | ||
if (this.props[matcher.id]) { | ||
linkedText = linkedText.replace(matcher.regex, (...args) => { | ||
const token = generateToken(); | ||
const matchedText = args[0]; | ||
matches[token] = new matcher.Match({ | ||
tagBuilder, | ||
matchedText, | ||
offset: args[args.length - 2], | ||
[matcher.id]: matchedText, | ||
}); | ||
return token; | ||
}); | ||
} | ||
}); | ||
} | ||
catch (e) { | ||
console.warn(e); // eslint-disable-line no-console | ||
return null; | ||
} | ||
const nodes = linkedText | ||
.split(tokenRegexp) | ||
.filter((part) => !!part) | ||
.map((part, index) => { | ||
var _a; | ||
const match = matches[part]; | ||
switch ((_a = match) === null || _a === void 0 ? void 0 : _a.getType()) { | ||
case 'email': | ||
case 'hashtag': | ||
case 'latlng': | ||
case 'mention': | ||
case 'phone': | ||
case 'url': | ||
return renderLink | ||
? renderLink(match.getAnchorText(), match, index) | ||
: this.renderLink(match.getAnchorText(), match, index, linkProps); | ||
default: | ||
return renderText | ||
? renderText(part, index) | ||
// eslint-disable-next-line react/jsx-props-no-spreading, react/no-array-index-key | ||
: React.createElement(Text, Object.assign({}, textProps, { key: index }), part); | ||
} | ||
}); | ||
return createElement(component, other, ...nodes); | ||
} | ||
} | ||
Autolink.defaultProps = { | ||
email: true, | ||
hashtag: false, | ||
latlng: false, | ||
linkProps: {}, | ||
mention: false, | ||
phone: true, | ||
showAlert: false, | ||
stripPrefix: true, | ||
stripTrailingSlash: true, | ||
textProps: {}, | ||
truncate: 32, | ||
truncateChars: '..', | ||
truncateLocation: 'smart', | ||
url: true, | ||
webFallback: Platform.OS !== 'ios', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/*! | ||
* React Native Autolink | ||
* | ||
* Copyright 2016-2020 Josh Swan | ||
* Released under the MIT license | ||
* https://github.com/joshswan/react-native-autolink/blob/master/LICENSE | ||
*/ | ||
import { Match, MatchConfig } from 'autolinker/dist/es2015'; | ||
export interface LatLngMatchConfig extends MatchConfig { | ||
latlng: string; | ||
} | ||
export declare class LatLngMatch extends Match { | ||
private latlng; | ||
constructor(cfg: LatLngMatchConfig); | ||
getType(): string; | ||
getLatLng(): string; | ||
getAnchorHref(): string; | ||
getAnchorText(): string; | ||
} | ||
export declare const CustomMatchers: { | ||
latlng: { | ||
id: string; | ||
regex: RegExp; | ||
Match: typeof LatLngMatch; | ||
}; | ||
}; | ||
export declare type MatcherId = keyof typeof CustomMatchers; | ||
export declare const Matchers: { | ||
id: string; | ||
regex: RegExp; | ||
Match: typeof LatLngMatch; | ||
}[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/*! | ||
* React Native Autolink | ||
* | ||
* Copyright 2016-2020 Josh Swan | ||
* Released under the MIT license | ||
* https://github.com/joshswan/react-native-autolink/blob/master/LICENSE | ||
*/ | ||
import { Match } from 'autolinker/dist/es2015'; | ||
export class LatLngMatch extends Match { | ||
constructor(cfg) { | ||
super(cfg); | ||
this.latlng = cfg.latlng; | ||
} | ||
getType() { | ||
return 'latlng'; | ||
} | ||
getLatLng() { | ||
return this.latlng; | ||
} | ||
getAnchorHref() { | ||
return this.latlng; | ||
} | ||
getAnchorText() { | ||
return this.latlng; | ||
} | ||
} | ||
export const CustomMatchers = { | ||
// LatLng | ||
latlng: { | ||
id: 'latlng', | ||
regex: /[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)/g, | ||
Match: LatLngMatch, | ||
}, | ||
}; | ||
export const Matchers = Object.keys(CustomMatchers).map((key) => CustomMatchers[key]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/*! | ||
* React Native Autolink | ||
* | ||
* Copyright 2016-2020 Josh Swan | ||
* Released under the MIT license | ||
* https://github.com/joshswan/react-native-autolink/blob/master/LICENSE | ||
*/ | ||
import { truncateEnd as end } from 'autolinker/dist/es2015/truncate/truncate-end'; | ||
import { truncateMiddle as middle } from 'autolinker/dist/es2015/truncate/truncate-middle'; | ||
import { truncateSmart as smart } from 'autolinker/dist/es2015/truncate/truncate-smart'; | ||
export { end, middle, smart, }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/*! | ||
* React Native Autolink | ||
* | ||
* Copyright 2016-2020 Josh Swan | ||
* Released under the MIT license | ||
* https://github.com/joshswan/react-native-autolink/blob/master/LICENSE | ||
*/ | ||
import { truncateEnd as end } from 'autolinker/dist/es2015/truncate/truncate-end'; | ||
import { truncateMiddle as middle } from 'autolinker/dist/es2015/truncate/truncate-middle'; | ||
import { truncateSmart as smart } from 'autolinker/dist/es2015/truncate/truncate-smart'; | ||
export { end, middle, smart, }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/// <reference types="react" /> | ||
export declare type PropsOf<E extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>> = JSX.LibraryManagedAttributes<E, React.ComponentPropsWithRef<E>>; |
Empty file.
Oops, something went wrong.