src/index.js
function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
	if (vnode==null || typeof vnode==='boolean') {
		return '';
	}

	let nodeName = vnode.type,
		props = vnode.props,
		isComponent = false;
	context = context || {};
	opts = opts || {};

	let pretty = ENABLE_PRETTY && opts.pretty,
		indentChar = pretty && typeof pretty==='string' ? pretty : '\t';

	// #text nodes
	if (typeof vnode!=='object' && !nodeName) {
		return encodeEntities(vnode);
	}

	// components
	if (typeof nodeName==='function') {
		isComponent = true;
		if (opts.shallow && (inner || opts.renderRootComponent===false)) {
			nodeName = getComponentName(nodeName);
		}
		else if (nodeName===Fragment) {
			let rendered = '';
			let children = [];
			getChildren(children, vnode.props.children);

			for (let i = 0; i < children.length; i++) {
				rendered += renderToString(children[i], context, opts, opts.shallowHighOrder!==false, isSvgMode, selectValue);
			}
			return rendered;
		}
		else {
			let rendered;
			
			let c = vnode.__c = { __v: vnode, context, props: vnode.props };
			if (options.render) options.render(vnode);

			if (!nodeName.prototype || typeof nodeName.prototype.render!=='function') {
				// Necessary for createContext api. Setting this property will pass
				// the context value as `this.context` just for this component.
				let cxType = nodeName.contextType;
				let provider = cxType && context[cxType.__c];
				let cctx = cxType != null ? (provider ? provider.props.value : cxType._defaultValue) : context;

				// stateless functional components
				rendered = nodeName.call(vnode.__c, props, cctx);
			}
			else {
				// class-based components
				// c = new nodeName(props, context);
				c = vnode.__c = new nodeName(props, context);
				c.__v = vnode;
				// turn off stateful re-rendering:
				c._dirty = c.__d = true;
				c.props = props;
				c.context = context;
				if (nodeName.getDerivedStateFromProps) c.state = assign(assign({}, c.state), nodeName.getDerivedStateFromProps(c.props, c.state));
				else if (c.componentWillMount) c.componentWillMount();
				rendered = c.render(c.props, c.state, c.context);
			}
			
			if (c.getChildContext) {
				context = assign(assign({}, context), c.getChildContext());
			}

			return renderToString(rendered, context, opts, opts.shallowHighOrder!==false, isSvgMode, selectValue);
		}
	}

	// render JSX to HTML
	let s = '', html;

	if (props) {
		let attrs = Object.keys(props);

		// allow sorting lexicographically for more determinism (useful for tests, such as via preact-jsx-chai)
		if (opts && opts.sortAttributes===true) attrs.sort();

		for (let i=0; i<attrs.length; i++) {
			let name = attrs[i],
				v = props[name];
			if (name==='children') continue;

			if (name.match(/[\s\n\\/='"\0<>]/)) continue;

			if (!(opts && opts.allAttributes) && (name==='key' || name==='ref')) continue;

			if (name==='className') {
				if (props.class) continue;
				name = 'class';
			}
			else if (isSvgMode && name.match(/^xlink:?./)) {
				name = name.toLowerCase().replace(/^xlink:?/, 'xlink:');
			}

			if (name==='style' && v && typeof v==='object') {
				v = styleObjToCss(v);
			}

			let hooked = opts.attributeHook && opts.attributeHook(name, v, context, opts, isComponent);
			if (hooked || hooked==='') {
				s += hooked;
				continue;
			}

			if (name==='dangerouslySetInnerHTML') {
				html = v && v.__html;
			}
			else if ((v || v===0 || v==='') && typeof v!=='function') {
				if (v===true || v==='') {
					v = name;
					// in non-xml mode, allow boolean attributes
					if (!opts || !opts.xml) {
						s += ' ' + name;
						continue;
					}
				}

				if (name==='value') {
					if (nodeName==='select') {
						selectValue = v;
						continue;
					}
					else if (nodeName==='option' && selectValue==v) {
						s += ` selected`;
					}
				}
				s += ` ${name}="${encodeEntities(v)}"`;
			}
		}
	}

	// account for >1 multiline attribute
	if (pretty) {
		let sub = s.replace(/^\n\s*/, ' ');
		if (sub!==s && !~sub.indexOf('\n')) s = sub;
		else if (pretty && ~s.indexOf('\n')) s += '\n';
	}

	s = `<${nodeName}${s}>`;
	if (String(nodeName).match(/[\s\n\\/='"\0<>]/)) throw s;

	let isVoid = String(nodeName).match(VOID_ELEMENTS);
	if (isVoid) s = s.replace(/>$/, ' />');

	let pieces = [];

	let children;
	if (html) {
		// if multiline, indent.
		if (pretty && isLargeString(html)) {
			html = '\n' + indentChar + indent(html, indentChar);
		}
		s += html;
	}
	else if (props && getChildren(children = [], props.children).length) {
		let hasLarge = pretty && ~s.indexOf('\n');
		for (let i=0; i<children.length; i++) {
			let child = children[i];
			if (child!=null && child!==false) {
				let childSvgMode = nodeName==='svg' ? true : nodeName==='foreignObject' ? false : isSvgMode,
					ret = renderToString(child, context, opts, true, childSvgMode, selectValue);
				if (pretty && !hasLarge && isLargeString(ret)) hasLarge = true;
				if (ret) pieces.push(ret);
			}
		}
		if (pretty && hasLarge) {
			for (let i=pieces.length; i--; ) {
				pieces[i] = '\n' + indentChar + indent(pieces[i], indentChar);
			}
		}
	}

	if (pieces.length) {
		s += pieces.join('');
	}
	else if (opts && opts.xml) {
		return s.substring(0, s.length-1) + ' />';
	}

	if (!isVoid) {
		if (pretty && ~s.indexOf('\n')) s += '\n';
		s += `</${nodeName}>`;
	}

	return s;
}
function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
	if (vnode==null || typeof vnode==='boolean') {
		return '';
	}

	let nodeName = vnode.type,
		props = vnode.props,
		isComponent = false;
	context = context || {};
	opts = opts || {};

	let pretty = ENABLE_PRETTY && opts.pretty,
		indentChar = pretty && typeof pretty==='string' ? pretty : '\t';

	// #text nodes
	if (typeof vnode!=='object' && !nodeName) {
		return encodeEntities(vnode);
	}

	// components
	if (typeof nodeName==='function') {
		isComponent = true;
		if (opts.shallow && (inner || opts.renderRootComponent===false)) {
			nodeName = getComponentName(nodeName);
		}
		else if (nodeName===Fragment) {
			let rendered = '';
			let children = [];
			getChildren(children, vnode.props.children);

			for (let i = 0; i < children.length; i++) {
				rendered += renderToString(children[i], context, opts, opts.shallowHighOrder!==false, isSvgMode, selectValue);
			}
			return rendered;
		}
		else {
			let rendered;
			
			let c = vnode.__c = { __v: vnode, context, props: vnode.props };
			if (options.render) options.render(vnode);

			if (!nodeName.prototype || typeof nodeName.prototype.render!=='function') {
				// Necessary for createContext api. Setting this property will pass
				// the context value as `this.context` just for this component.
				let cxType = nodeName.contextType;
				let provider = cxType && context[cxType.__c];
				let cctx = cxType != null ? (provider ? provider.props.value : cxType._defaultValue) : context;

				// stateless functional components
				rendered = nodeName.call(vnode.__c, props, cctx);
			}
			else {
				// class-based components
				// c = new nodeName(props, context);
				c = vnode.__c = new nodeName(props, context);
				c.__v = vnode;
				// turn off stateful re-rendering:
				c._dirty = c.__d = true;
				c.props = props;
				c.context = context;
				if (nodeName.getDerivedStateFromProps) c.state = assign(assign({}, c.state), nodeName.getDerivedStateFromProps(c.props, c.state));
				else if (c.componentWillMount) c.componentWillMount();
				rendered = c.render(c.props, c.state, c.context);
			}
			
			if (c.getChildContext) {
				context = assign(assign({}, context), c.getChildContext());
			}

			return renderToString(rendered, context, opts, opts.shallowHighOrder!==false, isSvgMode, selectValue);
		}
	}

	// render JSX to HTML
	let s = '', html;

	if (props) {
		let attrs = Object.keys(props);

		// allow sorting lexicographically for more determinism (useful for tests, such as via preact-jsx-chai)
		if (opts && opts.sortAttributes===true) attrs.sort();

		for (let i=0; i<attrs.length; i++) {
			let name = attrs[i],
				v = props[name];
			if (name==='children') continue;

			if (name.match(/[\s\n\\/='"\0<>]/)) continue;

			if (!(opts && opts.allAttributes) && (name==='key' || name==='ref')) continue;

			if (name==='className') {
				if (props.class) continue;
				name = 'class';
			}
			else if (isSvgMode && name.match(/^xlink:?./)) {
				name = name.toLowerCase().replace(/^xlink:?/, 'xlink:');
			}

			if (name==='style' && v && typeof v==='object') {
				v = styleObjToCss(v);
			}

			let hooked = opts.attributeHook && opts.attributeHook(name, v, context, opts, isComponent);
			if (hooked || hooked==='') {
				s += hooked;
				continue;
			}

			if (name==='dangerouslySetInnerHTML') {
				html = v && v.__html;
			}
			else if ((v || v===0 || v==='') && typeof v!=='function') {
				if (v===true || v==='') {
					v = name;
					// in non-xml mode, allow boolean attributes
					if (!opts || !opts.xml) {
						s += ' ' + name;
						continue;
					}
				}

				if (name==='value') {
					if (nodeName==='select') {
						selectValue = v;
						continue;
					}
					else if (nodeName==='option' && selectValue==v) {
						s += ` selected`;
					}
				}
				s += ` ${name}="${encodeEntities(v)}"`;
			}
		}
	}

	// account for >1 multiline attribute
	if (pretty) {
		let sub = s.replace(/^\n\s*/, ' ');
		if (sub!==s && !~sub.indexOf('\n')) s = sub;
		else if (pretty && ~s.indexOf('\n')) s += '\n';
	}

	s = `<${nodeName}${s}>`;
	if (String(nodeName).match(/[\s\n\\/='"\0<>]/)) throw s;

	let isVoid = String(nodeName).match(VOID_ELEMENTS);
	if (isVoid) s = s.replace(/>$/, ' />');

	let pieces = [];

	let children;
	if (html) {
		// if multiline, indent.
		if (pretty && isLargeString(html)) {
			html = '\n' + indentChar + indent(html, indentChar);
		}
		s += html;
	}
	else if (props && getChildren(children = [], props.children).length) {
		let hasLarge = pretty && ~s.indexOf('\n');
		for (let i=0; i<children.length; i++) {
			let child = children[i];
			if (child!=null && child!==false) {
				let childSvgMode = nodeName==='svg' ? true : nodeName==='foreignObject' ? false : isSvgMode,
					ret = renderToString(child, context, opts, true, childSvgMode, selectValue);
				if (pretty && !hasLarge && isLargeString(ret)) hasLarge = true;
				if (ret) pieces.push(ret);
			}
		}
		if (pretty && hasLarge) {
			for (let i=pieces.length; i--; ) {
				pieces[i] = '\n' + indentChar + indent(pieces[i], indentChar);
			}
		}
	}

	if (pieces.length) {
		s += pieces.join('');
	}
	else if (opts && opts.xml) {
		return s.substring(0, s.length-1) + ' />';
	}

	if (!isVoid) {
		if (pretty && ~s.indexOf('\n')) s += '\n';
		s += `</${nodeName}>`;
	}

	return s;
}
function renderToString ( vnode , context , opts , inner , isSvgMode , selectValue ) { if ( vnode == null || typeof vnode === 'boolean' ) { return '' ; } let nodeName = vnode . type , props = vnode . props , isComponent = false ; context = context || { } ; opts = opts || { } ; let pretty = ENABLE_PRETTY && opts . pretty , indentChar = pretty && typeof pretty === 'string' ? pretty : '\t' ; // #text nodes if ( typeof vnode !== 'object' && ! nodeName ) { return encodeEntities ( vnode ) ; } // components if ( typeof nodeName === 'function' ) { isComponent = true ; if ( opts . shallow && ( inner || opts . renderRootComponent === false ) ) { nodeName = getComponentName ( nodeName ) ; } else if ( nodeName === Fragment ) { let rendered = '' ; let children = [ ] ; getChildren ( children , vnode . props . children ) ; for ( let i = 0 ; i < children . length ; i ++ ) { rendered += renderToString ( children [ i ] , context , opts , opts . shallowHighOrder !== false , isSvgMode , selectValue ) ; } return rendered ; } else { let rendered ; let c = vnode . __c = { __v : vnode , context , props : vnode . props } ; if ( options . render ) options . render ( vnode ) ; if ( ! nodeName . prototype || typeof nodeName . prototype . render !== 'function' ) { // Necessary for createContext api. Setting this property will pass // the context value as `this.context` just for this component. let cxType = nodeName . contextType ; let provider = cxType && context [ cxType . __c ] ; let cctx = cxType != null ? ( provider ? provider . props . value : cxType . _defaultValue ) : context ; // stateless functional components rendered = nodeName . call ( vnode . __c , props , cctx ) ; } else { // class-based components // c = new nodeName(props, context); c = vnode . __c = new nodeName ( props , context ) ; c . __v = vnode ; // turn off stateful re-rendering: c . _dirty = c . __d = true ; c . props = props ; c . context = context ; if ( nodeName . getDerivedStateFromProps ) c . state = assign ( assign ( { } , c . state ) , nodeName . getDerivedStateFromProps ( c . props , c . state ) ) ; else if ( c . componentWillMount ) c . componentWillMount ( ) ; rendered = c . render ( c . props , c . state , c . context ) ; } if ( c . getChildContext ) { context = assign ( assign ( { } , context ) , c . getChildContext ( ) ) ; } return renderToString ( rendered , context , opts , opts . shallowHighOrder !== false , isSvgMode , selectValue ) ; } } // render JSX to HTML let s = '' , html ; if ( props ) { let attrs = Object . keys ( props ) ; // allow sorting lexicographically for more determinism (useful for tests, such as via preact-jsx-chai) if ( opts && opts . sortAttributes === true ) attrs . sort ( ) ; for ( let i = 0 ; i < attrs . length ; i ++ ) { let name = attrs [ i ] , v = props [ name ] ; if ( name === 'children' ) continue ; if ( name . match ( / [\s\n\\/='"\0<>] / ) ) continue ; if ( ! ( opts && opts . allAttributes ) && ( name === 'key' || name === 'ref' ) ) continue ; if ( name === 'className' ) { if ( props . class ) continue ; name = 'class' ; } else if ( isSvgMode && name . match ( / ^xlink:?. / ) ) { name = name . toLowerCase ( ) . replace ( / ^xlink:? / , 'xlink:' ) ; } if ( name === 'style' && v && typeof v === 'object' ) { v = styleObjToCss ( v ) ; } let hooked = opts . attributeHook && opts . attributeHook ( name , v , context , opts , isComponent ) ; if ( hooked || hooked === '' ) { s += hooked ; continue ; } if ( name === 'dangerouslySetInnerHTML' ) { html = v && v . __html ; } else if ( ( v || v === 0 || v === '' ) && typeof v !== 'function' ) { if ( v === true || v === '' ) { v = name ; // in non-xml mode, allow boolean attributes if ( ! opts || ! opts . xml ) { s += ' ' + name ; continue ; } } if ( name === 'value' ) { if ( nodeName === 'select' ) { selectValue = v ; continue ; } else if ( nodeName === 'option' && selectValue == v ) { s += ` ` ; } } s += ` ${ name } ${ encodeEntities ( v ) } ` ; } } } // account for >1 multiline attribute if ( pretty ) { let sub = s . replace ( / ^\n\s* / , ' ' ) ; if ( sub !== s && ! ~ sub . indexOf ( '\n' ) ) s = sub ; else if ( pretty && ~ s . indexOf ( '\n' ) ) s += '\n' ; } s = ` ${ nodeName } ${ s } ` ; if ( String ( nodeName ) . match ( / [\s\n\\/='"\0<>] / ) ) throw s ; let isVoid = String ( nodeName ) . match ( VOID_ELEMENTS ) ; if ( isVoid ) s = s . replace ( / >$ / , ' />' ) ; let pieces = [ ] ; let children ; if ( html ) { // if multiline, indent. if ( pretty && isLargeString ( html ) ) { html = '\n' + indentChar + indent ( html , indentChar ) ; } s += html ; } else if ( props && getChildren ( children = [ ] , props . children ) . length ) { let hasLarge = pretty && ~ s . indexOf ( '\n' ) ; for ( let i = 0 ; i < children . length ; i ++ ) { let child = children [ i ] ; if ( child != null && child !== false ) { let childSvgMode = nodeName === 'svg' ? true : nodeName === 'foreignObject' ? false : isSvgMode , ret = renderToString ( child , context , opts , true , childSvgMode , selectValue ) ; if ( pretty && ! hasLarge && isLargeString ( ret ) ) hasLarge = true ; if ( ret ) pieces . push ( ret ) ; } } if ( pretty && hasLarge ) { for ( let i = pieces . length ; i -- ; ) { pieces [ i ] = '\n' + indentChar + indent ( pieces [ i ] , indentChar ) ; } } } if ( pieces . length ) { s += pieces . join ( '' ) ; } else if ( opts && opts . xml ) { return s . substring ( 0 , s . length - 1 ) + ' />' ; } if ( ! isVoid ) { if ( pretty && ~ s . indexOf ( '\n' ) ) s += '\n' ; s += ` ${ nodeName } ` ; } return s ; }
The default export is an alias of `render()`.
The default export is an alias of render () .