Skip to content

Commit

Permalink
feat(hiccup-html): re-add support for emmet style tags
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Jun 24, 2020
1 parent 469e297 commit bb06dab
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 7 deletions.
36 changes: 32 additions & 4 deletions packages/hiccup-html/src/def.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
import type { Nullable } from "@thi.ng/api";
import type { Attribs } from "./api";

export interface ElementFactory<T, B> {
(attribs?: Nullable<T>, ...body: B[]): [string, Nullable<T>, ...B[]];
(emmet: string, attribs?: Nullable<T>, ...body: B[]): [
string,
Nullable<T>,
...B[]
];
}

/**
* HOF element. Returns new optimized element factory for given tag
* name, optional `baseAttribs` defaults and generics for defining
* supported attributes and children. See {@link ElementFactory} for
* supported call formats of the resulting function..
*
* @param tag
* @param baseAttribs
*/
export const defElement = <T = Partial<Attribs>, B = any>(
tag: string,
baseAttribs?: Partial<T>
) => (attribs: Nullable<T>, ...body: B[]): [string, Nullable<T>, ...B[]] =>
baseAttribs
? [tag, { ...baseAttribs, ...attribs }, ...body]
: [tag, attribs, ...body];
): ElementFactory<T, B> => (...args: any[]): any => {
const $tag = typeof args[0] === "string" ? tag + args.shift() : tag;
return args.length > 1
? baseAttribs
? [$tag, { ...baseAttribs, ...args[0] }, ...args.slice(1)]
: [$tag, args[0], ...args.slice(1)]
: args.length === 1
? baseAttribs
? [$tag, { ...baseAttribs, ...args[0] }]
: [$tag, args[0]]
: baseAttribs
? [$tag, baseAttribs]
: [$tag, null];
};
54 changes: 51 additions & 3 deletions packages/hiccup-html/test/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,54 @@
// import * as assert from "assert";
// import { } from "../src";
import type { IDeref } from "@thi.ng/api";
import * as assert from "assert";
import { AttribVal, defElement } from "../src";

describe("hiccup-html", () => {
it("tests pending");
it("defElement", () => {
type Foo = Partial<{ b: number; c: number }>;
const el = defElement<Foo>("a");
const el2 = defElement<Foo>("a", { b: 1 });
assert.deepEqual(el(), ["a", null]);
assert.deepEqual(el2(), ["a", { b: 1 }]);
assert.deepEqual(el(null), ["a", null]);
assert.deepEqual(el2(null), ["a", { b: 1 }]);
assert.deepEqual(el(null, "body"), ["a", null, "body"]);
assert.deepEqual(el2(null, "body"), ["a", { b: 1 }, "body"]);
assert.deepEqual(el({ c: 2 }), ["a", { c: 2 }]);
assert.deepEqual(el2({ c: 2 }), ["a", { b: 1, c: 2 }]);
assert.deepEqual(el({ c: 2 }, "body"), ["a", { c: 2 }, "body"]);
assert.deepEqual(el2({ c: 2 }, "body"), ["a", { b: 1, c: 2 }, "body"]);
assert.deepEqual(el("#id.foo"), ["a#id.foo", null]);
assert.deepEqual(el2("#id.foo"), ["a#id.foo", { b: 1 }]);
assert.deepEqual(el("#id.foo", { c: 2 }), ["a#id.foo", { c: 2 }]);
assert.deepEqual(el2("#id.foo", { c: 2 }), [
"a#id.foo",
{ b: 1, c: 2 },
]);
assert.deepEqual(el("#id.foo", { c: 2 }, "body"), [
"a#id.foo",
{ c: 2 },
"body",
]);
assert.deepEqual(el2("#id.foo", { c: 2 }, "body"), [
"a#id.foo",
{ b: 1, c: 2 },
"body",
]);
});

it("compile errors", () => {
class D<T> implements IDeref<T | undefined> {
constructor(private x?: T) {}
deref() {
return this.x;
}
}

const el = defElement<{ a: AttribVal<number> }, never>("a");
el({ a: new D() });
el({ a: new D(2) });
// compile errors:
// el({ b: new D("x") }); // wrong attrib type
// el(null, "body"); // no body allowed
});
});

0 comments on commit bb06dab

Please sign in to comment.