Skip to content

Commit

Permalink
Merge branch 'release/0.1.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
jogoodma committed Jul 3, 2018
2 parents 994ce7b + b2b43e4 commit 030bd00
Show file tree
Hide file tree
Showing 10 changed files with 870 additions and 708 deletions.
131 changes: 130 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,136 @@
[![npm package][npm-badge]][npm]
[![Coveralls][coveralls-badge]][coveralls]

Describe react-flybase-utils here.
## React FlyBase Utils

This is a collection of miscellaneous utilies for working with FlyBase
data in React.

### Getting started

```
yarn add https://github.com/FlyBase/react-flybase-utils.git
or
npm install https://github.com/FlyBase/react-flybase-utils.git
```

### Components

#### SupSubFormatter -

#####Description
Accepts a string via either the `text` parameter or a single `children`
element which contains FlyBase notations for super and subscripts and returns a React
element. The React element will have all FlyBase tags converted to their HTML equivalent.

#####Parameters:
- text - A string containing FlyBase symbol notations.
- children - Same as text.

#####Returns:
- A react element with tags converted to their html equivalents.

#####Tags currently converted: `<up />`, `<down />`

#####Examples:

```
import React from 'react';
import { SupSubFormatter } from 'react-flybase-utils';
export default () => <SupSubFormatter text={'mysymbol<up>1234</up>'} />;
```
or
```
import React from 'react';
import { SupSubFormatter } from 'react-flybase-utils';
export default () => <SupSubFormatter>{'mysymbol<up>1234</up>'}</SupSubFormatter>;
```

#### CurationStampParser -

#####Description
Accepts a string via either the `text` parameter or a single `children`
element which contains FlyBase notations for embedded symbols in text statements.
This component also passes the `@` delimited text through `<SupSubFormatter />` component.

#####Parameters:
- text - A string containing FlyBase symbol notations.
- children - Same as text.
- baseURI - The base URI to use for the link. Default: ''

#####Returns:
- A react fragment with stamped text entities converted into links to
FlyBase searches or links directly to reports.

#####Examples:

```
import React from 'react';
import { CurationStampParser } from 'react-flybase-utils';
const myText = 'blah @mygene@ blah blah';
export default () => <CurationStampParser>{myText}</CurationStampParser>;
```
or
```
import React from 'react';
import { CurationStampParser } from 'react-flybase-utils';
const myText = 'blah @mygene@ blah blah';
export default () => <CurationStampParser text={myText} />;
```
#### ReportLink -

#####Description
A simple component for forming links to FlyBase reports.

#####Parameters:
- fbid - The FlyBase ID to establish a link to.
- text - A string to be used for link text. Curation `<up/>` and `<down/>` tags are supported.
- children - Same as text.
- baseURI - The base URI to use for the link. Default: ''

#####Returns:
- A react link element pointing directly to the report.

#####Examples:

```
import React from 'react';
import { ReportLink } from 'react-flybase-utils';
export default () => <ReportLink fbid={'FBgn12345'} text={'mygene'} />;
```
or
```
import React from 'react';
import { ReportLink } from 'react-flybase-utils';
export default () => <ReportLink fbid={'FBgn12345'}>{'mygene'}</ReportLink>;
```

### Utility functions and constants

#### Symbols

##### SgmlToAscii -

##### Description
Takes a string and converts all curation notations of `<up />` and `<down />` to their ASCII equivalents.

##### Parameters:
- text - The text to parse.

##### Returns:
- An string representing the ASCII version of the symbol.

##### Examples:

```
import { Symbols } from 'react-flybase-utils';
const asciiSymbol = Symbols.SgmlToAscii('mygene<up>12345</up>');
console.log(asciiSymbol); // Logs mygene[12345]
```


[build-badge]: https://img.shields.io/travis/user/repo/master.png?style=flat-square
[build]: https://travis-ci.org/user/repo
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-flybase-utils",
"version": "0.1.1",
"version": "0.1.2",
"description": "A react component and function library for FlyBase",
"main": "lib/index.js",
"module": "es/index.js",
Expand Down Expand Up @@ -36,7 +36,7 @@
},
"author": "Josh Goodman",
"homepage": "",
"license": "Apache 2.0",
"license": "Apache-2.0",
"repository": "https://github.com/FlyBase/react-flybase-utils.git",
"keywords": [
"react-component",
Expand Down
25 changes: 25 additions & 0 deletions src/components/CurationStampParser/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,29 @@ describe('<CurationStampParser />', () => {
expect(wrapper.find('a[href="/search/Rnor%5CmyGene%5Bup%5D"]').length).toBe(1);
});

it('Blank', () => {
const wrapper = shallow(<CurationStampParser text={''} />);
expect(wrapper.isEmptyRender()).toBe(true);
});

it('null', () => {
const wrapper = shallow(<CurationStampParser text={null} />);
expect(wrapper.isEmptyRender()).toBe(true);
});

it('Link via children', () => {
const wrapper = mount(<CurationStampParser>blah @myGene@ blah</CurationStampParser>);
expect(wrapper.find('a[href="/search/myGene"]').length).toBe(1);
});

it('Link with FBid (children)', () => {
const wrapper = mount(<CurationStampParser>blah @FBgn12345:myGene@ blah</CurationStampParser>);
expect(wrapper.find('a[href="/reports/FBgn12345"]').length).toBe(1);
});

it('Link with FBid (text)', () => {
const wrapper = mount(<CurationStampParser text={'blah @FBgn12345:myGene@ blah'} />);
expect(wrapper.find('a[href="/reports/FBgn12345"]').length).toBe(1);
});

});
74 changes: 51 additions & 23 deletions src/components/CurationStampParser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,71 @@ import React, { Fragment } from 'react';
import PropTypes from 'prop-types';

import SupSubFormatter from '../SupSubFormatter';
import ReportLink from '../ReportLink';

import { SgmlToAscii } from '../../utils/Symbols';

// Pattern to match @ stamps, text leading @stamps, and everything else.
const AT_STAMP_SEARCH_PATTERN = /@\S+@|.+?(?=@\S+@)|.+/g;
// Pattern to match isolated at stamps.
const ISOLATED_AT_STAMPS = /^@(\S+)@$/;

const FLYBASE_IDS = /^(FB\w{2}\d+):/i;

/**
* Component that accepts text and replaces curator
* stamps with search links.
*
* e.g. blah @mygene@ -> blah <a href="/search/mygene">mygene</a>
*
* @param text - The text to process.
* @constructor
* @param children - The text to process
* @param baseURI - The base URI to use for the links.
*
* @returns A React.Fragment with text and '@' stamps turned into links to searches or reports.
*/
function CurationStampParser({text}) {
const pattern = /@\S+@|.+?(?=@\S+@)|.+/g;

const arr = text.match(pattern);

return (
<Fragment>
{arr.map((val,i) => {
const atsRe = /^@(\S+)@$/;
if (atsRe.test(val)) {
const linkText = val.replace(atsRe,'$1');
return (
<a key={i} href={`/search/${encodeURI(SgmlToAscii(linkText))}`}>
<SupSubFormatter text={linkText}/>
</a>
);
}
return val;
})}
</Fragment>
);
function CurationStampParser({text, children, baseURI}) {
const textToSearch = (text) ? text : children;

if (textToSearch && textToSearch.length > 0) {
// Get an array of text matches.
const arr = textToSearch.match(AT_STAMP_SEARCH_PATTERN);

// Iterate over array and process isolated @ stamps.
return (
<Fragment>
{arr.map((val, i) => {
if (ISOLATED_AT_STAMPS.test(val)) {
const linkText = val.replace(ISOLATED_AT_STAMPS, '$1');
const idMatch = FLYBASE_IDS.exec(linkText);

if (idMatch && idMatch[1]) {
return <ReportLink key={idMatch[1]} fbid={idMatch[1]} text={linkText} baseURI={baseURI} />;
}
else {
return (
<a key={i} href={`${baseURI}/search/${encodeURI(SgmlToAscii(linkText))}`}>
<SupSubFormatter>{linkText}</SupSubFormatter>
</a>
);
}
}
return val;
})}
</Fragment>
);
}
return null;
}

CurationStampParser.propTypes = {
text: PropTypes.string.isRequired,
text: PropTypes.string,
children: PropTypes.string,
baseURI: PropTypes.string,
}

CurationStampParser.defaultProps = {
baseURI: '',
}

export default CurationStampParser;
Expand Down
5 changes: 5 additions & 0 deletions src/components/ReportLink/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@ describe('<ReportLink />', () => {
const wrapper = mount(<ReportLink fbid={'FBgn0000001'} text={'blah<down>down</down>'}/>);
expect(wrapper.contains(<sub>down</sub>)).toBe(true);
});

it('Link children w/ sub', () => {
const wrapper = mount(<ReportLink fbid={'FBgn0000001'}>{'blah<down>down</down>'}</ReportLink>);
expect(wrapper.contains(<sub>down</sub>)).toBe(true);
});
});

19 changes: 14 additions & 5 deletions src/components/ReportLink/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ import SupSubFormatter from '../SupSubFormatter';
*
* @param fbid - The FlyBase ID to link to.
* @param text - The text to use for the link text.
* @constructor
* @param baseURI - The base URI to use for the link.
*/
function ReportLink({ fbid, text }) {
const url = `/reports/${fbid}`;
function ReportLink({ fbid, text, children, baseURI }) {
const linkText = (text) ? text : children;
const url = `${baseURI}/reports/${fbid}`;
return (
<a href={url}>
<SupSubFormatter text={text} />
<SupSubFormatter>
{linkText}
</SupSubFormatter>
</a>
);
}
Expand All @@ -31,7 +34,13 @@ ReportLink.propTypes = {
);
}
},
text: PropTypes.string.isRequired,
text: PropTypes.string,
children: PropTypes.string,
baseURI: PropTypes.string,
}

ReportLink.defaultProps = {
baseURI: '',
}

export default ReportLink;
21 changes: 8 additions & 13 deletions src/components/SupSubFormatter/__tests__/index.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Fragment } from 'react';
import React from 'react';
import expect from 'expect';
import { shallow } from 'enzyme';

Expand All @@ -17,21 +17,16 @@ describe('<SupSubFormatter />', () =>{

it('Insertion symbol', () => {
const wrapper = shallow(<SupSubFormatter text={'P{GawB}Eip63F-1<up>55B</up>'}/>);
const wanted = (
<Fragment>
{'P{GawB}Eip63F-1'}<sup>55B</sup>
</Fragment>
);
expect(wrapper.equals(wanted)).toEqual(true);
expect(wrapper.html()).toEqual('P{GawB}Eip63F-1<sup>55B</sup>');
});

it('Allele symbol', () => {
const wrapper = shallow(<SupSubFormatter text={'cnn<up>HK21</up>'}/>);
const wanted = (
<Fragment>
cnn<sup>HK21</sup>
</Fragment>
);
expect(wrapper.equals(wanted)).toEqual(true);
expect(wrapper.html()).toEqual('cnn<sup>HK21</sup>');
});

it('Child string elements', () => {
const wrapper = shallow(<SupSubFormatter>{'cnn<up>HK21</up>'}</SupSubFormatter>);
expect(wrapper.html()).toEqual('cnn<sup>HK21</sup>');
});
});
8 changes: 5 additions & 3 deletions src/components/SupSubFormatter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,18 @@ function transform(node,index) {
* @returns {React Element} - An element
* @constructor
*/
function SupSubFormatter({text}) {
function SupSubFormatter({text,children}) {
return (
<Fragment>
{ ReactHtmlParser(text, { transform: transform}) }
{ text && ReactHtmlParser(text, { transform: transform}) }
{ children && ReactHtmlParser(children, { transform: transform}) }
</Fragment>
);
}

SupSubFormatter.propTypes = {
text: PropTypes.string.isRequired,
text: PropTypes.string,
children: PropTypes.string,
};

SupSubFormatter.defaultProps = {
Expand Down
Loading

0 comments on commit 030bd00

Please sign in to comment.