astro-d2
Version:
Astro integration and remark plugin to transform D2 Markdown code blocks into diagrams.
110 lines (98 loc) • 3.39 kB
text/typescript
import { z } from 'astro/zod'
export const AttributesSchema = z
.object({
/**
* When specified, the diagram will package multiple boards as 1 SVG which transitions through each board at the
* specified interval (in milliseconds).
*/
animateInterval: z.string().optional(),
/**
* Overrides the global `appendix` configuration for the diagram.
*/
appendix: z
.union([z.literal('true'), z.literal('false')])
.optional()
.transform((value) => value === 'true'),
/**
* The dark theme to use for the diagram when the user's system preference is set to dark mode.
*
* To disable the dark theme, set this attribute to `'false'`.
*
* @see https://d2lang.com/tour/themes
*/
darkTheme: z
.string()
.optional()
.transform((value) => (value === 'false' ? false : value)),
/**
* Overrides the global `inline` configuration for the diagram.
*/
inline: z
.union([z.literal('true'), z.literal('false')])
.optional()
.transform((value) => (value === undefined ? undefined : value === 'true')),
/**
* Overrides the global `layout` configuration for the diagram.
*/
layout: z.union([z.literal('dagre'), z.literal('elk'), z.literal('tala')]).optional(),
/**
* Overrides the global `pad` configuration for the diagram.
*/
pad: z.coerce.number().optional(),
/**
* Overrides the global `sketch` configuration for the diagram.
*/
sketch: z
.union([z.literal('true'), z.literal('false')])
.optional()
.transform((value) => (value === 'false' ? false : value)),
/**
* Defines the target board to render when using composition.
* Use `root` to target the root board.
*
* @see https://d2lang.com/tour/composition
*/
target: z
.string()
.optional()
.transform((value) => (value === 'root' ? '' : value)),
/**
* The title of the diagram that will be used as the `alt` attribute of the generated image.
*
* @default 'Diagram'
*/
title: z.string().default('Diagram'),
/**
* The default theme to use for the diagram.
*
* @see https://d2lang.com/tour/themes
*/
theme: z.string().optional(),
/**
* The width (in pixels) of the diagram.
*/
width: z.coerce.number().optional(),
})
.default({})
const attributeRegex =
/(?<key>[^\s"'=]+)=(?:(?<noQuoteValue>\w+)|'(?<singleQuoteValue>[^']+)'|"(?<doubleQuoteValue>[^"]+))|(?<truthyKey>\w+)/g
export function getAttributes(attributesStr: string | null | undefined) {
return AttributesSchema.parse(parseAttributes(attributesStr))
}
function parseAttributes(attributesStr: string | null | undefined) {
if (!attributesStr) {
return {}
}
const matches = attributesStr.matchAll(attributeRegex)
const attributes: Record<string, string> = {}
for (const match of matches) {
const { key, noQuoteValue, singleQuoteValue, doubleQuoteValue, truthyKey } = match.groups ?? {}
const attributeKey = truthyKey ?? key
const attributeValue = truthyKey ? 'true' : (noQuoteValue ?? singleQuoteValue ?? doubleQuoteValue)
if (attributeKey && attributeValue) {
attributes[attributeKey] = attributeValue
}
}
return attributes
}
export type DiagramAttributes = z.infer<typeof AttributesSchema>