diff --git a/xml/README.md b/xml/README.md index cdf729b1..2b137eb2 100644 --- a/xml/README.md +++ b/xml/README.md @@ -244,6 +244,24 @@ Note that while you can _theoretically_ use internal API properties, currently, Supporting `~children` might be added in the future ([#57](https://github.com/lowlighter/libs/issues/57)) for mixed content, but its behavior is not yet well defined. Setting `~name` manually might lead to unexpected behaviors, especially if it differs from the parent key. +> [!TIP] +> For more type-safety, write `satisfies Partial` after whatever you pass into `stringify`, like so: +> +> +> +> ``` +> import { stringify, type xml_document } from "./stringify.ts" +> +> const ast = { +> "@version": "1.0", +> "@encoding": "UTF-8", +> "root": {}, +> } satisfies Partial +> const result = stringify(ast) +> ``` +> +> We expose lax typing, but `Partial` uses the stricter typing we use internally. + ## ๐Ÿ“œ License and credits ```plaintext diff --git a/xml/_types.ts b/xml/_types.ts index a7630ce9..d29b61e5 100644 --- a/xml/_types.ts +++ b/xml/_types.ts @@ -25,11 +25,11 @@ export type xml_node = { /** XML document. */ export type xml_document = xml_node & { /** XML version. */ - ["@version"]?: string + ["@version"]?: `1.${number}` /** XML character encoding. */ ["@encoding"]?: string /** XML standalone. */ - ["@standalone"]?: string + ["@standalone"]?: "yes" | "no" /** XML doctype. */ ["#doctype"]?: xml_node /** XML instructions. */ diff --git a/xml/stringify.ts b/xml/stringify.ts index fabf2b79..48bf0c4b 100644 --- a/xml/stringify.ts +++ b/xml/stringify.ts @@ -40,6 +40,9 @@ type _options = options & { format: NonNullable } /** Internal symbol to store properties without erasing user-provided ones. */ const internal = Symbol("internal") +/** A laxer type for what can be stringified. We wonโ€™t ever create this, but weโ€™ll accept it. */ +export type stringifyable = Partial & { "@version": string; "@standalone": string }> + /** * Stringify an {@link xml_document} object into a XML string. * @@ -50,6 +53,8 @@ const internal = Symbol("internal") * import { stringify } from "./stringify.ts" * * console.log(stringify({ + * "@version": "1.0", + * "@standalone": "yes", * root: { * text: "hello", * array: ["world", "monde", "ไธ–็•Œ", "๐ŸŒ"], @@ -63,7 +68,7 @@ const internal = Symbol("internal") * })) * ``` */ -export function stringify(document: Partial, options?: options): string { +export function stringify(document: stringifyable, options?: options): string { options ??= {} options.format ??= {} options.format.indent ??= " "