Skip to content

Commit

Permalink
feat(hiccup): add special INLINE tag & __escape behavior attrib
Browse files Browse the repository at this point in the history
- add `INLINE` tag & handling for embedded markup
- add `__escape` control attrib to enable/disable entity escaping (per element)
- add tests
  • Loading branch information
postspectacular committed Jan 22, 2025
1 parent 38cce6b commit 42e7717
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 1 deletion.
3 changes: 3 additions & 0 deletions packages/hiccup/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export const RE_TAG = /^([^\s.#]+)(?:#([^\s.#]+))?(?:\.([^\s#]+))?$/;
/** @internal */
export const COMMENT = "__COMMENT__";

/** @internal */
export const INLINE = "__INLINE__";

/** @internal */
export const CDATA = "!CDATA";

Expand Down
7 changes: 7 additions & 0 deletions packages/hiccup/src/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
ATTRIB_JOIN_DELIMS,
CDATA,
COMMENT,
INLINE,
NO_CLOSE_EMPTY,
NO_SPANS,
PROC_TAGS,
Expand Down Expand Up @@ -246,6 +247,8 @@ const __serializeElement = (tree: any[], opts: SerializeOpts, path: any[]) => {
)
: tag === COMMENT
? __serializeComment(tree)
: tag === INLINE
? __serializeInline(tree)
: tag == CDATA
? __serializeCData(tree)
: isString(tag)
Expand All @@ -261,6 +264,7 @@ const __serializeTag = (tree: any[], opts: SerializeOpts, path: any[]) => {
const attribs = tree[1];
if (attribs.__skip || attribs.__serialize === false) return "";
opts.keys && attribs.key === undefined && (attribs.key = path.join("-"));
if (attribs.__escape != null) opts = { ...opts, escape: attribs.__escape };
const tag = tree[0];
const body = tree[2]
? __serializeBody(tag, tree[2], opts, path)
Expand Down Expand Up @@ -353,6 +357,9 @@ const __serializeComment = (tree: any[]) =>
.join("\n")}\n-->\n`
: `\n<!-- ${tree[1]} -->\n`;

/** @internal */
const __serializeInline = (tree: any[]) => tree.slice(1).join("");

/** @internal */
const __serializeCData = (tree: any[]) =>
`<![CDATA[\n${tree.slice(1).join("\n")}\n]]>`;
Expand Down
29 changes: 28 additions & 1 deletion packages/hiccup/test/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Atom } from "@thi.ng/atom";
import { foaf } from "@thi.ng/prefixes";
import { escapeEntities } from "@thi.ng/strings";
import { expect, test } from "bun:test";
import { DOCTYPE_HTML, XML_PROC, serialize } from "../src/index.js";
import { DOCTYPE_HTML, INLINE, XML_PROC, serialize } from "../src/index.js";

const _check = (a: any, b: any) => expect(serialize(a)).toBe(b);

Expand Down Expand Up @@ -369,3 +369,30 @@ test("escape entities (custom)", () =>
escapeFn: escapeEntities,
})
).toBe("<div>&Auml;&ouml;&uuml; &lt;&amp;&gt; &apos;&quot; &mdash;</div>"));

test("escape behavior attrib", () =>
expect(
serialize(
[
"a",
"&",
[
"b",
{ __escape: false },
"x < y",
["c", { __escape: true }, "'"],
],
"&",
],
{
escape: true,
}
)
).toBe("<a>&amp;<b>x < y<c>&apos;</c></b>&amp;</a>"));

test("inline", () =>
expect(
serialize(["div", {}, [INLINE, "<inline>&amp;</inline>"]], {
escape: true,
})
).toBe("<div><inline>&amp;</inline></div>"));

0 comments on commit 42e7717

Please sign in to comment.