UNPKG

@thi.ng/hiccup

Version:

HTML/SVG/XML serialization of nested data structures, iterables & closures

175 lines 5.99 kB
import type { FnU } from "@thi.ng/api"; /** * Options to customize the behavior of {@link serialize}. */ export interface SerializeOpts { /** * Arbitrary user context object */ ctx?: any; /** * If true, auto-escape entities via {@link SerializeOpts.escapeFn}. * * @defaultValue false */ escape: boolean; /** * Only used if {@link SerializeOpts.escape} is enabled. Function to escape * entities. By default uses * [`escapeEntitiesNum`](https://docs.thi.ng/umbrella/strings/functions/escapeEntitiesNum.html). */ escapeFn: FnU<string>; /** * If true (default: false), all text content will be wrapped in `<span>` * elements (to ensure DOM compatibility with hdom). The only elements for * spans are never created are listed in {@link NO_SPANS}. * * @defaultValue false */ span: boolean; /** * If true (default: false), all elements will have an autogenerated `key` * attribute injected. If {@link SerializeOpts.span} is enabled, `keys` will * be enabled by default too (since in this case we assume the output is * meant to be compatible with [`thi.ng/hdom`](https://thi.ng/hdom)). * * @defaultValue false */ keys: boolean; /** * If true, some serialization behaviors will be adjusted to target XML * output. * * @remarks * Currently, the following aspects are supported: * * - boolean attributes are serialized as `name=""` rather than just `name` * * @defaultValue false */ xml: boolean; } /** * Recursively normalizes and serializes given tree as HTML/SVG/XML string. * Expands any embedded component functions with their results. * * @remarks * Each node of the input tree can have one of the following input forms: * * ```js * ["tag", ...] * ["tag#id.class1.class2", ...] * ["tag", {other: "attrib"}, ...] * ["tag", {...}, "body", function, ...] * [function, arg1, arg2, ...] * [{render: (ctx,...) => [...]}, args...] * iterable * ``` * * Tags can be defined in "Emmet" convention, e.g. * * ```js * ["div#foo.bar.baz", "hi"] // <div id="foo" class="bar baz">hi</div> * ``` * * The presence of the attributes object (2nd array index) is optional. Any * attribute values, incl. functions are allowed. If the latter, the function is * called with the full attribs object as argument and the return value is used * for the attribute. This allows for the dynamic creation of attrib values * based on other attribs. The only exception to this are event attributes, i.e. * attribute names starting with "on". Function values assigned to event * attributes will be omitted from the output. * * ```js * ["div#foo", { bar: (attribs) => attribs.id + "-bar" }] * // <div id="foo" bar="foo-bar"></div> * ``` * * The `style` attribute can ONLY be defined as string or object. * * ```js * ["div", { style: { color: "red", background: "#000" } }] * // <div style="color:red;background:#000;"></div> * ``` * * Boolean attribs are serialized in HTML5 syntax (present or not). `null`, * `undefined` or empty string attrib values are ignored. * * Any `null` or `undefined` array values (other than in head position) will * also be removed, unless a function is in head position. * * A function in head position of a node acts as a mechanism for component * composition & delayed execution. The function will only be executed at * serialization time. In this case the optional global context object and all * other elements of that node / array are passed as arguments when that * function is called. The return value the function MUST be a valid new tree * (or `undefined`). * * If the `ctx` option is given it'll be passed to each embedded component fns. * Optionally call {@link derefContext} prior to `serialize()` to auto-deref * context keys with values implementing the * [`IDeref`](https://docs.thi.ng/umbrella/api/interfaces/IDeref.html) * interface. * * ```js * import { serialize } from "@thi.ng/hiccup"; * * const foo = (ctx, a, b) => ["div#" + a, ctx.foo, b]; * * serialize([foo, "id", "body"], { ctx: { foo: { class: "black" } } }) * // <div id="id" class="black">body</div> * ``` * * Functions located in other positions are called ONLY with the global context * arg and can return any (serializable) value (i.e. new trees, strings, * numbers, iterables or any type with a suitable `.toString()`, `.toHiccup()` * or `.deref()` implementation). * * hiccup & hdom control attributes (i.e. attrib names prefixed with `__`) will * be omitted from the output. The only control attrib supported by this package * is `__serialize`. If set to `false`, the entire tree branch below (and * including) the element with that attrib will be excluded from the output. * * **See {@link SerializeOpts} for further available options.** * * Single or multiline comments can be included using the special `COMMENT` tag * (`"__COMMENT__"`) (always WITHOUT attributes!). * * ```js * import { COMMENT } from "@thi.ng/hiccup"; * * [COMMENT, "Hello world"] * // serializes to: * // <!-- Hello world --> * * [COMMENT, "Hello", "world"] * // <!-- * // Hello * // world * // --> * ``` * * Currently, the only processing / DTD instructions supported are: * * - `?xml` * - `!DOCTYTPE` * - `!ELEMENT` * - `!ENTITY` * - `!ATTLIST` * * These are used as follows (attribs are only allowed for `?xml`, all others * only accept a body string which is taken as is): * * ```js * serialize(["?xml", { version: "1.0", standalone: "yes" }]) * // <?xml version="1.0" standalone="yes"?> * * ["!DOCTYPE", "html"] // (also available as DOCTYPE_HTML) * // <!DOCTYPE html> * ``` * * @param tree - hiccup elements / component tree * @param opts - options */ export declare const serialize: (tree: any, opts?: Partial<SerializeOpts>, path?: number[]) => string; //# sourceMappingURL=serialize.d.ts.map