From 5993b6106774459ee88bcbef3bed9641b5ce772f Mon Sep 17 00:00:00 2001 From: Taku Amano Date: Sun, 12 Jun 2022 08:20:31 +0900 Subject: [PATCH] feat(middleware/jsx): We need Fragment. (#310) --- src/middleware/jsx/index.test.tsx | 28 +++++++++++++++++++++++++--- src/middleware/jsx/index.ts | 14 +++++++++++--- tsconfig.json | 1 + 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/middleware/jsx/index.test.tsx b/src/middleware/jsx/index.test.tsx index 4bcd99d5..eb5c3a41 100644 --- a/src/middleware/jsx/index.test.tsx +++ b/src/middleware/jsx/index.test.tsx @@ -1,5 +1,5 @@ import { Hono } from '../../hono' -import { h, jsx, memo } from '.' +import { h, jsx, memo, Fragment } from '.' describe('JSX middleware', () => { const app = new Hono() @@ -146,8 +146,8 @@ describe('memo', () => { it('custom propsAreEqual', () => { const Body = memo( - ({ counter }: { counter: number, refresh?: boolean }) => {counter}, - (_, nextProps) => typeof nextProps.refresh == 'undefined' ? true : !nextProps.refresh + ({ counter }: { counter: number; refresh?: boolean }) => {counter}, + (_, nextProps) => (typeof nextProps.refresh == 'undefined' ? true : !nextProps.refresh) ) let template = @@ -160,3 +160,25 @@ describe('memo', () => { expect(template.toString()).toBe('2') }) }) + +describe('Fragment', () => { + it('Should render children', () => { + const template = ( + <> +

1

+

2

+ + ) + expect(template.toString()).toBe('

1

2

') + }) + + it('Should render nothing for empty Fragment', () => { + const template = <> + expect(template.toString()).toBe('') + }) + + it('Should render nothing for undefined', () => { + const template = <>{undefined} + expect(template.toString()).toBe('') + }) +}) diff --git a/src/middleware/jsx/index.ts b/src/middleware/jsx/index.ts index 8f52c270..08ccc7d1 100644 --- a/src/middleware/jsx/index.ts +++ b/src/middleware/jsx/index.ts @@ -32,7 +32,7 @@ export const h = ( return tag.call(null, { ...props, children: children.length <= 1 ? children[0] : children }) } - let result = `<${tag}` + let result = tag !== '' ? `<${tag}` : '' const propsKeys = Object.keys(props || {}) for (let i = 0, len = propsKeys.length; i < len; i++) { @@ -53,7 +53,9 @@ export const h = ( result += ` ${propsKeys[i]}="${escape(v.toString())}"` } - result += '>' + if (tag !== '') { + result += '>' + } const flattenChildren = children.flat(Infinity) for (let i = 0, len = flattenChildren.length; i < len; i++) { @@ -67,7 +69,9 @@ export const h = ( } } - result += `` + if (tag !== '') { + result += `` + } const escapedString = new String(result) as EscapedString escapedString.isEscaped = true @@ -111,3 +115,7 @@ export const memo = ( return (computed ||= component(props)) }) as FC } + +export const Fragment = (props: { key?: string; children?: any }): EscapedString => { + return h('', {}, ...(props.children || [])) +} diff --git a/tsconfig.json b/tsconfig.json index 58c6b1c5..2d1cffa0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,7 @@ ], "jsx": "react", "jsxFactory": "h", + "jsxFragmentFactory": "Fragment", }, "include": [ "src/**/*.ts",