+
+ assertEquals(trueHtml.toString().replace('=""', ''), '
')
+ assertEquals(falseHtml.toString(), '
')
+})
+
+Deno.test('JSX: number', async () => {
+ const html =
+
+ assertEquals(html.toString(), '
')
+})
+
+Deno.test('JSX: style', async () => {
+ const html =
+ assertEquals(html.toString(), '
')
+})
diff --git a/src/jsx/base.ts b/src/jsx/base.ts
index 5523c0a8..7b184373 100644
--- a/src/jsx/base.ts
+++ b/src/jsx/base.ts
@@ -62,7 +62,7 @@ const emptyTags = [
'track',
'wbr',
]
-const booleanAttributes = [
+export const booleanAttributes = [
'allowfullscreen',
'async',
'autofocus',
diff --git a/src/jsx/jsx-runtime.ts b/src/jsx/jsx-runtime.ts
index af7444f2..77da8f61 100644
--- a/src/jsx/jsx-runtime.ts
+++ b/src/jsx/jsx-runtime.ts
@@ -6,13 +6,43 @@
export { jsxDEV as jsx, Fragment } from './jsx-dev-runtime'
export { jsxDEV as jsxs } from './jsx-dev-runtime'
export type { JSX } from './jsx-dev-runtime'
-
import { html, raw } from '../helper/html'
-import type { HtmlEscapedString } from '../utils/html'
+import type { HtmlEscapedString, StringBuffer, HtmlEscaped } from '../utils/html'
+import { escapeToBuffer, stringBufferToString } from '../utils/html'
+import { styleObjectForEach } from './utils'
+
export { html as jsxTemplate }
+
export const jsxAttr = (
- name: string,
- value: string | Promise
-): HtmlEscapedString | Promise =>
- typeof value === 'string' ? raw(name + '="' + html`${value}` + '"') : html`${name}="${value}"`
+ key: string,
+ v: string | Promise | Record
+): HtmlEscapedString | Promise => {
+ const buffer: StringBuffer = [`${key}="`] as StringBuffer
+ if (key === 'style' && typeof v === 'object') {
+ // object to style strings
+ let styleStr = ''
+ styleObjectForEach(v as Record, (property, value) => {
+ if (value != null) {
+ styleStr += `${styleStr ? ';' : ''}${property}:${value}`
+ }
+ })
+ escapeToBuffer(styleStr, buffer)
+ buffer[0] += '"'
+ } else if (typeof v === 'string') {
+ escapeToBuffer(v, buffer)
+ buffer[0] += '"'
+ } else if (v === null || v === undefined) {
+ return raw('')
+ } else if (typeof v === 'number' || (v as unknown as HtmlEscaped).isEscaped) {
+ buffer[0] += `${v}"`
+ } else if (v instanceof Promise) {
+ buffer.unshift('"', v)
+ } else {
+ escapeToBuffer(v.toString(), buffer)
+ buffer[0] += '"'
+ }
+
+ return buffer.length === 1 ? raw(buffer[0]) : stringBufferToString(buffer, undefined)
+}
+
export const jsxEscape = (value: string) => value