react-linkify
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -9,2 +9,4 @@ 'use strict'; | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
@@ -14,3 +16,3 @@ | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
@@ -21,72 +23,31 @@ var _react = require('react'); | ||
var Linkify = (function (_React$Component) { | ||
function Linkify() { | ||
_classCallCheck(this, Linkify); | ||
var _linkifyIt = require('linkify-it'); | ||
if (_React$Component != null) { | ||
_React$Component.apply(this, arguments); | ||
} | ||
} | ||
var _linkifyIt2 = _interopRequireDefault(_linkifyIt); | ||
_inherits(Linkify, _React$Component); | ||
var _tlds = require('tlds'); | ||
_createClass(Linkify, [{ | ||
key: 'getMatch', | ||
value: function getMatch(string) { | ||
var urlIdx = string.search(this.props.urlRegex); | ||
var emailIdx = string.search(this.props.emailRegex); | ||
var _tlds2 = _interopRequireDefault(_tlds); | ||
if (urlIdx === -1 && emailIdx === -1) { | ||
return false; | ||
} | ||
var linkify = new _linkifyIt2['default'](); | ||
linkify.tlds(_tlds2['default']); | ||
var idx = undefined, | ||
regex = undefined, | ||
type = undefined; | ||
if (urlIdx === -1) { | ||
idx = emailIdx; | ||
regex = this.props.emailRegex; | ||
type = 'email'; | ||
} else if (emailIdx === -1) { | ||
idx = urlIdx; | ||
regex = this.props.urlRegex; | ||
type = 'url'; | ||
} else if (urlIdx < emailIdx) { | ||
idx = urlIdx; | ||
regex = this.props.urlRegex; | ||
type = 'url'; | ||
} else { | ||
// Email has precedence over url when equal | ||
idx = emailIdx; | ||
regex = this.props.emailRegex; | ||
type = 'email'; | ||
} | ||
var Linkify = (function (_React$Component) { | ||
_inherits(Linkify, _React$Component); | ||
var str = string.match(regex)[0]; | ||
function Linkify() { | ||
_classCallCheck(this, Linkify); | ||
return { | ||
str: str, | ||
type: type, | ||
idx: idx, | ||
len: str.length | ||
}; | ||
} | ||
}, { | ||
key: 'formatLink', | ||
value: function formatLink(match) { | ||
if (match.type === 'email') { | ||
return 'mailto:' + match.str; | ||
} else if (match.type === 'url') { | ||
if (match.str.substring(0, 4).toLowerCase() === 'http') { | ||
return match.str; | ||
} else { | ||
return 'http://' + match.str; | ||
} | ||
} | ||
_get(Object.getPrototypeOf(Linkify.prototype), 'constructor', this).apply(this, arguments); | ||
} | ||
return match.str; | ||
_createClass(Linkify, [{ | ||
key: 'getMatches', | ||
value: function getMatches(string) { | ||
return linkify.match(string); | ||
} | ||
}, { | ||
key: 'parseStringHelper', | ||
value: function parseStringHelper(string, elements) { | ||
key: 'parseString', | ||
value: function parseString(string) { | ||
var elements = []; | ||
if (string === '') { | ||
@@ -96,35 +57,52 @@ return elements; | ||
var match = this.getMatch(string); | ||
if (!match) { | ||
elements.push(string); | ||
return this.parseStringHelper('', elements); | ||
var matches = this.getMatches(string); | ||
if (!matches) { | ||
return string; | ||
} | ||
// Push the preceding text if there is any | ||
if (match.idx > 0) { | ||
elements.push(string.substring(0, match.idx)); | ||
} | ||
var lastIndex = 0; | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
// Shallow update values that specified the match | ||
var props = { href: this.formatLink(match), key: Linkify.uniqueKey() }; | ||
for (var key in this.props.properties) { | ||
var val = this.props.properties[key]; | ||
if (val === Linkify.MATCH) { | ||
val = this.formatLink(match); | ||
try { | ||
for (var _iterator = matches[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var match = _step.value; | ||
// Push the preceding text if there is any | ||
if (match.index > lastIndex) { | ||
elements.push(string.substring(lastIndex, match.index)); | ||
} | ||
// Shallow update values that specified the match | ||
var props = { href: match.url, key: Linkify.uniqueKey() }; | ||
for (var key in this.props.properties) { | ||
var val = this.props.properties[key]; | ||
if (val === Linkify.MATCH) { | ||
val = match.url; | ||
} | ||
props[key] = val; | ||
} | ||
elements.push(_react2['default'].createElement(this.props.component, props, match.text)); | ||
lastIndex = match.lastIndex; | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator['return']) { | ||
_iterator['return'](); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
props[key] = val; | ||
if (lastIndex !== string) { | ||
elements.push(string.substring(lastIndex)); | ||
} | ||
elements.push(_react2['default'].createElement(this.props.component, props, match.str)); | ||
return this.parseStringHelper(string.substring(match.idx + match.len), elements); | ||
} | ||
}, { | ||
key: 'parseString', | ||
value: function parseString(string) { | ||
var elements = []; | ||
this.parseStringHelper(string, elements); | ||
return elements.length === 1 ? elements[0] : elements; | ||
@@ -163,2 +141,7 @@ } | ||
}], [{ | ||
key: 'uniqueKey', | ||
value: function uniqueKey() { | ||
return 'LINKIFY_KEY_' + ++Linkify.keyCounter; | ||
} | ||
}, { | ||
key: 'MATCH', | ||
@@ -172,7 +155,2 @@ value: 'LINKIFY_MATCH', | ||
}, { | ||
key: 'uniqueKey', | ||
value: function uniqueKey() { | ||
return 'LINKIFY_KEY_' + ++Linkify.keyCounter; | ||
} | ||
}, { | ||
key: 'propTypes', | ||
@@ -190,6 +168,3 @@ value: { | ||
component: 'a', | ||
properties: {}, | ||
// TODO: Improve regexs | ||
urlRegex: /\b(?:(?:https):\/\/|[-A-Z0-9+&@#/%=~_|$?!:,.]+\.)(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[A-Z0-9+&@#/%=~_|$])/i, | ||
emailRegex: /\b[-A-Z0-9+&%=~_|$!.]+@[-A-Z0-9+&%=~_|$!.]+\.[-A-Z0-9+&%=~_|$!]+/i | ||
properties: {} | ||
}, | ||
@@ -196,0 +171,0 @@ enumerable: true |
{ | ||
"name": "react-linkify", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "React component to parse links (urls, emails, etc.) in text into clickable links", | ||
@@ -31,2 +31,3 @@ "homepage": "http://tasti.github.io/react-linkify/", | ||
"babel-jest": "~5.2.0", | ||
"jest": "^0.1.40", | ||
"jest-cli": "~0.4.5", | ||
@@ -41,3 +42,7 @@ "react": "~0.13.3", | ||
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest" | ||
}, | ||
"dependencies": { | ||
"linkify-it": "^1.2.0", | ||
"tlds": "^1.57.0" | ||
} | ||
} |
@@ -72,21 +72,6 @@ # [react-linkify](http://tasti.github.io/react-linkify/) | ||
**urlRegex** | ||
The regular expression used to identify url links. | ||
_type:_ `object` | ||
_default:_ `/\b(?:(?:https):\/\/|[-A-Z0-9+&@#/%=~_|$?!:,.]+\.)(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[A-Z0-9+&@#/%=~_|$])/i` | ||
## Examples | ||
**emailRegex** | ||
The regular expression used to identify email links. | ||
_type:_ `object` | ||
_default:_ `/\b[-A-Z0-9+&%=~_|$!.]+@[-A-Z0-9+&%=~_|$!.]+\.[-A-Z0-9+&%=~_|$!]+/i` | ||
Some of the cases the default regex handles (link inside code block): | ||
- `github.com` | ||
- `www.google.com` | ||
- `http://www.zakarie.com` | ||
- `https://www.facebook.com` | ||
- "`www.google.com:8080`" | ||
- `http://en.wikipedia.org/wiki/React_(JavaScript_library)` | ||
- Examples are available at `http://tasti.github.io/react-linkify/`. | ||
- `tasti@zakarie.com` | ||
- For more information, contact `tasti@zakarie.com`. | ||
All kind of links detectable by | ||
[linkify-it](https://github.com/markdown-it/linkify-it) are supported. For | ||
examples, visit [their website](http://markdown-it.github.io/linkify-it/). |
import React from 'react'; | ||
import LinkifyIt from 'linkify-it'; | ||
import tlds from 'tlds'; | ||
const linkify = new LinkifyIt(); | ||
linkify.tlds(tlds); | ||
class Linkify extends React.Component { | ||
@@ -21,59 +26,10 @@ static MATCH = 'LINKIFY_MATCH' | ||
properties: {}, | ||
// TODO: Improve regexs | ||
urlRegex: /\b(?:(?:https):\/\/|[-A-Z0-9+&@#/%=~_|$?!:,.]+\.)(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[A-Z0-9+&@#/%=~_|$])/i, | ||
emailRegex: /\b[-A-Z0-9+&%=~_|$!.]+@[-A-Z0-9+&%=~_|$!.]+\.[-A-Z0-9+&%=~_|$!]+/i | ||
} | ||
getMatch(string) { | ||
let urlIdx = string.search(this.props.urlRegex); | ||
let emailIdx = string.search(this.props.emailRegex); | ||
if ((urlIdx === -1) && (emailIdx === -1)) { | ||
return false; | ||
} | ||
let idx, regex, type; | ||
if (urlIdx === -1) { | ||
idx = emailIdx; | ||
regex = this.props.emailRegex; | ||
type = 'email'; | ||
} else if (emailIdx === -1) { | ||
idx = urlIdx; | ||
regex = this.props.urlRegex; | ||
type = 'url'; | ||
} else if (urlIdx < emailIdx) { | ||
idx = urlIdx; | ||
regex = this.props.urlRegex; | ||
type = 'url'; | ||
} else { // Email has precedence over url when equal | ||
idx = emailIdx; | ||
regex = this.props.emailRegex; | ||
type = 'email'; | ||
} | ||
var str = string.match(regex)[0]; | ||
return { | ||
str: str, | ||
type: type, | ||
idx: idx, | ||
len: str.length | ||
} | ||
getMatches(string) { | ||
return linkify.match(string); | ||
} | ||
formatLink(match) { | ||
if (match.type === 'email') { | ||
return `mailto:${match.str}`; | ||
} else if (match.type === 'url') { | ||
if (match.str.substring(0, 4).toLowerCase() === 'http') { | ||
return match.str; | ||
} else { | ||
return `http://${match.str}`; | ||
} | ||
} | ||
return match.str; | ||
} | ||
parseStringHelper(string, elements) { | ||
parseString(string) { | ||
let elements = []; | ||
if (string === '') { | ||
@@ -83,38 +39,35 @@ return elements; | ||
let match = this.getMatch(string); | ||
if (!match) { | ||
elements.push(string); | ||
return this.parseStringHelper('', elements); | ||
const matches = this.getMatches(string); | ||
if (!matches) { | ||
return string; | ||
} | ||
// Push the preceding text if there is any | ||
if (match.idx > 0) { | ||
elements.push(string.substring(0, match.idx)); | ||
} | ||
let lastIndex = 0; | ||
for (let match of matches) { | ||
// Push the preceding text if there is any | ||
if (match.index > lastIndex) { | ||
elements.push(string.substring(lastIndex, match.index)); | ||
} | ||
// Shallow update values that specified the match | ||
let props = {href: match.url, key: Linkify.uniqueKey()}; | ||
for (let key in this.props.properties) { | ||
let val = this.props.properties[key]; | ||
if (val === Linkify.MATCH) { | ||
val = match.url; | ||
} | ||
// Shallow update values that specified the match | ||
let props = {href: this.formatLink(match), key: Linkify.uniqueKey()}; | ||
for (let key in this.props.properties) { | ||
let val = this.props.properties[key]; | ||
if (val === Linkify.MATCH) { | ||
val = this.formatLink(match); | ||
props[key] = val; | ||
} | ||
elements.push(React.createElement( | ||
this.props.component, | ||
props, | ||
match.text | ||
)); | ||
lastIndex = match.lastIndex; | ||
} | ||
props[key] = val; | ||
if (lastIndex !== string) { | ||
elements.push(string.substring(lastIndex)); | ||
} | ||
elements.push(React.createElement( | ||
this.props.component, | ||
props, | ||
match.str | ||
)); | ||
return this.parseStringHelper(string.substring(match.idx + match.len), elements); | ||
} | ||
parseString(string) { | ||
let elements = []; | ||
this.parseStringHelper(string, elements); | ||
return (elements.length === 1) ? elements[0] : elements; | ||
@@ -144,3 +97,3 @@ } | ||
render() { | ||
let parsedChildren = this.parse(this.props.children); | ||
const parsedChildren = this.parse(this.props.children); | ||
@@ -147,0 +100,0 @@ return <span className="Linkify">{parsedChildren}</span>; |
17197
2
5
330
77
+ Addedlinkify-it@^1.2.0
+ Addedtlds@^1.57.0
+ Addedlinkify-it@1.2.4(transitive)
+ Addedtlds@1.252.0(transitive)
+ Addeduc.micro@1.0.6(transitive)