pvcresin / react-jsx-renderer

A React component for Rendering JSX

Home Page:https://aduca.org/react-jsx-renderer/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

React JSX Renderer

demo npm version CI status Coverage Status Dependencies Status Install size License: MIT

A React Component for Rendering JSX.

Description

React JSX Renderer is a React Component for rendering JSX to React nodes.

It has a JavaScript Runtime inside, and can execute the user's JSX with controlled behavior.

Launch Demo

Features

  • Rendering JSX as React nodes
  • TypeScritpt ready
  • Provides CommonJS and ES Modules
  • JavaScript syntax and featues
    • without async, await and generator
  • Injectable custom React components
  • Pass binding variables
  • Applicable filters to parsed nodes
    • You can create allowlist / denylist filters to tagName, attributes or properties
  • Avoid user's call expressions
  • Avoid user's new expressions
  • Parse with meriyah

Installation

  1. npm install -s react-jsx-renderer (or yarn add react-jsx-renderer)
  2. Add import { JSXRenderer } from 'react-jsx-renderer';
  3. <JSXRenderer code="Hello, World" /> to render Hello, World

Options

interface ParseOptions {
  /**
   * Options of parser
   */
  meriyah?: meriyah.Options;

  /**
   * When this option is enabled, always parse as an expression.
   */
  forceExpression?: boolean;
}

interface EvaluateOptions {
  /**
   * binding
   */
  binding?: Binding;

  /**
   * components
   */
  components?: ComponentsBinding;

  /**
   * Prefix of generated keys.
   */
  keyPrefix?: string;

  /**
   * When this option is enabled, no key will be generated
   */
  disableKeyGeneration?: boolean;

  /**
   * When this option is enabled, bindings will be excluded from the component search.
   */
  disableSearchCompontsByBinding?: boolean;

  /**
   * When this option is enabled, Call Expression and New Expression will always return undefined.
   */
  disableCall?: boolean;

  /**
   * When this option is enabled, New Expression will always return undefined.
   */
  disableNew?: boolean;

  /**
   * When this option is enabled, access to undefined variables will raise an exception.
   */
  raiseReferenceError?: boolean;

  /**
   * List of functions allowed to be executed.
   *
   * If empty, all functions will be allowed to execute.
   */
  allowedFunctions?: AnyFunction[];

  /**
   * List of functions denied to be executed.
   *
   * If empty, all functions will be allowed to execute.
   */
  deniedFunctions?: AnyFunction[];
}

interface RenderingOptions {
  /**
   * List of filters to be applied to elements.
   */
  elementFilters?: JSXElementFilter[];

  /**
   * List of filters to be applied to fragments.
   */
  fragmentFilters?: JSXFragmentFilter[];

  /**
   * List of filters to be applied to text nodes.
   */
  textFilters?: JSXTextFilter[];

  /**
   * When this option is enabled, non-existent HTML elements will not be rendered.
   */
  disableUnknownHTMLElement?: boolean;
}

interface RendererOptions extends {
  /**
   * JSX code
   */
  code?: string;

  /**
   * The component that will be displayed instead when an error occurs.
   */
  fallbackComponent?: JSXFallbackComponent;

  /**
   * If you want to receive the parsed result, set a Ref object to this option.
   */
  refNodes?: Ref<JSXNode[]>;
}

Usage

Using like a simple HTML template engine

input:

import { render } from 'react-dom';
import { JSXRenderer } from 'react-jsx-renderer';

const root = document.getElementById('root');

render(
  <JSXRenderer
    binding={{ name: 'Sho Kusano' }}
    code={'<p>Hello, {name}</p>'}
  />,
  root
);

to:

<p>Hello, Sho Kusano</p>

Using JSX with JavaScript expressions

input:

render(
  <JSXRenderer
    binding={{
      three: 3,
      seven: 7,
    }}
    code={
      '<p>+ {three + seven}</p>' +
      '<p>- {three - seven}</p>' +
      '<p>bitwise shift {three << seven}</p>'
    }
  />,
  root
);

to:

<p>+ 10</p>
<p>- -4</p>
<p>bitwise shift 384</p>

Using JSX with your favorite custom components

const Red = ({ children }) => <b style={{ color: 'red' }}>{children}</b>

render(
  <JSXRenderer
    components={{ RedColor: Red }}
    code={'<p><RedColor>red</RedColor></p>'}
  />,
  root
);

to:

<p><b style="color: red">red</b></p>

Convert JSX with filters

const hrefFilter = (element: JSXElement) => {
  const { props, component, children } = element;
  if (component !== 'a') return element;

  let href = props.href || '';
  if (href.includes('//')) {
    href = secureURLConvert(href); // Add prefix https://secure.url/redirect?url=
  }
  const filteredProps = { ...props, href };
  return { component, children, props: filteredProps };
}

render(
  <JSXRenderer
    elementFilters={[hrefFilter]}
    code={
      '<p><a href="/">root</a></p>' +
      '<p><a href="../">upper directory</a></p>' +
      '<p><a href="subdir">sub directory</a></p>' +
      '<p><a href="https://github.com/">github</a></p>' +
    }
  />,
  root
);

to:

<p><a href="/">root</a></p>
<p><a href="../">upper directory</a></p>
<p><a href="subdir">sub directory</a></p>
<p><a href="https://secure.url/redirect?url=https://github.com">github</a></p>

License

MIT License

Related projects

About

A React component for Rendering JSX

https://aduca.org/react-jsx-renderer/

License:MIT License


Languages

Language:TypeScript 96.1%Language:JavaScript 3.8%Language:SCSS 0.1%