npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

dangerously-atomic-html

v1.1.7

Published

## Introduction Sometimes you can't avoid having to do dangerouslySetInnerHtml in your React apps. But, once you have dangerously set some html in react you lose all control of that part of the DOM. Dangerously Atomic Html takes html and dynamically turns

Downloads

6

Readme

dangerously-atomic-html

Introduction

Sometimes you can't avoid having to do dangerouslySetInnerHtml in your React apps. But, once you have dangerously set some html in react you lose all control of that part of the DOM. Dangerously Atomic Html takes html and dynamically turns it into react components at run time. This is useful for working with output from tools like tinyMCE or when looking at search results from elastic search.

Installation

dangerously-atomic-html has a peer dependency of "react": ">=14.0.0

To install run yarn add dangerously-atomic-html

Basic Usage

import React from 'react';
import dangerouslyAtomicHtml from 'dangerously-atomic-html';

class Example extends React.Component {
  render(){
    const html = '<h1 class="title">Hello, world!</h1>';
    return dangerouslyAtomicHtml(html);
    /* the same as doing
    return (
      <h1 className="title">Hello, world</h1>
    );
    */
  }
}

Take note that dangerouslyAtomicHtml does not wrap your html in a div or any other tag. Consider the following example:

render(){
  const html = '<label for="input1">Email</label><input id="input1">';
  return dangerouslyAtomicHtml(html); // invariant violation
  /* to correct this you need to do
  return <some tag>{dangerouslyAtomicHtml(...)}</some tag>;
  */
}

Advanced Usage

dangerouslyAtomicHtml accepts a second argument which is function that is a visitor for each DOM node in the html. Those who have worked with babel or eslint plugins will be familiar with this pattern. The visitor function accepts an html node as the only argument and returns an object that describes how you want to transform that node. For example:

function visitor(domNode){
  if(domNode.nodeName === 'H1'){ // text nodes will have a node name of `#text`
    return {
      type: 'node', // one of ['node', 'text], use node when returning anything that is not raw text.
      Component: domNode.nodeName, // can be a string that is the the name of an html node, or a react component,
      props: { className: 'custom-class-name' }
    }
  }
}

dangerouslyAtomicHtml('<h1>Welcome!</h1>', visitor);

This example adds the class "custom-class-name" to all the h1 tags in the document.

You can also return a react component from the visitor, for example:

const html = (
`
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
`
);

class CustomLi extends React.Component {
  render(){
    // return some custom react stuff
  }
}

function visitor(domNode){
  if(domNode.nodeName === 'LI'){
    return {
      type: 'node',
      Component: CustomLi,
      // the props value is optional
    }
  }
}

dangerouslyAtomicHtml(html, visitor);

/* this would be the same as if you wrote in react
<ul>
  <CustomLi>Item 1</CustomLi>
  <CustomLi>Item 2</CustomLi>
  <CustomLi>Item 3</CustomLi>
  <CustomLi>Item 4</CustomLi>
</ul>
*/

Note that if you return a react component for a node that has children then it is up to your react component to handle rendering the children via this.props.children.

We also provided a function that will give a hash of the attributes preset on the dom node but in the react format. It takes the node as the only argument. For example:

import dangerouslyAtomicHtml, { reactifyAttributes } from 'dangerously-atomic-html'

function visitor(domNode){
  if(domNode.nodeName === 'LI'){
    return {
      type: 'node',
      Component: CustomLi,
      props: reactifyAttributes(domNode)
    }
  }
}

This is useful when you want to keep all of the current attributes on a node but maybe modify one of them.

If you are using dangerouslyAtomicHtml more than once in your app you must also provide a third argument that is the key that the component will use, for example:

render(){
  return (
    <div>
      {dangerouslyAtomicHtml(someHtml, someVistor, 'component1')}
      {dangerouslyAtomicHtml(someOtherHtml, null, 'component2')}
    </div>
  )
}

You must do that because the way react handles iterated components.

Gotchas

  • If a dom node has an onclick attribute (or any other event) then dangerouslyAtomicHtml will throw an error. Event attributes have no meaning when going from html to react. If you suspect that the html you will be transforming has event attributes in it then you will need to have a visitor function that handles those nodes.
  • Try to avoid traversing a node's tree in your visitor. Each node has direct access to its parent node. For example instead of having a visitor for a table tag then checking to see if one of its rows has some property, have a visitor on the row and check to see if the parent has some property.
  • Beware trailing or leading spaces / newline chars in strings, whitespace is considered a text node in html. For example:
render(){
  const html = ' <div></div>';
  return dangerouslyAtomicHtml(html); // invariant violation
  /* this is same as doing
  return [
    ' ',
    <div />
  ]
  which obviously would make react mad
  */
}

Other Ideas of How to Use

  • Manipulating text of text nodes. Maybe you have have a comment box that uses tinyMCE and you want to add a link to another user's page when they are mentioned in a comment via @userName. You could find that in a text node and instead render a react component that links you to the users page.
  • Templating or theming user created content.

The Future

  • Add support for aria tags
  • Transform inline styles to react inline styles

Contributing

Feel free to submit pull requests and we will look at them as soon as we can.