React-native-render-html: TypeScript support

Created on 3 May 2018  路  15Comments  路  Source: meliorence/react-native-render-html

Hi,

Would you be open to a PR to add .d.ts type file(s) to your project for typescript support?

help wanted new feature

Most helpful comment

@Exilz I am writing a more accurate version of typescript definitions for my own usage, with comments from your documentation.
I'll offer a PR when it's complete enough, but bellow is a draft:

declare module 'react-native-render-html' {
  import { ComponentType, ReactNode } from "react"
  import { StyleProp, Text, View, GestureResponderEvent, RecursiveArray, Falsy } from "react-native"
  namespace HTML {
    type HTMLNode = any
    type NonRegisteredStylesProp<T> = T | Falsy | RecursiveArray<T | Falsy>
    type HtmlAttributesDictionary = {
      [attribute: string]: string
    }
    type PassProps<T> = any
    type RendererFunction = <T>(htmlAttribs: HtmlAttributesDictionary, children: HTMLNode[], convertedCSSStyles: NonRegisteredStylesProp<any>, passProps: PassProps<T>) => ReactNode
    type RendererDeclaration = RendererFunction | { renderer: RendererFunction, wrapper: 'Text' | 'View' }
    type RendererDictionary = {
      [tag: string]: RendererDeclaration
    }
    type StylesDictionary = {
      [tag: string]: NonRegisteredStylesProp<any>
    }
    type ImageDimensions = {
      width: number,
      height: number
    }
    interface ContainerProps {
      /**
       * HTML string to parse and render
       */
      html: string
      /**
       * Resize your images to this maximum width.
       */
      imagesMaxWidth?: number
      /**
       * Your custom renderers.
       */
      renderers?: RendererDictionary
      /**
       * Your custom renderers from ul and ol bullets, see [lists prefixes](https://github.com/archriss/react-native-render-html#lists-prefixes)
       */
      listsPrefixesRenderers?: RendererDictionary
      /**
       * Remote website to parse and render
       */
      uri?: string
      /**
       * Decode HTML entities of your content.
       * Optional, defaults to true
       */
      decodeEntities?: boolean
      /**
       * Set a maximum width to non-responsive content (<iframe> for instance)
       */
      staticContentMaxWidth?: number
      /**
       * Default width and height to display while image's dimensions are being retrieved.
       */
      imagesInitialDimensions?: ImageDimensions
      /**
       * Fired with the event, the href and an object with all attributes of the tag as its arguments when tapping a link
       */
      onLinkPress?: (event: GestureResponderEvent, href: string, htmlAttribs: HtmlAttributesDictionary) => void
      /**
       * Fired when your HTML content has been parsed. Also useful to tweak your rendering.
       */
      onParsed?: any
      /**
       * Provide your styles for specific HTML tags.
       * 
       * **Important note** Do NOT use the StyleSheet API to create the styles you're going to feed to tagsStyle and classesStyles.
       * Although it might look like it's working at first, the caching logic of react-native makes it impossible for this module
       * to deep check each of your style to properly apply the precedence and priorities of your nested tags' styles.
       */
      tagsStyles?: StylesDictionary
      /**
       * Provide your styles for specific HTML classes.
       * 
       * **Important note** Do NOT use the StyleSheet API to create the styles you're going to feed to tagsStyle and classesStyles.
       * Although it might look like it's working at first, the caching logic of react-native makes it impossible for this module
       * to deep check each of your style to properly apply the precedence and priorities of your nested tags' styles.
       */
      classesStyles?: StylesDictionary
      /**
       * Custom style for the default container of the renderered HTML.
       */
      containerStyle?: StyleProp<View>
      /**
       * Replace the default wrapper with a function that takes your content as the first parameter.
       */
      customWrapper?: Function
      /**
       * Replace the default loader while fetching a remote website's content.
       */
      remoteLoadingView?: Function
      /**
       * Replace the default error if a remote website's content could not be fetched.
       */
      remoteErrorView?: Function
      /**
       * The default value in pixels for 1em
       */
      emSize?: number
      /**
       * The default value in pixels for 1pt
       */
      ptSize?: number
      /**
       * The default style applied to `<Text>` components
       */
      baseFontStyle?: NonRegisteredStylesProp<TextStyle>
      /**
       * Allow all texts to be selected. Default to `false`.
       */
      textSelectable?: boolean
      /**
       * Target some specific texts and change their content, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterData?: (...args: any[]) => any;
      /**
       * Target some specific nested children and change them, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterChildren?: (...args: any[]) => any;
      /**
       * Target a specific node and change it, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterNode?: (...args: any[]) => any;
      /**
       * HTML tags you don't want rendered, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ingoredTags?: string[]
      /**
       * Allow render only certain CSS style properties and ignore every other. If you have some property both in `allowedStyles` and `ignoredStyles`, it will be ignored anyway.
       */
      allowedStyles?: string[]
      /**
       * CSS styles from the style attribute you don't want rendered, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ignoredStyles?: string[]
      /**
       * Return true in this custom function to ignore nodes very precisely, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ignoreNodesFunction?: (node: HTMLNode) => boolean
      /**
       * Prints the parsing result from htmlparser2 and render-html after the initial render
       */
      debug?: boolean
    }
  }
  const HTML: ComponentType<HTML.ContainerProps>
  export = HTML
}

declare module 'react-native-render-html/src/HTMLUtils' {
  type HTMLNode = any
  /**
   * Returns an array with the tagname of every parent of a node or an empty array if nothing is found.
   * @param node A parsed HTML node from alterChildren for example
   */
  export const getParentsTagsRecursively: (node: HTMLNode) => string[]

  /**
   * Returns the closest parent of a node with a specific tag.
   * @param node A parsed HTML node from alterChildren for example
   * @param tag The tag to match
   */
  export const getClosestNodeParentByTag: (node: HTMLNode, tag: string) => HTMLNode

  /**
   * The set of default ignored tags
   */
  export const IGNORED_TAGS: string[]
}

All 15 comments

Hi, yes that would be a very nice addition to the plugin. I was thinking about rewriting the whole codebase in typescript, since I'm pretty sure there are a lot of leftovers from previous versions that haven't been cleaned up properly. Switching to TS would help me see them.

In the meantime, providing typings would be a great start.

I have a preliminary version that I'm using in my project, but I didn't dig enough into the documentation and/or code to fill in all the types, so there are quite a few anys in place.

I'll submit a PR later when I have some time with improvements. If you would like any help with a typescript re-write I'd be happy to help

declare module "react-native-render-html" {
    import * as React from "react";
    import * as ReactNative from "react-native";

    type Renderer = (
        htmlAttribs: any,
        children: React.Children,
        convertedCSSStyles: any,
        passProps: any,
    ) => JSX.Element;

    export default class HTML extends React.PureComponent<{
        renderers?: { [key: string]: Renderer };
        ignoredTags?: string[];
        ignoredStyles?: string[];
        allowedStyles?: string[];
        decodeEntities?: boolean;
        debug?: boolean;
        listsPrefixesRenderers?: { ul?: Renderer; ol?: Renderer };
        ignoreNodesFunction?: (...args: any[]) => any;
        alterData?: (...args: any[]) => any;
        alterChildren?: (...args: any[]) => any;
        alterNode?: (...args: any[]) => any;
        html?: string;
        uri?: string;
        tagsStyles?: { [key: string]: ReactNative.ViewStyle | Array<ReactNative.ViewStyle> };
        classesStyles?: { [key: string]: ReactNative.ViewStyle | Array<ReactNative.ViewStyle> };
        containerStyle?: ReactNative.ViewStyle | Array<ReactNative.ViewStyle>;
        customWrapper?: (...args: any[]) => any;
        onLinkPress?: (...args: any[]) => any;
        onParsed?: (...args: any[]) => any;
        imagesMaxWidth?: number;
        staticContentMaxWidth?: number;
        imagesInitialDimensions?: {
            width?: number;
            height?: number;
        };
        emSize?: number;
        ptSize?: number;
        baseFontStyle?: ReactNative.ViewStyle | Array<ReactNative.ViewStyle>;
        textSelectable?: boolean;
    }> {}
}

@Exilz I am writing a more accurate version of typescript definitions for my own usage, with comments from your documentation.
I'll offer a PR when it's complete enough, but bellow is a draft:

declare module 'react-native-render-html' {
  import { ComponentType, ReactNode } from "react"
  import { StyleProp, Text, View, GestureResponderEvent, RecursiveArray, Falsy } from "react-native"
  namespace HTML {
    type HTMLNode = any
    type NonRegisteredStylesProp<T> = T | Falsy | RecursiveArray<T | Falsy>
    type HtmlAttributesDictionary = {
      [attribute: string]: string
    }
    type PassProps<T> = any
    type RendererFunction = <T>(htmlAttribs: HtmlAttributesDictionary, children: HTMLNode[], convertedCSSStyles: NonRegisteredStylesProp<any>, passProps: PassProps<T>) => ReactNode
    type RendererDeclaration = RendererFunction | { renderer: RendererFunction, wrapper: 'Text' | 'View' }
    type RendererDictionary = {
      [tag: string]: RendererDeclaration
    }
    type StylesDictionary = {
      [tag: string]: NonRegisteredStylesProp<any>
    }
    type ImageDimensions = {
      width: number,
      height: number
    }
    interface ContainerProps {
      /**
       * HTML string to parse and render
       */
      html: string
      /**
       * Resize your images to this maximum width.
       */
      imagesMaxWidth?: number
      /**
       * Your custom renderers.
       */
      renderers?: RendererDictionary
      /**
       * Your custom renderers from ul and ol bullets, see [lists prefixes](https://github.com/archriss/react-native-render-html#lists-prefixes)
       */
      listsPrefixesRenderers?: RendererDictionary
      /**
       * Remote website to parse and render
       */
      uri?: string
      /**
       * Decode HTML entities of your content.
       * Optional, defaults to true
       */
      decodeEntities?: boolean
      /**
       * Set a maximum width to non-responsive content (<iframe> for instance)
       */
      staticContentMaxWidth?: number
      /**
       * Default width and height to display while image's dimensions are being retrieved.
       */
      imagesInitialDimensions?: ImageDimensions
      /**
       * Fired with the event, the href and an object with all attributes of the tag as its arguments when tapping a link
       */
      onLinkPress?: (event: GestureResponderEvent, href: string, htmlAttribs: HtmlAttributesDictionary) => void
      /**
       * Fired when your HTML content has been parsed. Also useful to tweak your rendering.
       */
      onParsed?: any
      /**
       * Provide your styles for specific HTML tags.
       * 
       * **Important note** Do NOT use the StyleSheet API to create the styles you're going to feed to tagsStyle and classesStyles.
       * Although it might look like it's working at first, the caching logic of react-native makes it impossible for this module
       * to deep check each of your style to properly apply the precedence and priorities of your nested tags' styles.
       */
      tagsStyles?: StylesDictionary
      /**
       * Provide your styles for specific HTML classes.
       * 
       * **Important note** Do NOT use the StyleSheet API to create the styles you're going to feed to tagsStyle and classesStyles.
       * Although it might look like it's working at first, the caching logic of react-native makes it impossible for this module
       * to deep check each of your style to properly apply the precedence and priorities of your nested tags' styles.
       */
      classesStyles?: StylesDictionary
      /**
       * Custom style for the default container of the renderered HTML.
       */
      containerStyle?: StyleProp<View>
      /**
       * Replace the default wrapper with a function that takes your content as the first parameter.
       */
      customWrapper?: Function
      /**
       * Replace the default loader while fetching a remote website's content.
       */
      remoteLoadingView?: Function
      /**
       * Replace the default error if a remote website's content could not be fetched.
       */
      remoteErrorView?: Function
      /**
       * The default value in pixels for 1em
       */
      emSize?: number
      /**
       * The default value in pixels for 1pt
       */
      ptSize?: number
      /**
       * The default style applied to `<Text>` components
       */
      baseFontStyle?: NonRegisteredStylesProp<TextStyle>
      /**
       * Allow all texts to be selected. Default to `false`.
       */
      textSelectable?: boolean
      /**
       * Target some specific texts and change their content, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterData?: (...args: any[]) => any;
      /**
       * Target some specific nested children and change them, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterChildren?: (...args: any[]) => any;
      /**
       * Target a specific node and change it, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterNode?: (...args: any[]) => any;
      /**
       * HTML tags you don't want rendered, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ingoredTags?: string[]
      /**
       * Allow render only certain CSS style properties and ignore every other. If you have some property both in `allowedStyles` and `ignoredStyles`, it will be ignored anyway.
       */
      allowedStyles?: string[]
      /**
       * CSS styles from the style attribute you don't want rendered, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ignoredStyles?: string[]
      /**
       * Return true in this custom function to ignore nodes very precisely, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ignoreNodesFunction?: (node: HTMLNode) => boolean
      /**
       * Prints the parsing result from htmlparser2 and render-html after the initial render
       */
      debug?: boolean
    }
  }
  const HTML: ComponentType<HTML.ContainerProps>
  export = HTML
}

declare module 'react-native-render-html/src/HTMLUtils' {
  type HTMLNode = any
  /**
   * Returns an array with the tagname of every parent of a node or an empty array if nothing is found.
   * @param node A parsed HTML node from alterChildren for example
   */
  export const getParentsTagsRecursively: (node: HTMLNode) => string[]

  /**
   * Returns the closest parent of a node with a specific tag.
   * @param node A parsed HTML node from alterChildren for example
   * @param tag The tag to match
   */
  export const getClosestNodeParentByTag: (node: HTMLNode, tag: string) => HTMLNode

  /**
   * The set of default ignored tags
   */
  export const IGNORED_TAGS: string[]
}

@jsamr Any progress on the PR? It would be a great addition to this library 馃憤

@jsamr this is a must have

I'd also love this please! 馃挴

@jsamr I used yours, included one missing property from the new version and fixed a typo.

declare module 'react-native-render-html' {
  import { ComponentType, ReactNode } from 'react';
  import {
    StyleProp,
    Text,
    View,
    GestureResponderEvent,
    RecursiveArray,
    Falsy,
  } from 'react-native';
  namespace HTML {
    type HTMLNode = any;
    type NonRegisteredStylesProp<T> = T | Falsy | RecursiveArray<T | Falsy>;
    type HtmlAttributesDictionary = {
      [attribute: string]: string;
    };
    type PassProps<T> = any;
    type RendererFunction = <T>(
      htmlAttribs: HtmlAttributesDictionary,
      children: HTMLNode[],
      convertedCSSStyles: NonRegisteredStylesProp<any>,
      passProps: PassProps<T>,
    ) => ReactNode;
    type RendererDeclaration =
      | RendererFunction
      | { renderer: RendererFunction; wrapper: 'Text' | 'View' };
    type RendererDictionary = {
      [tag: string]: RendererDeclaration;
    };
    type StylesDictionary = {
      [tag: string]: NonRegisteredStylesProp<any>;
    };
    type ImageDimensions = {
      width: number;
      height: number;
    };
    interface ContainerProps {
      /**
       * HTML string to parse and render
       */
      html: string;
      /**
       * Your custom renderers.
       */
      renderers?: RendererDictionary;
      /**
       * Set of props accessible into your custom renderers in passProps (4th argument)
       */
      renderersProps?: PassProps<T>;
      /**
       * (experimental) Remote website to parse and render
       */
      uri?: string;
      /**
       * Decode HTML entities of your content.
       * Optional, defaults to true
       */
      decodeEntities?: boolean;
      /**
       * Resize your images to this maximum width.
       */
      imagesMaxWidth?: number;
      /**
       * Set a maximum width to non-responsive content (<iframe> for instance)
       */
      staticContentMaxWidth?: number;
      /**
       * Default width and height to display while image's dimensions are being retrieved.
       */
      imagesInitialDimensions?: ImageDimensions;
      /**
       * Fired with the event, the href and an object with all attributes of the tag as its arguments when tapping a link
       */
      onLinkPress?: (
        event: GestureResponderEvent,
        href: string,
        htmlAttribs: HtmlAttributesDictionary,
      ) => void;
      /**
       * Fired when your HTML content has been parsed. Also useful to tweak your rendering.
       */
      onParsed?: any;
      /**
       * Provide your styles for specific HTML tags.
       *
       * **Important note** Do NOT use the StyleSheet API to create the styles you're going to feed to tagsStyle and classesStyles.
       * Although it might look like it's working at first, the caching logic of react-native makes it impossible for this module
       * to deep check each of your style to properly apply the precedence and priorities of your nested tags' styles.
       */
      tagsStyles?: StylesDictionary;
      /**
       * Provide your styles for specific HTML classes.
       *
       * **Important note** Do NOT use the StyleSheet API to create the styles you're going to feed to tagsStyle and classesStyles.
       * Although it might look like it's working at first, the caching logic of react-native makes it impossible for this module
       * to deep check each of your style to properly apply the precedence and priorities of your nested tags' styles.
       */
      classesStyles?: StylesDictionary;
      /**
       * Your custom renderers from ul and ol bullets, see [lists prefixes](https://github.com/archriss/react-native-render-html#lists-prefixes)
       */
      listsPrefixesRenderers?: RendererDictionary;
      /**
       * Custom style for the default container of the renderered HTML.
       */
      containerStyle?: StyleProp<View>;
      /**
       * Replace the default wrapper with a function that takes your content as the first parameter.
       */
      customWrapper?: Function;
      /**
       * Replace the default loader while fetching a remote website's content.
       */
      remoteLoadingView?: Function;
      /**
       * Replace the default error if a remote website's content could not be fetched.
       */
      remoteErrorView?: Function;
      /**
       * The default value in pixels for 1em
       */
      emSize?: number;
      /**
       * The default value in pixels for 1pt
       */
      ptSize?: number;
      /**
       * The default style applied to `<Text>` components
       */
      baseFontStyle?: NonRegisteredStylesProp<TextStyle>;
      /**
       * Allow all texts to be selected. Default to `false`.
       */
      textSelectable?: boolean;
      /**
       * Target some specific texts and change their content, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterData?: (...args: any[]) => any;
      /**
       * Target some specific nested children and change them, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterChildren?: (...args: any[]) => any;
      /**
       * Target a specific node and change it, see [altering content](https://github.com/archriss/react-native-render-html#altering-content)
       */
      alterNode?: (...args: any[]) => any;
      /**
       * HTML tags you don't want rendered, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ignoredTags?: string[];
      /**
       * Allow render only certain CSS style properties and ignore every other. If you have some property both in `allowedStyles` and `ignoredStyles`, it will be ignored anyway.
       */
      allowedStyles?: string[];
      /**
       * CSS styles from the style attribute you don't want rendered, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ignoredStyles?: string[];
      /**
       * Return true in this custom function to ignore nodes very precisely, see [ignoring HTML content](https://github.com/archriss/react-native-render-html#ignoring-html-content)
       */
      ignoreNodesFunction?: (node: HTMLNode) => boolean;
      /**
       * Prints the parsing result from htmlparser2 and render-html after the initial render
       */
      debug?: boolean;
    }
  }
  const HTML: ComponentType<HTML.ContainerProps>;
  export = HTML;
}

declare module 'react-native-render-html/src/HTMLUtils' {
  type HTMLNode = any;
  /**
   * Returns an array with the tagname of every parent of a node or an empty array if nothing is found.
   * @param node A parsed HTML node from alterChildren for example
   */
  export const getParentsTagsRecursively: (node: HTMLNode) => string[];

  /**
   * Returns the closest parent of a node with a specific tag.
   * @param node A parsed HTML node from alterChildren for example
   * @param tag The tag to match
   */
  export const getClosestNodeParentByTag: (
    node: HTMLNode,
    tag: string,
  ) => HTMLNode;

  /**
   * The set of default ignored tags
   */
  export const IGNORED_TAGS: string[];
}

OK I'll do a PR!

Done, #341

If you want to see those types landing fast, it would be appreciated if you could test locally and give some feedback in PR #341.
To test, just change your version of react-native-render-html to:

{
  "dependencies": {
    "react-native-render-html": "github:jsamr/react-native-render-html#ts"
  }
}

and run npm i

Still there no typings when downloading from NPM.

Hi guys, any progress with this? Thanks

@dkoprowski @felisio Please test the branch as I instructed. @Exilz is waiting for a few user feedback before merging. Report your feedback in #341!

Any updates on adding type definitions to the npm package?

This is available as of 4.2.1

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fahadhaq picture fahadhaq  路  6Comments

psegalen picture psegalen  路  7Comments

KimJeonghun91 picture KimJeonghun91  路  4Comments

HarrisKoffi picture HarrisKoffi  路  5Comments

Aparus picture Aparus  路  3Comments