GithubHelp home page GithubHelp logo

jsdf / react-native-htmlview Goto Github PK

View Code? Open in Web Editor NEW
2.7K 46.0 465.0 836 KB

A React Native component which renders HTML content as native views

License: ISC License

JavaScript 97.39% Shell 2.61%
react react-native html html-parser html-renderer react-component

react-native-htmlview's Introduction

React Native HTMLView Build status

A component which takes HTML content and renders it as native views, with customisable style and handling of links, etc.

In action (from ReactNativeHackerNews):

React Native Hacker News Comments

Table of contents

Install

npm install react-native-htmlview --save

Usage

props:

  • value: a string of HTML content to render
  • onLinkPress: a function which will be called with a url when a link is pressed. Passing this prop will override how links are handled (defaults to calling Linking.openURL(url))
  • onLinkLongPress: a function which will be called with a url when a link is long pressed. The default is null.
  • stylesheet: a stylesheet object keyed by tag name, which will override the styles applied to those respective tags.
  • renderNode: a custom function to render HTML nodes however you see fit. If the function returns undefined (not null), the default renderer will be used for that node. The function takes the following arguments:
    • node the html node as parsed by htmlparser2
    • index position of the node in parent node's children
    • siblings parent node's children (including current node)
    • parent parent node
    • defaultRenderer the default rendering implementation, so you can use the normal rendering logic for some subtree. defaultRenderer takes the following arguments:
      • node the node to render with the default rendering logic
      • parent the parent of node of node
  • bullet: text which is rendered before every li inside a ul
  • paragraphBreak: text which appears after every p element
  • lineBreak: text which appears after text elements which create a new line (br, headings)
  • addLineBreaks: when explicitly false, effectively sets paragraphBreak and lineBreak to null
  • NodeComponent, nodeComponentProps, RootComponent, rootComponentProps, TextComponent, textComponentProps: see Customizing things even further below.

Example

import React from 'react';
import {StyleSheet} from 'react-native';
import HTMLView from 'react-native-htmlview';

class App extends React.Component {
  render() {
    const htmlContent = `<p><a href="http://jsdf.co">&hearts; nice job!</a></p>`;

    return (
      <HTMLView
        value={htmlContent}
        stylesheet={styles}
      />
    );
  }
}

const styles = StyleSheet.create({
  a: {
    fontWeight: '300',
    color: '#FF3366', // make links coloured pink
  },
});

Custom Link Handling

When a link is clicked, by default ReactNative.Linking.openURL is called with the link url. You can customise what happens when a link is clicked with onLinkPress:

class App extends React.Component {
  render() {
    return (
      <HTMLView
        value={this.props.html}
        onLinkPress={(url) => console.log('clicked link: ', url)}
      />
    );
  }
}

If you're getting the error "undefined is not an object (evaluating 'RCTLinkingManager.openURL’)” from the LinkingIOS API, try adding ‘RCTLinking' to the project's 'Linked Frameworks and Libraries’. You might have to find RCTLinking.xcodeproj in the react-native package dir and drag that into your main Xcode project first.

Custom Element Rendering

You can implement the renderNode prop to add support for unsupported element types, or override the rendering for supported types. renderNode is a function which is called with the type and attributes of each HTML element found in the input HTML, and from this function you can return a React element to be rendered in its place. If you return null nothing will be rendered in place of this element or its children. If you return undefined (or don't return anything) then HTMLView will drop back to its default rendering for that type of HTML element.

For example, here is how you might implement the <iframe> element:

function renderNode(node, index, siblings, parent, defaultRenderer) {
  if (node.name == 'iframe') {
    const a = node.attribs;
    const iframeHtml = `<iframe src="${a.src}"></iframe>`;
    return (
      <View key={index} style={{width: Number(a.width), height: Number(a.height)}}>
        <WebView source={{html: iframeHtml}} />
      </View>
    );
  }
}

const htmlContent = `
  <div>
    <iframe src="http://info.cern.ch/" width="360" height="300" />
  </div>
`;

class App extends React.Component {
  render() {
    return (
      <HTMLView value={htmlContent} renderNode={renderNode} />
    );
  }
}

Alternatively, this example shows how you could disallow the <iframe> element:

function renderNode(node, index, siblings, parent, defaultRenderer) {
  if (node.name == 'iframe') {
    return null;
  }
}

const htmlContent = `
  <div>
    <iframe src="http://info.cern.ch/" width="360" height="300" />
  </div>
`;

class App extends React.Component {
  render() {
    return (
      <HTMLView value={htmlContent} renderNode={renderNode} />
    );
  }
}

If you want to reuse the default renderer, you need to call it passing an array of nodes. This example shows how to replace a specific HTML tag with something different, but still process the children.

function renderNode(node, index, siblings, parent, defaultRenderer) {
  if (node.name == 'mytag') {
      const specialSyle = node.attribs.style
      return (
        <Text key={index} style={specialSyle}>
          {defaultRenderer(node.children, parent)}
        </Text>
      )
    }
}

const htmlContent = `
  <div>
    <mytag>
      <div>some content processed normally by the engine</div>
    </mytag>
  </div>
`;

class App extends React.Component {
  render() {
    return (
      <HTMLView value={htmlContent} renderNode={renderNode} />
    );
  }
}

For further understanding of the possiblities of the renderNode prop, read through htmlToElement.js. Particularly look at where renderNode is called to see how it can override what sort of React element is created in place of an element in the input HTML.

Customizing things even further

In addition to supplying a custom renderNode function, you can customize what is rendered by the built in renderNode function. Read through htmlToElement.js and note the usage of NodeComponent (for rendering HTML element nodes) and TextComponent (for rendering text strings in the HTML). Both of these components can be injected as the NodeComponent and TextComponent props to HTMLView, or alternatively they can be given extra props by passing an object as the nodeComponentProps and textComponentProps props. Finally you can also use the props RootComponent and rootComponentProps to customize the root wrapper View element that is rendered by the HTMLView in HTMLView.js.

Changelog

See CHANGELOG.md.

react-native-htmlview's People

Contributors

alphasp avatar antares24 avatar blackbing avatar crysfel avatar damusnet avatar douglasjunior avatar helloyou2012 avatar isilher avatar jmacedoit avatar jsdf avatar kengorab avatar koenpunt avatar liu-tim avatar lukejsimonetti avatar macgregorthomson avatar minjaes avatar misaeldossantos avatar nikolaik avatar nobalmohan avatar richchurcher avatar shashkovdanil avatar soska avatar stevenfishercantarus avatar waldyrious avatar wildseansy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-htmlview's Issues

zui le

😌 醉了 找到了三个控件都是ios 的
ri i have drnik find three component are can't use becaust its for ios

Update NPM Package

Hi,

Can you possibly push the recent changes to NPM?

Best regards

Steven Fisher

Open local html file

Hi, i would like if there is a way to open a local html file which loads some local js libs too..
What if i want to host a complete website from inside my app?
Thanks

<p></p> gets too much space after

Hi,

If I have some text like <p>123</p><p>456</p> the final result has like 3 or 4 break lines between the two paragraphs.
I tryed to put negative margins and paddings on p tag style but with no success.
Is there any way reduce that space?
Thanks.

onLinkPress

Hi,
While the htmlContent displays correctly I can't seem to get onLinkPress to work
Thanks,
John

render: function() {

    var htmlContent = '<p><a href="">&hearts; nice job!</a></p>';
       var url = 'http://gooogle.com';
        return (
            <View style={property.color}>
            <Image source={require('../img/glow2.png')} style={property.container}>
                <Navbar
                    title="Property Info"
                    subtitle=""
                    style={property.toolbar}
                    subtitleStyle={property.subtitle}   />          
                <ScrollView style={{marginBottom: 55, backgroundColor: 'transparent'}}>
                    <View style={property.propertyContent}>
                    <Icon name="android-checkbox-outline" size={20} color="rgba(255,255,255,0.9)" style={{position: 'absolute',top:0, left: 0}}/>
                     <Text style={property.content}>Address   {this.state.property.Address} </Text>
                    <HTMLView
                        value={htmlContent}
                        onLinkPress={(url) => console.log('navigating to: ', url)}
                        stylesheet={styles}
                      />  
                     </View>
                </ScrollView>

            </Image>
            </View>
        );
    }

Inline style not supported.

Could not render inline style attribute?
<div dir="ltr" style="text-decoration: underline; font-weight: bold; font-style: italic;">

Height CSS not applying

Hi,

<HTMLView value={htmlContent} stylesheet={stylesShortDesc}/>

and Stylesheet

const stylesShortDesc = StyleSheet.create({
  a: {
     height:55,
    color:'#343434', 
    fontSize:13,
    lineHeight:18
  }

But HTML view is not rendering with custom StyleSheet

WebView not working with renderNode

I'm trying to extend functionality for adding iframes (youtube videos) etc, but it's throwing an error "Views nested within a must have a width and height", where infact, the width and height are explicitly mentioned

renderNode={(node) => {
  if(node.name === 'iframe') {
    console.log(node);
    const iframeHtml = "<iframe"+ {...node.attribs} +"></iframe>";
    return <WebView key={'node_iframe'} source={{html: iframeHtml}} style={{width: 200, height: 200}} />
  }
}}

How to adjust the image style

The picture may cover the text above.
So I want the picture to be spaced from the text.
But do not know how to do it

Center text

Hi everyone,

Is it possible to center text? If I have something like this:
<p> this is some text... bla bla bla </p>

How would I need to set the style to set the text alignment to center?

I tried something like this, which did not work:

let text = "<p>this is some text... bla bla bla </p>";

<View style={styles.wrapper}>
    <HTMLView value={text} stylesheet={styles}/>
</View>

const styles = StyleSheet.create({
    wrapper: {
        alignItems: "center",
  },
   p: {
     textAlign: "center",
}
);

I also tried to set the alignment directly with <p align="right">. Did not work either...

Any help would be appreciated :)

UL OL not showing correct number

Do you know why the generated OL always show even number? eg.below
2. Test
4. Asd.
6. aasdd
8. aaaaa.
10. ddddd

Anybody experience same thing?

Weird spacing/newline issues with some tags

I've noticed some unexpected rendering when dealing with some tags. I've listed three of them here (p, ul, and pre). There's a lot here (reality vs. expectation for each tag), but if you skip to the end I note the part of the code where (I think) the problem/solution lies.

<p> Tags

The html that's passed in here is

1. Use <a href="http//asciiflow.com/" rel="nofollow">http://asciiflow.com/</a> to generate diagram<p>2. Use Ascii to SVG<span></span>

(exactly like that, with no newlines). This produces:

screen shot 2016-10-06 at 9 31 37 pm

What I'd expect to see is something like this:

1. Use http://asciiflow.com/ to generate diagram

2. Use Ascii to SVG

<ul> Tags

The html that's passed in here is

Here is a list: <ul><li>Item 1</li><li>Item 2</li></ul> It was a good list

which produces:

screen shot 2016-10-06 at 9 38 07 pm

What I'd expect to see is something like this:

Here is a list:
    • Item 1
    • Item 2 
It was a good list.

(note that, aside from the newline errors, the rendered version of this html doesn't trim the whitespace preceeding the 'It was a good list' text node. I'll file a separate issue for that.)

<pre> Tags

(This is the last one, I promise...)

The html that's passed in here is

<pre><code>console.log('hello');</code></pre> That was some code

which produces:

screen shot 2016-10-06 at 9 41 40 pm

What I'd expect to see is something like this:

screen shot 2016-10-06 at 9 44 19 pm

(A side issue here is that, by default, the Monaco font is not present in Android, so pre/code nodes just use the normal font family. In the examples above, I set the fontFamily to monospace, which should probably be the default. I'll file a separate issue for that.)


Sorry, this is a rather large issue. I can break this up into separate issues (one per tag maybe?) if it'll make it easier to track progress on it. Although, I think a lot of the problem/solution lies within this block in htmlToElement.js (the expectation screenshot under the <pre> section was taken from a run of my app where, in the htmlToElement.js file, I added another line break after the domToElement function call, if the node was a pre node).

this.setState() won't trigger a re-render of HtmlView

If I set the value prop to some state variable and then set that variable through setState() function, the HtmlView does not get refreshed with the new value. Haven't had much time to check the source for myself.

Tests fail on master

I noticed this when writing #53 and decided to make a separate issue for it. I'll put up a fix soon.

[HELP WANTED] Inserting inside HTMLView as child

Hey, I'm using a combination of Autolinker and HTMLView to render text.

I want to pass something like:
const commentText = <p><a href="http://www.google.com" target="_blank" rel="noopener noreferrer">google.com</a></p>

and render it like:

<View style={[flexStyle, appStyles.chatBubble]}>
    <Text style={appStyles.chatBubbleText}>
       <HTMLView
            value={commentText}
         />
      </Text>
</View>

but when I place HTMLView within another tag, it does not get rendered, any idea on how to achieve this?

Style text not contained in tag

Is there a way to style text not contained in a tag? For instance, in the ReactNativeHackerNews example the beginning of the {comment.text} content is often not included in a tag. Is there a way to apply a style to all of the html content?

Android Support ?

Hi there!

Firstly, this is so awesome!

I was wondering if this supports Android ?

Best Regards.

error because of the require

At the line of my require('react-native-html-webview'); (DumbProduct.js:10:0) it throws the error "undefined is not an object (evaluating 'PropTypes.string").
screenshot_20160607-161453

Funny fact : my index.ios.js file is only 6 lignes long.

onRenderNode not working with image nodes in Android

I'm getting this error rendering my html: Nesting of <View> within <Text> is not supported on Android
The code in my component:

  _onRenderNode = (node, index, siblings, parent, defaultRenderer) => {
	if (node.name == 'img') {
	  return (
		<Image source={'https://i.redd.it/1l01wjsv22my.jpg'} width={50} height={50} />
	  );
	}
  }
  
  render() {
	let myHtml = "<p><img src=\"https://i.redd.it/1l01wjsv22my.jpg\" width=\"10\" height=\"10\" /></p>";
	return (
	  <HTMLView value={myHtml} renderNode = {this._onRenderNode} />
	);
  }

IOS lineHeight

if i changing IOS Setting to get bigger font, the htmlview linehight will be change. how can i fix it to keep the lineheight unchanged

<b> not working on android

Provided this html string we see the bold text showing up in iOS but not on android. On android it appears to be all the same fontWeight.

<b>Bold text</b> not bold

Default styling for all the text

We got response in two format. Sometimes we got HTML tag within the response but sometimes we got plain string.

We do styling bases on the tags like given below. I want to apply the styling for all the text whether they are wrapped in HTML tag or not.

const webViewStyle = StyleSheet.create({ p: { color:"red", }, })

const body = "<p>Display Text</p>"
const body = "Display Text"

<HTMLView style={styles.content} value={subHeader} stylesheet={webViewStyle} />

How to get onPress work?

I hope to handle the event when user click any place on the htmlview, code's followed:
<ScrollView style={{flex: 1}}> <HTMLView style={{flex: 1}} value={this.state.content} onPress={() => this._toggleToolbar()} /> </ScrollView>

Text elements don't support a lot of formatting that Views do

So I tried writing some CSS to style a div and that didn't work well at all. Started digging into why and find that most everything is a <Text> element which does very little when it comes to layout. I don't know why <Text> elements don't do it, but they don't.

So I coded up a simple renderer to compensate for this and show the issue and hope to discuss how to best go forward with a real fix.

function myDomElement(node, index, list, parent, origRenderer) {
    console.log(node);
    if(node.name === 'div') {
        return (<View style={ {paddingLeft: 25} }>
                    <Text>{ node.children[0].data }</Text>
                </View>);
    }
    return undefined;
}

-------------
                <HTMLView
                    value={ HTML}
                    stylesheet={ styles }
                    renderNode= { myDomElement }
                />

When I surround the <Text> element with a <View> I can now do things like padding (and borders). Where the <Text> element will ignore those stylings, but will happily accept font specifications.

I'm wondering aloud here if it makes sense to just wrap every <Text> in a <View> and hand them both the styles for that tag, but I seem to remember <Text> being a bit indignant about certain layoutProps so it probably needs a function to divide the styles according to some set of rules.

The real fix is probably for react-native to support all the styling in all the elements but pretty sure that will not fit in my time table too well.

Ideas? Cautions? What's a good way to approach this? I'm fairly new to react-native (less than 10 hours) so I'm hoping someone with some more experience can give me some guidance.

Error installing newest version (0.7.1)

Hi,

Thanks for making such useful plugin, I was previously using 0.5.0 and tried to update to newest version, however I am getting errors when installing from npm or yarn, here are the screenshots:
screen shot 2017-03-18 at 5 13 16 pm
screen shot 2017-03-18 at 5 14 03 pm
Am I doing it correctly? Am I missing something?

Cheers.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.