diff --git a/__tests__/tests/components/GithubHtmlView.js b/__tests__/tests/components/GithubHtmlView.js new file mode 100644 index 000000000..04fe79d8c --- /dev/null +++ b/__tests__/tests/components/GithubHtmlView.js @@ -0,0 +1,77 @@ +import React from 'react'; +import { Text } from 'react-native'; +import renderer from 'react-test-renderer'; +import { GithubHtmlView } from 'components'; +import { Icon } from 'react-native-elements'; + +describe('', () => { + it('correctly renders
tag in GithubHtmlView with correct icon', () => { + const sourceHtml = ` +
+ title +
description
+
+ `; + + const inst = renderer.create( + 0} /> + ); + + expect(inst.root.findByType(Icon).props.name).toEqual('triangle-right'); + }); + + it('if tag contains a single text node, we shoud prettify it', () => { + const sourceHtml = ` +
+ + make some space and line break here... + + +
description
+
+ `; + + const inst = renderer.create( + 0} /> + ); + + expect( + !!inst.root + .findAllByType(Text) + .find( + e => e.props.children === 'make some space and line break here...' + ) + ).toBe(true); + }); + + it('if there is no tag, we should do fallback render which contains no icon', () => { + const sourceHtml = ` +
+
no summary here!!
+
+ `; + + const inst = renderer.create( + 0} /> + ); + + expect(inst.root.findAllByType(Icon).length).toBe(0); + }); + + it('if contain nested tags, should still be rendered without exception', () => { + const sourceHtml = ` +
+ + abcde
test
fg +
+
no summary here!!
+
+ `; + + const inst = renderer.create( + 0} /> + ); + + expect(inst.root.findByType(Icon).props.name).toEqual('triangle-right'); + }); +}); diff --git a/src/components/github-htmlview.component.js b/src/components/github-htmlview.component.js index 0b9b775b1..14ea0c241 100644 --- a/src/components/github-htmlview.component.js +++ b/src/components/github-htmlview.component.js @@ -5,6 +5,7 @@ import { TableWrapper, Table, Cell } from 'react-native-table-component'; import SyntaxHighlighter from 'react-native-syntax-highlighter'; import { github as GithubStyle } from 'react-syntax-highlighter/dist/styles'; import entities from 'entities'; +import { Icon } from 'react-native-elements'; import { ImageZoom, ToggleView } from 'components'; import { colors, fonts, normalize } from 'config'; @@ -386,6 +387,53 @@ export class GithubHtmlView extends Component { ); }, + details: (node, index, siblings, parent, defaultRenderer) => { + const summaryTagIdx = node.children.findIndex( + n => n.type === 'tag' && n.name === 'summary' + ); + const summaryTag = node.children[summaryTagIdx]; + + if (!summaryTag) { + // we have a details tag without summary, rollback to default render + return {defaultRenderer(node.children, node)}; + } + + const childrenWithoutSummary = [...node.children]; // don't touch the original data + + childrenWithoutSummary.splice(summaryTagIdx, 1); + + const renderSummary = tag => { + if (tag.children.length === 1 && tag.children[0].type === 'text') { + // if we only have one text child, make it prettier + // by removing line break and triming space + return ( + + {tag.children[0].data.replace(/\s\s+/g, ' ').trim()} + + ); + } + + return defaultRenderer(tag.children, tag); + }; + + return ( + ( + + + {renderSummary(summaryTag)} + + )} + > + {defaultRenderer(childrenWithoutSummary, node)} + + ); + }, }; if (_node.type === 'text') { diff --git a/src/components/toggle-view.component.js b/src/components/toggle-view.component.js index 03797a6b2..021637906 100644 --- a/src/components/toggle-view.component.js +++ b/src/components/toggle-view.component.js @@ -6,6 +6,7 @@ export class ToggleView extends Component { props: { children: any, TouchableView: any, + renderTouchable: Function, }; state: { @@ -28,7 +29,9 @@ export class ToggleView extends Component { return ( this._toggle()}> - {this.props.TouchableView} + {this.props.renderTouchable + ? this.props.renderTouchable(this.state.collapsed) + : this.props.TouchableView} {this.props.children}