UNPKG

hastx

Version:

JSX Transform emitting Rehype syntax trees (HAST)

104 lines (89 loc) 2.58 kB
import type * as hast from "@types/hast"; import type * as html from "./html.js"; import type * as svg from "./svg.js"; export type Element = hast.Element; export type JSXChild = string | number | boolean | JSXElement; export type JSXChildren = JSXChild | JSXChild[]; export type JSXElement = hast.Element | hast.Root | hast.Text; export type JSXElementProps = Record<string, string> & { children?: JSXChildren; }; export type JSXComponentProps = Record<string, unknown> & { key?: string; }; export interface JSXComponent { (props: JSXComponentProps): JSXElement; } export interface JSXElementConstructor { //deno-lint-ignore no-explicit-any (...args: any[]): JSXElement; } declare global { export namespace JSX { type Element = JSXElement; type ElementType = | keyof html.HTMLElements | keyof svg.SVGElements | JSXElementConstructor; interface IntrinsicElements extends html.HTMLElements, svg.SVGElements {} interface ElementChildrenAttribute { //deno-lint-ignore ban-types children: {}; } } } export function jsx( component: JSXComponent, props: JSXComponentProps, ): JSXElement; export function jsx(element: string, props: JSXElementProps): JSXElement; export function jsx( type: string | JSXComponent, props: JSXElementProps | JSXComponentProps, key?: string, ): JSXElement { if (typeof type === "string") { let tagName = type; let { children, ...properties } = props as JSXElementProps; let className = properties.class ? { className: properties.class } : null; return { type: "element", tagName, properties: { ...properties, ...className }, children: read(children), }; } else { return type({ ...props, ...(key ? { key } : {}) }); } } export const jsxs = jsx; export const jsxDEV = jsx; export function Fragment( props: { children?: JSXChild | JSXChild[] }, ): hast.Root { let { children = [] } = props; return { type: "root", children: read(children), }; } function read(children?: JSXChild | JSXChild[]): (hast.Element | hast.Text)[] { let nodes = Array.isArray(children) ? children : (children ? [children] : []); return nodes.flatMap((child) => { switch (typeof child) { case "number": case "boolean": case "string": return [{ type: "text", value: String(child), }]; default: if (child.type === "root") { return child.children as Array<hast.Element | hast.Text>; } else { return [child]; } } }); }