Skip to content

Commit

Permalink
Add the component
Browse files Browse the repository at this point in the history
  • Loading branch information
Doron Tohar committed Aug 13, 2017
1 parent 4ec4033 commit 69ea4b9
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 0 deletions.
113 changes: 113 additions & 0 deletions HyperlinkedText.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* @providesModule react-native-hyperlinked-text
*/

import React, { Component, PropTypes } from 'react'
import {
View,
Text,
Linking,
} from 'react-native'
import styles from './Styles/HyperlinkedTextStyle';
import R from 'ramda';

'use strict';

const textPropTypes = Text.propTypes || {}

export default class HyperlinkedText extends Component {
constructor(props){
super(props)
this._getMatches = this._getMatches.bind(this);
}

render(){
return this._linkify(this);
}

_linkify(component) {
const matches = this._gatherMatches(component.props.children);
const newElements = this._replaceMatches(component, matches);
return (<Text {...component.props} style={ this.props.style }>{ newElements }</Text>);
}

_gatherMatches(text) {
const matches = this.props.linkDefs.reduce((matches, linkDef)=>R.concat(this._getMatches(linkDef, text), matches), []);
return R.sort((m1, m2)=>m1.index-m2.index, matches);
}

_getMatches(linkDef, text) {
const regex = linkDef.regex;
regex.lastIndex = 0; // reset the regex in case it was used before
let matches = [];
while ((regexResult = regex.exec(text)) !== null) {
matches.push({
text: regexResult[0],
groups: R.drop(1,regexResult),
index: regexResult.index,
lastIndex: regex.lastIndex,
linkDef
});
}
return matches;
}

_replaceMatches(component, matches) {
const componentProps = {
...component.props,
ref: undefined,
key: undefined,
};
let _lastIndex = 0;
const elements = [];
for (let match of matches) {
const linkDef = match.linkDef;
const style = linkDef.style || this.props.linkStyle;
const onPress = linkDef.noPress? ()=>{} : (linkDef.onPress || this.props.onLinkPress);
const replaceText = linkDef.replaceText || R.identity;

let nonLinkedText = component.props.children.substring(_lastIndex, match.index);
nonLinkedText && elements.push(nonLinkedText);
_lastIndex = match.lastIndex;
elements.push(
<Text
{...componentProps}
key={match.index}
style={[component.props.style, style]}
onPress={onPress && (()=>onPress(match.text, ...match.groups))}
>
{linkDef.replaceText?linkDef.replaceText(match.text, ...match.groups):match.text}
</Text>
);
}
elements.push(component.props.children.substring(_lastIndex, component.props.children.length))
return elements;
}

static _openWebUrl(url) {
Linking.canOpenURL(url).then(supported => supported && Linking.openURL(url)).catch(console.log('Failed to open url ' + url));
}

static get webUrlLinkDef() {
return {
regex: /(https?:\/\/[^\s]+)/mgi,
onPress: HyperlinkedText._openWebUrl,
linkStyle: styles.hyperlink
};
}
}

HyperlinkedText.propTypes = {
onLinkPress: PropTypes.func,
linkDefs: PropTypes.array,
linkStyle: textPropTypes.style
}

// Defaults for props
HyperlinkedText.defaultProps = {
onLinkPress: HyperlinkedText._openWebUrl,
linkDefs: [{
regex: /(https?:\/\/[^\s]+)/mgi
}],
linkStyle: styles.hyperlink
}
12 changes: 12 additions & 0 deletions Styles/HyperlinkedTextStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { StyleSheet } from 'react-native'
import { Metrics, Colors } from '../../Themes/'

export default StyleSheet.create({
container: {
flex: 1,
paddingTop: Metrics.titlePadding
},
hyperlink: {
color: Colors.hyperlink
}
})
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "react-native-hyperlinked-text",
"version": "0.0.1",
"keywords": [
"react-native"
],
"dependencies": {
"ramda": "^0.24.1"
},
"description": "Text component for React Native with regex defined hyperlinks",
"main": "HyperlinkedText.js",
"devDependencies": {},
"scripts": {
"test": "mocha --reporter spec"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Kimaia/react-native-hyperlinked-text.git"
},
"author": "Doron Tohar <[email protected]> (https://www.kimaia.com/)",
"license": "ISC",
"bugs": {
"url": "https://github.com/Kimaia/react-native-hyperlinked-text/issues"
},
"homepage": "https://github.com/Kimaia/react-native-hyperlinked-text#readme"
}
7 changes: 7 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


ramda@^0.24.1:
version "0.24.1"
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857"

0 comments on commit 69ea4b9

Please sign in to comment.