JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q29915F
  • License MIT

A versatile replacement for 'dangerouslySetInnerHTML'. Let's you build react-components deep within a regular HTML-Dom

Package Exports

  • dom-to-react

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (dom-to-react) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Dom to React

dom-to-react is a replacement for React's own method dangerouslySetInnerHTML.

It lets you build a React structure from a regular HTML-Dom. Your React application is aware of all elements wthin the added DOM, and it even lets you initialize your own React components anywhere inside that structure.

dom-to-react is very lightweight. It does not use any further third party modules.

How to install

Use npm (or your preferred package manager)

npm install --save-dev dom-to-react

Simple usage

It takes a regular Dom-Node as entrypoint from which it creates the according React-elements (by calling React.createElement()) recursively. So the simplest way is:

<main id="app">
  <div class="content-to-render">
    <p>A Paragraph</p>
  </div>
</main>
import Dom2react from 'dom-to-react';
import React from 'react';
import { render } from 'react-dom';

const d2r = new Dom2react();
const rootNode = document.querySelector('.content-to-render');

render(d2r.prepareNode(rootNode), document.querySelector('#app'));

This will create the initial DOM structure, but now all elements are React elements. Easy, isn't it?

Advanced usage

when creating an instance of Dom2React, a configuration can be provided which allows to manipulate and handle the original DOM:

const d2r = new Dom2react(options);

where options is an array with instruction objects with each 2-3 callback functions all the functions are being passed the following params:

  • @param {node} the node being tested/manipulated
  • @param {key} the React-key which would be assigned when the node renders (always in the format ${level}-${index})
  • @param {level} the level how deep in the DOM the nod is nested (an integer)
  • @param {parser} the parser itself
var options = [
  {
    // If this function returns true, the two following functions are called as long as they are defined
    // This function must always return true or false
    'condition': function(node, key) { return node.nodeName.toLowerCase() === 'div'; },

    // This function can be used for easy manipulations to the node, e.g. for removing or adding attributes
    // This function must always return a DOM-Node (even if it's a new one created by document.createElement)
    'modify':  function(node, key, level) { return document.createElement('div'); },

    //This function is used to inject your own components into the parsed DOM
    // This function must return an object which can be rendered by React (a react element or null)
    'action':  function(node, key, level) { return React.createElement('div'); }
  }
];

Example instructions

Add a class to all divs:

{
  condition: function(node, key, level, parser) { return node.nodeName.toLowerCase() === 'div';} ),
  modify: function(node, key, level) {
    node.className += ' a-class-added';
    return node;
  }
}

Remove all divs with a certain class:

{
  condition: function(node, key, level parser) { return node.className.indexOf('delete-me') >= 0;} ),
  action: function(node, key, level, parser) {
    return null;
  }
}

Initialize a react component for all nodes of a certain type (e.g. the react-markdown-component):

{
  condition: function(node, key, level, parser) return {node.nodeName.toLowerCase() === 'pre'},
  action: function(node, key, level, parser) {
    return <ReactMarkdown key={key} source={node.innerText} />;
  }
}

transform one node-type into another (e.g. ul=>ol) but preserve all childnodes:

{
  condition: function(node, key, level parser) { return node.nodeName.toLowerCase() === 'ul'},
  modify: function(node, key, level, parser) {
    var ol = document.createElement('ol');
    for (var i = node.childNodes.length - 1; i >= 0; i--) {
      ol.appendChild(node.childNodes[i]);
    }
    return ol;
  }
}

Initialize a more complex component with an object parsed from a JSON within a HTML comment. (That's actually what I used this for 👍)

<div class="complex-component">
<!-- { ...complex JSON-object } -->
</div>
{
  condition: function(node, key, level, parser) { return node.className.indexOf('complex-component') >= 0;},
  action: function(node, key, level, parser) {
    var props = false;
    for (var i = node.childNodes.length - 1; i >= 0; i--) {
      if (childNode.nodeType === 8) {
          props = JSON.parse(childNode.nodeValue);
      }
    }
    return <ComplexComponent {...props} />;
  }
}

Demo

To see the included demo in action, clone/download this repo and

npm i
npm run start

and open

http://localhost:8080/