Skip to content

Commit

Permalink
first stab at merging global and instance linkifyIt customizations
Browse files Browse the repository at this point in the history
  • Loading branch information
olslash committed Jun 3, 2016
1 parent 4f72d2a commit 35512d0
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 19 deletions.
68 changes: 50 additions & 18 deletions src/Linkify.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,33 @@ import React from 'react';
import LinkifyIt from 'linkify-it';
import tlds from 'tlds';

export const linkify = new LinkifyIt();
linkify.tlds(tlds);
const globalCustomizations = {
add: [],
tlds: [],
set: []
};

export const config = {
add: (...args) => {
globalCustomizations.add.push(args);
return config;
},
tlds: (...args) => {
globalCustomizations.tlds.push(args);
return config;
},
set: (...args) => {
globalCustomizations.set.push(args);
return config;
},
resetAll: () => {
for (let type in globalCustomizations) {
globalCustomizations[type] = [];
}

return config;
}
};

class Linkify extends React.Component {
static MATCH = 'LINKIFY_MATCH'
Expand All @@ -20,7 +45,10 @@ class Linkify extends React.Component {
validate: React.PropTypes.func.isRequired,
normalize: React.PropTypes.func.isRequired
})
)
),
fuzzyLink: React.PropTypes.bool,
fuzzyIP: React.PropTypes.bool,
fuzzyEmail: React.PropTypes.bool
}

static defaultProps = {
Expand All @@ -35,33 +63,37 @@ class Linkify extends React.Component {
}

componentDidUpdate(nextProps) {
if (this.props.handlers !== nextProps.handlers) {
this.addCustomHandlers();
}
this.addCustomHandlers();
}

addCustomHandlers() {
const { handlers } = this.props;

if (handlers.length) {
this.linkify = new LinkifyIt();
this.linkify.tlds(tlds);
this.linkify = this.linkify || new LinkifyIt();
this.linkify.tlds(tlds);

handlers.forEach(handler => {
this.linkify.add(handler.prefix, {
validate: handler.validate,
normalize: handler.normalize
});
});
// add global customizations
for (let type in globalCustomizations) {
globalCustomizations[type].forEach(c => this.linkify[type](...c))
}

// add instance customizations
(handlers || []).forEach((handler) => {
this.linkify.add(handler.prefix, {
validate: handler.validate,
normalize: handler.normalize
});
});

['fuzzyLink', 'fuzzyIP', 'fuzzyEmail'].forEach(f => {
typeof this.props[f] === 'boolean' && this.linkify.set({ [f]: this.props[f] })
})
}

parseCounter = 0

getMatches(string) {
const linkifyInstance = this.linkify || linkify;

return linkifyInstance.match(string);
return this.linkify.match(string);
}

parseString(string) {
Expand Down
107 changes: 106 additions & 1 deletion src/__tests__/Linkify-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ let TestUtils = require('react-addons-test-utils');

describe('Linkify', () => {
let Linkify = require('../Linkify.jsx').default;
let linkifyCustomizations = require('../Linkify.jsx').config;


describe('#parseString', () => {
let linkify = TestUtils.renderIntoDocument(<Linkify></Linkify>);
Expand Down Expand Up @@ -121,7 +123,7 @@ describe('Linkify', () => {
});
});

describe('#addCustomHandlers', () => {
describe('LinkifyIt config', () => {
it('should match a custom handler added through the "handlers" prop', () => {
const linkify = TestUtils.renderIntoDocument(
<Linkify handlers={[{
Expand Down Expand Up @@ -184,6 +186,109 @@ describe('Linkify', () => {
expect(output[3].props.children).toEqual(input[3]);
expect(output[4]).toEqual(input[4]);
})

it('should apply global customizations', () => {
linkifyCustomizations
.resetAll()
.tlds('linkify', true)
.add('@', {
validate() {
return 7;
},
normalize(match) {
match.url = 'https://twitter.com/' + match.url.replace(/^@/, '');
}
})
const linkify = TestUtils.renderIntoDocument(
<Linkify />
);

const input = ['this is an ', '@mention', ' and ', 'test.linkify', ' TLD handler'];
const output = linkify.parseString(input.join(''));

expect(output[0]).toEqual(input[0]);
expect(output[1].type).toEqual('a');
expect(output[1].props.href).toEqual(`https://twitter.com/mention`);
expect(output[1].props.children).toEqual(input[1]);

expect(output[2]).toEqual(input[2]);
expect(output[3].type).toEqual('a');
expect(output[3].props.href).toEqual(`http://test.linkify`);
expect(output[3].props.children).toEqual(input[3]);
expect(output[4]).toEqual(input[4]);
});

it('should merge global and instance handlers', () => {
linkifyCustomizations
.resetAll()
.add('@', {
validate() {
return 7;
},
normalize(match) {
match.url = 'https://twitter.com/' + match.url.replace(/^@/, '');
}
})
const linkify = TestUtils.renderIntoDocument(
<Linkify handlers={[{
prefix: '$',
validate() {
return 7;
},
normalize(match) {
match.url = 'https://blingtwitter.com/' + match.url.replace(/^\$/, '');
}
}]}
>
</Linkify>
);

const input = ['this is an ', '@mention', ' and ', '$mention', ' handler'];
const output = linkify.parseString(input.join(''));

expect(output[0]).toEqual(input[0]);
expect(output[1].type).toEqual('a');
expect(output[1].props.href).toEqual(`https://twitter.com/mention`);
expect(output[1].props.children).toEqual(input[1]);

expect(output[2]).toEqual(input[2]);
expect(output[3].type).toEqual('a');
expect(output[3].props.href).toEqual(`https://blingtwitter.com/mention`);
expect(output[3].props.children).toEqual(input[3]);
expect(output[4]).toEqual(input[4]);
});

it('should set fuzzy* options', () => {
const linkify = TestUtils.renderIntoDocument(
<Linkify fuzzyLink={ false } />
);

const linkInput = 'this should not match: www.test.com';
const linkOutput = linkify.parseString(linkInput);
expect(linkOutput).toEqual(linkInput);
});

it('should reset global customizations', () => {
linkifyCustomizations
.add('@', {
validate() {
return 7;
},
normalize(match) {
match.url = 'https://twitter.com/' + match.url.replace(/^@/, '');
}
})
.resetAll()

const linkify = TestUtils.renderIntoDocument(
<Linkify />
);

const input = 'this @mention should not match';
const output = linkify.parseString(input);

expect(output).toEqual(input);
})
});

describe('#render', () => {
Expand Down

0 comments on commit 35512d0

Please sign in to comment.