New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@elliottsj/react-render-html

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@elliottsj/react-render-html - npm Package Compare versions

Comparing version 0.2.0 to 0.2.1

73

lib/index.js

@@ -9,2 +9,5 @@ 'use strict';

exports.applyMiddleware = applyMiddleware;
exports.default = renderHTML;
var _parse = require('parse5');

@@ -22,2 +25,6 @@

var _reactStyling = require('react-styling');
var _reactStyling2 = _interopRequireDefault(_reactStyling);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -29,17 +36,43 @@

function baseRenderNode() {
var compose = function compose() {
for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) {
fns[_key] = arguments[_key];
}
return function (arg) {
return fns.reduceRight(function (prev, fn) {
return fn(prev);
}, arg);
};
};
function baseRenderNode(renderNode) {
return function (node, key) {
if (node.nodeName === '#text') {
return node.value;
}
var props = _extends({
key: key
}, node.attrs.reduce(function (attrs, attr) {
var name = (0, _reactAttrConverter2.default)(attr.name);
return _extends({}, attrs, _defineProperty({}, name, name === 'style' ? (0, _reactStyling2.default)(attr.value) : attr.value));
}, {}));
var children = node.childNodes.map(renderNode);
return _react2.default.createElement.apply(_react2.default, [node.tagName, props].concat(_toConsumableArray(children)));
};
}
function applyMiddleware() {
for (var _len2 = arguments.length, transformers = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
transformers[_key2] = arguments[_key2];
}
return function (renderNode) {
return function (node, key) {
if (node.nodeName === '#text') {
return node.value;
}
var props = _extends({
key: key
}, node.attrs.reduce(function (attrs, attr) {
return _extends({}, attrs, _defineProperty({}, (0, _reactAttrConverter2.default)(attr.name), attr.value));
}, {}));
var children = node.childNodes.map(renderNode);
return _react2.default.createElement.apply(_react2.default, [node.tagName, props].concat(_toConsumableArray(children)));
var chain = transformers.map(function (transformer) {
return transformer(renderNode);
});
return compose.apply(undefined, _toConsumableArray(chain))(node, key);
};

@@ -50,5 +83,7 @@ };

function renderHTML(html) {
var renderNode = arguments.length <= 1 || arguments[1] === undefined ? function (next) {
return function () {
return next.apply(undefined, arguments);
var renderNode = arguments.length <= 1 || arguments[1] === undefined ? function () {
return function (next) {
return function () {
return next.apply(undefined, arguments);
};
};

@@ -64,3 +99,3 @@ } : arguments[1];

var finalRenderNode = function finalRenderNode(node, key) {
return renderNode(baseRenderNode())(finalRenderNode)(node, key);
return renderNode(finalRenderNode)(baseRenderNode(finalRenderNode))(node, key);
};

@@ -70,4 +105,2 @@ var result = htmlAST.childNodes.map(finalRenderNode);

return result.length === 1 ? result[0] : result;
}
exports.default = renderHTML;
}
{
"name": "@elliottsj/react-render-html",
"version": "0.2.0",
"version": "0.2.1",
"description": "No more dangerouslySetInnerHTML, render HTML as React element.",

@@ -32,2 +32,3 @@ "main": "lib/index.js",

"babel-preset-stage-2": "^6.5.0",
"react": "^15.1.0",
"react-dom": "^15.1.0",

@@ -42,3 +43,4 @@ "xo": "^0.15.1"

"parse5": "^2.0.2",
"react-attr-converter": "0.1.0"
"react-attr-converter": "0.1.0",
"react-styling": "^1.5.0"
},

@@ -45,0 +47,0 @@ "peerDependencies": {

@@ -44,23 +44,28 @@ # react-render-html [![travis-ci](https://travis-ci.org/noraesae/react-render-html.svg)](https://travis-ci.org/noraesae/react-render-html)

### Custom renderers
### Custom renderers ("Middleware")
Pass a function as the 2nd argument to `renderHTML` to customize how nodes are rendered:
```js
function renderNode(next) { /* ... */ }
function middleware(renderNode) { /* ... */ }
renderHTML('<li>hello</li><li>world</li>', renderNode);
renderHTML('<li>hello</li><li>world</li>', middleware);
```
The function should have the signature
The middleware function should have the signature
```js
renderNode(next: renderNode) => (renderNode: renderNode) => (node: ASTNode.<Element>, key: String) => ReactElement
type Middleware = (renderNode: NodeRenderer) => (next: NodeRenderer) => NodeRenderer
type NodeRenderer = (node: ASTNode.<Element>, key: String) => ReactElement
```
Where `next` is the next renderer in the chain, `renderNode` is the entire chain, and `node` and `key` correspond to the current node being rendered.
Where `next` is the next renderer in the middleware chain, `renderNode` is the entire chain, and `node` and `key` correspond to the current node being rendered.
For example, to replace the `href` attribute of all `<a>` elements, use:
```js
function replaceHref(next) {
return next => renderNode => (node, key) => {
const element = next(renderNode)(node, key);
import renderHTML, {
applyMiddleware
} from 'react-render-html';
function replaceHref(renderNode) {
return next => (node, key) => {
const element = next(node, key);
if (node.tagName === 'a') {

@@ -80,6 +85,6 @@ return React.cloneElement(element, {

Custom renders are composable: simply call `next` from within a renderer to get the resulting ReactElement from subsequent renders, and call `renderNode` if you need to render a node from scratch (e.g. child nodes). For example:
Custom renders are composable: using `applyMiddleware`, simply call `next` from within a renderer to get the resulting ReactElement from subsequent renderers, and call `renderNode` if you need to render a node from scratch using the entire renderer chain (e.g. child nodes). For example:
```js
const replaceHref = next => renderNode => (node, key) => {
const element = next(renderNode)(node, key);
const replaceHref = renderNode => next => (node, key) => {
const element = next(node, key);
if (node.tagName === 'a') {

@@ -92,10 +97,10 @@ return React.cloneElement(element, {

};
const replacePs = next => renderNode => (node, key) => {
const replacePs = renderNode => next => (node, key) => {
if (node.tagName === 'p') {
return React.createElement(node.tagName, {}, 'Redacted');
}
return next(renderNode)(node, key);
return next(node, key);
};
const addLi = next => renderNode => (node, key) => {
const element = next(renderNode)(node, key);
const addLi = renderNode => next => (node, key) => {
const element = next(node, key);
if (node.tagName === 'ul') {

@@ -116,3 +121,3 @@ return React.cloneElement(

'</ul>',
compose(replaceHref, replacePs, addLi)
applyMiddleware(replaceHref, replacePs, addLi)
);

@@ -136,6 +141,10 @@

```js
const renderHTML = require('react-render-html');
const {
default: renderHTML,
applyMiddleware
} = require('react-render-html');
import renderHTML from 'react-render-html';
import * as renderHTML from 'react-render-html'; // both of them work
// OR
import renderHTML, { applyMiddleware } from 'react-render-html';
```

@@ -142,0 +151,0 @@

import parse5 from 'parse5';
import React from 'react';
import convertAttr from 'react-attr-converter';
import styler from 'react-styling';
function baseRenderNode() {
return renderNode => (node, key) => {
const compose = (...fns) => arg => fns.reduceRight((prev, fn) => fn(prev), arg);
function baseRenderNode(renderNode) {
return (node, key) => {
if (node.nodeName === '#text') {

@@ -13,6 +16,9 @@ return node.value;

key,
...node.attrs.reduce((attrs, attr) => ({
...attrs,
[convertAttr(attr.name)]: attr.value
}), {})
...node.attrs.reduce((attrs, attr) => {
const name = convertAttr(attr.name);
return {
...attrs,
[name]: name === 'style' ? styler(attr.value) : attr.value
};
}, {})
};

@@ -25,3 +31,10 @@

function renderHTML(html, renderNode = next => (...args) => next(...args)) {
export function applyMiddleware(...transformers) {
return renderNode => (node, key) => {
const chain = transformers.map(transformer => transformer(renderNode));
return compose(...chain)(node, key);
};
}
export default function renderHTML(html, renderNode = () => next => (...args) => next(...args)) {
const htmlAST = parse5.parseFragment(html);

@@ -33,3 +46,4 @@

const finalRenderNode = (node, key) => renderNode(baseRenderNode())(finalRenderNode)(node, key);
const finalRenderNode =
(node, key) => renderNode(finalRenderNode)(baseRenderNode(finalRenderNode))(node, key);
const result = htmlAST.childNodes.map(finalRenderNode);

@@ -39,3 +53,1 @@

}
export default renderHTML;
import test from 'ava';
import React from 'react';
import * as ReactDOMServer from 'react-dom/server';
import renderHTML from '../lib/index';
import renderHTML, {
applyMiddleware
} from '../lib/index';
const compose = (...fns) => arg => fns.reduceRight((prev, fn) => fn(prev), arg);
const renderTest = (t, reactEl, expectedHTML) => {

@@ -31,5 +31,12 @@ t.is(ReactDOMServer.renderToStaticMarkup(reactEl), expectedHTML);

test('parse the style attribute when specified as a string', t => {
singleElementTest(t, '<ul>' +
'<li style="font-weight:bold;color:green;"><a class="hello" href="https://github.com">hihi</a></li>' +
'<li style="font-style:italic;"><p><b>hello</b>world</p><p>react</p></li>' +
'</ul>');
});
test('uses the given `renderNode` function', t => {
const replaceHref = next => renderNode => (node, key) => {
const element = next(renderNode)(node, key);
const replaceHref = () => next => (node, key) => {
const element = next(node, key);
if (node.tagName === 'a') {

@@ -61,4 +68,4 @@ return React.cloneElement(element, {

test('can compose `renderNode` functions', t => {
const replaceHref = next => renderNode => (node, key) => {
const element = next(renderNode)(node, key);
const replaceHref = () => next => (node, key) => {
const element = next(node, key);
if (node.tagName === 'a') {

@@ -71,10 +78,10 @@ return React.cloneElement(element, {

};
const replacePs = next => renderNode => (node, key) => {
const replacePs = () => next => (node, key) => {
if (node.tagName === 'p') {
return React.createElement(node.tagName, {}, 'Redacted');
}
return next(renderNode)(node, key);
return next(node, key);
};
const addLi = next => renderNode => (node, key) => {
const element = next(renderNode)(node, key);
const addLi = renderNode => next => (node, key) => {
const element = next(node, key);
if (node.tagName === 'ul') {

@@ -95,3 +102,3 @@ return React.cloneElement(

'</ul>',
compose(replaceHref, replacePs, addLi)
applyMiddleware(replaceHref, replacePs, addLi)
);

@@ -98,0 +105,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc