UNPKG

remark-docx

Version:

remark plugin to compile markdown to docx (Microsoft Word, Office Open XML).

1 lines 30.6 kB
{"version":3,"file":"index.cjs","names":[],"sources":["../src/mdast-util-to-docx.ts","../src/plugin.ts"],"sourcesContent":["import {\n Packer,\n Document,\n Paragraph,\n Table,\n TableRow,\n TableCell,\n TextRun,\n ExternalHyperlink,\n HeadingLevel,\n LevelFormat,\n AlignmentType,\n type ILevelsOptions,\n FootnoteReferenceRun,\n type IPropertiesOptions,\n sectionPageSizeDefaults,\n sectionMarginDefaults,\n type IRunOptions,\n type IParagraphOptions,\n PageBreak,\n type ISectionPropertiesOptions,\n type IIndentAttributesProperties,\n type IStylesOptions,\n type ITableOptions,\n ImageRun,\n type FileChild,\n} from \"docx\";\nimport type * as mdast from \"mdast\";\nimport { warnOnce } from \"./utils\";\nimport { definitions } from \"mdast-util-definitions\";\nimport deepmerge from \"deepmerge\";\nimport type {\n Context,\n DocxContent,\n DocxImageData,\n FootnoteRegistry,\n ListContext,\n NodeBuilder,\n NodeBuilders,\n RemarkDocxPlugin,\n ThematicBreakType,\n Writeable,\n} from \"./types\";\n\nconst BULLET_LIST_REF = \"bullet\";\nconst ORDERED_LIST_REF = \"ordered\";\nconst COMPLETE_TASK_LIST_REF = \"task-complete\";\nconst INCOMPLETE_TASK_LIST_REF = \"task-incomplete\";\nconst HYPERLINK_STYLE_ID = \"Hyperlink\";\n\nconst calcIndent = (i: number): IIndentAttributesProperties => {\n const INDENT_UNIT = 10 * 40;\n return { hanging: INDENT_UNIT, left: INDENT_UNIT * (i + 1) };\n};\n\nconst createFootnoteRegistry = (): FootnoteRegistry => {\n const idToInternalId = new Map<string, number>();\n const defs = new Map<number, Paragraph[]>();\n\n return {\n id: (id) => {\n let internalId = idToInternalId.get(id);\n if (internalId == null) {\n idToInternalId.set(id, (internalId = idToInternalId.size + 1));\n }\n return internalId;\n },\n set: (id, def) => {\n defs.set(id, def);\n },\n toConfig: () => {\n return defs.entries().reduce(\n (acc, [key, def]) => {\n acc[key] = { children: def };\n return acc;\n },\n {} as {\n [key: string]: { children: Paragraph[] };\n },\n );\n },\n };\n};\n\ntype ListFormat = {\n format: keyof typeof LevelFormat;\n text: string;\n};\n\ntype OrderedListRegistry = {\n createId: () => string;\n getIds: () => string[];\n};\nconst createOrderedListRegistry = (): OrderedListRegistry => {\n let counter = 1;\n\n const ids: string[] = [];\n\n return {\n createId: () => {\n const id = `${ORDERED_LIST_REF}-${counter++}`;\n ids.push(id);\n return id;\n },\n getIds: () => {\n return ids;\n },\n };\n};\n\nconst composeBuilders = (\n pluginsBuilders: readonly NodeBuilders[],\n defaultBuilders: NodeBuilders,\n): NodeBuilders => {\n return pluginsBuilders.reduceRight<NodeBuilders>((acc, p) => {\n type Key = keyof typeof p;\n for (const [k, cur] of Object.entries(p)) {\n const prev = acc[k as Key];\n acc[k as Key] = (\n prev\n ? (n, c) => {\n const r = cur(n as any, c);\n if (r) {\n return r;\n }\n return prev(n as any, c);\n }\n : cur\n ) as NodeBuilder<any>;\n }\n return acc;\n }, defaultBuilders);\n};\n\nconst buildLevels = (formats: readonly ListFormat[]): ILevelsOptions[] => {\n return formats.map(({ format, text }, i) => {\n return {\n level: i,\n format: LevelFormat[format],\n text: text,\n alignment: AlignmentType.LEFT,\n style: {\n paragraph: {\n indent: calcIndent(i),\n },\n },\n };\n });\n};\n\nconst docxParagraph = (\n options: Writeable<IParagraphOptions>,\n ctx: Context,\n): Paragraph => {\n if (ctx.quote != null) {\n options.indent = calcIndent(ctx.quote + 1);\n }\n\n if (ctx.list) {\n const { level, meta } = ctx.list;\n if (meta.type === \"task\") {\n options.numbering = {\n reference: meta.checked\n ? COMPLETE_TASK_LIST_REF\n : INCOMPLETE_TASK_LIST_REF,\n level,\n };\n } else if (meta.type === \"ordered\") {\n options.numbering = {\n reference: meta.reference,\n level,\n };\n } else {\n options.numbering = {\n reference: BULLET_LIST_REF,\n level,\n };\n }\n }\n\n if (ctx.rtl) {\n options.bidirectional = true;\n }\n\n return new Paragraph(options);\n};\n\nexport interface DocxOptions extends Pick<\n IPropertiesOptions,\n | \"title\"\n | \"subject\"\n | \"creator\"\n | \"keywords\"\n | \"description\"\n | \"styles\"\n | \"background\"\n> {\n /**\n * Page size defined in twip (1 twip == 1/1440 inch).\n * @default A4 ({@link sectionPageSizeDefaults})\n */\n size?: { width?: number; height?: number };\n /**\n * Page margin defined in twip (1 twip == 1/1440 inch).\n * @default 1 inch ({@link sectionMarginDefaults})\n */\n margin?: { top?: number; left?: number; bottom?: number; right?: number };\n /**\n * Page orientation.\n * @default \"portrait\"\n */\n orientation?: \"portrait\" | \"landscape\";\n /**\n * Number of page columns.\n * @default 1\n */\n columns?: number;\n /**\n * Spacing after Paragraphs in twip (1 twip == 1/1440 inch).\n * @default 0\n */\n spacing?: number;\n /**\n * Direction of texts.\n * @default \"ltr\"\n */\n direction?: \"ltr\" | \"rtl\" | \"vertical\";\n /**\n * An option to override the text format of ordered list.\n * See https://docx.js.org/#/usage/numbering?id=level-options for more details.\n */\n orderedListFormat?: ListFormat[];\n /**\n * An option to select how thematicBreak works.\n *\n * - \"page\": Page Break\n * - \"section\": Section Break\n * - \"line\": Horizontal line\n * @default \"page\"\n */\n thematicBreak?: ThematicBreakType;\n /**\n * Plugins to customize how mdast nodes are compiled.\n */\n plugins?: RemarkDocxPlugin[];\n}\n\nexport const mdastToDocx = async (\n node: mdast.Root,\n {\n plugins = [],\n title,\n subject,\n creator,\n keywords,\n description,\n styles,\n size,\n margin,\n orientation,\n columns,\n spacing,\n direction,\n background,\n thematicBreak = \"page\",\n orderedListFormat,\n }: DocxOptions = {},\n): Promise<ArrayBuffer> => {\n const definition = definitions(node);\n\n const ordered = createOrderedListRegistry();\n const footnote = createFootnoteRegistry();\n\n const images = new Map<string, DocxImageData>();\n const pluginCtx = { root: node, images, definition };\n\n const builders = composeBuilders(\n await Promise.all(plugins.map((p) => p(pluginCtx))),\n {\n paragraph: buildParagraph,\n heading: buildHeading,\n thematicBreak: buildThematicBreak,\n blockquote: buildBlockquote,\n list: buildList,\n listItem: buildListItem,\n table: buildTable,\n tableRow: noop,\n tableCell: noop,\n html: fallbackText,\n code: fallbackCode,\n definition: noop,\n footnoteDefinition: buildFootnoteDefinition,\n text: buildText,\n emphasis: buildEmphasis,\n strong: buildStrong,\n delete: buildDelete,\n inlineCode: buildInlineCode,\n break: buildBreak,\n link: buildLink,\n linkReference: buildLinkReference,\n image: buildImage,\n imageReference: buildImageReference,\n footnoteReference: buildFootnoteReference,\n math: fallbackText,\n inlineMath: fallbackText,\n },\n );\n\n const renderNode = (\n node: mdast.RootContent,\n c: Context,\n ): DocxContent[] | null => {\n const builder = builders[node.type];\n if (!builder) {\n warnOnce(`${node.type} node is not supported without plugins.`);\n return null;\n }\n const r = builder(node as any, c);\n if (r) {\n if (Array.isArray(r)) {\n return r;\n } else {\n return [r];\n }\n }\n return null;\n };\n\n let { WIDTH: pageWidth, HEIGHT: pageHeight } = sectionPageSizeDefaults;\n if (size) {\n if (size.width != null) {\n pageWidth = size.width;\n }\n if (size.height != null) {\n pageHeight = size.height;\n }\n }\n let {\n TOP: marginTop,\n LEFT: marginLeft,\n BOTTOM: marginBottom,\n RIGHT: marginRight,\n } = sectionMarginDefaults;\n if (margin) {\n if (margin.top != null) {\n marginTop = margin.top;\n }\n if (margin.left != null) {\n marginLeft = margin.left;\n }\n if (margin.bottom != null) {\n marginBottom = margin.bottom;\n }\n if (margin.right != null) {\n marginRight = margin.right;\n }\n }\n\n const ctx: Context = {\n render(nodes, c) {\n const results: DocxContent[] = [];\n for (const node of nodes) {\n const r = renderNode(node, c ?? this);\n if (r) {\n results.push(...r);\n }\n }\n return results;\n },\n width: pageWidth - marginLeft - marginRight,\n style: {},\n thematicBreak,\n rtl: direction === \"rtl\",\n definition: definition,\n images,\n footnote,\n orderedId: ordered.createId,\n };\n\n const sections: DocxContent[][] = [[]];\n for (const n of node.children) {\n const r = renderNode(n, ctx);\n if (r) {\n if (!r.length) {\n // thematicBreak\n sections.push([]);\n } else {\n const lastSection = sections[sections.length - 1]!;\n lastSection.push(...r);\n }\n }\n }\n\n const orderedLevels = buildLevels(\n orderedListFormat ?? [\n { text: \"%1.\", format: \"DECIMAL\" },\n { text: \"%2.\", format: \"DECIMAL\" },\n { text: \"%3.\", format: \"DECIMAL\" },\n { text: \"%4.\", format: \"DECIMAL\" },\n { text: \"%5.\", format: \"DECIMAL\" },\n { text: \"%6.\", format: \"DECIMAL\" },\n ],\n );\n\n const sectionProperties: ISectionPropertiesOptions = {\n column: columns ? { count: columns } : undefined,\n page: {\n textDirection: direction === \"vertical\" ? \"tbRl\" : undefined,\n size: { width: pageWidth, height: pageHeight, orientation },\n margin: {\n top: marginTop,\n left: marginLeft,\n bottom: marginBottom,\n right: marginRight,\n },\n },\n };\n\n const doc = new Document({\n title,\n subject,\n creator,\n keywords,\n description,\n styles: deepmerge<IStylesOptions>(\n {\n default: {\n document: {\n paragraph: {\n spacing: spacing ? { after: spacing } : undefined,\n },\n },\n },\n },\n styles || {},\n ),\n background,\n sections: sections\n .filter((s) => s.length)\n .map((s) => ({\n properties: sectionProperties,\n children: s as FileChild[],\n })),\n footnotes: footnote.toConfig(),\n numbering: {\n config: [\n {\n reference: BULLET_LIST_REF,\n levels: buildLevels([\n { text: \"\\u25CF\", format: \"BULLET\" },\n { text: \"\\u25CB\", format: \"BULLET\" },\n { text: \"\\u25A0\", format: \"BULLET\" },\n { text: \"\\u25CF\", format: \"BULLET\" },\n { text: \"\\u25CB\", format: \"BULLET\" },\n { text: \"\\u25A0\", format: \"BULLET\" },\n ]),\n },\n ...ordered.getIds().map((ref) => ({\n reference: ref,\n levels: orderedLevels,\n })),\n {\n reference: COMPLETE_TASK_LIST_REF,\n levels: buildLevels([\n { text: \"\\u2611\", format: \"BULLET\" },\n { text: \"\\u2611\", format: \"BULLET\" },\n { text: \"\\u2611\", format: \"BULLET\" },\n { text: \"\\u2611\", format: \"BULLET\" },\n { text: \"\\u2611\", format: \"BULLET\" },\n { text: \"\\u2611\", format: \"BULLET\" },\n ]),\n },\n {\n reference: INCOMPLETE_TASK_LIST_REF,\n levels: buildLevels([\n { text: \"\\u2610\", format: \"BULLET\" },\n { text: \"\\u2610\", format: \"BULLET\" },\n { text: \"\\u2610\", format: \"BULLET\" },\n { text: \"\\u2610\", format: \"BULLET\" },\n { text: \"\\u2610\", format: \"BULLET\" },\n { text: \"\\u2610\", format: \"BULLET\" },\n ]),\n },\n ],\n },\n });\n\n // HACK: docx.js has no option to remove default numbering definitions from .docx. So do it here for now.\n // https://github.com/dolanmiu/docx/blob/master/src/file/numbering/numbering.ts\n const defaultBulletKey = \"default-bullet-numbering\";\n const _numbering = (doc as any).numbering;\n _numbering.abstractNumberingMap.delete(defaultBulletKey);\n _numbering.concreteNumberingMap.delete(defaultBulletKey);\n\n return Packer.toArrayBuffer(doc);\n};\n\nconst buildParagraph: NodeBuilder<\"paragraph\"> = ({ children }, ctx) => {\n return docxParagraph(\n {\n children: ctx.render(children),\n },\n ctx,\n );\n};\n\nconst buildHeading: NodeBuilder<\"heading\"> = ({ children, depth }, ctx) => {\n let level: keyof typeof HeadingLevel;\n switch (depth) {\n case 1:\n level = \"TITLE\";\n break;\n case 2:\n level = \"HEADING_1\";\n break;\n case 3:\n level = \"HEADING_2\";\n break;\n case 4:\n level = \"HEADING_3\";\n break;\n case 5:\n level = \"HEADING_4\";\n break;\n case 6:\n level = \"HEADING_5\";\n break;\n }\n return docxParagraph(\n {\n heading: HeadingLevel[level],\n outlineLevel: depth - 1,\n children: ctx.render(children),\n },\n ctx,\n );\n};\n\nconst buildThematicBreak: NodeBuilder<\"thematicBreak\"> = (_, ctx) => {\n switch (ctx.thematicBreak) {\n case \"page\": {\n return new Paragraph({ children: [new PageBreak()] });\n }\n case \"section\": {\n // Returning empty array at toplevel means section insertion.\n return [];\n }\n case \"line\": {\n return new Paragraph({ thematicBreak: true });\n }\n }\n};\n\nconst buildBlockquote: NodeBuilder<\"blockquote\"> = ({ children }, ctx) => {\n return ctx.render(children, {\n ...ctx,\n quote: ctx.quote == null ? 0 : ctx.quote + 1,\n });\n};\n\nconst buildList: NodeBuilder<\"list\"> = ({ children, ordered }, ctx) => {\n const parentList = ctx.list;\n\n let meta: ListContext[\"meta\"];\n if (ordered) {\n meta = {\n type: \"ordered\",\n reference:\n parentList && parentList.meta.type === \"ordered\"\n ? parentList.meta.reference\n : ctx.orderedId(),\n };\n } else {\n meta = { type: \"bullet\" };\n }\n\n return ctx.render(children, {\n ...ctx,\n list: {\n level: !parentList ? 0 : parentList.level + 1,\n meta,\n },\n });\n};\n\nconst buildListItem: NodeBuilder<\"listItem\"> = ({ children, checked }, ctx) => {\n let list = ctx.list;\n if (list) {\n // listItem must be the child of list\n if (checked != null) {\n list = {\n level: list.level,\n meta: {\n type: \"task\",\n checked,\n },\n };\n }\n }\n return ctx.render(children, {\n ...ctx,\n list,\n });\n};\n\nconst buildTable: NodeBuilder<\"table\"> = ({ children, align }, ctx) => {\n const textAlign = align?.map((a): keyof typeof AlignmentType => {\n switch (a) {\n case \"left\":\n return \"LEFT\";\n case \"right\":\n return \"RIGHT\";\n case \"center\":\n return \"CENTER\";\n default:\n return \"LEFT\";\n }\n });\n\n const columnLength = children[0]!.children.length;\n const columnWidth = ctx.width / columnLength;\n\n const options: Writeable<ITableOptions> = {\n columnWidths: Array.from({ length: columnLength }).map(() => columnWidth),\n rows: children.map((r) => {\n return new TableRow({\n children: r.children.map((c, i) => {\n return new TableCell({\n width: { size: columnWidth, type: \"dxa\" },\n children: [\n new Paragraph({\n alignment: AlignmentType[textAlign?.[i] ?? \"LEFT\"],\n children: ctx.render(c.children, {\n ...ctx,\n // https://github.com/dolanmiu/docx/blob/master/demo/22-right-to-left-text.ts\n rtl: undefined,\n }),\n }),\n ],\n });\n }),\n });\n }),\n };\n\n if (ctx.rtl) {\n options.visuallyRightToLeft = true;\n }\n\n return new Table(options);\n};\n\nconst buildText: NodeBuilder<\"text\"> = ({ value }, { style, rtl }) => {\n const options: Writeable<IRunOptions> = {\n text: value,\n bold: style.bold,\n italics: style.italic,\n strike: style.strike,\n };\n if (style.inlineCode) {\n options.highlight = \"lightGray\";\n }\n if (style.link) {\n // https://docx.js.org/#/usage/hyperlinks?id=styling-hyperlinks\n options.style = HYPERLINK_STYLE_ID;\n }\n if (rtl) {\n options.rightToLeft = true;\n }\n\n return new TextRun(options);\n};\n\nconst buildEmphasis: NodeBuilder<\"emphasis\"> = ({ children }, ctx) => {\n return ctx.render(children, {\n ...ctx,\n style: { ...ctx.style, italic: true },\n });\n};\n\nconst buildStrong: NodeBuilder<\"strong\"> = ({ children }, ctx) => {\n return ctx.render(children, {\n ...ctx,\n style: { ...ctx.style, bold: true },\n });\n};\n\nconst buildDelete: NodeBuilder<\"delete\"> = ({ children }, ctx) => {\n return ctx.render(children, {\n ...ctx,\n style: { ...ctx.style, strike: true },\n });\n};\n\nconst buildInlineCode: NodeBuilder<\"inlineCode\"> = ({ value }, ctx) => {\n return buildText(\n { type: \"text\", value },\n {\n ...ctx,\n style: { ...ctx.style, inlineCode: true },\n },\n );\n};\n\nconst buildBreak: NodeBuilder<\"break\"> = () => {\n return new TextRun({ text: \"\", break: 1 });\n};\n\nconst buildLink: NodeBuilder<\"link\"> = ({ children, url }, ctx) => {\n if (url.startsWith(\"#\")) {\n // TODO support anchor link\n return ctx.render(children);\n }\n return new ExternalHyperlink({\n link: url,\n children: ctx.render(children, {\n ...ctx,\n style: { ...ctx.style, link: true },\n }),\n });\n};\n\nconst buildLinkReference: NodeBuilder<\"linkReference\"> = (\n { children, identifier },\n ctx,\n) => {\n const def = ctx.definition(identifier);\n if (def == null) {\n return ctx.render(children);\n }\n return buildLink({ type: \"link\", children, url: def.url }, ctx);\n};\n\nconst buildImage: NodeBuilder<\"image\"> = (node, ctx) => {\n const image = ctx.images.get(node.url);\n if (!image) {\n return null;\n }\n\n let { width, height } = image;\n const pageWidthInch = ctx.width / 1440;\n const DPI = 96;\n const pageWidthPx = pageWidthInch * DPI;\n if (width > pageWidthPx) {\n const scale = pageWidthPx / width;\n width *= scale;\n height *= scale;\n }\n\n const altText =\n node.alt || node.title\n ? {\n name: \"\",\n description: node.alt ?? undefined,\n title: node.title ?? undefined,\n }\n : undefined;\n\n if (image.type === \"svg\") {\n const { type, data, fallback } = image;\n return new ImageRun({\n type: type,\n data: data,\n transformation: {\n width,\n height,\n },\n // https://github.com/dolanmiu/docx/issues/1162#issuecomment-3228368003\n fallback: { type: \"png\", data: fallback },\n altText,\n });\n }\n\n const { type, data } = image;\n return new ImageRun({\n type: type,\n data: data,\n transformation: {\n width,\n height,\n },\n altText,\n });\n};\n\nconst buildImageReference: NodeBuilder<\"imageReference\"> = (node, ctx) => {\n const def = ctx.definition(node.identifier);\n if (def == null) {\n return null;\n }\n return buildImage(\n { type: \"image\", url: def.url, alt: node.alt, title: def.title },\n ctx,\n );\n};\n\nconst buildFootnoteDefinition: NodeBuilder<\"footnoteDefinition\"> = (\n { children, identifier },\n ctx,\n) => {\n const contents = ctx.render(children).filter((c) => c instanceof Paragraph);\n ctx.footnote.set(ctx.footnote.id(identifier), contents);\n return null;\n};\n\nconst buildFootnoteReference: NodeBuilder<\"footnoteReference\"> = (\n { identifier },\n ctx,\n) => {\n return new FootnoteReferenceRun(ctx.footnote.id(identifier));\n};\n\nconst noop = () => {\n return null;\n};\n\nconst fallbackText = (node: { type: string; value: string }, ctx: Context) => {\n warnOnce(\n `${node.type} node is not supported without plugins, falling back to text.`,\n );\n return buildText({ type: \"text\", value: node.value }, ctx);\n};\n\nconst fallbackCode = (node: { type: string; value: string }, ctx: Context) => {\n warnOnce(\n `${node.type} node is not supported without plugins, falling back to text.`,\n );\n const children = node.value.split(/\\r?\\n/).map(\n (line, index) =>\n new TextRun({\n text: line,\n break: index === 0 ? undefined : 1,\n }),\n );\n return docxParagraph(\n {\n children,\n },\n ctx,\n );\n};\n","import type { Plugin } from \"unified\";\nimport type { Root } from \"mdast\";\nimport { mdastToDocx, type DocxOptions } from \"./mdast-util-to-docx\";\n\nexport type { DocxOptions };\n\ndeclare module \"unified\" {\n interface CompileResultMap {\n docx: Promise<ArrayBuffer>;\n }\n}\n\nconst plugin: Plugin<[DocxOptions?], Root, Promise<ArrayBuffer>> = function (\n opts,\n) {\n this.compiler = (node) => {\n return mdastToDocx(node as Root, opts);\n };\n};\nexport default plugin;\n"],"mappings":"sKA4CA,IAAM,EAAkB,SAClB,EAAmB,UACnB,EAAyB,gBACzB,EAA2B,kBAC3B,EAAqB,YAErB,EAAc,IAEX,CAAE,QAAS,IAAa,KAAM,KAAe,EAAI,EAAG,GAGvD,OAAiD,CACrD,IAAM,EAAiB,IAAI,IACrB,EAAO,IAAI,IAEjB,MAAO,CACL,GAAK,GAAO,CACV,IAAI,EAAa,EAAe,IAAI,CAAE,EAItC,OAHI,GACF,EAAe,IAAI,EAAK,EAAa,EAAe,KAAO,CAAE,EAExD,CACT,EACA,KAAM,EAAI,IAAQ,CAChB,EAAK,IAAI,EAAI,CAAG,CAClB,EACA,aACS,EAAK,QAAQ,EAAE,QACnB,EAAK,CAAC,EAAK,MACV,EAAI,GAAO,CAAE,SAAU,CAAI,EACpB,GAET,CAAC,CAGH,CAEJ,CACF,EAWM,OAAuD,CAC3D,IAAI,EAAU,EAER,EAAgB,CAAC,EAEvB,MAAO,CACL,aAAgB,CACd,IAAM,EAAK,GAAG,EAAiB,GAAG,MAElC,OADA,EAAI,KAAK,CAAE,EACJ,CACT,EACA,WACS,CAEX,CACF,EAEM,GACJ,EACA,IAEO,EAAgB,aAA2B,EAAK,IAAM,CAE3D,IAAK,GAAM,CAAC,EAAG,KAAQ,OAAO,QAAQ,CAAC,EAAG,CACxC,IAAM,EAAO,EAAI,GACjB,EAAI,GACF,GACK,EAAG,IACM,EAAI,EAAU,CACpB,GAGG,EAAK,EAAU,CAAC,EAEvB,CAER,CACA,OAAO,CACT,EAAG,CAAe,EAGd,EAAe,GACZ,EAAQ,KAAK,CAAE,SAAQ,QAAQ,KAC7B,CACL,MAAO,EACP,OAAQ,EAAA,YAAY,GACd,OACN,UAAW,EAAA,cAAc,KACzB,MAAO,CACL,UAAW,CACT,OAAQ,EAAW,CAAC,CACtB,CACF,CACF,EACD,EAGG,GACJ,EACA,IACc,CAKd,GAJI,EAAI,OAAS,OACf,EAAQ,OAAS,EAAW,EAAI,MAAQ,CAAC,GAGvC,EAAI,KAAM,CACZ,GAAM,CAAE,QAAO,QAAS,EAAI,KACxB,EAAK,OAAS,OAChB,EAAQ,UAAY,CAClB,UAAW,EAAK,QACZ,EACA,EACJ,OACF,EACS,EAAK,OAAS,UACvB,EAAQ,UAAY,CAClB,UAAW,EAAK,UAChB,OACF,EAEA,EAAQ,UAAY,CAClB,UAAW,EACX,OACF,CAEJ,CAMA,OAJI,EAAI,MACN,EAAQ,cAAgB,IAGnB,IAAI,EAAA,UAAU,CAAO,CAC9B,EA8Da,EAAc,MACzB,EACA,CACE,UAAU,CAAC,EACX,QACA,UACA,UACA,WACA,cACA,UACA,OACA,SACA,cACA,UACA,UACA,YACA,aACA,gBAAgB,OAChB,qBACe,CAAC,IACO,CACzB,IAAM,GAAA,EAAA,EAAA,aAAyB,CAAI,EAE7B,EAAU,GAA0B,EACpC,EAAW,GAAuB,EAElC,EAAS,IAAI,IACb,GAAY,CAAE,KAAM,EAAM,SAAQ,YAAW,EAE7C,GAAW,EACf,MAAM,QAAQ,IAAI,EAAQ,IAAK,GAAM,EAAE,EAAS,CAAC,CAAC,EAClD,CACE,UAAW,EACX,QAAS,GACT,cAAe,GACf,WAAY,GACZ,KAAM,GACN,SAAU,GACV,MAAO,EACP,SAAU,EACV,UAAW,EACX,KAAM,EACN,KAAM,GACN,WAAY,EACZ,mBAAoB,EACpB,KAAM,EACN,SAAU,EACV,OAAQ,EACR,OAAQ,GACR,WAAY,GACZ,MAAO,EACP,KAAM,EACN,cAAe,EACf,MAAO,EACP,eAAgB,EAChB,kBAAmB,EACnB,KAAM,EACN,WAAY,CACd,CACF,EAEM,GACJ,EACA,IACyB,CACzB,IAAM,EAAU,GAAS,EAAK,MAC9B,GAAI,CAAC,EAEH,OADA,EAAA,EAAS,GAAG,EAAK,KAAK,wCAAwC,EACvD,KAET,IAAM,EAAI,EAAQ,EAAa,CAAC,EAQhC,OAPI,EACE,MAAM,QAAQ,CAAC,EACV,EAEA,CAAC,CAAC,EAGN,IACT,EAEI,CAAE,MAAO,EAAW,OAAQ,GAAe,EAAA,wBAC3C,IACE,EAAK,OAAS,OAChB,EAAY,EAAK,OAEf,EAAK,QAAU,OACjB,EAAa,EAAK,SAGtB,GAAI,CACF,IAAK,EACL,KAAM,EACN,OAAQ,EACR,MAAO,GACL,EAAA,sBACA,IACE,EAAO,KAAO,OAChB,EAAY,EAAO,KAEjB,EAAO,MAAQ,OACjB,EAAa,EAAO,MAElB,EAAO,QAAU,OACnB,EAAe,EAAO,QAEpB,EAAO,OAAS,OAClB,EAAc,EAAO,QAIzB,IAAM,GAAe,CACnB,OAAO,EAAO,EAAG,CACf,IAAM,EAAyB,CAAC,EAChC,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAI,EAAW,EAAM,GAAK,IAAI,EAChC,GACF,EAAQ,KAAK,GAAG,CAAC,CAErB,CACA,OAAO,CACT,EACA,MAAO,EAAY,EAAa,EAChC,MAAO,CAAC,EACR,gBACA,IAAK,IAAc,MACP,aACZ,SACA,WACA,UAAW,EAAQ,QACrB,EAEM,EAA4B,CAAC,CAAC,CAAC,EACrC,IAAK,IAAM,KAAK,EAAK,SAAU,CAC7B,IAAM,EAAI,EAAW,EAAG,EAAG,EACvB,IACG,EAAE,OAKL,EAD6B,EAAS,OAAS,GACnC,KAAK,GAAG,CAAC,EAHrB,EAAS,KAAK,CAAC,CAAC,EAMtB,CAEA,IAAM,GAAgB,EACpB,GAAqB,CACnB,CAAE,KAAM,MAAO,OAAQ,SAAU,EACjC,CAAE,KAAM,MAAO,OAAQ,SAAU,EACjC,CAAE,KAAM,MAAO,OAAQ,SAAU,EACjC,CAAE,KAAM,MAAO,OAAQ,SAAU,EACjC,CAAE,KAAM,MAAO,OAAQ,SAAU,EACjC,CAAE,KAAM,MAAO,OAAQ,SAAU,CACnC,CACF,EAEM,GAA+C,CACnD,OAAQ,EAAU,CAAE,MAAO,CAAQ,EAAI,IAAA,GACvC,KAAM,CACJ,cAAe,IAAc,WAAa,OAAS,IAAA,GACnD,KAAM,CAAE,MAAO,EAAW,OAAQ,EAAY,aAAY,EAC1D,OAAQ,CACN,IAAK,EACL,KAAM,EACN,OAAQ,EACR,MAAO,CACT,CACF,CACF,EAEM,EAAM,IAAI,EAAA,SAAS,CACvB,QACA,UACA,UACA,WACA,cACA,QAAA,EAAA,EAAA,SACE,CACE,QAAS,CACP,SAAU,CACR,UAAW,CACT,QAAS,EAAU,CAAE,MAAO,CAAQ,EAAI,IAAA,EAC1C,CACF,CACF,CACF,EACA,IAAU,CAAC,CACb,EACA,aACA,SAAU,EACP,OAAQ,GAAM,EAAE,MAAM,EACtB,IAAK,IAAO,CACX,WAAY,GACZ,SAAU,CACZ,EAAE,EACJ,UAAW,EAAS,SAAS,EAC7B,UAAW,CACT,OAAQ,CACN,CACE,UAAW,EACX,OAAQ,EAAY,CAClB,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,CACrC,CAAC,CACH,EACA,GAAG,EAAQ,OAAO,EAAE,IAAK,IAAS,CAChC,UAAW,EACX,OAAQ,EACV,EAAE,EACF,CACE,UAAW,EACX,OAAQ,EAAY,CAClB,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,CACrC,CAAC,CACH,EACA,CACE,UAAW,EACX,OAAQ,EAAY,CAClB,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,EACnC,CAAE,KAAM,IAAU,OAAQ,QAAS,CACrC,CAAC,CACH,CACF,CACF,CACF,CAAC,EAIK,EAAmB,2BACnB,EAAc,EAAY,UAIhC,OAHA,EAAW,qBAAqB,OAAO,CAAgB,EACvD,EAAW,qBAAqB,OAAO,CAAgB,EAEhD,EAAA,OAAO,cAAc,CAAG,CACjC,EAEM,GAA4C,CAAE,YAAY,IACvD,EACL,CACE,SAAU,EAAI,OAAO,CAAQ,CAC/B,EACA,CACF,EAGI,IAAwC,CAAE,WAAU,SAAS,IAAQ,CACzE,IAAI,EACJ,OAAQ,EAAR,CACE,IAAK,GACH,EAAQ,QACR,MACF,IAAK,GACH,EAAQ,YACR,MACF,IAAK,GACH,EAAQ,YACR,MACF,IAAK,GACH,EAAQ,YACR,MACF,IAAK,GACH,EAAQ,YACR,MACF,IAAK,GACH,EAAQ,YACR,KACJ,CACA,OAAO,EACL,CACE,QAAS,EAAA,aAAa,GACtB,aAAc,EAAQ,EACtB,SAAU,EAAI,OAAO,CAAQ,CAC/B,EACA,CACF,CACF,EAEM,IAAoD,EAAG,IAAQ,CACnE,OAAQ,EAAI,cAAZ,CACE,IAAK,OACH,OAAO,IAAI,EAAA,UAAU,CAAE,SAAU,CAAC,IAAI,EAAA,SAAW,CAAE,CAAC,EAEtD,IAAK,UAEH,MAAO,CAAC,EAEV,IAAK,OACH,OAAO,IAAI,EAAA,UAAU,CAAE,cAAe,EAAK,CAAC,CAEhD,CACF,EAEM,IAA8C,CAAE,YAAY,IACzD,EAAI,OAAO,EAAU,CAC1B,GAAG,EACH,MAAO,EAAI,OAAS,KAAO,EAAI,EAAI,MAAQ,CAC7C,CAAC,EAGG,IAAkC,CAAE,WAAU,WAAW,IAAQ,CACrE,IAAM,EAAa,EAAI,KAEnB,EAaJ,MAZA,CASE,EATE,EACK,CACL,KAAM,UACN,UACE,GAAc,EAAW,KAAK,OAAS,UACnC,EAAW,KAAK,UAChB,EAAI,UAAU,CACtB,EAEO,CAAE,KAAM,QAAS,EAGnB,EAAI,OAAO,EAAU,CAC1B,GAAG,EACH,KAAM,CACJ,MAAQ,EAAiB,EAAW,MAAQ,EAAvB,EACrB,MACF,CACF,CAAC,CACH,EAEM,IAA0C,CAAE,WAAU,WAAW,IAAQ,CAC7E,IAAI,EAAO,EAAI,KAaf,OAZI,GAEE,GAAW,OACb,EAAO,CACL,MAAO,EAAK,MACZ,KAAM,CACJ,KAAM,OACN,SACF,CACF,GAGG,EAAI,OAAO,EAAU,CAC1B,GAAG,EACH,MACF,CAAC,CACH,EAEM,GAAoC,CAAE,WAAU,SAAS,IAAQ,CACrE,IAAM,EAAY,GAAO,IAAK,GAAkC,CAC9D,OAAQ,EAAR,CACE,IAAK,OACH,MAAO,OACT,IAAK,QACH,MAAO,QACT,IAAK,SACH,MAAO,SACT,QACE,MAAO,MACX,CACF,CAAC,EAEK,EAAe,EAAS,GAAI,SAAS,OACrC,EAAc,EAAI,MAAQ,EAE1B,EAAoC,CACxC,aAAc,MAAM,KAAK,CAAE,OAAQ,CAAa,CAAC,EAAE,QAAU,CAAW,EACxE,KAAM,EAAS,IAAK,GACX,IAAI,EAAA,SAAS,CAClB,SAAU,EAAE,SAAS,KAAK,EAAG,IACpB,IAAI,EAAA,UAAU,CACnB,MAAO,CAAE,KAAM,EAAa,KAAM,KAAM,EACxC,SAAU,CACR,IAAI,EAAA,UAAU,CACZ,UAAW,EAAA,cAAc,IAAY,IAAM,QAC3C,SAAU,EAAI,OAAO,EAAE,SAAU,CAC/B,GAAG,EAEH,IAAK,IAAA,EACP,CAAC,CACH,CAAC,CACH,CACF,CAAC,CACF,CACH,CAAC,CACF,CACH,EAMA,OAJI,EAAI,MACN,EAAQ,oBAAsB,IAGzB,IAAI,EAAA,MAAM,CAAO,CAC1B,EAEM,GAAkC,CAAE,SAAS,CAAE,QAAO,SAAU,CACpE,IAAM,EAAkC,CACtC,KAAM,EACN,KAAM,EAAM,KACZ,QAAS,EAAM,OACf,OAAQ,EAAM,MAChB,EAYA,OAXI,EAAM,aACR,EAAQ,UAAY,aAElB,EAAM,OAER,EAAQ,MAAQ,GAEd,IACF,EAAQ,YAAc,IAGjB,IAAI,EAAA,QAAQ,CAAO,CAC5B,EAEM,GAA0C,CAAE,YAAY,IACrD,EAAI,OAAO,EAAU,CAC1B,GAAG,EACH,MAAO,CAAE,GAAG,EAAI,MAAO,OAAQ,EAAK,CACtC,CAAC,EAGG,GAAsC,CAAE,YAAY,IACjD,EAAI,OAAO,EAAU,CAC1B,GAAG,EACH,MAAO,CAAE,GAAG,EAAI,MAAO,KAAM,EAAK,CACpC,CAAC,EAGG,IAAsC,CAAE,YAAY,IACjD,EAAI,OAAO,EAAU,CAC1B,GAAG,EACH,MAAO,CAAE,GAAG,EAAI,MAAO,OAAQ,EAAK,CACtC,CAAC,EAGG,IAA8C,CAAE,SAAS,IACtD,EACL,CAAE,KAAM,OAAQ,OAAM,EACtB,CACE,GAAG,EACH,MAAO,CAAE,GAAG,EAAI,MAAO,WAAY,EAAK,CAC1C,CACF,EAGI,MACG,IAAI,EAAA,QAAQ,CAAE,KAAM,GAAI,MAAO,CAAE,CAAC,EAGrC,GAAkC,CAAE,WAAU,OAAO,IACrD,EAAI,WAAW,GAAG,EAEb,EAAI,OAAO,CAAQ,EAErB,IAAI,EAAA,kBAAkB,CAC3B,KAAM,EACN,SAAU,EAAI,OAAO,EAAU,CAC7B,GAAG,EACH,MAAO,CAAE,GAAG,EAAI,MAAO,KAAM,EAAK,CACpC,CAAC,CACH,CAAC,EAGG,GACJ,CAAE,WAAU,cACZ,IACG,CACH,IAAM,EAAM,EAAI,WAAW,CAAU,EAIrC,OAHI,GAAO,KACF,EAAI,OAAO,CAAQ,EAErB,EAAU,CAAE,KAAM,OAAQ,WAAU,IAAK,EAAI,GAAI,EAAG,CAAG,CAChE,EAEM,GAAoC,EAAM,IAAQ,CACtD,IAAM,EAAQ,EAAI,OAAO,IAAI,EAAK,GAAG,EACrC,GAAI,CAAC,EACH,OAAO,KAGT,GAAI,CAAE,QAAO,UAAW,EAGlB,EAFgB,EAAI,MAAQ,KAEE,GACpC,GAAI,EAAQ,EAAa,CACvB,IAAM,EAAQ,EAAc,EAC5B,GAAS,EACT,GAAU,CACZ,CAEA,IAAM,EACJ,EAAK,KAAO,EAAK,MACb,CACA,KAAM,GACN,YAAa,EAAK,KAAO,IAAA,GACzB,MAAO,EAAK,OAAS,IAAA,EACvB,EACE,IAAA,GAEN,GAAI,EAAM,OAAS,MAAO,CACxB,GAAM,CAAE,OAAM,OAAM,YAAa,EACjC,OAAO,IAAI,EAAA,SAAS,CACZ,OACA,OACN,eAAgB,CACd,QACA,QACF,EAEA,SAAU,CAAE,KAAM,MAAO,KAAM,CAAS,EACxC,SACF,CAAC,CACH,CAEA,GAAM,CAAE,OAAM,QAAS,EACvB,OAAO,IAAI,EAAA,SAAS,CACZ,OACA,OACN,eAAgB,CACd,QACA,QACF,EACA,SACF,CAAC,CACH,EAEM,GAAsD,EAAM,IAAQ,CACxE,IAAM,EAAM,EAAI,WAAW,EAAK,UAAU,EAI1C,OAHI,GAAO,KACF,KAEF,EACL,CAAE,KAAM,QAAS,IAAK,EAAI,IAAK,IAAK,EAAK,IAAK,MAAO,EAAI,KAAM,EAC/D,CACF,CACF,EAEM,GACJ,CAAE,WAAU,cACZ,IACG,CACH,IAAM,EAAW,EAAI,OAAO,CAAQ,EAAE,OAAQ,GAAM,aAAa,EAAA,SAAS,EAE1E,OADA,EAAI,SAAS,IAAI,EAAI,SAAS,GAAG,CAAU,EAAG,CAAQ,EAC/C,IACT,EAEM,GACJ,CAAE,cACF,IAEO,IAAI,EAAA,qBAAqB,EAAI,SAAS,GAAG,CAAU,CAAC,EAGvD,MACG,KAGH,GAAgB,EAAuC,KAC3D,EAAA,EACE,GAAG,EAAK,KAAK,8DACf,EACO,EAAU,CAAE,KAAM,OAAQ,MAAO,EAAK,KAAM,EAAG,CAAG,GAGrD,IAAgB,EAAuC,KAC3D,EAAA,EACE,GAAG,EAAK,KAAK,8DACf,EAQO,EACL,CACE,SATa,EAAK,MAAM,MAAM,OAAO,EAAE,KACxC,EAAM,IACL,IAAI,EAAA,QAAQ,CACV,KAAM,EACN,MAAO,IAAU,EAAI,IAAA,GAAY,CACnC,CAAC,CAID,CACF,EACA,CACF,GC3zBI,EAA6D,SACjE,EACA,CACA,KAAK,SAAY,GACR,EAAY,EAAc,CAAI,CAEzC"}