diff --git a/.gitignore b/.gitignore
index c3f3a00..d3a1666 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@ pnpm*
dist
tmp
*.log
-.out*
\ No newline at end of file
+.out*
+test
\ No newline at end of file
diff --git a/src/html.spec.tsx b/src/html.spec.tsx
index 41956a5..f380a7b 100644
--- a/src/html.spec.tsx
+++ b/src/html.spec.tsx
@@ -5,8 +5,8 @@ import { html as h } from "./html"
describe("HTML", () => {
it("should generate a string", () => {
- let s = h("a", { href: "example.com" }, "Welcome")
- expect(s).toEqual('Welcome')
+ let s = h("a", { href: "example.com" }, "Welcome & Hello & Ciao")
+ expect(s).toEqual('Welcome & Hello & Ciao') // the second & is correct, because plain string should be unescaped
})
it("should nest", () => {
diff --git a/src/html.ts b/src/html.ts
index b04e48e..c58d286 100644
--- a/src/html.ts
+++ b/src/html.ts
@@ -27,18 +27,8 @@ export const SELF_CLOSING_TAGS = [
"command",
]
-let USED_JSX: Record = {} // HACK:dholtwick:2016-08-23
-
-export function CDATA(s: string) {
- s = ""
- USED_JSX[s] = true
- return s
-}
-
-export function HTML(s: string) {
- USED_JSX[s] = true
- return s
-}
+export const CDATA = (s: string) => ""
+export const HTML = (s: string) => s
// export function prependXMLIdentifier(s) {
// return '\n' + s
@@ -51,15 +41,17 @@ export function markup(
attrs: any = {},
children?: any[]
) {
- // console.log('markup', xmlMode, tag, attrs, children)
const hasChildren = children && children.length > 0
- let s = ""
+
+ let parts: string[] = []
tag = tag.replace(/__/g, ":")
- if (tag !== "noop") {
+
+ // React fragment <>...> and ours: ...
+ if (tag !== "noop" && tag !== "") {
if (tag !== "cdata") {
- s += `<${tag}`
+ parts.push(`<${tag}`)
} else {
- s += " v[k] != null)
- .map((k) => {
- let vv = v[k]
- vv = typeof vv === "number" ? vv + "px" : vv
- return `${k
- .replace(/([a-z])([A-Z])/g, "$1-$2")
- .toLowerCase()}:${vv}`
- })
- .join(";")}"`
+ parts.push(
+ ` ${name}="${Object.keys(v)
+ .filter((k) => v[k] != null)
+ .map((k) => {
+ let vv = v[k]
+ vv = typeof vv === "number" ? vv + "px" : vv
+ return `${k
+ .replace(/([a-z])([A-Z])/g, "$1-$2")
+ .toLowerCase()}:${vv}`
+ })
+ .join(";")}"`
+ )
} else if (v !== false && v != null) {
- s += ` ${name}="${escapeHTML(v.toString())}"`
+ parts.push(` ${name}="${escapeHTML(v.toString())}"`)
}
}
}
if (tag !== "cdata") {
if (xmlMode && !hasChildren) {
- s += " />"
- USED_JSX[s] = true
- return s
+ parts.push(" />")
+ return parts.join("")
} else {
- s += `>`
+ parts.push(">")
}
}
- if (!xmlMode) {
- if (SELF_CLOSING_TAGS.includes(tag)) {
- USED_JSX[s] = true
- return s
- }
+ if (!xmlMode && SELF_CLOSING_TAGS.includes(tag)) {
+ return parts.join("")
}
}
@@ -118,10 +108,10 @@ export function markup(
child = [child]
}
for (let c of child) {
- if (USED_JSX[c] || tag === "script" || tag === "style") {
- s += c
+ if (c.startsWith("<") || tag === "script" || tag === "style") {
+ parts.push(c)
} else {
- s += escapeHTML(c.toString())
+ parts.push(escapeHTML(c.toString()))
}
}
}
@@ -129,18 +119,17 @@ export function markup(
}
if (attrs.html) {
- s += attrs.html
+ parts.push(attrs.html)
}
if (tag !== "noop") {
if (tag !== "cdata") {
- s += `${tag}>`
+ parts.push(`${tag}>`)
} else {
- s += "]]>"
+ parts.push("]]>")
}
}
- USED_JSX[s] = true
- return s
+ return parts.join("")
}
export function html(itag: string, iattrs?: object, ...ichildren: any[]) {