render.ts
60 lines
| 2.0 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r98 | import { IScope, Scope } from "./Scope"; | ||
| import { destroy, isNode, isRendition, isWidget, Rendition } from "./traits"; | ||||
| let _scope = Scope.dummy; | ||||
| const beginRender = async () => { | ||||
| } | ||||
| const endRender = () => { | ||||
| } | ||||
| /** Returns the current scope */ | ||||
| export const getScope = () => _scope; | ||||
| /** Schedules the rendition to be rendered to the DOM Node | ||||
| * @param rendition The rendition to be rendered | ||||
| * @param scope The scope | ||||
| */ | ||||
| export const render = async (rendition: unknown, scope = Scope.dummy) => { | ||||
| await beginRender(); | ||||
| const prev = _scope; | ||||
| _scope = scope; | ||||
| try { | ||||
| const node = getItemDom(rendition, scope); | ||||
| 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 if (v instanceof Array) { | ||||
| // arrays will be translated to document fragments | ||||
| const fragment = document.createDocumentFragment(); | ||||
| v.map(item => getItemDom(item, scope)) | ||||
| .forEach(node => fragment.appendChild(node)); | ||||
| return fragment; | ||||
| } else { | ||||
| // bug: explicit error otherwise | ||||
| throw new Error("Invalid parameter: " + v); | ||||
| } | ||||
| } | ||||
