JSFiddle - React, Tailwind, and code Playground

by mcsf

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom-server.browser.development.js"></script>

Babel + JSX

assert(
  serialize(<p></p>),
  '<p></p>',
  'empty paragraph',
)

assert(
  serialize(<h1>Code {'&'} friends at 100%!</h1>),
  '<h1>Code &amp; friends at 100%!</h1>',
  'heading with ampersand',
)

assert(
  serialize(React.createElement('p', {}, 
    'A [shortcode ids="1,2,3"] is worth >= 1000 pictures'
  )),
  '<p>A [shortcode ids="1,2,3"] is worth &gt;= 1000 pictures</p>',
  'paragraph with quotes',
)

assert(
	serialize(<p><p>[shortcode ids="1,2,3"]</p></p>),
  '<p><p>[shortcode ids="1,2,3"]</p></p>',
  'nested paragraph with quotes'
)

function serialize(el) {
  return ReactDOMServer.renderToStaticMarkup(escapeTree(el))
}
  
function escapeTree(el) {
	if (! el || ! el.props || ! el.props.children) return el
  
  if ('string' === typeof el.props.children &&
      el.props.children.indexOf('"')) {
    const { children, ...otherProps } = el.props
    return React.createElement(el.type, {
      ...otherProps,
      dangerouslySetInnerHTML: {
        __html: dangerouslyEscape(children),
      }
    })
  }
  
  return React.cloneElement(
  	el,
    el.props,
    React.Children.map(el.props.children, escapeTree)
  )
}

function dangerouslyEscape(text) {
	return escapeHtml(text)
}

/**
 * FROM https://github.com/facebook/react/blob/master/packages/react-dom/src/server/escapeTextForBrowser.js
 * MODIFIED to skip escaping of &quot;
 *
 * Escapes special characters and HTML entities in a given html string.
 *
 * @param  {string} string HTML string to escape for later insertion
 * @return {string}
 * @public
 */
function escapeHtml(string) {
  const str = '' + string;
  const match = /["'&<>]/.exec(str);

  if (!match) {
    return str;
  }

  let escape;
  let html = '';
  let index = 0;
  let lastIndex = 0;

  for (index = match.index; index < str.length; index++) {
    switch (str.charCodeAt(index)) {
      //case 34: // "
      //  escape = '&quot;';
      //  break;
      case 38: // &
        escape = '&amp;';
        break;
      case 39: // '
        escape =...