|
|
import { IScope, Scope } from "./Scope";
|
|
|
import { destroy, isNode, isRendition, isWidget, Rendition } from "./traits";
|
|
|
|
|
|
let _scope = Scope.dummy;
|
|
|
|
|
|
const beginRender = async () => {
|
|
|
}
|
|
|
|
|
|
const endRender = () => {
|
|
|
}
|
|
|
|
|
|
export const getScope = () => _scope;
|
|
|
|
|
|
export const render = async (rendition: () => Rendition, scope = Scope.dummy) => {
|
|
|
await beginRender();
|
|
|
const prev = _scope;
|
|
|
_scope = scope;
|
|
|
try {
|
|
|
const node = rendition().getDomNode();
|
|
|
scope.own(() => destroy(node));
|
|
|
return node;
|
|
|
} finally {
|
|
|
_scope = prev;
|
|
|
endRender();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Renders DOM element for different types of the argument. */
|
|
|
export const getItemDom = (v: unknown, scope: IScope) => {
|
|
|
if (typeof v === "string" || typeof v === "number" || v instanceof RegExp || v instanceof Date) {
|
|
|
// primitive types converted to the text nodes
|
|
|
return document.createTextNode(v.toString());
|
|
|
} else if (isNode(v)) {
|
|
|
// nodes are kept as is
|
|
|
return v;
|
|
|
} else if (isRendition(v)) {
|
|
|
// renditions are instantiated
|
|
|
return v.getDomNode(scope);
|
|
|
} else if (isWidget(v)) {
|
|
|
// widgets are converted to it's markup
|
|
|
return v.domNode;
|
|
|
} else if (typeof v === "boolean" || v === null || v === undefined) {
|
|
|
// null | undefined | boolean are removed, converted to comments
|
|
|
return document.createComment(`[${typeof v} ${String(v)}]`);
|
|
|
} else {
|
|
|
// bug: explicit error otherwise
|
|
|
throw new Error("Invalid parameter: " + v);
|
|
|
}
|
|
|
}
|
|
|
|