From f142c0e921a2b09b41116f708f804c26fb411579 Mon Sep 17 00:00:00 2001 From: Fatih Kalifa Date: Fri, 6 Aug 2021 12:25:43 +0700 Subject: [PATCH] code golf --- src/index.browser.ts | 53 ++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/index.browser.ts b/src/index.browser.ts index e2c03a7..6403b3c 100644 --- a/src/index.browser.ts +++ b/src/index.browser.ts @@ -4,6 +4,9 @@ import React, { ReactNode } from 'react'; import mapAttribute, { RawAttributes } from './mapAttribute'; import { HtmrOptions, HTMLTags } from './types'; +const rce = React.createElement; +const dce = document.createElement.bind(document); + export default function htmrBrowser( html: string, options: Partial = {} @@ -12,7 +15,7 @@ export default function htmrBrowser( throw new TypeError('Expected HTML string'); } - const container = document.createElement('div'); + const container = dce('div'); container.innerHTML = html.trim(); const nodes = Array.from(container.childNodes) @@ -109,14 +112,13 @@ function toReactNode( } // map HTML attribute to react props, and optionally DOM prop by using array -// if DOM prop is same as attribute name, use single item array const attributePropMap: Record = { for: 'htmlFor', class: 'className', // react prop and DOM prop have different casing allowfullscreen: ['allowFullScreen', 'allowFullscreen'], autocomplete: 'autoComplete', - autofocus: ['autoFocus'], + autofocus: 'autoFocus', contenteditable: 'contentEditable', spellcheck: 'spellCheck', srcdoc: 'srcDoc', @@ -132,33 +134,42 @@ const attributePropMap: Record = { */ function getPropInfo(tagName: HTMLTags, attributeName: string) { const propName = attributePropMap[attributeName]; - const el = document.createElement(tagName); + const el = dce(tagName); + + let reactProp: string = ''; + let isBoolean: boolean = false; // handle edge cases first if (propName) { - const reactProp = Array.isArray(propName) ? propName[0] : propName; - const domProp = Array.isArray(propName) - ? propName[1] || attributeName - : propName; - return { name: reactProp, isBoolean: checkBooleanAttribute(el, domProp) }; - } + reactProp = propName as string; + let domProp = reactProp; + if (Array.isArray(propName)) { + reactProp = propName[0]; + domProp = propName[1]; + } + isBoolean = checkBooleanAttribute(el, domProp, attributeName); + } else { + for (let propName in el) { + if (propName.toLowerCase() === attributeName.toLowerCase()) { + reactProp = propName; + isBoolean = checkBooleanAttribute(el, propName, attributeName); + break; + } + } - for (let propName in el) { - if (propName.toLowerCase() === attributeName.toLowerCase()) { - return { name: propName, isBoolean: checkBooleanAttribute(el, propName) }; + if (!reactProp) { + reactProp = attributeName; + isBoolean = checkBooleanAttribute(el, attributeName, attributeName); } } - return { - name: attributeName, - isBoolean: checkBooleanAttribute(el, attributeName), - }; + return { name: reactProp, isBoolean }; } -function checkBooleanAttribute(el: HTMLElement, prop: any) { +function checkBooleanAttribute(el: HTMLElement, prop: string, attr: string) { el.setAttribute(prop, ''); // @ts-ignore - return el[prop] === true; + return el[prop] === true || el[attr] === true; } function reactCreateElement( @@ -171,8 +182,8 @@ function reactCreateElement( const defaultTransform = transform._; return customElement - ? React.createElement(customElement as any, props, children) + ? rce(customElement as any, props, children) : defaultTransform ? defaultTransform(tag, props, children) - : React.createElement(tag, props, children); + : rce(tag, props, children); }