From e91648466a1e0922a82bdc5901271c4a9b883e3c Mon Sep 17 00:00:00 2001 From: Eli <88557639+lishaduck@users.noreply.github.com> Date: Thu, 6 Jun 2024 12:55:24 -0500 Subject: [PATCH 1/2] fix(xml): use the type system to verify version Reverts: 78ed4ac2a1641c208844600c0fbea4b23bbd0b06 --- xml/_types.ts | 4 ++-- xml/stringify.ts | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/xml/_types.ts b/xml/_types.ts index a7630ce..d29b61e 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 fabf2b7..48bf0c4 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 ??= " " From c9ef07b6466617fcd3ab686345fe4097f8c1b191 Mon Sep 17 00:00:00 2001 From: Eli <88557639+lishaduck@users.noreply.github.com> Date: Thu, 6 Jun 2024 22:16:05 -0500 Subject: [PATCH 2/2] docs(xml): write a tip on enhanced type safety --- xml/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/xml/README.md b/xml/README.md index cdf729b..2b137eb 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