UNPKG

hastx

Version:

JSX Transform emitting Rehype syntax trees (HAST)

127 lines (112 loc) 2.98 kB
import type * as hast from "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 | undefined | null | JSXElement; export type JSXChildren = JSXChild | JSXChildren[]; 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): JSXChildren; } export interface JSXElementConstructor { //deno-lint-ignore no-explicit-any (...args: any[]): JSXChildren; } 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; if (tagName === "template") { return { type: "element", tagName, properties: { ...properties, ...className }, children: [], content: { type: "root", children: read(children), }, }; } else { return { type: "element", tagName, properties: { ...properties, ...className }, children: read(children).filter((child) => child.type !== "doctype"), }; } } else { return { type: "root", children: read(type({ ...props, ...(key ? { key } : {}) })), }; } } export const jsxs = jsx; export const jsxDEV = jsx; export function Fragment(props: { children?: JSXChildren }): hast.Root { let { children = [] } = props; return { type: "root", children: read(children), }; } function read(children?: JSXChildren): hast.RootContent[] { switch (typeof children) { case "undefined": case "boolean": return []; case "number": case "string": return [{ type: "text", value: String(children), }]; default: if (children === null) { return []; } else if (Array.isArray(children)) { return children.flatMap(read); } else if (children.type === "root") { return children.children; } else { return [children]; } } }