Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions Demo/ios/Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,48 @@
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
remoteInfo = RCTText;
};
9C0B832A202B096F00034121 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3DBE0D001F3B181A0099AA32;
remoteInfo = fishhook;
};
9C0B832C202B096F00034121 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32;
remoteInfo = "fishhook-tvOS";
};
9C0B833E202B096F00034121 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = EBF21BDC1FC498900052F4D5;
remoteInfo = jsinspector;
};
9C0B8340202B096F00034121 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = EBF21BFA1FC4989A0052F4D5;
remoteInfo = "jsinspector-tvOS";
};
9C0B8342202B096F00034121 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 9936F3131F5F2E4B0010BF04;
remoteInfo = privatedata;
};
9C0B8344202B096F00034121 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 9936F32F1F5F2E5B0010BF04;
remoteInfo = "privatedata-tvOS";
};
ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */;
Expand Down Expand Up @@ -428,6 +470,8 @@
children = (
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */,
9C0B832B202B096F00034121 /* libfishhook.a */,
9C0B832D202B096F00034121 /* libfishhook-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -457,10 +501,14 @@
3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */,
3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */,
3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */,
9C0B833F202B096F00034121 /* libjsinspector.a */,
9C0B8341202B096F00034121 /* libjsinspector-tvOS.a */,
D2AEA03F1F6C07B100D823F6 /* libthird-party.a */,
D2AEA0411F6C07B100D823F6 /* libthird-party.a */,
D2AEA0431F6C07B100D823F6 /* libdouble-conversion.a */,
D2AEA0451F6C07B100D823F6 /* libdouble-conversion.a */,
9C0B8343202B096F00034121 /* libprivatedata.a */,
9C0B8345202B096F00034121 /* libprivatedata-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -894,6 +942,48 @@
remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
9C0B832B202B096F00034121 /* libfishhook.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libfishhook.a;
remoteRef = 9C0B832A202B096F00034121 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
9C0B832D202B096F00034121 /* libfishhook-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libfishhook-tvOS.a";
remoteRef = 9C0B832C202B096F00034121 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
9C0B833F202B096F00034121 /* libjsinspector.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libjsinspector.a;
remoteRef = 9C0B833E202B096F00034121 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
9C0B8341202B096F00034121 /* libjsinspector-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libjsinspector-tvOS.a";
remoteRef = 9C0B8340202B096F00034121 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
9C0B8343202B096F00034121 /* libprivatedata.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libprivatedata.a;
remoteRef = 9C0B8342202B096F00034121 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
9C0B8345202B096F00034121 /* libprivatedata-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libprivatedata-tvOS.a";
remoteRef = 9C0B8344202B096F00034121 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
Expand Down
2 changes: 1 addition & 1 deletion Demo/ios/Demo/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Demo</string>
<string>RenderHTML</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
Expand Down
2 changes: 1 addition & 1 deletion Demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"dependencies": {
"react": "16.2.0",
"react-native": "0.52.0",
"react-native-render-html": "3.7.0"
"react-native-render-html": "3.8.0"
},
"devDependencies": {
"babel-jest": "22.0.6",
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Prop | Description | Type | Required/Default
`remoteErrorView` | Replace the default error if a remote website's content could not be fetched | `function` | Optional
`emSize` | The default value in pixels for `1em` | `number` | `14`
`baseFontStyle` | The default style applied to `<Text>` components | `number` | `14`
`textSelectable` | Allow all texts to be selected | `boolean` | `false`
`alterData` | Target some specific texts and change their content, see [altering content](#altering-content) | `function` | Optional
`alterChildren` | Target some specific nested children and change them, see [altering content](#altering-content) | `function` | Optional
`alterNode` | Target a specific node and change it, see [altering content](#altering-content) | `function` | Optional
Expand Down Expand Up @@ -295,7 +296,7 @@ You can't expect native components to be able to render *everything* you can fin
**Please note** that if you supply `ignoredTags`, you will override the default ignored ones. There are *a lot* of them, if you want to keep them and add you own, you can do something like :

```javascript
import { IGNORED_TAGS } from 'react-native-render-html/HTMLUtils';
import { IGNORED_TAGS } from 'react-native-render-html/src/HTMLUtils';
...

// your props
Expand All @@ -320,3 +321,7 @@ import { functionName } from 'react-native-render-html/src/HTMLUtils';
* Parameters : - `node` : a parsed HTML node from `alterChildren` for example
* Returns : An empty array or an array of strings.
* Notes : this is very useful to check if a node is nested in a specific parent. See [alterNode](#alterNode) for an advanced example.
* `getClosestNodeParentByTag(node, tag)`
* Description: Returns the closest parent of a node with a specific tag.
* Parameters : - `node` : a parsed HTML node from `alterChildren` for example
* Returns : An HTML node if found.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-render-html",
"version": "3.7.0",
"version": "3.8.0",
"author": "Archriss",
"license": "BSD-2-Clause",
"repository": "https://github.com/archriss/react-native-render-html",
Expand All @@ -17,7 +17,6 @@
"events": "^1.1.0",
"html-entities": "^1.2.0",
"htmlparser2": "^3.9.0",
"lodash.isequal": "4.5.0",
"stream": "0.0.2"
},
"peerDependencies": {
Expand Down
55 changes: 30 additions & 25 deletions src/HTML.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { BLOCK_TAGS, TEXT_TAGS, MIXED_TAGS, IGNORED_TAGS, TEXT_TAGS_IGNORING_ASS
import { cssStringToRNStyle, _getElementClassStyles, cssStringToObject, cssObjectToString } from './HTMLStyles';
import { generateDefaultBlockStyles, generateDefaultTextStyles } from './HTMLDefaultStyles';
import htmlparser2 from 'htmlparser2';
import _isEqual from 'lodash.isequal';
import * as HTMLRenderers from './HTMLRenderers';

export default class HTML extends PureComponent {
Expand Down Expand Up @@ -34,7 +33,8 @@ export default class HTML extends PureComponent {
height: PropTypes.number
}),
emSize: PropTypes.number.isRequired,
baseFontStyle: PropTypes.object.isRequired
baseFontStyle: PropTypes.object.isRequired,
textSelectable: PropTypes.bool
}

static defaultProps = {
Expand All @@ -46,7 +46,8 @@ export default class HTML extends PureComponent {
ignoredStyles: [],
baseFontStyle: { fontSize: 14 },
tagsStyles: {},
classesStyles: {}
classesStyles: {},
textSelectable: false
}

constructor (props) {
Expand All @@ -56,7 +57,6 @@ export default class HTML extends PureComponent {
...HTMLRenderers,
...(this.props.renderers || {})
};
this.imgsToRender = [];
}

componentWillMount () {
Expand All @@ -68,17 +68,19 @@ export default class HTML extends PureComponent {
}

componentWillReceiveProps (nextProps) {
const { html, uri, renderers, baseFontStyle } = this.props;
const { html, uri, renderers } = this.props;

if (html !== nextProps.html || uri !== nextProps.uri) {
this.imgsToRender = [];
this.registerDOM(nextProps);
}
this.generateDefaultStyles(nextProps.baseFontStyle);
if (renderers !== nextProps.renderers) {
this.renderers = { ...HTMLRenderers, ...(nextProps.renderers || {}) };
}
if (!_isEqual(baseFontStyle, nextProps.baseFontStyle)) {
this.generateDefaultStyles(nextProps.baseFontStyle);
if (html !== nextProps.html || uri !== nextProps.uri) {
// If the source changed, register the new HTML and parse it
this.registerDOM(nextProps);
} else {
// If it didn't, let's just parse the current DOM and re-render the nodes
// to compute potential style changes
this.parseDOM(this.state.dom, nextProps);
}
}

Expand All @@ -88,7 +90,7 @@ export default class HTML extends PureComponent {
}
}

async registerDOM (props = this.props) {
async registerDOM (props = this.props, cb) {
const { html, uri } = props;
if (html) {
this.setState({ dom: html, loadingRemoteURL: false, errorLoadingRemoteURL: false });
Expand All @@ -113,18 +115,18 @@ export default class HTML extends PureComponent {
}
}

parseDOM (dom) {
parseDOM (dom, props = this.props) {
const { decodeEntities, debug, onParsed } = this.props;
const parser = new htmlparser2.Parser(
new htmlparser2.DomHandler((_err, dom) => {
let RNElements = this.mapDOMNodesTORNElements(dom);
let RNElements = this.mapDOMNodesTORNElements(dom, false, props);
if (onParsed) {
const alteredRNElements = onParsed(dom, RNElements);
if (alteredRNElements) {
RNElements = alteredRNElements;
}
}
this.setState({ RNNodes: this.renderRNElements(RNElements) });
this.setState({ RNNodes: this.renderRNElements(RNElements, 'root', 0, props) });
if (debug) {
console.log('DOMNodes from htmlparser2', dom);
console.log('RNElements from render-html', RNElements);
Expand All @@ -141,8 +143,8 @@ export default class HTML extends PureComponent {
this.defaultTextStyles = generateDefaultTextStyles(baseFontStyle.fontSize || 14);
}

filterBaseFontStyles (element, classStyles) {
const { tagsStyles, baseFontStyle } = this.props;
filterBaseFontStyles (element, classStyles, props = this.props) {
const { tagsStyles, baseFontStyle } = props;
const { tagName, parentTag, parent, attribs } = element;
const styles = Object.keys(baseFontStyle);
let appliedStyles = {};
Expand Down Expand Up @@ -247,8 +249,8 @@ export default class HTML extends PureComponent {
* @returns
* @memberof HTML
*/
mapDOMNodesTORNElements (DOMNodes, parentTag = false) {
const { ignoreNodesFunction, ignoredTags, alterNode, alterData, alterChildren, tagsStyles, classesStyles } = this.props;
mapDOMNodesTORNElements (DOMNodes, parentTag = false, props = this.props) {
const { ignoreNodesFunction, ignoredTags, alterNode, alterData, alterChildren, tagsStyles, classesStyles } = props;
let RNElements = DOMNodes.map((node, nodeIndex) => {
let { children, data } = node;
if (ignoreNodesFunction && ignoreNodesFunction(node, parentTag) === true) {
Expand Down Expand Up @@ -388,8 +390,8 @@ export default class HTML extends PureComponent {
* @returns {array}
* @memberof HTML
*/
renderRNElements (RNElements, parentWrapper = 'root', parentIndex = 0) {
const { tagsStyles, classesStyles, emSize, ignoredStyles } = this.props;
renderRNElements (RNElements, parentWrapper = 'root', parentIndex = 0, props = this.props) {
const { tagsStyles, classesStyles, emSize, ignoredStyles } = props;
return RNElements && RNElements.length ? RNElements.map((element, index) => {
const { attribs, data, tagName, parentTag, children, nodeIndex, wrapper } = element;
const Wrapper = wrapper === 'Text' ? Text : View;
Expand All @@ -404,7 +406,7 @@ export default class HTML extends PureComponent {
{};

const childElements = children && children.length ?
children.map((child, childIndex) => this.renderRNElements([child], wrapper, index)) :
children.map((child, childIndex) => this.renderRNElements([child], wrapper, index, props)) :
false;

if (this.renderers[tagName]) {
Expand All @@ -423,7 +425,7 @@ export default class HTML extends PureComponent {
childElements,
convertedCSSStyles,
{
...this.props,
...props,
parentWrapper: wrapper,
parentTag,
nodeIndex,
Expand All @@ -435,8 +437,9 @@ export default class HTML extends PureComponent {
}

const classStyles = _getElementClassStyles(attribs, classesStyles);
const textElementStyles = this.filterBaseFontStyles(element, classStyles, props);
const textElement = data ?
<Text style={this.filterBaseFontStyles(element, classStyles)}>{ data }</Text> :
<Text style={textElementStyles}>{ data }</Text> :
false;

const style = [
Expand All @@ -447,8 +450,10 @@ export default class HTML extends PureComponent {
]
.filter((s) => s !== undefined);

const extraProps = {};
if (Wrapper === Text) extraProps.selectable = this.props.textSelectable;
return (
<Wrapper key={key} style={style}>
<Wrapper key={key} style={style} {...extraProps}>
{ textElement }
{ childElements }
</Wrapper>
Expand Down
1 change: 1 addition & 0 deletions src/HTMLDefaultStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function generateDefaultTextStyles (baseFontSize = BASE_FONT_SIZE) {
em: { fontStyle: 'italic' },
i: { fontStyle: 'italic' },
b: { fontWeight: 'bold' },
s: { textDecorationLine: 'line-through' },
strong: { fontWeight: 'bold' },
big: { fontSize: baseFontSize * 1.2 },
small: { fontSize: baseFontSize * 0.8 },
Expand Down
Loading