obsidian-visualiser/shared/dom.virtual.util.ts

106 lines
3.5 KiB
TypeScript

import { iconLoaded, loadIcon, getIcon } from "iconify-icon";
import type { NodeProperties, Class } from "#shared/dom.util";
export type VirtualNode = string;
export function dom<K extends keyof HTMLElementTagNameMap>(tag: K, properties?: NodeProperties, children?: VirtualNode[]): VirtualNode
{
const node = [`<${tag}`];
if(properties?.attributes)
for(const [k, v] of Object.entries(properties.attributes))
if(typeof v === 'string' || typeof v === 'number') node.push(` ${k}="${v.toString(10).replaceAll('"', "'")}"`);
else if(typeof v === 'boolean' && v) node.push(` ${k.replaceAll('"', "'")}`);
if(properties?.class)
node.push(` class="${mergeClasses(properties.class).replaceAll('"', "'")}"`);
if(properties?.style)
{
if(typeof properties.style === 'string') node.push(` style="${properties.style.replaceAll('"', "'")}"`);
else node.push(` style="${Object.entries(properties.style).map(([k, v]) => { if(v !== undefined && v !== false) return `${k.replaceAll('"', "'")}: ${v.toString(10).replaceAll('"', "'")};` }).join('')}"`);
}
if(properties?.text)
{
children ??= [];
children?.push(properties.text);
}
if(children)
node.push(`>${children.filter(e => !!e).join('')}</${tag}>`);
else
node.push(`></${tag}>`)
return node.join('');
}
export function div(cls?: Class, children?: VirtualNode[]): VirtualNode
{
return dom("div", { class: cls }, children);
}
export function span(cls?: Class, text?: string): VirtualNode
{
return dom("span", { class: cls, text: text });
}
export function svg<K extends keyof SVGElementTagNameMap>(tag: K, properties?: NodeProperties, children?: VirtualNode[]): VirtualNode
{
const node = [`<${tag}`];
if(properties?.attributes)
for(const [k, v] of Object.entries(properties.attributes))
if(typeof v === 'string' || typeof v === 'number') node.push(` ${k.replaceAll('"', "'")}="${v.toString(10).replaceAll('"', "'")}"`);
else if(typeof v === 'boolean' && v) node.push(` ${k.replaceAll('"', "'")}`);
if(properties?.class)
node.push(` class="${mergeClasses(properties.class).replaceAll('"', "'")}"`);
if(properties?.style)
{
if(typeof properties.style === 'string') node.push(` style="${properties.style.replaceAll('"', "'")}"`);
else node.push(` style="${Object.entries(properties.style).map(([k, v]) => { if(v !== undefined && v !== false) return `${k.replaceAll('"', "'")}: ${v.toString(10).replaceAll('"', "'")};"` }).join('')}"`);
}
if(children)
node.push(`>${children.filter(e => !!e).join('')}</${tag}>`);
else
node.push(`></${tag}>`)
return node.join(' ');
}
export function text(data: string): VirtualNode
{
return data;
}
export interface IconProperties
{
mode?: string;
inline?: boolean;
noobserver?: boolean;
width?: string|number;
height?: string|number;
flip?: string;
rotate?: number|string;
style?: Record<string, string | undefined> | string;
class?: Class;
}
export function icon(name: string, properties?: IconProperties): VirtualNode
{
return '';
}
export function mergeClasses(classes: Class): string
{
if(typeof classes === 'string')
{
return classes.trim();
}
else if(Array.isArray(classes))
{
return classes.map(e => mergeClasses(e)).join(' ');
}
else if(classes)
{
return Object.entries(classes).filter(e => e[1]).map(e => e[0].trim()).join(' ');
}
else
{
return '';
}
}