Skip to content

Commit 3f750b7

Browse files
gnestorrgbkrk
authored andcommitted
Add linkify prop and make linkify false by default (#20)
1 parent 5ea930a commit 3f750b7

File tree

3 files changed

+47
-26
lines changed

3 files changed

+47
-26
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"babel": {
2424
"presets": [
2525
"es2015",
26+
"stage-3",
2627
"react"
2728
]
2829
},
@@ -40,6 +41,7 @@
4041
"babel-core": "^6.8.0",
4142
"babel-preset-es2015": "^6.6.0",
4243
"babel-preset-react": "^6.5.0",
44+
"babel-preset-stage-3": "^6.22.0",
4345
"chai": "^3.5.0",
4446
"enzyme": "^2.2.0",
4547
"mkdirp": "0.5.1",

src/index.js

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,42 +37,54 @@ function ansiToInlineStyle(text) {
3737
return ansiToJSON(text).map(ansiJSONtoStyleBundle);
3838
}
3939

40+
function linkifyBundle(bundle) {
41+
return {
42+
...bundle,
43+
content: bundle.content.split(' ').reduce(
44+
(result, word) => {
45+
// If word is a URL
46+
if (/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.test(word)) {
47+
return [
48+
...result,
49+
' ',
50+
React.createElement('a', {
51+
href: word ,
52+
target: '_blank'
53+
}, `${word}`)
54+
];
55+
}
56+
const lastWord = result.pop();
57+
if (lastWord) {
58+
// If lastWord is a `<a>` element
59+
if (lastWord.type) return [...result, lastWord, ' ', word];
60+
// If not, combine lastWord and word into single string
61+
return [...result, [lastWord, word].join(' ')];
62+
}
63+
// If there is no lastWord because word is the first
64+
return [...result, word];
65+
},
66+
[]
67+
)
68+
}
69+
}
70+
4071
function inlineBundleToReact(bundle, key) {
41-
const children = bundle.content.split(' ').reduce(
42-
(result, word) => {
43-
// If word is a URL
44-
if (/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.test(word)) {
45-
return [
46-
...result,
47-
React.createElement('a', {
48-
href: word ,
49-
target: '_blank'
50-
}, `${word} `)
51-
];
52-
}
53-
const lastWord = result.pop();
54-
if (lastWord) {
55-
// If lastWord is a `<a>` element
56-
if (lastWord.type) return [...result, lastWord, word];
57-
// If not, combine lastWord and word into single string
58-
return [...result, [lastWord, word].join(' ')];
59-
}
60-
// If there is no lastWord because word is the first
61-
return [...result, word];
62-
},
63-
[]
64-
);
6572
return React.createElement('span', {
6673
style: bundle.style,
6774
key,
68-
}, children);
75+
}, bundle.content);
6976
}
7077

7178
function Ansi(props) {
7279
return React.createElement(
7380
'code',
7481
{},
75-
ansiToInlineStyle(props.children).map(inlineBundleToReact));
82+
props.linkify
83+
? ansiToInlineStyle(props.children)
84+
.map(linkifyBundle)
85+
.map(inlineBundleToReact)
86+
: ansiToInlineStyle(props.children).map(inlineBundleToReact)
87+
);
7688
}
7789

7890
Ansi.propTypes = {

test/index-spec.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,11 @@ describe('Ansi', () => {
3333
expect(el).to.not.be.null;
3434
expect(el.text()).to.equal('that sentence\nwill make you pause');
3535
});
36+
37+
it('can linkify', () => {
38+
const el = enzyme.shallow(React.createElement(Ansi, {linkify: true}, 'this is a link: https://nteract.io/'));
39+
expect(el).to.not.be.null;
40+
expect(el.text()).to.equal('this is a link: https://nteract.io/');
41+
expect(el.html()).to.equal('<code><span>this is a link: <a href="https://nteract.io/" target="_blank">https://nteract.io/</a></span></code>');
42+
});
3643
});

0 commit comments

Comments
 (0)