@blocknote/core 0.31.1 → 0.32.0-hackdays.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"blocknote.js","sources":["../src/extensions/UniqueID/UniqueID.ts","../src/schema/inlineContent/types.ts","../src/util/table.ts","../src/util/typescript.ts","../src/util/browser.ts","../src/blocks/defaultBlockHelpers.ts","../src/blocks/defaultProps.ts","../src/util/string.ts","../src/schema/blocks/internal.ts","../src/schema/blocks/createSpec.ts","../src/api/getBlockInfoFromPos.ts","../src/api/pmUtil.ts","../src/api/nodeConversions/nodeToBlock.ts","../src/schema/inlineContent/internal.ts","../src/schema/inlineContent/createSpec.ts","../src/schema/styles/internal.ts","../src/schema/styles/createSpec.ts","../src/api/blockManipulation/tables/tables.ts","../src/api/nodeConversions/blockToNode.ts","../src/api/nodeUtil.ts","../src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts","../src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts","../src/api/blockManipulation/commands/updateBlock/updateBlock.ts","../src/api/exporters/html/util/serializeBlocksExternalHTML.ts","../src/api/exporters/html/externalHTMLExporter.ts","../src/api/exporters/html/util/serializeBlocksInternalHTML.ts","../src/api/exporters/html/internalHTMLSerializer.ts","../src/blocks/FileBlockContent/helpers/parse/parseFigureElement.ts","../src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts","../src/blocks/FileBlockContent/helpers/render/createFileNameWithIcon.ts","../src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.ts","../src/blocks/FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.ts","../src/blocks/FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.ts","../src/blocks/AudioBlockContent/parseAudioElement.ts","../src/blocks/AudioBlockContent/AudioBlockContent.ts","../src/blocks/CodeBlockContent/CodeBlockContent.ts","../src/extensions/BackgroundColor/BackgroundColorMark.ts","../src/extensions/TextColor/TextColorMark.ts","../src/blocks/FileBlockContent/helpers/parse/parseEmbedElement.ts","../src/blocks/FileBlockContent/FileBlockContent.ts","../src/blocks/HeadingBlockContent/HeadingBlockContent.ts","../src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts","../src/blocks/ImageBlockContent/parseImageElement.ts","../src/blocks/ImageBlockContent/ImageBlockContent.ts","../src/blocks/ListItemBlockContent/getListItemContent.ts","../src/api/blockManipulation/commands/splitBlock/splitBlock.ts","../src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","../src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","../src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts","../src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","../src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","../src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","../src/blocks/QuoteBlockContent/QuoteBlockContent.ts","../src/blocks/TableBlockContent/TableExtension.ts","../src/blocks/TableBlockContent/TableBlockContent.ts","../src/blocks/VideoBlockContent/parseVideoElement.ts","../src/blocks/VideoBlockContent/VideoBlockContent.ts","../src/blocks/defaultBlocks.ts","../src/blocks/defaultBlockTypeGuards.ts","../src/blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","../src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts","../src/editor/BlockNoteSchema.ts","../src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts","../src/blocks/PageBreakBlockContent/schema.ts","../src/blocks/PageBreakBlockContent/getPageBreakSlashMenuItems.ts","../src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts","../src/api/blockManipulation/commands/nestBlock/nestBlock.ts","../src/api/blockManipulation/getBlock/getBlock.ts","../src/api/blockManipulation/insertContentAt.ts","../src/api/blockManipulation/selections/selection.ts","../src/api/blockManipulation/selections/textCursorPosition.ts","../src/util/esmDependencies.ts","../src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","../src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts","../src/api/exporters/markdown/markdownExporter.ts","../src/api/parsers/html/util/nestedLists.ts","../src/api/parsers/html/parseHTML.ts","../src/api/parsers/markdown/parseMarkdown.ts","../src/api/clipboard/fromClipboard/acceptedMIMETypes.ts","../src/api/clipboard/fromClipboard/handleFileInsertion.ts","../src/api/clipboard/fromClipboard/fileDropExtension.ts","../src/api/parsers/markdown/detectMarkdown.ts","../src/api/clipboard/fromClipboard/handleVSCodePaste.ts","../src/api/clipboard/fromClipboard/pasteExtension.ts","../src/api/nodeConversions/fragmentToBlocks.ts","../src/api/clipboard/toClipboard/copyExtension.ts","../src/extensions/BackgroundColor/BackgroundColorExtension.ts","../src/util/EventEmitter.ts","../src/editor/BlockNoteExtension.ts","../src/extensions/Collaboration/CursorPlugin.ts","../src/extensions/Collaboration/SyncPlugin.ts","../src/extensions/Collaboration/UndoPlugin.ts","../src/extensions/Comments/CommentMark.ts","../src/extensions/Comments/userstore/UserStore.ts","../src/extensions/Comments/CommentsPlugin.ts","../src/extensions/FilePanel/FilePanelPlugin.ts","../src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","../src/extensions/HardBreak/HardBreak.ts","../src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts","../src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts","../src/extensions/LinkToolbar/LinkToolbarPlugin.ts","../src/extensions/LinkToolbar/protocols.ts","../src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts","../src/extensions/Placeholder/PlaceholderPlugin.ts","../src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","../src/extensions/ShowSelection/ShowSelectionPlugin.ts","../src/extensions/getDraggableBlockFromElement.ts","../src/extensions/SideMenu/MultipleNodeSelection.ts","../src/extensions/SideMenu/dragging.ts","../src/extensions/SideMenu/SideMenuPlugin.ts","../src/api/positionMapping.ts","../src/extensions/SuggestionMenu/SuggestionPlugin.ts","../src/extensions/Suggestions/SuggestionMarks.ts","../src/extensions/TableHandles/TableHandlesPlugin.ts","../src/extensions/TextAlignment/TextAlignmentExtension.ts","../src/extensions/TextColor/TextColorExtension.ts","../src/extensions/TrailingNode/TrailingNodeExtension.ts","../src/pm-nodes/BlockContainer.ts","../src/pm-nodes/BlockGroup.ts","../src/pm-nodes/Doc.ts","../src/extensions/Collaboration/ForkYDocPlugin.ts","../src/editor/BlockNoteExtensions.ts","../src/editor/transformPasted.ts","../src/editor/BlockNoteTipTapEditor.ts","../src/editor/BlockNoteEditor.ts","../src/editor/defaultColors.ts","../src/exporter/Exporter.ts","../src/exporter/mapping.ts","../src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts","../src/util/combineByGroup.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n Extension,\n findChildrenInRange,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport { Fragment, Slice } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { v4 } from \"uuid\";\n\n/**\n * Code from Tiptap UniqueID extension (https://tiptap.dev/api/extensions/unique-id)\n * This extension is licensed under MIT (even though it's part of Tiptap pro).\n *\n * If you're a user of BlockNote, we still recommend to support their awesome work and become a sponsor!\n * https://tiptap.dev/pro\n */\n\n/**\n * Removes duplicated values within an array.\n * Supports numbers, strings and objects.\n */\nfunction removeDuplicates(array: any, by = JSON.stringify) {\n const seen: any = {};\n return array.filter((item: any) => {\n const key = by(item);\n return Object.prototype.hasOwnProperty.call(seen, key)\n ? false\n : (seen[key] = true);\n });\n}\n\n/**\n * Returns a list of duplicated items within an array.\n */\nfunction findDuplicates(items: any) {\n const filtered = items.filter(\n (el: any, index: number) => items.indexOf(el) !== index,\n );\n const duplicates = removeDuplicates(filtered);\n return duplicates;\n}\n\nconst UniqueID = Extension.create({\n name: \"uniqueID\",\n // we’ll set a very high priority to make sure this runs first\n // and is compatible with `appendTransaction` hooks of other extensions\n priority: 10000,\n addOptions() {\n return {\n attributeName: \"id\",\n types: [],\n setIdAttribute: false,\n generateID: () => {\n // Use mock ID if tests are running.\n if (typeof window !== \"undefined\" && (window as any).__TEST_OPTIONS) {\n const testOptions = (window as any).__TEST_OPTIONS;\n if (testOptions.mockID === undefined) {\n testOptions.mockID = 0;\n } else {\n testOptions.mockID++;\n }\n\n return testOptions.mockID.toString() as string;\n }\n\n return v4();\n },\n filterTransaction: null,\n };\n },\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n [this.options.attributeName]: {\n default: null,\n parseHTML: (element) =>\n element.getAttribute(`data-${this.options.attributeName}`),\n renderHTML: (attributes) => {\n const defaultIdAttributes = {\n [`data-${this.options.attributeName}`]:\n attributes[this.options.attributeName],\n };\n if (this.options.setIdAttribute) {\n return {\n ...defaultIdAttributes,\n id: attributes[this.options.attributeName],\n };\n } else {\n return defaultIdAttributes;\n }\n },\n },\n },\n },\n ];\n },\n // check initial content for missing ids\n // onCreate() {\n // // Don’t do this when the collaboration extension is active\n // // because this may update the content, so Y.js tries to merge these changes.\n // // This leads to empty block nodes.\n // // See: https://github.com/ueberdosis/tiptap/issues/2400\n // if (\n // this.editor.extensionManager.extensions.find(\n // (extension) => extension.name === \"collaboration\"\n // )\n // ) {\n // return;\n // }\n // const { view, state } = this.editor;\n // const { tr, doc } = state;\n // const { types, attributeName, generateID } = this.options;\n // const nodesWithoutId = findChildren(doc, (node) => {\n // return (\n // types.includes(node.type.name) && node.attrs[attributeName] === null\n // );\n // });\n // nodesWithoutId.forEach(({ node, pos }) => {\n // tr.setNodeMarkup(pos, undefined, {\n // ...node.attrs,\n // [attributeName]: generateID(),\n // });\n // });\n // tr.setMeta(\"addToHistory\", false);\n // view.dispatch(tr);\n // },\n addProseMirrorPlugins() {\n let dragSourceElement: any = null;\n let transformPasted = false;\n return [\n new Plugin({\n key: new PluginKey(\"uniqueID\"),\n appendTransaction: (transactions, oldState, newState) => {\n // console.log(\"appendTransaction\");\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n const filterTransactions =\n this.options.filterTransaction &&\n transactions.some((tr) => {\n let _a, _b;\n return !((_b = (_a = this.options).filterTransaction) === null ||\n _b === void 0\n ? void 0\n : _b.call(_a, tr));\n });\n if (!docChanges || filterTransactions) {\n return;\n }\n const { tr } = newState;\n const { types, attributeName, generateID } = this.options;\n const transform = combineTransactionSteps(\n oldState.doc,\n transactions as any,\n );\n const { mapping } = transform;\n // get changed ranges based on the old state\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange }) => {\n const newNodes = findChildrenInRange(\n newState.doc,\n newRange,\n (node) => {\n return types.includes(node.type.name);\n },\n );\n const newIds = newNodes\n .map(({ node }) => node.attrs[attributeName])\n .filter((id) => id !== null);\n const duplicatedNewIds = findDuplicates(newIds);\n newNodes.forEach(({ node, pos }) => {\n let _a;\n // instead of checking `node.attrs[attributeName]` directly\n // we look at the current state of the node within `tr.doc`.\n // this helps to prevent adding new ids to the same node\n // if the node changed multiple times within one transaction\n const id =\n (_a = tr.doc.nodeAt(pos)) === null || _a === void 0\n ? void 0\n : _a.attrs[attributeName];\n if (id === null) {\n // edge case, when using collaboration, yjs will set the id to null in `_forceRerender`\n // when loading the editor\n // this checks for this case and keeps it at initialBlockId so there will be no change\n const initialDoc = oldState.doc.type.createAndFill()!.content;\n const wasInitial =\n oldState.doc.content.findDiffStart(initialDoc) === null;\n\n if (wasInitial) {\n // the old state was the \"initial content\"\n const jsonNode = JSON.parse(\n JSON.stringify(newState.doc.toJSON()),\n );\n jsonNode.content[0].content[0].attrs.id = \"initialBlockId\";\n // would the new state with the fix also be the \"initial content\"?\n if (\n JSON.stringify(jsonNode.content) ===\n JSON.stringify(initialDoc.toJSON())\n ) {\n // yes, apply the fix\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: \"initialBlockId\",\n });\n return;\n }\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n });\n return;\n }\n // check if the node doesn’t exist in the old state\n const { deleted } = mapping.invert().mapResult(pos);\n const newNode = deleted && duplicatedNewIds.includes(id);\n if (newNode) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n });\n }\n });\n });\n if (!tr.steps.length) {\n return;\n }\n return tr;\n },\n // we register a global drag handler to track the current drag source element\n view(view) {\n const handleDragstart = (event: any) => {\n let _a;\n dragSourceElement = (\n (_a = view.dom.parentElement) === null || _a === void 0\n ? void 0\n : _a.contains(event.target)\n )\n ? view.dom.parentElement\n : null;\n };\n window.addEventListener(\"dragstart\", handleDragstart);\n return {\n destroy() {\n window.removeEventListener(\"dragstart\", handleDragstart);\n },\n };\n },\n props: {\n // `handleDOMEvents` is called before `transformPasted` so we can do\n // some checks before. However, `transformPasted` only runs when\n // editor content is pasted - not external content.\n handleDOMEvents: {\n // only create new ids for dropped content while holding `alt`\n // or content is dragged from another editor\n drop: (view, event: any) => {\n let _a;\n if (\n dragSourceElement !== view.dom.parentElement ||\n ((_a = event.dataTransfer) === null || _a === void 0\n ? void 0\n : _a.effectAllowed) === \"copy\"\n ) {\n transformPasted = true;\n } else {\n transformPasted = false;\n }\n\n dragSourceElement = null;\n\n return false;\n },\n // always create new ids on pasted content\n paste: () => {\n transformPasted = true;\n return false;\n },\n },\n // we’ll remove ids for every pasted node\n // so we can create a new one within `appendTransaction`\n transformPasted: (slice) => {\n if (!transformPasted) {\n return slice;\n }\n const { types, attributeName } = this.options;\n const removeId = (fragment: any) => {\n const list: any[] = [];\n fragment.forEach((node: any) => {\n // don’t touch text nodes\n if (node.isText) {\n list.push(node);\n return;\n }\n // check for any other child nodes\n if (!types.includes(node.type.name)) {\n list.push(node.copy(removeId(node.content)));\n return;\n }\n // remove id\n const nodeWithoutId = node.type.create(\n {\n ...node.attrs,\n [attributeName]: null,\n },\n removeId(node.content),\n node.marks,\n );\n list.push(nodeWithoutId);\n });\n return Fragment.from(list);\n };\n // reset check\n transformPasted = false;\n return new Slice(\n removeId(slice.content),\n slice.openStart,\n slice.openEnd,\n );\n },\n },\n }),\n ];\n },\n});\n\nexport { UniqueID as default, UniqueID };\n","import { Node } from \"@tiptap/core\";\nimport { PropSchema, Props } from \"../propTypes.js\";\nimport { StyleSchema, Styles } from \"../styles/types.js\";\n\nexport type CustomInlineContentConfig = {\n type: string;\n content: \"styled\" | \"none\"; // | \"plain\"\n readonly propSchema: PropSchema;\n // content: \"inline\" | \"none\" | \"table\";\n};\n// InlineContentConfig contains the \"schema\" info about an InlineContent type\n// i.e. what props it supports, what content it supports, etc.\nexport type InlineContentConfig = CustomInlineContentConfig | \"text\" | \"link\";\n\n// InlineContentImplementation contains the \"implementation\" info about an InlineContent element\n// such as the functions / Nodes required to render and / or serialize it\n// @ts-ignore\nexport type InlineContentImplementation<T extends InlineContentConfig> =\n T extends \"link\" | \"text\"\n ? undefined\n : {\n node: Node;\n };\n\n// Container for both the config and implementation of InlineContent,\n// and the type of `implementation` is based on that of the config\nexport type InlineContentSpec<T extends InlineContentConfig> = {\n config: T;\n implementation: InlineContentImplementation<T>;\n};\n\n// A Schema contains all the types (Configs) supported in an editor\n// The keys are the \"type\" of InlineContent elements\nexport type InlineContentSchema = Record<string, InlineContentConfig>;\n\nexport type InlineContentSpecs = {\n text: { config: \"text\"; implementation: undefined };\n link: { config: \"link\"; implementation: undefined };\n} & Record<string, InlineContentSpec<InlineContentConfig>>;\n\nexport type InlineContentSchemaFromSpecs<T extends InlineContentSpecs> = {\n [K in keyof T]: T[K][\"config\"];\n};\n\nexport type CustomInlineContentFromConfig<\n I extends CustomInlineContentConfig,\n S extends StyleSchema,\n> = {\n type: I[\"type\"];\n props: Props<I[\"propSchema\"]>;\n content: I[\"content\"] extends \"styled\"\n ? StyledText<S>[]\n : I[\"content\"] extends \"plain\"\n ? string\n : I[\"content\"] extends \"none\"\n ? undefined\n : never;\n};\n\nexport type InlineContentFromConfig<\n I extends InlineContentConfig,\n S extends StyleSchema,\n> = I extends \"text\"\n ? StyledText<S>\n : I extends \"link\"\n ? Link<S>\n : I extends CustomInlineContentConfig\n ? CustomInlineContentFromConfig<I, S>\n : never;\n\nexport type PartialCustomInlineContentFromConfig<\n I extends CustomInlineContentConfig,\n S extends StyleSchema,\n> = {\n type: I[\"type\"];\n props?: Props<I[\"propSchema\"]>;\n content?: I[\"content\"] extends \"styled\"\n ? StyledText<S>[] | string\n : I[\"content\"] extends \"plain\"\n ? string\n : I[\"content\"] extends \"none\"\n ? undefined\n : never;\n};\n\nexport type PartialInlineContentFromConfig<\n I extends InlineContentConfig,\n S extends StyleSchema,\n> = I extends \"text\"\n ? string | StyledText<S>\n : I extends \"link\"\n ? PartialLink<S>\n : I extends CustomInlineContentConfig\n ? PartialCustomInlineContentFromConfig<I, S>\n : never;\n\nexport type StyledText<T extends StyleSchema> = {\n type: \"text\";\n text: string;\n styles: Styles<T>;\n};\n\nexport type Link<T extends StyleSchema> = {\n type: \"link\";\n href: string;\n content: StyledText<T>[];\n};\n\nexport type PartialLink<T extends StyleSchema> = Omit<Link<T>, \"content\"> & {\n content: string | Link<T>[\"content\"];\n};\n\nexport type InlineContent<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = InlineContentFromConfig<I[keyof I], T>;\n\ntype PartialInlineContentElement<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = PartialInlineContentFromConfig<I[keyof I], T>;\n\nexport type PartialInlineContent<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = PartialInlineContentElement<I, T>[] | string;\n\nexport function isLinkInlineContent<T extends StyleSchema>(\n content: InlineContent<any, T>,\n): content is Link<T> {\n return content.type === \"link\";\n}\n\nexport function isPartialLinkInlineContent<T extends StyleSchema>(\n content: PartialInlineContentElement<any, T>,\n): content is PartialLink<T> {\n return typeof content !== \"string\" && content.type === \"link\";\n}\n\nexport function isStyledTextInlineContent<T extends StyleSchema>(\n content: PartialInlineContentElement<any, T>,\n): content is StyledText<T> {\n return typeof content !== \"string\" && content.type === \"text\";\n}\n","import type {\n InlineContentSchema,\n StyleSchema,\n PartialInlineContent,\n InlineContent,\n} from \"../schema\";\nimport { PartialTableCell, TableCell } from \"../schema/blocks/types.js\";\n\n/**\n * This will map a table cell to a TableCell object.\n * This is useful for when we want to get the full table cell object from a partial table cell.\n * It is guaranteed to return a new TableCell object.\n */\nexport function mapTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | TableCell<T, S>,\n): TableCell<T, S> {\n return isTableCell(content)\n ? { ...content }\n : isPartialTableCell(content)\n ? {\n type: \"tableCell\",\n content: ([] as InlineContent<T, S>[]).concat(content.content as any),\n props: {\n backgroundColor: content.props?.backgroundColor ?? \"default\",\n textColor: content.props?.textColor ?? \"default\",\n textAlignment: content.props?.textAlignment ?? \"left\",\n colspan: content.props?.colspan ?? 1,\n rowspan: content.props?.rowspan ?? 1,\n },\n }\n : {\n type: \"tableCell\",\n content: ([] as InlineContent<T, S>[]).concat(content as any),\n props: {\n backgroundColor: \"default\",\n textColor: \"default\",\n textAlignment: \"left\",\n colspan: 1,\n rowspan: 1,\n },\n };\n}\n\nexport function isPartialTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | TableCell<T, S>\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | undefined\n | null,\n): content is PartialTableCell<T, S> {\n return (\n content !== undefined &&\n content !== null &&\n typeof content !== \"string\" &&\n !Array.isArray(content) &&\n content.type === \"tableCell\"\n );\n}\n\nexport function isTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | TableCell<T, S>\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | undefined\n | null,\n): content is TableCell<T, S> {\n return (\n isPartialTableCell(content) &&\n content.props !== undefined &&\n content.content !== undefined\n );\n}\n\nexport function getColspan(\n cell:\n | TableCell<any, any>\n | PartialTableCell<any, any>\n | PartialInlineContent<any, any>,\n): number {\n if (isTableCell(cell)) {\n return cell.props.colspan ?? 1;\n }\n return 1;\n}\n\nexport function getRowspan(\n cell:\n | TableCell<any, any>\n | PartialTableCell<any, any>\n | PartialInlineContent<any, any>,\n): number {\n if (isTableCell(cell)) {\n return cell.props.rowspan ?? 1;\n }\n return 1;\n}\n","export class UnreachableCaseError extends Error {\n constructor(val: never) {\n super(`Unreachable case: ${val}`);\n }\n}\n\nexport function assertEmpty(obj: Record<string, never>, throwError = true) {\n const { \"data-test\": dataTest, ...rest } = obj; // exclude data-test\n\n if (Object.keys(rest).length > 0 && throwError) {\n throw new Error(\"Object must be empty \" + JSON.stringify(obj));\n }\n}\n\n// TODO: change for built-in version of typescript 5.4 after upgrade\nexport type NoInfer<T> = [T][T extends any ? 0 : never];\n","export const isAppleOS = () =>\n typeof navigator !== \"undefined\" &&\n (/Mac/.test(navigator.platform) ||\n (/AppleWebKit/.test(navigator.userAgent) &&\n /Mobile\\/\\w+/.test(navigator.userAgent)));\n\nexport function formatKeyboardShortcut(shortcut: string, ctrlText = \"Ctrl\") {\n if (isAppleOS()) {\n return shortcut.replace(\"Mod\", \"⌘\");\n } else {\n return shortcut.replace(\"Mod\", ctrlText);\n }\n}\n\nexport function mergeCSSClasses(...classes: (string | false | undefined)[]) {\n return classes.filter((c) => c).join(\" \");\n}\n\nexport const isSafari = () =>\n /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n","import { blockToNode } from \"../api/nodeConversions/blockToNode.js\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport type {\n BlockNoDefaults,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../schema/index.js\";\nimport { mergeCSSClasses } from \"../util/browser.js\";\n\n// Function that creates a ProseMirror `DOMOutputSpec` for a default block.\n// Since all default blocks have the same structure (`blockContent` div with a\n// `inlineContent` element inside), this function only needs the block's name\n// for the `data-content-type` attribute of the `blockContent` element and the\n// HTML tag of the `inlineContent` element, as well as any HTML attributes to\n// add to those.\nexport function createDefaultBlockDOMOutputSpec(\n blockName: string,\n htmlTag: string,\n blockContentHTMLAttributes: Record<string, string>,\n inlineContentHTMLAttributes: Record<string, string>,\n) {\n const blockContent = document.createElement(\"div\");\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n blockContentHTMLAttributes.class,\n );\n blockContent.setAttribute(\"data-content-type\", blockName);\n for (const [attribute, value] of Object.entries(blockContentHTMLAttributes)) {\n if (attribute !== \"class\") {\n blockContent.setAttribute(attribute, value);\n }\n }\n\n const inlineContent = document.createElement(htmlTag);\n inlineContent.className = mergeCSSClasses(\n \"bn-inline-content\",\n inlineContentHTMLAttributes.class,\n );\n for (const [attribute, value] of Object.entries(\n inlineContentHTMLAttributes,\n )) {\n if (attribute !== \"class\") {\n inlineContent.setAttribute(attribute, value);\n }\n }\n\n blockContent.appendChild(inlineContent);\n\n return {\n dom: blockContent,\n contentDOM: inlineContent,\n };\n}\n\n// Function used to convert default blocks to HTML. It uses the corresponding\n// node's `renderHTML` method to do the conversion by using a default\n// `DOMSerializer`.\nexport const defaultBlockToHTML = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n block: BlockNoDefaults<BSchema, I, S>,\n editor: BlockNoteEditor<BSchema, I, S>,\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} => {\n let node = blockToNode(block, editor.pmSchema);\n\n if (node.type.name === \"blockContainer\") {\n // for regular blocks, get the toDOM spec from the blockContent node\n node = node.firstChild!;\n }\n\n const toDOM = editor.pmSchema.nodes[node.type.name].spec.toDOM;\n\n if (toDOM === undefined) {\n throw new Error(\n \"This block has no default HTML serialization as its corresponding TipTap node doesn't implement `renderHTML`.\",\n );\n }\n\n const renderSpec = toDOM(node);\n\n if (typeof renderSpec !== \"object\" || !(\"dom\" in renderSpec)) {\n throw new Error(\n \"Cannot use this block's default HTML serialization as its corresponding TipTap node's `renderHTML` function does not return an object with the `dom` property.\",\n );\n }\n\n return renderSpec as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n};\n\n// Function that merges all paragraphs into a single one separated by line breaks.\n// This is used when parsing blocks like list items and table cells, as they may\n// contain multiple paragraphs that ProseMirror will not be able to handle\n// properly.\nexport function mergeParagraphs(element: HTMLElement) {\n const paragraphs = element.querySelectorAll(\"p\");\n if (paragraphs.length > 1) {\n const firstParagraph = paragraphs[0];\n for (let i = 1; i < paragraphs.length; i++) {\n const paragraph = paragraphs[i];\n firstParagraph.innerHTML += \"<br>\" + paragraph.innerHTML;\n paragraph.remove();\n }\n }\n}\n","import type { Props, PropSchema } from \"../schema/index.js\";\n\n// TODO: this system should probably be moved / refactored.\n// The dependency from schema on this file doesn't make sense\n\nexport const defaultProps = {\n backgroundColor: {\n default: \"default\" as const,\n },\n textColor: {\n default: \"default\" as const,\n },\n textAlignment: {\n default: \"left\" as const,\n values: [\"left\", \"center\", \"right\", \"justify\"] as const,\n },\n} satisfies PropSchema;\n\nexport type DefaultProps = Props<typeof defaultProps>;\n\n// Default props which are set on `blockContainer` nodes rather than\n// `blockContent` nodes. Ensures that they are not redundantly added to\n// a custom block's TipTap node attributes.\nexport const inheritedProps = [\"backgroundColor\", \"textColor\"];\n","export function camelToDataKebab(str: string): string {\n return \"data-\" + str.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\nexport function filenameFromURL(url: string): string {\n const parts = url.split(\"/\");\n if (\n !parts.length || // invalid?\n parts[parts.length - 1] === \"\" // for example, URL ends in a directory-like trailing slash\n ) {\n // in this case just return the original url\n return url;\n }\n return parts[parts.length - 1];\n}\n","import {\n Attribute,\n Attributes,\n Editor,\n Extension,\n Node,\n NodeConfig,\n} from \"@tiptap/core\";\nimport { defaultBlockToHTML } from \"../../blocks/defaultBlockHelpers.js\";\nimport { inheritedProps } from \"../../blocks/defaultProps.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { mergeCSSClasses } from \"../../util/browser.js\";\nimport { camelToDataKebab } from \"../../util/string.js\";\nimport { InlineContentSchema } from \"../inlineContent/types.js\";\nimport { PropSchema, Props } from \"../propTypes.js\";\nimport { StyleSchema } from \"../styles/types.js\";\nimport {\n BlockConfig,\n BlockSchemaFromSpecs,\n BlockSchemaWithBlock,\n BlockSpec,\n BlockSpecs,\n SpecificBlock,\n TiptapBlockImplementation,\n} from \"./types.js\";\n\n// Function that uses the 'propSchema' of a blockConfig to create a TipTap\n// node's `addAttributes` property.\n// TODO: extract function\nexport function propsToAttributes(propSchema: PropSchema): Attributes {\n const tiptapAttributes: Record<string, Attribute> = {};\n\n Object.entries(propSchema)\n .filter(([name, _spec]) => !inheritedProps.includes(name))\n .forEach(([name, spec]) => {\n tiptapAttributes[name] = {\n default: spec.default,\n keepOnSplit: true,\n // Props are displayed in kebab-case as HTML attributes. If a prop's\n // value is the same as its default, we don't display an HTML\n // attribute for it.\n parseHTML: (element) => {\n const value = element.getAttribute(camelToDataKebab(name));\n\n if (value === null) {\n return null;\n }\n\n if (\n (spec.default === undefined && spec.type === \"boolean\") ||\n (spec.default !== undefined && typeof spec.default === \"boolean\")\n ) {\n if (value === \"true\") {\n return true;\n }\n\n if (value === \"false\") {\n return false;\n }\n\n return null;\n }\n\n if (\n (spec.default === undefined && spec.type === \"number\") ||\n (spec.default !== undefined && typeof spec.default === \"number\")\n ) {\n const asNumber = parseFloat(value);\n const isNumeric =\n !Number.isNaN(asNumber) && Number.isFinite(asNumber);\n\n if (isNumeric) {\n return asNumber;\n }\n\n return null;\n }\n\n return value;\n },\n renderHTML: (attributes) => {\n // don't render to html if the value is the same as the default\n return attributes[name] !== spec.default\n ? {\n [camelToDataKebab(name)]: attributes[name],\n }\n : {};\n },\n };\n });\n\n return tiptapAttributes;\n}\n\n// Used to figure out which block should be rendered. This block is then used to\n// create the node view.\nexport function getBlockFromPos<\n BType extends string,\n Config extends BlockConfig,\n BSchema extends BlockSchemaWithBlock<BType, Config>,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n getPos: (() => number) | boolean,\n editor: BlockNoteEditor<BSchema, I, S>,\n tipTapEditor: Editor,\n type: BType,\n) {\n // Gets position of the node\n if (typeof getPos === \"boolean\") {\n throw new Error(\n \"Cannot find node position as getPos is a boolean, not a function.\",\n );\n }\n const pos = getPos();\n // Gets parent blockContainer node\n const blockContainer = tipTapEditor.state.doc.resolve(pos!).node();\n // Gets block identifier\n const blockIdentifier = blockContainer.attrs.id;\n\n if (!blockIdentifier) {\n throw new Error(\"Block doesn't have id\");\n }\n\n // Gets the block\n const block = editor.getBlock(blockIdentifier)! as SpecificBlock<\n BSchema,\n BType,\n I,\n S\n >;\n if (block.type !== type) {\n throw new Error(\"Block type does not match\");\n }\n\n return block;\n}\n\n// Function that wraps the `dom` element returned from 'blockConfig.render' in a\n// `blockContent` div, which contains the block type and props as HTML\n// attributes. If `blockConfig.render` also returns a `contentDOM`, it also adds\n// an `inlineContent` class to it.\nexport function wrapInBlockStructure<\n BType extends string,\n PSchema extends PropSchema,\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n },\n blockType: BType,\n blockProps: Props<PSchema>,\n propSchema: PSchema,\n isFileBlock = false,\n domAttributes?: Record<string, string>,\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n} {\n // Creates `blockContent` element\n const blockContent = document.createElement(\"div\");\n\n // Adds custom HTML attributes\n if (domAttributes !== undefined) {\n for (const [attr, value] of Object.entries(domAttributes)) {\n if (attr !== \"class\") {\n blockContent.setAttribute(attr, value);\n }\n }\n }\n // Sets blockContent class\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n domAttributes?.class || \"\",\n );\n // Sets content type attribute\n blockContent.setAttribute(\"data-content-type\", blockType);\n // Adds props as HTML attributes in kebab-case with \"data-\" prefix. Skips props\n // which are already added as HTML attributes to the parent `blockContent`\n // element (inheritedProps) and props set to their default values.\n for (const [prop, value] of Object.entries(blockProps)) {\n const spec = propSchema[prop];\n const defaultValue = spec.default;\n if (!inheritedProps.includes(prop) && value !== defaultValue) {\n blockContent.setAttribute(camelToDataKebab(prop), value);\n }\n }\n // Adds file block attribute\n if (isFileBlock) {\n blockContent.setAttribute(\"data-file-block\", \"\");\n }\n\n blockContent.appendChild(element.dom);\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.className = mergeCSSClasses(\n \"bn-inline-content\",\n element.contentDOM.className,\n );\n }\n\n return {\n ...element,\n dom: blockContent,\n };\n}\n\n// Helper type to keep track of the `name` and `content` properties after calling Node.create.\ntype StronglyTypedTipTapNode<\n Name extends string,\n Content extends\n | \"inline*\"\n | \"tableRow+\"\n | \"blockContainer+\"\n | \"column column+\"\n | \"\",\n> = Node & { name: Name; config: { content: Content } };\n\nexport function createStronglyTypedTiptapNode<\n Name extends string,\n Content extends\n | \"inline*\"\n | \"tableRow+\"\n | \"blockContainer+\"\n | \"column column+\"\n | \"\",\n>(config: NodeConfig & { name: Name; content: Content }) {\n return Node.create(config) as StronglyTypedTipTapNode<Name, Content>; // force re-typing (should be safe as it's type-checked from the config)\n}\n\n// This helper function helps to instantiate a blockspec with a\n// config and implementation that conform to the type of Config\nexport function createInternalBlockSpec<T extends BlockConfig>(\n config: T,\n implementation: TiptapBlockImplementation<\n T,\n any,\n InlineContentSchema,\n StyleSchema\n >,\n) {\n return {\n config,\n implementation,\n } satisfies BlockSpec<T, any, InlineContentSchema, StyleSchema>;\n}\n\nexport function createBlockSpecFromStronglyTypedTiptapNode<\n T extends Node,\n P extends PropSchema,\n>(node: T, propSchema: P, requiredExtensions?: Array<Extension | Node>) {\n return createInternalBlockSpec(\n {\n type: node.name as T[\"name\"],\n content: (node.config.content === \"inline*\"\n ? \"inline\"\n : node.config.content === \"tableRow+\"\n ? \"table\"\n : \"none\") as T[\"config\"][\"content\"] extends \"inline*\"\n ? \"inline\"\n : T[\"config\"][\"content\"] extends \"tableRow+\"\n ? \"table\"\n : \"none\",\n propSchema,\n },\n {\n node,\n requiredExtensions,\n toInternalHTML: defaultBlockToHTML,\n toExternalHTML: defaultBlockToHTML,\n // parse: () => undefined, // parse rules are in node already\n },\n );\n}\n\nexport function getBlockSchemaFromSpecs<T extends BlockSpecs>(specs: T) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config]),\n ) as BlockSchemaFromSpecs<T>;\n}\n","import { Editor } from \"@tiptap/core\";\nimport { TagParseRule } from \"@tiptap/pm/model\";\nimport { NodeView } from \"@tiptap/pm/view\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { InlineContentSchema } from \"../inlineContent/types.js\";\nimport { StyleSchema } from \"../styles/types.js\";\nimport {\n createInternalBlockSpec,\n createStronglyTypedTiptapNode,\n getBlockFromPos,\n propsToAttributes,\n wrapInBlockStructure,\n} from \"./internal.js\";\nimport {\n BlockConfig,\n BlockFromConfig,\n BlockSchemaWithBlock,\n PartialBlockFromConfig,\n} from \"./types.js\";\n\n// restrict content to \"inline\" and \"none\" only\nexport type CustomBlockConfig = BlockConfig & {\n content: \"inline\" | \"none\";\n};\n\nexport type CustomBlockImplementation<\n T extends CustomBlockConfig,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = {\n render: (\n /**\n * The custom block to render\n */\n block: BlockFromConfig<T, I, S>,\n /**\n * The BlockNote editor instance\n * This is typed generically. If you want an editor with your custom schema, you need to\n * cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`\n */\n editor: BlockNoteEditor<BlockSchemaWithBlock<T[\"type\"], T>, I, S>,\n // (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations\n // or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n };\n // Exports block to external HTML. If not defined, the output will be the same\n // as `render(...).dom`. Used to create clipboard data when pasting outside\n // BlockNote.\n // TODO: Maybe can return undefined to ignore when serializing?\n toExternalHTML?: (\n block: BlockFromConfig<T, I, S>,\n editor: BlockNoteEditor<BlockSchemaWithBlock<T[\"type\"], T>, I, S>,\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n parse?: (\n el: HTMLElement,\n ) => PartialBlockFromConfig<T, I, S>[\"props\"] | undefined;\n};\n\n// Function that causes events within non-selectable blocks to be handled by the\n// browser instead of the editor.\nexport function applyNonSelectableBlockFix(nodeView: NodeView, editor: Editor) {\n nodeView.stopEvent = (event) => {\n // Blurs the editor on mouse down as the block is non-selectable. This is\n // mainly done to prevent UI elements like the formatting toolbar from being\n // visible while content within a non-selectable block is selected.\n if (event.type === \"mousedown\") {\n setTimeout(() => {\n editor.view.dom.blur();\n }, 10);\n }\n\n return true;\n };\n}\n\n// Function that uses the 'parse' function of a blockConfig to create a\n// TipTap node's `parseHTML` property. This is only used for parsing content\n// from the clipboard.\nexport function getParseRules(\n config: BlockConfig,\n customParseFunction: CustomBlockImplementation<any, any, any>[\"parse\"],\n) {\n const rules: TagParseRule[] = [\n {\n tag: \"[data-content-type=\" + config.type + \"]\",\n contentElement: \".bn-inline-content\",\n },\n ];\n\n if (customParseFunction) {\n rules.push({\n tag: \"*\",\n getAttrs(node: string | HTMLElement) {\n if (typeof node === \"string\") {\n return false;\n }\n\n const props = customParseFunction?.(node);\n\n if (props === undefined) {\n return false;\n }\n\n return props;\n },\n });\n }\n // getContent(node, schema) {\n // const block = blockConfig.parse?.(node as HTMLElement);\n //\n // if (block !== undefined && block.content !== undefined) {\n // return Fragment.from(\n // typeof block.content === \"string\"\n // ? schema.text(block.content)\n // : inlineContentToNodes(block.content, schema)\n // );\n // }\n //\n // return Fragment.empty;\n // },\n // });\n // }\n\n return rules;\n}\n\n// A function to create custom block for API consumers\n// we want to hide the tiptap node from API consumers and provide a simpler API surface instead\nexport function createBlockSpec<\n T extends CustomBlockConfig,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockConfig: T,\n blockImplementation: CustomBlockImplementation<NoInfer<T>, I, S>,\n) {\n const node = createStronglyTypedTiptapNode({\n name: blockConfig.type as T[\"type\"],\n content: (blockConfig.content === \"inline\"\n ? \"inline*\"\n : \"\") as T[\"content\"] extends \"inline\" ? \"inline*\" : \"\",\n group: \"blockContent\",\n selectable: blockConfig.isSelectable ?? true,\n isolating: true,\n addAttributes() {\n return propsToAttributes(blockConfig.propSchema);\n },\n\n parseHTML() {\n return getParseRules(blockConfig, blockImplementation.parse);\n },\n\n renderHTML({ HTMLAttributes }) {\n // renderHTML is used for copy/pasting content from the editor back into\n // the editor, so we need to make sure the `blockContent` element is\n // structured correctly as this is what's used for parsing blocks. We\n // just render a placeholder div inside as the `blockContent` element\n // already has all the information needed for proper parsing.\n const div = document.createElement(\"div\");\n return wrapInBlockStructure(\n {\n dom: div,\n contentDOM: blockConfig.content === \"inline\" ? div : undefined,\n },\n blockConfig.type,\n {},\n blockConfig.propSchema,\n blockConfig.isFileBlock,\n HTMLAttributes,\n );\n },\n\n addNodeView() {\n return ({ getPos }) => {\n // Gets the BlockNote editor instance\n const editor = this.options.editor;\n // Gets the block\n const block = getBlockFromPos(\n getPos,\n editor,\n this.editor,\n blockConfig.type,\n );\n // Gets the custom HTML attributes for `blockContent` nodes\n const blockContentDOMAttributes =\n this.options.domAttributes?.blockContent || {};\n\n const output = blockImplementation.render(block as any, editor);\n\n const nodeView: NodeView = wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes,\n );\n\n if (blockConfig.isSelectable === false) {\n applyNonSelectableBlockFix(nodeView, this.editor);\n }\n\n return nodeView;\n };\n },\n });\n\n if (node.name !== blockConfig.type) {\n throw new Error(\n \"Node name does not match block type. This is a bug in BlockNote.\",\n );\n }\n\n return createInternalBlockSpec(blockConfig, {\n node,\n toInternalHTML: (block, editor) => {\n const blockContentDOMAttributes =\n node.options.domAttributes?.blockContent || {};\n\n const output = blockImplementation.render(block as any, editor as any);\n\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockConfig.isFileBlock,\n blockContentDOMAttributes,\n );\n },\n // TODO: this should not have wrapInBlockStructure and generally be a lot simpler\n // post-processing in externalHTMLExporter should not be necessary\n toExternalHTML: (block, editor) => {\n const blockContentDOMAttributes =\n node.options.domAttributes?.blockContent || {};\n\n let output = blockImplementation.toExternalHTML?.(\n block as any,\n editor as any,\n );\n if (output === undefined) {\n output = blockImplementation.render(block as any, editor as any);\n }\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes,\n );\n },\n });\n}\n","import { Node, ResolvedPos } from \"prosemirror-model\";\nimport { EditorState, Transaction } from \"prosemirror-state\";\n\ntype SingleBlockInfo = {\n node: Node;\n beforePos: number;\n afterPos: number;\n};\n\nexport type BlockInfo = {\n /**\n * The outer node that represents a BlockNote block. This is the node that has the ID.\n * Most of the time, this will be a blockContainer node, but it could also be a Column or ColumnList\n */\n bnBlock: SingleBlockInfo;\n /**\n * The type of BlockNote block that this node represents.\n * When dealing with a blockContainer, this is retrieved from the blockContent node, otherwise it's retrieved from the bnBlock node.\n */\n blockNoteType: string;\n} & (\n | {\n // In case we're not dealing with a BlockContainer, we're dealing with a \"wrapper node\" (like a Column or ColumnList), so it will always have children\n\n /**\n * The Prosemirror node that holds block.children. For non-blockContainer, this node will be the same as bnBlock.\n */\n childContainer: SingleBlockInfo;\n isBlockContainer: false;\n }\n | {\n /**\n * The Prosemirror node that holds block.children. For blockContainers, this is the blockGroup node, if it exists.\n */\n childContainer?: SingleBlockInfo;\n /**\n * The Prosemirror node that wraps block.content and has most of the props\n */\n blockContent: SingleBlockInfo;\n /**\n * Whether bnBlock is a blockContainer node\n */\n isBlockContainer: true;\n }\n);\n\n/**\n * Retrieves the position just before the nearest block node in a ProseMirror\n * doc, relative to a position. If the position is within a block node or its\n * descendants, the position just before it is returned. If the position is not\n * within a block node or its descendants, the position just before the next\n * closest block node is returned. If the position is beyond the last block, the\n * position just before the last block is returned.\n * @param doc The ProseMirror doc.\n * @param pos An integer position in the document.\n * @returns The position just before the nearest blockContainer node.\n */\nexport function getNearestBlockPos(doc: Node, pos: number) {\n const $pos = doc.resolve(pos);\n\n // Checks if the position provided is already just before a block node, in\n // which case we return the position.\n if ($pos.nodeAfter && $pos.nodeAfter.type.isInGroup(\"bnBlock\")) {\n return {\n posBeforeNode: $pos.pos,\n node: $pos.nodeAfter,\n };\n }\n\n // Checks the node containing the position and its ancestors until a\n // block node is found and returned.\n let depth = $pos.depth;\n let node = $pos.node(depth);\n while (depth > 0) {\n if (node.type.isInGroup(\"bnBlock\")) {\n return {\n posBeforeNode: $pos.before(depth),\n node: node,\n };\n }\n\n depth--;\n node = $pos.node(depth);\n }\n\n // If the position doesn't lie within a block node, we instead find the\n // position of the next closest one. If the position is beyond the last block,\n // we return the position of the last block. While running `doc.descendants`\n // is expensive, this case should be very rarely triggered. However, it's\n // possible for the position to sometimes be beyond the last block node. This\n // is a problem specifically when using the collaboration plugin.\n const allBlockContainerPositions: number[] = [];\n doc.descendants((node, pos) => {\n if (node.type.isInGroup(\"bnBlock\")) {\n allBlockContainerPositions.push(pos);\n }\n });\n\n // eslint-disable-next-line no-console\n console.warn(`Position ${pos} is not within a blockContainer node.`);\n\n const resolvedPos = doc.resolve(\n allBlockContainerPositions.find((position) => position >= pos) ||\n allBlockContainerPositions[allBlockContainerPositions.length - 1],\n );\n return {\n posBeforeNode: resolvedPos.pos,\n node: resolvedPos.nodeAfter!,\n };\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block in a\n * BlockNote document. This includes the main `blockContainer` node, the\n * `blockContent` node with the block's main body, and the optional `blockGroup`\n * node which contains the block's children. As well as the nodes, also returns\n * the ProseMirror positions just before & after each node.\n * @param node The main `blockContainer` node that the block information should\n * be retrieved from,\n * @param bnBlockBeforePosOffset the position just before the\n * `blockContainer` node in the document.\n */\nexport function getBlockInfoWithManualOffset(\n node: Node,\n bnBlockBeforePosOffset: number,\n): BlockInfo {\n if (!node.type.isInGroup(\"bnBlock\")) {\n throw new Error(\n `Attempted to get bnBlock node at position but found node of different type ${node.type.name}`,\n );\n }\n\n const bnBlockNode = node;\n const bnBlockBeforePos = bnBlockBeforePosOffset;\n const bnBlockAfterPos = bnBlockBeforePos + bnBlockNode.nodeSize;\n\n const bnBlock: SingleBlockInfo = {\n node: bnBlockNode,\n beforePos: bnBlockBeforePos,\n afterPos: bnBlockAfterPos,\n };\n\n if (bnBlockNode.type.name === \"blockContainer\") {\n let blockContent: SingleBlockInfo | undefined;\n let blockGroup: SingleBlockInfo | undefined;\n\n bnBlockNode.forEach((node, offset) => {\n if (node.type.spec.group === \"blockContent\") {\n // console.log(beforePos, offset);\n const blockContentNode = node;\n const blockContentBeforePos = bnBlockBeforePos + offset + 1;\n const blockContentAfterPos = blockContentBeforePos + node.nodeSize;\n\n blockContent = {\n node: blockContentNode,\n beforePos: blockContentBeforePos,\n afterPos: blockContentAfterPos,\n };\n } else if (node.type.name === \"blockGroup\") {\n const blockGroupNode = node;\n const blockGroupBeforePos = bnBlockBeforePos + offset + 1;\n const blockGroupAfterPos = blockGroupBeforePos + node.nodeSize;\n\n blockGroup = {\n node: blockGroupNode,\n beforePos: blockGroupBeforePos,\n afterPos: blockGroupAfterPos,\n };\n }\n });\n\n if (!blockContent) {\n throw new Error(\n `blockContainer node does not contain a blockContent node in its children: ${bnBlockNode}`,\n );\n }\n\n return {\n isBlockContainer: true,\n bnBlock,\n blockContent,\n childContainer: blockGroup,\n blockNoteType: blockContent.node.type.name,\n };\n } else {\n if (!bnBlock.node.type.isInGroup(\"childContainer\")) {\n throw new Error(\n `bnBlock node is not in the childContainer group: ${bnBlock.node}`,\n );\n }\n\n return {\n isBlockContainer: false,\n bnBlock: bnBlock,\n childContainer: bnBlock,\n blockNoteType: bnBlock.node.type.name,\n };\n }\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block in a\n * BlockNote document. This includes the main `blockContainer` node, the\n * `blockContent` node with the block's main body, and the optional `blockGroup`\n * node which contains the block's children. As well as the nodes, also returns\n * the ProseMirror positions just before & after each node.\n * @param posInfo An object with the main `blockContainer` node that the block\n * information should be retrieved from, and the position just before it in the\n * document.\n */\nexport function getBlockInfo(posInfo: { posBeforeNode: number; node: Node }) {\n return getBlockInfoWithManualOffset(posInfo.node, posInfo.posBeforeNode);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block from a\n * resolved position just before the `blockContainer` node in the document that\n * corresponds to it.\n * @param resolvedPos The resolved position just before the `blockContainer`\n * node.\n */\nexport function getBlockInfoFromResolvedPos(resolvedPos: ResolvedPos) {\n if (!resolvedPos.nodeAfter) {\n throw new Error(\n `Attempted to get blockContainer node at position ${resolvedPos.pos} but a node at this position does not exist`,\n );\n }\n return getBlockInfoWithManualOffset(resolvedPos.nodeAfter, resolvedPos.pos);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block. The\n * block chosen is the one currently containing the current ProseMirror\n * selection.\n * @param state The ProseMirror editor state.\n */\nexport function getBlockInfoFromSelection(state: EditorState) {\n const posInfo = getNearestBlockPos(state.doc, state.selection.anchor);\n\n return getBlockInfo(posInfo);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block. The\n * block chosen is the one currently containing the current ProseMirror\n * selection.\n * @param tr The ProseMirror transaction.\n */\nexport function getBlockInfoFromTransaction(tr: Transaction) {\n const posInfo = getNearestBlockPos(tr.doc, tr.selection.anchor);\n\n return getBlockInfo(posInfo);\n}\n","import type { Node, Schema } from \"prosemirror-model\";\nimport { Transform } from \"prosemirror-transform\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport { BlockNoteSchema } from \"../editor/BlockNoteSchema.js\";\nimport type { BlockSchema } from \"../schema/blocks/types.js\";\nimport type { InlineContentSchema } from \"../schema/inlineContent/types.js\";\nimport type { StyleSchema } from \"../schema/styles/types.js\";\n\nexport function getPmSchema(trOrNode: Transform | Node) {\n if (\"doc\" in trOrNode) {\n return trOrNode.doc.type.schema;\n }\n return trOrNode.type.schema;\n}\n\nfunction getBlockNoteEditor<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(schema: Schema): BlockNoteEditor<BSchema, I, S> {\n return schema.cached.blockNoteEditor as BlockNoteEditor<BSchema, I, S>;\n}\n\nexport function getBlockNoteSchema<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(schema: Schema): BlockNoteSchema<BSchema, I, S> {\n return getBlockNoteEditor(schema).schema as unknown as BlockNoteSchema<\n BSchema,\n I,\n S\n >;\n}\n\nexport function getBlockSchema<BSchema extends BlockSchema>(\n schema: Schema,\n): BSchema {\n return getBlockNoteSchema(schema).blockSchema as BSchema;\n}\n\nexport function getInlineContentSchema<I extends InlineContentSchema>(\n schema: Schema,\n): I {\n return getBlockNoteSchema(schema).inlineContentSchema as I;\n}\n\nexport function getStyleSchema<S extends StyleSchema>(schema: Schema): S {\n return getBlockNoteSchema(schema).styleSchema as S;\n}\n\nexport function getBlockCache(schema: Schema) {\n return getBlockNoteEditor(schema).blockCache;\n}\n","import { Mark, Node, Schema, Slice } from \"@tiptap/pm/model\";\nimport type { Block } from \"../../blocks/defaultBlocks.js\";\nimport UniqueID from \"../../extensions/UniqueID/UniqueID.js\";\nimport type {\n BlockSchema,\n CustomInlineContentConfig,\n CustomInlineContentFromConfig,\n InlineContent,\n InlineContentFromConfig,\n InlineContentSchema,\n StyleSchema,\n Styles,\n TableCell,\n TableContent,\n} from \"../../schema/index.js\";\nimport {\n isLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types.js\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport { getBlockInfoWithManualOffset } from \"../getBlockInfoFromPos.js\";\nimport {\n getBlockCache,\n getBlockSchema,\n getInlineContentSchema,\n getStyleSchema,\n} from \"../pmUtil.js\";\n\n/**\n * Converts an internal (prosemirror) table node contentto a BlockNote Tablecontent\n */\nexport function contentNodeToTableContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(contentNode: Node, inlineContentSchema: I, styleSchema: S) {\n const ret: TableContent<I, S> = {\n type: \"tableContent\",\n columnWidths: [],\n headerRows: undefined,\n headerCols: undefined,\n rows: [],\n };\n\n /**\n * A matrix of boolean values indicating whether a cell is a header.\n * The first index is the row index, the second index is the cell index.\n */\n const headerMatrix: boolean[][] = [];\n\n contentNode.content.forEach((rowNode, _offset, rowIndex) => {\n const row: TableContent<I, S>[\"rows\"][0] = {\n cells: [],\n };\n\n if (rowIndex === 0) {\n rowNode.content.forEach((cellNode) => {\n let colWidth = cellNode.attrs.colwidth as null | undefined | number[];\n if (colWidth === undefined || colWidth === null) {\n colWidth = new Array(cellNode.attrs.colspan ?? 1).fill(undefined);\n }\n ret.columnWidths.push(...colWidth);\n });\n }\n\n row.cells = rowNode.content.content.map((cellNode, cellIndex) => {\n if (!headerMatrix[rowIndex]) {\n headerMatrix[rowIndex] = [];\n }\n // Mark the cell as a header if it is a tableHeader node.\n headerMatrix[rowIndex][cellIndex] = cellNode.type.name === \"tableHeader\";\n // Convert cell content to inline content and merge adjacent styled text nodes\n const content = cellNode.content.content\n .map((child) =>\n contentNodeToInlineContent(child, inlineContentSchema, styleSchema),\n )\n // The reason that we merge this content is that we allow table cells to contain multiple tableParagraph nodes\n // So that we can leverage prosemirror-tables native merging\n // If the schema only allowed a single tableParagraph node, then the merging would not work and cause prosemirror to fit the content into a new cell\n .reduce(\n (acc, contentPartial) => {\n if (!acc.length) {\n return contentPartial;\n }\n\n const last = acc[acc.length - 1];\n const first = contentPartial[0];\n\n // Only merge if the last and first content are both styled text nodes and have the same styles\n if (\n first &&\n isStyledTextInlineContent(last) &&\n isStyledTextInlineContent(first) &&\n JSON.stringify(last.styles) === JSON.stringify(first.styles)\n ) {\n // Join them together if they have the same styles\n last.text += \"\\n\" + first.text;\n acc.push(...contentPartial.slice(1));\n return acc;\n }\n acc.push(...contentPartial);\n return acc;\n },\n [] as InlineContent<I, S>[],\n );\n\n return {\n type: \"tableCell\",\n content,\n props: {\n colspan: cellNode.attrs.colspan,\n rowspan: cellNode.attrs.rowspan,\n backgroundColor: cellNode.attrs.backgroundColor,\n textColor: cellNode.attrs.textColor,\n textAlignment: cellNode.attrs.textAlignment,\n },\n } satisfies TableCell<I, S>;\n });\n\n ret.rows.push(row);\n });\n\n for (let i = 0; i < headerMatrix.length; i++) {\n if (headerMatrix[i]?.every((isHeader) => isHeader)) {\n ret.headerRows = (ret.headerRows ?? 0) + 1;\n }\n }\n\n for (let i = 0; i < headerMatrix[0]?.length; i++) {\n if (headerMatrix?.every((row) => row[i])) {\n ret.headerCols = (ret.headerCols ?? 0) + 1;\n }\n }\n\n return ret;\n}\n\n/**\n * Converts an internal (prosemirror) content node to a BlockNote InlineContent array.\n */\nexport function contentNodeToInlineContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(contentNode: Node, inlineContentSchema: I, styleSchema: S) {\n const content: InlineContent<any, S>[] = [];\n let currentContent: InlineContent<any, S> | undefined = undefined;\n\n // Most of the logic below is for handling links because in ProseMirror links are marks\n // while in BlockNote links are a type of inline content\n contentNode.content.forEach((node) => {\n // hardBreak nodes do not have an InlineContent equivalent, instead we\n // add a newline to the previous node.\n if (node.type.name === \"hardBreak\") {\n if (currentContent) {\n // Current content exists.\n if (isStyledTextInlineContent(currentContent)) {\n // Current content is text.\n currentContent.text += \"\\n\";\n } else if (isLinkInlineContent(currentContent)) {\n // Current content is a link.\n currentContent.content[currentContent.content.length - 1].text +=\n \"\\n\";\n } else {\n throw new Error(\"unexpected\");\n }\n } else {\n // Current content does not exist.\n currentContent = {\n type: \"text\",\n text: \"\\n\",\n styles: {},\n };\n }\n\n return;\n }\n\n if (node.type.name !== \"link\" && node.type.name !== \"text\") {\n if (!inlineContentSchema[node.type.name]) {\n // eslint-disable-next-line no-console\n console.warn(\"unrecognized inline content type\", node.type.name);\n return;\n }\n if (currentContent) {\n content.push(currentContent);\n currentContent = undefined;\n }\n\n content.push(\n nodeToCustomInlineContent(node, inlineContentSchema, styleSchema),\n );\n\n return;\n }\n\n const styles: Styles<S> = {};\n let linkMark: Mark | undefined;\n\n for (const mark of node.marks) {\n if (mark.type.name === \"link\") {\n linkMark = mark;\n } else {\n const config = styleSchema[mark.type.name];\n if (!config) {\n if (mark.type.spec.blocknoteIgnore) {\n // at this point, we don't want to show certain marks (such as comments)\n // in the BlockNote JSON output. These marks should be tagged with \"blocknoteIgnore\" in the spec\n continue;\n }\n throw new Error(`style ${mark.type.name} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n (styles as any)[config.type] = true;\n } else if (config.propSchema === \"string\") {\n (styles as any)[config.type] = mark.attrs.stringValue;\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n // Parsing links and text.\n // Current content exists.\n if (currentContent) {\n // Current content is text.\n if (isStyledTextInlineContent(currentContent)) {\n if (!linkMark) {\n // Node is text (same type as current content).\n if (\n JSON.stringify(currentContent.styles) === JSON.stringify(styles)\n ) {\n // Styles are the same.\n currentContent.text += node.textContent;\n } else {\n // Styles are different.\n content.push(currentContent);\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n } else {\n // Node is a link (different type to current content).\n content.push(currentContent);\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n } else if (isLinkInlineContent(currentContent)) {\n // Current content is a link.\n if (linkMark) {\n // Node is a link (same type as current content).\n // Link URLs are the same.\n if (currentContent.href === linkMark.attrs.href) {\n // Styles are the same.\n if (\n JSON.stringify(\n currentContent.content[currentContent.content.length - 1]\n .styles,\n ) === JSON.stringify(styles)\n ) {\n currentContent.content[currentContent.content.length - 1].text +=\n node.textContent;\n } else {\n // Styles are different.\n currentContent.content.push({\n type: \"text\",\n text: node.textContent,\n styles,\n });\n }\n } else {\n // Link URLs are different.\n content.push(currentContent);\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n } else {\n // Node is text (different type to current content).\n content.push(currentContent);\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n } else {\n // TODO\n }\n }\n // Current content does not exist.\n else {\n // Node is text.\n if (!linkMark) {\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n // Node is a link.\n else {\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n }\n });\n\n if (currentContent) {\n content.push(currentContent);\n }\n\n return content as InlineContent<I, S>[];\n}\n\nexport function nodeToCustomInlineContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(node: Node, inlineContentSchema: I, styleSchema: S): InlineContent<I, S> {\n if (node.type.name === \"text\" || node.type.name === \"link\") {\n throw new Error(\"unexpected\");\n }\n const props: any = {};\n const icConfig = inlineContentSchema[\n node.type.name\n ] as CustomInlineContentConfig;\n for (const [attr, value] of Object.entries(node.attrs)) {\n if (!icConfig) {\n throw Error(\"ic node is of an unrecognized type: \" + node.type.name);\n }\n\n const propSchema = icConfig.propSchema;\n\n if (attr in propSchema) {\n props[attr] = value;\n }\n }\n\n let content: CustomInlineContentFromConfig<any, any>[\"content\"];\n\n if (icConfig.content === \"styled\") {\n content = contentNodeToInlineContent(\n node,\n inlineContentSchema,\n styleSchema,\n ) as any; // TODO: is this safe? could we have Links here that are undesired?\n } else {\n content = undefined;\n }\n\n const ic = {\n type: node.type.name,\n props,\n content,\n } as InlineContentFromConfig<I[keyof I], S>;\n return ic;\n}\n\n/**\n * Convert a Prosemirror node to a BlockNote block.\n *\n * TODO: test changes\n */\nexport function nodeToBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n node: Node,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache = getBlockCache(schema),\n): Block<BSchema, I, S> {\n if (!node.type.isInGroup(\"bnBlock\")) {\n throw Error(\"Node should be a bnBlock, but is instead: \" + node.type.name);\n }\n\n const cachedBlock = blockCache?.get(node);\n\n if (cachedBlock) {\n return cachedBlock;\n }\n\n const blockInfo = getBlockInfoWithManualOffset(node, 0);\n\n let id = blockInfo.bnBlock.node.attrs.id;\n\n // Only used for blocks converted from other formats.\n if (id === null) {\n id = UniqueID.options.generateID();\n }\n\n const blockSpec = blockSchema[blockInfo.blockNoteType];\n\n if (!blockSpec) {\n throw Error(\"Block is of an unrecognized type: \" + blockInfo.blockNoteType);\n }\n\n const props: any = {};\n for (const [attr, value] of Object.entries({\n ...node.attrs,\n ...(blockInfo.isBlockContainer ? blockInfo.blockContent.node.attrs : {}),\n })) {\n const propSchema = blockSpec.propSchema;\n\n if (\n attr in propSchema &&\n !(propSchema[attr].default === undefined && value === undefined)\n ) {\n props[attr] = value;\n }\n }\n\n const blockConfig = blockSchema[blockInfo.blockNoteType];\n\n const children: Block<BSchema, I, S>[] = [];\n blockInfo.childContainer?.node.forEach((child) => {\n children.push(\n nodeToBlock(\n child,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n ),\n );\n });\n\n let content: Block<any, any, any>[\"content\"];\n\n if (blockConfig.content === \"inline\") {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n content = contentNodeToInlineContent(\n blockInfo.blockContent.node,\n inlineContentSchema,\n styleSchema,\n );\n } else if (blockConfig.content === \"table\") {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n content = contentNodeToTableContent(\n blockInfo.blockContent.node,\n inlineContentSchema,\n styleSchema,\n );\n } else if (blockConfig.content === \"none\") {\n content = undefined;\n } else {\n throw new UnreachableCaseError(blockConfig.content);\n }\n\n const block = {\n id,\n type: blockConfig.type,\n props,\n content,\n children,\n } as Block<BSchema, I, S>;\n\n blockCache?.set(node, block);\n\n return block;\n}\n\n/**\n * Convert a Prosemirror document to a BlockNote document (array of blocks)\n */\nexport function docToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache = getBlockCache(schema),\n) {\n const blocks: Block<BSchema, I, S>[] = [];\n doc.firstChild!.descendants((node) => {\n blocks.push(\n nodeToBlock(\n node,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n ),\n );\n return false;\n });\n return blocks;\n}\n\n/**\n *\n * Parse a Prosemirror Slice into a BlockNote selection. The prosemirror schema looks like this:\n *\n * <blockGroup>\n * <blockContainer> (main content of block)\n * <p, heading, etc.>\n * <blockGroup> (only if blocks has children)\n * <blockContainer> (child block)\n * <p, heading, etc.>\n * </blockContainer>\n * <blockContainer> (child block 2)\n * <p, heading, etc.>\n * </blockContainer>\n * </blockContainer>\n * </blockGroup>\n * </blockGroup>\n *\n */\nexport function prosemirrorSliceToSlicedBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n slice: Slice,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache: WeakMap<Node, Block<BSchema, I, S>> = getBlockCache(schema),\n): {\n /**\n * The blocks that are included in the selection.\n */\n blocks: Block<BSchema, I, S>[];\n /**\n * If a block was \"cut\" at the start of the selection, this will be the id of the block that was cut.\n */\n blockCutAtStart: string | undefined;\n /**\n * If a block was \"cut\" at the end of the selection, this will be the id of the block that was cut.\n */\n blockCutAtEnd: string | undefined;\n} {\n // console.log(JSON.stringify(slice.toJSON()));\n function processNode(\n node: Node,\n openStart: number,\n openEnd: number,\n ): {\n blocks: Block<BSchema, I, S>[];\n blockCutAtStart: string | undefined;\n blockCutAtEnd: string | undefined;\n } {\n if (node.type.name !== \"blockGroup\") {\n throw new Error(\"unexpected\");\n }\n const blocks: Block<BSchema, I, S>[] = [];\n let blockCutAtStart: string | undefined;\n let blockCutAtEnd: string | undefined;\n\n node.forEach((blockContainer, _offset, index) => {\n if (blockContainer.type.name !== \"blockContainer\") {\n throw new Error(\"unexpected\");\n }\n if (blockContainer.childCount === 0) {\n return;\n }\n if (blockContainer.childCount === 0 || blockContainer.childCount > 2) {\n throw new Error(\n \"unexpected, blockContainer.childCount: \" + blockContainer.childCount,\n );\n }\n\n const isFirstBlock = index === 0;\n const isLastBlock = index === node.childCount - 1;\n\n if (blockContainer.firstChild!.type.name === \"blockGroup\") {\n // this is the parent where a selection starts within one of its children,\n // e.g.:\n // A\n // ├── B\n // selection starts within B, then this blockContainer is A, but we don't care about A\n // so let's descend into B and continue processing\n if (!isFirstBlock) {\n throw new Error(\"unexpected\");\n }\n const ret = processNode(\n blockContainer.firstChild!,\n Math.max(0, openStart - 1),\n isLastBlock ? Math.max(0, openEnd - 1) : 0,\n );\n blockCutAtStart = ret.blockCutAtStart;\n if (isLastBlock) {\n blockCutAtEnd = ret.blockCutAtEnd;\n }\n blocks.push(...ret.blocks);\n return;\n }\n\n const block = nodeToBlock(\n blockContainer,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n );\n const childGroup =\n blockContainer.childCount > 1 ? blockContainer.child(1) : undefined;\n\n let childBlocks: Block<BSchema, I, S>[] = [];\n if (childGroup) {\n const ret = processNode(\n childGroup,\n 0, // TODO: can this be anything other than 0?\n isLastBlock ? Math.max(0, openEnd - 1) : 0,\n );\n childBlocks = ret.blocks;\n if (isLastBlock) {\n blockCutAtEnd = ret.blockCutAtEnd;\n }\n }\n\n if (isLastBlock && !childGroup && openEnd > 1) {\n blockCutAtEnd = block.id;\n }\n\n if (isFirstBlock && openStart > 1) {\n blockCutAtStart = block.id;\n }\n\n blocks.push({\n ...(block as any),\n children: childBlocks,\n });\n });\n\n return { blocks, blockCutAtStart, blockCutAtEnd };\n }\n\n if (slice.content.childCount === 0) {\n return {\n blocks: [],\n blockCutAtStart: undefined,\n blockCutAtEnd: undefined,\n };\n }\n\n if (slice.content.childCount !== 1) {\n throw new Error(\n \"slice must be a single block, did you forget includeParents=true?\",\n );\n }\n\n return processNode(\n slice.content.firstChild!,\n Math.max(slice.openStart - 1, 0),\n Math.max(slice.openEnd - 1, 0),\n );\n}\n","import { KeyboardShortcutCommand, Node } from \"@tiptap/core\";\n\nimport { camelToDataKebab } from \"../../util/string.js\";\nimport { PropSchema, Props } from \"../propTypes.js\";\nimport {\n CustomInlineContentConfig,\n InlineContentConfig,\n InlineContentImplementation,\n InlineContentSchemaFromSpecs,\n InlineContentSpec,\n InlineContentSpecs,\n} from \"./types.js\";\n\n// Function that adds necessary classes and attributes to the `dom` element\n// returned from a custom inline content's 'render' function, to ensure no data\n// is lost on internal copy & paste.\nexport function addInlineContentAttributes<\n IType extends string,\n PSchema extends PropSchema,\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n },\n inlineContentType: IType,\n inlineContentProps: Props<PSchema>,\n propSchema: PSchema,\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} {\n // Sets content type attribute\n element.dom.setAttribute(\"data-inline-content-type\", inlineContentType);\n // Adds props as HTML attributes in kebab-case with \"data-\" prefix. Skips props\n // set to their default values.\n Object.entries(inlineContentProps)\n .filter(([prop, value]) => {\n const spec = propSchema[prop];\n return value !== spec.default;\n })\n .map(([prop, value]) => {\n return [camelToDataKebab(prop), value];\n })\n .forEach(([prop, value]) => element.dom.setAttribute(prop, value));\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return element;\n}\n\n// see https://github.com/TypeCellOS/BlockNote/pull/435\nexport function addInlineContentKeyboardShortcuts<\n T extends CustomInlineContentConfig,\n>(\n config: T,\n): {\n [p: string]: KeyboardShortcutCommand;\n} {\n return {\n Backspace: ({ editor }) => {\n const resolvedPos = editor.state.selection.$from;\n\n return (\n editor.state.selection.empty &&\n resolvedPos.node().type.name === config.type &&\n resolvedPos.parentOffset === 0\n );\n },\n };\n}\n\n// This helper function helps to instantiate a InlineContentSpec with a\n// config and implementation that conform to the type of Config\nexport function createInternalInlineContentSpec<T extends InlineContentConfig>(\n config: T,\n implementation: InlineContentImplementation<T>,\n) {\n return {\n config,\n implementation,\n } satisfies InlineContentSpec<T>;\n}\n\nexport function createInlineContentSpecFromTipTapNode<\n T extends Node,\n P extends PropSchema,\n>(node: T, propSchema: P) {\n return createInternalInlineContentSpec(\n {\n type: node.name as T[\"name\"],\n propSchema,\n content: node.config.content === \"inline*\" ? \"styled\" : \"none\",\n },\n {\n node,\n },\n );\n}\n\nexport function getInlineContentSchemaFromSpecs<T extends InlineContentSpecs>(\n specs: T,\n) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config]),\n ) as InlineContentSchemaFromSpecs<T>;\n}\n","import { Node } from \"@tiptap/core\";\n\nimport { TagParseRule } from \"@tiptap/pm/model\";\nimport { inlineContentToNodes } from \"../../api/nodeConversions/blockToNode.js\";\nimport { nodeToCustomInlineContent } from \"../../api/nodeConversions/nodeToBlock.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { propsToAttributes } from \"../blocks/internal.js\";\nimport { Props } from \"../propTypes.js\";\nimport { StyleSchema } from \"../styles/types.js\";\nimport {\n addInlineContentAttributes,\n addInlineContentKeyboardShortcuts,\n createInlineContentSpecFromTipTapNode,\n} from \"./internal.js\";\nimport {\n CustomInlineContentConfig,\n InlineContentFromConfig,\n InlineContentSpec,\n PartialCustomInlineContentFromConfig,\n} from \"./types.js\";\n\n// TODO: support serialization\n\nexport type CustomInlineContentImplementation<\n T extends CustomInlineContentConfig,\n // B extends BlockSchema,\n // I extends InlineContentSchema,\n S extends StyleSchema,\n> = {\n render: (\n /**\n * The custom inline content to render\n */\n inlineContent: InlineContentFromConfig<T, S>,\n updateInlineContent: (\n update: PartialCustomInlineContentFromConfig<T, S>,\n ) => void,\n /**\n * The BlockNote editor instance\n * This is typed generically. If you want an editor with your custom schema, you need to\n * cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`\n */\n editor: BlockNoteEditor<any, any, S>,\n // (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations\n // or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n // destroy?: () => void;\n };\n};\n\nexport function getInlineContentParseRules(\n config: CustomInlineContentConfig,\n): TagParseRule[] {\n return [\n {\n tag: `[data-inline-content-type=\"${config.type}\"]`,\n contentElement: (element) => {\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.matches(\"[data-editable]\")) {\n return htmlElement;\n }\n\n return htmlElement.querySelector(\"[data-editable]\") || htmlElement;\n },\n },\n ];\n}\n\nexport function createInlineContentSpec<\n T extends CustomInlineContentConfig,\n S extends StyleSchema,\n>(\n inlineContentConfig: T,\n inlineContentImplementation: CustomInlineContentImplementation<T, S>,\n): InlineContentSpec<T> {\n const node = Node.create({\n name: inlineContentConfig.type,\n inline: true,\n group: \"inline\",\n selectable: inlineContentConfig.content === \"styled\",\n atom: inlineContentConfig.content === \"none\",\n content: (inlineContentConfig.content === \"styled\"\n ? \"inline*\"\n : \"\") as T[\"content\"] extends \"styled\" ? \"inline*\" : \"\",\n\n addAttributes() {\n return propsToAttributes(inlineContentConfig.propSchema);\n },\n\n addKeyboardShortcuts() {\n return addInlineContentKeyboardShortcuts(inlineContentConfig);\n },\n\n parseHTML() {\n return getInlineContentParseRules(inlineContentConfig);\n },\n\n renderHTML({ node }) {\n const editor = this.options.editor;\n\n const output = inlineContentImplementation.render(\n nodeToCustomInlineContent(\n node,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n ) as any as InlineContentFromConfig<T, S>, // TODO: fix cast\n () => {\n // No-op\n },\n editor,\n );\n\n return addInlineContentAttributes(\n output,\n inlineContentConfig.type,\n node.attrs as Props<T[\"propSchema\"]>,\n inlineContentConfig.propSchema,\n );\n },\n\n addNodeView() {\n return ({ node, getPos }) => {\n const editor = this.options.editor as BlockNoteEditor<any, any, S>;\n\n const output = inlineContentImplementation.render(\n nodeToCustomInlineContent(\n node,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n ) as any as InlineContentFromConfig<T, S>, // TODO: fix cast\n (update) => {\n if (typeof getPos === \"boolean\") {\n return;\n }\n\n const content = inlineContentToNodes([update], editor.pmSchema);\n\n editor.transact((tr) =>\n tr.replaceWith(getPos(), getPos() + node.nodeSize, content),\n );\n },\n editor,\n );\n\n return addInlineContentAttributes(\n output,\n inlineContentConfig.type,\n node.attrs as Props<T[\"propSchema\"]>,\n inlineContentConfig.propSchema,\n );\n };\n },\n });\n\n return createInlineContentSpecFromTipTapNode(\n node,\n inlineContentConfig.propSchema,\n ) as InlineContentSpec<T>; // TODO: fix cast\n}\n","import { Attributes, Mark } from \"@tiptap/core\";\nimport {\n StyleConfig,\n StyleImplementation,\n StylePropSchema,\n StyleSchemaFromSpecs,\n StyleSpec,\n StyleSpecs,\n} from \"./types.js\";\n\nexport function stylePropsToAttributes(\n propSchema: StylePropSchema,\n): Attributes {\n if (propSchema === \"boolean\") {\n return {};\n }\n return {\n stringValue: {\n default: undefined,\n keepOnSplit: true,\n parseHTML: (element) => element.getAttribute(\"data-value\"),\n renderHTML: (attributes) =>\n attributes.stringValue !== undefined\n ? {\n \"data-value\": attributes.stringValue,\n }\n : {},\n },\n };\n}\n\n// Function that adds necessary classes and attributes to the `dom` element\n// returned from a custom style's 'render' function, to ensure no data is lost\n// on internal copy & paste.\nexport function addStyleAttributes<\n SType extends string,\n PSchema extends StylePropSchema,\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n },\n styleType: SType,\n styleValue: PSchema extends \"boolean\" ? undefined : string,\n propSchema: PSchema,\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} {\n // Sets content type attribute\n element.dom.setAttribute(\"data-style-type\", styleType);\n // Adds style value as an HTML attribute in kebab-case with \"data-\" prefix, if\n // the style takes a string value.\n if (propSchema === \"string\") {\n element.dom.setAttribute(\"data-value\", styleValue as string);\n }\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return element;\n}\n\n// This helper function helps to instantiate a stylespec with a\n// config and implementation that conform to the type of Config\nexport function createInternalStyleSpec<T extends StyleConfig>(\n config: T,\n implementation: StyleImplementation,\n) {\n return {\n config,\n implementation,\n } satisfies StyleSpec<T>;\n}\n\nexport function createStyleSpecFromTipTapMark<\n T extends Mark,\n P extends StylePropSchema,\n>(mark: T, propSchema: P) {\n return createInternalStyleSpec(\n {\n type: mark.name as T[\"name\"],\n propSchema,\n },\n {\n mark,\n },\n );\n}\n\nexport function getStyleSchemaFromSpecs<T extends StyleSpecs>(specs: T) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config]),\n ) as StyleSchemaFromSpecs<T>;\n}\n","import { Mark } from \"@tiptap/core\";\n\nimport { ParseRule } from \"@tiptap/pm/model\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport {\n addStyleAttributes,\n createInternalStyleSpec,\n stylePropsToAttributes,\n} from \"./internal.js\";\nimport { StyleConfig, StyleSpec } from \"./types.js\";\n\nexport type CustomStyleImplementation<T extends StyleConfig> = {\n render: T[\"propSchema\"] extends \"boolean\"\n ? () => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n }\n : (value: string) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n};\n\n// TODO: support serialization\n\nexport function getStyleParseRules(config: StyleConfig): ParseRule[] {\n return [\n {\n tag: `[data-style-type=\"${config.type}\"]`,\n contentElement: (element) => {\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.matches(\"[data-editable]\")) {\n return htmlElement;\n }\n\n return htmlElement.querySelector(\"[data-editable]\") || htmlElement;\n },\n },\n ];\n}\n\nexport function createStyleSpec<T extends StyleConfig>(\n styleConfig: T,\n styleImplementation: CustomStyleImplementation<T>,\n): StyleSpec<T> {\n const mark = Mark.create({\n name: styleConfig.type,\n\n addAttributes() {\n return stylePropsToAttributes(styleConfig.propSchema);\n },\n\n parseHTML() {\n return getStyleParseRules(styleConfig);\n },\n\n renderHTML({ mark }) {\n let renderResult: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n if (styleConfig.propSchema === \"boolean\") {\n // @ts-ignore not sure why this is complaining\n renderResult = styleImplementation.render();\n } else if (styleConfig.propSchema === \"string\") {\n renderResult = styleImplementation.render(mark.attrs.stringValue);\n } else {\n throw new UnreachableCaseError(styleConfig.propSchema);\n }\n\n // const renderResult = styleImplementation.render();\n return addStyleAttributes(\n renderResult,\n styleConfig.type,\n mark.attrs.stringValue,\n styleConfig.propSchema,\n );\n },\n });\n\n return createInternalStyleSpec(styleConfig, {\n mark,\n });\n}\n","import { DefaultBlockSchema } from \"../../../blocks/defaultBlocks.js\";\nimport {\n BlockFromConfigNoChildren,\n PartialTableContent,\n TableCell,\n TableContent,\n} from \"../../../schema/blocks/types.js\";\nimport {\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../../schema/index.js\";\nimport {\n getColspan,\n getRowspan,\n isPartialTableCell,\n mapTableCell,\n} from \"../../../util/table.js\";\n\n/**\n * Here be dragons.\n *\n * Tables are complex because of rowspan and colspan behavior.\n * The majority of this file is concerned with translating between \"relative\" and \"absolute\" indices.\n *\n * The following diagram may help explain the relationship between the different indices:\n *\n * One-based indexing of rows and columns in a table:\n * | 1-1 | 1-2 | 1-3 |\n * | 2-1 | 2-2 | 2-3 |\n * | 3-1 | 3-2 | 3-3 |\n *\n * A complicated table with colspans and rowspans:\n * | 1-1 | 1-2 | 1-2 |\n * | 2-1 | 2-1 | 2-2 |\n * | 2-1 | 2-1 | 3-1 |\n *\n * You can see here that we have:\n * - two cells that contain the value \"1-2\", because it has a colspan of 2.\n * - four cells that contain the value \"2-1\", because it has a rowspan of 2 and a colspan of 2.\n *\n * This would be represented in block note json (roughly) as:\n * [\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"1,1\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1\n * },\n * },\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"1,2\"],\n * \"props\": {\n * \"colspan\": 2,\n * \"rowspan\": 1\n * }\n * }\n * ],\n * },\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"2,1\"],\n * \"props\": {\n * \"colspan\": 2,\n * \"rowspan\": 2\n * }\n * },\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"2,2\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1\n * }\n * ],\n * },\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"3,1\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1,\n * }\n * }\n * ]\n * }\n * ]\n *\n * Which maps cleanly to the following HTML:\n *\n * <table>\n * <tr>\n * <td>1-1</td>\n * <td colspan=\"2\">1-2</td>\n * </tr>\n * <tr>\n * <td rowspan=\"2\" colspan=\"2\">2-1</td>\n * <td>2-2</td>\n * </tr>\n * <tr>\n * <td>3-1</td>\n * </tr>\n * </table>\n *\n * We have a problem though, from the block json, there is no way to tell that the cell \"2-1\" is the second cell in the second row.\n * To resolve this, we created the occupancy grid, which is a grid of all the cells in the table, as though they were only 1x1 cells.\n * See {@link OccupancyGrid} for more information.\n *\n */\n\n/**\n * Relative cell indices are relative to the table block's content.\n *\n * This is a sparse representation of the table and is how HTML and BlockNote JSON represent tables.\n *\n * For example, if we have a table with a rowspan of 2, the second row may only have 1 element in a 2x2 table.\n *\n * ```\n * // Visual representation of the table\n * | 1-1 | 1-2 | // has 2 cells\n * | 1-1 | 2-2 | // has only 1 cell\n * // Relative cell indices\n * [{ row: 1, col: 1, rowspan: 2 }, { row: 1, col: 2 }] // has 2 cells\n * [{ row: 1, col: 2 }] // has only 1 cell\n * ```\n */\nexport type RelativeCellIndices = {\n row: number;\n col: number;\n};\n\n/**\n * Absolute cell indices are relative to the table's layout (it's {@link OccupancyGrid}).\n *\n * It is as though the table is a grid of 1x1 cells, and any colspan or rowspan results in multiple 1x1 cells being occupied.\n *\n * For example, if we have a table with a colspan of 2, it will occupy 2 cells in the layout grid.\n *\n * ```\n * // Visual representation of the table\n * | 1-1 | 1-1 | // has 2 cells\n * | 2-1 | 2-2 | // has 2 cell\n * // Absolute cell indices\n * [{ row: 1, col: 1, colspan: 2 }, { row: 1, col: 2, colspan: 2 }] // has 2 cells\n * [{ row: 1, col: 1 }, { row: 1, col: 2 }] // has 2 cells\n * ```\n */\nexport type AbsoluteCellIndices = {\n row: number;\n col: number;\n};\n\n/**\n * An occupancy grid is a grid of the occupied cells in the table.\n * It is used to track the occupied cells in the table to know where to place the next cell.\n *\n * Since it allows us to resolve cell indices both {@link RelativeCellIndices} and {@link AbsoluteCellIndices}, it is the core data structure for table operations.\n */\ntype OccupancyGrid = (RelativeCellIndices & {\n /**\n * The rowspan of the cell.\n */\n rowspan: number;\n /**\n * The colspan of the cell.\n */\n colspan: number;\n /**\n * The cell.\n */\n cell: TableCell<any, any>;\n})[][];\n\n/**\n * This will return the {@link OccupancyGrid} of the table.\n * By laying out the table as though it were a grid of 1x1 cells, we can easily track where the cells are located (both relatively and absolutely).\n *\n * @returns an {@link OccupancyGrid}\n */\nexport function getTableCellOccupancyGrid(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n): OccupancyGrid {\n const { height, width } = getDimensionsOfTable(block);\n\n /**\n * Create a grid to track occupied cells\n * This is used because rowspans and colspans take up multiple spaces\n * So, we need to track the occupied cells in the grid to know where to place the next cell\n */\n const grid: OccupancyGrid = new Array(height)\n .fill(false)\n .map(() => new Array(width).fill(null));\n\n // Find the next unoccupied cell in the table, row-major order\n const findNextAvailable = (row: number, col: number) => {\n for (let i = row; i < height; i++) {\n for (let j = col; j < width; j++) {\n if (!grid[i][j]) {\n return { row: i, col: j };\n }\n }\n }\n\n throw new Error(\n \"Unable to create occupancy grid for table, no more available cells\",\n );\n };\n\n // Build up the grid, trying to fill in the cells with the correct relative row and column indices\n for (let row = 0; row < block.content.rows.length; row++) {\n for (let col = 0; col < block.content.rows[row].cells.length; col++) {\n const cell = mapTableCell(block.content.rows[row].cells[col]);\n const rowspan = getRowspan(cell);\n const colspan = getColspan(cell);\n\n // Rowspan and colspan complicate things, by taking up multiple cells in the grid\n // We need to iterate over the cells that the rowspan and colspan take up\n // and fill in the grid with the correct relative row and column indices\n const { row: startRow, col: startCol } = findNextAvailable(row, col);\n\n // Fill in the rowspan X colspan cells, starting from the next available cell, with the correct relative row and column indices\n for (let i = startRow; i < startRow + rowspan; i++) {\n for (let j = startCol; j < startCol + colspan; j++) {\n if (grid[i][j]) {\n // The cell is already occupied, the table is malformed\n throw new Error(\n `Unable to create occupancy grid for table, cell at ${i},${j} is already occupied`,\n );\n }\n\n grid[i][j] = {\n row,\n col,\n rowspan,\n colspan,\n cell,\n };\n }\n }\n }\n }\n\n // console.log(grid);\n\n return grid;\n}\n\n/**\n * Given an {@link OccupancyGrid}, this will return the {@link TableContent} rows.\n *\n * @note This will remove duplicates from the occupancy grid. And does no bounds checking for validity of the occupancy grid.\n */\nexport function getTableRowsFromOccupancyGrid(\n occupancyGrid: OccupancyGrid,\n): TableContent<any, any>[\"rows\"] {\n // Because a cell can have a rowspan or colspan, it can occupy multiple cells in the occupancy grid\n // So, we need to remove duplicates from the occupancy grid before we can return the table rows\n const seen = new Set<string>();\n\n return occupancyGrid.map((row) => {\n // Just read out the cells in the occupancy grid, removing duplicates\n return {\n cells: row\n .map((cell) => {\n if (seen.has(cell.row + \":\" + cell.col)) {\n return false;\n }\n seen.add(cell.row + \":\" + cell.col);\n return cell.cell;\n })\n .filter((cell): cell is TableCell<any, any> => cell !== false),\n };\n });\n}\n\n/**\n * This will resolve the relative cell indices within the table block to the absolute cell indices within the table, accounting for colspan and rowspan.\n *\n * @note It will return only the first cell (i.e. top-left) that matches the relative cell indices. To find the other absolute cell indices this cell occupies, you can assume it is the rowspan and colspan number of cells away from the top-left cell.\n *\n * @returns The {@link AbsoluteCellIndices} and the {@link TableCell} at the absolute position.\n */\nexport function getAbsoluteTableCells(\n /**\n * The relative position of the cell in the table.\n */\n relativeCellIndices: RelativeCellIndices,\n /**\n * The table block containing the cell.\n */\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n /**\n * The occupancy grid of the table.\n */\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): AbsoluteCellIndices & {\n cell: TableCell<any, any>;\n} {\n for (let r = 0; r < occupancyGrid.length; r++) {\n for (let c = 0; c < occupancyGrid[r].length; c++) {\n // console.log(r, c, occupancyGrid);\n const cell = occupancyGrid[r][c];\n if (\n cell.row === relativeCellIndices.row &&\n cell.col === relativeCellIndices.col\n ) {\n return { row: r, col: c, cell: cell.cell };\n }\n }\n }\n\n throw new Error(\n `Unable to resolve relative table cell indices for table, cell at ${relativeCellIndices.row},${relativeCellIndices.col} is not occupied`,\n );\n}\n\n/**\n * This will get the dimensions of the table block.\n *\n * @returns The height and width of the table.\n */\nexport function getDimensionsOfTable(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n): {\n /**\n * The number of rows in the table.\n */\n height: number;\n /**\n * The number of columns in the table.\n */\n width: number;\n} {\n // Due to the way we store the table, the height is always the number of rows\n const height = block.content.rows.length;\n\n // Calculating the width is a bit more complex, as it is the maximum width of any row\n let width = 0;\n block.content.rows.forEach((row) => {\n // Find the width of the row by summing the colspan of each cell\n let rowWidth = 0;\n row.cells.forEach((cell) => {\n rowWidth += getColspan(cell);\n });\n\n // Update the width if the row is wider than the current width\n width = Math.max(width, rowWidth);\n });\n\n return { height, width };\n}\n\n/**\n * This will resolve the absolute cell indices within the table block to the relative cell indices within the table, accounting for colspan and rowspan.\n *\n * @returns The {@link RelativeCellIndices} and the {@link TableCell} at the relative position.\n */\nexport function getRelativeTableCells(\n /**\n * The {@link AbsoluteCellIndices} of the cell in the table.\n */\n absoluteCellIndices: AbsoluteCellIndices,\n /**\n * The table block containing the cell.\n */\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n /**\n * The occupancy grid of the table.\n */\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n):\n | (RelativeCellIndices & {\n cell: TableContent<any, any>[\"rows\"][number][\"cells\"][number];\n })\n | undefined {\n const occupancyCell =\n occupancyGrid[absoluteCellIndices.row]?.[absoluteCellIndices.col];\n\n // Double check that the cell can be accessed\n if (!occupancyCell) {\n // The cell is not occupied, so it is invalid\n return undefined;\n }\n\n return {\n row: occupancyCell.row,\n col: occupancyCell.col,\n cell: occupancyCell.cell,\n };\n}\n\n/**\n * This will get all the cells within a relative row of a table block.\n *\n * This method always starts the search for the row at the first column of the table.\n *\n * ```\n * // Visual representation of a table\n * | A | B | C |\n * | | D | E |\n * | F | G | H |\n * // \"A\" has a rowspan of 2\n *\n * // getCellsAtRowHandle(0)\n * // returns [\n * { row: 0, col: 0, cell: \"A\" },\n * { row: 0, col: 1, cell: \"B\" },\n * { row: 0, col: 2, cell: \"C\" },\n * ]\n *\n * // getCellsAtColumnHandle(1)\n * // returns [\n * { row: 1, col: 0, cell: \"F\" },\n * { row: 1, col: 1, cell: \"G\" },\n * { row: 1, col: 2, cell: \"H\" },\n * ]\n * ```\n *\n * As you can see, you may not be able to retrieve all nodes given a relative row index, as cells can span multiple rows.\n *\n * @returns All of the cells associated with the relative row of the table. (All cells that have the same relative row index)\n */\nexport function getCellsAtRowHandle(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeRowIndex: RelativeCellIndices[\"row\"],\n) {\n const occupancyGrid = getTableCellOccupancyGrid(block);\n\n if (relativeRowIndex < 0 || relativeRowIndex >= occupancyGrid.length) {\n return [];\n }\n\n // First need to resolve the relative row index to an absolute row index\n let absoluteRow = 0;\n\n // Jump through the occupied cells ${relativeCellIndices.row} times to find the absolute row position\n for (let i = 0; i < relativeRowIndex; i++) {\n const cell = occupancyGrid[absoluteRow]?.[0];\n\n if (!cell) {\n return [];\n }\n\n // Skip the cells that the rowspan takes up\n absoluteRow += cell.rowspan;\n }\n\n // Then for each column, get the cell at the absolute row index as a relative cell index\n const cells = new Array(occupancyGrid[0].length)\n .fill(false)\n .map((_v, col) => {\n return getRelativeTableCells(\n { row: absoluteRow, col },\n block,\n occupancyGrid,\n );\n })\n .filter(\n (a): a is RelativeCellIndices & { cell: TableCell<any, any> } =>\n a !== undefined,\n );\n\n // Filter out duplicates based on row and col properties\n return cells.filter((cell, index) => {\n return (\n cells.findIndex((c) => c.row === cell.row && c.col === cell.col) === index\n );\n });\n}\n\n/**\n * This will get all the cells within a relative column of a table block.\n *\n * This method always starts the search for the column at the first row of the table.\n *\n * ```\n * // Visual representation of a table\n * | A | B |\n * | C | D | E |\n * | F | G | H |\n * // \"A\" has a colspan of 2\n *\n * // getCellsAtColumnHandle(0)\n * // returns [\n * { row: 0, col: 0, cell: \"A\" },\n * { row: 1, col: 0, cell: \"C\" },\n * { row: 2, col: 0, cell: \"F\" },\n * ]\n *\n * // getCellsAtColumnHandle(1)\n * // returns [\n * { row: 0, col: 1, cell: \"B\" },\n * { row: 1, col: 2, cell: \"E\" },\n * { row: 2, col: 2, cell: \"F\" },\n * ]\n * ```\n *\n * As you can see, you may not be able to retrieve all nodes given a relative column index, as cells can span multiple columns.\n *\n * @returns All of the cells associated with the relative column of the table. (All cells that have the same relative column index)\n */\nexport function getCellsAtColumnHandle(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeColumnIndex: RelativeCellIndices[\"col\"],\n) {\n const occupancyGrid = getTableCellOccupancyGrid(block);\n\n if (\n relativeColumnIndex < 0 ||\n relativeColumnIndex >= occupancyGrid[0].length\n ) {\n return [];\n }\n\n // First need to resolve the relative column index to an absolute column index\n let absoluteCol = 0;\n\n // Now that we've already resolved the absolute row position, we can jump through the occupied cells ${relativeCellIndices.col} times to find the absolute column position\n for (let i = 0; i < relativeColumnIndex; i++) {\n const cell = occupancyGrid[0]?.[absoluteCol];\n\n if (!cell) {\n return [];\n }\n\n // Skip the cells that the colspan takes up\n absoluteCol += cell.colspan;\n }\n\n // Then for each row, get the cell at the absolute column index as a relative cell index\n const cells = new Array(occupancyGrid.length)\n .fill(false)\n .map((_v, row) => {\n return getRelativeTableCells(\n { row, col: absoluteCol },\n block,\n occupancyGrid,\n );\n })\n .filter(\n (a): a is RelativeCellIndices & { cell: TableCell<any, any> } =>\n a !== undefined,\n );\n\n // Filter out duplicates based on row and col properties\n return cells.filter((cell, index) => {\n return (\n cells.findIndex((c) => c.row === cell.row && c.col === cell.col) === index\n );\n });\n}\n\n/**\n * This moves a column from one index to another.\n *\n * @note This is a destructive operation, it will modify the provided {@link OccupancyGrid} in place.\n */\nexport function moveColumn(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n fromColIndex: RelativeCellIndices[\"col\"],\n toColIndex: RelativeCellIndices[\"col\"],\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n // To move cells in a column, we need to layout the whole table\n // and then move the cells accordingly.\n const { col: absoluteSourceCol } = getAbsoluteTableCells(\n {\n row: 0,\n col: fromColIndex,\n },\n block,\n occupancyGrid,\n );\n const { col: absoluteTargetCol } = getAbsoluteTableCells(\n {\n row: 0,\n col: toColIndex,\n },\n block,\n occupancyGrid,\n );\n\n /**\n * Currently, this function assumes that the caller has already checked that the source and target columns are valid.\n * Such as by using {@link canColumnBeDraggedInto}. In the future, we may want to have the move logic be smarter\n * and handle invalid column indices in some way.\n */\n occupancyGrid.forEach((row) => {\n // Move the cell to the target column\n const [sourceCell] = row.splice(absoluteSourceCol, 1);\n row.splice(absoluteTargetCol, 0, sourceCell);\n });\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This moves a row from one index to another.\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function moveRow(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n fromRowIndex: RelativeCellIndices[\"row\"],\n toRowIndex: RelativeCellIndices[\"row\"],\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n // To move cells in a column, we need to layout the whole table\n // and then move the cells accordingly.\n const { row: absoluteSourceRow } = getAbsoluteTableCells(\n {\n row: fromRowIndex,\n col: 0,\n },\n block,\n occupancyGrid,\n );\n const { row: absoluteTargetRow } = getAbsoluteTableCells(\n {\n row: toRowIndex,\n col: 0,\n },\n block,\n occupancyGrid,\n );\n\n /**\n * Currently, this function assumes that the caller has already checked that the source and target rows are valid.\n * Such as by using {@link canRowBeDraggedInto}. In the future, we may want to have the move logic be smarter\n * and handle invalid row indices in some way.\n */\n const [sourceRow] = occupancyGrid.splice(absoluteSourceRow, 1);\n occupancyGrid.splice(absoluteTargetRow, 0, sourceRow);\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This will check if a cell is empty.\n *\n * @returns True if the cell is empty, false otherwise.\n */\nfunction isCellEmpty(\n cell:\n | PartialTableContent<any, any>[\"rows\"][number][\"cells\"][number]\n | undefined,\n): boolean {\n if (!cell) {\n return true;\n }\n if (isPartialTableCell(cell)) {\n return isCellEmpty(cell.content);\n } else if (typeof cell === \"string\") {\n return cell.length === 0;\n } else if (Array.isArray(cell)) {\n return cell.every((c) =>\n typeof c === \"string\"\n ? c.length === 0\n : isStyledTextInlineContent(c)\n ? c.text.length === 0\n : isPartialLinkInlineContent(c)\n ? typeof c.content === \"string\"\n ? c.content.length === 0\n : c.content.every((s) => s.text.length === 0)\n : false,\n );\n } else {\n return false;\n }\n}\n\n/**\n * This will remove empty rows or columns from the table.\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function cropEmptyRowsOrColumns(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n removeEmpty: \"columns\" | \"rows\",\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n if (removeEmpty === \"columns\") {\n // strips empty columns on the right\n let emptyColsOnRight = 0;\n for (\n let cellIndex = occupancyGrid[0].length - 1;\n cellIndex >= 0;\n cellIndex--\n ) {\n const isEmpty = occupancyGrid.every(\n (row) =>\n isCellEmpty(row[cellIndex].cell) && row[cellIndex].colspan === 1,\n );\n if (!isEmpty) {\n break;\n }\n\n emptyColsOnRight++;\n }\n\n for (let i = occupancyGrid.length - 1; i >= 0; i--) {\n // We maintain at least one cell, even if all the cells are empty\n const cellsToRemove = Math.max(\n occupancyGrid[i].length - emptyColsOnRight,\n 1,\n );\n occupancyGrid[i] = occupancyGrid[i].slice(0, cellsToRemove);\n }\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n }\n\n // strips empty rows at the bottom\n let emptyRowsOnBottom = 0;\n for (let rowIndex = occupancyGrid.length - 1; rowIndex >= 0; rowIndex--) {\n const isEmpty = occupancyGrid[rowIndex].every(\n (cell) => isCellEmpty(cell.cell) && cell.rowspan === 1,\n );\n if (!isEmpty) {\n break;\n }\n\n emptyRowsOnBottom++;\n }\n\n // We maintain at least one row, even if all the rows are empty\n const rowsToRemove = Math.min(emptyRowsOnBottom, occupancyGrid.length - 1);\n\n occupancyGrid.splice(occupancyGrid.length - rowsToRemove, rowsToRemove);\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This will add a specified number of rows or columns to the table (filling with empty cells).\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function addRowsOrColumns(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n addType: \"columns\" | \"rows\",\n /**\n * The number of rows or columns to add.\n *\n * @note if negative, it will remove rows or columns.\n */\n numToAdd: number,\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n const { width, height } = getDimensionsOfTable(block);\n\n if (addType === \"columns\") {\n // Add empty columns to the right\n occupancyGrid.forEach((row, rowIndex) => {\n if (numToAdd >= 0) {\n for (let i = 0; i < numToAdd; i++) {\n row.push({\n row: rowIndex,\n col: Math.max(...row.map((r) => r.col)) + 1,\n rowspan: 1,\n colspan: 1,\n cell: mapTableCell(\"\"),\n });\n }\n } else {\n // Remove columns on the right\n row.splice(width + numToAdd, -1 * numToAdd);\n }\n });\n } else {\n if (numToAdd > 0) {\n // Add empty rows to the bottom\n for (let i = 0; i < numToAdd; i++) {\n const newRow = new Array(width).fill(null).map((_, colIndex) => ({\n row: height + i,\n col: colIndex,\n rowspan: 1,\n colspan: 1,\n cell: mapTableCell(\"\"),\n }));\n occupancyGrid.push(newRow);\n }\n } else if (numToAdd < 0) {\n // Remove rows at the bottom\n occupancyGrid.splice(height + numToAdd, -1 * numToAdd);\n }\n }\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * Checks if a row can be safely dropped at the target row index without splitting merged cells.\n */\nexport function canRowBeDraggedInto(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n draggingIndex: RelativeCellIndices[\"row\"],\n targetRowIndex: RelativeCellIndices[\"row\"],\n) {\n // Check cells at the target row\n const targetCells = getCellsAtRowHandle(block, targetRowIndex);\n\n // If no cells have rowspans > 1, dragging is always allowed\n const hasMergedCells = targetCells.some((cell) => getRowspan(cell.cell) > 1);\n if (!hasMergedCells) {\n return true;\n }\n\n let endRowIndex = targetRowIndex;\n let startRowIndex = targetRowIndex;\n targetCells.forEach((cell) => {\n const rowspan = getRowspan(cell.cell);\n endRowIndex = Math.max(endRowIndex, cell.row + rowspan - 1);\n startRowIndex = Math.min(startRowIndex, cell.row);\n });\n\n // Check the direction of the drag\n const isDraggingDown = draggingIndex < targetRowIndex;\n\n // Allow dragging only at the start/end of merged cells\n // Otherwise, the target row was within a merged cell which we don't allow\n return isDraggingDown\n ? targetRowIndex === endRowIndex\n : targetRowIndex === startRowIndex;\n}\n\n/**\n * Checks if a column can be safely dropped at the target column index without splitting merged cells.\n */\nexport function canColumnBeDraggedInto(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n draggingIndex: RelativeCellIndices[\"col\"],\n targetColumnIndex: RelativeCellIndices[\"col\"],\n) {\n // Check cells at the target column\n const targetCells = getCellsAtColumnHandle(block, targetColumnIndex);\n\n // If no cells have colspans > 1, dragging is always allowed\n const hasMergedCells = targetCells.some((cell) => getColspan(cell.cell) > 1);\n if (!hasMergedCells) {\n return true;\n }\n\n let endColumnIndex = targetColumnIndex;\n let startColumnIndex = targetColumnIndex;\n targetCells.forEach((cell) => {\n const colspan = getColspan(cell.cell);\n endColumnIndex = Math.max(endColumnIndex, cell.col + colspan - 1);\n startColumnIndex = Math.min(startColumnIndex, cell.col);\n });\n\n // Check the direction of the drag\n const isDraggingRight = draggingIndex < targetColumnIndex;\n\n // Allow dragging only at the start/end of merged cells\n // Otherwise, the target column was within a merged cell which we don't allow\n return isDraggingRight\n ? targetColumnIndex === endColumnIndex\n : targetColumnIndex === startColumnIndex;\n}\n\n/**\n * Checks if two cells are in the same column.\n *\n * @returns True if the cells are in the same column, false otherwise.\n */\nexport function areInSameColumn(\n from: RelativeCellIndices,\n to: RelativeCellIndices,\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n) {\n // Table indices are relative to the table, so we need to resolve the absolute cell indices\n const anchorAbsoluteCellIndices = getAbsoluteTableCells(from, block);\n\n // Table indices are relative to the table, so we need to resolve the absolute cell indices\n const headAbsoluteCellIndices = getAbsoluteTableCells(to, block);\n\n // Compare the column indices to determine the merge direction\n return anchorAbsoluteCellIndices.col === headAbsoluteCellIndices.col;\n}\n","import { Attrs, Fragment, Mark, Node, Schema } from \"@tiptap/pm/model\";\n\nimport UniqueID from \"../../extensions/UniqueID/UniqueID.js\";\nimport type {\n InlineContentSchema,\n PartialCustomInlineContentFromConfig,\n PartialInlineContent,\n PartialLink,\n PartialTableContent,\n StyleSchema,\n StyledText,\n} from \"../../schema\";\n\nimport type { PartialBlock } from \"../../blocks/defaultBlocks\";\nimport {\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types.js\";\nimport { getColspan, isPartialTableCell } from \"../../util/table.js\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport { getAbsoluteTableCells } from \"../blockManipulation/tables/tables.js\";\nimport { getStyleSchema } from \"../pmUtil.js\";\n\n/**\n * Convert a StyledText inline element to a\n * prosemirror text node with the appropriate marks\n */\nfunction styledTextToNodes<T extends StyleSchema>(\n styledText: StyledText<T>,\n schema: Schema,\n styleSchema: T,\n blockType?: string,\n): Node[] {\n const marks: Mark[] = [];\n\n for (const [style, value] of Object.entries(styledText.styles || {})) {\n const config = styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n\n if (config.propSchema === \"boolean\") {\n marks.push(schema.mark(style));\n } else if (config.propSchema === \"string\") {\n marks.push(schema.mark(style, { stringValue: value }));\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n\n const parseHardBreaks = !blockType || !schema.nodes[blockType].spec.code;\n\n if (!parseHardBreaks) {\n return styledText.text.length > 0\n ? [schema.text(styledText.text, marks)]\n : [];\n }\n\n return (\n styledText.text\n // Splits text & line breaks.\n .split(/(\\n)/g)\n // If the content ends with a line break, an empty string is added to the\n // end, which this removes.\n .filter((text) => text.length > 0)\n // Converts text & line breaks to nodes.\n .map((text) => {\n if (text === \"\\n\") {\n return schema.nodes[\"hardBreak\"].createChecked();\n } else {\n return schema.text(text, marks);\n }\n })\n );\n}\n\n/**\n * Converts a Link inline content element to\n * prosemirror text nodes with the appropriate marks\n */\nfunction linkToNodes(\n link: PartialLink<StyleSchema>,\n schema: Schema,\n styleSchema: StyleSchema,\n): Node[] {\n const linkMark = schema.marks.link.create({\n href: link.href,\n });\n\n return styledTextArrayToNodes(link.content, schema, styleSchema).map(\n (node) => {\n if (node.type.name === \"text\") {\n return node.mark([...node.marks, linkMark]);\n }\n\n if (node.type.name === \"hardBreak\") {\n return node;\n }\n throw new Error(\"unexpected node type\");\n },\n );\n}\n\n/**\n * Converts an array of StyledText inline content elements to\n * prosemirror text nodes with the appropriate marks\n */\nfunction styledTextArrayToNodes<S extends StyleSchema>(\n content: string | StyledText<S>[],\n schema: Schema,\n styleSchema: S,\n blockType?: string,\n): Node[] {\n const nodes: Node[] = [];\n\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextToNodes(\n { type: \"text\", text: content, styles: {} },\n schema,\n styleSchema,\n blockType,\n ),\n );\n return nodes;\n }\n\n for (const styledText of content) {\n nodes.push(\n ...styledTextToNodes(styledText, schema, styleSchema, blockType),\n );\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function inlineContentToNodes<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockContent: PartialInlineContent<I, S>,\n schema: Schema,\n blockType?: string,\n styleSchema: S = getStyleSchema(schema),\n): Node[] {\n const nodes: Node[] = [];\n\n for (const content of blockContent) {\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextArrayToNodes(content, schema, styleSchema, blockType),\n );\n } else if (isPartialLinkInlineContent(content)) {\n nodes.push(...linkToNodes(content, schema, styleSchema));\n } else if (isStyledTextInlineContent(content)) {\n nodes.push(\n ...styledTextArrayToNodes([content], schema, styleSchema, blockType),\n );\n } else {\n nodes.push(\n blockOrInlineContentToContentNode(content, schema, styleSchema),\n );\n }\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function tableContentToNodes<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tableContent: PartialTableContent<I, S>,\n schema: Schema,\n styleSchema: StyleSchema = getStyleSchema(schema),\n): Node[] {\n const rowNodes: Node[] = [];\n // Header rows and columns are used to determine the type of the cell\n // If headerRows is 1, then the first row is a header row\n const headerRows = new Array(tableContent.headerRows ?? 0).fill(true);\n // If headerCols is 1, then the first column is a header column\n const headerCols = new Array(tableContent.headerCols ?? 0).fill(true);\n\n const columnWidths: (number | undefined)[] = tableContent.columnWidths ?? [];\n\n for (let rowIndex = 0; rowIndex < tableContent.rows.length; rowIndex++) {\n const row = tableContent.rows[rowIndex];\n const columnNodes: Node[] = [];\n const isHeaderRow = headerRows[rowIndex];\n for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex++) {\n const cell = row.cells[cellIndex];\n const isHeaderCol = headerCols[cellIndex];\n /**\n * The attributes of the cell to apply to the node\n */\n const attrs: Attrs | undefined = undefined;\n /**\n * The content of the cell to apply to the node\n */\n let content: Fragment | Node | readonly Node[] | null = null;\n\n // Colwidths are absolutely referenced to the table, so we need to resolve the relative cell index to the absolute cell index\n const absoluteCellIndex = getAbsoluteTableCells(\n {\n row: rowIndex,\n col: cellIndex,\n },\n { type: \"table\", content: tableContent } as any,\n );\n\n // Assume the column width is the width of the cell at the absolute cell index\n let colwidth: (number | undefined)[] | null = columnWidths[\n absoluteCellIndex.col\n ]\n ? [columnWidths[absoluteCellIndex.col]]\n : null;\n\n if (!cell) {\n // No-op\n } else if (typeof cell === \"string\") {\n content = schema.text(cell);\n } else if (isPartialTableCell(cell)) {\n if (cell.content) {\n content = inlineContentToNodes(\n cell.content,\n schema,\n \"tableParagraph\",\n styleSchema,\n );\n }\n const colspan = getColspan(cell);\n\n if (colspan > 1) {\n // If the cell has a > 1 colspan, we need to get the column width for each cell in the span\n colwidth = new Array(colspan).fill(false).map((_, i) => {\n // Starting from the absolute column index, get the column width for each cell in the span\n return columnWidths[absoluteCellIndex.col + i] ?? undefined;\n });\n }\n } else {\n content = inlineContentToNodes(\n cell,\n schema,\n \"tableParagraph\",\n styleSchema,\n );\n }\n\n const cellNode = schema.nodes[\n isHeaderCol || isHeaderRow ? \"tableHeader\" : \"tableCell\"\n ].createChecked(\n {\n ...(isPartialTableCell(cell) ? cell.props : {}),\n colwidth,\n },\n schema.nodes[\"tableParagraph\"].createChecked(attrs, content),\n );\n columnNodes.push(cellNode);\n }\n\n const rowNode = schema.nodes[\"tableRow\"].createChecked({}, columnNodes);\n rowNodes.push(rowNode);\n }\n return rowNodes;\n}\n\nfunction blockOrInlineContentToContentNode(\n block:\n | PartialBlock<any, any, any>\n | PartialCustomInlineContentFromConfig<any, any>,\n schema: Schema,\n styleSchema: StyleSchema,\n) {\n let contentNode: Node;\n let type = block.type;\n\n // TODO: needed? came from previous code\n if (type === undefined) {\n type = \"paragraph\";\n }\n\n if (!schema.nodes[type]) {\n throw new Error(`node type ${type} not found in schema`);\n }\n\n if (!block.content) {\n contentNode = schema.nodes[type].createChecked(block.props);\n } else if (typeof block.content === \"string\") {\n const nodes = inlineContentToNodes(\n [block.content],\n schema,\n type,\n styleSchema,\n );\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else if (Array.isArray(block.content)) {\n const nodes = inlineContentToNodes(\n block.content,\n schema,\n type,\n styleSchema,\n );\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else if (block.content.type === \"tableContent\") {\n const nodes = tableContentToNodes(block.content, schema, styleSchema);\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n return contentNode;\n}\n\n/**\n * Converts a BlockNote block to a Prosemirror node.\n */\nexport function blockToNode(\n block: PartialBlock<any, any, any>,\n schema: Schema,\n styleSchema: StyleSchema = getStyleSchema(schema),\n) {\n let id = block.id;\n\n if (id === undefined) {\n id = UniqueID.options.generateID();\n }\n\n const children: Node[] = [];\n\n if (block.children) {\n for (const child of block.children) {\n children.push(blockToNode(child, schema, styleSchema));\n }\n }\n\n const isBlockContent =\n !block.type || // can happen if block.type is not defined (this should create the default node)\n schema.nodes[block.type].isInGroup(\"blockContent\");\n\n if (isBlockContent) {\n // Blocks with a type that matches \"blockContent\" group always need to be wrapped in a blockContainer\n\n const contentNode = blockOrInlineContentToContentNode(\n block,\n schema,\n styleSchema,\n );\n\n const groupNode =\n children.length > 0\n ? schema.nodes[\"blockGroup\"].createChecked({}, children)\n : undefined;\n\n return schema.nodes[\"blockContainer\"].createChecked(\n {\n id: id,\n ...block.props,\n },\n groupNode ? [contentNode, groupNode] : contentNode,\n );\n } else if (schema.nodes[block.type].isInGroup(\"bnBlock\")) {\n // this is a bnBlock node like Column or ColumnList that directly translates to a prosemirror node\n return schema.nodes[block.type].createChecked(\n {\n id: id,\n ...block.props,\n },\n children,\n );\n } else {\n throw new Error(\n `block type ${block.type} doesn't match blockContent or bnBlock group`,\n );\n }\n}\n","import {\n combineTransactionSteps,\n findChildrenInRange,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport type { Node } from \"prosemirror-model\";\nimport type { Transaction } from \"prosemirror-state\";\nimport {\n Block,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n DefaultStyleSchema,\n} from \"../blocks/defaultBlocks.js\";\nimport type { BlockSchema } from \"../schema/index.js\";\nimport type { InlineContentSchema } from \"../schema/inlineContent/types.js\";\nimport type { StyleSchema } from \"../schema/styles/types.js\";\nimport { nodeToBlock } from \"./nodeConversions/nodeToBlock.js\";\nimport { getPmSchema } from \"./pmUtil.js\";\n\n/**\n * Get a TipTap node by id\n */\nexport function getNodeById(\n id: string,\n doc: Node,\n): { node: Node; posBeforeNode: number } | undefined {\n let targetNode: Node | undefined = undefined;\n let posBeforeNode: number | undefined = undefined;\n\n doc.firstChild!.descendants((node, pos) => {\n // Skips traversing nodes after node with target ID has been found.\n if (targetNode) {\n return false;\n }\n\n // Keeps traversing nodes if block with target ID has not been found.\n if (!isNodeBlock(node) || node.attrs.id !== id) {\n return true;\n }\n\n targetNode = node;\n posBeforeNode = pos + 1;\n\n return false;\n });\n\n if (targetNode === undefined || posBeforeNode === undefined) {\n return undefined;\n }\n\n return {\n node: targetNode,\n posBeforeNode: posBeforeNode,\n };\n}\n\nexport function isNodeBlock(node: Node): boolean {\n return node.type.isInGroup(\"bnBlock\");\n}\n\n/**\n * This attributes the changes to a specific source.\n */\nexport type BlockChangeSource =\n | {\n /**\n * When an event is triggered by the local user, the source is \"local\".\n * This is the default source.\n */\n type: \"local\";\n }\n | {\n /**\n * When an event is triggered by a paste operation, the source is \"paste\".\n */\n type: \"paste\";\n }\n | {\n /**\n * When an event is triggered by a drop operation, the source is \"drop\".\n */\n type: \"drop\";\n }\n | {\n /**\n * When an event is triggered by an undo or redo operation, the source is \"undo\" or \"redo\".\n * @note Y.js undo/redo are not differentiated.\n */\n type: \"undo\" | \"redo\" | \"undo-redo\";\n }\n | {\n /**\n * When an event is triggered by a remote user, the source is \"remote\".\n */\n type: \"yjs-remote\";\n };\n\nexport type BlocksChanged<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema,\n> = Array<\n {\n /**\n * The affected block.\n */\n block: Block<BSchema, ISchema, SSchema>;\n /**\n * The source of the change.\n */\n source: BlockChangeSource;\n } & (\n | {\n type: \"insert\" | \"delete\";\n /**\n * Insert and delete changes don't have a previous block.\n */\n prevBlock: undefined;\n }\n | {\n type: \"update\";\n /**\n * The block before the update.\n */\n prevBlock: Block<BSchema, ISchema, SSchema>;\n }\n )\n>;\n\n/**\n * Compares two blocks, ignoring their children.\n * Returns true if the blocks are different (excluding children).\n */\nfunction areBlocksDifferentExcludingChildren<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema,\n>(\n block1: Block<BSchema, ISchema, SSchema>,\n block2: Block<BSchema, ISchema, SSchema>,\n): boolean {\n // TODO use an actual diff algorithm\n // Compare all properties except children\n return (\n block1.id !== block2.id ||\n block1.type !== block2.type ||\n JSON.stringify(block1.props) !== JSON.stringify(block2.props) ||\n JSON.stringify(block1.content) !== JSON.stringify(block2.content)\n );\n}\n\n/**\n * Get the blocks that were changed by a transaction.\n * @param transaction The transaction to get the changes from.\n * @param editor The editor to get the changes from.\n * @returns The blocks that were changed by the transaction.\n */\nexport function getBlocksChangedByTransaction<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema,\n>(\n transaction: Transaction,\n appendedTransactions: Transaction[] = [],\n): BlocksChanged<BSchema, ISchema, SSchema> {\n let source: BlockChangeSource = { type: \"local\" };\n\n if (transaction.getMeta(\"paste\")) {\n source = { type: \"paste\" };\n } else if (transaction.getMeta(\"uiEvent\") === \"drop\") {\n source = { type: \"drop\" };\n } else if (transaction.getMeta(\"history$\")) {\n source = {\n type: transaction.getMeta(\"history$\").redo ? \"redo\" : \"undo\",\n };\n } else if (transaction.getMeta(\"y-sync$\")) {\n if (transaction.getMeta(\"y-sync$\").isUndoRedoOperation) {\n source = {\n type: \"undo-redo\",\n };\n } else {\n source = {\n type: \"yjs-remote\",\n };\n }\n }\n\n // Get affected blocks before and after the change\n const pmSchema = getPmSchema(transaction);\n const combinedTransaction = combineTransactionSteps(transaction.before, [\n transaction,\n ...appendedTransactions,\n ]);\n\n const changedRanges = getChangedRanges(combinedTransaction);\n const prevAffectedBlocks = changedRanges\n .flatMap((range) => {\n return findChildrenInRange(\n combinedTransaction.before,\n range.oldRange,\n isNodeBlock,\n );\n })\n .map(({ node }) => nodeToBlock(node, pmSchema));\n\n const nextAffectedBlocks = changedRanges\n .flatMap((range) => {\n return findChildrenInRange(\n combinedTransaction.doc,\n range.newRange,\n isNodeBlock,\n );\n })\n .map(({ node }) => nodeToBlock(node, pmSchema));\n\n const nextBlocks = new Map(\n nextAffectedBlocks.map((block) => {\n return [block.id, block];\n }),\n );\n const prevBlocks = new Map(\n prevAffectedBlocks.map((block) => {\n return [block.id, block];\n }),\n );\n\n const changes: BlocksChanged<BSchema, ISchema, SSchema> = [];\n\n // Inserted blocks are blocks that were not in the previous state and are in the next state\n for (const [id, block] of nextBlocks) {\n if (!prevBlocks.has(id)) {\n changes.push({\n type: \"insert\",\n block,\n source,\n prevBlock: undefined,\n });\n }\n }\n\n // Deleted blocks are blocks that were in the previous state but not in the next state\n for (const [id, block] of prevBlocks) {\n if (!nextBlocks.has(id)) {\n changes.push({\n type: \"delete\",\n block,\n source,\n prevBlock: undefined,\n });\n }\n }\n\n // Updated blocks are blocks that were in the previous state and are in the next state\n for (const [id, block] of nextBlocks) {\n if (prevBlocks.has(id)) {\n const prevBlock = prevBlocks.get(id)!;\n\n // Only include the update if the block itself changed (excluding children)\n if (areBlocksDifferentExcludingChildren(prevBlock, block)) {\n changes.push({\n type: \"update\",\n block,\n prevBlock,\n source,\n });\n }\n }\n }\n\n return changes;\n}\n","import { Fragment, Slice } from \"prosemirror-model\";\nimport type { Transaction } from \"prosemirror-state\";\nimport { ReplaceStep } from \"prosemirror-transform\";\nimport { Block, PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema/index.js\";\nimport { blockToNode } from \"../../../nodeConversions/blockToNode.js\";\nimport { nodeToBlock } from \"../../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../../nodeUtil.js\";\nimport { getPmSchema } from \"../../../pmUtil.js\";\n\nexport function insertBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tr: Transaction,\n blocksToInsert: PartialBlock<BSchema, I, S>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" = \"before\",\n): Block<BSchema, I, S>[] {\n const id =\n typeof referenceBlock === \"string\" ? referenceBlock : referenceBlock.id;\n const pmSchema = getPmSchema(tr);\n const nodesToInsert = blocksToInsert.map((block) =>\n blockToNode(block, pmSchema),\n );\n\n const posInfo = getNodeById(id, tr.doc);\n if (!posInfo) {\n throw new Error(`Block with ID ${id} not found`);\n }\n\n let pos = posInfo.posBeforeNode;\n if (placement === \"after\") {\n pos += posInfo.node.nodeSize;\n }\n\n tr.step(\n new ReplaceStep(pos, pos, new Slice(Fragment.from(nodesToInsert), 0, 0)),\n );\n\n // Now that the `PartialBlock`s have been converted to nodes, we can\n // re-convert them into full `Block`s.\n const insertedBlocks = nodesToInsert.map((node) =>\n nodeToBlock(node, pmSchema),\n );\n\n return insertedBlocks;\n}\n","import type { Node } from \"prosemirror-model\";\nimport type { Transaction } from \"prosemirror-state\";\nimport type { Block, PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport type {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema/index.js\";\nimport { blockToNode } from \"../../../nodeConversions/blockToNode.js\";\nimport { nodeToBlock } from \"../../../nodeConversions/nodeToBlock.js\";\nimport { getPmSchema } from \"../../../pmUtil.js\";\n\nexport function removeAndInsertBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tr: Transaction,\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema, I, S>[],\n): {\n insertedBlocks: Block<BSchema, I, S>[];\n removedBlocks: Block<BSchema, I, S>[];\n} {\n const pmSchema = getPmSchema(tr);\n // Converts the `PartialBlock`s to ProseMirror nodes to insert them into the\n // document.\n const nodesToInsert: Node[] = blocksToInsert.map((block) =>\n blockToNode(block, pmSchema),\n );\n\n const idsOfBlocksToRemove = new Set<string>(\n blocksToRemove.map((block) =>\n typeof block === \"string\" ? block : block.id,\n ),\n );\n const removedBlocks: Block<BSchema, I, S>[] = [];\n\n const idOfFirstBlock =\n typeof blocksToRemove[0] === \"string\"\n ? blocksToRemove[0]\n : blocksToRemove[0].id;\n let removedSize = 0;\n\n tr.doc.descendants((node, pos) => {\n // Skips traversing nodes after all target blocks have been removed.\n if (idsOfBlocksToRemove.size === 0) {\n return false;\n }\n\n // Keeps traversing nodes if block with target ID has not been found.\n if (\n !node.type.isInGroup(\"bnBlock\") ||\n !idsOfBlocksToRemove.has(node.attrs.id)\n ) {\n return true;\n }\n\n // Saves the block that is being deleted.\n removedBlocks.push(nodeToBlock(node, pmSchema));\n idsOfBlocksToRemove.delete(node.attrs.id);\n\n if (blocksToInsert.length > 0 && node.attrs.id === idOfFirstBlock) {\n const oldDocSize = tr.doc.nodeSize;\n tr.insert(pos, nodesToInsert);\n const newDocSize = tr.doc.nodeSize;\n\n removedSize += oldDocSize - newDocSize;\n }\n\n const oldDocSize = tr.doc.nodeSize;\n // Checks if the block is the only child of its parent. In this case, we\n // need to delete the parent `blockGroup` node instead of just the\n // `blockContainer`.\n const $pos = tr.doc.resolve(pos - removedSize);\n if (\n $pos.node().type.name === \"blockGroup\" &&\n $pos.node($pos.depth - 1).type.name !== \"doc\" &&\n $pos.node().childCount === 1\n ) {\n tr.delete($pos.before(), $pos.after());\n } else {\n tr.delete(pos - removedSize, pos - removedSize + node.nodeSize);\n }\n const newDocSize = tr.doc.nodeSize;\n removedSize += oldDocSize - newDocSize;\n\n return false;\n });\n\n // Throws an error if now all blocks could be found.\n if (idsOfBlocksToRemove.size > 0) {\n const notFoundIds = [...idsOfBlocksToRemove].join(\"\\n\");\n\n throw Error(\n \"Blocks with the following IDs could not be found in the editor: \" +\n notFoundIds,\n );\n }\n\n // Converts the nodes created from `blocksToInsert` into full `Block`s.\n const insertedBlocks = nodesToInsert.map((node) =>\n nodeToBlock(node, pmSchema),\n );\n\n return { insertedBlocks, removedBlocks };\n}","import {\n Fragment,\n type NodeType,\n type Node as PMNode,\n Slice,\n} from \"prosemirror-model\";\nimport type { Transaction } from \"prosemirror-state\";\n\nimport { ReplaceStep, Transform } from \"prosemirror-transform\";\nimport type { Block, PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport type {\n BlockIdentifier,\n BlockSchema,\n} from \"../../../../schema/blocks/types.js\";\nimport type { InlineContentSchema } from \"../../../../schema/inlineContent/types.js\";\nimport type { StyleSchema } from \"../../../../schema/styles/types.js\";\nimport { UnreachableCaseError } from \"../../../../util/typescript.js\";\nimport {\n type BlockInfo,\n getBlockInfoFromResolvedPos,\n} from \"../../../getBlockInfoFromPos.js\";\nimport {\n blockToNode,\n inlineContentToNodes,\n tableContentToNodes,\n} from \"../../../nodeConversions/blockToNode.js\";\nimport { nodeToBlock } from \"../../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../../nodeUtil.js\";\nimport { getPmSchema } from \"../../../pmUtil.js\";\n\n// for compatibility with tiptap. TODO: remove as we want to remove dependency on tiptap command interface\nexport const updateBlockCommand = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n posBeforeBlock: number,\n block: PartialBlock<BSchema, I, S>,\n) => {\n return ({\n tr,\n dispatch,\n }: {\n tr: Transaction;\n dispatch?: () => void;\n }): boolean => {\n if (dispatch) {\n updateBlockTr(tr, posBeforeBlock, block);\n }\n return true;\n };\n};\n\nexport function updateBlockTr<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tr: Transform,\n posBeforeBlock: number,\n block: PartialBlock<BSchema, I, S>,\n replaceFromPos?: number,\n replaceToPos?: number,\n) {\n const blockInfo = getBlockInfoFromResolvedPos(tr.doc.resolve(posBeforeBlock));\n\n const pmSchema = getPmSchema(tr);\n\n if (\n replaceFromPos !== undefined &&\n replaceToPos !== undefined &&\n replaceFromPos > replaceToPos\n ) {\n throw new Error(\"Invalid replaceFromPos or replaceToPos\");\n }\n\n // Adds blockGroup node with child blocks if necessary.\n\n const oldNodeType = pmSchema.nodes[blockInfo.blockNoteType];\n const newNodeType = pmSchema.nodes[block.type || blockInfo.blockNoteType];\n const newBnBlockNodeType = newNodeType.isInGroup(\"bnBlock\")\n ? newNodeType\n : pmSchema.nodes[\"blockContainer\"];\n\n if (blockInfo.isBlockContainer && newNodeType.isInGroup(\"blockContent\")) {\n const replaceFromOffset =\n replaceFromPos !== undefined &&\n replaceFromPos > blockInfo.blockContent.beforePos &&\n replaceFromPos < blockInfo.blockContent.afterPos\n ? replaceFromPos - blockInfo.blockContent.beforePos - 1\n : undefined;\n\n const replaceToOffset =\n replaceToPos !== undefined &&\n replaceToPos > blockInfo.blockContent.beforePos &&\n replaceToPos < blockInfo.blockContent.afterPos\n ? replaceToPos - blockInfo.blockContent.beforePos - 1\n : undefined;\n\n updateChildren(block, tr, blockInfo);\n // The code below determines the new content of the block.\n // or \"keep\" to keep as-is\n updateBlockContentNode(\n block,\n tr,\n oldNodeType,\n newNodeType,\n blockInfo,\n replaceFromOffset,\n replaceToOffset,\n );\n } else if (!blockInfo.isBlockContainer && newNodeType.isInGroup(\"bnBlock\")) {\n updateChildren(block, tr, blockInfo);\n // old node was a bnBlock type (like column or columnList) and new block as well\n // No op, we just update the bnBlock below (at end of function) and have already updated the children\n } else {\n // switching from blockContainer to non-blockContainer or v.v.\n // currently breaking for column slash menu items converting empty block\n // to column.\n\n // currently, we calculate the new node and replace the entire node with the desired new node.\n // for this, we do a nodeToBlock on the existing block to get the children.\n // it would be cleaner to use a ReplaceAroundStep, but this is a bit simpler and it's quite an edge case\n const existingBlock = nodeToBlock(blockInfo.bnBlock.node, pmSchema);\n tr.replaceWith(\n blockInfo.bnBlock.beforePos,\n blockInfo.bnBlock.afterPos,\n blockToNode(\n {\n children: existingBlock.children, // if no children are passed in, use existing children\n ...block,\n },\n pmSchema,\n ),\n );\n\n return;\n }\n\n // Adds all provided props as attributes to the parent blockContainer node too, and also preserves existing\n // attributes.\n tr.setNodeMarkup(blockInfo.bnBlock.beforePos, newBnBlockNodeType, {\n ...blockInfo.bnBlock.node.attrs,\n ...block.props,\n });\n}\n\nfunction updateBlockContentNode<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n block: PartialBlock<BSchema, I, S>,\n tr: Transform,\n oldNodeType: NodeType,\n newNodeType: NodeType,\n blockInfo: {\n childContainer?:\n | { node: PMNode; beforePos: number; afterPos: number }\n | undefined;\n blockContent: { node: PMNode; beforePos: number; afterPos: number };\n },\n replaceFromOffset?: number,\n replaceToOffset?: number,\n) {\n const pmSchema = getPmSchema(tr);\n let content: PMNode[] | \"keep\" = \"keep\";\n\n // Has there been any custom content provided?\n if (block.content) {\n if (typeof block.content === \"string\") {\n // Adds a single text node with no marks to the content.\n content = inlineContentToNodes(\n [block.content],\n pmSchema,\n newNodeType.name,\n );\n } else if (Array.isArray(block.content)) {\n // Adds a text node with the provided styles converted into marks to the content,\n // for each InlineContent object.\n content = inlineContentToNodes(block.content, pmSchema, newNodeType.name);\n } else if (block.content.type === \"tableContent\") {\n content = tableContentToNodes(block.content, pmSchema);\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n } else {\n // no custom content has been provided, use existing content IF possible\n // Since some block types contain inline content and others don't,\n // we either need to call setNodeMarkup to just update type &\n // attributes, or replaceWith to replace the whole blockContent.\n if (oldNodeType.spec.content === \"\") {\n // keep old content, because it's empty anyway and should be compatible with\n // any newContentType\n } else if (newNodeType.spec.content !== oldNodeType.spec.content) {\n // the content type changed, replace the previous content\n content = [];\n } else {\n // keep old content, because the content type is the same and should be compatible\n }\n }\n\n // Now, changes the blockContent node type and adds the provided props\n // as attributes. Also preserves all existing attributes that are\n // compatible with the new type.\n //\n // Use either setNodeMarkup or replaceWith depending on whether the\n // content is being replaced or not.\n if (content === \"keep\") {\n // use setNodeMarkup to only update the type and attributes\n tr.setNodeMarkup(blockInfo.blockContent.beforePos, newNodeType, {\n ...blockInfo.blockContent.node.attrs,\n ...block.props,\n });\n } else if (replaceFromOffset !== undefined || replaceToOffset !== undefined) {\n // first update markup of the containing node\n tr.setNodeMarkup(blockInfo.blockContent.beforePos, newNodeType, {\n ...blockInfo.blockContent.node.attrs,\n ...block.props,\n });\n\n const start =\n blockInfo.blockContent.beforePos + 1 + (replaceFromOffset ?? 0);\n const end =\n blockInfo.blockContent.beforePos +\n 1 +\n (replaceToOffset ?? blockInfo.blockContent.node.content.size);\n\n // for content like table cells (where the blockcontent has nested PM nodes),\n // we need to figure out the correct openStart and openEnd for the slice when replacing\n\n const contentDepth = tr.doc.resolve(blockInfo.blockContent.beforePos).depth;\n const startDepth = tr.doc.resolve(start).depth;\n const endDepth = tr.doc.resolve(end).depth;\n\n tr.replace(\n start,\n end,\n new Slice(\n Fragment.from(content),\n startDepth - contentDepth - 1,\n endDepth - contentDepth - 1,\n ),\n );\n } else {\n // use replaceWith to replace the content and the block itself\n // also reset the selection since replacing the block content\n // sets it to the next block.\n tr.replaceWith(\n blockInfo.blockContent.beforePos,\n blockInfo.blockContent.afterPos,\n newNodeType.createChecked(\n {\n ...blockInfo.blockContent.node.attrs,\n ...block.props,\n },\n content,\n ),\n );\n }\n}\n\nfunction updateChildren<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(block: PartialBlock<BSchema, I, S>, tr: Transform, blockInfo: BlockInfo) {\n const pmSchema = getPmSchema(tr);\n if (block.children !== undefined && block.children.length > 0) {\n const childNodes = block.children.map((child) => {\n return blockToNode(child, pmSchema);\n });\n\n // Checks if a blockGroup node already exists.\n if (blockInfo.childContainer) {\n // Replaces all child nodes in the existing blockGroup with the ones created earlier.\n\n // use a replacestep to avoid the fitting algorithm\n tr.step(\n new ReplaceStep(\n blockInfo.childContainer.beforePos + 1,\n blockInfo.childContainer.afterPos - 1,\n new Slice(Fragment.from(childNodes), 0, 0),\n ),\n );\n } else {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n // Inserts a new blockGroup containing the child nodes created earlier.\n tr.insert(\n blockInfo.blockContent.afterPos,\n pmSchema.nodes[\"blockGroup\"].createChecked({}, childNodes),\n );\n }\n }\n}\n\nexport function updateBlock<\n BSchema extends BlockSchema = any,\n I extends InlineContentSchema = any,\n S extends StyleSchema = any,\n>(\n tr: Transaction,\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema, I, S>,\n replaceFromPos?: number,\n replaceToPos?: number,\n): Block<BSchema, I, S> {\n const id =\n typeof blockToUpdate === \"string\" ? blockToUpdate : blockToUpdate.id;\n const posInfo = getNodeById(id, tr.doc);\n if (!posInfo) {\n throw new Error(`Block with ID ${id} not found`);\n }\n\n updateBlockTr(\n tr,\n posInfo.posBeforeNode,\n update,\n replaceFromPos,\n replaceToPos,\n );\n\n const blockContainerNode = tr.doc\n .resolve(posInfo.posBeforeNode + 1) // TODO: clean?\n .node();\n\n const pmSchema = getPmSchema(tr);\n return nodeToBlock(blockContainerNode, pmSchema);\n}\n","import { DOMSerializer, Fragment } from \"prosemirror-model\";\n\nimport { PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema/index.js\";\nimport { UnreachableCaseError } from \"../../../../util/typescript.js\";\nimport {\n inlineContentToNodes,\n tableContentToNodes,\n} from \"../../../nodeConversions/blockToNode.js\";\n\nfunction addAttributesAndRemoveClasses(element: HTMLElement) {\n // Removes all BlockNote specific class names.\n const className =\n Array.from(element.classList).filter(\n (className) => !className.startsWith(\"bn-\"),\n ) || [];\n\n if (className.length > 0) {\n element.className = className.join(\" \");\n } else {\n element.removeAttribute(\"class\");\n }\n}\n\nexport function serializeInlineContentExternalHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<any, I, S>,\n blockContent: PartialBlock<BSchema, I, S>[\"content\"],\n serializer: DOMSerializer,\n options?: { document?: Document },\n) {\n let nodes: any;\n\n // TODO: reuse function from nodeconversions?\n if (!blockContent) {\n throw new Error(\"blockContent is required\");\n } else if (typeof blockContent === \"string\") {\n nodes = inlineContentToNodes([blockContent], editor.pmSchema);\n } else if (Array.isArray(blockContent)) {\n nodes = inlineContentToNodes(blockContent, editor.pmSchema);\n } else if (blockContent.type === \"tableContent\") {\n nodes = tableContentToNodes(blockContent, editor.pmSchema);\n } else {\n throw new UnreachableCaseError(blockContent.type);\n }\n\n // We call the prosemirror serializer here because it handles Marks and Inline Content nodes nicely.\n // If we'd want to support custom serialization or externalHTML for Inline Content, we'd have to implement\n // a custom serializer here.\n const dom = serializer.serializeFragment(Fragment.from(nodes), options);\n\n if (dom.nodeType === 1 /* Node.ELEMENT_NODE */) {\n addAttributesAndRemoveClasses(dom as HTMLElement);\n }\n\n return dom;\n}\n\n/**\n * TODO: there's still quite some logic that handles getting and filtering properties,\n * we should make sure the `toExternalHTML` methods of default blocks actually handle this,\n * instead of the serializer.\n */\nfunction serializeBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n fragment: DocumentFragment,\n editor: BlockNoteEditor<BSchema, I, S>,\n block: PartialBlock<BSchema, I, S>,\n serializer: DOMSerializer,\n orderedListItemBlockTypes: Set<string>,\n unorderedListItemBlockTypes: Set<string>,\n options?: { document?: Document },\n) {\n const doc = options?.document ?? document;\n const BC_NODE = editor.pmSchema.nodes[\"blockContainer\"];\n\n let props = block.props;\n // set default props in case we were passed a partial block\n if (!block.props) {\n props = {};\n for (const [name, spec] of Object.entries(\n editor.schema.blockSchema[block.type as any].propSchema,\n )) {\n if (spec.default !== undefined) {\n (props as any)[name] = spec.default;\n }\n }\n }\n\n const bc = BC_NODE.spec?.toDOM?.(\n BC_NODE.create({\n id: block.id,\n ...props,\n }),\n ) as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n // the container node is just used as a workaround to get some block-level attributes.\n // we should change toExternalHTML so that this is not necessary\n const attrs = Array.from(bc.dom.attributes);\n\n const ret = editor.blockImplementations[\n block.type as any\n ].implementation.toExternalHTML({ ...block, props } as any, editor as any);\n\n const elementFragment = doc.createDocumentFragment();\n if (ret.dom.classList.contains(\"bn-block-content\")) {\n const blockContentDataAttributes = [\n ...attrs,\n ...Array.from(ret.dom.attributes),\n ].filter(\n (attr) =>\n attr.name.startsWith(\"data\") &&\n attr.name !== \"data-content-type\" &&\n attr.name !== \"data-file-block\" &&\n attr.name !== \"data-node-view-wrapper\" &&\n attr.name !== \"data-node-type\" &&\n attr.name !== \"data-id\" &&\n attr.name !== \"data-index\" &&\n attr.name !== \"data-editable\",\n );\n\n // ret.dom = ret.dom.firstChild! as any;\n for (const attr of blockContentDataAttributes) {\n (ret.dom.firstChild! as HTMLElement).setAttribute(attr.name, attr.value);\n }\n\n addAttributesAndRemoveClasses(ret.dom.firstChild! as HTMLElement);\n elementFragment.append(...Array.from(ret.dom.childNodes));\n } else {\n elementFragment.append(ret.dom);\n }\n\n if (ret.contentDOM && block.content) {\n const ic = serializeInlineContentExternalHTML(\n editor,\n block.content as any, // TODO\n serializer,\n options,\n );\n\n ret.contentDOM.appendChild(ic);\n }\n\n let listType = undefined;\n if (orderedListItemBlockTypes.has(block.type!)) {\n listType = \"OL\";\n } else if (unorderedListItemBlockTypes.has(block.type!)) {\n listType = \"UL\";\n }\n\n if (listType) {\n if (fragment.lastChild?.nodeName !== listType) {\n const list = doc.createElement(listType);\n\n if (listType === \"OL\" && props?.start && props?.start !== 1) {\n list.setAttribute(\"start\", props.start + \"\");\n }\n fragment.append(list);\n }\n const li = doc.createElement(\"li\");\n li.append(elementFragment);\n fragment.lastChild!.appendChild(li);\n } else {\n fragment.append(elementFragment);\n }\n\n if (block.children && block.children.length > 0) {\n const childFragment = doc.createDocumentFragment();\n serializeBlocksToFragment(\n childFragment,\n editor,\n block.children,\n serializer,\n orderedListItemBlockTypes,\n unorderedListItemBlockTypes,\n options,\n );\n if (\n fragment.lastChild?.nodeName === \"UL\" ||\n fragment.lastChild?.nodeName === \"OL\"\n ) {\n // add nested lists to the last list item\n while (\n childFragment.firstChild?.nodeName === \"UL\" ||\n childFragment.firstChild?.nodeName === \"OL\"\n ) {\n fragment.lastChild!.lastChild!.appendChild(childFragment.firstChild!);\n }\n }\n\n if (editor.pmSchema.nodes[block.type as any].isInGroup(\"blockContent\")) {\n // default \"blockContainer\" style blocks are flattened (no \"nested block\" support) for externalHTML, so append the child fragment to the outer fragment\n fragment.append(childFragment);\n } else {\n // for columns / column lists, do use nesting\n ret.contentDOM?.append(childFragment);\n }\n }\n}\n\nconst serializeBlocksToFragment = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n fragment: DocumentFragment,\n editor: BlockNoteEditor<BSchema, I, S>,\n blocks: PartialBlock<BSchema, I, S>[],\n serializer: DOMSerializer,\n orderedListItemBlockTypes: Set<string>,\n unorderedListItemBlockTypes: Set<string>,\n options?: { document?: Document },\n) => {\n for (const block of blocks) {\n serializeBlock(\n fragment,\n editor,\n block,\n serializer,\n orderedListItemBlockTypes,\n unorderedListItemBlockTypes,\n options,\n );\n }\n};\n\nexport const serializeBlocksExternalHTML = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n blocks: PartialBlock<BSchema, I, S>[],\n serializer: DOMSerializer,\n orderedListItemBlockTypes: Set<string>,\n unorderedListItemBlockTypes: Set<string>,\n options?: { document?: Document },\n) => {\n const doc = options?.document ?? document;\n const fragment = doc.createDocumentFragment();\n\n serializeBlocksToFragment(\n fragment,\n editor,\n blocks,\n serializer,\n orderedListItemBlockTypes,\n unorderedListItemBlockTypes,\n options,\n );\n return fragment;\n};\n","import { DOMSerializer, Schema } from \"prosemirror-model\";\n\nimport { PartialBlock } from \"../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContent,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport {\n serializeBlocksExternalHTML,\n serializeInlineContentExternalHTML,\n} from \"./util/serializeBlocksExternalHTML.js\";\n\n// Used to export BlockNote blocks and ProseMirror nodes to HTML for use outside\n// the editor. Blocks are exported using the `toExternalHTML` method in their\n// `blockSpec`, or `toInternalHTML` if `toExternalHTML` is not defined.\n//\n// The HTML created by this serializer is different to what's rendered by the\n// editor to the DOM. This also means that data is likely to be lost when\n// converting back to original blocks. The differences in the output HTML are:\n// 1. It doesn't include the `blockGroup` and `blockContainer` wrappers meaning\n// that nesting is not preserved for non-list-item blocks.\n// 2. `li` items in the output HTML are wrapped in `ul` or `ol` elements.\n// 3. While nesting for list items is preserved, other types of blocks nested\n// inside a list are un-nested and a new list is created after them.\n// 4. The HTML is wrapped in a single `div` element.\n\n// Needs to be sync because it's used in drag handler event (SideMenuPlugin)\n// Ideally, call `await initializeESMDependencies()` before calling this function\nexport const createExternalHTMLExporter = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>,\n) => {\n const serializer = DOMSerializer.fromSchema(schema);\n\n return {\n exportBlocks: (\n blocks: PartialBlock<BSchema, I, S>[],\n options: { document?: Document },\n ) => {\n const html = serializeBlocksExternalHTML(\n editor,\n blocks,\n serializer,\n new Set<string>([\"numberedListItem\"]),\n new Set<string>([\"bulletListItem\", \"checkListItem\"]),\n options,\n );\n const div = document.createElement(\"div\");\n div.append(html);\n return div.innerHTML;\n },\n\n exportInlineContent: (\n inlineContent: InlineContent<I, S>[],\n options: { document?: Document },\n ) => {\n const domFragment = serializeInlineContentExternalHTML(\n editor,\n inlineContent as any,\n serializer,\n options,\n );\n\n const parent = document.createElement(\"div\");\n parent.append(domFragment.cloneNode(true));\n\n return parent.innerHTML;\n },\n };\n};\n","import { DOMSerializer, Fragment } from \"prosemirror-model\";\n\nimport { PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema/index.js\";\nimport { UnreachableCaseError } from \"../../../../util/typescript.js\";\nimport {\n inlineContentToNodes,\n tableContentToNodes,\n} from \"../../../nodeConversions/blockToNode.js\";\n\nexport function serializeInlineContentInternalHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<any, I, S>,\n blockContent: PartialBlock<BSchema, I, S>[\"content\"],\n serializer: DOMSerializer,\n blockType?: string,\n options?: { document?: Document },\n) {\n let nodes: any;\n\n // TODO: reuse function from nodeconversions?\n if (!blockContent) {\n throw new Error(\"blockContent is required\");\n } else if (typeof blockContent === \"string\") {\n nodes = inlineContentToNodes([blockContent], editor.pmSchema, blockType);\n } else if (Array.isArray(blockContent)) {\n nodes = inlineContentToNodes(blockContent, editor.pmSchema, blockType);\n } else if (blockContent.type === \"tableContent\") {\n nodes = tableContentToNodes(blockContent, editor.pmSchema);\n } else {\n throw new UnreachableCaseError(blockContent.type);\n }\n\n // We call the prosemirror serializer here because it handles Marks and Inline Content nodes nicely.\n // If we'd want to support custom serialization or externalHTML for Inline Content, we'd have to implement\n // a custom serializer here.\n const dom = serializer.serializeFragment(Fragment.from(nodes), options);\n\n return dom;\n}\n\nfunction serializeBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n block: PartialBlock<BSchema, I, S>,\n serializer: DOMSerializer,\n listIndex: number,\n options?: { document?: Document },\n) {\n const BC_NODE = editor.pmSchema.nodes[\"blockContainer\"];\n\n let props = block.props;\n // set default props in case we were passed a partial block\n if (!block.props) {\n props = {};\n for (const [name, spec] of Object.entries(\n editor.schema.blockSchema[block.type as any].propSchema,\n )) {\n if (spec.default !== undefined) {\n (props as any)[name] = spec.default;\n }\n }\n }\n\n const impl = editor.blockImplementations[block.type as any].implementation;\n const ret = impl.toInternalHTML({ ...block, props } as any, editor as any);\n\n if (block.type === \"numberedListItem\") {\n // This is a workaround to make sure there's a list index set.\n // Normally, this is set on the internal prosemirror nodes by the NumberedListIndexingPlugin,\n // but:\n // - (a) this information is not available on the Blocks passed to the serializer. (we only have access to BlockNote Blocks)\n // - (b) the NumberedListIndexingPlugin might not even have run, because we can manually call blocksToFullHTML\n // with blocks that are not part of the active document\n ret.dom.setAttribute(\"data-index\", listIndex.toString());\n }\n\n if (ret.contentDOM && block.content) {\n const ic = serializeInlineContentInternalHTML(\n editor,\n block.content as any, // TODO\n serializer,\n block.type,\n options,\n );\n ret.contentDOM.appendChild(ic);\n }\n\n const pmType = editor.pmSchema.nodes[block.type as any];\n\n if (pmType.isInGroup(\"bnBlock\")) {\n if (block.children && block.children.length > 0) {\n const fragment = serializeBlocks(\n editor,\n block.children,\n serializer,\n options,\n );\n\n ret.contentDOM?.append(fragment);\n }\n return ret.dom;\n }\n\n // wrap the block in a blockContainer\n const bc = BC_NODE.spec?.toDOM?.(\n BC_NODE.create({\n id: block.id,\n ...props,\n }),\n ) as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n bc.contentDOM?.appendChild(ret.dom);\n\n if (block.children && block.children.length > 0) {\n bc.contentDOM?.appendChild(\n serializeBlocksInternalHTML(editor, block.children, serializer, options),\n );\n }\n return bc.dom;\n}\n\nfunction serializeBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n blocks: PartialBlock<BSchema, I, S>[],\n serializer: DOMSerializer,\n options?: { document?: Document },\n) {\n const doc = options?.document ?? document;\n const fragment = doc.createDocumentFragment();\n\n let listIndex = 0;\n for (const block of blocks) {\n if (block.type === \"numberedListItem\") {\n listIndex++;\n } else {\n listIndex = 0;\n }\n const blockDOM = serializeBlock(\n editor,\n block,\n serializer,\n listIndex,\n options,\n );\n fragment.appendChild(blockDOM);\n }\n\n return fragment;\n}\n\nexport const serializeBlocksInternalHTML = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n blocks: PartialBlock<BSchema, I, S>[],\n serializer: DOMSerializer,\n options?: { document?: Document },\n) => {\n const BG_NODE = editor.pmSchema.nodes[\"blockGroup\"];\n\n const bg = BG_NODE.spec!.toDOM!(BG_NODE.create({})) as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n const fragment = serializeBlocks(editor, blocks, serializer, options);\n\n bg.contentDOM?.appendChild(fragment);\n\n return bg.dom;\n};\n","import { DOMSerializer, Schema } from \"prosemirror-model\";\nimport { PartialBlock } from \"../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { serializeBlocksInternalHTML } from \"./util/serializeBlocksInternalHTML.js\";\n// Used to serialize BlockNote blocks and ProseMirror nodes to HTML without\n// losing data. Blocks are exported using the `toInternalHTML` method in their\n// `blockSpec`.\n//\n// The HTML created by this serializer is the same as what's rendered by the\n// editor to the DOM. This means that it retains the same structure as the\n// editor, including the `blockGroup` and `blockContainer` wrappers. This also\n// means that it can be converted back to the original blocks without any data\n// loss.\nexport const createInternalHTMLSerializer = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>,\n) => {\n const serializer = DOMSerializer.fromSchema(schema);\n\n return {\n serializeBlocks: (\n blocks: PartialBlock<BSchema, I, S>[],\n options: { document?: Document },\n ) => {\n return serializeBlocksInternalHTML(editor, blocks, serializer, options)\n .outerHTML;\n },\n };\n};\n","export const parseFigureElement = (\n figureElement: HTMLElement,\n targetTag: string,\n) => {\n const targetElement = figureElement.querySelector(\n targetTag,\n ) as HTMLElement | null;\n if (!targetElement) {\n return undefined;\n }\n\n const captionElement = figureElement.querySelector(\"figcaption\");\n const caption = captionElement?.textContent ?? undefined;\n\n return { targetElement, caption };\n};\n","import type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport { BlockFromConfig, FileBlockConfig } from \"../../../../schema/index.js\";\n\nexport const createAddFileButton = (\n block: BlockFromConfig<FileBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n buttonText?: string,\n buttonIcon?: HTMLElement,\n) => {\n const addFileButton = document.createElement(\"div\");\n addFileButton.className = \"bn-add-file-button\";\n\n const addFileButtonIcon = document.createElement(\"div\");\n addFileButtonIcon.className = \"bn-add-file-button-icon\";\n if (buttonIcon) {\n addFileButtonIcon.appendChild(buttonIcon);\n } else {\n addFileButtonIcon.innerHTML =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3 8L9.00319 2H19.9978C20.5513 2 21 2.45531 21 2.9918V21.0082C21 21.556 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5501 3 20.9932V8ZM10 4V9H5V20H19V4H10Z\"></path></svg>';\n }\n addFileButton.appendChild(addFileButtonIcon);\n\n const addFileButtonText = document.createElement(\"p\");\n addFileButtonText.className = \"bn-add-file-button-text\";\n addFileButtonText.innerHTML =\n buttonText || editor.dictionary.file_blocks.file.add_button_text;\n addFileButton.appendChild(addFileButtonText);\n\n // Prevents focus from moving to the button.\n const addFileButtonMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n };\n // Opens the file toolbar.\n const addFileButtonClickHandler = () => {\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: block,\n }),\n );\n };\n addFileButton.addEventListener(\n \"mousedown\",\n addFileButtonMouseDownHandler,\n true,\n );\n addFileButton.addEventListener(\"click\", addFileButtonClickHandler, true);\n\n return {\n dom: addFileButton,\n destroy: () => {\n addFileButton.removeEventListener(\n \"mousedown\",\n addFileButtonMouseDownHandler,\n true,\n );\n addFileButton.removeEventListener(\n \"click\",\n addFileButtonClickHandler,\n true,\n );\n },\n };\n};\n","import { BlockFromConfig, FileBlockConfig } from \"../../../../schema/index.js\";\n\nexport const FILE_ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3 8L9.00319 2H19.9978C20.5513 2 21 2.45531 21 2.9918V21.0082C21 21.556 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5501 3 20.9932V8ZM10 4V9H5V20H19V4H10Z\"></path></svg>`;\n\nexport const createFileNameWithIcon = (\n block: BlockFromConfig<FileBlockConfig, any, any>,\n): { dom: HTMLElement; destroy?: () => void } => {\n const file = document.createElement(\"div\");\n file.className = \"bn-file-name-with-icon\";\n\n const icon = document.createElement(\"div\");\n icon.className = \"bn-file-icon\";\n icon.innerHTML = FILE_ICON_SVG;\n file.appendChild(icon);\n\n const fileName = document.createElement(\"p\");\n fileName.className = \"bn-file-name\";\n fileName.textContent = block.props.name;\n file.appendChild(fileName);\n\n return {\n dom: file,\n };\n};\n","import type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n BlockSchemaWithBlock,\n FileBlockConfig,\n} from \"../../../../schema/index.js\";\nimport { createAddFileButton } from \"./createAddFileButton.js\";\nimport { createFileNameWithIcon } from \"./createFileNameWithIcon.js\";\n\nexport const createFileBlockWrapper = (\n block: BlockFromConfig<FileBlockConfig, any, any>,\n editor: BlockNoteEditor<\n BlockSchemaWithBlock<FileBlockConfig[\"type\"], FileBlockConfig>,\n any,\n any\n >,\n element?: { dom: HTMLElement; destroy?: () => void },\n buttonText?: string,\n buttonIcon?: HTMLElement,\n) => {\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"bn-file-block-content-wrapper\";\n\n // Show the add file button if the file has not been uploaded yet. Change to\n // show a loader if a file upload for the block begins.\n if (block.props.url === \"\") {\n const addFileButton = createAddFileButton(\n block,\n editor,\n buttonText,\n buttonIcon,\n );\n wrapper.appendChild(addFileButton.dom);\n\n const destroyUploadStartHandler = editor.onUploadStart((blockId) => {\n if (blockId === block.id) {\n wrapper.removeChild(addFileButton.dom);\n\n const loading = document.createElement(\"div\");\n loading.className = \"bn-file-loading-preview\";\n loading.textContent = \"Loading...\";\n wrapper.appendChild(loading);\n }\n });\n\n return {\n dom: wrapper,\n destroy: () => {\n destroyUploadStartHandler();\n addFileButton.destroy();\n },\n };\n }\n\n const ret: { dom: HTMLElement; destroy?: () => void } = { dom: wrapper };\n\n // Show the file preview, or the file name and icon.\n if (block.props.showPreview === false || !element) {\n // Show file name and icon.\n const fileNameWithIcon = createFileNameWithIcon(block);\n wrapper.appendChild(fileNameWithIcon.dom);\n\n ret.destroy = () => {\n fileNameWithIcon.destroy?.();\n };\n } else {\n // Show file preview.\n wrapper.appendChild(element.dom);\n }\n\n // Show the caption if there is one.\n if (block.props.caption) {\n const caption = document.createElement(\"p\");\n caption.className = \"bn-file-caption\";\n caption.textContent = block.props.caption;\n wrapper.appendChild(caption);\n }\n\n return ret;\n};\n","export const createFigureWithCaption = (\n element: HTMLElement,\n caption: string,\n) => {\n const figure = document.createElement(\"figure\");\n const captionElement = document.createElement(\"figcaption\");\n captionElement.textContent = caption;\n\n figure.appendChild(element);\n figure.appendChild(captionElement);\n\n return { dom: figure };\n};\n","export const createLinkWithCaption = (\n element: HTMLElement,\n caption: string,\n) => {\n const wrapper = document.createElement(\"div\");\n const fileCaption = document.createElement(\"p\");\n fileCaption.textContent = caption;\n\n wrapper.appendChild(element);\n wrapper.appendChild(fileCaption);\n\n return {\n dom: wrapper,\n };\n};\n","export const parseAudioElement = (audioElement: HTMLAudioElement) => {\n const url = audioElement.src || undefined;\n\n return { url };\n};\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n createBlockSpec,\n FileBlockConfig,\n Props,\n PropSchema,\n} from \"../../schema/index.js\";\nimport { defaultProps } from \"../defaultProps.js\";\n\nimport { parseFigureElement } from \"../FileBlockContent/helpers/parse/parseFigureElement.js\";\nimport { createFileBlockWrapper } from \"../FileBlockContent/helpers/render/createFileBlockWrapper.js\";\nimport { createFigureWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.js\";\nimport { createLinkWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.js\";\nimport { parseAudioElement } from \"./parseAudioElement.js\";\n\nexport const FILE_AUDIO_ICON_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M2 16.0001H5.88889L11.1834 20.3319C11.2727 20.405 11.3846 20.4449 11.5 20.4449C11.7761 20.4449 12 20.2211 12 19.9449V4.05519C12 3.93977 11.9601 3.8279 11.887 3.73857C11.7121 3.52485 11.3971 3.49335 11.1834 3.66821L5.88889 8.00007H2C1.44772 8.00007 1 8.44778 1 9.00007V15.0001C1 15.5524 1.44772 16.0001 2 16.0001ZM23 12C23 15.292 21.5539 18.2463 19.2622 20.2622L17.8445 18.8444C19.7758 17.1937 21 14.7398 21 12C21 9.26016 19.7758 6.80629 17.8445 5.15557L19.2622 3.73779C21.5539 5.75368 23 8.70795 23 12ZM18 12C18 10.0883 17.106 8.38548 15.7133 7.28673L14.2842 8.71584C15.3213 9.43855 16 10.64 16 12C16 13.36 15.3213 14.5614 14.2842 15.2841L15.7133 16.7132C17.106 15.6145 18 13.9116 18 12Z\"></path></svg>';\n\nexport const audioPropSchema = {\n backgroundColor: defaultProps.backgroundColor,\n // File name.\n name: {\n default: \"\" as const,\n },\n // File url.\n url: {\n default: \"\" as const,\n },\n // File caption.\n caption: {\n default: \"\" as const,\n },\n\n showPreview: {\n default: true,\n },\n} satisfies PropSchema;\n\nexport const audioBlockConfig = {\n type: \"audio\" as const,\n propSchema: audioPropSchema,\n content: \"none\",\n isFileBlock: true,\n fileBlockAccept: [\"audio/*\"],\n} satisfies FileBlockConfig;\n\nexport const audioRender = (\n block: BlockFromConfig<typeof audioBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n) => {\n const icon = document.createElement(\"div\");\n icon.innerHTML = FILE_AUDIO_ICON_SVG;\n\n const audio = document.createElement(\"audio\");\n audio.className = \"bn-audio\";\n if (editor.resolveFileUrl) {\n editor.resolveFileUrl(block.props.url).then((downloadUrl) => {\n audio.src = downloadUrl;\n });\n } else {\n audio.src = block.props.url;\n }\n audio.controls = true;\n audio.contentEditable = \"false\";\n audio.draggable = false;\n\n return createFileBlockWrapper(\n block,\n editor,\n { dom: audio },\n editor.dictionary.file_blocks.audio.add_button_text,\n icon.firstElementChild as HTMLElement,\n );\n};\n\nexport const audioParse = (\n element: HTMLElement,\n): Partial<Props<typeof audioBlockConfig.propSchema>> | undefined => {\n if (element.tagName === \"AUDIO\") {\n // Ignore if parent figure has already been parsed.\n if (element.closest(\"figure\")) {\n return undefined;\n }\n\n return parseAudioElement(element as HTMLAudioElement);\n }\n\n if (element.tagName === \"FIGURE\") {\n const parsedFigure = parseFigureElement(element, \"audio\");\n if (!parsedFigure) {\n return undefined;\n }\n\n const { targetElement, caption } = parsedFigure;\n\n return {\n ...parseAudioElement(targetElement as HTMLAudioElement),\n caption,\n };\n }\n\n return undefined;\n};\n\nexport const audioToExternalHTML = (\n block: BlockFromConfig<typeof audioBlockConfig, any, any>,\n) => {\n if (!block.props.url) {\n const div = document.createElement(\"p\");\n div.textContent = \"Add audio\";\n\n return {\n dom: div,\n };\n }\n\n let audio;\n if (block.props.showPreview) {\n audio = document.createElement(\"audio\");\n audio.src = block.props.url;\n } else {\n audio = document.createElement(\"a\");\n audio.href = block.props.url;\n audio.textContent = block.props.name || block.props.url;\n }\n\n if (block.props.caption) {\n if (block.props.showPreview) {\n return createFigureWithCaption(audio, block.props.caption);\n } else {\n return createLinkWithCaption(audio, block.props.caption);\n }\n }\n\n return {\n dom: audio,\n };\n};\n\nexport const AudioBlock = createBlockSpec(audioBlockConfig, {\n render: audioRender,\n parse: audioParse,\n toExternalHTML: audioToExternalHTML,\n});\n","import type { HighlighterGeneric } from \"@shikijs/types\";\nimport { InputRule, isTextSelection } from \"@tiptap/core\";\nimport { TextSelection } from \"@tiptap/pm/state\";\nimport { Parser, createHighlightPlugin } from \"prosemirror-highlight\";\nimport { createParser } from \"prosemirror-highlight/shiki\";\nimport { BlockNoteEditor } from \"../../index.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\n\nexport type CodeBlockOptions = {\n /**\n * Whether to indent lines with a tab when the user presses `Tab` in a code block.\n *\n * @default true\n */\n indentLineWithTab?: boolean;\n /**\n * The default language to use for code blocks.\n *\n * @default \"text\"\n */\n defaultLanguage?: string;\n /**\n * The languages that are supported in the editor.\n *\n * @example\n * {\n * javascript: {\n * name: \"JavaScript\",\n * aliases: [\"js\"],\n * },\n * typescript: {\n * name: \"TypeScript\",\n * aliases: [\"ts\"],\n * },\n * }\n */\n supportedLanguages: Record<\n string,\n {\n /**\n * The display name of the language.\n */\n name: string;\n /**\n * Aliases for this language.\n */\n aliases?: string[];\n }\n >;\n /**\n * The highlighter to use for code blocks.\n */\n createHighlighter?: () => Promise<HighlighterGeneric<any, any>>;\n};\n\ntype CodeBlockConfigOptions = {\n editor: BlockNoteEditor<any, any, any>;\n};\n\nexport const shikiParserSymbol = Symbol.for(\"blocknote.shikiParser\");\nexport const shikiHighlighterPromiseSymbol = Symbol.for(\n \"blocknote.shikiHighlighterPromise\",\n);\nexport const defaultCodeBlockPropSchema = {\n language: {\n default: \"text\",\n },\n} satisfies PropSchema;\n\nconst CodeBlockContent = createStronglyTypedTiptapNode({\n name: \"codeBlock\",\n content: \"inline*\",\n group: \"blockContent\",\n marks: \"insertion deletion modification\",\n code: true,\n defining: true,\n addOptions() {\n return {\n defaultLanguage: \"text\",\n indentLineWithTab: true,\n supportedLanguages: {},\n };\n },\n addAttributes() {\n const options = this.options as CodeBlockConfigOptions;\n\n return {\n language: {\n default: options.editor.settings.codeBlock.defaultLanguage,\n parseHTML: (inputElement) => {\n let element = inputElement as HTMLElement | null;\n let language: string | null = null;\n\n if (\n element?.tagName === \"DIV\" &&\n element?.dataset.contentType === \"codeBlock\"\n ) {\n element = element.children[0] as HTMLElement | null;\n }\n\n if (element?.tagName === \"PRE\") {\n element = element?.children[0] as HTMLElement | null;\n }\n\n const dataLanguage = element?.getAttribute(\"data-language\");\n\n if (dataLanguage) {\n language = dataLanguage.toLowerCase();\n } else {\n const classNames = [...(element?.className.split(\" \") || [])];\n const languages = classNames\n .filter((className) => className.startsWith(\"language-\"))\n .map((className) => className.replace(\"language-\", \"\"));\n\n if (languages.length > 0) {\n language = languages[0].toLowerCase();\n }\n }\n\n if (!language) {\n return null;\n }\n\n return (\n getLanguageId(options.editor.settings.codeBlock, language) ??\n language\n );\n },\n renderHTML: (attributes) => {\n return attributes.language\n ? {\n class: `language-${attributes.language}`,\n \"data-language\": attributes.language,\n }\n : {};\n },\n },\n };\n },\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"pre\",\n // contentElement: \"code\",\n preserveWhitespace: \"full\",\n },\n ];\n },\n renderHTML({ HTMLAttributes }) {\n const pre = document.createElement(\"pre\");\n const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(\n this.name,\n \"code\",\n this.options.domAttributes?.blockContent || {},\n {\n ...(this.options.domAttributes?.inlineContent || {}),\n ...HTMLAttributes,\n },\n );\n\n dom.removeChild(contentDOM);\n dom.appendChild(pre);\n pre.appendChild(contentDOM);\n\n return {\n dom,\n contentDOM,\n };\n },\n addNodeView() {\n const options = this.options as CodeBlockConfigOptions;\n\n return ({ editor, node, getPos, HTMLAttributes }) => {\n const pre = document.createElement(\"pre\");\n const select = document.createElement(\"select\");\n const selectWrapper = document.createElement(\"div\");\n const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(\n this.name,\n \"code\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n const handleLanguageChange = (event: Event) => {\n const language = (event.target as HTMLSelectElement).value;\n\n editor.commands.command(({ tr }) => {\n tr.setNodeAttribute(getPos(), \"language\", language);\n\n return true;\n });\n };\n\n Object.entries(\n options.editor.settings.codeBlock.supportedLanguages,\n ).forEach(([id, { name }]) => {\n const option = document.createElement(\"option\");\n\n option.value = id;\n option.text = name;\n select.appendChild(option);\n });\n\n selectWrapper.contentEditable = \"false\";\n select.value =\n node.attrs.language ||\n options.editor.settings.codeBlock.defaultLanguage;\n dom.removeChild(contentDOM);\n dom.appendChild(selectWrapper);\n dom.appendChild(pre);\n pre.appendChild(contentDOM);\n selectWrapper.appendChild(select);\n select.addEventListener(\"change\", handleLanguageChange);\n\n return {\n dom,\n contentDOM,\n update: (newNode) => {\n if (newNode.type !== this.type) {\n return false;\n }\n\n return true;\n },\n destroy: () => {\n select.removeEventListener(\"change\", handleLanguageChange);\n },\n };\n };\n },\n addProseMirrorPlugins() {\n const options = this.options as CodeBlockConfigOptions;\n const globalThisForShiki = globalThis as {\n [shikiHighlighterPromiseSymbol]?: Promise<HighlighterGeneric<any, any>>;\n [shikiParserSymbol]?: Parser;\n };\n\n let highlighter: HighlighterGeneric<any, any> | undefined;\n let parser: Parser | undefined;\n let hasWarned = false;\n const lazyParser: Parser = (parserOptions) => {\n if (!options.editor.settings.codeBlock.createHighlighter) {\n if (process.env.NODE_ENV === \"development\" && !hasWarned) {\n // eslint-disable-next-line no-console\n console.log(\n \"For syntax highlighting of code blocks, you must provide a `codeBlock.createHighlighter` function\",\n );\n hasWarned = true;\n }\n return [];\n }\n if (!highlighter) {\n globalThisForShiki[shikiHighlighterPromiseSymbol] =\n globalThisForShiki[shikiHighlighterPromiseSymbol] ||\n options.editor.settings.codeBlock.createHighlighter();\n\n return globalThisForShiki[shikiHighlighterPromiseSymbol].then(\n (createdHighlighter) => {\n highlighter = createdHighlighter;\n },\n );\n }\n const language = getLanguageId(\n options.editor.settings.codeBlock,\n parserOptions.language!,\n );\n\n if (\n !language ||\n language === \"text\" ||\n language === \"none\" ||\n language === \"plaintext\" ||\n language === \"txt\"\n ) {\n return [];\n }\n\n if (!highlighter.getLoadedLanguages().includes(language)) {\n return highlighter.loadLanguage(language);\n }\n\n if (!parser) {\n parser =\n globalThisForShiki[shikiParserSymbol] ||\n createParser(highlighter as any);\n globalThisForShiki[shikiParserSymbol] = parser;\n }\n\n return parser(parserOptions);\n };\n\n const shikiLazyPlugin = createHighlightPlugin({\n parser: lazyParser,\n languageExtractor: (node) => node.attrs.language,\n nodeTypes: [this.name],\n });\n\n return [shikiLazyPlugin];\n },\n addInputRules() {\n const options = this.options as CodeBlockConfigOptions;\n\n return [\n new InputRule({\n find: /^```(.*?)\\s$/,\n handler: ({ state, range, match }) => {\n const $start = state.doc.resolve(range.from);\n const languageName = match[1].trim();\n const attributes = {\n language:\n getLanguageId(options.editor.settings.codeBlock, languageName) ??\n languageName,\n };\n\n if (\n !$start\n .node(-1)\n .canReplaceWith(\n $start.index(-1),\n $start.indexAfter(-1),\n this.type,\n )\n ) {\n return null;\n }\n\n state.tr\n .delete(range.from, range.to)\n .setBlockType(range.from, range.from, this.type, attributes)\n .setSelection(TextSelection.create(state.tr.doc, range.from));\n\n return;\n },\n }),\n ];\n },\n addKeyboardShortcuts() {\n return {\n Delete: ({ editor }) => {\n const { selection } = editor.state;\n const { $from } = selection;\n\n // When inside empty codeblock, on `DELETE` key press, delete the codeblock\n if (\n editor.isActive(this.name) &&\n !$from.parent.textContent &&\n isTextSelection(selection)\n ) {\n // Get the start position of the codeblock for node selection\n const from = $from.pos - $from.parentOffset - 2;\n\n editor.chain().setNodeSelection(from).deleteSelection().run();\n\n return true;\n }\n\n return false;\n },\n Tab: ({ editor }) => {\n if (!this.options.indentLineWithTab) {\n return false;\n }\n if (editor.isActive(this.name)) {\n editor.commands.insertContent(\" \");\n return true;\n }\n\n return false;\n },\n Enter: ({ editor }) => {\n const { $from } = editor.state.selection;\n\n if (!editor.isActive(this.name)) {\n return false;\n }\n\n const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2;\n const endsWithDoubleNewline = $from.parent.textContent.endsWith(\"\\n\\n\");\n\n if (!isAtEnd || !endsWithDoubleNewline) {\n editor.commands.insertContent(\"\\n\");\n return true;\n }\n\n return editor\n .chain()\n .command(({ tr }) => {\n tr.delete($from.pos - 2, $from.pos);\n\n return true;\n })\n .exitCode()\n .run();\n },\n \"Shift-Enter\": ({ editor }) => {\n const { $from } = editor.state.selection;\n\n if (!editor.isActive(this.name)) {\n return false;\n }\n\n editor\n .chain()\n .insertContentAt(\n $from.pos - $from.parentOffset + $from.parent.nodeSize,\n {\n type: \"paragraph\",\n },\n )\n .run();\n\n return true;\n },\n };\n },\n});\n\nexport const CodeBlock = createBlockSpecFromStronglyTypedTiptapNode(\n CodeBlockContent,\n defaultCodeBlockPropSchema,\n);\n\nfunction getLanguageId(\n options: CodeBlockOptions,\n languageName: string,\n): string | undefined {\n return Object.entries(options.supportedLanguages).find(\n ([id, { aliases }]) => {\n return aliases?.includes(languageName) || id === languageName;\n },\n )?.[0];\n}\n","import { Mark } from \"@tiptap/core\";\nimport { createStyleSpecFromTipTapMark } from \"../../schema/index.js\";\n\nconst BackgroundColorMark = Mark.create({\n name: \"backgroundColor\",\n\n addAttributes() {\n return {\n stringValue: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-background-color\"),\n renderHTML: (attributes) => ({\n \"data-background-color\": attributes.stringValue,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.hasAttribute(\"data-background-color\")) {\n return {\n stringValue: element.getAttribute(\"data-background-color\"),\n };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n});\n\nexport const BackgroundColor = createStyleSpecFromTipTapMark(\n BackgroundColorMark,\n \"string\",\n);\n","import { Mark } from \"@tiptap/core\";\nimport { createStyleSpecFromTipTapMark } from \"../../schema/index.js\";\n\nconst TextColorMark = Mark.create({\n name: \"textColor\",\n\n addAttributes() {\n return {\n stringValue: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-text-color\"),\n renderHTML: (attributes) => ({\n \"data-text-color\": attributes.stringValue,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.hasAttribute(\"data-text-color\")) {\n return { stringValue: element.getAttribute(\"data-text-color\") };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n});\n\nexport const TextColor = createStyleSpecFromTipTapMark(TextColorMark, \"string\");\n","export const parseEmbedElement = (embedElement: HTMLEmbedElement) => {\n const url = embedElement.src || undefined;\n\n return { url };\n};\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n FileBlockConfig,\n PropSchema,\n createBlockSpec,\n} from \"../../schema/index.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { parseEmbedElement } from \"./helpers/parse/parseEmbedElement.js\";\nimport { parseFigureElement } from \"./helpers/parse/parseFigureElement.js\";\nimport { createFileBlockWrapper } from \"./helpers/render/createFileBlockWrapper.js\";\nimport { createLinkWithCaption } from \"./helpers/toExternalHTML/createLinkWithCaption.js\";\n\nexport const filePropSchema = {\n backgroundColor: defaultProps.backgroundColor,\n // File name.\n name: {\n default: \"\" as const,\n },\n // File url.\n url: {\n default: \"\" as const,\n },\n // File caption.\n caption: {\n default: \"\" as const,\n },\n} satisfies PropSchema;\n\nexport const fileBlockConfig = {\n type: \"file\" as const,\n propSchema: filePropSchema,\n content: \"none\",\n isFileBlock: true,\n} satisfies FileBlockConfig;\n\nexport const fileRender = (\n block: BlockFromConfig<typeof fileBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n) => {\n return createFileBlockWrapper(block, editor);\n};\n\nexport const fileParse = (element: HTMLElement) => {\n if (element.tagName === \"EMBED\") {\n // Ignore if parent figure has already been parsed.\n if (element.closest(\"figure\")) {\n return undefined;\n }\n\n return parseEmbedElement(element as HTMLEmbedElement);\n }\n\n if (element.tagName === \"FIGURE\") {\n const parsedFigure = parseFigureElement(element, \"embed\");\n if (!parsedFigure) {\n return undefined;\n }\n\n const { targetElement, caption } = parsedFigure;\n\n return {\n ...parseEmbedElement(targetElement as HTMLEmbedElement),\n caption,\n };\n }\n\n return undefined;\n};\n\nexport const fileToExternalHTML = (\n block: BlockFromConfig<typeof fileBlockConfig, any, any>,\n) => {\n if (!block.props.url) {\n const div = document.createElement(\"p\");\n div.textContent = \"Add file\";\n\n return {\n dom: div,\n };\n }\n\n const fileSrcLink = document.createElement(\"a\");\n fileSrcLink.href = block.props.url;\n fileSrcLink.textContent = block.props.name || block.props.url;\n\n if (block.props.caption) {\n return createLinkWithCaption(fileSrcLink, block.props.caption);\n }\n\n return {\n dom: fileSrcLink,\n };\n};\n\nexport const FileBlock = createBlockSpec(fileBlockConfig, {\n render: fileRender,\n parse: fileParse,\n toExternalHTML: fileToExternalHTML,\n});\n","import { InputRule } from \"@tiptap/core\";\nimport { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../api/getBlockInfoFromPos.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n propsToAttributes,\n} from \"../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../defaultProps.js\";\n\nexport const headingPropSchema = {\n ...defaultProps,\n level: { default: 1, values: [1, 2, 3] as const },\n} satisfies PropSchema;\n\nconst HeadingBlockContent = createStronglyTypedTiptapNode({\n name: \"heading\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addAttributes() {\n return propsToAttributes(headingPropSchema);\n },\n\n addInputRules() {\n return [\n ...[1, 2, 3].map((level) => {\n // Creates a heading of appropriate level when starting with \"#\", \"##\", or \"###\".\n return new InputRule({\n find: new RegExp(`^(#{${level}})\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"heading\",\n props: {\n level: level as any,\n },\n }),\n )\n // Removes the \"#\" character(s) used to set the heading.\n .deleteRange({ from: range.from, to: range.to })\n .run();\n },\n });\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Alt-1\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n // call updateBlockCommand\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"heading\",\n props: {\n level: 1 as any,\n },\n }),\n );\n },\n \"Mod-Alt-2\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"heading\",\n props: {\n level: 2 as any,\n },\n }),\n );\n },\n \"Mod-Alt-3\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"heading\",\n props: {\n level: 3 as any,\n },\n }),\n );\n },\n };\n },\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"h1\",\n attrs: { level: 1 },\n node: \"heading\",\n },\n {\n tag: \"h2\",\n attrs: { level: 2 },\n node: \"heading\",\n },\n {\n tag: \"h3\",\n attrs: { level: 3 },\n node: \"heading\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n `h${node.attrs.level}`,\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const Heading = createBlockSpecFromStronglyTypedTiptapNode(\n HeadingBlockContent,\n headingPropSchema,\n);\n","import type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport { BlockFromConfig, FileBlockConfig } from \"../../../../schema/index.js\";\nimport { createFileBlockWrapper } from \"./createFileBlockWrapper.js\";\n\nexport const createResizableFileBlockWrapper = (\n block: BlockFromConfig<FileBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n element: { dom: HTMLElement; destroy?: () => void },\n resizeHandlesContainerElement: HTMLElement,\n buttonText: string,\n buttonIcon: HTMLElement,\n): { dom: HTMLElement; destroy: () => void } => {\n const { dom, destroy } = createFileBlockWrapper(\n block,\n editor,\n element,\n buttonText,\n buttonIcon,\n );\n const wrapper = dom;\n if (block.props.url && block.props.showPreview) {\n if (block.props.previewWidth) {\n wrapper.style.width = `${block.props.previewWidth}px`;\n } else {\n wrapper.style.width = \"fit-content\";\n }\n }\n\n const leftResizeHandle = document.createElement(\"div\");\n leftResizeHandle.className = \"bn-resize-handle\";\n leftResizeHandle.style.left = \"4px\";\n const rightResizeHandle = document.createElement(\"div\");\n rightResizeHandle.className = \"bn-resize-handle\";\n rightResizeHandle.style.right = \"4px\";\n\n // Temporary parameters set when the user begins resizing the element, used to\n // calculate the new width of the element.\n let resizeParams:\n | {\n handleUsed: \"left\" | \"right\";\n initialWidth: number;\n initialClientX: number;\n }\n | undefined;\n let width = block.props.previewWidth! as number;\n\n // Updates the element width with an updated width depending on the cursor X\n // offset from when the resize began, and which resize handle is being used.\n const windowMouseMoveHandler = (event: MouseEvent) => {\n if (!resizeParams) {\n if (\n !editor.isEditable &&\n resizeHandlesContainerElement.contains(leftResizeHandle) &&\n resizeHandlesContainerElement.contains(rightResizeHandle)\n ) {\n resizeHandlesContainerElement.removeChild(leftResizeHandle);\n resizeHandlesContainerElement.removeChild(rightResizeHandle);\n }\n\n return;\n }\n\n let newWidth: number;\n\n if (block.props.textAlignment === \"center\") {\n if (resizeParams.handleUsed === \"left\") {\n newWidth =\n resizeParams.initialWidth +\n (resizeParams.initialClientX - event.clientX) * 2;\n } else {\n newWidth =\n resizeParams.initialWidth +\n (event.clientX - resizeParams.initialClientX) * 2;\n }\n } else {\n if (resizeParams.handleUsed === \"left\") {\n newWidth =\n resizeParams.initialWidth +\n resizeParams.initialClientX -\n event.clientX;\n } else {\n newWidth =\n resizeParams.initialWidth +\n event.clientX -\n resizeParams.initialClientX;\n }\n }\n\n // Min element width in px.\n const minWidth = 64;\n\n // Ensures the element is not wider than the editor and not narrower than a\n // predetermined minimum width.\n width = Math.min(\n Math.max(newWidth, minWidth),\n editor.domElement?.firstElementChild?.clientWidth || Number.MAX_VALUE,\n );\n wrapper.style.width = `${width}px`;\n };\n // Stops mouse movements from resizing the element and updates the block's\n // `width` prop to the new value.\n const windowMouseUpHandler = (event: MouseEvent) => {\n // Hides the drag handles if the cursor is no longer over the element.\n if (\n (!event.target ||\n !wrapper.contains(event.target as Node) ||\n !editor.isEditable) &&\n resizeHandlesContainerElement.contains(leftResizeHandle) &&\n resizeHandlesContainerElement.contains(rightResizeHandle)\n ) {\n resizeHandlesContainerElement.removeChild(leftResizeHandle);\n resizeHandlesContainerElement.removeChild(rightResizeHandle);\n }\n\n if (!resizeParams) {\n return;\n }\n\n resizeParams = undefined;\n\n editor.updateBlock(block, {\n props: {\n previewWidth: width,\n },\n });\n };\n\n // Shows the resize handles when hovering over the wrapper with the cursor.\n const wrapperMouseEnterHandler = () => {\n if (editor.isEditable) {\n resizeHandlesContainerElement.appendChild(leftResizeHandle);\n resizeHandlesContainerElement.appendChild(rightResizeHandle);\n }\n };\n // Hides the resize handles when the cursor leaves the wrapper, unless the\n // cursor moves to one of the resize handles.\n const wrapperMouseLeaveHandler = (event: MouseEvent) => {\n if (\n event.relatedTarget === leftResizeHandle ||\n event.relatedTarget === rightResizeHandle\n ) {\n return;\n }\n\n if (resizeParams) {\n return;\n }\n\n if (\n editor.isEditable &&\n resizeHandlesContainerElement.contains(leftResizeHandle) &&\n resizeHandlesContainerElement.contains(rightResizeHandle)\n ) {\n resizeHandlesContainerElement.removeChild(leftResizeHandle);\n resizeHandlesContainerElement.removeChild(rightResizeHandle);\n }\n };\n\n // Sets the resize params, allowing the user to begin resizing the element by\n // moving the cursor left or right.\n const leftResizeHandleMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n resizeParams = {\n handleUsed: \"left\",\n initialWidth: wrapper.clientWidth,\n initialClientX: event.clientX,\n };\n };\n const rightResizeHandleMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n resizeParams = {\n handleUsed: \"right\",\n initialWidth: wrapper.clientWidth,\n initialClientX: event.clientX,\n };\n };\n\n window.addEventListener(\"mousemove\", windowMouseMoveHandler);\n window.addEventListener(\"mouseup\", windowMouseUpHandler);\n wrapper.addEventListener(\"mouseenter\", wrapperMouseEnterHandler);\n wrapper.addEventListener(\"mouseleave\", wrapperMouseLeaveHandler);\n leftResizeHandle.addEventListener(\n \"mousedown\",\n leftResizeHandleMouseDownHandler,\n );\n rightResizeHandle.addEventListener(\n \"mousedown\",\n rightResizeHandleMouseDownHandler,\n );\n\n return {\n dom: wrapper,\n destroy: () => {\n destroy?.();\n window.removeEventListener(\"mousemove\", windowMouseMoveHandler);\n window.removeEventListener(\"mouseup\", windowMouseUpHandler);\n wrapper.removeEventListener(\"mouseenter\", wrapperMouseEnterHandler);\n wrapper.removeEventListener(\"mouseleave\", wrapperMouseLeaveHandler);\n leftResizeHandle.removeEventListener(\n \"mousedown\",\n leftResizeHandleMouseDownHandler,\n );\n rightResizeHandle.removeEventListener(\n \"mousedown\",\n rightResizeHandleMouseDownHandler,\n );\n },\n };\n};\n","export const parseImageElement = (imageElement: HTMLImageElement) => {\n const url = imageElement.src || undefined;\n const previewWidth = imageElement.width || undefined;\n\n return { url, previewWidth };\n};\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n createBlockSpec,\n FileBlockConfig,\n Props,\n PropSchema,\n} from \"../../schema/index.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { parseFigureElement } from \"../FileBlockContent/helpers/parse/parseFigureElement.js\";\nimport { createFigureWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.js\";\nimport { createLinkWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.js\";\nimport { createResizableFileBlockWrapper } from \"../FileBlockContent/helpers/render/createResizableFileBlockWrapper.js\";\nimport { parseImageElement } from \"./parseImageElement.js\";\n\nexport const FILE_IMAGE_ICON_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M5 11.1005L7 9.1005L12.5 14.6005L16 11.1005L19 14.1005V5H5V11.1005ZM4 3H20C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3ZM15.5 10C14.6716 10 14 9.32843 14 8.5C14 7.67157 14.6716 7 15.5 7C16.3284 7 17 7.67157 17 8.5C17 9.32843 16.3284 10 15.5 10Z\"></path></svg>';\n\nexport const imagePropSchema = {\n textAlignment: defaultProps.textAlignment,\n backgroundColor: defaultProps.backgroundColor,\n // File name.\n name: {\n default: \"\" as const,\n },\n // File url.\n url: {\n default: \"\" as const,\n },\n // File caption.\n caption: {\n default: \"\" as const,\n },\n\n showPreview: {\n default: true,\n },\n // File preview width in px.\n previewWidth: {\n default: undefined,\n type: \"number\",\n },\n} satisfies PropSchema;\n\nexport const imageBlockConfig = {\n type: \"image\" as const,\n propSchema: imagePropSchema,\n content: \"none\",\n isFileBlock: true,\n fileBlockAccept: [\"image/*\"],\n} satisfies FileBlockConfig;\n\nexport const imageRender = (\n block: BlockFromConfig<typeof imageBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n) => {\n const icon = document.createElement(\"div\");\n icon.innerHTML = FILE_IMAGE_ICON_SVG;\n\n const imageWrapper = document.createElement(\"div\");\n imageWrapper.className = \"bn-visual-media-wrapper\";\n\n const image = document.createElement(\"img\");\n image.className = \"bn-visual-media\";\n if (editor.resolveFileUrl) {\n editor.resolveFileUrl(block.props.url).then((downloadUrl) => {\n image.src = downloadUrl;\n });\n } else {\n image.src = block.props.url;\n }\n\n image.alt = block.props.name || block.props.caption || \"BlockNote image\";\n image.contentEditable = \"false\";\n image.draggable = false;\n imageWrapper.appendChild(image);\n\n return createResizableFileBlockWrapper(\n block,\n editor,\n { dom: imageWrapper },\n imageWrapper,\n editor.dictionary.file_blocks.image.add_button_text,\n icon.firstElementChild as HTMLElement,\n );\n};\n\nexport const imageParse = (\n element: HTMLElement,\n): Partial<Props<typeof imageBlockConfig.propSchema>> | undefined => {\n if (element.tagName === \"IMG\") {\n // Ignore if parent figure has already been parsed.\n if (element.closest(\"figure\")) {\n return undefined;\n }\n\n return parseImageElement(element as HTMLImageElement);\n }\n\n if (element.tagName === \"FIGURE\") {\n const parsedFigure = parseFigureElement(element, \"img\");\n if (!parsedFigure) {\n return undefined;\n }\n\n const { targetElement, caption } = parsedFigure;\n\n return {\n ...parseImageElement(targetElement as HTMLImageElement),\n caption,\n };\n }\n\n return undefined;\n};\n\nexport const imageToExternalHTML = (\n block: BlockFromConfig<typeof imageBlockConfig, any, any>,\n) => {\n if (!block.props.url) {\n const div = document.createElement(\"p\");\n div.textContent = \"Add image\";\n\n return {\n dom: div,\n };\n }\n\n let image;\n if (block.props.showPreview) {\n image = document.createElement(\"img\");\n image.src = block.props.url;\n image.alt = block.props.name || block.props.caption || \"BlockNote image\";\n if (block.props.previewWidth) {\n image.width = block.props.previewWidth;\n }\n } else {\n image = document.createElement(\"a\");\n image.href = block.props.url;\n image.textContent = block.props.name || block.props.url;\n }\n\n if (block.props.caption) {\n if (block.props.showPreview) {\n return createFigureWithCaption(image, block.props.caption);\n } else {\n return createLinkWithCaption(image, block.props.caption);\n }\n }\n\n return {\n dom: image,\n };\n};\n\nexport const ImageBlock = createBlockSpec(imageBlockConfig, {\n render: imageRender,\n parse: imageParse,\n toExternalHTML: imageToExternalHTML,\n});\n","import { DOMParser, Fragment, Schema } from \"prosemirror-model\";\n\n/**\n * This function is used to parse the content of a list item external HTML node.\n *\n * Due to a change in how prosemirror-model handles parsing elements, we have additional flexibility in how we can \"fit\" content into a list item.\n *\n * We've decided to take an approach that is similar to Notion. The core rules of the algorithm are:\n *\n * - If the first child of an `li` has ONLY text content, take the text content, and flatten it into the list item. Subsequent siblings are carried over as is, as children of the list item.\n * - e.g. `<li><h1>Hello</h1><p>World</p></li> -> <li>Hello<blockGroup><blockContainer><p>World</p></blockContainer></blockGroup></li>`\n * - Else, take the content and insert it as children instead.\n * - e.g. `<li><img src=\"url\" /></li> -> <li><p></p><blockGroup><blockContainer><img src=\"url\" /></blockContainer></blockGroup></li>`\n *\n * This ensures that a list item's content is always valid ProseMirror content. Smoothing over differences between how external HTML may be rendered, and how ProseMirror expects content to be structured.\n */\nexport function getListItemContent(\n /**\n * The `li` element to parse.\n */\n _node: Node,\n /**\n * The schema to use for parsing.\n */\n schema: Schema,\n /**\n * The name of the list item node.\n */\n name: string,\n): Fragment {\n /**\n * To actually implement this algorithm, we need to leverage ProseMirror's \"fitting\" algorithm.\n * Where, if content is parsed which doesn't fit into the current node, it will be moved into the parent node.\n *\n * This allows us to parse multiple pieces of content from within the list item (even though it normally would not match the list item's schema) and \"throw\" the excess content into the list item's children.\n *\n * The expected return value is a `Fragment` which contains the list item's content as the first element, and the children wrapped in a blockGroup node. Like so:\n * ```\n * Fragment<[Node<Text>, Node<BlockGroup<Node<BlockContainer<any>>>>]>\n * ```\n */\n const parser = DOMParser.fromSchema(schema);\n\n // TODO: This will be unnecessary in the future: https://github.com/ProseMirror/prosemirror-model/commit/166188d4f9db96eb86fb7de62e72049c86c9dd79\n const node = _node as HTMLElement;\n\n // Move the `li` element's content into a new `div` element\n // This is a hacky workaround to not re-trigger list item parsing,\n // when we are looking to understand what the list item's content actually is, in terms of the schema.\n const clonedNodeDiv = document.createElement(\"div\");\n // Mark the `div` element as a `blockGroup` to make the parsing easier.\n clonedNodeDiv.setAttribute(\"data-node-type\", \"blockGroup\");\n // Clone all children of the `li` element into the new `div` element\n for (const child of Array.from(node.childNodes)) {\n clonedNodeDiv.appendChild(child.cloneNode(true));\n }\n\n // Parses children of the `li` element into a `blockGroup` with `blockContainer` node children\n // This is the structure of list item children, so parsing into this structure allows for\n // easy separation of list item content from child list item content.\n let blockGroupNode = parser.parse(clonedNodeDiv, {\n topNode: schema.nodes.blockGroup.create(),\n });\n\n // There is an edge case where a list item's content may contain a `<input>` element.\n // Causing it to be recognized as a `checkListItem`.\n // We want to skip this, and just parse the list item's content as is.\n if (blockGroupNode.firstChild?.firstChild?.type.name === \"checkListItem\") {\n // We skip the first child, by cutting it out of the `blockGroup` node.\n // and continuing with the rest of the algorithm.\n blockGroupNode = blockGroupNode.copy(\n blockGroupNode.content.cut(\n blockGroupNode.firstChild.firstChild.nodeSize + 2,\n ),\n );\n }\n\n // Structure above is `blockGroup<blockContainer<any>[]>`\n // We want to extract the first `blockContainer` node's content, and see if it is a text block.\n const listItemsFirstChild = blockGroupNode.firstChild?.firstChild;\n\n // If the first node is not a text block, then it's first child is not compatible with the list item node.\n if (!listItemsFirstChild?.isTextblock) {\n // So, we do not try inserting anything into the list item, and instead return anything we found as children for the list item.\n return Fragment.from(blockGroupNode);\n }\n\n // If it is a text block, then we know it only contains text content.\n // So, we extract it, and insert its content into the `listItemNode`.\n // The remaining nodes in the `blockGroup` stay in-place.\n const listItemNode = schema.nodes[name].create(\n {},\n listItemsFirstChild.content,\n );\n\n // We have `blockGroup<listItemsFirstChild, ...blockContainer<any>[]>`\n // We want to extract out the rest of the nodes as `<...blockContainer<any>[]>`\n const remainingListItemChildren = blockGroupNode.content.cut(\n // +2 for the `blockGroup` node's start and end markers\n listItemsFirstChild.nodeSize + 2,\n );\n const hasRemainingListItemChildren = remainingListItemChildren.size > 0;\n\n if (hasRemainingListItemChildren) {\n // Copy the remaining list item children back into the `blockGroup` node.\n // This will make it back into: `blockGroup<...blockContainer<any>[]>`\n const listItemsChildren = blockGroupNode.copy(remainingListItemChildren);\n\n // Return the `listItem` node's content, then add the parsed children after to be lifted out by ProseMirror \"fitting\" algorithm.\n return listItemNode.content.addToEnd(listItemsChildren);\n }\n\n // Otherwise, just return the `listItem` node's content.\n return listItemNode.content;\n}\n","import { EditorState } from \"prosemirror-state\";\n\nimport {\n getBlockInfo,\n getNearestBlockPos,\n} from \"../../../getBlockInfoFromPos.js\";\n\nexport const splitBlockCommand = (\n posInBlock: number,\n keepType?: boolean,\n keepProps?: boolean,\n) => {\n return ({\n state,\n dispatch,\n }: {\n state: EditorState;\n dispatch: ((args?: any) => any) | undefined;\n }) => {\n const nearestBlockContainerPos = getNearestBlockPos(state.doc, posInBlock);\n\n const info = getBlockInfo(nearestBlockContainerPos);\n\n if (!info.isBlockContainer) {\n throw new Error(\n `BlockContainer expected when calling splitBlock, position ${posInBlock}`,\n );\n }\n\n const types = [\n {\n type: info.bnBlock.node.type, // always keep blockcontainer type\n attrs: keepProps ? { ...info.bnBlock.node.attrs, id: undefined } : {},\n },\n {\n type: keepType\n ? info.blockContent.node.type\n : state.schema.nodes[\"paragraph\"],\n attrs: keepProps ? { ...info.blockContent.node.attrs } : {},\n },\n ];\n\n if (dispatch) {\n state.tr.split(posInBlock, 2, types);\n }\n\n return true;\n };\n};\n","import { splitBlockCommand } from \"../../api/blockManipulation/commands/splitBlock/splitBlock.js\";\nimport { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromTransaction } from \"../../api/getBlockInfoFromPos.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\n\nexport const handleEnter = (editor: BlockNoteEditor<any, any, any>) => {\n const { blockInfo, selectionEmpty } = editor.transact((tr) => {\n return {\n blockInfo: getBlockInfoFromTransaction(tr),\n selectionEmpty: tr.selection.anchor === tr.selection.head,\n };\n });\n\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { bnBlock: blockContainer, blockContent } = blockInfo;\n\n if (\n !(\n blockContent.node.type.name === \"bulletListItem\" ||\n blockContent.node.type.name === \"numberedListItem\" ||\n blockContent.node.type.name === \"checkListItem\"\n ) ||\n !selectionEmpty\n ) {\n return false;\n }\n\n return editor._tiptapEditor.commands.first(({ state, chain, commands }) => [\n () =>\n // Changes list item block to a paragraph block if the content is empty.\n commands.command(() => {\n if (blockContent.node.childCount === 0) {\n return commands.command(\n updateBlockCommand(blockContainer.beforePos, {\n type: \"paragraph\",\n props: {},\n }),\n );\n }\n\n return false;\n }),\n\n () =>\n // Splits the current block, moving content inside that's after the cursor\n // to a new block of the same type below.\n commands.command(() => {\n if (blockContent.node.childCount > 0) {\n chain()\n .deleteSelection()\n .command(splitBlockCommand(state.selection.from, true))\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n};\n","import { InputRule } from \"@tiptap/core\";\nimport { updateBlockCommand } from \"../../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../../api/getBlockInfoFromPos.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../../defaultProps.js\";\nimport { getListItemContent } from \"../getListItemContent.js\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts.js\";\n\nexport const bulletListItemPropSchema = {\n ...defaultProps,\n} satisfies PropSchema;\n\nconst BulletListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"bulletListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n // This is to make sure that check list parse rules run before, since they\n // both parse `li` elements but check lists are more specific.\n priority: 90,\n addInputRules() {\n return [\n // Creates an unordered list when starting with \"-\", \"+\", or \"*\".\n new InputRule({\n find: new RegExp(`^[-+*]\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"bulletListItem\",\n props: {},\n }),\n )\n // Removes the \"-\", \"+\", or \"*\" character used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.options.editor),\n \"Mod-Shift-8\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"bulletListItem\",\n props: {},\n }),\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"UL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement?.tagName === \"UL\")\n ) {\n return {};\n }\n\n return false;\n },\n // As `li` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n getListItemContent(node, schema, this.name),\n node: \"bulletListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n // We use a <p> tag, because for <li> tags we'd need a <ul> element to put\n // them in to be semantically correct, which we can't have due to the\n // schema.\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const BulletListItem = createBlockSpecFromStronglyTypedTiptapNode(\n BulletListItemBlockContent,\n bulletListItemPropSchema,\n);\n","import { InputRule } from \"@tiptap/core\";\nimport { updateBlockCommand } from \"../../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport {\n getBlockInfoFromSelection,\n getNearestBlockPos,\n} from \"../../../api/getBlockInfoFromPos.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n propsToAttributes,\n} from \"../../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../../defaultProps.js\";\nimport { getListItemContent } from \"../getListItemContent.js\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts.js\";\n\nexport const checkListItemPropSchema = {\n ...defaultProps,\n checked: {\n default: false,\n },\n} satisfies PropSchema;\n\nconst checkListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"checkListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addAttributes() {\n return propsToAttributes(checkListItemPropSchema);\n },\n\n addInputRules() {\n return [\n // Creates a checklist when starting with \"[]\" or \"[X]\".\n new InputRule({\n find: new RegExp(`\\\\[\\\\s*\\\\]\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"checkListItem\",\n props: {\n checked: false as any,\n },\n }),\n )\n // Removes the characters used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n new InputRule({\n find: new RegExp(`\\\\[[Xx]\\\\]\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"checkListItem\",\n props: {\n checked: true as any,\n },\n }),\n )\n // Removes the characters used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.options.editor),\n \"Mod-Shift-9\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"checkListItem\",\n props: {},\n }),\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"input\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n // Ignore if we already parsed an ancestor list item to avoid double-parsing.\n if (element.closest(\"[data-content-type]\") || element.closest(\"li\")) {\n return false;\n }\n\n if ((element as HTMLInputElement).type === \"checkbox\") {\n return { checked: (element as HTMLInputElement).checked };\n }\n\n return false;\n },\n node: \"checkListItem\",\n },\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"UL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement?.tagName === \"UL\")\n ) {\n const checkbox =\n (element.querySelector(\n \"input[type=checkbox]\",\n ) as HTMLInputElement) || null;\n\n if (checkbox === null) {\n return false;\n }\n\n return { checked: checkbox.checked };\n }\n\n return false;\n },\n // As `li` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n getListItemContent(node, schema, this.name),\n node: \"checkListItem\",\n },\n ];\n },\n\n // Since there is no HTML checklist element, there isn't really any\n // standardization for what checklists should look like in the DOM. GDocs'\n // and Notion's aren't cross compatible, for example. This implementation\n // has a semantically correct DOM structure (though missing a label for the\n // checkbox) which is also converted correctly to Markdown by remark.\n renderHTML({ node, HTMLAttributes }) {\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.checked = node.attrs.checked;\n if (node.attrs.checked) {\n checkbox.setAttribute(\"checked\", \"\");\n }\n\n const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(\n this.name,\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n\n dom.insertBefore(checkbox, contentDOM);\n\n return { dom, contentDOM };\n },\n\n // Need to render node view since the checkbox needs to be able to update the\n // node. This is only possible with a node view as it exposes `getPos`.\n addNodeView() {\n return ({ node, getPos, editor, HTMLAttributes }) => {\n // Need to wrap certain elements in a div or keyboard navigation gets\n // confused.\n const wrapper = document.createElement(\"div\");\n const checkboxWrapper = document.createElement(\"div\");\n checkboxWrapper.contentEditable = \"false\";\n\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.checked = node.attrs.checked;\n if (node.attrs.checked) {\n checkbox.setAttribute(\"checked\", \"\");\n }\n\n const changeHandler = () => {\n if (!editor.isEditable) {\n // This seems like the most effective way of blocking the checkbox\n // from being toggled, as event.preventDefault() does not stop it for\n // \"click\" or \"change\" events.\n checkbox.checked = !checkbox.checked;\n return;\n }\n\n // TODO: test\n if (typeof getPos !== \"boolean\") {\n const beforeBlockContainerPos = getNearestBlockPos(\n editor.state.doc,\n getPos(),\n );\n\n if (beforeBlockContainerPos.node.type.name !== \"blockContainer\") {\n throw new Error(\n `Expected blockContainer node, got ${beforeBlockContainerPos.node.type.name}`,\n );\n }\n\n this.editor.commands.command(\n updateBlockCommand(beforeBlockContainerPos.posBeforeNode, {\n type: \"checkListItem\",\n props: {\n checked: checkbox.checked as any,\n },\n }),\n );\n }\n };\n checkbox.addEventListener(\"change\", changeHandler);\n\n const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(\n this.name,\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n\n if (typeof getPos !== \"boolean\") {\n // Since `node` is a blockContent node, we have to get the block ID from\n // the parent blockContainer node. This means we can't add the label in\n // `renderHTML` as we can't use `getPos` and therefore can't get the\n // parent blockContainer node.\n const blockID = this.editor.state.doc.resolve(getPos()).node().attrs.id;\n const label = \"label-\" + blockID;\n checkbox.setAttribute(\"aria-labelledby\", label);\n contentDOM.id = label;\n }\n\n dom.removeChild(contentDOM);\n dom.appendChild(wrapper);\n wrapper.appendChild(checkboxWrapper);\n wrapper.appendChild(contentDOM);\n checkboxWrapper.appendChild(checkbox);\n\n return {\n dom,\n contentDOM,\n destroy: () => {\n checkbox.removeEventListener(\"change\", changeHandler);\n },\n };\n };\n },\n});\n\nexport const CheckListItem = createBlockSpecFromStronglyTypedTiptapNode(\n checkListItemBlockContent,\n checkListItemPropSchema,\n);\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { getBlockInfo } from \"../../../api/getBlockInfoFromPos.js\";\n\n// ProseMirror Plugin which automatically assigns indices to ordered list items per nesting level.\nconst PLUGIN_KEY = new PluginKey(`numbered-list-indexing`);\nexport const NumberedListIndexingPlugin = () => {\n return new Plugin({\n key: PLUGIN_KEY,\n appendTransaction: (_transactions, _oldState, newState) => {\n const tr = newState.tr;\n tr.setMeta(\"numberedListIndexing\", true);\n\n let modified = false;\n\n // Traverses each node the doc using DFS, so blocks which are on the same nesting level will be traversed in the\n // same order they appear. This means the index of each list item block can be calculated by incrementing the\n // index of the previous list item block.\n newState.doc.descendants((node, pos) => {\n if (\n node.type.name === \"blockContainer\" &&\n node.firstChild!.type.name === \"numberedListItem\"\n ) {\n let newIndex = `${node.firstChild!.attrs[\"start\"] || 1}`;\n\n const blockInfo = getBlockInfo({\n posBeforeNode: pos,\n node,\n });\n\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n\n // Checks if this block is the start of a new ordered list, i.e. if it's the first block in the document, the\n // first block in its nesting level, or the previous block is not an ordered list item.\n\n const prevBlock = tr.doc.resolve(\n blockInfo.bnBlock.beforePos,\n ).nodeBefore;\n\n if (prevBlock) {\n const prevBlockInfo = getBlockInfo({\n posBeforeNode: blockInfo.bnBlock.beforePos - prevBlock.nodeSize,\n node: prevBlock,\n });\n\n const isPrevBlockOrderedListItem =\n prevBlockInfo.blockNoteType === \"numberedListItem\";\n\n if (isPrevBlockOrderedListItem) {\n if (!prevBlockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n const prevBlockIndex =\n prevBlockInfo.blockContent.node.attrs[\"index\"];\n\n newIndex = (parseInt(prevBlockIndex) + 1).toString();\n }\n }\n\n const contentNode = blockInfo.blockContent.node;\n const index = contentNode.attrs[\"index\"];\n const isFirst =\n prevBlock?.firstChild?.type.name !== \"numberedListItem\";\n\n if (index !== newIndex || (contentNode.attrs.start && !isFirst)) {\n modified = true;\n\n const { start, ...attrs } = contentNode.attrs;\n\n tr.setNodeMarkup(blockInfo.blockContent.beforePos, undefined, {\n ...attrs,\n index: newIndex,\n ...(typeof start === \"number\" &&\n isFirst && {\n start,\n }),\n });\n }\n }\n });\n\n return modified ? tr : null;\n },\n });\n};\n","import { InputRule } from \"@tiptap/core\";\nimport { updateBlockCommand } from \"../../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../../api/getBlockInfoFromPos.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n propsToAttributes,\n} from \"../../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../../defaultProps.js\";\nimport { getListItemContent } from \"../getListItemContent.js\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts.js\";\nimport { NumberedListIndexingPlugin } from \"./NumberedListIndexingPlugin.js\";\n\nexport const numberedListItemPropSchema = {\n ...defaultProps,\n start: { default: undefined, type: \"number\" },\n} satisfies PropSchema;\n\nconst NumberedListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"numberedListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n priority: 90,\n addAttributes() {\n return {\n ...propsToAttributes(numberedListItemPropSchema),\n // the index attribute is only used internally (it's not part of the blocknote schema)\n // that's why it's defined explicitly here, and not part of the prop schema\n index: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-index\"),\n renderHTML: (attributes) => {\n return {\n \"data-index\": attributes.index,\n };\n },\n },\n };\n },\n\n addInputRules() {\n return [\n // Creates an ordered list when starting with \"1.\".\n new InputRule({\n find: new RegExp(`^(\\\\d+)\\\\.\\\\s$`),\n handler: ({ state, chain, range, match }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\" ||\n blockInfo.blockNoteType === \"numberedListItem\"\n ) {\n return;\n }\n const startIndex = parseInt(match[1]);\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"numberedListItem\",\n props:\n (startIndex === 1 && {}) ||\n ({\n start: startIndex,\n } as any),\n }),\n )\n // Removes the \"1.\" characters used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.options.editor),\n \"Mod-Shift-7\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"numberedListItem\",\n props: {},\n }),\n );\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [NumberedListIndexingPlugin()];\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"OL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement?.tagName === \"OL\")\n ) {\n const startIndex =\n parseInt(parent.getAttribute(\"start\") || \"1\") || 1;\n\n if (element.previousSibling || startIndex === 1) {\n return {};\n }\n\n return {\n start: startIndex,\n };\n }\n\n return false;\n },\n // As `li` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n getListItemContent(node, schema, this.name),\n priority: 300,\n node: \"numberedListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n // We use a <p> tag, because for <li> tags we'd need an <ol> element to\n // put them in to be semantically correct, which we can't have due to the\n // schema.\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const NumberedListItem = createBlockSpecFromStronglyTypedTiptapNode(\n NumberedListItemBlockContent,\n numberedListItemPropSchema,\n);\n","import { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../api/getBlockInfoFromPos.js\";\nimport {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../defaultProps.js\";\n\nexport const paragraphPropSchema = {\n ...defaultProps,\n};\n\nexport const ParagraphBlockContent = createStronglyTypedTiptapNode({\n name: \"paragraph\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Alt-0\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"paragraph\",\n props: {},\n }),\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"p\",\n getAttrs: (element) => {\n if (typeof element === \"string\" || !element.textContent?.trim()) {\n return false;\n }\n\n return {};\n },\n node: \"paragraph\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const Paragraph = createBlockSpecFromStronglyTypedTiptapNode(\n ParagraphBlockContent,\n paragraphPropSchema,\n);\n","import {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { getBlockInfoFromSelection } from \"../../api/getBlockInfoFromPos.js\";\nimport { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { InputRule } from \"@tiptap/core\";\n\nexport const quotePropSchema = {\n ...defaultProps,\n};\n\nexport const QuoteBlockContent = createStronglyTypedTiptapNode({\n name: \"quote\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addInputRules() {\n return [\n // Creates a block quote when starting with \">\".\n new InputRule({\n find: new RegExp(`^>\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"quote\",\n props: {},\n }),\n )\n // Removes the \">\" character used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Alt-q\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"quote\",\n }),\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"blockquote\",\n node: \"quote\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"blockquote\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const Quote = createBlockSpecFromStronglyTypedTiptapNode(\n QuoteBlockContent,\n quotePropSchema,\n);\n","import { callOrReturn, Extension, getExtensionField } from \"@tiptap/core\";\nimport { columnResizing, goToNextCell, tableEditing } from \"prosemirror-tables\";\n\nexport const RESIZE_MIN_WIDTH = 35;\nexport const EMPTY_CELL_WIDTH = 120;\nexport const EMPTY_CELL_HEIGHT = 31;\n\nexport const TableExtension = Extension.create({\n name: \"BlockNoteTableExtension\",\n\n addProseMirrorPlugins: () => {\n return [\n columnResizing({\n cellMinWidth: RESIZE_MIN_WIDTH,\n defaultCellMinWidth: EMPTY_CELL_WIDTH,\n // We set this to null as we implement our own node view in the table\n // block content. This node view is the same as what's used by default,\n // but is wrapped in a `blockContent` HTML element.\n View: null,\n }),\n tableEditing(),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n // Makes enter create a new line within the cell.\n Enter: () => {\n if (\n this.editor.state.selection.empty &&\n this.editor.state.selection.$head.parent.type.name ===\n \"tableParagraph\"\n ) {\n this.editor.commands.insertContent({ type: \"hardBreak\" });\n\n return true;\n }\n\n return false;\n },\n // Ensures that backspace won't delete the table if the text cursor is at\n // the start of a cell and the selection is empty.\n Backspace: () => {\n const selection = this.editor.state.selection;\n const selectionIsEmpty = selection.empty;\n const selectionIsAtStartOfNode = selection.$head.parentOffset === 0;\n const selectionIsInTableParagraphNode =\n selection.$head.node().type.name === \"tableParagraph\";\n\n return (\n selectionIsEmpty &&\n selectionIsAtStartOfNode &&\n selectionIsInTableParagraphNode\n );\n },\n // Enables navigating cells using the tab key.\n Tab: () => {\n return this.editor.commands.command(({ state, dispatch, view }) =>\n goToNextCell(1)(state, dispatch, view),\n );\n },\n \"Shift-Tab\": () => {\n return this.editor.commands.command(({ state, dispatch, view }) =>\n goToNextCell(-1)(state, dispatch, view),\n );\n },\n };\n },\n\n extendNodeSchema(extension) {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n };\n\n return {\n tableRole: callOrReturn(\n getExtensionField(extension, \"tableRole\", context),\n ),\n };\n },\n});\n","import { Node, mergeAttributes } from \"@tiptap/core\";\nimport { TableCell } from \"@tiptap/extension-table-cell\";\nimport { TableHeader } from \"@tiptap/extension-table-header\";\nimport { DOMParser, Fragment, Node as PMNode, Schema } from \"prosemirror-model\";\nimport { TableView } from \"prosemirror-tables\";\nimport { NodeView } from \"prosemirror-view\";\nimport {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema/index.js\";\nimport { mergeCSSClasses } from \"../../util/browser.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { EMPTY_CELL_WIDTH, TableExtension } from \"./TableExtension.js\";\n\nexport const tablePropSchema = {\n textColor: defaultProps.textColor,\n};\n\nexport const TableBlockContent = createStronglyTypedTiptapNode({\n name: \"table\",\n content: \"tableRow+\",\n group: \"blockContent\",\n tableRole: \"table\",\n\n marks: \"deletion insertion modification\",\n isolating: true,\n\n parseHTML() {\n return [\n {\n tag: \"table\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"table\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n\n // This node view is needed for the `columnResizing` plugin. By default, the\n // plugin adds its own node view, which overrides how the node is rendered vs\n // `renderHTML`. This means that the wrapping `blockContent` HTML element is\n // no longer rendered. The `columnResizing` plugin uses the `TableView` as its\n // default node view. `BlockNoteTableView` extends it by wrapping it in a\n // `blockContent` element, so the DOM structure is consistent with other block\n // types.\n addNodeView() {\n return ({ node, HTMLAttributes }) => {\n class BlockNoteTableView extends TableView {\n constructor(\n public node: PMNode,\n public cellMinWidth: number,\n public blockContentHTMLAttributes: Record<string, string>,\n ) {\n super(node, cellMinWidth);\n\n const blockContent = document.createElement(\"div\");\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n blockContentHTMLAttributes.class,\n );\n blockContent.setAttribute(\"data-content-type\", \"table\");\n for (const [attribute, value] of Object.entries(\n blockContentHTMLAttributes,\n )) {\n if (attribute !== \"class\") {\n blockContent.setAttribute(attribute, value);\n }\n }\n\n const tableWrapper = this.dom;\n\n const tableWrapperInner = document.createElement(\"div\");\n tableWrapperInner.className = \"tableWrapper-inner\";\n tableWrapperInner.appendChild(tableWrapper.firstChild!);\n\n tableWrapper.appendChild(tableWrapperInner);\n\n blockContent.appendChild(tableWrapper);\n const floatingContainer = document.createElement(\"div\");\n floatingContainer.className = \"table-widgets-container\";\n floatingContainer.style.position = \"relative\";\n tableWrapper.appendChild(floatingContainer);\n\n this.dom = blockContent;\n }\n\n ignoreMutation(record: MutationRecord): boolean {\n return (\n !(record.target as HTMLElement).closest(\".tableWrapper-inner\") ||\n super.ignoreMutation(record)\n );\n }\n }\n\n return new BlockNoteTableView(node, EMPTY_CELL_WIDTH, {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n }) as NodeView; // needs cast, tiptap types (wrongly) doesn't support return tableview here\n };\n },\n});\n\nconst TableParagraph = createStronglyTypedTiptapNode({\n name: \"tableParagraph\",\n group: \"tableContent\",\n content: \"inline*\",\n\n parseHTML() {\n return [\n {\n tag: \"p\",\n getAttrs: (element) => {\n if (typeof element === \"string\" || !element.textContent) {\n return false;\n }\n\n // Only parse in internal HTML.\n if (!element.closest(\"[data-content-type]\")) {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (parent.tagName === \"TD\" || parent.tagName === \"TH\") {\n return {};\n }\n\n return false;\n },\n node: \"tableParagraph\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"p\", HTMLAttributes, 0];\n },\n});\n\n/**\n * This extension allows you to create table rows.\n * @see https://www.tiptap.dev/api/nodes/table-row\n */\nexport const TableRow = Node.create<{ HTMLAttributes: Record<string, any> }>({\n name: \"tableRow\",\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n content: \"(tableCell | tableHeader)+\",\n\n tableRole: \"row\",\n marks: \"deletion insertion modification\",\n parseHTML() {\n return [{ tag: \"tr\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"tr\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n 0,\n ];\n },\n});\n\n/*\n * This will flatten a node's content to fit into a table cell's paragraph.\n */\nfunction parseTableContent(node: HTMLElement, schema: Schema) {\n const parser = DOMParser.fromSchema(schema);\n\n // This will parse the content of the table paragraph as though it were a blockGroup.\n // Resulting in a structure like:\n // <blockGroup>\n // <blockContainer>\n // <p>Hello</p>\n // </blockContainer>\n // <blockContainer>\n // <p>Hello</p>\n // </blockContainer>\n // </blockGroup>\n const parsedContent = parser.parse(node, {\n topNode: schema.nodes.blockGroup.create(),\n });\n const extractedContent: PMNode[] = [];\n\n // Try to extract any content within the blockContainer.\n parsedContent.content.descendants((child) => {\n // As long as the child is an inline node, we can append it to the fragment.\n if (child.isInline) {\n // And append it to the fragment\n extractedContent.push(child);\n return false;\n }\n\n return undefined;\n });\n\n return Fragment.fromArray(extractedContent);\n}\n\nexport const Table = createBlockSpecFromStronglyTypedTiptapNode(\n TableBlockContent,\n tablePropSchema,\n [\n TableExtension,\n TableParagraph,\n TableHeader.extend({\n /**\n * We allow table headers and cells to have multiple tableContent nodes because\n * when merging cells, prosemirror-tables will concat the contents of the cells naively.\n * This would cause that content to overflow into other cells when prosemirror tries to enforce the cell structure.\n *\n * So, we manually fix this up when reading back in the `nodeToBlock` and only ever place a single tableContent back into the cell.\n */\n content: \"tableContent+\",\n parseHTML() {\n return [\n {\n tag: \"th\",\n // As `th` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n parseTableContent(node as HTMLElement, schema),\n },\n ];\n },\n }),\n TableCell.extend({\n content: \"tableContent+\",\n parseHTML() {\n return [\n {\n tag: \"td\",\n // As `td` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n parseTableContent(node as HTMLElement, schema),\n },\n ];\n },\n }),\n TableRow,\n ],\n);\n","export const parseVideoElement = (videoElement: HTMLVideoElement) => {\n const url = videoElement.src || undefined;\n const previewWidth = videoElement.width || undefined;\n\n return { url, previewWidth };\n};\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n createBlockSpec,\n FileBlockConfig,\n Props,\n PropSchema,\n} from \"../../schema/index.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { parseFigureElement } from \"../FileBlockContent/helpers/parse/parseFigureElement.js\";\nimport { createFigureWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.js\";\nimport { createLinkWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.js\";\nimport { createResizableFileBlockWrapper } from \"../FileBlockContent/helpers/render/createResizableFileBlockWrapper.js\";\nimport { parseVideoElement } from \"./parseVideoElement.js\";\n\nexport const FILE_VIDEO_ICON_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M2 3.9934C2 3.44476 2.45531 3 2.9918 3H21.0082C21.556 3 22 3.44495 22 3.9934V20.0066C22 20.5552 21.5447 21 21.0082 21H2.9918C2.44405 21 2 20.5551 2 20.0066V3.9934ZM8 5V19H16V5H8ZM4 5V7H6V5H4ZM18 5V7H20V5H18ZM4 9V11H6V9H4ZM18 9V11H20V9H18ZM4 13V15H6V13H4ZM18 13V15H20V13H18ZM4 17V19H6V17H4ZM18 17V19H20V17H18Z\"></path></svg>';\n\nexport const videoPropSchema = {\n textAlignment: defaultProps.textAlignment,\n backgroundColor: defaultProps.backgroundColor,\n // File name.\n name: {\n default: \"\" as const,\n },\n // File url.\n url: {\n default: \"\" as const,\n },\n // File caption.\n caption: {\n default: \"\" as const,\n },\n\n showPreview: {\n default: true,\n },\n // File preview width in px.\n previewWidth: {\n default: undefined,\n type: \"number\",\n },\n} satisfies PropSchema;\n\nexport const videoBlockConfig = {\n type: \"video\" as const,\n propSchema: videoPropSchema,\n content: \"none\",\n isFileBlock: true,\n fileBlockAccept: [\"video/*\"],\n} satisfies FileBlockConfig;\n\nexport const videoRender = (\n block: BlockFromConfig<typeof videoBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n) => {\n const icon = document.createElement(\"div\");\n icon.innerHTML = FILE_VIDEO_ICON_SVG;\n\n const videoWrapper = document.createElement(\"div\");\n videoWrapper.className = \"bn-visual-media-wrapper\";\n\n const video = document.createElement(\"video\");\n video.className = \"bn-visual-media\";\n if (editor.resolveFileUrl) {\n editor.resolveFileUrl(block.props.url).then((downloadUrl) => {\n video.src = downloadUrl;\n });\n } else {\n video.src = block.props.url;\n }\n video.controls = true;\n video.contentEditable = \"false\";\n video.draggable = false;\n video.width = block.props.previewWidth;\n videoWrapper.appendChild(video);\n\n return createResizableFileBlockWrapper(\n block,\n editor,\n { dom: videoWrapper },\n videoWrapper,\n editor.dictionary.file_blocks.video.add_button_text,\n icon.firstElementChild as HTMLElement,\n );\n};\n\nexport const videoParse = (\n element: HTMLElement,\n): Partial<Props<typeof videoBlockConfig.propSchema>> | undefined => {\n if (element.tagName === \"VIDEO\") {\n // Ignore if parent figure has already been parsed.\n if (element.closest(\"figure\")) {\n return undefined;\n }\n\n return parseVideoElement(element as HTMLVideoElement);\n }\n\n if (element.tagName === \"FIGURE\") {\n const parsedFigure = parseFigureElement(element, \"video\");\n if (!parsedFigure) {\n return undefined;\n }\n\n const { targetElement, caption } = parsedFigure;\n\n return {\n ...parseVideoElement(targetElement as HTMLVideoElement),\n caption,\n };\n }\n\n return undefined;\n};\n\nexport const videoToExternalHTML = (\n block: BlockFromConfig<typeof videoBlockConfig, any, any>,\n) => {\n if (!block.props.url) {\n const div = document.createElement(\"p\");\n div.textContent = \"Add video\";\n\n return {\n dom: div,\n };\n }\n\n let video;\n if (block.props.showPreview) {\n video = document.createElement(\"video\");\n video.src = block.props.url;\n if (block.props.previewWidth) {\n video.width = block.props.previewWidth;\n }\n } else {\n video = document.createElement(\"a\");\n video.href = block.props.url;\n video.textContent = block.props.name || block.props.url;\n }\n\n if (block.props.caption) {\n if (block.props.showPreview) {\n return createFigureWithCaption(video, block.props.caption);\n } else {\n return createLinkWithCaption(video, block.props.caption);\n }\n }\n\n return {\n dom: video,\n };\n};\n\nexport const VideoBlock = createBlockSpec(videoBlockConfig, {\n render: videoRender,\n parse: videoParse,\n toExternalHTML: videoToExternalHTML,\n});\n","import Bold from \"@tiptap/extension-bold\";\nimport Code from \"@tiptap/extension-code\";\nimport Italic from \"@tiptap/extension-italic\";\nimport Strike from \"@tiptap/extension-strike\";\nimport Underline from \"@tiptap/extension-underline\";\nimport { BackgroundColor } from \"../extensions/BackgroundColor/BackgroundColorMark.js\";\nimport { TextColor } from \"../extensions/TextColor/TextColorMark.js\";\nimport {\n BlockNoDefaults,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n PartialBlockNoDefaults,\n StyleSchema,\n StyleSpecs,\n createStyleSpecFromTipTapMark,\n getBlockSchemaFromSpecs,\n getInlineContentSchemaFromSpecs,\n getStyleSchemaFromSpecs,\n} from \"../schema/index.js\";\n\nimport { AudioBlock } from \"./AudioBlockContent/AudioBlockContent.js\";\nimport { CodeBlock } from \"./CodeBlockContent/CodeBlockContent.js\";\nimport { FileBlock } from \"./FileBlockContent/FileBlockContent.js\";\nimport { Heading } from \"./HeadingBlockContent/HeadingBlockContent.js\";\nimport { ImageBlock } from \"./ImageBlockContent/ImageBlockContent.js\";\nimport { BulletListItem } from \"./ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.js\";\nimport { CheckListItem } from \"./ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.js\";\nimport { NumberedListItem } from \"./ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.js\";\nimport { Paragraph } from \"./ParagraphBlockContent/ParagraphBlockContent.js\";\nimport { Quote } from \"./QuoteBlockContent/QuoteBlockContent.js\";\nimport { Table } from \"./TableBlockContent/TableBlockContent.js\";\nimport { VideoBlock } from \"./VideoBlockContent/VideoBlockContent.js\";\n\nexport const defaultBlockSpecs = {\n paragraph: Paragraph,\n heading: Heading,\n quote: Quote,\n codeBlock: CodeBlock,\n bulletListItem: BulletListItem,\n numberedListItem: NumberedListItem,\n checkListItem: CheckListItem,\n table: Table,\n file: FileBlock,\n image: ImageBlock,\n video: VideoBlock,\n audio: AudioBlock,\n} satisfies BlockSpecs;\n\nexport const defaultBlockSchema = getBlockSchemaFromSpecs(defaultBlockSpecs);\n\n// underscore is used that in case a user overrides DefaultBlockSchema,\n// they can still access the original default block schema\nexport type _DefaultBlockSchema = typeof defaultBlockSchema;\nexport type DefaultBlockSchema = _DefaultBlockSchema;\n\nexport const defaultStyleSpecs = {\n bold: createStyleSpecFromTipTapMark(Bold, \"boolean\"),\n italic: createStyleSpecFromTipTapMark(Italic, \"boolean\"),\n underline: createStyleSpecFromTipTapMark(Underline, \"boolean\"),\n strike: createStyleSpecFromTipTapMark(Strike, \"boolean\"),\n code: createStyleSpecFromTipTapMark(Code, \"boolean\"),\n textColor: TextColor,\n backgroundColor: BackgroundColor,\n} satisfies StyleSpecs;\n\nexport const defaultStyleSchema = getStyleSchemaFromSpecs(defaultStyleSpecs);\n\n// underscore is used that in case a user overrides DefaultStyleSchema,\n// they can still access the original default style schema\nexport type _DefaultStyleSchema = typeof defaultStyleSchema;\nexport type DefaultStyleSchema = _DefaultStyleSchema;\n\nexport const defaultInlineContentSpecs = {\n text: { config: \"text\", implementation: {} as any },\n link: { config: \"link\", implementation: {} as any },\n} satisfies InlineContentSpecs;\n\nexport const defaultInlineContentSchema = getInlineContentSchemaFromSpecs(\n defaultInlineContentSpecs,\n);\n\n// underscore is used that in case a user overrides DefaultInlineContentSchema,\n// they can still access the original default inline content schema\nexport type _DefaultInlineContentSchema = typeof defaultInlineContentSchema;\nexport type DefaultInlineContentSchema = _DefaultInlineContentSchema;\n\nexport type PartialBlock<\n BSchema extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema,\n> = PartialBlockNoDefaults<BSchema, I, S>;\n\nexport type Block<\n BSchema extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema,\n> = BlockNoDefaults<BSchema, I, S>;\n","import { CellSelection } from \"prosemirror-tables\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n BlockSchema,\n FileBlockConfig,\n InlineContentSchema,\n StyleSchema,\n} from \"../schema/index.js\";\nimport {\n Block,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n defaultBlockSchema,\n defaultInlineContentSchema,\n} from \"./defaultBlocks.js\";\nimport { defaultProps } from \"./defaultProps.js\";\nimport { Selection } from \"prosemirror-state\";\n\nexport function checkDefaultBlockTypeInSchema<\n BlockType extends keyof DefaultBlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockType: BlockType,\n editor: BlockNoteEditor<any, I, S>,\n): editor is BlockNoteEditor<{ Type: DefaultBlockSchema[BlockType] }, I, S> {\n return (\n blockType in editor.schema.blockSchema &&\n editor.schema.blockSchema[blockType] === defaultBlockSchema[blockType]\n );\n}\n\nexport function checkDefaultInlineContentTypeInSchema<\n InlineContentType extends keyof DefaultInlineContentSchema,\n B extends BlockSchema,\n S extends StyleSchema,\n>(\n inlineContentType: InlineContentType,\n editor: BlockNoteEditor<B, any, S>,\n): editor is BlockNoteEditor<\n B,\n { Type: DefaultInlineContentSchema[InlineContentType] },\n S\n> {\n return (\n inlineContentType in editor.schema.inlineContentSchema &&\n editor.schema.inlineContentSchema[inlineContentType] ===\n defaultInlineContentSchema[inlineContentType]\n );\n}\n\nexport function checkBlockIsDefaultType<\n BlockType extends keyof DefaultBlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockType: BlockType,\n block: Block<any, I, S>,\n editor: BlockNoteEditor<any, I, S>,\n): block is BlockFromConfig<DefaultBlockSchema[BlockType], I, S> {\n return (\n block.type === blockType &&\n block.type in editor.schema.blockSchema &&\n checkDefaultBlockTypeInSchema(block.type, editor)\n );\n}\n\nexport function checkBlockIsFileBlock<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n block: Block<any, I, S>,\n editor: BlockNoteEditor<B, I, S>,\n): block is BlockFromConfig<FileBlockConfig, I, S> {\n return (\n (block.type in editor.schema.blockSchema &&\n editor.schema.blockSchema[block.type].isFileBlock) ||\n false\n );\n}\n\nexport function checkBlockIsFileBlockWithPreview<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n block: Block<any, I, S>,\n editor: BlockNoteEditor<B, I, S>,\n): block is BlockFromConfig<\n FileBlockConfig & {\n propSchema: Required<FileBlockConfig[\"propSchema\"]>;\n },\n I,\n S\n> {\n return (\n (block.type in editor.schema.blockSchema &&\n editor.schema.blockSchema[block.type].isFileBlock &&\n \"showPreview\" in editor.schema.blockSchema[block.type].propSchema) ||\n false\n );\n}\n\nexport function checkBlockIsFileBlockWithPlaceholder<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(block: Block<B, I, S>, editor: BlockNoteEditor<B, I, S>) {\n const config = editor.schema.blockSchema[block.type];\n return config.isFileBlock && !block.props.url;\n}\n\nexport function checkBlockTypeHasDefaultProp<\n Prop extends keyof typeof defaultProps,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n prop: Prop,\n blockType: string,\n editor: BlockNoteEditor<any, I, S>,\n): editor is BlockNoteEditor<\n {\n [BT in string]: {\n type: BT;\n propSchema: {\n [P in Prop]: (typeof defaultProps)[P];\n };\n content: \"table\" | \"inline\" | \"none\";\n };\n },\n I,\n S\n> {\n return (\n blockType in editor.schema.blockSchema &&\n prop in editor.schema.blockSchema[blockType].propSchema &&\n editor.schema.blockSchema[blockType].propSchema[prop] === defaultProps[prop]\n );\n}\n\nexport function checkBlockHasDefaultProp<\n Prop extends keyof typeof defaultProps,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n prop: Prop,\n block: Block<any, I, S>,\n editor: BlockNoteEditor<any, I, S>,\n): block is BlockFromConfig<\n {\n type: string;\n propSchema: {\n [P in Prop]: (typeof defaultProps)[P];\n };\n content: \"table\" | \"inline\" | \"none\";\n },\n I,\n S\n> {\n return checkBlockTypeHasDefaultProp(prop, block.type, editor);\n}\n\nexport function isTableCellSelection(\n selection: Selection,\n): selection is CellSelection {\n return selection instanceof CellSelection;\n}\n","/**\n * Uploads a file to tmpfiles.org and returns the URL to the uploaded file.\n *\n * @warning This function should only be used for development purposes, replace with your own backend!\n */\nexport const uploadToTmpFilesDotOrg_DEV_ONLY = async (\n file: File,\n): Promise<string> => {\n const body = new FormData();\n body.append(\"file\", file);\n\n const ret = await fetch(\"https://tmpfiles.org/api/v1/upload\", {\n method: \"POST\",\n body: body,\n });\n return (await ret.json()).data.url.replace(\n \"tmpfiles.org/\",\n \"tmpfiles.org/dl/\",\n );\n};\n","import { Block, PartialBlock } from \"../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\n\nimport { checkDefaultBlockTypeInSchema } from \"../../blocks/defaultBlockTypeGuards.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n isStyledTextInlineContent,\n} from \"../../schema/index.js\";\nimport { formatKeyboardShortcut } from \"../../util/browser.js\";\nimport { DefaultSuggestionItem } from \"./DefaultSuggestionItem.js\";\n\n// Sets the editor's text cursor position to the next content editable block,\n// so either a block with inline content or a table. The last block is always a\n// paragraph, so this function won't try to set the cursor position past the\n// last block.\nfunction setSelectionToNextContentEditableBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n let block: Block<BSchema, I, S> | undefined =\n editor.getTextCursorPosition().block;\n let contentType = editor.schema.blockSchema[block.type].content;\n\n while (contentType === \"none\") {\n block = editor.getTextCursorPosition().nextBlock;\n if (block === undefined) {\n return;\n }\n contentType = editor.schema.blockSchema[block.type].content as\n | \"inline\"\n | \"table\"\n | \"none\";\n editor.setTextCursorPosition(block, \"end\");\n }\n}\n\n// Checks if the current block is empty or only contains a slash, and if so,\n// updates the current block instead of inserting a new one below. If the new\n// block doesn't contain editable content, the cursor is moved to the next block\n// that does.\nexport function insertOrUpdateBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n block: PartialBlock<BSchema, I, S>,\n): Block<BSchema, I, S> {\n const currentBlock = editor.getTextCursorPosition().block;\n\n if (currentBlock.content === undefined) {\n throw new Error(\"Slash Menu open in a block that doesn't contain content.\");\n }\n\n let newBlock: Block<BSchema, I, S>;\n\n if (\n Array.isArray(currentBlock.content) &&\n ((currentBlock.content.length === 1 &&\n isStyledTextInlineContent(currentBlock.content[0]) &&\n currentBlock.content[0].type === \"text\" &&\n currentBlock.content[0].text === \"/\") ||\n currentBlock.content.length === 0)\n ) {\n newBlock = editor.updateBlock(currentBlock, block);\n // We make sure to reset the cursor position to the new block as calling\n // `updateBlock` may move it out. This generally happens when the content\n // changes, or the update makes the block multi-column.\n editor.setTextCursorPosition(newBlock);\n } else {\n newBlock = editor.insertBlocks([block], currentBlock, \"after\")[0];\n editor.setTextCursorPosition(editor.getTextCursorPosition().nextBlock!);\n }\n\n setSelectionToNextContentEditableBlock(editor);\n\n return newBlock;\n}\n\nexport function getDefaultSlashMenuItems<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n const items: DefaultSuggestionItem[] = [];\n\n if (checkDefaultBlockTypeInSchema(\"heading\", editor)) {\n items.push(\n {\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 1 },\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-1\"),\n key: \"heading\",\n ...editor.dictionary.slash_menu.heading,\n },\n {\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 2 },\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-2\"),\n key: \"heading_2\",\n ...editor.dictionary.slash_menu.heading_2,\n },\n {\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 3 },\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-3\"),\n key: \"heading_3\",\n ...editor.dictionary.slash_menu.heading_3,\n },\n );\n }\n\n if (checkDefaultBlockTypeInSchema(\"quote\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"quote\",\n });\n },\n key: \"quote\",\n ...editor.dictionary.slash_menu.quote,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"numberedListItem\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"numberedListItem\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Shift-7\"),\n key: \"numbered_list\",\n ...editor.dictionary.slash_menu.numbered_list,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"bulletListItem\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"bulletListItem\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Shift-8\"),\n key: \"bullet_list\",\n ...editor.dictionary.slash_menu.bullet_list,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"checkListItem\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"checkListItem\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Shift-9\"),\n key: \"check_list\",\n ...editor.dictionary.slash_menu.check_list,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"paragraph\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"paragraph\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-0\"),\n key: \"paragraph\",\n ...editor.dictionary.slash_menu.paragraph,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"codeBlock\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"codeBlock\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-c\"),\n key: \"code_block\",\n ...editor.dictionary.slash_menu.code_block,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"table\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"table\",\n content: {\n type: \"tableContent\",\n rows: [\n {\n cells: [\"\", \"\", \"\"],\n },\n {\n cells: [\"\", \"\", \"\"],\n },\n ],\n },\n });\n },\n badge: undefined,\n key: \"table\",\n ...editor.dictionary.slash_menu.table,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"image\", editor)) {\n items.push({\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"image\",\n });\n\n // Immediately open the file toolbar\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: insertedBlock,\n }),\n );\n },\n key: \"image\",\n ...editor.dictionary.slash_menu.image,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"video\", editor)) {\n items.push({\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"video\",\n });\n\n // Immediately open the file toolbar\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: insertedBlock,\n }),\n );\n },\n key: \"video\",\n ...editor.dictionary.slash_menu.video,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"audio\", editor)) {\n items.push({\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"audio\",\n });\n\n // Immediately open the file toolbar\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: insertedBlock,\n }),\n );\n },\n key: \"audio\",\n ...editor.dictionary.slash_menu.audio,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"file\", editor)) {\n items.push({\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"file\",\n });\n\n // Immediately open the file toolbar\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: insertedBlock,\n }),\n );\n },\n key: \"file\",\n ...editor.dictionary.slash_menu.file,\n });\n }\n\n items.push({\n onItemClick: () => {\n editor.openSuggestionMenu(\":\", {\n deleteTriggerCharacter: true,\n ignoreQueryLength: true,\n });\n },\n key: \"emoji\",\n ...editor.dictionary.slash_menu.emoji,\n });\n\n return items;\n}\n\nexport function filterSuggestionItems<\n T extends { title: string; aliases?: readonly string[] },\n>(items: T[], query: string) {\n return items.filter(\n ({ title, aliases }) =>\n title.toLowerCase().includes(query.toLowerCase()) ||\n (aliases &&\n aliases.filter((alias) =>\n alias.toLowerCase().includes(query.toLowerCase()),\n ).length !== 0),\n );\n}\n","import {\n defaultBlockSpecs,\n defaultInlineContentSpecs,\n defaultStyleSpecs,\n} from \"../blocks/defaultBlocks.js\";\nimport type {\n BlockNoDefaults,\n PartialBlockNoDefaults,\n} from \"../schema/blocks/types.js\";\nimport {\n BlockSchema,\n BlockSchemaFromSpecs,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSchemaFromSpecs,\n InlineContentSpecs,\n StyleSchema,\n StyleSchemaFromSpecs,\n StyleSpecs,\n getBlockSchemaFromSpecs,\n getInlineContentSchemaFromSpecs,\n getStyleSchemaFromSpecs,\n} from \"../schema/index.js\";\nimport type { BlockNoteEditor } from \"./BlockNoteEditor.js\";\n\nfunction removeUndefined<T extends Record<string, any> | undefined>(obj: T): T {\n if (!obj) {\n return obj;\n }\n return Object.fromEntries(\n Object.entries(obj).filter(([, value]) => value !== undefined),\n ) as T;\n}\n\nexport class BlockNoteSchema<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema,\n> {\n public readonly blockSpecs: BlockSpecs;\n public readonly inlineContentSpecs: InlineContentSpecs;\n public readonly styleSpecs: StyleSpecs;\n\n public readonly blockSchema: BSchema;\n public readonly inlineContentSchema: ISchema;\n public readonly styleSchema: SSchema;\n\n // Helper so that you can use typeof schema.BlockNoteEditor\n public readonly BlockNoteEditor: BlockNoteEditor<BSchema, ISchema, SSchema> =\n \"only for types\" as any;\n\n public readonly Block: BlockNoDefaults<BSchema, ISchema, SSchema> =\n \"only for types\" as any;\n\n public readonly PartialBlock: PartialBlockNoDefaults<\n BSchema,\n ISchema,\n SSchema\n > = \"only for types\" as any;\n\n public static create<\n BSpecs extends BlockSpecs = typeof defaultBlockSpecs,\n ISpecs extends InlineContentSpecs = typeof defaultInlineContentSpecs,\n SSpecs extends StyleSpecs = typeof defaultStyleSpecs,\n >(options?: {\n /**\n * A list of custom block types that should be available in the editor.\n */\n blockSpecs?: BSpecs;\n /**\n * A list of custom InlineContent types that should be available in the editor.\n */\n inlineContentSpecs?: ISpecs;\n /**\n * A list of custom Styles that should be available in the editor.\n */\n styleSpecs?: SSpecs;\n }) {\n return new BlockNoteSchema<\n BlockSchemaFromSpecs<BSpecs>,\n InlineContentSchemaFromSpecs<ISpecs>,\n StyleSchemaFromSpecs<SSpecs>\n >(options);\n // as BlockNoteSchema<\n // BlockSchemaFromSpecs<BSpecs>,\n // InlineContentSchemaFromSpecs<ISpecs>,\n // StyleSchemaFromSpecs<SSpecs>\n // >;\n }\n\n constructor(opts?: {\n blockSpecs?: BlockSpecs;\n inlineContentSpecs?: InlineContentSpecs;\n styleSpecs?: StyleSpecs;\n }) {\n this.blockSpecs = removeUndefined(opts?.blockSpecs) || defaultBlockSpecs;\n this.inlineContentSpecs =\n removeUndefined(opts?.inlineContentSpecs) || defaultInlineContentSpecs;\n this.styleSpecs = removeUndefined(opts?.styleSpecs) || defaultStyleSpecs;\n\n this.blockSchema = getBlockSchemaFromSpecs(this.blockSpecs) as any;\n this.inlineContentSchema = getInlineContentSchemaFromSpecs(\n this.inlineContentSpecs,\n ) as any;\n this.styleSchema = getStyleSchemaFromSpecs(this.styleSpecs) as any;\n }\n}\n","import {\n createBlockSpec,\n CustomBlockConfig,\n Props,\n} from \"../../schema/index.js\";\n\nexport const pageBreakConfig = {\n type: \"pageBreak\" as const,\n propSchema: {},\n content: \"none\",\n isFileBlock: false,\n isSelectable: false,\n} satisfies CustomBlockConfig;\nexport const pageBreakRender = () => {\n const pageBreak = document.createElement(\"div\");\n\n pageBreak.className = \"bn-page-break\";\n pageBreak.setAttribute(\"data-page-break\", \"\");\n\n return {\n dom: pageBreak,\n };\n};\nexport const pageBreakParse = (\n element: HTMLElement,\n): Partial<Props<typeof pageBreakConfig.propSchema>> | undefined => {\n if (element.tagName === \"DIV\" && element.hasAttribute(\"data-page-break\")) {\n return {\n type: \"pageBreak\",\n };\n }\n\n return undefined;\n};\nexport const pageBreakToExternalHTML = () => {\n const pageBreak = document.createElement(\"div\");\n\n pageBreak.setAttribute(\"data-page-break\", \"\");\n\n return {\n dom: pageBreak,\n };\n};\n\nexport const PageBreak = createBlockSpec(pageBreakConfig, {\n render: pageBreakRender,\n parse: pageBreakParse,\n toExternalHTML: pageBreakToExternalHTML,\n});\n","import { BlockNoteSchema } from \"../../editor/BlockNoteSchema.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { PageBreak } from \"./PageBreakBlockContent.js\";\n\nexport const pageBreakSchema = BlockNoteSchema.create({\n blockSpecs: {\n pageBreak: PageBreak,\n },\n});\n\n/**\n * Adds page break support to the given schema.\n */\nexport const withPageBreak = <\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n schema: BlockNoteSchema<B, I, S>,\n) => {\n return BlockNoteSchema.create({\n blockSpecs: {\n ...schema.blockSpecs,\n ...pageBreakSchema.blockSpecs,\n },\n inlineContentSpecs: schema.inlineContentSpecs,\n styleSpecs: schema.styleSpecs,\n }) as any as BlockNoteSchema<\n // typescript needs some help here\n B & {\n pageBreak: typeof PageBreak.config;\n },\n I,\n S\n >;\n};\n","import { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { DefaultSuggestionItem } from \"../../extensions/SuggestionMenu/DefaultSuggestionItem.js\";\nimport { insertOrUpdateBlock } from \"../../extensions/SuggestionMenu/getDefaultSlashMenuItems.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { pageBreakSchema } from \"./schema.js\";\n\nexport function checkPageBreakBlocksInSchema<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<any, I, S>,\n): editor is BlockNoteEditor<typeof pageBreakSchema.blockSchema, I, S> {\n return (\n \"pageBreak\" in editor.schema.blockSchema &&\n editor.schema.blockSchema[\"pageBreak\"] ===\n pageBreakSchema.blockSchema[\"pageBreak\"]\n );\n}\n\nexport function getPageBreakSlashMenuItems<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n const items: (Omit<DefaultSuggestionItem, \"key\"> & { key: \"page_break\" })[] =\n [];\n\n if (checkPageBreakBlocksInSchema(editor)) {\n items.push({\n ...editor.dictionary.slash_menu.page_break,\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"pageBreak\",\n });\n },\n key: \"page_break\",\n });\n }\n\n return items;\n}\n","import {\n NodeSelection,\n Selection,\n TextSelection,\n Transaction,\n} from \"prosemirror-state\";\nimport { CellSelection } from \"prosemirror-tables\";\n\nimport { Block } from \"../../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor\";\nimport { BlockIdentifier } from \"../../../../schema/index.js\";\nimport { getNearestBlockPos } from \"../../../getBlockInfoFromPos.js\";\nimport { getNodeById } from \"../../../nodeUtil.js\";\n\ntype BlockSelectionData = (\n | {\n type: \"text\";\n headBlockId: string;\n anchorOffset: number;\n headOffset: number;\n }\n | {\n type: \"node\";\n }\n | {\n type: \"cell\";\n anchorCellOffset: number;\n headCellOffset: number;\n }\n) & {\n anchorBlockId: string;\n};\n\n/**\n * `getBlockSelectionData` and `updateBlockSelectionFromData` are used to save\n * and restore the selection within a block, when the block is moved. This is\n * done by first saving the offsets of the anchor and head from the before\n * positions of their surrounding blocks, as well as the IDs of those blocks. We\n * can then recreate the selection by finding the blocks with those IDs, getting\n * their before positions, and adding the offsets to those positions.\n * @param editor The BlockNote editor instance to get the selection data from.\n */\nfunction getBlockSelectionData(\n editor: BlockNoteEditor<any, any, any>,\n): BlockSelectionData {\n return editor.transact((tr) => {\n const anchorBlockPosInfo = getNearestBlockPos(tr.doc, tr.selection.anchor);\n\n if (tr.selection instanceof CellSelection) {\n return {\n type: \"cell\" as const,\n anchorBlockId: anchorBlockPosInfo.node.attrs.id,\n anchorCellOffset:\n tr.selection.$anchorCell.pos - anchorBlockPosInfo.posBeforeNode,\n headCellOffset:\n tr.selection.$headCell.pos - anchorBlockPosInfo.posBeforeNode,\n };\n } else if (tr.selection instanceof NodeSelection) {\n return {\n type: \"node\" as const,\n anchorBlockId: anchorBlockPosInfo.node.attrs.id,\n };\n } else {\n const headBlockPosInfo = getNearestBlockPos(tr.doc, tr.selection.head);\n\n return {\n type: \"text\" as const,\n anchorBlockId: anchorBlockPosInfo.node.attrs.id,\n headBlockId: headBlockPosInfo.node.attrs.id,\n anchorOffset: tr.selection.anchor - anchorBlockPosInfo.posBeforeNode,\n headOffset: tr.selection.head - headBlockPosInfo.posBeforeNode,\n };\n }\n });\n}\n\n/**\n * `getBlockSelectionData` and `updateBlockSelectionFromData` are used to save\n * and restore the selection within a block, when the block is moved. This is\n * done by first saving the offsets of the anchor and head from the before\n * positions of their surrounding blocks, as well as the IDs of those blocks. We\n * can then recreate the selection by finding the blocks with those IDs, getting\n * their before positions, and adding the offsets to those positions.\n * @param tr The transaction to update the selection in.\n * @param data The selection data to update the selection with (generated by\n * `getBlockSelectionData`).\n */\nfunction updateBlockSelectionFromData(\n tr: Transaction,\n data: BlockSelectionData,\n) {\n const anchorBlockPos = getNodeById(data.anchorBlockId, tr.doc)?.posBeforeNode;\n if (anchorBlockPos === undefined) {\n throw new Error(\n `Could not find block with ID ${data.anchorBlockId} to update selection`,\n );\n }\n\n let selection: Selection;\n if (data.type === \"cell\") {\n selection = CellSelection.create(\n tr.doc,\n anchorBlockPos + data.anchorCellOffset,\n anchorBlockPos + data.headCellOffset,\n );\n } else if (data.type === \"node\") {\n selection = NodeSelection.create(tr.doc, anchorBlockPos + 1);\n } else {\n const headBlockPos = getNodeById(data.headBlockId, tr.doc)?.posBeforeNode;\n if (headBlockPos === undefined) {\n throw new Error(\n `Could not find block with ID ${data.headBlockId} to update selection`,\n );\n }\n\n selection = TextSelection.create(\n tr.doc,\n anchorBlockPos + data.anchorOffset,\n headBlockPos + data.headOffset,\n );\n }\n\n tr.setSelection(selection);\n}\n\n/**\n * Replaces any `columnList` blocks with the children of their columns. This is\n * done here instead of in `getSelection` as we still need to remove the entire\n * `columnList` node but only insert the `blockContainer` nodes inside it.\n * @param blocks The blocks to flatten.\n */\nfunction flattenColumns(\n blocks: Block<any, any, any>[],\n): Block<any, any, any>[] {\n return blocks\n .map((block) => {\n if (block.type === \"columnList\") {\n return block.children\n .map((column) => flattenColumns(column.children))\n .flat();\n }\n\n return {\n ...block,\n children: flattenColumns(block.children),\n };\n })\n .flat();\n}\n\n/**\n * Removes the selected blocks from the editor, then inserts them before/after a\n * reference block. Also updates the selection to match the original selection\n * using `getBlockSelectionData` and `updateBlockSelectionFromData`.\n * @param editor The BlockNote editor instance to move the blocks in.\n * @param referenceBlock The reference block to insert the selected blocks\n * before/after.\n * @param placement Whether to insert the selected blocks before or after the\n * reference block.\n */\nexport function moveSelectedBlocksAndSelection(\n editor: BlockNoteEditor<any, any, any>,\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\",\n) {\n // We want this to be a single step in the undo history\n editor.transact((tr) => {\n const blocks = editor.getSelection()?.blocks || [\n editor.getTextCursorPosition().block,\n ];\n const selectionData = getBlockSelectionData(editor);\n\n editor.removeBlocks(blocks);\n editor.insertBlocks(flattenColumns(blocks), referenceBlock, placement);\n\n updateBlockSelectionFromData(tr, selectionData);\n });\n}\n\n// Checks if a block is in a valid place after being moved. This check is\n// primitive at the moment and only returns false if the block's parent is a\n// `columnList` block. This is because regular blocks cannot be direct children\n// of `columnList` blocks.\nfunction checkPlacementIsValid(parentBlock?: Block<any, any, any>): boolean {\n return !parentBlock || parentBlock.type !== \"columnList\";\n}\n\n// Gets the placement for moving a block up. This has 3 cases:\n// 1. If the block has a previous sibling without children, the placement is\n// before it.\n// 2. If the block has a previous sibling with children, the placement is after\n// the last child.\n// 3. If the block has no previous sibling, but is nested, the placement is\n// before its parent.\n// If the placement is invalid, the function is called recursively until a valid\n// placement is found. Returns undefined if no valid placement is found, meaning\n// the block is already at the top of the document.\nfunction getMoveUpPlacement(\n editor: BlockNoteEditor<any, any, any>,\n prevBlock?: Block<any, any, any>,\n parentBlock?: Block<any, any, any>,\n):\n | { referenceBlock: BlockIdentifier; placement: \"before\" | \"after\" }\n | undefined {\n let referenceBlock: Block<any, any, any> | undefined;\n let placement: \"before\" | \"after\" | undefined;\n\n if (!prevBlock) {\n if (parentBlock) {\n referenceBlock = parentBlock;\n placement = \"before\";\n }\n } else if (prevBlock.children.length > 0) {\n referenceBlock = prevBlock.children[prevBlock.children.length - 1];\n placement = \"after\";\n } else {\n referenceBlock = prevBlock;\n placement = \"before\";\n }\n\n // Case when the block is already at the top of the document.\n if (!referenceBlock || !placement) {\n return undefined;\n }\n\n const referenceBlockParent = editor.getParentBlock(referenceBlock);\n if (!checkPlacementIsValid(referenceBlockParent)) {\n return getMoveUpPlacement(\n editor,\n placement === \"after\"\n ? referenceBlock\n : editor.getPrevBlock(referenceBlock),\n referenceBlockParent,\n );\n }\n\n return { referenceBlock, placement };\n}\n\n// Gets the placement for moving a block down. This has 3 cases:\n// 1. If the block has a next sibling without children, the placement is after\n// it.\n// 2. If the block has a next sibling with children, the placement is before the\n// first child.\n// 3. If the block has no next sibling, but is nested, the placement is\n// after its parent.\n// If the placement is invalid, the function is called recursively until a valid\n// placement is found. Returns undefined if no valid placement is found, meaning\n// the block is already at the bottom of the document.\nfunction getMoveDownPlacement(\n editor: BlockNoteEditor<any, any, any>,\n nextBlock?: Block<any, any, any>,\n parentBlock?: Block<any, any, any>,\n):\n | { referenceBlock: BlockIdentifier; placement: \"before\" | \"after\" }\n | undefined {\n let referenceBlock: Block<any, any, any> | undefined;\n let placement: \"before\" | \"after\" | undefined;\n\n if (!nextBlock) {\n if (parentBlock) {\n referenceBlock = parentBlock;\n placement = \"after\";\n }\n } else if (nextBlock.children.length > 0) {\n referenceBlock = nextBlock.children[0];\n placement = \"before\";\n } else {\n referenceBlock = nextBlock;\n placement = \"after\";\n }\n\n // Case when the block is already at the bottom of the document.\n if (!referenceBlock || !placement) {\n return undefined;\n }\n\n const referenceBlockParent = editor.getParentBlock(referenceBlock);\n if (!checkPlacementIsValid(referenceBlockParent)) {\n return getMoveDownPlacement(\n editor,\n placement === \"before\"\n ? referenceBlock\n : editor.getNextBlock(referenceBlock),\n referenceBlockParent,\n );\n }\n\n return { referenceBlock, placement };\n}\n\nexport function moveBlocksUp(editor: BlockNoteEditor<any, any, any>) {\n editor.transact(() => {\n const selection = editor.getSelection();\n const block = selection?.blocks[0] || editor.getTextCursorPosition().block;\n\n const moveUpPlacement = getMoveUpPlacement(\n editor,\n editor.getPrevBlock(block),\n editor.getParentBlock(block),\n );\n\n if (!moveUpPlacement) {\n return;\n }\n\n moveSelectedBlocksAndSelection(\n editor,\n moveUpPlacement.referenceBlock,\n moveUpPlacement.placement,\n );\n });\n}\n\nexport function moveBlocksDown(editor: BlockNoteEditor<any, any, any>) {\n editor.transact(() => {\n const selection = editor.getSelection();\n const block =\n selection?.blocks[selection?.blocks.length - 1] ||\n editor.getTextCursorPosition().block;\n\n const moveDownPlacement = getMoveDownPlacement(\n editor,\n editor.getNextBlock(block),\n editor.getParentBlock(block),\n );\n\n if (!moveDownPlacement) {\n return;\n }\n\n moveSelectedBlocksAndSelection(\n editor,\n moveDownPlacement.referenceBlock,\n moveDownPlacement.placement,\n );\n });\n}\n","import { Fragment, NodeType, Slice } from \"prosemirror-model\";\nimport { EditorState, Transaction } from \"prosemirror-state\";\nimport { ReplaceAroundStep } from \"prosemirror-transform\";\n\nimport { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport { getBlockInfoFromTransaction } from \"../../../getBlockInfoFromPos.js\";\n\n// TODO: Unit tests\n/**\n * This is a modified version of https://github.com/ProseMirror/prosemirror-schema-list/blob/569c2770cbb8092d8f11ea53ecf78cb7a4e8f15a/src/schema-list.ts#L232\n *\n * The original function derives too many information from the parentnode and itemtype\n */\nfunction sinkListItem(itemType: NodeType, groupType: NodeType) {\n return function (state: EditorState, dispatch?: (tr: Transaction) => void) {\n const { $from, $to } = state.selection;\n const range = $from.blockRange(\n $to,\n (node) =>\n node.childCount > 0 &&\n (node.type.name === \"blockGroup\" || node.type.name === \"column\"), // change necessary to not look at first item child type\n );\n if (!range) {\n return false;\n }\n const startIndex = range.startIndex;\n if (startIndex === 0) {\n return false;\n }\n const parent = range.parent;\n const nodeBefore = parent.child(startIndex - 1);\n if (nodeBefore.type !== itemType) {\n return false;\n }\n if (dispatch) {\n const nestedBefore =\n nodeBefore.lastChild && nodeBefore.lastChild.type === groupType; // change necessary to check groupType instead of parent.type\n const inner = Fragment.from(nestedBefore ? itemType.create() : null);\n const slice = new Slice(\n Fragment.from(\n itemType.create(null, Fragment.from(groupType.create(null, inner))), // change necessary to create \"groupType\" instead of parent.type\n ),\n nestedBefore ? 3 : 1,\n 0,\n );\n\n const before = range.start;\n const after = range.end;\n dispatch(\n state.tr\n .step(\n new ReplaceAroundStep(\n before - (nestedBefore ? 3 : 1),\n after,\n before,\n after,\n slice,\n 1,\n true,\n ),\n )\n .scrollIntoView(),\n );\n }\n return true;\n };\n}\n\nexport function nestBlock(editor: BlockNoteEditor<any, any, any>) {\n return editor.exec((state, dispatch) =>\n sinkListItem(\n state.schema.nodes[\"blockContainer\"],\n state.schema.nodes[\"blockGroup\"],\n )(state, dispatch),\n );\n}\n\nexport function unnestBlock(editor: BlockNoteEditor<any, any, any>) {\n editor._tiptapEditor.commands.liftListItem(\"blockContainer\");\n}\n\nexport function canNestBlock(editor: BlockNoteEditor<any, any, any>) {\n return editor.transact((tr) => {\n const { bnBlock: blockContainer } = getBlockInfoFromTransaction(tr);\n\n return tr.doc.resolve(blockContainer.beforePos).nodeBefore !== null;\n });\n}\n\nexport function canUnnestBlock(editor: BlockNoteEditor<any, any, any>) {\n return editor.transact((tr) => {\n const { bnBlock: blockContainer } = getBlockInfoFromTransaction(tr);\n\n return tr.doc.resolve(blockContainer.beforePos).depth > 1;\n });\n}\n","import type { Node } from \"prosemirror-model\";\nimport type { Block } from \"../../../blocks/defaultBlocks.js\";\nimport type {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { nodeToBlock } from \"../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../nodeUtil.js\";\nimport { getPmSchema } from \"../../pmUtil.js\";\n\nexport function getBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n blockIdentifier: BlockIdentifier,\n): Block<BSchema, I, S> | undefined {\n const id =\n typeof blockIdentifier === \"string\" ? blockIdentifier : blockIdentifier.id;\n const pmSchema = getPmSchema(doc);\n\n const posInfo = getNodeById(id, doc);\n if (!posInfo) {\n return undefined;\n }\n\n return nodeToBlock(posInfo.node, pmSchema);\n}\n\nexport function getPrevBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n blockIdentifier: BlockIdentifier,\n): Block<BSchema, I, S> | undefined {\n const id =\n typeof blockIdentifier === \"string\" ? blockIdentifier : blockIdentifier.id;\n\n const posInfo = getNodeById(id, doc);\n const pmSchema = getPmSchema(doc);\n if (!posInfo) {\n return undefined;\n }\n\n const $posBeforeNode = doc.resolve(posInfo.posBeforeNode);\n const nodeToConvert = $posBeforeNode.nodeBefore;\n if (!nodeToConvert) {\n return undefined;\n }\n\n return nodeToBlock(nodeToConvert, pmSchema);\n}\n\nexport function getNextBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n blockIdentifier: BlockIdentifier,\n): Block<BSchema, I, S> | undefined {\n const id =\n typeof blockIdentifier === \"string\" ? blockIdentifier : blockIdentifier.id;\n const posInfo = getNodeById(id, doc);\n const pmSchema = getPmSchema(doc);\n if (!posInfo) {\n return undefined;\n }\n\n const $posAfterNode = doc.resolve(\n posInfo.posBeforeNode + posInfo.node.nodeSize,\n );\n const nodeToConvert = $posAfterNode.nodeAfter;\n if (!nodeToConvert) {\n return undefined;\n }\n\n return nodeToBlock(nodeToConvert, pmSchema);\n}\n\nexport function getParentBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n blockIdentifier: BlockIdentifier,\n): Block<BSchema, I, S> | undefined {\n const id =\n typeof blockIdentifier === \"string\" ? blockIdentifier : blockIdentifier.id;\n const pmSchema = getPmSchema(doc);\n const posInfo = getNodeById(id, doc);\n if (!posInfo) {\n return undefined;\n }\n\n const $posBeforeNode = doc.resolve(posInfo.posBeforeNode);\n const parentNode = $posBeforeNode.node();\n const grandparentNode = $posBeforeNode.node(-1);\n const nodeToConvert =\n grandparentNode.type.name !== \"doc\"\n ? parentNode.type.name === \"blockGroup\"\n ? grandparentNode\n : parentNode\n : undefined;\n if (!nodeToConvert) {\n return undefined;\n }\n\n return nodeToBlock(nodeToConvert, pmSchema);\n}\n","import { selectionToInsertionEnd } from \"@tiptap/core\";\nimport { Node } from \"prosemirror-model\";\n\nimport type { Transaction } from \"prosemirror-state\";\n\n// similar to tiptap insertContentAt\nexport function insertContentAt(\n tr: Transaction,\n position: number | { from: number; to: number },\n nodes: Node[],\n options: {\n updateSelection: boolean;\n } = { updateSelection: true },\n) {\n // don’t dispatch an empty fragment because this can lead to strange errors\n // if (content.toString() === \"<>\") {\n // return true;\n // }\n\n let { from, to } =\n typeof position === \"number\"\n ? { from: position, to: position }\n : { from: position.from, to: position.to };\n\n let isOnlyTextContent = true;\n let isOnlyBlockContent = true;\n // const nodes = isFragment(content) ? content : [content];\n\n let text = \"\";\n\n nodes.forEach((node) => {\n // check if added node is valid\n node.check();\n\n if (isOnlyTextContent && node.isText && node.marks.length === 0) {\n text += node.text;\n } else {\n isOnlyTextContent = false;\n }\n\n isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;\n });\n\n // check if we can replace the wrapping node by\n // the newly inserted content\n // example:\n // replace an empty paragraph by an inserted image\n // instead of inserting the image below the paragraph\n if (from === to && isOnlyBlockContent) {\n const { parent } = tr.doc.resolve(from);\n const isEmptyTextBlock =\n parent.isTextblock && !parent.type.spec.code && !parent.childCount;\n\n if (isEmptyTextBlock) {\n from -= 1;\n to += 1;\n }\n }\n\n // if there is only plain text we have to use `insertText`\n // because this will keep the current marks\n if (isOnlyTextContent) {\n // if value is string, we can use it directly\n // otherwise if it is an array, we have to join it\n // if (Array.isArray(value)) {\n // tr.insertText(value.map((v) => v.text || \"\").join(\"\"), from, to);\n // } else if (typeof value === \"object\" && !!value && !!value.text) {\n // tr.insertText(value.text, from, to);\n // } else {\n // tr.insertText(value as string, from, to);\n // }\n tr.insertText(text, from, to);\n } else {\n tr.replaceWith(from, to, nodes);\n }\n\n // set cursor at end of inserted content\n if (options.updateSelection) {\n selectionToInsertionEnd(tr, tr.steps.length - 1, -1);\n }\n\n return true;\n}\n","import { TextSelection, type Transaction } from \"prosemirror-state\";\nimport { TableMap } from \"prosemirror-tables\";\n\nimport { Block } from \"../../../blocks/defaultBlocks.js\";\nimport { Selection } from \"../../../editor/selectionTypes.js\";\nimport {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { getBlockInfo, getNearestBlockPos } from \"../../getBlockInfoFromPos.js\";\nimport {\n nodeToBlock,\n prosemirrorSliceToSlicedBlocks,\n} from \"../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../nodeUtil.js\";\nimport { getBlockNoteSchema, getPmSchema } from \"../../pmUtil.js\";\n\nexport function getSelection<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(tr: Transaction): Selection<BSchema, I, S> | undefined {\n const pmSchema = getPmSchema(tr);\n // Return undefined if the selection is collapsed or a node is selected.\n if (tr.selection.empty || \"node\" in tr.selection) {\n return undefined;\n }\n\n const $startBlockBeforePos = tr.doc.resolve(\n getNearestBlockPos(tr.doc, tr.selection.from).posBeforeNode,\n );\n const $endBlockBeforePos = tr.doc.resolve(\n getNearestBlockPos(tr.doc, tr.selection.to).posBeforeNode,\n );\n\n // Converts the node at the given index and depth around `$startBlockBeforePos`\n // to a block. Used to get blocks at given indices at the shared depth and\n // at the depth of `$startBlockBeforePos`.\n const indexToBlock = (\n index: number,\n depth?: number,\n ): Block<BSchema, I, S> => {\n const pos = $startBlockBeforePos.posAtIndex(index, depth);\n const node = tr.doc.resolve(pos).nodeAfter;\n\n if (!node) {\n throw new Error(\n `Error getting selection - node not found at position ${pos}`,\n );\n }\n\n return nodeToBlock(node, pmSchema);\n };\n\n const blocks: Block<BSchema, I, S>[] = [];\n // Minimum depth at which the blocks share a common ancestor.\n const sharedDepth = $startBlockBeforePos.sharedDepth($endBlockBeforePos.pos);\n const startIndex = $startBlockBeforePos.index(sharedDepth);\n const endIndex = $endBlockBeforePos.index(sharedDepth);\n\n // In most cases, we want to return the blocks spanned by the selection at the\n // shared depth. However, when the block in which the selection starts is at a\n // higher depth than the shared depth, we omit the first block at the shared\n // depth. Instead, we include the first block at its depth, and any blocks at\n // a higher index up to the shared depth. The following example illustrates\n // this:\n // - id-0\n // - id-1\n // - >|id-2\n // - id-3\n // - id-4\n // - id-5\n // - id-6\n // - id-7\n // - id-8\n // - id-9|<\n // - id-10\n // Here, each block is represented by its ID, and the selection is represented\n // by the `>|` and `|<` markers. So the selection starts in block `id-2` and\n // ends in block `id-8`. In this case, the shared depth is 0, since the blocks\n // `id-6`, `id-7`, and `id-8` set the shared depth, as they are the least\n // nested blocks spanned by the selection. Therefore, these blocks are all\n // added to the `blocks` array. However, the selection starts in block `id-2`,\n // which is at a higher depth than the shared depth. So we add block `id-2` to\n // the `blocks` array, as well as any later siblings (in this case, `id-3`),\n // and move up one level of depth. The ancestor of block `id-2` at this depth\n // is block `id-1`, so we add all its later siblings to the `blocks` array as\n // well, again moving up one level of depth. Since we're now at the shared\n // depth, we are done. The final `blocks` array for this example would be:\n // [ id-2, id-3, id-4, id-6, id-7, id-8, id-9 ]\n if ($startBlockBeforePos.depth > sharedDepth) {\n // Adds the block that the selection starts in.\n blocks.push(nodeToBlock($startBlockBeforePos.nodeAfter!, pmSchema));\n\n // Traverses all depths from the depth of the block in which the selection\n // starts, up to the shared depth.\n for (let depth = $startBlockBeforePos.depth; depth > sharedDepth; depth--) {\n const parentNode = $startBlockBeforePos.node(depth);\n\n if (parentNode.type.isInGroup(\"childContainer\")) {\n const startIndexAtDepth = $startBlockBeforePos.index(depth) + 1;\n const childCountAtDepth = $startBlockBeforePos.node(depth).childCount;\n\n // Adds all blocks after the index of the block in which the selection\n // starts (or its ancestors at lower depths).\n for (let i = startIndexAtDepth; i < childCountAtDepth; i++) {\n blocks.push(indexToBlock(i, depth));\n }\n }\n }\n } else {\n // Adds the first block spanned by the selection at the shared depth.\n blocks.push(indexToBlock(startIndex, sharedDepth));\n }\n\n // Adds all blocks spanned by the selection at the shared depth, excluding\n // the first.\n for (let i = startIndex + 1; i <= endIndex; i++) {\n blocks.push(indexToBlock(i, sharedDepth));\n }\n\n if (blocks.length === 0) {\n throw new Error(\n `Error getting selection - selection doesn't span any blocks (${tr.selection})`,\n );\n }\n\n return {\n blocks,\n };\n}\n\nexport function setSelection(\n tr: Transaction,\n startBlock: BlockIdentifier,\n endBlock: BlockIdentifier,\n) {\n const startBlockId =\n typeof startBlock === \"string\" ? startBlock : startBlock.id;\n const endBlockId = typeof endBlock === \"string\" ? endBlock : endBlock.id;\n const pmSchema = getPmSchema(tr);\n const schema = getBlockNoteSchema(pmSchema);\n\n if (startBlockId === endBlockId) {\n throw new Error(\n `Attempting to set selection with the same anchor and head blocks (id ${startBlockId})`,\n );\n }\n const anchorPosInfo = getNodeById(startBlockId, tr.doc);\n if (!anchorPosInfo) {\n throw new Error(`Block with ID ${startBlockId} not found`);\n }\n const headPosInfo = getNodeById(endBlockId, tr.doc);\n if (!headPosInfo) {\n throw new Error(`Block with ID ${endBlockId} not found`);\n }\n\n const anchorBlockInfo = getBlockInfo(anchorPosInfo);\n const headBlockInfo = getBlockInfo(headPosInfo);\n\n const anchorBlockConfig =\n schema.blockSchema[\n anchorBlockInfo.blockNoteType as keyof typeof schema.blockSchema\n ];\n const headBlockConfig =\n schema.blockSchema[\n headBlockInfo.blockNoteType as keyof typeof schema.blockSchema\n ];\n\n if (\n !anchorBlockInfo.isBlockContainer ||\n anchorBlockConfig.content === \"none\"\n ) {\n throw new Error(\n `Attempting to set selection anchor in block without content (id ${startBlockId})`,\n );\n }\n if (!headBlockInfo.isBlockContainer || headBlockConfig.content === \"none\") {\n throw new Error(\n `Attempting to set selection anchor in block without content (id ${endBlockId})`,\n );\n }\n\n let startPos: number;\n let endPos: number;\n\n if (anchorBlockConfig.content === \"table\") {\n const tableMap = TableMap.get(anchorBlockInfo.blockContent.node);\n const firstCellPos =\n anchorBlockInfo.blockContent.beforePos +\n tableMap.positionAt(0, 0, anchorBlockInfo.blockContent.node) +\n 1;\n startPos = firstCellPos + 2;\n } else {\n startPos = anchorBlockInfo.blockContent.beforePos + 1;\n }\n\n if (headBlockConfig.content === \"table\") {\n const tableMap = TableMap.get(headBlockInfo.blockContent.node);\n const lastCellPos =\n headBlockInfo.blockContent.beforePos +\n tableMap.positionAt(\n tableMap.height - 1,\n tableMap.width - 1,\n headBlockInfo.blockContent.node,\n ) +\n 1;\n const lastCellNodeSize = tr.doc.resolve(lastCellPos).nodeAfter!.nodeSize;\n endPos = lastCellPos + lastCellNodeSize - 2;\n } else {\n endPos = headBlockInfo.blockContent.afterPos - 1;\n }\n\n // TODO: We should polish up the `MultipleNodeSelection` and use that instead.\n // Right now it's missing a few things like a jsonID and styling to show\n // which nodes are selected. `TextSelection` is ok for now, but has the\n // restriction that the start/end blocks must have content.\n tr.setSelection(TextSelection.create(tr.doc, startPos, endPos));\n}\n\nexport function getSelectionCutBlocks(tr: Transaction) {\n // TODO: fix image node selection\n\n const pmSchema = getPmSchema(tr);\n let start = tr.selection.$from;\n let end = tr.selection.$to;\n\n // the selection moves below are used to make sure `prosemirrorSliceToSlicedBlocks` returns\n // the correct information about whether content is cut at the start or end of a block\n\n // if the end is at the end of a node (|</span></p>) move it forward so we include all closing tags (</span></p>|)\n while (end.parentOffset >= end.parent.nodeSize - 2 && end.depth > 0) {\n end = tr.doc.resolve(end.pos + 1);\n }\n\n // if the end is at the start of an empty node (</span></p><p>|) move it backwards so we drop empty start tags (</span></p>|)\n while (end.parentOffset === 0 && end.depth > 0) {\n end = tr.doc.resolve(end.pos - 1);\n }\n\n // if the start is at the start of a node (<p><span>|) move it backwards so we include all open tags (|<p><span>)\n while (start.parentOffset === 0 && start.depth > 0) {\n start = tr.doc.resolve(start.pos - 1);\n }\n\n // if the start is at the end of a node (|</p><p><span>|) move it forwards so we drop all closing tags (|<p><span>)\n while (start.parentOffset >= start.parent.nodeSize - 2 && start.depth > 0) {\n start = tr.doc.resolve(start.pos + 1);\n }\n\n const selectionInfo = prosemirrorSliceToSlicedBlocks(\n tr.doc.slice(start.pos, end.pos, true),\n pmSchema,\n );\n\n return {\n _meta: {\n startPos: start.pos,\n endPos: end.pos,\n },\n ...selectionInfo,\n };\n}\n","import type { Node } from \"prosemirror-model\";\nimport {\n NodeSelection,\n TextSelection,\n type Transaction,\n} from \"prosemirror-state\";\nimport type { TextCursorPosition } from \"../../../editor/cursorPositionTypes.js\";\nimport type {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { UnreachableCaseError } from \"../../../util/typescript.js\";\nimport {\n getBlockInfo,\n getBlockInfoFromTransaction,\n} from \"../../getBlockInfoFromPos.js\";\nimport { nodeToBlock } from \"../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../nodeUtil.js\";\nimport { getBlockNoteSchema, getPmSchema } from \"../../pmUtil.js\";\n\nexport function getTextCursorPosition<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(tr: Transaction): TextCursorPosition<BSchema, I, S> {\n const { bnBlock } = getBlockInfoFromTransaction(tr);\n const pmSchema = getPmSchema(tr.doc);\n\n const resolvedPos = tr.doc.resolve(bnBlock.beforePos);\n // Gets previous blockContainer node at the same nesting level, if the current node isn't the first child.\n const prevNode = resolvedPos.nodeBefore;\n\n // Gets next blockContainer node at the same nesting level, if the current node isn't the last child.\n const nextNode = tr.doc.resolve(bnBlock.afterPos).nodeAfter;\n\n // Gets parent blockContainer node, if the current node is nested.\n let parentNode: Node | undefined = undefined;\n if (resolvedPos.depth > 1) {\n // for nodes nested in bnBlocks\n parentNode = resolvedPos.node();\n if (!parentNode.type.isInGroup(\"bnBlock\")) {\n // for blockGroups, we need to go one level up\n parentNode = resolvedPos.node(resolvedPos.depth - 1);\n }\n }\n\n return {\n block: nodeToBlock(bnBlock.node, pmSchema),\n prevBlock: prevNode === null ? undefined : nodeToBlock(prevNode, pmSchema),\n nextBlock: nextNode === null ? undefined : nodeToBlock(nextNode, pmSchema),\n parentBlock:\n parentNode === undefined ? undefined : nodeToBlock(parentNode, pmSchema),\n };\n}\n\nexport function setTextCursorPosition(\n tr: Transaction,\n targetBlock: BlockIdentifier,\n placement: \"start\" | \"end\" = \"start\",\n) {\n const id = typeof targetBlock === \"string\" ? targetBlock : targetBlock.id;\n const pmSchema = getPmSchema(tr.doc);\n const schema = getBlockNoteSchema(pmSchema);\n\n const posInfo = getNodeById(id, tr.doc);\n if (!posInfo) {\n throw new Error(`Block with ID ${id} not found`);\n }\n\n const info = getBlockInfo(posInfo);\n\n const contentType: \"none\" | \"inline\" | \"table\" =\n schema.blockSchema[info.blockNoteType]!.content;\n\n if (info.isBlockContainer) {\n const blockContent = info.blockContent;\n if (contentType === \"none\") {\n tr.setSelection(NodeSelection.create(tr.doc, blockContent.beforePos));\n return;\n }\n\n if (contentType === \"inline\") {\n if (placement === \"start\") {\n tr.setSelection(\n TextSelection.create(tr.doc, blockContent.beforePos + 1),\n );\n } else {\n tr.setSelection(\n TextSelection.create(tr.doc, blockContent.afterPos - 1),\n );\n }\n } else if (contentType === \"table\") {\n if (placement === \"start\") {\n // Need to offset the position as we have to get through the `tableRow`\n // and `tableCell` nodes to get to the `tableParagraph` node we want to\n // set the selection in.\n tr.setSelection(\n TextSelection.create(tr.doc, blockContent.beforePos + 4),\n );\n } else {\n tr.setSelection(\n TextSelection.create(tr.doc, blockContent.afterPos - 4),\n );\n }\n } else {\n throw new UnreachableCaseError(contentType);\n }\n } else {\n const child =\n placement === \"start\"\n ? info.childContainer.node.firstChild!\n : info.childContainer.node.lastChild!;\n\n setTextCursorPosition(tr, child.attrs.id, placement);\n }\n}\n","// some dependencies only export as ESM modules. This makes them incompatible with Node CJS.\n// To work around this, we load these dependencies as dynamic imports in a function that initializes them.\n\n// (to reproduce this issue, run ts-node on a file that users server-util)\nexport let esmDependencies:\n | undefined\n | {\n rehypeParse: typeof import(\"rehype-parse\");\n rehypeStringify: typeof import(\"rehype-stringify\");\n unified: typeof import(\"unified\");\n hastUtilFromDom: typeof import(\"hast-util-from-dom\");\n rehypeRemark: typeof import(\"rehype-remark\");\n remarkGfm: typeof import(\"remark-gfm\");\n remarkStringify: typeof import(\"remark-stringify\");\n remarkParse: typeof import(\"remark-parse\");\n remarkRehype: typeof import(\"remark-rehype\");\n rehypeFormat: typeof import(\"rehype-format\");\n };\n\nexport async function initializeESMDependencies() {\n if (esmDependencies) {\n return esmDependencies;\n }\n const vals = await Promise.all([\n import(\"rehype-parse\"),\n import(\"rehype-stringify\"),\n import(\"unified\"),\n import(\"hast-util-from-dom\"),\n import(\"rehype-remark\"),\n import(\"remark-gfm\"),\n import(\"remark-stringify\"),\n import(\"remark-parse\"),\n import(\"remark-rehype\"),\n import(\"rehype-format\"),\n ]);\n\n esmDependencies = {\n rehypeParse: vals[0],\n rehypeStringify: vals[1],\n unified: vals[2],\n hastUtilFromDom: vals[3],\n rehypeRemark: vals[4],\n remarkGfm: vals[5],\n remarkStringify: vals[6],\n remarkParse: vals[7],\n remarkRehype: vals[8],\n rehypeFormat: vals[9],\n };\n\n return esmDependencies;\n}\n","import { Element as HASTElement, Parent as HASTParent } from \"hast\";\n\n/**\n * Rehype plugin which removes <u> tags. Used to remove underlines before converting HTML to markdown, as Markdown\n * doesn't support underlines.\n */\nexport function removeUnderlines() {\n const removeUnderlinesHelper = (tree: HASTParent) => {\n let numChildElements = tree.children.length;\n\n for (let i = 0; i < numChildElements; i++) {\n const node = tree.children[i];\n\n if (node.type === \"element\") {\n // Recursively removes underlines from child elements.\n removeUnderlinesHelper(node);\n\n if ((node as HASTElement).tagName === \"u\") {\n // Lifts child nodes outside underline element, deletes the underline element, and updates current index &\n // the number of child elements.\n if (node.children.length > 0) {\n tree.children.splice(i, 1, ...node.children);\n\n const numElementsAdded = node.children.length - 1;\n numChildElements += numElementsAdded;\n i += numElementsAdded;\n } else {\n tree.children.splice(i, 1);\n\n numChildElements--;\n i--;\n }\n }\n }\n }\n };\n\n return removeUnderlinesHelper;\n}\n","import { Element as HASTElement, Parent as HASTParent } from \"hast\";\nimport { esmDependencies } from \"../../../../util/esmDependencies.js\";\n\n/**\n * Rehype plugin which adds a space after each checkbox input element. This is\n * because remark doesn't add any spaces between the checkbox input and the text\n * itself, but these are needed for correct Markdown syntax.\n */\nexport function addSpacesToCheckboxes() {\n const deps = esmDependencies;\n\n if (!deps) {\n throw new Error(\n \"addSpacesToCheckboxes requires ESM dependencies to be initialized\",\n );\n }\n\n const helper = (tree: HASTParent) => {\n if (tree.children && \"length\" in tree.children && tree.children.length) {\n for (let i = tree.children.length - 1; i >= 0; i--) {\n const child = tree.children[i];\n const nextChild =\n i + 1 < tree.children.length ? tree.children[i + 1] : undefined;\n\n // Checks for paragraph element after checkbox input element.\n if (\n child.type === \"element\" &&\n child.tagName === \"input\" &&\n child.properties?.type === \"checkbox\" &&\n nextChild?.type === \"element\" &&\n nextChild.tagName === \"p\"\n ) {\n // Converts paragraph to span, otherwise remark will think it needs to\n // be on a new line.\n nextChild.tagName = \"span\";\n // Adds a space after the checkbox input element.\n nextChild.children.splice(\n 0,\n 0,\n deps.hastUtilFromDom.fromDom(\n document.createTextNode(\" \"),\n ) as HASTElement,\n );\n } else {\n helper(child as HASTParent);\n }\n }\n }\n };\n\n return helper;\n}\n","import { Schema } from \"prosemirror-model\";\nimport { PartialBlock } from \"../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport {\n esmDependencies,\n initializeESMDependencies,\n} from \"../../../util/esmDependencies.js\";\nimport { createExternalHTMLExporter } from \"../html/externalHTMLExporter.js\";\nimport { removeUnderlines } from \"./removeUnderlinesRehypePlugin.js\";\nimport { addSpacesToCheckboxes } from \"./util/addSpacesToCheckboxesRehypePlugin.js\";\n\n// Needs to be sync because it's used in drag handler event (SideMenuPlugin)\n// Ideally, call `await initializeESMDependencies()` before calling this function\nexport function cleanHTMLToMarkdown(cleanHTMLString: string) {\n const deps = esmDependencies;\n\n if (!deps) {\n throw new Error(\n \"cleanHTMLToMarkdown requires ESM dependencies to be initialized\",\n );\n }\n\n const markdownString = deps.unified\n .unified()\n .use(deps.rehypeParse.default, { fragment: true })\n .use(removeUnderlines)\n .use(addSpacesToCheckboxes)\n .use(deps.rehypeRemark.default)\n .use(deps.remarkGfm.default)\n .use(deps.remarkStringify.default, {\n handlers: { text: (node) => node.value },\n })\n .processSync(cleanHTMLString);\n\n return markdownString.value as string;\n}\n\nexport async function blocksToMarkdown<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blocks: PartialBlock<BSchema, I, S>[],\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>,\n options: { document?: Document },\n): Promise<string> {\n await initializeESMDependencies();\n const exporter = createExternalHTMLExporter(schema, editor);\n const externalHTML = exporter.exportBlocks(blocks, options);\n\n return cleanHTMLToMarkdown(externalHTML);\n}\n","function getChildIndex(node: Element) {\n return Array.prototype.indexOf.call(node.parentElement!.childNodes, node);\n}\n\nfunction isWhitespaceNode(node: Node) {\n return node.nodeType === 3 && !/\\S/.test(node.nodeValue || \"\");\n}\n\n/**\n * Step 1, Turns:\n *\n * <ul>\n * <li>item</li>\n * <li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </li>\n *\n * Into:\n * <ul>\n * <li>item</li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </ul>\n *\n */\nfunction liftNestedListsToParent(element: HTMLElement) {\n element.querySelectorAll(\"li > ul, li > ol\").forEach((list) => {\n const index = getChildIndex(list);\n const parentListItem = list.parentElement!;\n const siblingsAfter = Array.from(parentListItem.childNodes).slice(\n index + 1,\n );\n list.remove();\n siblingsAfter.forEach((sibling) => {\n sibling.remove();\n });\n\n parentListItem.insertAdjacentElement(\"afterend\", list);\n\n siblingsAfter.reverse().forEach((sibling) => {\n if (isWhitespaceNode(sibling)) {\n return;\n }\n const siblingContainer = document.createElement(\"li\");\n siblingContainer.append(sibling);\n list.insertAdjacentElement(\"afterend\", siblingContainer);\n });\n if (parentListItem.childNodes.length === 0) {\n parentListItem.remove();\n }\n });\n}\n\n/**\n * Step 2, Turns (output of liftNestedListsToParent):\n *\n * <li>item</li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n *\n * Into:\n * <div>\n * <li>item</li>\n * <div data-node-type=\"blockGroup\">\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </div>\n * </div>\n *\n * This resulting format is parsed\n */\nfunction createGroups(element: HTMLElement) {\n element.querySelectorAll(\"li + ul, li + ol\").forEach((list) => {\n const listItem = list.previousElementSibling as HTMLElement;\n const blockContainer = document.createElement(\"div\");\n\n listItem.insertAdjacentElement(\"afterend\", blockContainer);\n blockContainer.append(listItem);\n\n const blockGroup = document.createElement(\"div\");\n blockGroup.setAttribute(\"data-node-type\", \"blockGroup\");\n blockContainer.append(blockGroup);\n\n while (\n blockContainer.nextElementSibling?.nodeName === \"UL\" ||\n blockContainer.nextElementSibling?.nodeName === \"OL\"\n ) {\n blockGroup.append(blockContainer.nextElementSibling);\n }\n });\n}\n\n// prevent XSS, similar to https://github.com/ProseMirror/prosemirror-view/blob/1251b2b412656a2a06263e4187574beb43651273/src/clipboard.ts#L204\n// https://github.com/TypeCellOS/BlockNote/issues/601\nlet _detachedDoc: Document | null = null;\nfunction detachedDoc() {\n return (\n _detachedDoc ||\n (_detachedDoc = document.implementation.createHTMLDocument(\"title\"))\n );\n}\n\nexport function nestedListsToBlockNoteStructure(\n elementOrHTML: HTMLElement | string,\n) {\n if (typeof elementOrHTML === \"string\") {\n const element = detachedDoc().createElement(\"div\");\n element.innerHTML = elementOrHTML;\n elementOrHTML = element;\n }\n liftNestedListsToParent(elementOrHTML);\n createGroups(elementOrHTML);\n return elementOrHTML;\n}\n","import { DOMParser, Schema } from \"prosemirror-model\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\n\nimport { Block } from \"../../../blocks/defaultBlocks.js\";\nimport { nodeToBlock } from \"../../nodeConversions/nodeToBlock.js\";\nimport { nestedListsToBlockNoteStructure } from \"./util/nestedLists.js\";\nexport async function HTMLToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(html: string, pmSchema: Schema): Promise<Block<BSchema, I, S>[]> {\n const htmlNode = nestedListsToBlockNoteStructure(html);\n const parser = DOMParser.fromSchema(pmSchema);\n\n // Other approach might be to use\n // const doc = pmSchema.nodes[\"doc\"].createAndFill()!;\n // and context: doc.resolve(3),\n\n const parentNode = parser.parse(htmlNode, {\n topNode: pmSchema.nodes[\"blockGroup\"].create(),\n });\n\n const blocks: Block<BSchema, I, S>[] = [];\n\n for (let i = 0; i < parentNode.childCount; i++) {\n blocks.push(nodeToBlock(parentNode.child(i), pmSchema));\n }\n\n return blocks;\n}\n","import { Schema } from \"prosemirror-model\";\n\nimport { Block } from \"../../../blocks/defaultBlocks.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { initializeESMDependencies } from \"../../../util/esmDependencies.js\";\nimport { HTMLToBlocks } from \"../html/parseHTML.js\";\n\n// modified version of https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js\n// that outputs a data-language attribute instead of a CSS class (e.g.: language-typescript)\nfunction code(state: any, node: any) {\n const value = node.value ? node.value : \"\";\n /** @type {Properties} */\n const properties: any = {};\n\n if (node.lang) {\n // changed line\n properties[\"data-language\"] = node.lang;\n }\n\n // Create `<code>`.\n /** @type {Element} */\n let result: any = {\n type: \"element\",\n tagName: \"code\",\n properties,\n children: [{ type: \"text\", value }],\n };\n\n if (node.meta) {\n result.data = { meta: node.meta };\n }\n\n state.patch(node, result);\n result = state.applyData(node, result);\n\n // Create `<pre>`.\n result = {\n type: \"element\",\n tagName: \"pre\",\n properties: {},\n children: [result],\n };\n state.patch(node, result);\n return result;\n}\n\nexport async function markdownToHTML(markdown: string): Promise<string> {\n const deps = await initializeESMDependencies();\n\n const htmlString = deps.unified\n .unified()\n .use(deps.remarkParse.default)\n .use(deps.remarkGfm.default)\n .use(deps.remarkRehype.default, {\n handlers: {\n ...(deps.remarkRehype.defaultHandlers as any),\n code,\n },\n })\n .use(deps.rehypeStringify.default)\n .processSync(markdown);\n\n return htmlString.value as string;\n}\n\nexport async function markdownToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(markdown: string, pmSchema: Schema): Promise<Block<BSchema, I, S>[]> {\n const htmlString = await markdownToHTML(markdown);\n\n return HTMLToBlocks(htmlString, pmSchema);\n}\n","export const acceptedMIMETypes = [\n \"vscode-editor-data\",\n \"blocknote/html\",\n \"text/markdown\",\n \"text/html\",\n \"text/plain\",\n \"Files\",\n] as const;\n","import { Block, PartialBlock } from \"../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor\";\nimport {\n BlockSchema,\n FileBlockConfig,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { getNearestBlockPos } from \"../../getBlockInfoFromPos.js\";\nimport { acceptedMIMETypes } from \"./acceptedMIMETypes.js\";\n\nfunction checkFileExtensionsMatch(\n fileExtension1: string,\n fileExtension2: string,\n) {\n if (!fileExtension1.startsWith(\".\") || !fileExtension2.startsWith(\".\")) {\n throw new Error(`The strings provided are not valid file extensions.`);\n }\n\n return fileExtension1 === fileExtension2;\n}\n\nfunction checkMIMETypesMatch(mimeType1: string, mimeType2: string) {\n const types1 = mimeType1.split(\"/\");\n const types2 = mimeType2.split(\"/\");\n\n if (types1.length !== 2) {\n throw new Error(`The string ${mimeType1} is not a valid MIME type.`);\n }\n if (types2.length !== 2) {\n throw new Error(`The string ${mimeType2} is not a valid MIME type.`);\n }\n\n if (types1[1] === \"*\" || types2[1] === \"*\") {\n return types1[0] === types2[0];\n }\n if (types1[0] === \"*\" || types2[0] === \"*\") {\n return types1[1] === types2[1];\n }\n\n return types1[0] === types2[0] && types1[1] === types2[1];\n}\n\nfunction insertOrUpdateBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n referenceBlock: Block<BSchema, I, S>,\n newBlock: PartialBlock<BSchema, I, S>,\n) {\n let insertedBlockId: string | undefined;\n\n if (\n Array.isArray(referenceBlock.content) &&\n referenceBlock.content.length === 0\n ) {\n insertedBlockId = editor.updateBlock(referenceBlock, newBlock).id;\n } else {\n insertedBlockId = editor.insertBlocks(\n [newBlock],\n referenceBlock,\n \"after\",\n )[0].id;\n }\n\n return insertedBlockId;\n}\n\nexport async function handleFileInsertion<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(event: DragEvent | ClipboardEvent, editor: BlockNoteEditor<BSchema, I, S>) {\n if (!editor.uploadFile) {\n // eslint-disable-next-line no-console\n console.warn(\n \"Attempted ot insert file, but uploadFile is not set in the BlockNote editor options\",\n );\n return;\n }\n\n const dataTransfer =\n \"dataTransfer\" in event ? event.dataTransfer : event.clipboardData;\n if (dataTransfer === null) {\n return;\n }\n\n let format: (typeof acceptedMIMETypes)[number] | null = null;\n for (const mimeType of acceptedMIMETypes) {\n if (dataTransfer.types.includes(mimeType)) {\n format = mimeType;\n break;\n }\n }\n if (format !== \"Files\") {\n return;\n }\n\n const items = dataTransfer.items;\n if (!items) {\n return;\n }\n\n event.preventDefault();\n\n const fileBlockConfigs = Object.values(editor.schema.blockSchema).filter(\n (blockConfig) => blockConfig.isFileBlock,\n ) as FileBlockConfig[];\n\n for (let i = 0; i < items.length; i++) {\n // Gets file block corresponding to MIME type.\n let fileBlockType = \"file\";\n for (const fileBlockConfig of fileBlockConfigs) {\n for (const mimeType of fileBlockConfig.fileBlockAccept || []) {\n const isFileExtension = mimeType.startsWith(\".\");\n const file = items[i].getAsFile();\n\n if (file) {\n if (\n (!isFileExtension &&\n file.type &&\n checkMIMETypesMatch(items[i].type, mimeType)) ||\n (isFileExtension &&\n checkFileExtensionsMatch(\n \".\" + file.name.split(\".\").pop(),\n mimeType,\n ))\n ) {\n fileBlockType = fileBlockConfig.type;\n break;\n }\n }\n }\n }\n\n const file = items[i].getAsFile();\n if (file) {\n const fileBlock = {\n type: fileBlockType,\n props: {\n name: file.name,\n },\n } as PartialBlock<BSchema, I, S>;\n\n let insertedBlockId: string | undefined = undefined;\n\n if (event.type === \"paste\") {\n const currentBlock = editor.getTextCursorPosition().block;\n insertedBlockId = insertOrUpdateBlock(editor, currentBlock, fileBlock);\n } else if (event.type === \"drop\") {\n const coords = {\n left: (event as DragEvent).clientX,\n top: (event as DragEvent).clientY,\n };\n\n const pos = editor.prosemirrorView?.posAtCoords(coords);\n if (!pos) {\n return;\n }\n\n insertedBlockId = editor.transact((tr) => {\n const posInfo = getNearestBlockPos(tr.doc, pos.pos);\n return insertOrUpdateBlock(\n editor,\n editor.getBlock(posInfo.node.attrs.id)!,\n fileBlock,\n );\n });\n } else {\n return;\n }\n\n const updateData = await editor.uploadFile(file, insertedBlockId);\n\n const updatedFileBlock =\n typeof updateData === \"string\"\n ? ({\n props: {\n url: updateData,\n },\n } as PartialBlock<BSchema, I, S>)\n : { ...updateData };\n\n editor.updateBlock(insertedBlockId, updatedFileBlock);\n }\n }\n}\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"prosemirror-state\";\n\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { acceptedMIMETypes } from \"./acceptedMIMETypes.js\";\nimport { handleFileInsertion } from \"./handleFileInsertion.js\";\n\nexport const createDropFileExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n) =>\n Extension.create<{ editor: BlockNoteEditor<BSchema, I, S> }, undefined>({\n name: \"dropFile\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n drop(_view, event) {\n if (!editor.isEditable) {\n return;\n }\n\n let format: (typeof acceptedMIMETypes)[number] | null = null;\n for (const mimeType of acceptedMIMETypes) {\n if (event.dataTransfer!.types.includes(mimeType)) {\n format = mimeType;\n break;\n }\n }\n if (format === null) {\n return true;\n }\n\n if (format === \"Files\") {\n handleFileInsertion(event, editor);\n return true;\n }\n\n return false;\n },\n },\n },\n }),\n ];\n },\n });\n","// Headings H1-H6.\nconst h1 = /(^|\\n) {0,3}#{1,6} {1,8}[^\\n]{1,64}\\r?\\n\\r?\\n\\s{0,32}\\S/;\n\n// Bold, italic, underline, strikethrough, highlight.\nconst bold = /(?:\\s|^)(_|__|\\*|\\*\\*|~~|==|\\+\\+)(?!\\s).{1,64}(?<!\\s)(?=\\1)/;\n\n// Basic inline link (also captures images).\nconst link = /\\[[^\\]]{1,128}\\]\\(https?:\\/\\/\\S{1,999}\\)/;\n\n// Inline code.\nconst code = /(?:\\s|^)`(?!\\s)[^`]{1,48}(?<!\\s)`([^\\w]|$)/;\n\n// Unordered list.\nconst ul = /(?:^|\\n)\\s{0,5}-\\s{1}[^\\n]+\\n\\s{0,15}-\\s/;\n\n// Ordered list.\nconst ol = /(?:^|\\n)\\s{0,5}\\d+\\.\\s{1}[^\\n]+\\n\\s{0,15}\\d+\\.\\s/;\n\n// Horizontal rule.\nconst hr = /\\n{2} {0,3}-{2,48}\\n{2}/;\n\n// Fenced code block.\nconst fences =\n /(?:\\n|^)(```|~~~|\\$\\$)(?!`|~)[^\\s]{0,64} {0,64}[^\\n]{0,64}\\n[\\s\\S]{0,9999}?\\s*\\1 {0,64}(?:\\n+|$)/;\n\n// Classical underlined H1 and H2 headings.\nconst title = /(?:\\n|^)(?!\\s)\\w[^\\n]{0,64}\\r?\\n(-|=)\\1{0,64}\\n\\n\\s{0,64}(\\w|$)/;\n\n// Blockquote.\nconst blockquote =\n /(?:^|(\\r?\\n\\r?\\n))( {0,3}>[^\\n]{1,333}\\n){1,999}($|(\\r?\\n))/;\n\n// Table Header\nconst tableHeader = /^\\s*\\|(.+\\|)+\\s*$/m;\n\n// Table Divider\nconst tableDivider = /^\\s*\\|(\\s*[-:]+[-:]\\s*\\|)+\\s*$/m;\n\n// Table Row\nconst tableRow = /^\\s*\\|(.+\\|)+\\s*$/m;\n\n/**\n * Returns `true` if the source text might be a markdown document.\n *\n * @param src Source text to analyze.\n */\nexport const isMarkdown = (src: string): boolean =>\n h1.test(src) ||\n bold.test(src) ||\n link.test(src) ||\n code.test(src) ||\n ul.test(src) ||\n ol.test(src) ||\n hr.test(src) ||\n fences.test(src) ||\n title.test(src) ||\n blockquote.test(src) ||\n tableHeader.test(src) ||\n tableDivider.test(src) ||\n tableRow.test(src);\n","import { EditorView } from \"prosemirror-view\";\n\nexport async function handleVSCodePaste(\n event: ClipboardEvent,\n view: EditorView,\n) {\n const { schema } = view.state;\n\n if (!event.clipboardData) {\n return false;\n }\n\n const text = event.clipboardData!.getData(\"text/plain\");\n\n if (!text) {\n return false;\n }\n\n if (!schema.nodes.codeBlock) {\n view.pasteText(text);\n return true;\n }\n\n const vscode = event.clipboardData!.getData(\"vscode-editor-data\");\n const vscodeData = vscode ? JSON.parse(vscode) : undefined;\n const language = vscodeData?.mode;\n\n if (!language) {\n return false;\n }\n\n // strip carriage return chars from text pasted as code\n // see: https://github.com/ProseMirror/prosemirror-view/commit/a50a6bcceb4ce52ac8fcc6162488d8875613aacd\n view.pasteHTML(\n `<pre><code class=\"language-${language}\">${text.replace(\n /\\r\\n?/g,\n \"\\n\",\n )}</code></pre>`,\n );\n\n return true;\n}\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"prosemirror-state\";\n\nimport type {\n BlockNoteEditor,\n BlockNoteEditorOptions,\n} from \"../../../editor/BlockNoteEditor\";\nimport { isMarkdown } from \"../../parsers/markdown/detectMarkdown.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { acceptedMIMETypes } from \"./acceptedMIMETypes.js\";\nimport { handleFileInsertion } from \"./handleFileInsertion.js\";\nimport { handleVSCodePaste } from \"./handleVSCodePaste.js\";\n\nfunction defaultPasteHandler({\n event,\n editor,\n prioritizeMarkdownOverHTML,\n plainTextAsMarkdown,\n}: {\n event: ClipboardEvent;\n editor: BlockNoteEditor<any, any, any>;\n prioritizeMarkdownOverHTML: boolean;\n plainTextAsMarkdown: boolean;\n}) {\n // Special case for code blocks, as they do not support any rich text\n // formatting, so we force pasting plain text.\n const isInCodeBlock = editor.transact(\n (tr) =>\n tr.selection.$from.parent.type.spec.code &&\n tr.selection.$to.parent.type.spec.code,\n );\n\n if (isInCodeBlock) {\n const data = event.clipboardData?.getData(\"text/plain\");\n\n if (data) {\n editor.pasteText(data);\n\n return true;\n }\n }\n\n let format: (typeof acceptedMIMETypes)[number] | undefined;\n for (const mimeType of acceptedMIMETypes) {\n if (event.clipboardData!.types.includes(mimeType)) {\n format = mimeType;\n break;\n }\n }\n\n if (!format) {\n return true;\n }\n\n if (format === \"vscode-editor-data\") {\n handleVSCodePaste(event, editor.prosemirrorView!);\n return true;\n }\n\n if (format === \"Files\") {\n handleFileInsertion(event, editor);\n return true;\n }\n\n const data = event.clipboardData!.getData(format);\n\n if (format === \"blocknote/html\") {\n // Is blocknote/html, so no need to convert it\n editor.pasteHTML(data, true);\n return true;\n }\n\n if (format === \"text/markdown\") {\n editor.pasteMarkdown(data);\n return true;\n }\n\n if (prioritizeMarkdownOverHTML) {\n // Use plain text instead of HTML if it looks like Markdown\n const plainText = event.clipboardData!.getData(\"text/plain\");\n\n if (isMarkdown(plainText)) {\n editor.pasteMarkdown(plainText);\n return true;\n }\n }\n\n if (format === \"text/html\") {\n editor.pasteHTML(data);\n return true;\n }\n\n if (plainTextAsMarkdown) {\n editor.pasteMarkdown(data);\n return true;\n }\n\n editor.pasteText(data);\n return true;\n}\n\nexport const createPasteFromClipboardExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n pasteHandler: Exclude<\n BlockNoteEditorOptions<any, any, any>[\"pasteHandler\"],\n undefined\n >,\n) =>\n Extension.create({\n name: \"pasteFromClipboard\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n paste(_view, event) {\n event.preventDefault();\n\n if (!editor.isEditable) {\n return;\n }\n\n return pasteHandler({\n event,\n editor,\n defaultPasteHandler: ({\n prioritizeMarkdownOverHTML = true,\n plainTextAsMarkdown = true,\n } = {}) => {\n return defaultPasteHandler({\n event,\n editor,\n prioritizeMarkdownOverHTML,\n plainTextAsMarkdown,\n });\n },\n });\n },\n },\n },\n }),\n ];\n },\n });\n","import { Fragment } from \"@tiptap/pm/model\";\nimport {\n BlockNoDefaults,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { getPmSchema } from \"../pmUtil.js\";\nimport { nodeToBlock } from \"./nodeToBlock.js\";\n\n/**\n * Converts all Blocks within a fragment to BlockNote blocks.\n */\nexport function fragmentToBlocks<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(fragment: Fragment) {\n // first convert selection to blocknote-style blocks, and then\n // pass these to the exporter\n const blocks: BlockNoDefaults<B, I, S>[] = [];\n fragment.descendants((node) => {\n const pmSchema = getPmSchema(node);\n if (node.type.name === \"blockContainer\") {\n if (node.firstChild?.type.name === \"blockGroup\") {\n // selection started within a block group\n // in this case the fragment starts with:\n // <blockContainer>\n // <blockGroup>\n // <blockContainer ... />\n // <blockContainer ... />\n // </blockGroup>\n // </blockContainer>\n //\n // instead of:\n // <blockContainer>\n // <blockContent ... />\n // <blockGroup>\n // <blockContainer ... />\n // <blockContainer ... />\n // </blockGroup>\n // </blockContainer>\n //\n // so we don't need to serialize this block, just descend into the children of the blockGroup\n return true;\n }\n }\n\n if (node.type.name === \"columnList\" && node.childCount === 1) {\n // column lists with a single column should be flattened (not the entire column list has been selected)\n node.firstChild?.forEach((child) => {\n blocks.push(nodeToBlock(child, pmSchema));\n });\n return false;\n }\n\n if (node.type.isInGroup(\"bnBlock\")) {\n blocks.push(nodeToBlock(node, pmSchema));\n // don't descend into children, as they're already included in the block returned by nodeToBlock\n return false;\n }\n return true;\n });\n return blocks;\n}\n","import { Extension } from \"@tiptap/core\";\nimport { Fragment, Node } from \"prosemirror-model\";\nimport { NodeSelection, Plugin } from \"prosemirror-state\";\nimport { CellSelection } from \"prosemirror-tables\";\nimport type { EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { createExternalHTMLExporter } from \"../../exporters/html/externalHTMLExporter.js\";\nimport { cleanHTMLToMarkdown } from \"../../exporters/markdown/markdownExporter.js\";\nimport { fragmentToBlocks } from \"../../nodeConversions/fragmentToBlocks.js\";\nimport {\n contentNodeToInlineContent,\n contentNodeToTableContent,\n} from \"../../nodeConversions/nodeToBlock.js\";\n\nfunction fragmentToExternalHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n view: EditorView,\n selectedFragment: Fragment,\n editor: BlockNoteEditor<BSchema, I, S>,\n) {\n let isWithinBlockContent = false;\n const isWithinTable = view.state.selection instanceof CellSelection;\n\n if (!isWithinTable) {\n // Checks whether block ancestry should be included when creating external\n // HTML. If the selection is within a block content node, the block ancestry\n // is excluded as we only care about the inline content.\n const fragmentWithoutParents = view.state.doc.slice(\n view.state.selection.from,\n view.state.selection.to,\n false,\n ).content;\n\n const children = [];\n for (let i = 0; i < fragmentWithoutParents.childCount; i++) {\n children.push(fragmentWithoutParents.child(i));\n }\n\n isWithinBlockContent =\n children.find(\n (child) =>\n child.type.isInGroup(\"bnBlock\") ||\n child.type.name === \"blockGroup\" ||\n child.type.spec.group === \"blockContent\",\n ) === undefined;\n if (isWithinBlockContent) {\n selectedFragment = fragmentWithoutParents;\n }\n }\n\n let externalHTML: string;\n\n const externalHTMLExporter = createExternalHTMLExporter(\n view.state.schema,\n editor,\n );\n\n if (isWithinTable) {\n if (selectedFragment.firstChild?.type.name === \"table\") {\n // contentNodeToTableContent expects the fragment of the content of a table, not the table node itself\n // but cellselection.content() returns the table node itself if all cells and columns are selected\n selectedFragment = selectedFragment.firstChild.content;\n }\n\n // first convert selection to blocknote-style table content, and then\n // pass this to the exporter\n const ic = contentNodeToTableContent(\n selectedFragment as any,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n );\n\n // Wrap in table to ensure correct parsing by spreadsheet applications\n externalHTML = `<table>${externalHTMLExporter.exportInlineContent(\n ic as any,\n {},\n )}</table>`;\n } else if (isWithinBlockContent) {\n // first convert selection to blocknote-style inline content, and then\n // pass this to the exporter\n const ic = contentNodeToInlineContent(\n selectedFragment as any,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n );\n externalHTML = externalHTMLExporter.exportInlineContent(ic, {});\n } else {\n const blocks = fragmentToBlocks(selectedFragment);\n externalHTML = externalHTMLExporter.exportBlocks(blocks, {});\n }\n return externalHTML;\n}\n\nexport function selectedFragmentToHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n view: EditorView,\n editor: BlockNoteEditor<BSchema, I, S>,\n): {\n clipboardHTML: string;\n externalHTML: string;\n markdown: string;\n} {\n // Checks if a `blockContent` node is being copied and expands\n // the selection to the parent `blockContainer` node. This is\n // for the use-case in which only a block without content is\n // selected, e.g. an image block.\n if (\n \"node\" in view.state.selection &&\n (view.state.selection.node as Node).type.spec.group === \"blockContent\"\n ) {\n editor.transact((tr) =>\n tr.setSelection(\n new NodeSelection(tr.doc.resolve(view.state.selection.from - 1)),\n ),\n );\n }\n\n // Uses default ProseMirror clipboard serialization.\n const clipboardHTML: string = view.serializeForClipboard(\n view.state.selection.content(),\n ).dom.innerHTML;\n\n const selectedFragment = view.state.selection.content().content;\n\n const externalHTML = fragmentToExternalHTML<BSchema, I, S>(\n view,\n selectedFragment,\n editor,\n );\n\n const markdown = cleanHTMLToMarkdown(externalHTML);\n\n return { clipboardHTML, externalHTML, markdown };\n}\n\nconst checkIfSelectionInNonEditableBlock = () => {\n // Let browser handle event if selection is empty (nothing\n // happens).\n const selection = window.getSelection();\n if (!selection || selection.isCollapsed) {\n return true;\n }\n\n // Let browser handle event if it's within a non-editable\n // \"island\". This means it's in selectable content within a\n // non-editable block. We only need to check one node as it's\n // not possible for the browser selection to start in an\n // editable block and end in a non-editable one.\n let node = selection.focusNode;\n while (node) {\n if (\n node instanceof HTMLElement &&\n node.getAttribute(\"contenteditable\") === \"false\"\n ) {\n return true;\n }\n\n node = node.parentElement;\n }\n\n return false;\n};\n\nconst copyToClipboard = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n view: EditorView,\n event: ClipboardEvent,\n) => {\n // Stops the default browser copy behaviour.\n event.preventDefault();\n event.clipboardData!.clearData();\n\n const { clipboardHTML, externalHTML, markdown } = selectedFragmentToHTML(\n view,\n editor,\n );\n\n // TODO: Writing to other MIME types not working in Safari for\n // some reason.\n event.clipboardData!.setData(\"blocknote/html\", clipboardHTML);\n event.clipboardData!.setData(\"text/html\", externalHTML);\n event.clipboardData!.setData(\"text/plain\", markdown);\n};\n\nexport const createCopyToClipboardExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n) =>\n Extension.create<{ editor: BlockNoteEditor<BSchema, I, S> }, undefined>({\n name: \"copyToClipboard\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n copy(view, event) {\n if (checkIfSelectionInNonEditableBlock()) {\n return true;\n }\n\n copyToClipboard(editor, view, event);\n // Prevent default PM handler to be called\n return true;\n },\n cut(view, event) {\n if (checkIfSelectionInNonEditableBlock()) {\n return true;\n }\n\n copyToClipboard(editor, view, event);\n if (view.editable) {\n view.dispatch(view.state.tr.deleteSelection());\n }\n // Prevent default PM handler to be called\n return true;\n },\n // This is for the use-case in which only a block without content\n // is selected, e.g. an image block, and dragged (not using the\n // drag handle).\n dragstart(view, event) {\n // Checks if a `NodeSelection` is active.\n if (!(\"node\" in view.state.selection)) {\n return;\n }\n\n // Checks if a `blockContent` node is being dragged.\n if (\n (view.state.selection.node as Node).type.spec.group !==\n \"blockContent\"\n ) {\n return;\n }\n\n // Expands the selection to the parent `blockContainer` node.\n editor.transact((tr) =>\n tr.setSelection(\n new NodeSelection(\n tr.doc.resolve(view.state.selection.from - 1),\n ),\n ),\n );\n\n // Stops the default browser drag start behaviour.\n event.preventDefault();\n event.dataTransfer!.clearData();\n\n const { clipboardHTML, externalHTML, markdown } =\n selectedFragmentToHTML(view, editor);\n\n // TODO: Writing to other MIME types not working in Safari for\n // some reason.\n event.dataTransfer!.setData(\"blocknote/html\", clipboardHTML);\n event.dataTransfer!.setData(\"text/html\", externalHTML);\n event.dataTransfer!.setData(\"text/plain\", markdown);\n\n // Prevent default PM handler to be called\n return true;\n },\n },\n },\n }),\n ];\n },\n });\n","import { Extension } from \"@tiptap/core\";\nimport { defaultProps } from \"../../blocks/defaultProps.js\";\n\nexport const BackgroundColorExtension = Extension.create({\n name: \"blockBackgroundColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\", \"tableCell\", \"tableHeader\"],\n attributes: {\n backgroundColor: {\n default: defaultProps.backgroundColor.default,\n parseHTML: (element) =>\n element.hasAttribute(\"data-background-color\")\n ? element.getAttribute(\"data-background-color\")\n : defaultProps.backgroundColor.default,\n renderHTML: (attributes) => {\n if (\n attributes.backgroundColor ===\n defaultProps.backgroundColor.default\n ) {\n return {};\n }\n return {\n \"data-background-color\": attributes.backgroundColor,\n };\n },\n },\n },\n },\n ];\n },\n});\n","// from https://raw.githubusercontent.com/ueberdosis/tiptap/develop/packages/core/src/EventEmitter.ts (MIT)\n\ntype StringKeyOf<T> = Extract<keyof T, string>;\ntype CallbackType<\n T extends Record<string, any>,\n EventName extends StringKeyOf<T>,\n> = T[EventName] extends any[] ? T[EventName] : [T[EventName]];\ntype CallbackFunction<\n T extends Record<string, any>,\n EventName extends StringKeyOf<T>,\n> = (...props: CallbackType<T, EventName>) => any;\n\nexport class EventEmitter<T extends Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/ban-types\n private callbacks: { [key: string]: Function[] } = {};\n\n public on<EventName extends StringKeyOf<T>>(\n event: EventName,\n fn: CallbackFunction<T, EventName>,\n ) {\n if (!this.callbacks[event]) {\n this.callbacks[event] = [];\n }\n\n this.callbacks[event].push(fn);\n\n return () => this.off(event, fn);\n }\n\n protected emit<EventName extends StringKeyOf<T>>(\n event: EventName,\n ...args: CallbackType<T, EventName>\n ) {\n const callbacks = this.callbacks[event];\n\n if (callbacks) {\n callbacks.forEach((callback) => callback.apply(this, args));\n }\n }\n\n public off<EventName extends StringKeyOf<T>>(\n event: EventName,\n fn?: CallbackFunction<T, EventName>,\n ) {\n const callbacks = this.callbacks[event];\n\n if (callbacks) {\n if (fn) {\n this.callbacks[event] = callbacks.filter((callback) => callback !== fn);\n } else {\n delete this.callbacks[event];\n }\n }\n }\n\n protected removeAllListeners(): void {\n this.callbacks = {};\n }\n}\n","import { Plugin } from \"prosemirror-state\";\nimport { EventEmitter } from \"../util/EventEmitter.js\";\n\nexport abstract class BlockNoteExtension<\n TEvent extends Record<string, any> = any,\n> extends EventEmitter<TEvent> {\n public static key(): string {\n throw new Error(\"You must implement the key method in your extension\");\n }\n\n protected addProsemirrorPlugin(plugin: Plugin) {\n this.plugins.push(plugin);\n }\n\n public readonly plugins: Plugin[] = [];\n public get priority(): number | undefined {\n return undefined;\n }\n\n // eslint-disable-next-line\n constructor(..._args: any[]) {\n super();\n // Allow subclasses to have constructors with parameters\n // without this, we can't easily implement BlockNoteEditor.extension(MyExtension) pattern\n }\n}\n","import { defaultSelectionBuilder, yCursorPlugin } from \"y-prosemirror\";\nimport { Awareness } from \"y-protocols/awareness.js\";\nimport * as Y from \"yjs\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nexport type CollaborationUser = {\n name: string;\n color: string;\n [key: string]: string;\n};\n\nexport class CursorPlugin extends BlockNoteExtension {\n public static key() {\n return \"yCursorPlugin\";\n }\n\n private provider: { awareness: Awareness };\n private recentlyUpdatedCursors: Map<\n number,\n { element: HTMLElement; hideTimeout: NodeJS.Timeout | undefined }\n >;\n constructor(\n private collaboration: {\n fragment: Y.XmlFragment;\n user: CollaborationUser;\n provider: { awareness: Awareness };\n renderCursor?: (user: CollaborationUser) => HTMLElement;\n showCursorLabels?: \"always\" | \"activity\";\n },\n ) {\n super();\n this.provider = collaboration.provider;\n this.recentlyUpdatedCursors = new Map();\n\n this.provider.awareness.setLocalStateField(\"user\", collaboration.user);\n\n if (collaboration.showCursorLabels !== \"always\") {\n this.provider.awareness.on(\n \"change\",\n ({\n updated,\n }: {\n added: Array<number>;\n updated: Array<number>;\n removed: Array<number>;\n }) => {\n for (const clientID of updated) {\n const cursor = this.recentlyUpdatedCursors.get(clientID);\n\n if (cursor) {\n cursor.element.setAttribute(\"data-active\", \"\");\n\n if (cursor.hideTimeout) {\n clearTimeout(cursor.hideTimeout);\n }\n\n this.recentlyUpdatedCursors.set(clientID, {\n element: cursor.element,\n hideTimeout: setTimeout(() => {\n cursor.element.removeAttribute(\"data-active\");\n }, 2000),\n });\n }\n }\n },\n );\n }\n\n this.addProsemirrorPlugin(\n yCursorPlugin(this.provider.awareness, {\n selectionBuilder: defaultSelectionBuilder,\n cursorBuilder: this.renderCursor,\n }),\n );\n }\n\n public get priority() {\n return 999;\n }\n\n private renderCursor = (user: CollaborationUser, clientID: number) => {\n let cursorData = this.recentlyUpdatedCursors.get(clientID);\n\n if (!cursorData) {\n const cursorElement = (\n this.collaboration.renderCursor ?? CursorPlugin.defaultCursorRender\n )(user);\n\n if (this.collaboration.showCursorLabels !== \"always\") {\n cursorElement.addEventListener(\"mouseenter\", () => {\n const cursor = this.recentlyUpdatedCursors.get(clientID)!;\n cursor.element.setAttribute(\"data-active\", \"\");\n\n if (cursor.hideTimeout) {\n clearTimeout(cursor.hideTimeout);\n this.recentlyUpdatedCursors.set(clientID, {\n element: cursor.element,\n hideTimeout: undefined,\n });\n }\n });\n\n cursorElement.addEventListener(\"mouseleave\", () => {\n const cursor = this.recentlyUpdatedCursors.get(clientID)!;\n\n this.recentlyUpdatedCursors.set(clientID, {\n element: cursor.element,\n hideTimeout: setTimeout(() => {\n cursor.element.removeAttribute(\"data-active\");\n }, 2000),\n });\n });\n }\n\n cursorData = {\n element: cursorElement,\n hideTimeout: undefined,\n };\n\n this.recentlyUpdatedCursors.set(clientID, cursorData);\n }\n\n return cursorData.element;\n };\n\n public updateUser = (user: {\n name: string;\n color: string;\n [key: string]: string;\n }) => {\n this.provider.awareness.setLocalStateField(\"user\", user);\n };\n\n public static defaultCursorRender = (user: CollaborationUser) => {\n const cursorElement = document.createElement(\"span\");\n\n cursorElement.classList.add(\"bn-collaboration-cursor__base\");\n\n const caretElement = document.createElement(\"span\");\n caretElement.setAttribute(\"contentedEditable\", \"false\");\n caretElement.classList.add(\"bn-collaboration-cursor__caret\");\n caretElement.setAttribute(\"style\", `background-color: ${user.color}`);\n\n const labelElement = document.createElement(\"span\");\n\n labelElement.classList.add(\"bn-collaboration-cursor__label\");\n labelElement.setAttribute(\"style\", `background-color: ${user.color}`);\n labelElement.insertBefore(document.createTextNode(user.name), null);\n\n caretElement.insertBefore(labelElement, null);\n\n cursorElement.insertBefore(document.createTextNode(\"\\u2060\"), null); // Non-breaking space\n cursorElement.insertBefore(caretElement, null);\n cursorElement.insertBefore(document.createTextNode(\"\\u2060\"), null); // Non-breaking space\n\n return cursorElement;\n };\n}\n","import { ySyncPlugin } from \"y-prosemirror\";\nimport type * as Y from \"yjs\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nexport class SyncPlugin extends BlockNoteExtension {\n public static key() {\n return \"ySyncPlugin\";\n }\n\n constructor(fragment: Y.XmlFragment) {\n super();\n this.addProsemirrorPlugin(ySyncPlugin(fragment));\n }\n\n public get priority() {\n return 1001;\n }\n}\n","import { yUndoPlugin } from \"y-prosemirror\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nexport class UndoPlugin extends BlockNoteExtension {\n public static key() {\n return \"yUndoPlugin\";\n }\n\n constructor() {\n super();\n this.addProsemirrorPlugin(yUndoPlugin());\n }\n\n public get priority() {\n return 1000;\n }\n}\n","import { Mark, mergeAttributes } from \"@tiptap/core\";\n\nexport const CommentMark = Mark.create({\n name: \"comment\",\n excludes: \"\",\n inclusive: false,\n keepOnSplit: true,\n\n addAttributes() {\n // Return an object with attribute configuration\n return {\n // orphans are marks that currently don't have an active thread. It could be\n // that users have resolved the thread. Resolved threads by default are not shown in the document,\n // but we need to keep the mark (positioning) data so we can still \"revive\" it when the thread is unresolved\n // or we enter a \"comments\" view that includes resolved threads.\n orphan: {\n parseHTML: (element) => !!element.getAttribute(\"data-orphan\"),\n renderHTML: (attributes) => {\n return (attributes as { orphan: boolean }).orphan\n ? {\n \"data-orphan\": \"true\",\n }\n : {};\n },\n default: false,\n },\n threadId: {\n parseHTML: (element) => element.getAttribute(\"data-bn-thread-id\"),\n renderHTML: (attributes) => {\n return {\n \"data-bn-thread-id\": (attributes as { threadId: string }).threadId,\n };\n },\n default: \"\",\n },\n };\n },\n\n renderHTML({ HTMLAttributes }: { HTMLAttributes: Record<string, any> }) {\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"bn-thread-mark\",\n }),\n ];\n },\n\n parseHTML() {\n return [{ tag: \"span.bn-thread-mark\" }];\n },\n\n extendMarkSchema(extension) {\n if (extension.name === \"comment\") {\n return {\n blocknoteIgnore: true,\n };\n }\n return {};\n },\n});\n","import type { User } from \"../../../comments/index.js\";\nimport { EventEmitter } from \"../../../util/EventEmitter.js\";\n\n/**\n * The `UserStore` is used to retrieve and cache information about users.\n *\n * It does this by calling `resolveUsers` (which is user-defined in the Editor Options)\n * for users that are not yet cached.\n */\nexport class UserStore<U extends User> extends EventEmitter<any> {\n private userCache: Map<string, U> = new Map();\n\n // avoid duplicate loads\n private loadingUsers = new Set<string>();\n\n public constructor(\n private readonly resolveUsers: (userIds: string[]) => Promise<U[]>,\n ) {\n super();\n }\n\n /**\n * Load information about users based on an array of user ids.\n */\n public async loadUsers(userIds: string[]) {\n const missingUsers = userIds.filter(\n (id) => !this.userCache.has(id) && !this.loadingUsers.has(id),\n );\n\n if (missingUsers.length === 0) {\n return;\n }\n\n for (const id of missingUsers) {\n this.loadingUsers.add(id);\n }\n\n try {\n const users = await this.resolveUsers(missingUsers);\n for (const user of users) {\n this.userCache.set(user.id, user);\n }\n this.emit(\"update\", this.userCache);\n } finally {\n for (const id of missingUsers) {\n // delete the users from the loading set\n // on a next call to `loadUsers` we will either\n // return the cached user or retry loading the user if the request failed failed\n this.loadingUsers.delete(id);\n }\n }\n }\n\n /**\n * Retrieve information about a user based on their id, if cached.\n *\n * The user will have to be loaded via `loadUsers` first\n */\n public getUser(userId: string): U | undefined {\n return this.userCache.get(userId);\n }\n\n /**\n * Subscribe to changes in the user store.\n *\n * @param cb - The callback to call when the user store changes.\n * @returns A function to unsubscribe from the user store.\n */\n public subscribe(cb: (users: Map<string, U>) => void): () => void {\n return this.on(\"update\", cb);\n }\n}\n","import { Node } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { getRelativeSelection, ySyncPluginKey } from \"y-prosemirror\";\nimport type {\n CommentBody,\n ThreadData,\n ThreadStore,\n User,\n} from \"../../comments/index.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UserStore } from \"./userstore/UserStore.js\";\n\nconst PLUGIN_KEY = new PluginKey(`blocknote-comments`);\nconst SET_SELECTED_THREAD_ID = \"SET_SELECTED_THREAD_ID\";\n\ntype CommentsPluginState = {\n /**\n * Decorations to be rendered, specifically to indicate the selected thread\n */\n decorations: DecorationSet;\n};\n\n/**\n * Calculate the thread positions from the current document state\n */\nfunction getUpdatedThreadPositions(doc: Node, markType: string) {\n const threadPositions = new Map<string, { from: number; to: number }>();\n\n // find all thread marks and store their position + create decoration for selected thread\n doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === markType) {\n const thisThreadId = (mark.attrs as { threadId: string | undefined })\n .threadId;\n if (!thisThreadId) {\n return;\n }\n const from = pos;\n const to = from + node.nodeSize;\n\n // FloatingThreads component uses \"to\" as the position, so always store the largest \"to\" found\n // AnchoredThreads component uses \"from\" as the position, so always store the smallest \"from\" found\n const currentPosition = threadPositions.get(thisThreadId) ?? {\n from: Infinity,\n to: 0,\n };\n threadPositions.set(thisThreadId, {\n from: Math.min(from, currentPosition.from),\n to: Math.max(to, currentPosition.to),\n });\n }\n });\n });\n return threadPositions;\n}\n\nexport class CommentsPlugin extends BlockNoteExtension {\n public static key() {\n return \"comments\";\n }\n\n public readonly userStore: UserStore<User>;\n\n /**\n * Whether a comment is currently being composed\n */\n private pendingComment = false;\n\n /**\n * The currently selected thread id\n */\n private selectedThreadId: string | undefined;\n\n /**\n * Store the positions of all threads in the document.\n * this can be used later to implement a floating sidebar\n */\n private threadPositions: Map<string, { from: number; to: number }> =\n new Map();\n\n private emitStateUpdate() {\n this.emit(\"update\", {\n selectedThreadId: this.selectedThreadId,\n pendingComment: this.pendingComment,\n threadPositions: this.threadPositions,\n });\n }\n\n /**\n * when a thread is resolved or deleted, we need to update the marks to reflect the new state\n */\n private updateMarksFromThreads = (threads: Map<string, ThreadData>) => {\n this.editor.transact((tr) => {\n tr.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === this.markType) {\n const markType = mark.type;\n const markThreadId = mark.attrs.threadId;\n const thread = threads.get(markThreadId);\n const isOrphan = !!(!thread || thread.resolved || thread.deletedAt);\n\n if (isOrphan !== mark.attrs.orphan) {\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n tr.doc.content.size - 1,\n tr.doc.content.size - 1,\n );\n tr.removeMark(trimmedFrom, trimmedTo, mark);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n markType.create({\n ...mark.attrs,\n orphan: isOrphan,\n }),\n );\n\n if (isOrphan && this.selectedThreadId === markThreadId) {\n // unselect\n this.selectedThreadId = undefined;\n this.emitStateUpdate();\n }\n }\n }\n });\n });\n });\n };\n\n constructor(\n private readonly editor: BlockNoteEditor<any, any, any>,\n public readonly threadStore: ThreadStore,\n private readonly markType: string,\n ) {\n super();\n\n if (!editor.resolveUsers) {\n throw new Error(\"resolveUsers is required for comments\");\n }\n this.userStore = new UserStore<User>(editor.resolveUsers);\n\n // Note: Plugins are currently not destroyed when the editor is destroyed.\n // We should unsubscribe from the threadStore when the editor is destroyed.\n this.threadStore.subscribe(this.updateMarksFromThreads);\n\n editor.onCreate(() => {\n // Need to wait for TipTap editor state to be initialized\n this.updateMarksFromThreads(this.threadStore.getThreads());\n editor.onSelectionChange(() => {\n if (this.pendingComment) {\n this.pendingComment = false;\n this.emitStateUpdate();\n }\n });\n });\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n this.addProsemirrorPlugin(\n new Plugin<CommentsPluginState>({\n key: PLUGIN_KEY,\n state: {\n init() {\n return {\n decorations: DecorationSet.empty,\n };\n },\n apply(tr, state) {\n const action = tr.getMeta(PLUGIN_KEY);\n\n if (!tr.docChanged && !action) {\n return state;\n }\n\n // only update threadPositions if the doc changed\n const threadPositions = tr.docChanged\n ? getUpdatedThreadPositions(tr.doc, self.markType)\n : self.threadPositions;\n\n if (threadPositions.size > 0 || self.threadPositions.size > 0) {\n // small optimization; don't emit event if threadPositions before / after were both empty\n self.threadPositions = threadPositions;\n self.emitStateUpdate();\n }\n\n // update decorations if doc or selected thread changed\n const decorations = [];\n\n if (self.selectedThreadId) {\n const selectedThreadPosition = threadPositions.get(\n self.selectedThreadId,\n );\n\n if (selectedThreadPosition) {\n decorations.push(\n Decoration.inline(\n selectedThreadPosition.from,\n selectedThreadPosition.to,\n {\n class: \"bn-thread-mark-selected\",\n },\n ),\n );\n }\n }\n\n return {\n decorations: DecorationSet.create(tr.doc, decorations),\n };\n },\n },\n props: {\n decorations(state) {\n return (\n PLUGIN_KEY.getState(state)?.decorations ?? DecorationSet.empty\n );\n },\n /**\n * Handle click on a thread mark and mark it as selected\n */\n handleClick: (view, pos, event) => {\n if (event.button !== 0) {\n return;\n }\n\n const node = view.state.doc.nodeAt(pos);\n\n if (!node) {\n self.selectThread(undefined);\n return;\n }\n\n const commentMark = node.marks.find(\n (mark) =>\n mark.type.name === markType && mark.attrs.orphan !== true,\n );\n\n const threadId = commentMark?.attrs.threadId as string | undefined;\n self.selectThread(threadId, false);\n },\n },\n }),\n );\n }\n\n /**\n * Subscribe to state updates\n */\n public onUpdate(\n callback: (state: {\n pendingComment: boolean;\n selectedThreadId: string | undefined;\n threadPositions: Map<string, { from: number; to: number }>;\n }) => void,\n ) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Set the selected thread\n */\n public selectThread(threadId: string | undefined, scrollToThread = true) {\n if (this.selectedThreadId === threadId) {\n return;\n }\n this.selectedThreadId = threadId;\n this.emitStateUpdate();\n this.editor.transact((tr) =>\n tr.setMeta(PLUGIN_KEY, {\n name: SET_SELECTED_THREAD_ID,\n }),\n );\n\n if (threadId && scrollToThread) {\n const selectedThreadPosition = this.threadPositions.get(threadId);\n\n if (!selectedThreadPosition) {\n return;\n }\n\n // When a new thread is selected, scrolls the page to its reference text in\n // the editor.\n (\n this.editor.prosemirrorView?.domAtPos(selectedThreadPosition.from)\n .node as Element | undefined\n )?.scrollIntoView({\n behavior: \"smooth\",\n block: \"center\",\n });\n }\n }\n\n /**\n * Start a pending comment (e.g.: when clicking the \"Add comment\" button)\n */\n public startPendingComment() {\n this.pendingComment = true;\n this.emitStateUpdate();\n }\n\n /**\n * Stop a pending comment (e.g.: user closes the comment composer)\n */\n public stopPendingComment() {\n this.pendingComment = false;\n this.emitStateUpdate();\n }\n\n /**\n * Create a thread at the current selection\n */\n public async createThread(options: {\n initialComment: {\n body: CommentBody;\n metadata?: any;\n };\n metadata?: any;\n }) {\n const thread = await this.threadStore.createThread(options);\n\n if (this.threadStore.addThreadToDocument) {\n // creating the mark is handled by the store\n // this is useful if we don't have write-access to the document.\n // We can then offload the responsibility of creating the mark to the server.\n // (e.g.: RESTYjsThreadStore)\n const view = this.editor.prosemirrorView!;\n const pmSelection = view.state.selection;\n\n const ystate = ySyncPluginKey.getState(view.state);\n\n const selection = {\n prosemirror: {\n head: pmSelection.head,\n anchor: pmSelection.anchor,\n },\n yjs: ystate\n ? getRelativeSelection(ystate.binding, view.state)\n : undefined, // if we're not using yjs\n };\n\n await this.threadStore.addThreadToDocument({\n threadId: thread.id,\n selection,\n });\n } else {\n // we create the mark directly in the document\n this.editor._tiptapEditor.commands.setMark(this.markType, {\n orphan: false,\n threadId: thread.id,\n });\n }\n }\n}\n","import { EditorState, Plugin, PluginKey, PluginView } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport { ySyncPluginKey } from \"y-prosemirror\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport type {\n BlockFromConfig,\n FileBlockConfig,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\n\nexport type FilePanelState<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = UiElementPosition & {\n // TODO: This typing is not quite right (children should be from BSchema)\n block: BlockFromConfig<FileBlockConfig, I, S>;\n};\n\nexport class FilePanelView<I extends InlineContentSchema, S extends StyleSchema>\n implements PluginView\n{\n public state?: FilePanelState<I, S>;\n public emitUpdate: () => void;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n Record<string, FileBlockConfig>,\n I,\n S\n >,\n private readonly pluginKey: PluginKey<FilePanelState<I, S>>,\n private readonly pmView: EditorView,\n emitUpdate: (state: FilePanelState<I, S>) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized file panel\");\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.mouseDownHandler);\n pmView.dom.addEventListener(\"dragstart\", this.dragstartHandler);\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n pmView.root.addEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n mouseDownHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n // For dragging the whole editor.\n dragstartHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n const blockElement = this.pmView.root.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${this.state.block.id}\"]`,\n );\n if (!blockElement) {\n return;\n }\n this.state.referencePos = blockElement.getBoundingClientRect();\n this.emitUpdate();\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const pluginState = this.pluginKey.getState(view.state);\n const prevPluginState = this.pluginKey.getState(prevState);\n\n if (!this.state?.show && pluginState?.block && this.editor.isEditable) {\n const blockElement = this.pmView.root.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${pluginState.block.id}\"]`,\n );\n if (!blockElement) {\n return;\n }\n this.state = {\n show: true,\n referencePos: blockElement.getBoundingClientRect(),\n block: pluginState.block,\n };\n\n this.emitUpdate();\n\n return;\n }\n\n const isOpening = pluginState?.block && !prevPluginState?.block;\n const isClosing = !pluginState?.block && prevPluginState?.block;\n if (isOpening && this.state && !this.state.show) {\n this.state.show = true;\n this.emitUpdate();\n }\n if (isClosing && this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n closeMenu = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.mouseDownHandler);\n\n this.pmView.dom.removeEventListener(\"dragstart\", this.dragstartHandler);\n\n this.pmView.root.removeEventListener(\"scroll\", this.scrollHandler, true);\n }\n}\n\nconst filePanelPluginKey = new PluginKey<FilePanelState<any, any>>(\n \"FilePanelPlugin\",\n);\n\nexport class FilePanelProsemirrorPlugin<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"filePanel\";\n }\n\n private view: FilePanelView<I, S> | undefined;\n\n constructor(editor: BlockNoteEditor<Record<string, FileBlockConfig>, I, S>) {\n super();\n this.addProsemirrorPlugin(\n new Plugin<{\n block: BlockFromConfig<FileBlockConfig, I, S> | undefined;\n }>({\n key: filePanelPluginKey,\n view: (editorView) => {\n this.view = new FilePanelView<I, S>(\n editor,\n filePanelPluginKey,\n editorView,\n (state) => {\n this.emit(\"update\", state);\n },\n );\n return this.view;\n },\n props: {\n handleKeyDown: (_view, event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.shown) {\n this.view?.closeMenu();\n return true;\n }\n return false;\n },\n },\n state: {\n init: () => {\n return {\n block: undefined,\n };\n },\n apply: (transaction, prev) => {\n const state: FilePanelState<I, S> | undefined =\n transaction.getMeta(filePanelPluginKey);\n\n if (state) {\n return state;\n }\n\n if (\n !transaction.getMeta(ySyncPluginKey) &&\n (transaction.selectionSet || transaction.docChanged)\n ) {\n return { block: undefined };\n }\n return prev;\n },\n },\n }),\n );\n }\n\n public get shown() {\n return this.view?.state?.show || false;\n }\n\n public onUpdate(callback: (state: FilePanelState<I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n public closeMenu = () => this.view?.closeMenu();\n}\n","import { isNodeSelection, isTextSelection, posToDOMRect } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey, PluginView } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\n\nexport type FormattingToolbarState = UiElementPosition;\n\nexport class FormattingToolbarView implements PluginView {\n public state?: FormattingToolbarState;\n public emitUpdate: () => void;\n\n public preventHide = false;\n public preventShow = false;\n\n public shouldShow: (props: {\n view: EditorView;\n state: EditorState;\n from: number;\n to: number;\n }) => boolean = ({ view, state, from, to }) => {\n const { doc, selection } = state;\n const { empty } = selection;\n\n // Sometime check for `empty` is not enough.\n // Doubleclick an empty paragraph returns a node size of 2.\n // So we check also for an empty text size.\n const isEmptyTextBlock =\n !doc.textBetween(from, to).length && isTextSelection(state.selection);\n\n // Don't show toolbar inside code blocks\n if (\n selection.$from.parent.type.spec.code ||\n (isNodeSelection(selection) && selection.node.type.spec.code)\n ) {\n return false;\n }\n\n if (empty || isEmptyTextBlock) {\n return false;\n }\n\n const focusedElement = document.activeElement;\n if (!this.isElementWithinEditorWrapper(focusedElement) && view.editable) {\n // editable editors must have focus for the toolbar to show\n return false;\n }\n return true;\n };\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchema,\n InlineContentSchema,\n StyleSchema\n >,\n private readonly pmView: EditorView,\n emitUpdate: (state: FormattingToolbarState) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\n \"Attempting to update uninitialized formatting toolbar\",\n );\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n pmView.root.addEventListener(\"mouseup\", this.mouseupHandler);\n pmView.dom.addEventListener(\"dragstart\", this.dragHandler);\n pmView.dom.addEventListener(\"dragover\", this.dragHandler);\n pmView.dom.addEventListener(\"blur\", this.blurHandler);\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n pmView.root.addEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n blurHandler = (event: FocusEvent) => {\n if (this.preventHide) {\n this.preventHide = false;\n\n return;\n }\n\n const editorWrapper = this.pmView.dom.parentElement!;\n\n // Checks if the focus is moving to an element outside the editor. If it is,\n // the toolbar is hidden.\n if (\n // An element is clicked.\n event &&\n event.relatedTarget &&\n // Element is inside the editor.\n (editorWrapper === (event.relatedTarget as Node) ||\n editorWrapper.contains(event.relatedTarget as Node) ||\n (event.relatedTarget as HTMLElement).matches(\n \".bn-ui-container, .bn-ui-container *\",\n ))\n ) {\n return;\n }\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n isElementWithinEditorWrapper = (element: Node | null) => {\n if (!element) {\n return false;\n }\n const editorWrapper = this.pmView.dom.parentElement;\n if (!editorWrapper) {\n return false;\n }\n\n return editorWrapper.contains(element);\n };\n\n viewMousedownHandler = (e: MouseEvent) => {\n if (!this.isElementWithinEditorWrapper(e.target as Node)) {\n this.preventShow = true;\n }\n };\n\n mouseupHandler = () => {\n if (this.preventShow) {\n this.preventShow = false;\n setTimeout(() => this.update(this.pmView));\n }\n };\n\n // For dragging the whole editor.\n dragHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n this.state.referencePos = this.getSelectionBoundingBox();\n this.emitUpdate();\n }\n };\n\n update(view: EditorView, oldState?: EditorState) {\n // Delays the update to handle edge case with drag and drop, where the view\n // is blurred asynchronously and happens only after the state update.\n // Wrapping in a setTimeout gives enough time to wait for the blur event to\n // occur before updating the toolbar.\n const { state, composing } = view;\n const { doc, selection } = state;\n const isSame =\n oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection);\n\n if (composing || isSame) {\n return;\n }\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n const shouldShow = this.shouldShow({\n view,\n state,\n from,\n to,\n });\n\n // in jsdom, Range.prototype.getClientRects is not implemented,\n // this would cause `getSelectionBoundingBox` to fail\n // we can just ignore jsdom for now and not show the toolbar\n const jsdom = typeof Range.prototype.getClientRects === \"undefined\";\n\n // Checks if menu should be shown/updated.\n if (!this.preventShow && (shouldShow || this.preventHide) && !jsdom) {\n // Unlike other UI elements, we don't prevent the formatting toolbar from\n // showing when the editor is not editable. This is because some buttons,\n // e.g. the download file button, should still be accessible. Therefore,\n // logic for hiding when the editor is non-editable is handled\n // individually in each button.\n const nextState = {\n show: true,\n referencePos: this.getSelectionBoundingBox(),\n };\n\n if (\n nextState.show !== this.state?.show ||\n nextState.referencePos.toJSON() !== this.state?.referencePos.toJSON()\n ) {\n this.state = nextState;\n this.emitUpdate();\n }\n\n return;\n }\n\n // Checks if menu should be hidden.\n if (\n this.state?.show &&\n !this.preventHide &&\n (!shouldShow || this.preventShow || !this.editor.isEditable)\n ) {\n this.state.show = false;\n this.emitUpdate();\n\n return;\n }\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.viewMousedownHandler);\n this.pmView.root.removeEventListener(\"mouseup\", this.mouseupHandler);\n this.pmView.dom.removeEventListener(\"dragstart\", this.dragHandler);\n this.pmView.dom.removeEventListener(\"dragover\", this.dragHandler);\n this.pmView.dom.removeEventListener(\"blur\", this.blurHandler);\n\n this.pmView.root.removeEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n closeMenu = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n getSelectionBoundingBox() {\n const { state } = this.pmView;\n const { selection } = state;\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n if (isNodeSelection(selection)) {\n const node = this.pmView.nodeDOM(from) as HTMLElement;\n if (node) {\n return node.getBoundingClientRect();\n }\n }\n\n return posToDOMRect(this.pmView, from, to);\n }\n}\n\nexport const formattingToolbarPluginKey = new PluginKey(\n \"FormattingToolbarPlugin\",\n);\n\nexport class FormattingToolbarProsemirrorPlugin extends BlockNoteExtension {\n public static key() {\n return \"formattingToolbar\";\n }\n\n private view: FormattingToolbarView | undefined;\n\n constructor(editor: BlockNoteEditor<any, any, any>) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: formattingToolbarPluginKey,\n view: (editorView) => {\n this.view = new FormattingToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n props: {\n handleKeyDown: (_view, event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.shown) {\n this.view!.closeMenu();\n return true;\n }\n return false;\n },\n },\n }),\n );\n }\n\n public get shown() {\n return this.view?.state?.show || false;\n }\n\n public onUpdate(callback: (state: FormattingToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n\n public closeMenu = () => this.view!.closeMenu();\n}\n","// Stripped down version of the TipTap HardBreak extension:\n// https://github.com/ueberdosis/tiptap/blob/f3258d9ee5fb7979102fe63434f6ea4120507311/packages/extension-hard-break/src/hard-break.ts#L80\n// Changes:\n// - Removed options\n// - Removed keyboard shortcuts & moved them to the `KeyboardShortcutsExtension`\n// - Removed `setHardBreak` command (added a simpler version in the Shift+Enter\n// handler in `KeyboardShortcutsExtension`).\n// - Added priority\nimport { mergeAttributes, Node } from \"@tiptap/core\";\n\nexport const HardBreak = Node.create({\n name: \"hardBreak\",\n\n inline: true,\n\n group: \"inline\",\n\n selectable: false,\n\n linebreakReplacement: true,\n\n priority: 10,\n\n parseHTML() {\n return [{ tag: \"br\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"br\", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];\n },\n\n renderText() {\n return \"\\n\";\n },\n});\n","import { Node } from \"prosemirror-model\";\nimport { EditorState } from \"prosemirror-state\";\n\nimport {\n BlockInfo,\n getBlockInfoFromResolvedPos,\n} from \"../../../getBlockInfoFromPos.js\";\n\n/**\n * Returns the block info from the parent block\n * or undefined if we're at the root\n */\nexport const getParentBlockInfo = (doc: Node, beforePos: number) => {\n const $pos = doc.resolve(beforePos);\n\n if ($pos.depth <= 1) {\n return undefined;\n }\n\n // get start pos of parent\n const parentBeforePos = $pos.posAtIndex(\n $pos.index($pos.depth - 1),\n $pos.depth - 1,\n );\n\n const parentBlockInfo = getBlockInfoFromResolvedPos(\n doc.resolve(parentBeforePos),\n );\n return parentBlockInfo;\n};\n\n/**\n * Returns the block info from the sibling block before (above) the given block,\n * or undefined if the given block is the first sibling.\n */\nexport const getPrevBlockInfo = (doc: Node, beforePos: number) => {\n const $pos = doc.resolve(beforePos);\n\n const indexInParent = $pos.index();\n\n if (indexInParent === 0) {\n return undefined;\n }\n\n const prevBlockBeforePos = $pos.posAtIndex(indexInParent - 1);\n\n const prevBlockInfo = getBlockInfoFromResolvedPos(\n doc.resolve(prevBlockBeforePos),\n );\n return prevBlockInfo;\n};\n\n/**\n * If a block has children like this:\n * A\n * - B\n * - C\n * -- D\n *\n * Then the bottom nested block returned is D.\n */\nexport const getBottomNestedBlockInfo = (doc: Node, blockInfo: BlockInfo) => {\n while (blockInfo.childContainer) {\n const group = blockInfo.childContainer.node;\n\n const newPos = doc\n .resolve(blockInfo.childContainer.beforePos + 1)\n .posAtIndex(group.childCount - 1);\n blockInfo = getBlockInfoFromResolvedPos(doc.resolve(newPos));\n }\n\n return blockInfo;\n};\n\nconst canMerge = (prevBlockInfo: BlockInfo, nextBlockInfo: BlockInfo) => {\n return (\n prevBlockInfo.isBlockContainer &&\n prevBlockInfo.blockContent.node.type.spec.content === \"inline*\" &&\n prevBlockInfo.blockContent.node.childCount > 0 &&\n nextBlockInfo.isBlockContainer &&\n nextBlockInfo.blockContent.node.type.spec.content === \"inline*\"\n );\n};\n\nconst mergeBlocks = (\n state: EditorState,\n dispatch: ((args?: any) => any) | undefined,\n prevBlockInfo: BlockInfo,\n nextBlockInfo: BlockInfo,\n) => {\n // Un-nests all children of the next block.\n if (!nextBlockInfo.isBlockContainer) {\n throw new Error(\n `Attempted to merge block at position ${nextBlockInfo.bnBlock.beforePos} into previous block at position ${prevBlockInfo.bnBlock.beforePos}, but next block is not a block container`,\n );\n }\n\n // Removes a level of nesting all children of the next block by 1 level, if it contains both content and block\n // group nodes.\n if (nextBlockInfo.childContainer) {\n const childBlocksStart = state.doc.resolve(\n nextBlockInfo.childContainer.beforePos + 1,\n );\n const childBlocksEnd = state.doc.resolve(\n nextBlockInfo.childContainer.afterPos - 1,\n );\n const childBlocksRange = childBlocksStart.blockRange(childBlocksEnd);\n\n if (dispatch) {\n const pos = state.doc.resolve(nextBlockInfo.bnBlock.beforePos);\n state.tr.lift(childBlocksRange!, pos.depth);\n }\n }\n\n // Deletes the boundary between the two blocks. Can be thought of as\n // removing the closing tags of the first block and the opening tags of the\n // second one to stitch them together.\n if (dispatch) {\n if (!prevBlockInfo.isBlockContainer) {\n throw new Error(\n `Attempted to merge block at position ${nextBlockInfo.bnBlock.beforePos} into previous block at position ${prevBlockInfo.bnBlock.beforePos}, but previous block is not a block container`,\n );\n }\n\n // TODO: test merging between a columnList and paragraph, between two columnLists, and v.v.\n dispatch(\n state.tr.delete(\n prevBlockInfo.blockContent.afterPos - 1,\n nextBlockInfo.blockContent.beforePos + 1,\n ),\n );\n }\n\n return true;\n};\n\nexport const mergeBlocksCommand =\n (posBetweenBlocks: number) =>\n ({\n state,\n dispatch,\n }: {\n state: EditorState;\n dispatch: ((args?: any) => any) | undefined;\n }) => {\n const $pos = state.doc.resolve(posBetweenBlocks);\n const nextBlockInfo = getBlockInfoFromResolvedPos($pos);\n\n const prevBlockInfo = getPrevBlockInfo(\n state.doc,\n nextBlockInfo.bnBlock.beforePos,\n );\n\n if (!prevBlockInfo) {\n return false;\n }\n\n const bottomNestedBlockInfo = getBottomNestedBlockInfo(\n state.doc,\n prevBlockInfo,\n );\n\n if (!canMerge(bottomNestedBlockInfo, nextBlockInfo)) {\n return false;\n }\n\n return mergeBlocks(state, dispatch, bottomNestedBlockInfo, nextBlockInfo);\n };\n","import { Extension } from \"@tiptap/core\";\n\nimport { TextSelection } from \"prosemirror-state\";\nimport { ReplaceAroundStep } from \"prosemirror-transform\";\nimport {\n getBottomNestedBlockInfo,\n getParentBlockInfo,\n getPrevBlockInfo,\n mergeBlocksCommand,\n} from \"../../api/blockManipulation/commands/mergeBlocks/mergeBlocks.js\";\nimport { nestBlock } from \"../../api/blockManipulation/commands/nestBlock/nestBlock.js\";\nimport { splitBlockCommand } from \"../../api/blockManipulation/commands/splitBlock/splitBlock.js\";\nimport { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../api/getBlockInfoFromPos.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\n\nexport const KeyboardShortcutsExtension = Extension.create<{\n editor: BlockNoteEditor<any, any, any>;\n tabBehavior: \"prefer-navigate-ui\" | \"prefer-indent\";\n}>({\n priority: 50,\n\n // TODO: The shortcuts need a refactor. Do we want to use a command priority\n // design as there is now, or clump the logic into a single function?\n addKeyboardShortcuts() {\n // handleBackspace is partially adapted from https://github.com/ueberdosis/tiptap/blob/ed56337470efb4fd277128ab7ef792b37cfae992/packages/core/src/extensions/keymap.ts\n const handleBackspace = () =>\n this.editor.commands.first(({ chain, commands }) => [\n // Deletes the selection if it's not empty.\n () => commands.deleteSelection(),\n // Undoes an input rule if one was triggered in the last editor state change.\n () => commands.undoInputRule(),\n // Reverts block content type to a paragraph if the selection is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n\n const selectionAtBlockStart =\n state.selection.from === blockInfo.blockContent.beforePos + 1;\n const isParagraph =\n blockInfo.blockContent.node.type.name === \"paragraph\";\n\n if (selectionAtBlockStart && !isParagraph) {\n return commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"paragraph\",\n props: {},\n }),\n );\n }\n\n return false;\n }),\n // Removes a level of nesting if the block is indented if the selection is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { blockContent } = blockInfo;\n\n const selectionAtBlockStart =\n state.selection.from === blockContent.beforePos + 1;\n\n if (selectionAtBlockStart) {\n return commands.liftListItem(\"blockContainer\");\n }\n\n return false;\n }),\n // Merges block with the previous one if it isn't indented, and the selection is at the start of the\n // block. The target block for merging must contain inline content.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { bnBlock: blockContainer, blockContent } = blockInfo;\n\n const selectionAtBlockStart =\n state.selection.from === blockContent.beforePos + 1;\n const selectionEmpty = state.selection.empty;\n\n const posBetweenBlocks = blockContainer.beforePos;\n\n if (selectionAtBlockStart && selectionEmpty) {\n return chain()\n .command(mergeBlocksCommand(posBetweenBlocks))\n .scrollIntoView()\n .run();\n }\n\n return false;\n }),\n () =>\n commands.command(({ state, dispatch }) => {\n // when at the start of a first block in a column\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n\n const selectionAtBlockStart =\n state.selection.from === blockInfo.blockContent.beforePos + 1;\n\n if (!selectionAtBlockStart) {\n return false;\n }\n\n const prevBlockInfo = getPrevBlockInfo(\n state.doc,\n blockInfo.bnBlock.beforePos,\n );\n\n if (prevBlockInfo) {\n // should be no previous block\n return false;\n }\n\n const parentBlockInfo = getParentBlockInfo(\n state.doc,\n blockInfo.bnBlock.beforePos,\n );\n\n if (parentBlockInfo?.blockNoteType !== \"column\") {\n return false;\n }\n\n const column = parentBlockInfo;\n\n const columnList = getParentBlockInfo(\n state.doc,\n column.bnBlock.beforePos,\n );\n if (columnList?.blockNoteType !== \"columnList\") {\n throw new Error(\"parent of column is not a column list\");\n }\n\n const shouldRemoveColumn =\n column.childContainer!.node.childCount === 1;\n\n const shouldRemoveColumnList =\n shouldRemoveColumn &&\n columnList.childContainer!.node.childCount === 2;\n\n const isFirstColumn =\n columnList.childContainer!.node.firstChild ===\n column.bnBlock.node;\n\n if (dispatch) {\n const blockToMove = state.doc.slice(\n blockInfo.bnBlock.beforePos,\n blockInfo.bnBlock.afterPos,\n false,\n );\n\n /*\n There are 3 different cases:\n a) remove entire column list (if no columns would be remaining)\n b) remove just a column (if no blocks inside a column would be remaining)\n c) keep columns (if there are blocks remaining inside a column)\n\n Each of these 3 cases has 2 sub-cases, depending on whether the backspace happens at the start of the first (most-left) column,\n or at the start of a non-first column.\n */\n if (shouldRemoveColumnList) {\n if (isFirstColumn) {\n state.tr.step(\n new ReplaceAroundStep(\n // replace entire column list\n columnList.bnBlock.beforePos,\n columnList.bnBlock.afterPos,\n // select content of remaining column:\n column.bnBlock.afterPos + 1,\n columnList.bnBlock.afterPos - 2,\n blockToMove,\n blockToMove.size, // append existing content to blockToMove\n false,\n ),\n );\n const pos = state.tr.doc.resolve(column.bnBlock.beforePos);\n state.tr.setSelection(TextSelection.between(pos, pos));\n } else {\n // replaces the column list with the blockToMove slice, prepended with the content of the remaining column\n state.tr.step(\n new ReplaceAroundStep(\n // replace entire column list\n columnList.bnBlock.beforePos,\n columnList.bnBlock.afterPos,\n // select content of existing column:\n columnList.bnBlock.beforePos + 2,\n column.bnBlock.beforePos - 1,\n blockToMove,\n 0, // prepend existing content to blockToMove\n false,\n ),\n );\n const pos = state.tr.doc.resolve(\n state.tr.mapping.map(column.bnBlock.beforePos - 1),\n );\n state.tr.setSelection(TextSelection.between(pos, pos));\n }\n } else if (shouldRemoveColumn) {\n if (isFirstColumn) {\n // delete column\n state.tr.delete(\n column.bnBlock.beforePos,\n column.bnBlock.afterPos,\n );\n\n // move before columnlist\n state.tr.insert(\n columnList.bnBlock.beforePos,\n blockToMove.content,\n );\n\n const pos = state.tr.doc.resolve(\n columnList.bnBlock.beforePos,\n );\n state.tr.setSelection(TextSelection.between(pos, pos));\n } else {\n // just delete the </column><column> closing and opening tags to merge the columns\n state.tr.delete(\n column.bnBlock.beforePos - 1,\n column.bnBlock.beforePos + 1,\n );\n }\n } else {\n // delete block\n state.tr.delete(\n blockInfo.bnBlock.beforePos,\n blockInfo.bnBlock.afterPos,\n );\n if (isFirstColumn) {\n // move before columnlist\n state.tr.insert(\n columnList.bnBlock.beforePos - 1,\n blockToMove.content,\n );\n } else {\n // append block to previous column\n state.tr.insert(\n column.bnBlock.beforePos - 1,\n blockToMove.content,\n );\n }\n const pos = state.tr.doc.resolve(column.bnBlock.beforePos - 1);\n state.tr.setSelection(TextSelection.between(pos, pos));\n }\n }\n\n return true;\n }),\n // Deletes the current block if it's an empty block with inline content,\n // and moves the selection to the previous block.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n\n const blockEmpty =\n blockInfo.blockContent.node.childCount === 0 &&\n blockInfo.blockContent.node.type.spec.content === \"inline*\";\n\n if (blockEmpty) {\n const prevBlockInfo = getPrevBlockInfo(\n state.doc,\n blockInfo.bnBlock.beforePos,\n );\n if (!prevBlockInfo || !prevBlockInfo.isBlockContainer) {\n return false;\n }\n\n let chainedCommands = chain();\n\n if (\n prevBlockInfo.blockContent.node.type.spec.content ===\n \"tableRow+\"\n ) {\n const tableBlockEndPos = blockInfo.bnBlock.beforePos - 1;\n const tableBlockContentEndPos = tableBlockEndPos - 1;\n const lastRowEndPos = tableBlockContentEndPos - 1;\n const lastCellEndPos = lastRowEndPos - 1;\n const lastCellParagraphEndPos = lastCellEndPos - 1;\n\n chainedCommands = chainedCommands.setTextSelection(\n lastCellParagraphEndPos,\n );\n } else if (\n prevBlockInfo.blockContent.node.type.spec.content === \"\"\n ) {\n const nonEditableBlockContentStartPos =\n prevBlockInfo.blockContent.afterPos -\n prevBlockInfo.blockContent.node.nodeSize;\n\n chainedCommands = chainedCommands.setNodeSelection(\n nonEditableBlockContentStartPos,\n );\n } else {\n const blockContentStartPos =\n prevBlockInfo.blockContent.afterPos -\n prevBlockInfo.blockContent.node.nodeSize;\n\n chainedCommands =\n chainedCommands.setTextSelection(blockContentStartPos);\n }\n\n return chainedCommands\n .deleteRange({\n from: blockInfo.bnBlock.beforePos,\n to: blockInfo.bnBlock.afterPos,\n })\n .scrollIntoView()\n .run();\n }\n\n return false;\n }),\n // Deletes previous block if it contains no content and isn't a table,\n // when the selection is empty and at the start of the block. Moves the\n // current block into the deleted block's place.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n\n if (!blockInfo.isBlockContainer) {\n // TODO\n throw new Error(`todo`);\n }\n\n const selectionAtBlockStart =\n state.selection.from === blockInfo.blockContent.beforePos + 1;\n const selectionEmpty = state.selection.empty;\n\n const prevBlockInfo = getPrevBlockInfo(\n state.doc,\n blockInfo.bnBlock.beforePos,\n );\n\n if (prevBlockInfo && selectionAtBlockStart && selectionEmpty) {\n const bottomBlock = getBottomNestedBlockInfo(\n state.doc,\n prevBlockInfo,\n );\n\n if (!bottomBlock.isBlockContainer) {\n // TODO\n throw new Error(`todo`);\n }\n\n const prevBlockNotTableAndNoContent =\n bottomBlock.blockContent.node.type.spec.content === \"\" ||\n (bottomBlock.blockContent.node.type.spec.content ===\n \"inline*\" &&\n bottomBlock.blockContent.node.childCount === 0);\n\n if (prevBlockNotTableAndNoContent) {\n return chain()\n .cut(\n {\n from: blockInfo.bnBlock.beforePos,\n to: blockInfo.bnBlock.afterPos,\n },\n bottomBlock.bnBlock.afterPos,\n )\n .deleteRange({\n from: bottomBlock.bnBlock.beforePos,\n to: bottomBlock.bnBlock.afterPos,\n })\n .run();\n }\n }\n\n return false;\n }),\n ]);\n\n const handleDelete = () =>\n this.editor.commands.first(({ commands }) => [\n // Deletes the selection if it's not empty.\n () => commands.deleteSelection(),\n // Merges block with the next one (at the same nesting level or lower),\n // if one exists, the block has no children, and the selection is at the\n // end of the block.\n () =>\n commands.command(({ state }) => {\n // TODO: Change this to not rely on offsets & schema assumptions\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const {\n bnBlock: blockContainer,\n blockContent,\n childContainer,\n } = blockInfo;\n\n const { depth } = state.doc.resolve(blockContainer.beforePos);\n const blockAtDocEnd =\n blockContainer.afterPos === state.doc.nodeSize - 3;\n const selectionAtBlockEnd =\n state.selection.from === blockContent.afterPos - 1;\n const selectionEmpty = state.selection.empty;\n const hasChildBlocks = childContainer !== undefined;\n\n if (\n !blockAtDocEnd &&\n selectionAtBlockEnd &&\n selectionEmpty &&\n !hasChildBlocks\n ) {\n let oldDepth = depth;\n let newPos = blockContainer.afterPos + 1;\n let newDepth = state.doc.resolve(newPos).depth;\n\n while (newDepth < oldDepth) {\n oldDepth = newDepth;\n newPos += 2;\n newDepth = state.doc.resolve(newPos).depth;\n }\n\n return commands.command(mergeBlocksCommand(newPos - 1));\n }\n\n return false;\n }),\n ]);\n\n const handleEnter = (withShift = false) => {\n return this.editor.commands.first(({ commands }) => [\n // Removes a level of nesting if the block is empty & indented, while the selection is also empty & at the start\n // of the block.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { bnBlock: blockContainer, blockContent } = blockInfo;\n\n const { depth } = state.doc.resolve(blockContainer.beforePos);\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\n const blockEmpty = blockContent.node.childCount === 0;\n const blockIndented = depth > 1;\n\n if (\n selectionAtBlockStart &&\n selectionEmpty &&\n blockEmpty &&\n blockIndented\n ) {\n return commands.liftListItem(\"blockContainer\");\n }\n\n return false;\n }),\n // Creates a hard break if block is configured to do so.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n\n const blockHardBreakShortcut: \"shift+enter\" | \"enter\" | \"none\" =\n this.options.editor.schema.blockSchema[blockInfo.blockNoteType]\n .hardBreakShortcut ?? \"shift+enter\";\n\n if (blockHardBreakShortcut === \"none\") {\n return false;\n }\n\n if (\n // If shortcut is not configured, or is configured as \"shift+enter\",\n // create a hard break for shift+enter, but not for enter.\n (blockHardBreakShortcut === \"shift+enter\" && withShift) ||\n // If shortcut is configured as \"enter\", create a hard break for\n // both enter and shift+enter.\n blockHardBreakShortcut === \"enter\"\n ) {\n return commands.insertContent({\n type: \"hardBreak\",\n });\n }\n\n return false;\n }),\n // Creates a new block and moves the selection to it if the current one is empty, while the selection is also\n // empty & at the start of the block.\n () =>\n commands.command(({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { bnBlock: blockContainer, blockContent } = blockInfo;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\n const blockEmpty = blockContent.node.childCount === 0;\n\n if (selectionAtBlockStart && selectionEmpty && blockEmpty) {\n const newBlockInsertionPos = blockContainer.afterPos;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n if (dispatch) {\n const newBlock =\n state.schema.nodes[\"blockContainer\"].createAndFill()!;\n\n state.tr\n .insert(newBlockInsertionPos, newBlock)\n .scrollIntoView();\n state.tr.setSelection(\n new TextSelection(state.doc.resolve(newBlockContentPos)),\n );\n }\n\n return true;\n }\n\n return false;\n }),\n // Splits the current block, moving content inside that's after the cursor to a new text block below. Also\n // deletes the selection beforehand, if it's not empty.\n () =>\n commands.command(({ state, chain }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { blockContent } = blockInfo;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const blockEmpty = blockContent.node.childCount === 0;\n\n if (!blockEmpty) {\n chain()\n .deleteSelection()\n .command(\n splitBlockCommand(\n state.selection.from,\n selectionAtBlockStart,\n selectionAtBlockStart,\n ),\n )\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n };\n\n return {\n Backspace: handleBackspace,\n Delete: handleDelete,\n Enter: () => handleEnter(),\n \"Shift-Enter\": () => handleEnter(true),\n // Always returning true for tab key presses ensures they're not captured by the browser. Otherwise, they blur the\n // editor since the browser will try to use tab for keyboard navigation.\n Tab: () => {\n if (\n this.options.tabBehavior !== \"prefer-indent\" &&\n (this.options.editor.formattingToolbar?.shown ||\n this.options.editor.linkToolbar?.shown ||\n this.options.editor.filePanel?.shown)\n ) {\n // don't handle tabs if a toolbar is shown, so we can tab into / out of it\n return false;\n }\n return nestBlock(this.options.editor);\n // return true;\n },\n \"Shift-Tab\": () => {\n if (\n this.options.tabBehavior !== \"prefer-indent\" &&\n (this.options.editor.formattingToolbar?.shown ||\n this.options.editor.linkToolbar?.shown ||\n this.options.editor.filePanel?.shown)\n ) {\n // don't handle tabs if a toolbar is shown, so we can tab into / out of it\n return false;\n }\n this.editor.commands.liftListItem(\"blockContainer\");\n return true;\n },\n \"Shift-Mod-ArrowUp\": () => {\n this.options.editor.moveBlocksUp();\n return true;\n },\n \"Shift-Mod-ArrowDown\": () => {\n this.options.editor.moveBlocksDown();\n return true;\n },\n \"Mod-z\": () => this.options.editor.undo(),\n \"Mod-y\": () => this.options.editor.redo(),\n \"Shift-Mod-z\": () => this.options.editor.redo(),\n };\n },\n});\n","import { getMarkRange, posToDOMRect, Range } from \"@tiptap/core\";\n\nimport { EditorView } from \"@tiptap/pm/view\";\nimport { Mark } from \"prosemirror-model\";\nimport { EditorState, Plugin, PluginKey, PluginView } from \"prosemirror-state\";\n\nimport { getPmSchema } from \"../../api/pmUtil.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\n\nexport type LinkToolbarState = UiElementPosition & {\n // The hovered link's URL, and the text it's displayed with in the\n // editor.\n url: string;\n text: string;\n};\n\nclass LinkToolbarView implements PluginView {\n public state?: LinkToolbarState;\n public emitUpdate: () => void;\n\n menuUpdateTimer: ReturnType<typeof setTimeout> | undefined;\n startMenuUpdateTimer: () => void;\n stopMenuUpdateTimer: () => void;\n\n mouseHoveredLinkMark: Mark | undefined;\n mouseHoveredLinkMarkRange: Range | undefined;\n\n keyboardHoveredLinkMark: Mark | undefined;\n keyboardHoveredLinkMarkRange: Range | undefined;\n\n linkMark: Mark | undefined;\n linkMarkRange: Range | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<any, any, any>,\n private readonly pmView: EditorView,\n emitUpdate: (state: LinkToolbarState) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized link toolbar\");\n }\n\n emitUpdate(this.state);\n };\n\n this.startMenuUpdateTimer = () => {\n this.menuUpdateTimer = setTimeout(() => {\n this.update(this.pmView, undefined, true);\n }, 250);\n };\n\n this.stopMenuUpdateTimer = () => {\n if (this.menuUpdateTimer) {\n clearTimeout(this.menuUpdateTimer);\n this.menuUpdateTimer = undefined;\n }\n\n return false;\n };\n\n this.pmView.dom.addEventListener(\"mouseover\", this.mouseOverHandler);\n this.pmView.root.addEventListener(\n \"click\",\n this.clickHandler as EventListener,\n true,\n );\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n this.pmView.root.addEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n mouseOverHandler = (event: MouseEvent) => {\n // Resets the link mark currently hovered by the mouse cursor.\n this.mouseHoveredLinkMark = undefined;\n this.mouseHoveredLinkMarkRange = undefined;\n\n this.stopMenuUpdateTimer();\n\n if (\n event.target instanceof HTMLAnchorElement &&\n event.target.nodeName === \"A\"\n ) {\n // Finds link mark at the hovered element's position to update mouseHoveredLinkMark and\n // mouseHoveredLinkMarkRange.\n const hoveredLinkElement = event.target;\n const posInHoveredLinkMark =\n this.pmView.posAtDOM(hoveredLinkElement, 0) + 1;\n const resolvedPosInHoveredLinkMark =\n this.pmView.state.doc.resolve(posInHoveredLinkMark);\n const marksAtPos = resolvedPosInHoveredLinkMark.marks();\n\n for (const mark of marksAtPos) {\n if (\n mark.type.name === this.pmView.state.schema.mark(\"link\").type.name\n ) {\n this.mouseHoveredLinkMark = mark;\n this.mouseHoveredLinkMarkRange =\n getMarkRange(resolvedPosInHoveredLinkMark, mark.type, mark.attrs) ||\n undefined;\n\n break;\n }\n }\n }\n\n this.startMenuUpdateTimer();\n\n return false;\n };\n\n clickHandler = (event: MouseEvent) => {\n const editorWrapper = this.pmView.dom.parentElement!;\n\n if (\n // Toolbar is open.\n this.linkMark &&\n // An element is clicked.\n event &&\n event.target &&\n // The clicked element is not the editor.\n !(\n editorWrapper === (event.target as Node) ||\n editorWrapper.contains(event.target as Node)\n )\n ) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n };\n\n scrollHandler = () => {\n if (this.linkMark !== undefined) {\n if (this.state?.show) {\n this.state.referencePos = posToDOMRect(\n this.pmView,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n );\n this.emitUpdate();\n }\n }\n };\n\n editLink(url: string, text: string) {\n this.editor.transact((tr) => {\n const pmSchema = getPmSchema(tr);\n tr.insertText(text, this.linkMarkRange!.from, this.linkMarkRange!.to);\n tr.addMark(\n this.linkMarkRange!.from,\n this.linkMarkRange!.from + text.length,\n pmSchema.mark(\"link\", { href: url }),\n );\n });\n this.pmView.focus();\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n deleteLink() {\n this.editor.transact((tr) =>\n tr\n .removeMark(\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n this.linkMark!.type,\n )\n .setMeta(\"preventAutolink\", true),\n );\n this.pmView.focus();\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n update(view: EditorView, oldState?: EditorState, fromMouseOver = false) {\n const { state } = view;\n\n const isSame =\n oldState &&\n oldState.selection.from === state.selection.from &&\n oldState.selection.to === state.selection.to;\n\n if (isSame || !this.pmView.hasFocus()) {\n return;\n }\n\n // Saves the currently hovered link mark before it's updated.\n const prevLinkMark = this.linkMark;\n\n // Resets the currently hovered link mark.\n this.linkMark = undefined;\n this.linkMarkRange = undefined;\n\n // Resets the link mark currently hovered by the keyboard cursor.\n this.keyboardHoveredLinkMark = undefined;\n this.keyboardHoveredLinkMarkRange = undefined;\n\n // Finds link mark at the editor selection's position to update keyboardHoveredLinkMark and\n // keyboardHoveredLinkMarkRange.\n if (this.pmView.state.selection.empty) {\n const marksAtPos = this.pmView.state.selection.$from.marks();\n\n for (const mark of marksAtPos) {\n if (\n mark.type.name === this.pmView.state.schema.mark(\"link\").type.name\n ) {\n this.keyboardHoveredLinkMark = mark;\n this.keyboardHoveredLinkMarkRange =\n getMarkRange(\n this.pmView.state.selection.$from,\n mark.type,\n mark.attrs,\n ) || undefined;\n\n break;\n }\n }\n }\n\n if (this.mouseHoveredLinkMark && fromMouseOver) {\n this.linkMark = this.mouseHoveredLinkMark;\n this.linkMarkRange = this.mouseHoveredLinkMarkRange;\n }\n\n // Keyboard cursor position takes precedence over mouse hovered link.\n if (this.keyboardHoveredLinkMark) {\n this.linkMark = this.keyboardHoveredLinkMark;\n this.linkMarkRange = this.keyboardHoveredLinkMarkRange;\n }\n\n if (this.linkMark && this.editor.isEditable) {\n this.state = {\n show: true,\n referencePos: posToDOMRect(\n this.pmView,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n ),\n url: this.linkMark!.attrs.href,\n text: this.pmView.state.doc.textBetween(\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n ),\n };\n this.emitUpdate();\n\n return;\n }\n\n // Hides menu.\n if (\n this.state?.show &&\n prevLinkMark &&\n (!this.linkMark || !this.editor.isEditable)\n ) {\n this.state.show = false;\n this.emitUpdate();\n\n return;\n }\n }\n\n closeMenu = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mouseover\", this.mouseOverHandler);\n this.pmView.root.removeEventListener(\"scroll\", this.scrollHandler, true);\n this.pmView.root.removeEventListener(\n \"click\",\n this.clickHandler as EventListener,\n true,\n );\n }\n}\n\nexport const linkToolbarPluginKey = new PluginKey(\"LinkToolbarPlugin\");\n\nexport class LinkToolbarProsemirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"linkToolbar\";\n }\n\n private view: LinkToolbarView | undefined;\n\n constructor(editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: linkToolbarPluginKey,\n view: (editorView) => {\n this.view = new LinkToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n props: {\n handleKeyDown: (_view, event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.shown) {\n this.view!.closeMenu();\n return true;\n }\n return false;\n },\n },\n }),\n );\n }\n\n public onUpdate(callback: (state: LinkToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Edit the currently hovered link.\n */\n public editLink = (url: string, text: string) => {\n this.view!.editLink(url, text);\n };\n\n /**\n * Delete the currently hovered link.\n */\n public deleteLink = () => {\n this.view!.deleteLink();\n };\n\n /**\n * When hovering on/off links using the mouse cursor, the link toolbar will\n * open & close with a delay.\n *\n * This function starts the delay timer, and should be used for when the mouse\n * cursor enters the link toolbar.\n */\n public startHideTimer = () => {\n this.view!.startMenuUpdateTimer();\n };\n\n /**\n * When hovering on/off links using the mouse cursor, the link toolbar will\n * open & close with a delay.\n *\n * This function stops the delay timer, and should be used for when the mouse\n * cursor exits the link toolbar.\n */\n public stopHideTimer = () => {\n this.view!.stopMenuUpdateTimer();\n };\n\n public get shown() {\n return this.view?.state?.show || false;\n }\n\n public closeMenu = () => this.view!.closeMenu();\n}\n","export const VALID_LINK_PROTOCOLS = [\n \"http\",\n \"https\",\n \"ftp\",\n \"ftps\",\n \"mailto\",\n \"tel\",\n \"callto\",\n \"sms\",\n \"cid\",\n \"xmpp\",\n];\nexport const DEFAULT_LINK_PROTOCOL = \"https\";\n","import { Plugin, PluginKey, TextSelection } from \"prosemirror-state\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nconst PLUGIN_KEY = new PluginKey(\"node-selection-keyboard\");\n// By default, typing with a node selection active will cause ProseMirror to\n// replace the node with one that contains editable content. This plugin blocks\n// this behaviour without also blocking things like keyboard shortcuts:\n//\n// - Lets through key presses that do not include alphanumeric characters. This\n// includes things like backspace/delete/home/end/etc.\n// - Lets through any key presses that include ctrl/meta keys. These will be\n// shortcuts of some kind like ctrl+C/mod+C.\n// - Special case for Enter key which creates a new paragraph block below and\n// sets the selection to it. This is just to bring the UX closer to Notion\n//\n// While a more elegant solution would probably process transactions instead of\n// keystrokes, this brings us most of the way to Notion's UX without much added\n// complexity.\nexport class NodeSelectionKeyboardPlugin extends BlockNoteExtension {\n public static key() {\n return \"nodeSelectionKeyboard\";\n }\n\n constructor() {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: PLUGIN_KEY,\n props: {\n handleKeyDown: (view, event) => {\n // Checks for node selection\n if (\"node\" in view.state.selection) {\n // Checks if key press uses ctrl/meta modifier\n if (event.ctrlKey || event.metaKey) {\n return false;\n }\n // Checks if key press is alphanumeric\n if (event.key.length === 1) {\n event.preventDefault();\n\n return true;\n }\n // Checks if key press is Enter\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey\n ) {\n const tr = view.state.tr;\n view.dispatch(\n tr\n .insert(\n view.state.tr.selection.$to.after(),\n view.state.schema.nodes[\"paragraph\"].createChecked(),\n )\n .setSelection(\n new TextSelection(\n tr.doc.resolve(view.state.tr.selection.$to.after() + 1),\n ),\n ),\n );\n\n return true;\n }\n }\n\n return false;\n },\n },\n }),\n );\n }\n}\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { v4 } from \"uuid\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nconst PLUGIN_KEY = new PluginKey(`blocknote-placeholder`);\n\nexport class PlaceholderPlugin extends BlockNoteExtension {\n public static key() {\n return \"placeholder\";\n }\n\n constructor(\n editor: BlockNoteEditor<any, any, any>,\n placeholders: Record<\n string | \"default\" | \"emptyDocument\",\n string | undefined\n >,\n ) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: PLUGIN_KEY,\n view: (view) => {\n const uniqueEditorSelector = `placeholder-selector-${v4()}`;\n view.dom.classList.add(uniqueEditorSelector);\n const styleEl = document.createElement(\"style\");\n\n const nonce = editor._tiptapEditor.options.injectNonce;\n if (nonce) {\n styleEl.setAttribute(\"nonce\", nonce);\n }\n\n if (editor.prosemirrorView?.root instanceof ShadowRoot) {\n editor.prosemirrorView.root.append(styleEl);\n } else {\n editor.prosemirrorView?.root.head.appendChild(styleEl);\n }\n\n const styleSheet = styleEl.sheet!;\n\n const getSelector = (additionalSelectors = \"\") =>\n `.${uniqueEditorSelector} .bn-block-content${additionalSelectors} .bn-inline-content:has(> .ProseMirror-trailingBreak:only-child):before`;\n\n try {\n // FIXME: the names \"default\" and \"emptyDocument\" are hardcoded\n const {\n default: defaultPlaceholder,\n emptyDocument: emptyPlaceholder,\n ...rest\n } = placeholders;\n\n // add block specific placeholders\n for (const [blockType, placeholder] of Object.entries(rest)) {\n const blockTypeSelector = `[data-content-type=\"${blockType}\"]`;\n\n styleSheet.insertRule(\n `${getSelector(blockTypeSelector)} { content: ${JSON.stringify(\n placeholder,\n )}; }`,\n );\n }\n\n const onlyBlockSelector = `[data-is-only-empty-block]`;\n const mustBeFocusedSelector = `[data-is-empty-and-focused]`;\n\n // placeholder for when there's only one empty block\n styleSheet.insertRule(\n `${getSelector(onlyBlockSelector)} { content: ${JSON.stringify(\n emptyPlaceholder,\n )}; }`,\n );\n\n // placeholder for default blocks, only when the cursor is in the block (mustBeFocused)\n styleSheet.insertRule(\n `${getSelector(mustBeFocusedSelector)} { content: ${JSON.stringify(\n defaultPlaceholder,\n )}; }`,\n );\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(\n `Failed to insert placeholder CSS rule - this is likely due to the browser not supporting certain CSS pseudo-element selectors (:has, :only-child:, or :before)`,\n e,\n );\n }\n\n return {\n destroy: () => {\n if (editor.prosemirrorView?.root instanceof ShadowRoot) {\n editor.prosemirrorView.root.removeChild(styleEl);\n } else {\n editor.prosemirrorView?.root.head.removeChild(styleEl);\n }\n },\n };\n },\n props: {\n decorations: (state) => {\n const { doc, selection } = state;\n\n if (!editor.isEditable) {\n return;\n }\n\n if (!selection.empty) {\n return;\n }\n\n // Don't show placeholder when the cursor is inside a code block\n if (selection.$from.parent.type.spec.code) {\n return;\n }\n\n const decs = [];\n\n // decoration for when there's only one empty block\n // positions are hardcoded for now\n if (state.doc.content.size === 6) {\n decs.push(\n Decoration.node(2, 4, {\n \"data-is-only-empty-block\": \"true\",\n }),\n );\n }\n\n const $pos = selection.$anchor;\n const node = $pos.parent;\n\n if (node.content.size === 0) {\n const before = $pos.before();\n\n decs.push(\n Decoration.node(before, before + node.nodeSize, {\n \"data-is-empty-and-focused\": \"true\",\n }),\n );\n }\n\n return DecorationSet.create(doc, decs);\n },\n },\n }),\n );\n }\n}\n","import { findChildren } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nconst PLUGIN_KEY = new PluginKey(`previous-blocks`);\n\nconst nodeAttributes: Record<string, string> = {\n // Numbered List Items\n index: \"index\",\n // Headings\n level: \"level\",\n // All Blocks\n type: \"type\",\n depth: \"depth\",\n \"depth-change\": \"depth-change\",\n};\n\n/**\n * This plugin tracks transformation of Block node attributes, so we can support CSS transitions.\n *\n * Problem it solves: ProseMirror recreates the DOM when transactions happen. So when a transaction changes a Node attribute,\n * it results in a completely new DOM element. This means CSS transitions don't work.\n *\n * Solution: When attributes change on a node, this plugin sets a data-* attribute with the \"previous\" value. This way we can still use CSS transitions. (See block.module.css)\n */\nexport class PreviousBlockTypePlugin extends BlockNoteExtension {\n public static key() {\n return \"previousBlockType\";\n }\n\n constructor() {\n super();\n let timeout: ReturnType<typeof setTimeout>;\n this.addProsemirrorPlugin(\n new Plugin({\n key: PLUGIN_KEY,\n view(_editorView) {\n return {\n update: async (view, _prevState) => {\n if (this.key?.getState(view.state).updatedBlocks.size > 0) {\n // use setTimeout 0 to clear the decorations so that at least\n // for one DOM-render the decorations have been applied\n timeout = setTimeout(() => {\n view.dispatch(\n view.state.tr.setMeta(PLUGIN_KEY, { clearUpdate: true }),\n );\n }, 0);\n }\n },\n destroy: () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n },\n };\n },\n state: {\n init() {\n return {\n // Block attributes, by block ID, from just before the previous transaction.\n prevTransactionOldBlockAttrs: {} as any,\n // Block attributes, by block ID, from just before the current transaction.\n currentTransactionOldBlockAttrs: {} as any,\n // Set of IDs of blocks whose attributes changed from the current transaction.\n updatedBlocks: new Set<string>(),\n };\n },\n\n apply(transaction, prev, oldState, newState) {\n prev.currentTransactionOldBlockAttrs = {};\n prev.updatedBlocks.clear();\n\n if (!transaction.docChanged || oldState.doc.eq(newState.doc)) {\n return prev;\n }\n\n // TODO: Instead of iterating through the entire document, only check nodes affected by the transactions. Will\n // also probably require checking nodes affected by the previous transaction too.\n // We didn't get this to work yet:\n // const transform = combineTransactionSteps(oldState.doc, [transaction]);\n // // const { mapping } = transform;\n // const changes = getChangedRanges(transform);\n //\n // changes.forEach(({ oldRange, newRange }) => {\n // const oldNodes = findChildrenInRange(\n // oldState.doc,\n // oldRange,\n // (node) => node.attrs.id\n // );\n //\n // const newNodes = findChildrenInRange(\n // newState.doc,\n // newRange,\n // (node) => node.attrs.id\n // );\n\n const currentTransactionOriginalOldBlockAttrs = {} as any;\n\n const oldNodes = findChildren(\n oldState.doc,\n (node) => node.attrs.id,\n );\n const oldNodesById = new Map(\n oldNodes.map((node) => [node.node.attrs.id, node]),\n );\n const newNodes = findChildren(\n newState.doc,\n (node) => node.attrs.id,\n );\n\n // Traverses all block containers in the new editor state.\n for (const node of newNodes) {\n const oldNode = oldNodesById.get(node.node.attrs.id);\n\n const oldContentNode = oldNode?.node.firstChild;\n const newContentNode = node.node.firstChild;\n\n if (oldNode && oldContentNode && newContentNode) {\n const newAttrs = {\n index: newContentNode.attrs.index,\n level: newContentNode.attrs.level,\n type: newContentNode.type.name,\n depth: newState.doc.resolve(node.pos).depth,\n };\n\n let oldAttrs = {\n index: oldContentNode.attrs.index,\n level: oldContentNode.attrs.level,\n type: oldContentNode.type.name,\n depth: oldState.doc.resolve(oldNode.pos).depth,\n };\n\n currentTransactionOriginalOldBlockAttrs[node.node.attrs.id] =\n oldAttrs;\n\n // Whenever a transaction is appended by the OrderedListItemIndexPlugin, it's given the metadata:\n // { \"orderedListIndexing\": true }\n // These appended transactions happen immediately after any transaction which causes ordered list item\n // indices to require updating, including those which trigger animations. Therefore, these animations are\n // immediately overridden when the PreviousBlockTypePlugin processes the appended transaction, despite only\n // the listItemIndex attribute changing. To solve this, oldAttrs must be edited for transactions with the\n // \"orderedListIndexing\" metadata, so the correct animation can be re-triggered.\n if (transaction.getMeta(\"numberedListIndexing\")) {\n // If the block existed before the transaction, gets the attributes from before the previous transaction\n // (i.e. the transaction that caused list item indices to need updating).\n if (node.node.attrs.id in prev.prevTransactionOldBlockAttrs) {\n oldAttrs =\n prev.prevTransactionOldBlockAttrs[node.node.attrs.id];\n }\n\n // Stops list item indices themselves being animated (looks smoother), unless the block's content type is\n // changing from a numbered list item to something else.\n if (newAttrs.type === \"numberedListItem\") {\n oldAttrs.index = newAttrs.index;\n }\n }\n\n prev.currentTransactionOldBlockAttrs[node.node.attrs.id] =\n oldAttrs;\n\n // TODO: faster deep equal?\n if (JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs)) {\n (oldAttrs as any)[\"depth-change\"] =\n oldAttrs.depth - newAttrs.depth;\n\n // for debugging:\n // console.log(\n // \"id:\",\n // node.node.attrs.id,\n // \"previousBlockTypePlugin changes detected, oldAttrs\",\n // oldAttrs,\n // \"new\",\n // newAttrs\n // );\n\n prev.updatedBlocks.add(node.node.attrs.id);\n }\n }\n }\n\n prev.prevTransactionOldBlockAttrs =\n currentTransactionOriginalOldBlockAttrs;\n\n return prev;\n },\n },\n props: {\n decorations(state) {\n const pluginState = (this as Plugin).getState(state);\n if (pluginState.updatedBlocks.size === 0) {\n return undefined;\n }\n\n const decorations: Decoration[] = [];\n\n state.doc.descendants((node, pos) => {\n if (!node.attrs.id) {\n return;\n }\n\n if (!pluginState.updatedBlocks.has(node.attrs.id)) {\n return;\n }\n\n const prevAttrs =\n pluginState.currentTransactionOldBlockAttrs[node.attrs.id];\n const decorationAttrs: any = {};\n\n for (const [nodeAttr, val] of Object.entries(prevAttrs)) {\n decorationAttrs[\"data-prev-\" + nodeAttributes[nodeAttr]] =\n val || \"none\";\n }\n\n // for debugging:\n // console.log(\n // \"previousBlockTypePlugin committing decorations\",\n // decorationAttrs\n // );\n\n const decoration = Decoration.node(pos, pos + node.nodeSize, {\n ...decorationAttrs,\n });\n\n decorations.push(decoration);\n });\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n }),\n );\n }\n}\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nconst PLUGIN_KEY = new PluginKey(`blocknote-show-selection`);\n\n/**\n * Plugin that shows adds a decoration around the current selection\n * This can be used to highlight the current selection in the UI even when the\n * text editor is not focused.\n */\nexport class ShowSelectionPlugin extends BlockNoteExtension {\n public static key() {\n return \"showSelection\";\n }\n\n private enabled = false;\n\n public constructor(private readonly editor: BlockNoteEditor<any, any, any>) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: PLUGIN_KEY,\n props: {\n decorations: (state) => {\n const { doc, selection } = state;\n\n if (!this.enabled) {\n return DecorationSet.empty;\n }\n\n const dec = Decoration.inline(selection.from, selection.to, {\n \"data-show-selection\": \"true\",\n });\n\n return DecorationSet.create(doc, [dec]);\n },\n },\n }),\n );\n }\n\n public setEnabled(enabled: boolean) {\n if (this.enabled === enabled) {\n return;\n }\n\n this.enabled = enabled;\n\n this.editor.transact((tr) => tr.setMeta(PLUGIN_KEY, {}));\n }\n\n public getEnabled() {\n return this.enabled;\n }\n}\n","import { EditorView } from \"prosemirror-view\";\n\nexport function getDraggableBlockFromElement(\n element: Element,\n view: EditorView,\n) {\n while (\n element &&\n element.parentElement &&\n element.parentElement !== view.dom &&\n element.getAttribute?.(\"data-node-type\") !== \"blockContainer\"\n ) {\n element = element.parentElement;\n }\n if (element.getAttribute?.(\"data-node-type\") !== \"blockContainer\") {\n return undefined;\n }\n return { node: element as HTMLElement, id: element.getAttribute(\"data-id\")! };\n}\n","import { Fragment, Node, ResolvedPos, Slice } from \"prosemirror-model\";\nimport { Selection } from \"prosemirror-state\";\nimport { Mappable } from \"prosemirror-transform\";\n\n/**\n * This class represents an editor selection which spans multiple nodes/blocks. It's currently only used to allow users\n * to drag multiple blocks at the same time. Expects the selection anchor and head to be between nodes, i.e. just before\n * the first target node and just after the last, and that anchor and head are at the same nesting level.\n *\n * Partially based on ProseMirror's NodeSelection implementation:\n * (https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.ts)\n * MultipleNodeSelection differs from NodeSelection in the following ways:\n * 1. Stores which nodes are included in the selection instead of just a single node.\n * 2. Already expects the selection to start just before the first target node and ends just after the last, while a\n * NodeSelection automatically sets both anchor and head to just before the single target node.\n */\nexport class MultipleNodeSelection extends Selection {\n nodes: Array<Node>;\n\n constructor($anchor: ResolvedPos, $head: ResolvedPos) {\n super($anchor, $head);\n\n // Parent is at the same nesting level as anchor/head since they are just before/ just after target nodes.\n const parentNode = $anchor.node();\n\n this.nodes = [];\n $anchor.doc.nodesBetween($anchor.pos, $head.pos, (node, _pos, parent) => {\n if (parent !== null && parent.eq(parentNode)) {\n this.nodes.push(node);\n return false;\n }\n return;\n });\n }\n\n static create(doc: Node, from: number, to = from): MultipleNodeSelection {\n return new MultipleNodeSelection(doc.resolve(from), doc.resolve(to));\n }\n\n content(): Slice {\n return new Slice(Fragment.from(this.nodes), 0, 0);\n }\n\n eq(selection: Selection): boolean {\n if (!(selection instanceof MultipleNodeSelection)) {\n return false;\n }\n\n if (this.nodes.length !== selection.nodes.length) {\n return false;\n }\n\n if (this.from !== selection.from || this.to !== selection.to) {\n return false;\n }\n\n for (let i = 0; i < this.nodes.length; i++) {\n if (!this.nodes[i].eq(selection.nodes[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n map(doc: Node, mapping: Mappable): Selection {\n const fromResult = mapping.mapResult(this.from);\n const toResult = mapping.mapResult(this.to);\n\n if (toResult.deleted) {\n return Selection.near(doc.resolve(fromResult.pos));\n }\n\n if (fromResult.deleted) {\n return Selection.near(doc.resolve(toResult.pos));\n }\n\n return new MultipleNodeSelection(\n doc.resolve(fromResult.pos),\n doc.resolve(toResult.pos),\n );\n }\n\n toJSON(): any {\n return { type: \"multiple-node\", anchor: this.anchor, head: this.head };\n }\n}\n\nSelection.jsonID(\"multiple-node\", MultipleNodeSelection);\n","import { Node } from \"prosemirror-model\";\nimport { NodeSelection, Selection } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport { createExternalHTMLExporter } from \"../../api/exporters/html/externalHTMLExporter.js\";\nimport { cleanHTMLToMarkdown } from \"../../api/exporters/markdown/markdownExporter.js\";\nimport { fragmentToBlocks } from \"../../api/nodeConversions/fragmentToBlocks.js\";\nimport { getNodeById } from \"../../api/nodeUtil.js\";\nimport { Block } from \"../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { MultipleNodeSelection } from \"./MultipleNodeSelection.js\";\n\nlet dragImageElement: Element | undefined;\n\nexport type SideMenuState<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = UiElementPosition & {\n // The block that the side menu is attached to.\n block: Block<BSchema, I, S>;\n};\n\nfunction blockPositionsFromSelection(selection: Selection, doc: Node) {\n // Absolute positions just before the first block spanned by the selection, and just after the last block. Having the\n // selection start and end just before and just after the target blocks ensures no whitespace/line breaks are left\n // behind after dragging & dropping them.\n let beforeFirstBlockPos: number;\n let afterLastBlockPos: number;\n\n // Even the user starts dragging blocks but drops them in the same place, the selection will still be moved just\n // before & just after the blocks spanned by the selection, and therefore doesn't need to change if they try to drag\n // the same blocks again. If this happens, the anchor & head move out of the block content node they were originally\n // in. If the anchor should update but the head shouldn't and vice versa, it means the user selection is outside a\n // block content node, which should never happen.\n const selectionStartInBlockContent =\n doc.resolve(selection.from).node().type.spec.group === \"blockContent\";\n const selectionEndInBlockContent =\n doc.resolve(selection.to).node().type.spec.group === \"blockContent\";\n\n // Ensures that entire outermost nodes are selected if the selection spans multiple nesting levels.\n const minDepth = Math.min(selection.$anchor.depth, selection.$head.depth);\n\n if (selectionStartInBlockContent && selectionEndInBlockContent) {\n // Absolute positions at the start of the first block in the selection and at the end of the last block. User\n // selections will always start and end in block content nodes, but we want the start and end positions of their\n // parent block nodes, which is why minDepth - 1 is used.\n const startFirstBlockPos = selection.$from.start(minDepth - 1);\n const endLastBlockPos = selection.$to.end(minDepth - 1);\n\n // Shifting start and end positions by one moves them just outside the first and last selected blocks.\n beforeFirstBlockPos = doc.resolve(startFirstBlockPos - 1).pos;\n afterLastBlockPos = doc.resolve(endLastBlockPos + 1).pos;\n } else {\n beforeFirstBlockPos = selection.from;\n afterLastBlockPos = selection.to;\n }\n\n return { from: beforeFirstBlockPos, to: afterLastBlockPos };\n}\n\nfunction setDragImage(view: EditorView, from: number, to = from) {\n if (from === to) {\n // Moves to position to be just after the first (and only) selected block.\n to += view.state.doc.resolve(from + 1).node().nodeSize;\n }\n\n // Parent element is cloned to remove all unselected children without affecting the editor content.\n const parentClone = view.domAtPos(from).node.cloneNode(true) as Element;\n const parent = view.domAtPos(from).node as Element;\n\n const getElementIndex = (parentElement: Element, targetElement: Element) =>\n Array.prototype.indexOf.call(parentElement.children, targetElement);\n\n const firstSelectedBlockIndex = getElementIndex(\n parent,\n // Expects from position to be just before the first selected block.\n view.domAtPos(from + 1).node.parentElement!,\n );\n const lastSelectedBlockIndex = getElementIndex(\n parent,\n // Expects to position to be just after the last selected block.\n view.domAtPos(to - 1).node.parentElement!,\n );\n\n for (let i = parent.childElementCount - 1; i >= 0; i--) {\n if (i > lastSelectedBlockIndex || i < firstSelectedBlockIndex) {\n parentClone.removeChild(parentClone.children[i]);\n }\n }\n\n // dataTransfer.setDragImage(element) only works if element is attached to the DOM.\n unsetDragImage(view.root);\n dragImageElement = parentClone;\n\n // Browsers may have CORS policies which prevents iframes from being\n // manipulated, so better to stay on the safe side and remove them from the\n // drag preview. The drag preview doesn't work with iframes anyway.\n const iframes = dragImageElement.getElementsByTagName(\"iframe\");\n for (let i = 0; i < iframes.length; i++) {\n const iframe = iframes[i];\n const parent = iframe.parentElement;\n\n if (parent) {\n parent.removeChild(iframe);\n }\n }\n\n // TODO: This is hacky, need a better way of assigning classes to the editor so that they can also be applied to the\n // drag preview.\n const classes = view.dom.className.split(\" \");\n const inheritedClasses = classes\n .filter(\n (className) =>\n className !== \"ProseMirror\" &&\n className !== \"bn-root\" &&\n className !== \"bn-editor\",\n )\n .join(\" \");\n\n dragImageElement.className =\n dragImageElement.className + \" bn-drag-preview \" + inheritedClasses;\n\n if (view.root instanceof ShadowRoot) {\n view.root.appendChild(dragImageElement);\n } else {\n view.root.body.appendChild(dragImageElement);\n }\n}\n\nexport function unsetDragImage(rootEl: Document | ShadowRoot) {\n if (dragImageElement !== undefined) {\n if (rootEl instanceof ShadowRoot) {\n rootEl.removeChild(dragImageElement);\n } else {\n rootEl.body.removeChild(dragImageElement);\n }\n\n dragImageElement = undefined;\n }\n}\n\nexport function dragStart<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n e: { dataTransfer: DataTransfer | null; clientY: number },\n block: Block<BSchema, I, S>,\n editor: BlockNoteEditor<BSchema, I, S>,\n) {\n if (!e.dataTransfer) {\n return;\n }\n\n const view = editor.prosemirrorView;\n if (!view) {\n return;\n }\n\n const posInfo = getNodeById(block.id, view.state.doc);\n if (!posInfo) {\n throw new Error(`Block with ID ${block.id} not found`);\n }\n const pos = posInfo.posBeforeNode;\n\n if (pos != null) {\n const selection = view.state.selection;\n const doc = view.state.doc;\n\n const { from, to } = blockPositionsFromSelection(selection, doc);\n\n const draggedBlockInSelection = from <= pos && pos < to;\n const multipleBlocksSelected =\n selection.$anchor.node() !== selection.$head.node() ||\n selection instanceof MultipleNodeSelection;\n\n if (draggedBlockInSelection && multipleBlocksSelected) {\n view.dispatch(\n view.state.tr.setSelection(MultipleNodeSelection.create(doc, from, to)),\n );\n setDragImage(view, from, to);\n } else {\n view.dispatch(\n view.state.tr.setSelection(NodeSelection.create(view.state.doc, pos)),\n );\n setDragImage(view, pos);\n }\n\n const selectedSlice = view.state.selection.content();\n const schema = editor.pmSchema;\n\n const clipboardHTML =\n view.serializeForClipboard(selectedSlice).dom.innerHTML;\n\n const externalHTMLExporter = createExternalHTMLExporter(schema, editor);\n\n const blocks = fragmentToBlocks(selectedSlice.content);\n const externalHTML = externalHTMLExporter.exportBlocks(blocks, {});\n\n const plainText = cleanHTMLToMarkdown(externalHTML);\n\n e.dataTransfer.clearData();\n e.dataTransfer.setData(\"blocknote/html\", clipboardHTML);\n e.dataTransfer.setData(\"text/html\", externalHTML);\n e.dataTransfer.setData(\"text/plain\", plainText);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setDragImage(dragImageElement!, 0, 0);\n }\n}\n","import { DOMParser, Slice } from \"@tiptap/pm/model\";\nimport {\n EditorState,\n Plugin,\n PluginKey,\n PluginView,\n TextSelection,\n} from \"@tiptap/pm/state\";\nimport { EditorView } from \"@tiptap/pm/view\";\n\nimport { Block } from \"../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { initializeESMDependencies } from \"../../util/esmDependencies.js\";\nimport { getDraggableBlockFromElement } from \"../getDraggableBlockFromElement.js\";\nimport { dragStart, unsetDragImage } from \"./dragging.js\";\n\nexport type SideMenuState<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = UiElementPosition & {\n // The block that the side menu is attached to.\n block: Block<BSchema, I, S>;\n};\n\nconst PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP = 0.1;\n\nfunction getBlockFromCoords(\n view: EditorView,\n coords: { left: number; top: number },\n sideMenuDetection: \"viewport\" | \"editor\",\n adjustForColumns = true,\n) {\n const elements = view.root.elementsFromPoint(\n // bit hacky - offset x position to right to account for the width of sidemenu itself\n coords.left + (sideMenuDetection === \"editor\" ? 50 : 0),\n coords.top,\n );\n\n for (const element of elements) {\n if (!view.dom.contains(element)) {\n // probably a ui overlay like formatting toolbar etc\n continue;\n }\n if (adjustForColumns) {\n const column = element.closest(\"[data-node-type=columnList]\");\n if (column) {\n return getBlockFromCoords(\n view,\n {\n left: coords.left + 50, // bit hacky, but if we're inside a column, offset x position to right to account for the width of sidemenu itself\n top: coords.top,\n },\n sideMenuDetection,\n false,\n );\n }\n }\n return getDraggableBlockFromElement(element, view);\n }\n return undefined;\n}\n\nfunction getBlockFromMousePos(\n mousePos: {\n x: number;\n y: number;\n },\n view: EditorView,\n sideMenuDetection: \"viewport\" | \"editor\",\n): { node: HTMLElement; id: string } | undefined {\n // Editor itself may have padding or other styling which affects\n // size/position, so we get the boundingRect of the first child (i.e. the\n // blockGroup that wraps all blocks in the editor) for more accurate side\n // menu placement.\n if (!view.dom.firstChild) {\n return;\n }\n\n const editorBoundingBox = (\n view.dom.firstChild as HTMLElement\n ).getBoundingClientRect();\n\n // this.horizontalPosAnchor = editorBoundingBox.x;\n\n // Gets block at mouse cursor's position.\n const coords = {\n left: mousePos.x,\n top: mousePos.y,\n };\n\n const mouseLeftOfEditor = coords.left < editorBoundingBox.left;\n const mouseRightOfEditor = coords.left > editorBoundingBox.right;\n\n // Clamps the x position to the editor's bounding box.\n if (sideMenuDetection === \"viewport\") {\n if (mouseLeftOfEditor) {\n coords.left = editorBoundingBox.left + 10;\n }\n\n if (mouseRightOfEditor) {\n coords.left = editorBoundingBox.right - 10;\n }\n }\n\n let block = getBlockFromCoords(view, coords, sideMenuDetection);\n\n if (!mouseRightOfEditor && block) {\n // note: this case is not necessary when we're on the right side of the editor\n\n /* Now, because blocks can be nested\n | BlockA |\n x | BlockB y|\n\n hovering over position x (the \"margin of block B\") will return block A instead of block B.\n to fix this, we get the block from the right side of block A (position y, which will fall in BlockB correctly)\n */\n\n const rect = block.node.getBoundingClientRect();\n coords.left = rect.right - 10;\n block = getBlockFromCoords(view, coords, \"viewport\", false);\n }\n\n return block;\n}\n\n/**\n * With the sidemenu plugin we can position a menu next to a hovered block.\n */\nexport class SideMenuView<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> implements PluginView\n{\n public state?: SideMenuState<BSchema, I, S>;\n public readonly emitUpdate: (state: SideMenuState<BSchema, I, S>) => void;\n\n private mousePos: { x: number; y: number } | undefined;\n\n private hoveredBlock: HTMLElement | undefined;\n\n public menuFrozen = false;\n\n public isDragOrigin = false;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n private readonly sideMenuDetection: \"viewport\" | \"editor\",\n private readonly pmView: EditorView,\n emitUpdate: (state: SideMenuState<BSchema, I, S>) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized side menu\");\n }\n\n emitUpdate(this.state);\n };\n\n this.pmView.root.addEventListener(\n \"dragstart\",\n this.onDragStart as EventListener,\n );\n this.pmView.root.addEventListener(\n \"dragover\",\n this.onDragOver as EventListener,\n );\n this.pmView.root.addEventListener(\n \"drop\",\n this.onDrop as EventListener,\n true,\n );\n this.pmView.root.addEventListener(\n \"dragend\",\n this.onDragEnd as EventListener,\n true,\n );\n initializeESMDependencies();\n\n // Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.\n this.pmView.root.addEventListener(\n \"mousemove\",\n this.onMouseMove as EventListener,\n true,\n );\n\n // Hides and unfreezes the menu whenever the user presses a key.\n this.pmView.root.addEventListener(\n \"keydown\",\n this.onKeyDown as EventListener,\n true,\n );\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n pmView.root.addEventListener(\"scroll\", this.onScroll, true);\n }\n\n updateState = (state: SideMenuState<BSchema, I, S>) => {\n this.state = state;\n this.emitUpdate(this.state);\n };\n\n updateStateFromMousePos = () => {\n if (this.menuFrozen || !this.mousePos) {\n return;\n }\n\n const block = getBlockFromMousePos(\n this.mousePos,\n this.pmView,\n this.sideMenuDetection,\n );\n\n // Closes the menu if the mouse cursor is beyond the editor vertically.\n if (!block || !this.editor.isEditable) {\n if (this.state?.show) {\n this.state.show = false;\n this.updateState(this.state);\n }\n\n return;\n }\n\n // Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.\n if (\n this.state?.show &&\n this.hoveredBlock?.hasAttribute(\"data-id\") &&\n this.hoveredBlock?.getAttribute(\"data-id\") === block.id\n ) {\n return;\n }\n\n this.hoveredBlock = block.node;\n\n // Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.\n // TODO: needed?\n const blockContent = block.node.firstChild as HTMLElement;\n\n if (!blockContent) {\n return;\n }\n\n // TODO: needed?\n\n // Shows or updates elements.\n if (this.editor.isEditable) {\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n const column = block.node.closest(\"[data-node-type=column]\");\n this.updateState({\n show: true,\n referencePos: new DOMRect(\n column\n ? // We take the first child as column elements have some default\n // padding. This is a little weird since this child element will\n // be the first block, but since it's always non-nested and we\n // only take the x coordinate, it's ok.\n column.firstElementChild!.getBoundingClientRect().x\n : (\n this.pmView.dom.firstChild as HTMLElement\n ).getBoundingClientRect().x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height,\n ),\n block: this.editor.getBlock(\n this.hoveredBlock!.getAttribute(\"data-id\")!,\n )!,\n });\n }\n };\n\n onDrop = (event: DragEvent) => {\n // Content from outside a BlockNote editor is being dropped - just let\n // ProseMirror's default behaviour handle it.\n if (this.pmView.dragging === null) {\n return;\n }\n\n this.editor._tiptapEditor.commands.blur();\n\n // Finds the BlockNote editor element that the drop event occurred in (if\n // any).\n const parentEditorElement =\n event.target instanceof Node\n ? (event.target instanceof HTMLElement\n ? event.target\n : event.target.parentElement\n )?.closest(\".bn-editor\") || null\n : null;\n\n // Drop event occurred within an editor.\n if (parentEditorElement) {\n // When ProseMirror handles a drop event on the editor while\n // `view.dragging` is set, it deletes the selected content. However, if\n // a block from a different editor is being dropped, this causes some\n // issues that the code below fixes:\n if (!this.isDragOrigin && this.pmView.dom === parentEditorElement) {\n // Because the editor selection is unrelated to the dragged content, we\n // don't want PM to delete its content. Therefore, we collapse the\n // selection.\n this.pmView.dispatch(\n this.pmView.state.tr.setSelection(\n TextSelection.create(\n this.pmView.state.tr.doc,\n this.pmView.state.tr.selection.to,\n ),\n ),\n );\n } else if (this.isDragOrigin && this.pmView.dom !== parentEditorElement) {\n // Because the editor from which the block originates doesn't get a drop\n // event on it, PM doesn't delete its selected content. Therefore, we\n // need to do so manually.\n //\n // Note: Deleting the selected content from the editor from which the\n // block originates, may change its height. This can cause the position of\n // the editor in which the block is being dropping to shift, before it\n // can handle the drop event. That in turn can cause the drop to happen\n // somewhere other than the user intended. To get around this, we delay\n // deleting the selected content until all editors have had the chance to\n // handle the event.\n setTimeout(\n () => this.pmView.dispatch(this.pmView.state.tr.deleteSelection()),\n 0,\n );\n }\n }\n\n if (\n this.sideMenuDetection === \"editor\" ||\n (event as any).synthetic ||\n !event.dataTransfer?.types.includes(\"blocknote/html\")\n ) {\n return;\n }\n\n const pos = this.pmView.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n if (!pos || pos.inside === -1) {\n /**\n * When `this.sideMenuSelection === \"viewport\"`, if the event is outside the\n * editor contents, we dispatch a fake event, so that we can still drop the\n * content when dragging / dropping to the side of the editor\n */\n const evt = this.createSyntheticEvent(event);\n // console.log(\"dispatch fake drop\");\n this.pmView.dom.dispatchEvent(evt);\n }\n };\n\n onDragEnd = () => {\n // When the user starts dragging a block, `view.dragging` is set on all\n // BlockNote editors. However, when the drag ends, only the editor that the\n // drag originated in automatically clears `view.dragging`. Therefore, we\n // have to manually clear it on all editors.\n this.pmView.dragging = null;\n };\n\n /**\n * If a block is being dragged, ProseMirror usually gets the context of what's\n * being dragged from `view.dragging`, which is automatically set when a\n * `dragstart` event fires in the editor. However, if the user tries to drag\n * and drop blocks between multiple editors, only the one in which the drag\n * began has that context, so we need to set it on the others manually. This\n * ensures that PM always drops the blocks in between other blocks, and not\n * inside them.\n *\n * After the `dragstart` event fires on the drag handle, it sets\n * `blocknote/html` data on the clipboard. This handler fires right after,\n * parsing the `blocknote/html` data into nodes and setting them on\n * `view.dragging`.\n *\n * Note: Setting `view.dragging` on `dragover` would be better as the user\n * could then drag between editors in different windows, but you can only\n * access `dataTransfer` contents on `dragstart` and `drop` events.\n */\n onDragStart = (event: DragEvent) => {\n const html = event.dataTransfer?.getData(\"blocknote/html\");\n if (!html) {\n return;\n }\n\n if (this.pmView.dragging) {\n throw new Error(\"New drag was started while an existing drag is ongoing\");\n }\n\n const element = document.createElement(\"div\");\n element.innerHTML = html;\n\n const parser = DOMParser.fromSchema(this.pmView.state.schema);\n const node = parser.parse(element, {\n topNode: this.pmView.state.schema.nodes[\"blockGroup\"].create(),\n });\n\n this.pmView.dragging = {\n slice: new Slice(node.content, 0, 0),\n move: true,\n };\n };\n\n /**\n * If the event is outside the editor contents,\n * we dispatch a fake event, so that we can still drop the content\n * when dragging / dropping to the side of the editor\n */\n onDragOver = (event: DragEvent) => {\n if (\n this.sideMenuDetection === \"editor\" ||\n (event as any).synthetic ||\n !event.dataTransfer?.types.includes(\"blocknote/html\")\n ) {\n return;\n }\n\n const pos = this.pmView.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n if (!pos || (pos.inside === -1 && this.pmView.dom.firstChild)) {\n const evt = this.createSyntheticEvent(event);\n // console.log(\"dispatch fake dragover\");\n this.pmView.dom.dispatchEvent(evt);\n }\n };\n\n onKeyDown = (_event: KeyboardEvent) => {\n if (this.state?.show && this.editor.isFocused()) {\n // Typing in editor should hide side menu\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n };\n\n onMouseMove = (event: MouseEvent) => {\n if (this.menuFrozen) {\n return;\n }\n\n this.mousePos = { x: event.clientX, y: event.clientY };\n\n // We want the full area of the editor to check if the cursor is hovering\n // above it though.\n const editorOuterBoundingBox = this.pmView.dom.getBoundingClientRect();\n const cursorWithinEditor =\n this.mousePos.x > editorOuterBoundingBox.left &&\n this.mousePos.x < editorOuterBoundingBox.right &&\n this.mousePos.y > editorOuterBoundingBox.top &&\n this.mousePos.y < editorOuterBoundingBox.bottom;\n\n // TODO: remove parentElement, but then we need to remove padding from boundingbox or find a different solution\n const editorWrapper = this.pmView.dom!.parentElement!;\n\n // Doesn't update if the mouse hovers an element that's over the editor but\n // isn't a part of it or the side menu.\n if (\n // Cursor is within the editor area\n cursorWithinEditor &&\n // An element is hovered\n event &&\n event.target &&\n // Element is outside the editor\n !(\n editorWrapper === event.target ||\n editorWrapper.contains(event.target as HTMLElement)\n )\n ) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n\n return;\n }\n\n this.updateStateFromMousePos();\n };\n\n private createSyntheticEvent(event: DragEvent) {\n const evt = new Event(event.type, event) as any;\n const editorBoundingBox = (\n this.pmView.dom.firstChild as HTMLElement\n ).getBoundingClientRect();\n evt.clientX = event.clientX;\n evt.clientY = event.clientY;\n if (\n event.clientX < editorBoundingBox.left &&\n event.clientX >\n editorBoundingBox.left -\n editorBoundingBox.width *\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP\n ) {\n // when we're slightly left of the editor, we can drop to the side of the block\n evt.clientX =\n editorBoundingBox.left +\n (editorBoundingBox.width *\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP) /\n 2;\n } else if (\n event.clientX > editorBoundingBox.right &&\n event.clientX <\n editorBoundingBox.right +\n editorBoundingBox.width *\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP\n ) {\n // when we're slightly right of the editor, we can drop to the side of the block\n evt.clientX =\n editorBoundingBox.right -\n (editorBoundingBox.width *\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP) /\n 2;\n } else if (\n event.clientX < editorBoundingBox.left ||\n event.clientX > editorBoundingBox.right\n ) {\n // when mouse is outside of the editor on x axis, drop it somewhere safe (but not to the side of a block)\n evt.clientX =\n editorBoundingBox.left +\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP *\n editorBoundingBox.width *\n 2; // put it somewhere in first block, but safe outside of the PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP margin\n }\n\n evt.clientY = Math.min(\n Math.max(event.clientY, editorBoundingBox.top),\n editorBoundingBox.top + editorBoundingBox.height,\n );\n\n evt.dataTransfer = event.dataTransfer;\n evt.preventDefault = () => event.preventDefault();\n evt.synthetic = true; // prevent recursion\n return evt;\n }\n\n onScroll = () => {\n if (this.state?.show) {\n this.state.referencePos = this.hoveredBlock!.getBoundingClientRect();\n this.emitUpdate(this.state);\n }\n };\n\n // Needed in cases where the editor state updates without the mouse cursor\n // moving, as some state updates can require a side menu update. For example,\n // adding a button to the side menu which removes the block can cause the\n // block below to jump up into the place of the removed block when clicked,\n // allowing the user to click the button again without moving the cursor. This\n // would otherwise not update the side menu, and so clicking the button again\n // would attempt to remove the same block again, causing an error.\n update(_view: EditorView, prevState: EditorState) {\n const docChanged = !prevState.doc.eq(this.pmView.state.doc);\n if (docChanged && this.state?.show) {\n this.updateStateFromMousePos();\n }\n }\n\n destroy() {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n this.pmView.root.removeEventListener(\n \"mousemove\",\n this.onMouseMove as EventListener,\n true,\n );\n this.pmView.root.removeEventListener(\n \"dragstart\",\n this.onDragStart as EventListener,\n );\n this.pmView.root.removeEventListener(\n \"dragover\",\n this.onDragOver as EventListener,\n );\n this.pmView.root.removeEventListener(\n \"drop\",\n this.onDrop as EventListener,\n true,\n );\n this.pmView.root.removeEventListener(\n \"dragend\",\n this.onDragEnd as EventListener,\n true,\n );\n this.pmView.root.removeEventListener(\n \"keydown\",\n this.onKeyDown as EventListener,\n true,\n );\n this.pmView.root.removeEventListener(\"scroll\", this.onScroll, true);\n }\n}\n\nexport const sideMenuPluginKey = new PluginKey(\"SideMenuPlugin\");\n\nexport class SideMenuProsemirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"sideMenu\";\n }\n\n public view: SideMenuView<BSchema, I, S> | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n sideMenuDetection: \"viewport\" | \"editor\",\n ) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: sideMenuPluginKey,\n view: (editorView) => {\n this.view = new SideMenuView(\n editor,\n sideMenuDetection,\n editorView,\n (state) => {\n this.emit(\"update\", state);\n },\n );\n return this.view;\n },\n }),\n );\n }\n\n public onUpdate(callback: (state: SideMenuState<BSchema, I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragStart = (\n event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n },\n block: Block<BSchema, I, S>,\n ) => {\n if (this.view) {\n this.view.isDragOrigin = true;\n }\n\n dragStart(event, block, this.editor);\n };\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragEnd = () => {\n if (this.editor.prosemirrorView) {\n unsetDragImage(this.editor.prosemirrorView.root);\n }\n\n if (this.view) {\n this.view.isDragOrigin = false;\n }\n };\n /**\n * Freezes the side menu. When frozen, the side menu will stay\n * attached to the same block regardless of which block is hovered by the\n * mouse cursor.\n */\n freezeMenu = () => {\n this.view!.menuFrozen = true;\n this.view!.state!.show = true;\n this.view!.emitUpdate(this.view!.state!);\n };\n /**\n * Unfreezes the side menu. When frozen, the side menu will stay\n * attached to the same block regardless of which block is hovered by the\n * mouse cursor.\n */\n unfreezeMenu = () => {\n this.view!.menuFrozen = false;\n this.view!.state!.show = false;\n this.view!.emitUpdate(this.view!.state!);\n };\n}\n","import { Mapping } from \"prosemirror-transform\";\nimport {\n absolutePositionToRelativePosition,\n relativePositionToAbsolutePosition,\n ySyncPluginKey,\n} from \"y-prosemirror\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport * as Y from \"yjs\";\nimport type { ProsemirrorBinding } from \"y-prosemirror\";\n\n/**\n * This is used to track a mapping for each editor. The mapping stores the mappings for each transaction since the first transaction that was tracked.\n */\nconst editorToMapping = new Map<BlockNoteEditor<any, any, any>, Mapping>();\n\n/**\n * This initializes a single mapping for an editor instance.\n */\nfunction getMapping(editor: BlockNoteEditor<any, any, any>) {\n if (editorToMapping.has(editor)) {\n // Mapping already initialized, so we don't need to do anything\n return editorToMapping.get(editor)!;\n }\n const mapping = new Mapping();\n editor._tiptapEditor.on(\"transaction\", ({ transaction }) => {\n mapping.appendMapping(transaction.mapping);\n });\n editor._tiptapEditor.on(\"destroy\", () => {\n // Cleanup the mapping when the editor is destroyed\n editorToMapping.delete(editor);\n });\n\n // There only is one mapping per editor, so we can just set it\n editorToMapping.set(editor, mapping);\n\n return mapping;\n}\n\n/**\n * This is used to keep track of positions of elements in the editor.\n * It is needed because y-prosemirror's sync plugin can disrupt normal prosemirror position mapping.\n *\n * It is specifically made to be able to be used whether the editor is being used in a collaboratively, or single user, providing the same API.\n *\n * @param editor The editor to track the position of.\n * @param position The position to track.\n * @param side The side of the position to track. \"left\" is the default. \"right\" would move with the change if the change is in the right direction.\n * @returns A function that returns the position of the element.\n */\nexport function trackPosition(\n /**\n * The editor to track the position of.\n */\n editor: BlockNoteEditor<any, any, any>,\n /**\n * The position to track.\n */\n position: number,\n /**\n * This is the side of the position to track. \"left\" is the default. \"right\" would move with the change if the change is in the right direction.\n */\n side: \"left\" | \"right\" = \"left\",\n): () => number {\n const ySyncPluginState = ySyncPluginKey.getState(\n editor._tiptapEditor.state,\n ) as {\n doc: Y.Doc;\n binding: ProsemirrorBinding;\n };\n\n if (!ySyncPluginState) {\n // No y-prosemirror sync plugin, so we need to track the mapping manually\n // This will initialize the mapping for this editor, if needed\n const mapping = getMapping(editor);\n\n // This is the start point of tracking the mapping\n const trackedMapLength = mapping.maps.length;\n\n return () => {\n const pos = mapping\n // Only read the history of the mapping that we care about\n .slice(trackedMapLength)\n .map(position, side === \"left\" ? -1 : 1);\n\n return pos;\n };\n }\n\n const relativePosition = absolutePositionToRelativePosition(\n // Track the position after the position if we are on the right side\n position + (side === \"right\" ? 1 : 0),\n ySyncPluginState.binding.type,\n ySyncPluginState.binding.mapping,\n );\n\n return () => {\n const curYSyncPluginState = ySyncPluginKey.getState(\n editor._tiptapEditor.state,\n ) as typeof ySyncPluginState;\n const pos = relativePositionToAbsolutePosition(\n curYSyncPluginState.doc,\n curYSyncPluginState.binding.type,\n relativePosition,\n curYSyncPluginState.binding.mapping,\n );\n\n // This can happen if the element is garbage collected\n if (pos === null) {\n throw new Error(\"Position not found, cannot track positions\");\n }\n\n return pos + (side === \"right\" ? -1 : 0);\n };\n}\n","import { findParentNode } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\n\nimport { trackPosition } from \"../../api/positionMapping.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\n\nconst findBlock = findParentNode((node) => node.type.name === \"blockContainer\");\n\nexport type SuggestionMenuState = UiElementPosition & {\n query: string;\n ignoreQueryLength?: boolean;\n};\n\nclass SuggestionMenuView<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> {\n public state?: SuggestionMenuState;\n public emitUpdate: (triggerCharacter: string) => void;\n private rootEl?: Document | ShadowRoot;\n pluginState: SuggestionPluginState;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n emitUpdate: (menuName: string, state: SuggestionMenuState) => void,\n ) {\n this.pluginState = undefined;\n\n this.emitUpdate = (menuName: string) => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized suggestions menu\");\n }\n\n emitUpdate(menuName, {\n ...this.state,\n ignoreQueryLength: this.pluginState?.ignoreQueryLength,\n });\n };\n\n this.rootEl = this.editor.prosemirrorView?.root;\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n this.rootEl?.addEventListener(\"scroll\", this.handleScroll, true);\n }\n\n handleScroll = () => {\n if (this.state?.show) {\n const decorationNode = this.rootEl?.querySelector(\n `[data-decoration-id=\"${this.pluginState!.decorationId}\"]`,\n );\n if (!decorationNode) {\n return;\n }\n this.state.referencePos = decorationNode.getBoundingClientRect();\n this.emitUpdate(this.pluginState!.triggerCharacter!);\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const prev: SuggestionPluginState =\n suggestionMenuPluginKey.getState(prevState);\n const next: SuggestionPluginState = suggestionMenuPluginKey.getState(\n view.state,\n );\n\n // See how the state changed\n const started = prev === undefined && next !== undefined;\n const stopped = prev !== undefined && next === undefined;\n const changed = prev !== undefined && next !== undefined;\n\n // Cancel when suggestion isn't active\n if (!started && !changed && !stopped) {\n return;\n }\n\n this.pluginState = stopped ? prev : next;\n\n if (stopped || !this.editor.isEditable) {\n if (this.state) {\n this.state.show = false;\n }\n this.emitUpdate(this.pluginState!.triggerCharacter);\n\n return;\n }\n\n const decorationNode = this.rootEl?.querySelector(\n `[data-decoration-id=\"${this.pluginState!.decorationId}\"]`,\n );\n\n if (this.editor.isEditable && decorationNode) {\n this.state = {\n show: true,\n referencePos: decorationNode.getBoundingClientRect(),\n query: this.pluginState!.query,\n };\n\n this.emitUpdate(this.pluginState!.triggerCharacter!);\n }\n }\n\n destroy() {\n this.rootEl?.removeEventListener(\"scroll\", this.handleScroll, true);\n }\n\n closeMenu = () => {\n this.editor.transact((tr) => tr.setMeta(suggestionMenuPluginKey, null));\n };\n\n clearQuery = () => {\n if (this.pluginState === undefined) {\n return;\n }\n\n this.editor._tiptapEditor\n .chain()\n .focus()\n // TODO need to make an API for this\n .deleteRange({\n from:\n this.pluginState.queryStartPos() -\n (this.pluginState.deleteTriggerCharacter\n ? this.pluginState.triggerCharacter!.length\n : 0),\n to: this.editor.transact((tr) => tr.selection.from),\n })\n .run();\n };\n}\n\ntype SuggestionPluginState =\n | {\n triggerCharacter: string;\n deleteTriggerCharacter: boolean;\n queryStartPos: () => number;\n query: string;\n decorationId: string;\n ignoreQueryLength?: boolean;\n }\n | undefined;\n\nconst suggestionMenuPluginKey = new PluginKey(\"SuggestionMenuPlugin\");\n\n/**\n * A ProseMirror plugin for suggestions, designed to make '/'-commands possible as well as mentions.\n *\n * This is basically a simplified version of TipTap's [Suggestions](https://github.com/ueberdosis/tiptap/tree/db92a9b313c5993b723c85cd30256f1d4a0b65e1/packages/suggestion) plugin.\n *\n * This version is adapted from the aforementioned version in the following ways:\n * - This version supports generic items instead of only strings (to allow for more advanced filtering for example)\n * - This version hides some unnecessary complexity from the user of the plugin.\n * - This version handles key events differently\n */\nexport class SuggestionMenuProseMirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"suggestionMenu\";\n }\n\n private view: SuggestionMenuView<BSchema, I, S> | undefined;\n private triggerCharacters: string[] = [];\n\n constructor(editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n const triggerCharacters = this.triggerCharacters;\n this.addProsemirrorPlugin(\n new Plugin({\n key: suggestionMenuPluginKey,\n\n view: () => {\n this.view = new SuggestionMenuView<BSchema, I, S>(\n editor,\n (triggerCharacter, state) => {\n this.emit(`update ${triggerCharacter}`, state);\n },\n );\n return this.view;\n },\n\n state: {\n // Initialize the plugin's internal state.\n init(): SuggestionPluginState {\n return undefined;\n },\n\n // Apply changes to the plugin state from an editor transaction.\n apply: (\n transaction,\n prev,\n _oldState,\n newState,\n ): SuggestionPluginState => {\n // TODO: More clearly define which transactions should be ignored.\n if (transaction.getMeta(\"orderedListIndexing\") !== undefined) {\n return prev;\n }\n\n // Ignore transactions in code blocks.\n if (transaction.selection.$from.parent.type.spec.code) {\n return prev;\n }\n\n // Either contains the trigger character if the menu should be shown,\n // or null if it should be hidden.\n const suggestionPluginTransactionMeta: {\n triggerCharacter: string;\n deleteTriggerCharacter?: boolean;\n ignoreQueryLength?: boolean;\n } | null = transaction.getMeta(suggestionMenuPluginKey);\n\n if (\n typeof suggestionPluginTransactionMeta === \"object\" &&\n suggestionPluginTransactionMeta !== null\n ) {\n if (prev) {\n // Close the previous menu if it exists\n this.closeMenu();\n }\n const trackedPosition = trackPosition(\n editor,\n newState.selection.from -\n // Need to account for the trigger char that was inserted, so we offset the position by the length of the trigger character.\n suggestionPluginTransactionMeta.triggerCharacter.length,\n );\n return {\n triggerCharacter:\n suggestionPluginTransactionMeta.triggerCharacter,\n deleteTriggerCharacter:\n suggestionPluginTransactionMeta.deleteTriggerCharacter !==\n false,\n // When reading the queryStartPos, we offset the result by the length of the trigger character, to make it easy on the caller\n queryStartPos: () =>\n trackedPosition() +\n suggestionPluginTransactionMeta.triggerCharacter.length,\n query: \"\",\n decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,\n ignoreQueryLength:\n suggestionPluginTransactionMeta?.ignoreQueryLength,\n };\n }\n\n // Checks if the menu is hidden, in which case it doesn't need to be hidden or updated.\n if (prev === undefined) {\n return prev;\n }\n\n // Checks if the menu should be hidden.\n if (\n // Highlighting text should hide the menu.\n newState.selection.from !== newState.selection.to ||\n // Transactions with plugin metadata should hide the menu.\n suggestionPluginTransactionMeta === null ||\n // Certain mouse events should hide the menu.\n // TODO: Change to global mousedown listener.\n transaction.getMeta(\"focus\") ||\n transaction.getMeta(\"blur\") ||\n transaction.getMeta(\"pointer\") ||\n // Moving the caret before the character which triggered the menu should hide it.\n (prev.triggerCharacter !== undefined &&\n newState.selection.from < prev.queryStartPos()) ||\n // Moving the caret to a new block should hide the menu.\n !newState.selection.$from.sameParent(\n newState.doc.resolve(prev.queryStartPos()),\n )\n ) {\n return undefined;\n }\n\n const next = { ...prev };\n\n // Updates the current query.\n next.query = newState.doc.textBetween(\n prev.queryStartPos(),\n newState.selection.from,\n );\n\n return next;\n },\n },\n\n props: {\n handleTextInput(view, _from, _to, text) {\n if (triggerCharacters.includes(text)) {\n view.dispatch(view.state.tr.insertText(text));\n view.dispatch(\n view.state.tr\n .setMeta(suggestionMenuPluginKey, {\n triggerCharacter: text,\n })\n .scrollIntoView(),\n );\n\n return true;\n }\n return false;\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const suggestionPluginState: SuggestionPluginState = (\n this as Plugin\n ).getState(state);\n\n if (suggestionPluginState === undefined) {\n return null;\n }\n\n // If the menu was opened programmatically by another extension, it may not use a trigger character. In this\n // case, the decoration is set on the whole block instead, as the decoration range would otherwise be empty.\n if (!suggestionPluginState.deleteTriggerCharacter) {\n const blockNode = findBlock(state.selection);\n if (blockNode) {\n return DecorationSet.create(state.doc, [\n Decoration.node(\n blockNode.pos,\n blockNode.pos + blockNode.node.nodeSize,\n {\n nodeName: \"span\",\n class: \"bn-suggestion-decorator\",\n \"data-decoration-id\": suggestionPluginState.decorationId,\n },\n ),\n ]);\n }\n }\n // Creates an inline decoration around the trigger character.\n return DecorationSet.create(state.doc, [\n Decoration.inline(\n suggestionPluginState.queryStartPos() -\n suggestionPluginState.triggerCharacter!.length,\n suggestionPluginState.queryStartPos(),\n {\n nodeName: \"span\",\n class: \"bn-suggestion-decorator\",\n \"data-decoration-id\": suggestionPluginState.decorationId,\n },\n ),\n ]);\n },\n },\n }),\n );\n }\n\n public onUpdate(\n triggerCharacter: string,\n callback: (state: SuggestionMenuState) => void,\n ) {\n if (!this.triggerCharacters.includes(triggerCharacter)) {\n this.addTriggerCharacter(triggerCharacter);\n }\n // TODO: be able to remove the triggerCharacter\n return this.on(`update ${triggerCharacter}`, callback);\n }\n\n addTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters.push(triggerCharacter);\n };\n\n // TODO: Should this be called automatically when listeners are removed?\n removeTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters = this.triggerCharacters.filter(\n (c) => c !== triggerCharacter,\n );\n };\n\n closeMenu = () => this.view!.closeMenu();\n\n clearQuery = () => this.view!.clearQuery();\n\n public get shown() {\n return this.view?.state?.show || false;\n }\n}\n\nexport function createSuggestionMenu<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(editor: BlockNoteEditor<BSchema, I, S>, triggerCharacter: string) {\n editor.suggestionMenus.addTriggerCharacter(triggerCharacter);\n}\n","import { Mark } from \"@tiptap/core\";\nimport { MarkSpec } from \"prosemirror-model\";\n\n// This copies the marks from @handlewithcare/prosemirror-suggest-changes,\n// but uses the Tiptap Mark API instead so we can use them in BlockNote\n\n// The ideal solution would be to not depend on tiptap nodes / marks, but be able to use prosemirror nodes / marks directly\n// this way we could directly use the exported marks from @handlewithcare/prosemirror-suggest-changes\nexport const SuggestionAddMark = Mark.create({\n name: \"insertion\",\n inclusive: false,\n excludes: \"deletion modification insertion\",\n addAttributes() {\n return {\n id: { default: null, validate: \"number\" }, // note: validate is supported in prosemirror but not in tiptap, so this doesn't actually work (considered not critical)\n };\n },\n extendMarkSchema(extension) {\n if (extension.name !== \"insertion\") {\n return {};\n }\n return {\n blocknoteIgnore: true,\n inclusive: false,\n\n toDOM(mark, inline) {\n return [\n \"ins\",\n {\n \"data-id\": String(mark.attrs[\"id\"]),\n \"data-inline\": String(inline),\n ...(!inline && { style: \"display: contents\" }), // changed to \"contents\" to make this work for table rows\n },\n 0,\n ];\n },\n parseDOM: [\n {\n tag: \"ins\",\n getAttrs(node) {\n if (!node.dataset[\"id\"]) {\n return false;\n }\n return {\n id: parseInt(node.dataset[\"id\"], 10),\n };\n },\n },\n ],\n } satisfies MarkSpec;\n },\n});\n\nexport const SuggestionDeleteMark = Mark.create({\n name: \"deletion\",\n inclusive: false,\n excludes: \"insertion modification deletion\",\n addAttributes() {\n return {\n id: { default: null, validate: \"number\" }, // note: validate is supported in prosemirror but not in tiptap\n };\n },\n extendMarkSchema(extension) {\n if (extension.name !== \"deletion\") {\n return {};\n }\n return {\n blocknoteIgnore: true,\n inclusive: false,\n\n // attrs: {\n // id: { validate: \"number\" },\n // },\n toDOM(mark, inline) {\n return [\n \"del\",\n {\n \"data-id\": String(mark.attrs[\"id\"]),\n \"data-inline\": String(inline),\n ...(!inline && { style: \"display: contents\" }), // changed to \"contents\" to make this work for table rows\n },\n 0,\n ];\n },\n parseDOM: [\n {\n tag: \"del\",\n getAttrs(node) {\n if (!node.dataset[\"id\"]) {\n return false;\n }\n return {\n id: parseInt(node.dataset[\"id\"], 10),\n };\n },\n },\n ],\n } satisfies MarkSpec;\n },\n});\n\nexport const SuggestionModificationMark = Mark.create({\n name: \"modification\",\n inclusive: false,\n excludes: \"deletion insertion\",\n addAttributes() {\n // note: validate is supported in prosemirror but not in tiptap\n return {\n id: { default: null, validate: \"number\" },\n type: { validate: \"string\" },\n attrName: { default: null, validate: \"string|null\" },\n previousValue: { default: null },\n newValue: { default: null },\n };\n },\n extendMarkSchema(extension) {\n if (extension.name !== \"modification\") {\n return {};\n }\n return {\n blocknoteIgnore: true,\n inclusive: false,\n // attrs: {\n // id: { validate: \"number\" },\n // type: { validate: \"string\" },\n // attrName: { default: null, validate: \"string|null\" },\n // previousValue: { default: null },\n // newValue: { default: null },\n // },\n toDOM(mark, inline) {\n return [\n inline ? \"span\" : \"div\",\n {\n \"data-type\": \"modification\",\n \"data-id\": String(mark.attrs[\"id\"]),\n \"data-mod-type\": mark.attrs[\"type\"] as string,\n \"data-mod-prev-val\": JSON.stringify(mark.attrs[\"previousValue\"]),\n // TODO: Try to serialize marks with toJSON?\n \"data-mod-new-val\": JSON.stringify(mark.attrs[\"newValue\"]),\n },\n 0,\n ];\n },\n parseDOM: [\n {\n tag: \"span[data-type='modification']\",\n getAttrs(node) {\n if (!node.dataset[\"id\"]) {\n return false;\n }\n return {\n id: parseInt(node.dataset[\"id\"], 10),\n type: node.dataset[\"modType\"],\n previousValue: node.dataset[\"modPrevVal\"],\n newValue: node.dataset[\"modNewVal\"],\n };\n },\n },\n {\n tag: \"div[data-type='modification']\",\n getAttrs(node) {\n if (!node.dataset[\"id\"]) {\n return false;\n }\n return {\n id: parseInt(node.dataset[\"id\"], 10),\n type: node.dataset[\"modType\"],\n previousValue: node.dataset[\"modPrevVal\"],\n };\n },\n },\n ],\n } satisfies MarkSpec;\n },\n});\n","import { EditorState, Plugin, PluginKey, PluginView } from \"prosemirror-state\";\nimport {\n CellSelection,\n addColumnAfter,\n addColumnBefore,\n addRowAfter,\n addRowBefore,\n deleteColumn,\n deleteRow,\n mergeCells,\n splitCell,\n} from \"prosemirror-tables\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\nimport {\n RelativeCellIndices,\n addRowsOrColumns,\n areInSameColumn,\n canColumnBeDraggedInto,\n canRowBeDraggedInto,\n cropEmptyRowsOrColumns,\n getCellsAtColumnHandle,\n getCellsAtRowHandle,\n getDimensionsOfTable,\n moveColumn,\n moveRow,\n} from \"../../api/blockManipulation/tables/tables.js\";\nimport { nodeToBlock } from \"../../api/nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../api/nodeUtil.js\";\nimport {\n checkBlockIsDefaultType,\n isTableCellSelection,\n} from \"../../blocks/defaultBlockTypeGuards.js\";\nimport { DefaultBlockSchema } from \"../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport {\n BlockFromConfigNoChildren,\n BlockSchemaWithBlock,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { getDraggableBlockFromElement } from \"../getDraggableBlockFromElement.js\";\n\nlet dragImageElement: HTMLElement | undefined;\n\n// TODO consider switching this to jotai, it is a bit messy and noisy\nexport type TableHandlesState<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = {\n show: boolean;\n showAddOrRemoveRowsButton: boolean;\n showAddOrRemoveColumnsButton: boolean;\n referencePosCell: DOMRect | undefined;\n referencePosTable: DOMRect;\n\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], I, S>;\n colIndex: number | undefined;\n rowIndex: number | undefined;\n\n draggingState:\n | {\n draggedCellOrientation: \"row\" | \"col\";\n originalIndex: number;\n mousePos: number;\n }\n | undefined;\n\n widgetContainer: HTMLElement | undefined;\n};\n\nfunction setHiddenDragImage(rootEl: Document | ShadowRoot) {\n if (dragImageElement) {\n return;\n }\n\n dragImageElement = document.createElement(\"div\");\n dragImageElement.innerHTML = \"_\";\n dragImageElement.style.opacity = \"0\";\n dragImageElement.style.height = \"1px\";\n dragImageElement.style.width = \"1px\";\n if (rootEl instanceof Document) {\n rootEl.body.appendChild(dragImageElement);\n } else {\n rootEl.appendChild(dragImageElement);\n }\n}\n\nfunction unsetHiddenDragImage(rootEl: Document | ShadowRoot) {\n if (dragImageElement) {\n if (rootEl instanceof Document) {\n rootEl.body.removeChild(dragImageElement);\n } else {\n rootEl.removeChild(dragImageElement);\n }\n dragImageElement = undefined;\n }\n}\n\nfunction getChildIndex(node: Element) {\n return Array.prototype.indexOf.call(node.parentElement!.childNodes, node);\n}\n\n// Finds the DOM element corresponding to the table cell that the target element\n// is currently in. If the target element is not in a table cell, returns null.\nfunction domCellAround(target: Element) {\n let currentTarget: Element | undefined = target;\n while (\n currentTarget &&\n currentTarget.nodeName !== \"TD\" &&\n currentTarget.nodeName !== \"TH\" &&\n !currentTarget.classList.contains(\"tableWrapper\")\n ) {\n if (currentTarget.classList.contains(\"ProseMirror\")) {\n return undefined;\n }\n const parent: ParentNode | null = currentTarget.parentNode;\n\n if (!parent || !(parent instanceof Element)) {\n return undefined;\n }\n currentTarget = parent;\n }\n\n return currentTarget.nodeName === \"TD\" || currentTarget.nodeName === \"TH\"\n ? {\n type: \"cell\",\n domNode: currentTarget,\n tbodyNode: currentTarget.closest(\"tbody\"),\n }\n : {\n type: \"wrapper\",\n domNode: currentTarget,\n tbodyNode: currentTarget.querySelector(\"tbody\"),\n };\n}\n\n// Hides elements in the DOMwith the provided class names.\nfunction hideElements(selector: string, rootEl: Document | ShadowRoot) {\n const elementsToHide = rootEl.querySelectorAll(selector);\n\n for (let i = 0; i < elementsToHide.length; i++) {\n (elementsToHide[i] as HTMLElement).style.visibility = \"hidden\";\n }\n}\n\nexport class TableHandlesView<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> implements PluginView\n{\n public state?: TableHandlesState<I, S>;\n public emitUpdate: () => void;\n\n public tableId: string | undefined;\n public tablePos: number | undefined;\n public tableElement: HTMLElement | undefined;\n\n public menuFrozen = false;\n\n public mouseState: \"up\" | \"down\" | \"selecting\" = \"up\";\n\n public prevWasEditable: boolean | null = null;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >,\n private readonly pmView: EditorView,\n emitUpdate: (state: TableHandlesState<I, S>) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized image toolbar\");\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousemove\", this.mouseMoveHandler);\n pmView.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n window.addEventListener(\"mouseup\", this.mouseUpHandler);\n\n pmView.root.addEventListener(\n \"dragover\",\n this.dragOverHandler as EventListener,\n );\n pmView.root.addEventListener(\n \"drop\",\n this.dropHandler as unknown as EventListener,\n );\n }\n\n viewMousedownHandler = () => {\n this.mouseState = \"down\";\n };\n\n mouseUpHandler = (event: MouseEvent) => {\n this.mouseState = \"up\";\n this.mouseMoveHandler(event);\n };\n\n mouseMoveHandler = (event: MouseEvent) => {\n if (this.menuFrozen) {\n return;\n }\n\n if (this.mouseState === \"selecting\") {\n return;\n }\n\n if (\n !(event.target instanceof Element) ||\n !this.pmView.dom.contains(event.target)\n ) {\n return;\n }\n\n const target = domCellAround(event.target);\n\n if (\n target?.type === \"cell\" &&\n this.mouseState === \"down\" &&\n !this.state?.draggingState\n ) {\n // hide draghandles when selecting text as they could be in the way of the user\n this.mouseState = \"selecting\";\n\n if (this.state?.show) {\n this.state.show = false;\n this.state.showAddOrRemoveRowsButton = false;\n this.state.showAddOrRemoveColumnsButton = false;\n this.emitUpdate();\n }\n return;\n }\n\n if (!target || !this.editor.isEditable) {\n if (this.state?.show) {\n this.state.show = false;\n this.state.showAddOrRemoveRowsButton = false;\n this.state.showAddOrRemoveColumnsButton = false;\n this.emitUpdate();\n }\n return;\n }\n\n if (!target.tbodyNode) {\n return;\n }\n\n const tableRect = target.tbodyNode.getBoundingClientRect();\n\n const blockEl = getDraggableBlockFromElement(target.domNode, this.pmView);\n if (!blockEl) {\n return;\n }\n this.tableElement = blockEl.node;\n\n let tableBlock:\n | BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], I, S>\n | undefined;\n\n const pmNodeInfo = this.editor.transact((tr) =>\n getNodeById(blockEl.id, tr.doc),\n );\n if (!pmNodeInfo) {\n throw new Error(`Block with ID ${blockEl.id} not found`);\n }\n\n const block = nodeToBlock(\n pmNodeInfo.node,\n this.editor.pmSchema,\n this.editor.schema.blockSchema,\n this.editor.schema.inlineContentSchema,\n this.editor.schema.styleSchema,\n );\n\n if (checkBlockIsDefaultType(\"table\", block, this.editor)) {\n this.tablePos = pmNodeInfo.posBeforeNode + 1;\n tableBlock = block;\n }\n\n if (!tableBlock) {\n return;\n }\n\n this.tableId = blockEl.id;\n const widgetContainer = target.domNode\n .closest(\".tableWrapper\")\n ?.querySelector(\".table-widgets-container\") as HTMLElement;\n\n if (target?.type === \"wrapper\") {\n // if we're just to the right or below the table, show the extend buttons\n // (this is a bit hacky. It would probably be cleaner to render the extend buttons in the Table NodeView instead)\n const belowTable =\n event.clientY >= tableRect.bottom - 1 && // -1 to account for fractions of pixels in \"bottom\"\n event.clientY < tableRect.bottom + 20;\n const toRightOfTable =\n event.clientX >= tableRect.right - 1 &&\n event.clientX < tableRect.right + 20;\n\n // without this check, we'd also hide draghandles when hovering over them\n const hideHandles =\n event.clientX > tableRect.right || event.clientY > tableRect.bottom;\n\n this.state = {\n ...this.state!,\n show: true,\n showAddOrRemoveRowsButton: belowTable,\n showAddOrRemoveColumnsButton: toRightOfTable,\n referencePosTable: tableRect,\n block: tableBlock,\n widgetContainer,\n colIndex: hideHandles ? undefined : this.state?.colIndex,\n rowIndex: hideHandles ? undefined : this.state?.rowIndex,\n referencePosCell: hideHandles\n ? undefined\n : this.state?.referencePosCell,\n };\n } else {\n const colIndex = getChildIndex(target.domNode);\n const rowIndex = getChildIndex(target.domNode.parentElement!);\n const cellRect = target.domNode.getBoundingClientRect();\n\n if (\n this.state !== undefined &&\n this.state.show &&\n this.tableId === blockEl.id &&\n this.state.rowIndex === rowIndex &&\n this.state.colIndex === colIndex\n ) {\n // no update needed\n return;\n }\n\n this.state = {\n show: true,\n showAddOrRemoveColumnsButton:\n colIndex === tableBlock.content.rows[0].cells.length - 1,\n showAddOrRemoveRowsButton:\n rowIndex === tableBlock.content.rows.length - 1,\n referencePosTable: tableRect,\n\n block: tableBlock,\n draggingState: undefined,\n referencePosCell: cellRect,\n colIndex: colIndex,\n rowIndex: rowIndex,\n\n widgetContainer,\n };\n }\n this.emitUpdate();\n\n return false;\n };\n\n dragOverHandler = (event: DragEvent) => {\n if (this.state?.draggingState === undefined) {\n return;\n }\n\n event.preventDefault();\n event.dataTransfer!.dropEffect = \"move\";\n\n hideElements(\n \".prosemirror-dropcursor-block, .prosemirror-dropcursor-inline\",\n this.pmView.root,\n );\n\n // The mouse cursor coordinates, bounded to the table's bounding box. The\n // bounding box is shrunk by 1px on each side to ensure that the bounded\n // coordinates are always inside a table cell.\n const boundedMouseCoords = {\n left: Math.min(\n Math.max(event.clientX, this.state.referencePosTable.left + 1),\n this.state.referencePosTable.right - 1,\n ),\n top: Math.min(\n Math.max(event.clientY, this.state.referencePosTable.top + 1),\n this.state.referencePosTable.bottom - 1,\n ),\n };\n\n // Gets the table cell element that the bounded mouse cursor coordinates lie\n // in.\n const tableCellElements = this.pmView.root\n .elementsFromPoint(boundedMouseCoords.left, boundedMouseCoords.top)\n .filter(\n (element) => element.tagName === \"TD\" || element.tagName === \"TH\",\n );\n if (tableCellElements.length === 0) {\n return;\n }\n const tableCellElement = tableCellElements[0];\n\n let emitStateUpdate = false;\n\n // Gets current row and column index.\n const rowIndex = getChildIndex(tableCellElement.parentElement!);\n const colIndex = getChildIndex(tableCellElement);\n\n // Checks if the drop cursor needs to be updated. This affects decorations\n // only so it doesn't trigger a state update.\n const oldIndex =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? this.state.rowIndex\n : this.state.colIndex;\n const newIndex =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? rowIndex\n : colIndex;\n const dispatchDecorationsTransaction = newIndex !== oldIndex;\n\n // Checks if either the hovered cell has changed and updates the row and\n // column index. Also updates the reference DOMRect.\n if (this.state.rowIndex !== rowIndex || this.state.colIndex !== colIndex) {\n this.state.rowIndex = rowIndex;\n this.state.colIndex = colIndex;\n\n this.state.referencePosCell = tableCellElement.getBoundingClientRect();\n\n emitStateUpdate = true;\n }\n\n // Checks if the mouse cursor position along the axis that the user is\n // dragging on has changed and updates it.\n const mousePos =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? boundedMouseCoords.top\n : boundedMouseCoords.left;\n if (this.state.draggingState.mousePos !== mousePos) {\n this.state.draggingState.mousePos = mousePos;\n\n emitStateUpdate = true;\n }\n\n // Emits a state update if any of the fields have changed.\n if (emitStateUpdate) {\n this.emitUpdate();\n }\n\n // Dispatches a dummy transaction to force a decorations update if\n // necessary.\n if (dispatchDecorationsTransaction) {\n this.editor.transact((tr) => tr.setMeta(tableHandlesPluginKey, true));\n }\n };\n\n dropHandler = (event: DragEvent) => {\n this.mouseState = \"up\";\n if (this.state === undefined || this.state.draggingState === undefined) {\n return false;\n }\n\n if (\n this.state.rowIndex === undefined ||\n this.state.colIndex === undefined\n ) {\n throw new Error(\n \"Attempted to drop table row or column, but no table block was hovered prior.\",\n );\n }\n\n event.preventDefault();\n\n const { draggingState, colIndex, rowIndex } = this.state;\n\n const columnWidths = this.state.block.content.columnWidths;\n\n if (draggingState.draggedCellOrientation === \"row\") {\n if (\n !canRowBeDraggedInto(\n this.state.block,\n draggingState.originalIndex,\n rowIndex,\n )\n ) {\n // If the target row is invalid, don't move the row\n return false;\n }\n const newTable = moveRow(\n this.state.block,\n draggingState.originalIndex,\n rowIndex,\n );\n this.editor.updateBlock(this.state.block, {\n type: \"table\",\n content: {\n ...this.state.block.content,\n rows: newTable as any,\n },\n });\n } else {\n if (\n !canColumnBeDraggedInto(\n this.state.block,\n draggingState.originalIndex,\n colIndex,\n )\n ) {\n // If the target column is invalid, don't move the column\n return false;\n }\n const newTable = moveColumn(\n this.state.block,\n draggingState.originalIndex,\n colIndex,\n );\n const [columnWidth] = columnWidths.splice(draggingState.originalIndex, 1);\n columnWidths.splice(colIndex, 0, columnWidth);\n this.editor.updateBlock(this.state.block, {\n type: \"table\",\n content: {\n ...this.state.block.content,\n columnWidths,\n rows: newTable as any,\n },\n });\n }\n\n // Have to reset text cursor position to the block as `updateBlock` moves\n // the existing selection out of the block.\n this.editor.setTextCursorPosition(this.state.block.id);\n\n return true;\n };\n // Updates drag handles when the table is modified or removed.\n update() {\n if (!this.state || !this.state.show) {\n return;\n }\n\n // Hide handles if the table block has been removed.\n this.state.block = this.editor.getBlock(this.state.block.id)!;\n if (\n !this.state.block ||\n this.state.block.type !== \"table\" ||\n // when collaborating, the table element might be replaced and out of date\n // because yjs replaces the element when for example you change the color via the side menu\n !this.tableElement?.isConnected\n ) {\n this.state.show = false;\n this.state.showAddOrRemoveRowsButton = false;\n this.state.showAddOrRemoveColumnsButton = false;\n this.emitUpdate();\n\n return;\n }\n\n const { height: rowCount, width: colCount } = getDimensionsOfTable(\n this.state.block,\n );\n\n if (\n this.state.rowIndex !== undefined &&\n this.state.colIndex !== undefined\n ) {\n // If rows or columns are deleted in the update, the hovered indices for\n // those may now be out of bounds. If this is the case, they are moved to\n // the new last row or column.\n if (this.state.rowIndex >= rowCount) {\n this.state.rowIndex = rowCount - 1;\n }\n if (this.state.colIndex >= colCount) {\n this.state.colIndex = colCount - 1;\n }\n }\n\n // Update bounding boxes.\n const tableBody = this.tableElement!.querySelector(\"tbody\");\n\n if (!tableBody) {\n throw new Error(\n \"Table block does not contain a 'tbody' HTML element. This should never happen.\",\n );\n }\n\n if (\n this.state.rowIndex !== undefined &&\n this.state.colIndex !== undefined\n ) {\n const row = tableBody.children[this.state.rowIndex];\n const cell = row.children[this.state.colIndex];\n if (cell) {\n this.state.referencePosCell = cell.getBoundingClientRect();\n } else {\n this.state.rowIndex = undefined;\n this.state.colIndex = undefined;\n }\n }\n this.state.referencePosTable = tableBody.getBoundingClientRect();\n\n this.emitUpdate();\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousemove\", this.mouseMoveHandler);\n window.removeEventListener(\"mouseup\", this.mouseUpHandler);\n this.pmView.dom.removeEventListener(\"mousedown\", this.viewMousedownHandler);\n this.pmView.root.removeEventListener(\n \"dragover\",\n this.dragOverHandler as EventListener,\n );\n this.pmView.root.removeEventListener(\n \"drop\",\n this.dropHandler as unknown as EventListener,\n );\n }\n}\n\nexport const tableHandlesPluginKey = new PluginKey(\"TableHandlesPlugin\");\n\nexport class TableHandlesProsemirrorPlugin<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"tableHandles\";\n }\n\n private view: TableHandlesView<I, S> | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >,\n ) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: tableHandlesPluginKey,\n view: (editorView) => {\n this.view = new TableHandlesView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n // We use decorations to render the drop cursor when dragging a table row\n // or column. The decorations are updated in the `dragOverHandler` method.\n props: {\n decorations: (state) => {\n if (\n this.view === undefined ||\n this.view.state === undefined ||\n this.view.state.draggingState === undefined ||\n this.view.tablePos === undefined\n ) {\n return;\n }\n\n const newIndex =\n this.view.state.draggingState.draggedCellOrientation === \"row\"\n ? this.view.state.rowIndex\n : this.view.state.colIndex;\n\n if (newIndex === undefined) {\n return;\n }\n\n const decorations: Decoration[] = [];\n const { block, draggingState } = this.view.state;\n const { originalIndex, draggedCellOrientation } = draggingState;\n\n // Return empty decorations if:\n // - Dragging to same position\n // - No block exists\n // - Row drag not allowed\n // - Column drag not allowed\n if (\n newIndex === originalIndex ||\n !block ||\n (draggedCellOrientation === \"row\" &&\n !canRowBeDraggedInto(block, originalIndex, newIndex)) ||\n (draggedCellOrientation === \"col\" &&\n !canColumnBeDraggedInto(block, originalIndex, newIndex))\n ) {\n return DecorationSet.create(state.doc, decorations);\n }\n\n // Gets the table to show the drop cursor in.\n const tableResolvedPos = state.doc.resolve(this.view.tablePos + 1);\n\n if (\n this.view.state.draggingState.draggedCellOrientation === \"row\"\n ) {\n const cellsInRow = getCellsAtRowHandle(\n this.view.state.block,\n newIndex,\n );\n\n cellsInRow.forEach(({ row, col }) => {\n // Gets each row in the table.\n const rowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(row) + 1,\n );\n\n // Gets the cell within the row.\n const cellResolvedPos = state.doc.resolve(\n rowResolvedPos.posAtIndex(col) + 1,\n );\n const cellNode = cellResolvedPos.node();\n // Creates a decoration at the start or end of each cell,\n // depending on whether the new index is before or after the\n // original index.\n const decorationPos =\n cellResolvedPos.pos +\n (newIndex > originalIndex ? cellNode.nodeSize - 2 : 0);\n decorations.push(\n // The widget is a small bar which spans the width of the cell.\n Decoration.widget(decorationPos, () => {\n const widget = document.createElement(\"div\");\n widget.className = \"bn-table-drop-cursor\";\n widget.style.left = \"0\";\n widget.style.right = \"0\";\n // This is only necessary because the drop indicator's height\n // is an even number of pixels, whereas the border between\n // table cells is an odd number of pixels. So this makes the\n // positioning slightly more consistent regardless of where\n // the row is being dropped.\n if (newIndex > originalIndex) {\n widget.style.bottom = \"-2px\";\n } else {\n widget.style.top = \"-3px\";\n }\n widget.style.height = \"4px\";\n\n return widget;\n }),\n );\n });\n } else {\n const cellsInColumn = getCellsAtColumnHandle(\n this.view.state.block,\n newIndex,\n );\n\n cellsInColumn.forEach(({ row, col }) => {\n // Gets each row in the table.\n const rowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(row) + 1,\n );\n\n // Gets the cell within the row.\n const cellResolvedPos = state.doc.resolve(\n rowResolvedPos.posAtIndex(col) + 1,\n );\n const cellNode = cellResolvedPos.node();\n\n // Creates a decoration at the start or end of each cell,\n // depending on whether the new index is before or after the\n // original index.\n const decorationPos =\n cellResolvedPos.pos +\n (newIndex > originalIndex ? cellNode.nodeSize - 2 : 0);\n\n decorations.push(\n // The widget is a small bar which spans the height of the cell.\n Decoration.widget(decorationPos, () => {\n const widget = document.createElement(\"div\");\n widget.className = \"bn-table-drop-cursor\";\n widget.style.top = \"0\";\n widget.style.bottom = \"0\";\n // This is only necessary because the drop indicator's width\n // is an even number of pixels, whereas the border between\n // table cells is an odd number of pixels. So this makes the\n // positioning slightly more consistent regardless of where\n // the column is being dropped.\n if (newIndex > originalIndex) {\n widget.style.right = \"-2px\";\n } else {\n widget.style.left = \"-3px\";\n }\n widget.style.width = \"4px\";\n\n return widget;\n }),\n );\n });\n }\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n }),\n );\n }\n\n public onUpdate(callback: (state: TableHandlesState<I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Callback that should be set on the `dragStart` event for whichever element\n * is used as the column drag handle.\n */\n colDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientX: number;\n }) => {\n if (\n this.view!.state === undefined ||\n this.view!.state.colIndex === undefined\n ) {\n throw new Error(\n \"Attempted to drag table column, but no table block was hovered prior.\",\n );\n }\n\n this.view!.state.draggingState = {\n draggedCellOrientation: \"col\",\n originalIndex: this.view!.state.colIndex,\n mousePos: event.clientX,\n };\n this.view!.emitUpdate();\n\n this.editor.transact((tr) =>\n tr.setMeta(tableHandlesPluginKey, {\n draggedCellOrientation:\n this.view!.state!.draggingState!.draggedCellOrientation,\n originalIndex: this.view!.state!.colIndex,\n newIndex: this.view!.state!.colIndex,\n tablePos: this.view!.tablePos,\n }),\n );\n\n if (!this.editor.prosemirrorView) {\n throw new Error(\"Editor view not initialized.\");\n }\n\n setHiddenDragImage(this.editor.prosemirrorView.root);\n event.dataTransfer!.setDragImage(dragImageElement!, 0, 0);\n event.dataTransfer!.effectAllowed = \"move\";\n };\n\n /**\n * Callback that should be set on the `dragStart` event for whichever element\n * is used as the row drag handle.\n */\n rowDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n }) => {\n if (\n this.view!.state === undefined ||\n this.view!.state.rowIndex === undefined\n ) {\n throw new Error(\n \"Attempted to drag table row, but no table block was hovered prior.\",\n );\n }\n\n this.view!.state.draggingState = {\n draggedCellOrientation: \"row\",\n originalIndex: this.view!.state.rowIndex,\n mousePos: event.clientY,\n };\n this.view!.emitUpdate();\n\n this.editor.transact((tr) =>\n tr.setMeta(tableHandlesPluginKey, {\n draggedCellOrientation:\n this.view!.state!.draggingState!.draggedCellOrientation,\n originalIndex: this.view!.state!.rowIndex,\n newIndex: this.view!.state!.rowIndex,\n tablePos: this.view!.tablePos,\n }),\n );\n\n if (!this.editor.prosemirrorView) {\n throw new Error(\"Editor view not initialized.\");\n }\n\n setHiddenDragImage(this.editor.prosemirrorView.root);\n event.dataTransfer!.setDragImage(dragImageElement!, 0, 0);\n event.dataTransfer!.effectAllowed = \"copyMove\";\n };\n\n /**\n * Callback that should be set on the `dragEnd` event for both the element\n * used as the row drag handle, and the one used as the column drag handle.\n */\n dragEnd = () => {\n if (this.view!.state === undefined) {\n throw new Error(\n \"Attempted to drag table row, but no table block was hovered prior.\",\n );\n }\n\n this.view!.state.draggingState = undefined;\n this.view!.emitUpdate();\n\n this.editor.transact((tr) => tr.setMeta(tableHandlesPluginKey, null));\n\n if (!this.editor.prosemirrorView) {\n throw new Error(\"Editor view not initialized.\");\n }\n\n unsetHiddenDragImage(this.editor.prosemirrorView.root);\n };\n\n /**\n * Freezes the drag handles. When frozen, they will stay attached to the same\n * cell regardless of which cell is hovered by the mouse cursor.\n */\n freezeHandles = () => {\n this.view!.menuFrozen = true;\n };\n\n /**\n * Unfreezes the drag handles. When frozen, they will stay attached to the\n * same cell regardless of which cell is hovered by the mouse cursor.\n */\n unfreezeHandles = () => {\n this.view!.menuFrozen = false;\n };\n\n getCellsAtRowHandle = (\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeRowIndex: RelativeCellIndices[\"row\"],\n ) => {\n return getCellsAtRowHandle(block, relativeRowIndex);\n };\n\n /**\n * Get all the cells in a column of the table block.\n */\n getCellsAtColumnHandle = (\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeColumnIndex: RelativeCellIndices[\"col\"],\n ) => {\n return getCellsAtColumnHandle(block, relativeColumnIndex);\n };\n\n /**\n * Sets the selection to the given cell or a range of cells.\n * @returns The new state after the selection has been set.\n */\n private setCellSelection = (\n state: EditorState,\n relativeStartCell: RelativeCellIndices,\n relativeEndCell: RelativeCellIndices = relativeStartCell,\n ) => {\n const view = this.view;\n\n if (!view) {\n throw new Error(\"Table handles view not initialized\");\n }\n\n const tableResolvedPos = state.doc.resolve(view.tablePos! + 1);\n const startRowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(relativeStartCell.row) + 1,\n );\n const startCellResolvedPos = state.doc.resolve(\n // No need for +1, since CellSelection expects the position before the cell\n startRowResolvedPos.posAtIndex(relativeStartCell.col),\n );\n const endRowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(relativeEndCell.row) + 1,\n );\n const endCellResolvedPos = state.doc.resolve(\n // No need for +1, since CellSelection expects the position before the cell\n endRowResolvedPos.posAtIndex(relativeEndCell.col),\n );\n\n // Begin a new transaction to set the selection\n const tr = state.tr;\n\n // Set the selection to the given cell or a range of cells\n tr.setSelection(\n new CellSelection(startCellResolvedPos, endCellResolvedPos),\n );\n\n // Quickly apply the transaction to get the new state to update the selection before splitting the cell\n return state.apply(tr);\n };\n\n /**\n * Adds a row or column to the table using prosemirror-table commands\n */\n addRowOrColumn = (\n index: RelativeCellIndices[\"row\"] | RelativeCellIndices[\"col\"],\n direction:\n | { orientation: \"row\"; side: \"above\" | \"below\" }\n | { orientation: \"column\"; side: \"left\" | \"right\" },\n ) => {\n this.editor.exec((beforeState, dispatch) => {\n const state = this.setCellSelection(\n beforeState,\n direction.orientation === \"row\"\n ? { row: index, col: 0 }\n : { row: 0, col: index },\n );\n\n if (direction.orientation === \"row\") {\n if (direction.side === \"above\") {\n return addRowBefore(state, dispatch);\n } else {\n return addRowAfter(state, dispatch);\n }\n } else {\n if (direction.side === \"left\") {\n return addColumnBefore(state, dispatch);\n } else {\n return addColumnAfter(state, dispatch);\n }\n }\n });\n };\n\n /**\n * Removes a row or column from the table using prosemirror-table commands\n */\n removeRowOrColumn = (\n index: RelativeCellIndices[\"row\"] | RelativeCellIndices[\"col\"],\n direction: \"row\" | \"column\",\n ) => {\n if (direction === \"row\") {\n return this.editor.exec((beforeState, dispatch) => {\n const state = this.setCellSelection(beforeState, {\n row: index,\n col: 0,\n });\n return deleteRow(state, dispatch);\n });\n } else {\n return this.editor.exec((beforeState, dispatch) => {\n const state = this.setCellSelection(beforeState, {\n row: 0,\n col: index,\n });\n return deleteColumn(state, dispatch);\n });\n }\n };\n\n /**\n * Merges the cells in the table block.\n */\n mergeCells = (cellsToMerge?: {\n relativeStartCell: RelativeCellIndices;\n relativeEndCell: RelativeCellIndices;\n }) => {\n return this.editor.exec((beforeState, dispatch) => {\n const state = cellsToMerge\n ? this.setCellSelection(\n beforeState,\n cellsToMerge.relativeStartCell,\n cellsToMerge.relativeEndCell,\n )\n : beforeState;\n\n return mergeCells(state, dispatch);\n });\n };\n\n /**\n * Splits the cell in the table block.\n * If no cell is provided, the current cell selected will be split.\n */\n splitCell = (relativeCellToSplit?: RelativeCellIndices) => {\n return this.editor.exec((beforeState, dispatch) => {\n const state = relativeCellToSplit\n ? this.setCellSelection(beforeState, relativeCellToSplit)\n : beforeState;\n\n return splitCell(state, dispatch);\n });\n };\n\n /**\n * Gets the start and end cells of the current cell selection.\n * @returns The start and end cells of the current cell selection.\n */\n getCellSelection = ():\n | undefined\n | {\n from: RelativeCellIndices;\n to: RelativeCellIndices;\n /**\n * All of the cells that are within the selected range.\n */\n cells: RelativeCellIndices[];\n } => {\n // Based on the current selection, find the table cells that are within the selected range\n\n return this.editor.transact((tr) => {\n const selection = tr.selection;\n\n let $fromCell = selection.$from;\n let $toCell = selection.$to;\n if (isTableCellSelection(selection)) {\n // When the selection is a table cell selection, we can find the\n // from and to cells by iterating over the ranges in the selection\n const { ranges } = selection;\n ranges.forEach((range) => {\n $fromCell = range.$from.min($fromCell ?? range.$from);\n $toCell = range.$to.max($toCell ?? range.$to);\n });\n } else {\n // When the selection is a normal text selection\n // Assumes we are within a tableParagraph\n // And find the from and to cells by resolving the positions\n $fromCell = tr.doc.resolve(\n selection.$from.pos - selection.$from.parentOffset - 1,\n );\n $toCell = tr.doc.resolve(\n selection.$to.pos - selection.$to.parentOffset - 1,\n );\n\n // Opt-out when the selection is not pointing into cells\n if ($fromCell.pos === 0 || $toCell.pos === 0) {\n return undefined;\n }\n }\n\n // Find the row and table that the from and to cells are in\n const $fromRow = tr.doc.resolve(\n $fromCell.pos - $fromCell.parentOffset - 1,\n );\n const $toRow = tr.doc.resolve($toCell.pos - $toCell.parentOffset - 1);\n\n // Find the table\n const $table = tr.doc.resolve($fromRow.pos - $fromRow.parentOffset - 1);\n\n // Find the column and row indices of the from and to cells\n const fromColIndex = $fromCell.index($fromRow.depth);\n const fromRowIndex = $fromRow.index($table.depth);\n const toColIndex = $toCell.index($toRow.depth);\n const toRowIndex = $toRow.index($table.depth);\n\n const cells: RelativeCellIndices[] = [];\n for (let row = fromRowIndex; row <= toRowIndex; row++) {\n for (let col = fromColIndex; col <= toColIndex; col++) {\n cells.push({ row, col });\n }\n }\n\n return {\n from: {\n row: fromRowIndex,\n col: fromColIndex,\n },\n to: {\n row: toRowIndex,\n col: toColIndex,\n },\n cells,\n };\n });\n };\n\n /**\n * Gets the direction of the merge based on the current cell selection.\n *\n * Returns undefined when there is no cell selection, or the selection is not within a table.\n */\n getMergeDirection = (\n block:\n | BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>\n | undefined,\n ) => {\n return this.editor.transact((tr) => {\n const isSelectingTableCells = isTableCellSelection(tr.selection)\n ? tr.selection\n : undefined;\n\n if (\n !isSelectingTableCells ||\n !block ||\n // Only offer the merge button if there is more than one cell selected.\n isSelectingTableCells.ranges.length <= 1\n ) {\n return undefined;\n }\n\n const cellSelection = this.getCellSelection();\n\n if (!cellSelection) {\n return undefined;\n }\n\n if (areInSameColumn(cellSelection.from, cellSelection.to, block)) {\n return \"vertical\";\n }\n\n return \"horizontal\";\n });\n };\n\n cropEmptyRowsOrColumns = (\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n removeEmpty: \"columns\" | \"rows\",\n ) => {\n return cropEmptyRowsOrColumns(block, removeEmpty);\n };\n\n addRowsOrColumns = (\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n addType: \"columns\" | \"rows\",\n numToAdd: number,\n ) => {\n return addRowsOrColumns(block, addType, numToAdd);\n };\n}\n","import { Extension } from \"@tiptap/core\";\n\nexport const TextAlignmentExtension = Extension.create({\n name: \"textAlignment\",\n\n addGlobalAttributes() {\n return [\n {\n // Attribute is applied to block content instead of container so that child blocks don't inherit the text\n // alignment styling.\n types: [\n \"paragraph\",\n \"heading\",\n \"bulletListItem\",\n \"numberedListItem\",\n \"checkListItem\",\n \"tableCell\",\n \"tableHeader\",\n ],\n attributes: {\n textAlignment: {\n default: \"left\",\n parseHTML: (element) => {\n return element.getAttribute(\"data-text-alignment\");\n },\n renderHTML: (attributes) => {\n if (attributes.textAlignment === \"left\") {\n return {};\n }\n return {\n \"data-text-alignment\": attributes.textAlignment,\n };\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { defaultProps } from \"../../blocks/defaultProps.js\";\n\nexport const TextColorExtension = Extension.create({\n name: \"blockTextColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\", \"tableCell\", \"tableHeader\"],\n attributes: {\n textColor: {\n default: defaultProps.textColor.default,\n parseHTML: (element) =>\n element.hasAttribute(\"data-text-color\")\n ? element.getAttribute(\"data-text-color\")\n : defaultProps.textColor.default,\n renderHTML: (attributes) => {\n if (attributes.textColor === defaultProps.textColor.default) {\n return {};\n }\n return {\n \"data-text-color\": attributes.textColor,\n };\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\n\n// based on https://github.com/ueberdosis/tiptap/blob/40a9404c94c7fef7900610c195536384781ae101/demos/src/Experiments/TrailingNode/Vue/trailing-node.ts\n\n/**\n * Extension based on:\n * - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js\n * - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts\n */\n\nexport interface TrailingNodeOptions {\n node: string;\n}\n\n/**\n * Add a trailing node to the document so the user can always click at the bottom of the document and start typing\n */\nexport const TrailingNode = Extension.create<TrailingNodeOptions>({\n name: \"trailingNode\",\n\n addProseMirrorPlugins() {\n const plugin = new PluginKey(this.name);\n // const disabledNodes = Object.entries(this.editor.schema.nodes)\n // .map(([, value]) => value)\n // .filter((node) => this.options.notAfter.includes(node.name));\n\n return [\n new Plugin({\n key: plugin,\n appendTransaction: (_, __, state) => {\n const { doc, tr, schema } = state;\n const shouldInsertNodeAtEnd = plugin.getState(state);\n const endPosition = doc.content.size - 2;\n const type = schema.nodes[\"blockContainer\"];\n const contentType = schema.nodes[\"paragraph\"];\n if (!shouldInsertNodeAtEnd) {\n return;\n }\n\n return tr.insert(\n endPosition,\n type.create(undefined, contentType.create()),\n );\n },\n state: {\n init: (_, _state) => {\n // (maybe fix): use same logic as apply() here\n // so it works when initializing\n },\n apply: (tr, value) => {\n if (!tr.docChanged) {\n return value;\n }\n\n let lastNode = tr.doc.lastChild;\n\n if (!lastNode || lastNode.type.name !== \"blockGroup\") {\n throw new Error(\"Expected blockGroup\");\n }\n\n lastNode = lastNode.lastChild;\n\n if (!lastNode || lastNode.type.name !== \"blockContainer\") {\n return true; // not a blockContainer, but for example Columns. Insert trailing node\n }\n\n const lastContentNode = lastNode.firstChild;\n\n if (!lastContentNode) {\n throw new Error(\"Expected blockContent\");\n }\n\n // If last node is not empty (size > 4) or it doesn't contain\n // inline content, we need to add a trailing node.\n return (\n lastNode.nodeSize > 4 ||\n lastContentNode.type.spec.content !== \"inline*\"\n );\n },\n },\n }),\n ];\n },\n});\n","import { Node } from \"@tiptap/core\";\n\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport { BlockNoteDOMAttributes } from \"../schema/index.js\";\nimport { mergeCSSClasses } from \"../util/browser.js\";\n\n// Object containing all possible block attributes.\nconst BlockAttributes: Record<string, string> = {\n blockColor: \"data-block-color\",\n blockStyle: \"data-block-style\",\n id: \"data-id\",\n depth: \"data-depth\",\n depthChange: \"data-depth-change\",\n};\n\n/**\n * The main \"Block node\" documents consist of\n */\nexport const BlockContainer = Node.create<{\n domAttributes?: BlockNoteDOMAttributes;\n editor: BlockNoteEditor<any, any, any>;\n}>({\n name: \"blockContainer\",\n group: \"blockGroupChild bnBlock\",\n // A block always contains content, and optionally a blockGroup which contains nested blocks\n content: \"blockContent blockGroup?\",\n // Ensures content-specific keyboard handlers trigger first.\n priority: 50,\n defining: true,\n marks: \"insertion modification deletion\",\n parseHTML() {\n return [\n {\n tag: \"div[data-node-type=\" + this.name + \"]\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const attrs: Record<string, string> = {};\n for (const [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {\n if (element.getAttribute(HTMLAttr)) {\n attrs[nodeAttr] = element.getAttribute(HTMLAttr)!;\n }\n }\n\n return attrs;\n },\n },\n // Ignore `blockOuter` divs, but parse the `blockContainer` divs inside them.\n {\n tag: `div[data-node-type=\"blockOuter\"]`,\n skip: true,\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const blockOuter = document.createElement(\"div\");\n blockOuter.className = \"bn-block-outer\";\n blockOuter.setAttribute(\"data-node-type\", \"blockOuter\");\n for (const [attribute, value] of Object.entries(HTMLAttributes)) {\n if (attribute !== \"class\") {\n blockOuter.setAttribute(attribute, value);\n }\n }\n\n const blockHTMLAttributes = {\n ...(this.options.domAttributes?.block || {}),\n ...HTMLAttributes,\n };\n const block = document.createElement(\"div\");\n block.className = mergeCSSClasses(\"bn-block\", blockHTMLAttributes.class);\n block.setAttribute(\"data-node-type\", this.name);\n for (const [attribute, value] of Object.entries(blockHTMLAttributes)) {\n if (attribute !== \"class\") {\n block.setAttribute(attribute, value);\n }\n }\n\n blockOuter.appendChild(block);\n\n return {\n dom: blockOuter,\n contentDOM: block,\n };\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport { BlockNoteDOMAttributes } from \"../schema/index.js\";\nimport { mergeCSSClasses } from \"../util/browser.js\";\n\nexport const BlockGroup = Node.create<{\n domAttributes?: BlockNoteDOMAttributes;\n}>({\n name: \"blockGroup\",\n group: \"childContainer\",\n content: \"blockGroupChild+\",\n marks: \"deletion insertion modification\",\n parseHTML() {\n return [\n {\n tag: \"div\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.getAttribute(\"data-node-type\") === \"blockGroup\") {\n // Null means the element matches, but we don't want to add any attributes to the node.\n return null;\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const blockGroupHTMLAttributes = {\n ...(this.options.domAttributes?.blockGroup || {}),\n ...HTMLAttributes,\n };\n const blockGroup = document.createElement(\"div\");\n blockGroup.className = mergeCSSClasses(\n \"bn-block-group\",\n blockGroupHTMLAttributes.class,\n );\n blockGroup.setAttribute(\"data-node-type\", \"blockGroup\");\n for (const [attribute, value] of Object.entries(blockGroupHTMLAttributes)) {\n if (attribute !== \"class\") {\n blockGroup.setAttribute(attribute, value);\n }\n }\n\n return {\n dom: blockGroup,\n contentDOM: blockGroup,\n };\n },\n});\n","import { Node } from \"@tiptap/core\";\n\nexport const Doc = Node.create({\n name: \"doc\",\n topNode: true,\n content: \"blockGroup\",\n marks: \"insertion modification deletion\",\n});\n","import * as Y from \"yjs\";\n\nimport {\n yCursorPluginKey,\n ySyncPluginKey,\n yUndoPluginKey,\n} from \"y-prosemirror\";\nimport { CursorPlugin } from \"./CursorPlugin.js\";\nimport { SyncPlugin } from \"./SyncPlugin.js\";\nimport { UndoPlugin } from \"./UndoPlugin.js\";\n\nimport {\n BlockNoteEditor,\n BlockNoteEditorOptions,\n} from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nexport class ForkYDocPlugin extends BlockNoteExtension<{\n forked: boolean;\n}> {\n public static key() {\n return \"ForkYDocPlugin\";\n }\n\n private editor: BlockNoteEditor<any, any, any>;\n private collaboration: BlockNoteEditorOptions<any, any, any>[\"collaboration\"];\n\n constructor({\n editor,\n collaboration,\n }: {\n editor: BlockNoteEditor<any, any, any>;\n collaboration: BlockNoteEditorOptions<any, any, any>[\"collaboration\"];\n }) {\n super(editor);\n this.editor = editor;\n this.collaboration = collaboration;\n }\n\n /**\n * To find a fragment in another ydoc, we need to search for it.\n */\n private findTypeInOtherYdoc<T extends Y.AbstractType<any>>(\n ytype: T,\n otherYdoc: Y.Doc,\n ): T {\n const ydoc = ytype.doc!;\n if (ytype._item === null) {\n /**\n * If is a root type, we need to find the root key in the original ydoc\n * and use it to get the type in the other ydoc.\n */\n const rootKey = Array.from(ydoc.share.keys()).find(\n (key) => ydoc.share.get(key) === ytype,\n );\n if (rootKey == null) {\n throw new Error(\"type does not exist in other ydoc\");\n }\n return otherYdoc.get(rootKey, ytype.constructor as new () => T) as T;\n } else {\n /**\n * If it is a sub type, we use the item id to find the history type.\n */\n const ytypeItem = ytype._item;\n const otherStructs =\n otherYdoc.store.clients.get(ytypeItem.id.client) ?? [];\n const itemIndex = Y.findIndexSS(otherStructs, ytypeItem.id.clock);\n const otherItem = otherStructs[itemIndex] as Y.Item;\n const otherContent = otherItem.content as Y.ContentType;\n return otherContent.type as T;\n }\n }\n\n /**\n * Whether the editor is editing a forked document,\n * preserving a reference to the original document and the forked document.\n */\n public get isForkedFromRemote() {\n return this.forkedState !== undefined;\n }\n\n /**\n * Stores whether the editor is editing a forked document,\n * preserving a reference to the original document and the forked document.\n */\n private forkedState:\n | {\n originalFragment: Y.XmlFragment;\n forkedFragment: Y.XmlFragment;\n }\n | undefined;\n\n /**\n * Fork the Y.js document from syncing to the remote,\n * allowing modifications to the document without affecting the remote.\n * These changes can later be rolled back or applied to the remote.\n */\n public fork() {\n if (this.isForkedFromRemote) {\n return;\n }\n\n const originalFragment = this.collaboration.fragment;\n\n if (!originalFragment) {\n throw new Error(\"No fragment to fork from\");\n }\n\n const doc = new Y.Doc();\n // Copy the original document to a new Yjs document\n Y.applyUpdate(doc, Y.encodeStateAsUpdate(originalFragment.doc!));\n\n // Find the forked fragment in the new Yjs document\n const forkedFragment = this.findTypeInOtherYdoc(originalFragment, doc);\n\n this.forkedState = {\n originalFragment,\n forkedFragment,\n };\n\n // Need to reset all the yjs plugins\n this.editor._tiptapEditor.unregisterPlugin([\n yCursorPluginKey,\n yUndoPluginKey,\n ySyncPluginKey,\n ]);\n // Register them again, based on the new forked fragment\n this.editor._tiptapEditor.registerPlugin(\n new SyncPlugin(forkedFragment).plugins[0],\n );\n this.editor._tiptapEditor.registerPlugin(new UndoPlugin().plugins[0]);\n // No need to register the cursor plugin again, it's a local fork\n this.emit(\"forked\", true);\n }\n\n /**\n * Resume syncing the Y.js document to the remote\n * If `keepChanges` is true, any changes that have been made to the forked document will be applied to the original document.\n * Otherwise, the original document will be restored and the changes will be discarded.\n */\n public merge({ keepChanges }: { keepChanges: boolean }) {\n if (!this.forkedState) {\n return;\n }\n // Remove the forked fragment's plugins\n this.editor._tiptapEditor.unregisterPlugin(ySyncPluginKey);\n this.editor._tiptapEditor.unregisterPlugin(yUndoPluginKey);\n\n const { originalFragment, forkedFragment } = this.forkedState;\n if (keepChanges) {\n // Apply any changes that have been made to the fork, onto the original doc\n const update = Y.encodeStateAsUpdate(forkedFragment.doc!);\n Y.applyUpdate(originalFragment.doc!, update);\n }\n this.editor.extensions[\"ySyncPlugin\"] = new SyncPlugin(originalFragment);\n this.editor.extensions[\"yCursorPlugin\"] = new CursorPlugin(\n this.collaboration!,\n );\n this.editor.extensions[\"yUndoPlugin\"] = new UndoPlugin();\n // Register the plugins again, based on the original fragment\n this.editor._tiptapEditor.registerPlugin(\n this.editor.extensions[\"ySyncPlugin\"].plugins[0],\n );\n this.editor._tiptapEditor.registerPlugin(\n this.editor.extensions[\"yCursorPlugin\"].plugins[0],\n );\n this.editor._tiptapEditor.registerPlugin(\n this.editor.extensions[\"yUndoPlugin\"].plugins[0],\n );\n // Reset the forked state\n this.forkedState = undefined;\n this.emit(\"forked\", false);\n }\n}\n","import { AnyExtension, Extension, extensions } from \"@tiptap/core\";\nimport { Gapcursor } from \"@tiptap/extension-gapcursor\";\nimport { History } from \"@tiptap/extension-history\";\nimport { Link } from \"@tiptap/extension-link\";\nimport { Text } from \"@tiptap/extension-text\";\nimport { Plugin } from \"prosemirror-state\";\nimport * as Y from \"yjs\";\n\nimport { createDropFileExtension } from \"../api/clipboard/fromClipboard/fileDropExtension.js\";\nimport { createPasteFromClipboardExtension } from \"../api/clipboard/fromClipboard/pasteExtension.js\";\nimport { createCopyToClipboardExtension } from \"../api/clipboard/toClipboard/copyExtension.js\";\nimport type { ThreadStore } from \"../comments/index.js\";\nimport { BackgroundColorExtension } from \"../extensions/BackgroundColor/BackgroundColorExtension.js\";\nimport { CursorPlugin } from \"../extensions/Collaboration/CursorPlugin.js\";\nimport { SyncPlugin } from \"../extensions/Collaboration/SyncPlugin.js\";\nimport { UndoPlugin } from \"../extensions/Collaboration/UndoPlugin.js\";\nimport { CommentMark } from \"../extensions/Comments/CommentMark.js\";\nimport { CommentsPlugin } from \"../extensions/Comments/CommentsPlugin.js\";\nimport { FilePanelProsemirrorPlugin } from \"../extensions/FilePanel/FilePanelPlugin.js\";\nimport { FormattingToolbarProsemirrorPlugin } from \"../extensions/FormattingToolbar/FormattingToolbarPlugin.js\";\nimport { HardBreak } from \"../extensions/HardBreak/HardBreak.js\";\nimport { KeyboardShortcutsExtension } from \"../extensions/KeyboardShortcuts/KeyboardShortcutsExtension.js\";\nimport { LinkToolbarProsemirrorPlugin } from \"../extensions/LinkToolbar/LinkToolbarPlugin.js\";\nimport {\n DEFAULT_LINK_PROTOCOL,\n VALID_LINK_PROTOCOLS,\n} from \"../extensions/LinkToolbar/protocols.js\";\nimport { NodeSelectionKeyboardPlugin } from \"../extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.js\";\nimport { PlaceholderPlugin } from \"../extensions/Placeholder/PlaceholderPlugin.js\";\nimport { PreviousBlockTypePlugin } from \"../extensions/PreviousBlockType/PreviousBlockTypePlugin.js\";\nimport { ShowSelectionPlugin } from \"../extensions/ShowSelection/ShowSelectionPlugin.js\";\nimport { SideMenuProsemirrorPlugin } from \"../extensions/SideMenu/SideMenuPlugin.js\";\nimport { SuggestionMenuProseMirrorPlugin } from \"../extensions/SuggestionMenu/SuggestionPlugin.js\";\nimport {\n SuggestionAddMark,\n SuggestionDeleteMark,\n SuggestionModificationMark,\n} from \"../extensions/Suggestions/SuggestionMarks.js\";\nimport { TableHandlesProsemirrorPlugin } from \"../extensions/TableHandles/TableHandlesPlugin.js\";\nimport { TextAlignmentExtension } from \"../extensions/TextAlignment/TextAlignmentExtension.js\";\nimport { TextColorExtension } from \"../extensions/TextColor/TextColorExtension.js\";\nimport { TrailingNode } from \"../extensions/TrailingNode/TrailingNodeExtension.js\";\nimport UniqueID from \"../extensions/UniqueID/UniqueID.js\";\nimport { BlockContainer, BlockGroup, Doc } from \"../pm-nodes/index.js\";\nimport {\n BlockNoteDOMAttributes,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n StyleSchema,\n StyleSpecs,\n} from \"../schema/index.js\";\nimport type {\n BlockNoteEditor,\n BlockNoteEditorOptions,\n SupportedExtension,\n} from \"./BlockNoteEditor.js\";\nimport { ForkYDocPlugin } from \"../extensions/Collaboration/ForkYDocPlugin.js\";\n\ntype ExtensionOptions<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = {\n editor: BlockNoteEditor<BSchema, I, S>;\n domAttributes: Partial<BlockNoteDOMAttributes>;\n blockSpecs: BlockSpecs;\n inlineContentSpecs: InlineContentSpecs;\n styleSpecs: StyleSpecs;\n trailingBlock: boolean | undefined;\n collaboration?: {\n fragment: Y.XmlFragment;\n user: {\n name: string;\n color: string;\n [key: string]: string;\n };\n provider: any;\n renderCursor?: (user: any) => HTMLElement;\n showCursorLabels?: \"always\" | \"activity\";\n };\n disableExtensions: string[] | undefined;\n setIdAttribute?: boolean;\n animations: boolean;\n tableHandles: boolean;\n dropCursor: (opts: any) => Plugin;\n placeholders: Record<\n string | \"default\" | \"emptyDocument\",\n string | undefined\n >;\n tabBehavior?: \"prefer-navigate-ui\" | \"prefer-indent\";\n sideMenuDetection: \"viewport\" | \"editor\";\n comments?: {\n threadStore: ThreadStore;\n };\n pasteHandler: BlockNoteEditorOptions<any, any, any>[\"pasteHandler\"];\n};\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nexport const getBlockNoteExtensions = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n opts: ExtensionOptions<BSchema, I, S>,\n) => {\n const ret: Record<string, SupportedExtension> = {};\n const tiptapExtensions = getTipTapExtensions(opts);\n\n for (const ext of tiptapExtensions) {\n ret[ext.name] = ext;\n }\n\n if (opts.collaboration) {\n ret[\"ySyncPlugin\"] = new SyncPlugin(opts.collaboration.fragment);\n ret[\"yUndoPlugin\"] = new UndoPlugin();\n\n if (opts.collaboration.provider?.awareness) {\n ret[\"yCursorPlugin\"] = new CursorPlugin(opts.collaboration);\n }\n ret[\"forkYDocPlugin\"] = new ForkYDocPlugin({\n editor: opts.editor,\n collaboration: opts.collaboration,\n });\n }\n\n // Note: this is pretty hardcoded and will break when user provides plugins with same keys.\n // Define name on plugins instead and not make this a map?\n ret[\"formattingToolbar\"] = new FormattingToolbarProsemirrorPlugin(\n opts.editor,\n );\n ret[\"linkToolbar\"] = new LinkToolbarProsemirrorPlugin(opts.editor);\n ret[\"sideMenu\"] = new SideMenuProsemirrorPlugin(\n opts.editor,\n opts.sideMenuDetection,\n );\n ret[\"suggestionMenus\"] = new SuggestionMenuProseMirrorPlugin(opts.editor);\n ret[\"filePanel\"] = new FilePanelProsemirrorPlugin(opts.editor as any);\n ret[\"placeholder\"] = new PlaceholderPlugin(opts.editor, opts.placeholders);\n\n if (opts.animations ?? true) {\n ret[\"animations\"] = new PreviousBlockTypePlugin();\n }\n\n if (opts.tableHandles) {\n ret[\"tableHandles\"] = new TableHandlesProsemirrorPlugin(opts.editor as any);\n }\n\n ret[\"nodeSelectionKeyboard\"] = new NodeSelectionKeyboardPlugin();\n\n ret[\"showSelection\"] = new ShowSelectionPlugin(opts.editor);\n\n if (opts.comments) {\n ret[\"comments\"] = new CommentsPlugin(\n opts.editor,\n opts.comments.threadStore,\n CommentMark.name,\n );\n }\n\n const disableExtensions: string[] = opts.disableExtensions || [];\n for (const ext of disableExtensions) {\n delete ret[ext];\n }\n\n return ret;\n};\n\nlet LINKIFY_INITIALIZED = false;\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nconst getTipTapExtensions = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n opts: ExtensionOptions<BSchema, I, S>,\n) => {\n const tiptapExtensions: AnyExtension[] = [\n extensions.ClipboardTextSerializer,\n extensions.Commands,\n extensions.Editable,\n extensions.FocusEvents,\n extensions.Tabindex,\n\n // DevTools,\n Gapcursor,\n\n // DropCursor,\n Extension.create({\n name: \"dropCursor\",\n addProseMirrorPlugins: () => [\n opts.dropCursor({\n width: 5,\n color: \"#ddeeff\",\n editor: opts.editor,\n }),\n ],\n }),\n\n UniqueID.configure({\n // everything from bnBlock group (nodes that represent a BlockNote block should have an id)\n types: [\"blockContainer\", \"columnList\", \"column\"],\n setIdAttribute: opts.setIdAttribute,\n }),\n HardBreak,\n // Comments,\n\n // basics:\n Text,\n\n // marks:\n SuggestionAddMark,\n SuggestionDeleteMark,\n SuggestionModificationMark,\n Link.extend({\n inclusive: false,\n }).configure({\n defaultProtocol: DEFAULT_LINK_PROTOCOL,\n // only call this once if we have multiple editors installed. Or fix https://github.com/ueberdosis/tiptap/issues/5450\n protocols: LINKIFY_INITIALIZED ? [] : VALID_LINK_PROTOCOLS,\n }),\n ...Object.values(opts.styleSpecs).map((styleSpec) => {\n return styleSpec.implementation.mark.configure({\n editor: opts.editor as any,\n });\n }),\n\n TextColorExtension,\n\n BackgroundColorExtension,\n TextAlignmentExtension,\n\n // make sure escape blurs editor, so that we can tab to other elements in the host page (accessibility)\n Extension.create({\n name: \"OverrideEscape\",\n addKeyboardShortcuts() {\n return {\n Escape: () => {\n if (opts.editor.suggestionMenus.shown) {\n // escape is handled by suggestionmenu\n return false;\n }\n return this.editor.commands.blur();\n },\n };\n },\n }),\n\n // nodes\n Doc,\n BlockContainer.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n }),\n KeyboardShortcutsExtension.configure({\n editor: opts.editor,\n tabBehavior: opts.tabBehavior,\n }),\n BlockGroup.configure({\n domAttributes: opts.domAttributes,\n }),\n ...Object.values(opts.inlineContentSpecs)\n .filter((a) => a.config !== \"link\" && a.config !== \"text\")\n .map((inlineContentSpec) => {\n return inlineContentSpec.implementation!.node.configure({\n editor: opts.editor as any,\n });\n }),\n\n ...Object.values(opts.blockSpecs).flatMap((blockSpec) => {\n return [\n // dependent nodes (e.g.: tablecell / row)\n ...(blockSpec.implementation.requiredExtensions || []).map((ext) =>\n ext.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n }),\n ),\n // the actual node itself\n blockSpec.implementation.node.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n }),\n ];\n }),\n createCopyToClipboardExtension(opts.editor),\n createPasteFromClipboardExtension(\n opts.editor,\n opts.pasteHandler ||\n ((context: {\n defaultPasteHandler: (context?: {\n prioritizeMarkdownOverHTML?: boolean;\n plainTextAsMarkdown?: boolean;\n }) => boolean | undefined;\n }) => context.defaultPasteHandler()),\n ),\n createDropFileExtension(opts.editor),\n\n // This needs to be at the bottom of this list, because Key events (such as enter, when selecting a /command),\n // should be handled before Enter handlers in other components like splitListItem\n ...(opts.trailingBlock === undefined || opts.trailingBlock\n ? [TrailingNode]\n : []),\n ...(opts.comments ? [CommentMark] : []),\n ];\n\n LINKIFY_INITIALIZED = true;\n\n if (!opts.collaboration) {\n // disable history extension when collaboration is enabled as y-prosemirror takes care of undo / redo\n tiptapExtensions.push(History);\n }\n\n return tiptapExtensions;\n};\n","import { Fragment, Schema, Slice } from \"@tiptap/pm/model\";\nimport { EditorView } from \"@tiptap/pm/view\";\n\nimport { getBlockInfoFromSelection } from \"../api/getBlockInfoFromPos.js\";\n\n// helper function to remove a child from a fragment\nfunction removeChild(node: Fragment, n: number) {\n const children: any[] = [];\n node.forEach((child, _, i) => {\n if (i !== n) {\n children.push(child);\n }\n });\n return Fragment.from(children);\n}\n\n/**\n * Wrap adjacent tableRow items in a table.\n *\n * This makes sure the content that we paste is always a table (and not a tableRow)\n * A table works better for the remaing paste handling logic, as it's actually a blockContent node\n */\nexport function wrapTableRows(f: Fragment, schema: Schema) {\n const newItems: any[] = [];\n for (let i = 0; i < f.childCount; i++) {\n if (f.child(i).type.name === \"tableRow\") {\n if (\n newItems.length > 0 &&\n newItems[newItems.length - 1].type.name === \"table\"\n ) {\n // append to existing table\n const prevTable = newItems[newItems.length - 1];\n const newTable = prevTable.copy(prevTable.content.addToEnd(f.child(i)));\n newItems[newItems.length - 1] = newTable;\n } else {\n // create new table to wrap tableRow with\n const newTable = schema.nodes.table.createChecked(\n undefined,\n f.child(i),\n );\n newItems.push(newTable);\n }\n } else {\n newItems.push(f.child(i));\n }\n }\n f = Fragment.from(newItems);\n return f;\n}\n\n/**\n * fix for https://github.com/ProseMirror/prosemirror/issues/1430#issuecomment-1822570821\n *\n * This fix wraps pasted ProseMirror nodes in their own `blockContainer` nodes\n * in most cases. This is to ensure that ProseMirror inserts them as separate\n * blocks, which it sometimes doesn't do because it doesn't have enough context\n * about the hierarchy of the pasted nodes. The issue can be seen when pasting\n * e.g. an image or two consecutive paragraphs, where PM tries to nest the\n * pasted block(s) when it shouldn't.\n *\n * However, the fix is not applied in a few cases. See `shouldApplyFix` for\n * which cases are excluded.\n */\nexport function transformPasted(slice: Slice, view: EditorView) {\n let f = Fragment.from(slice.content);\n f = wrapTableRows(f, view.state.schema);\n\n if (!shouldApplyFix(f, view)) {\n // Don't apply the fix.\n return new Slice(f, slice.openStart, slice.openEnd);\n }\n\n for (let i = 0; i < f.childCount; i++) {\n if (f.child(i).type.spec.group === \"blockContent\") {\n const content = [f.child(i)];\n\n // when there is a blockGroup with lists, it should be nested in the new blockcontainer\n // (if we remove this if-block, the nesting bug will be fixed, but lists won't be nested correctly)\n if (\n i + 1 < f.childCount &&\n f.child(i + 1).type.name === \"blockGroup\" // TODO\n ) {\n const nestedChild = f\n .child(i + 1)\n .child(0)\n .child(0);\n\n if (\n nestedChild.type.name === \"bulletListItem\" ||\n nestedChild.type.name === \"numberedListItem\" ||\n nestedChild.type.name === \"checkListItem\"\n ) {\n content.push(f.child(i + 1));\n f = removeChild(f, i + 1);\n }\n }\n const container = view.state.schema.nodes.blockContainer.createChecked(\n undefined,\n content,\n );\n f = f.replaceChild(i, container);\n }\n }\n return new Slice(f, slice.openStart, slice.openEnd);\n}\n\n/**\n * Used in `transformPasted` to check if the fix there should be applied, i.e.\n * if the pasted fragment should be wrapped in a `blockContainer` node. This\n * will explicitly tell ProseMirror to treat it as a separate block.\n */\nfunction shouldApplyFix(fragment: Fragment, view: EditorView) {\n const nodeHasSingleChild = fragment.childCount === 1;\n const nodeHasInlineContent =\n fragment.firstChild?.type.spec.content === \"inline*\";\n const nodeHasTableContent =\n fragment.firstChild?.type.spec.content === \"tableRow+\";\n\n if (nodeHasSingleChild) {\n if (nodeHasInlineContent) {\n // Case when we paste a single node with inline content, e.g. a paragraph\n // or heading. We want to insert the content in-line for better UX instead\n // of a separate block, so we return false.\n return false;\n }\n\n if (nodeHasTableContent) {\n // Not ideal that we check selection here, as `transformPasted` is called\n // for both paste and drop events. Drop events can potentially cause\n // issues as they don't always happen at the current selection.\n const blockInfo = getBlockInfoFromSelection(view.state);\n if (blockInfo.isBlockContainer) {\n const selectedBlockHasTableContent =\n blockInfo.blockContent.node.type.spec.content === \"tableRow+\";\n\n // Case for when we paste a single node with table content, i.e. a\n // table. Normally, we return true as we want to ensure the table is\n // inserted as a separate block. However, if the selection is in an\n // existing table, we return false, as we want the content of the pasted\n // table to be added to the existing one for better UX.\n return !selectedBlockHasTableContent;\n }\n }\n }\n\n return true;\n}\n","import {\n Editor,\n EditorOptions,\n Editor as TiptapEditor,\n createDocument,\n} from \"@tiptap/core\";\n\nimport { Node } from \"@tiptap/pm/model\";\n\nimport { EditorView } from \"@tiptap/pm/view\";\n\nimport { EditorState, Transaction } from \"@tiptap/pm/state\";\nimport { blockToNode } from \"../api/nodeConversions/blockToNode.js\";\nimport { PartialBlock } from \"../blocks/defaultBlocks.js\";\nimport { StyleSchema } from \"../schema/index.js\";\nimport type { BlockNoteEditor } from \"./BlockNoteEditor.js\";\n\nexport type BlockNoteTipTapEditorOptions = Partial<\n Omit<EditorOptions, \"content\">\n> & {\n content: PartialBlock<any, any, any>[];\n};\n\n/**\n * Custom Editor class that extends TiptapEditor and separates\n * the creation of the view from the constructor.\n */\nexport class BlockNoteTipTapEditor extends TiptapEditor {\n private _state: EditorState;\n\n public static create = (\n options: BlockNoteTipTapEditorOptions,\n styleSchema: StyleSchema,\n ) => {\n // because we separate the constructor from the creation of the view,\n // we need to patch setTimeout to prevent this code from having any effect:\n // https://github.com/ueberdosis/tiptap/blob/45bac803283446795ad1b03f43d3746fa54a68ff/packages/core/src/Editor.ts#L117\n const oldSetTimeout = globalThis?.window?.setTimeout;\n if (typeof globalThis?.window?.setTimeout !== \"undefined\") {\n globalThis.window.setTimeout = (() => {\n return 0;\n }) as any;\n }\n try {\n return new BlockNoteTipTapEditor(options, styleSchema);\n } finally {\n if (oldSetTimeout) {\n globalThis.window.setTimeout = oldSetTimeout;\n }\n }\n };\n\n protected constructor(\n options: BlockNoteTipTapEditorOptions,\n styleSchema: StyleSchema,\n ) {\n // possible fix for next.js server side rendering\n // const d = globalThis.document;\n // const w = globalThis.window;\n // if (!globalThis.document) {\n // globalThis.document = {\n // createElement: () => {},\n // };\n // }\n\n // options.injectCSS = false\n\n super({ ...options, content: undefined });\n // try {\n // globalThis.window = w;\n // } catch(e) {}\n // try {\n // globalThis.document = d;\n // } catch(e) {}\n\n // This is a hack to make \"initial content detection\" by y-prosemirror (and also tiptap isEmpty)\n // properly detect whether or not the document has changed.\n // We change the doc.createAndFill function to make sure the initial block id is set, instead of null\n const schema = this.schema;\n let cache: any;\n const oldCreateAndFill = schema.nodes.doc.createAndFill;\n (schema.nodes.doc as any).createAndFill = (...args: any) => {\n if (cache) {\n return cache;\n }\n const ret = oldCreateAndFill.apply(schema.nodes.doc, args);\n\n // create a copy that we can mutate (otherwise, assigning attrs is not safe and corrupts the pm state)\n const jsonNode = JSON.parse(JSON.stringify(ret!.toJSON()));\n jsonNode.content[0].content[0].attrs.id = \"initialBlockId\";\n\n cache = Node.fromJSON(schema, jsonNode);\n return cache;\n };\n\n let doc: Node;\n\n try {\n const pmNodes = options?.content.map((b) =>\n blockToNode(b, this.schema, styleSchema).toJSON(),\n );\n doc = createDocument(\n {\n type: \"doc\",\n content: [\n {\n type: \"blockGroup\",\n content: pmNodes,\n },\n ],\n },\n this.schema,\n this.options.parseOptions,\n );\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\n \"Error creating document from blocks passed as `initialContent`. Caused by exception: \",\n e,\n );\n throw new Error(\n \"Error creating document from blocks passed as `initialContent`:\\n\" +\n +JSON.stringify(options.content),\n );\n }\n\n // Create state immediately, so that it's available independently from the View,\n // the way Prosemirror \"intends it to be\". This also makes sure that we can access\n // the state before the view is created / mounted.\n this._state = EditorState.create({\n doc,\n schema: this.schema,\n // selection: selection || undefined,\n });\n }\n\n get state() {\n if (this.view) {\n this._state = this.view.state;\n }\n return this._state;\n }\n\n dispatch(transaction: Transaction) {\n if (!this.view) {\n // before view has been initialized\n this._state = this.state.apply(transaction);\n this.emit(\"transaction\", {\n editor: this,\n transaction,\n });\n return;\n }\n // This is a verbatim copy of the default dispatch method, but with the following changes:\n // - We provide the appendedTransactions to a new `v3-update` event\n // In the future, we can remove this dispatch method entirely and rely on the new `update` event signature which does what we want by providing the appendedTransactions\n ////////////////////////////////////////////////////////////////////////////////\n // if the editor / the view of the editor was destroyed\n // the transaction should not be dispatched as there is no view anymore.\n if (this.view.isDestroyed) {\n return;\n }\n\n if (this.isCapturingTransaction) {\n // Do the default capture behavior\n (this as any).dispatchTransaction(transaction);\n\n return;\n }\n\n const { state, transactions: appendedTransactions } =\n this.state.applyTransaction(transaction);\n const selectionHasChanged = !this.state.selection.eq(state.selection);\n\n this.emit(\"beforeTransaction\", {\n editor: this,\n transaction,\n nextState: state,\n });\n this.view.updateState(state);\n this.emit(\"transaction\", {\n editor: this,\n transaction,\n });\n\n if (selectionHasChanged) {\n this.emit(\"selectionUpdate\", {\n editor: this,\n transaction,\n });\n }\n\n const focus = transaction.getMeta(\"focus\");\n const blur = transaction.getMeta(\"blur\");\n\n if (focus) {\n this.emit(\"focus\", {\n editor: this,\n event: focus.event,\n transaction,\n });\n }\n\n if (blur) {\n this.emit(\"blur\", {\n editor: this,\n event: blur.event,\n transaction,\n });\n }\n\n if (!transaction.docChanged || transaction.getMeta(\"preventUpdate\")) {\n return;\n }\n\n this.emit(\"update\", {\n editor: this,\n transaction,\n });\n this.emit(\"v3-update\", {\n editor: this,\n transaction,\n appendedTransactions: appendedTransactions.slice(1),\n });\n }\n\n // a helper method that can enable plugins before the view has been initialized\n // currently only used for testing\n forceEnablePlugins() {\n if (this.view) {\n throw new Error(\n \"forcePluginsEnabled called after view has been initialized\",\n );\n }\n this._state = this.state.reconfigure({\n plugins: this.extensionManager.plugins,\n });\n }\n\n /**\n * Replace the default `createView` method with a custom one - which we call on mount\n */\n private createViewAlternative(\n blockNoteEditor: BlockNoteEditor<any, any, any>,\n contentComponent?: any,\n ) {\n (this as any).contentComponent = contentComponent;\n\n const markViews: any = {};\n this.extensionManager.extensions.forEach((extension) => {\n if (extension.type === \"mark\" && extension.config.addMarkView) {\n // Note: migrate to using `addMarkView` from tiptap as soon as this lands\n // (currently tiptap doesn't support markviews)\n markViews[extension.name] =\n extension.config.addMarkView(blockNoteEditor);\n }\n });\n\n this.view = new EditorView(\n { mount: this.options.element as any }, // use mount option so that we reuse the existing element instead of creating a new one\n {\n ...this.options.editorProps,\n // @ts-ignore\n dispatchTransaction: this.dispatch.bind(this),\n state: this.state,\n markViews,\n nodeViews: this.extensionManager.nodeViews,\n },\n );\n\n // `editor.view` is not yet available at this time.\n // Therefore we will add all plugins directly afterwards.\n //\n // To research: this is the default tiptap behavior, but might actually not be necessary\n // it feels like it's a workaround for plugins that don't account for the view not being available yet\n const newState = this.state.reconfigure({\n plugins: this.extensionManager.plugins,\n });\n\n this.view.updateState(newState);\n\n // emit the created event, call here manually because we blocked the default call in the constructor\n // (https://github.com/ueberdosis/tiptap/blob/45bac803283446795ad1b03f43d3746fa54a68ff/packages/core/src/Editor.ts#L117)\n this.commands.focus(\n this.options.autofocus ||\n this.options.element.getAttribute(\"data-bn-autofocus\") === \"true\",\n { scrollIntoView: false },\n );\n this.emit(\"create\", { editor: this });\n this.isInitialized = true;\n }\n\n /**\n * Mounts / unmounts the editor to a dom element\n *\n * @param element DOM element to mount to, ur null / undefined to destroy\n */\n public mount = (\n blockNoteEditor: BlockNoteEditor<any, any, any>,\n element?: HTMLElement | null,\n contentComponent?: any,\n ) => {\n if (!element) {\n this.destroy();\n } else {\n this.options.element = element;\n this.createViewAlternative(blockNoteEditor, contentComponent);\n }\n };\n}\n\n(BlockNoteTipTapEditor.prototype as any).createView = function () {\n // no-op\n // Disable default call to `createView` in the Editor constructor.\n // We should call `createView` manually only when a DOM element is available\n\n // additional fix because onPaste and onDrop depend on installing plugins in constructor which we don't support\n // (note: can probably be removed after tiptap upgrade fixed in 2.8.0)\n this.options.onPaste = this.options.onDrop = undefined;\n};\n\ndeclare module \"@tiptap/core\" {\n interface EditorEvents {\n /**\n * This is a custom event that will be emitted in Tiptap V3.\n * We use it to provide the appendedTransactions, until Tiptap V3 is released.\n */\n \"v3-update\": {\n editor: Editor;\n transaction: Transaction;\n appendedTransactions: Transaction[];\n };\n }\n}\n","import {\n AnyExtension,\n EditorOptions,\n Extension,\n getSchema,\n isNodeSelection,\n Mark,\n posToDOMRect,\n Node as TipTapNode,\n} from \"@tiptap/core\";\nimport { Node, Schema } from \"prosemirror-model\";\n// import \"./blocknote.css\";\nimport * as Y from \"yjs\";\nimport { insertBlocks } from \"../api/blockManipulation/commands/insertBlocks/insertBlocks.js\";\nimport {\n moveBlocksDown,\n moveBlocksUp,\n} from \"../api/blockManipulation/commands/moveBlocks/moveBlocks.js\";\nimport {\n canNestBlock,\n canUnnestBlock,\n nestBlock,\n unnestBlock,\n} from \"../api/blockManipulation/commands/nestBlock/nestBlock.js\";\nimport { removeAndInsertBlocks } from \"../api/blockManipulation/commands/replaceBlocks/replaceBlocks.js\";\nimport { updateBlock } from \"../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport {\n getBlock,\n getNextBlock,\n getParentBlock,\n getPrevBlock,\n} from \"../api/blockManipulation/getBlock/getBlock.js\";\nimport { insertContentAt } from \"../api/blockManipulation/insertContentAt.js\";\nimport {\n getSelection,\n getSelectionCutBlocks,\n setSelection,\n} from \"../api/blockManipulation/selections/selection.js\";\nimport {\n getTextCursorPosition,\n setTextCursorPosition,\n} from \"../api/blockManipulation/selections/textCursorPosition.js\";\nimport { createExternalHTMLExporter } from \"../api/exporters/html/externalHTMLExporter.js\";\nimport { blocksToMarkdown } from \"../api/exporters/markdown/markdownExporter.js\";\nimport { HTMLToBlocks } from \"../api/parsers/html/parseHTML.js\";\nimport {\n markdownToBlocks,\n markdownToHTML,\n} from \"../api/parsers/markdown/parseMarkdown.js\";\nimport {\n Block,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n DefaultStyleSchema,\n PartialBlock,\n} from \"../blocks/defaultBlocks.js\";\nimport type { CommentsPlugin } from \"../extensions/Comments/CommentsPlugin.js\";\nimport { FilePanelProsemirrorPlugin } from \"../extensions/FilePanel/FilePanelPlugin.js\";\nimport { FormattingToolbarProsemirrorPlugin } from \"../extensions/FormattingToolbar/FormattingToolbarPlugin.js\";\nimport { LinkToolbarProsemirrorPlugin } from \"../extensions/LinkToolbar/LinkToolbarPlugin.js\";\nimport { ShowSelectionPlugin } from \"../extensions/ShowSelection/ShowSelectionPlugin.js\";\nimport { SideMenuProsemirrorPlugin } from \"../extensions/SideMenu/SideMenuPlugin.js\";\nimport { SuggestionMenuProseMirrorPlugin } from \"../extensions/SuggestionMenu/SuggestionPlugin.js\";\nimport { TableHandlesProsemirrorPlugin } from \"../extensions/TableHandles/TableHandlesPlugin.js\";\nimport { UniqueID } from \"../extensions/UniqueID/UniqueID.js\";\nimport {\n BlockIdentifier,\n BlockNoteDOMAttributes,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n PartialInlineContent,\n Styles,\n StyleSchema,\n StyleSpecs,\n} from \"../schema/index.js\";\nimport { mergeCSSClasses } from \"../util/browser.js\";\nimport { NoInfer, UnreachableCaseError } from \"../util/typescript.js\";\n\nimport { getBlockNoteExtensions } from \"./BlockNoteExtensions.js\";\nimport { TextCursorPosition } from \"./cursorPositionTypes.js\";\n\nimport { Selection } from \"./selectionTypes.js\";\nimport { transformPasted } from \"./transformPasted.js\";\n\nimport { checkDefaultBlockTypeInSchema } from \"../blocks/defaultBlockTypeGuards.js\";\nimport { BlockNoteSchema } from \"./BlockNoteSchema.js\";\nimport {\n BlockNoteTipTapEditor,\n BlockNoteTipTapEditorOptions,\n} from \"./BlockNoteTipTapEditor.js\";\n\nimport { Dictionary } from \"../i18n/dictionary.js\";\nimport { en } from \"../i18n/locales/index.js\";\n\nimport { redo, undo } from \"@tiptap/pm/history\";\nimport {\n TextSelection,\n type Command,\n type Plugin,\n type Transaction,\n} from \"@tiptap/pm/state\";\nimport { dropCursor } from \"prosemirror-dropcursor\";\nimport { EditorView } from \"prosemirror-view\";\nimport { redoCommand, undoCommand, ySyncPluginKey } from \"y-prosemirror\";\nimport { createInternalHTMLSerializer } from \"../api/exporters/html/internalHTMLSerializer.js\";\nimport { inlineContentToNodes } from \"../api/nodeConversions/blockToNode.js\";\nimport { docToBlocks } from \"../api/nodeConversions/nodeToBlock.js\";\nimport {\n BlocksChanged,\n getBlocksChangedByTransaction,\n} from \"../api/nodeUtil.js\";\nimport { nestedListsToBlockNoteStructure } from \"../api/parsers/html/util/nestedLists.js\";\nimport { CodeBlockOptions } from \"../blocks/CodeBlockContent/CodeBlockContent.js\";\nimport type { ThreadStore, User } from \"../comments/index.js\";\nimport type { CursorPlugin } from \"../extensions/Collaboration/CursorPlugin.js\";\nimport type { ForkYDocPlugin } from \"../extensions/Collaboration/ForkYDocPlugin.js\";\nimport { EventEmitter } from \"../util/EventEmitter.js\";\nimport { BlockNoteExtension } from \"./BlockNoteExtension.js\";\n\nimport \"../style.css\";\n\n/**\n * A factory function that returns a BlockNoteExtension\n * This is useful so we can create extensions that require an editor instance\n * in the constructor\n */\nexport type BlockNoteExtensionFactory = (\n editor: BlockNoteEditor<any, any, any>,\n) => BlockNoteExtension;\n\n/**\n * We support Tiptap extensions and BlockNoteExtension based extensions\n */\nexport type SupportedExtension = AnyExtension | BlockNoteExtension;\n\nexport type BlockCache<\n BSchema extends BlockSchema = any,\n ISchema extends InlineContentSchema = any,\n SSchema extends StyleSchema = any,\n> = WeakMap<Node, Block<BSchema, ISchema, SSchema>>;\n\nexport type BlockNoteEditorOptions<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema,\n> = {\n /**\n * Whether changes to blocks (like indentation, creating lists, changing headings) should be animated or not. Defaults to `true`.\n *\n * @default true\n */\n animations?: boolean;\n\n /**\n * When enabled, allows for collaboration between multiple users.\n */\n collaboration: {\n /**\n * The Yjs XML fragment that's used for collaboration.\n */\n fragment: Y.XmlFragment;\n /**\n * The user info for the current user that's shown to other collaborators.\n */\n user: {\n name: string;\n color: string;\n };\n /**\n * A Yjs provider (used for awareness / cursor information)\n */\n provider: any;\n /**\n * Optional function to customize how cursors of users are rendered\n */\n renderCursor?: (user: any) => HTMLElement;\n /**\n * Optional flag to set when the user label should be shown with the default\n * collaboration cursor. Setting to \"always\" will always show the label,\n * while \"activity\" will only show the label when the user moves the cursor\n * or types. Defaults to \"activity\".\n */\n showCursorLabels?: \"always\" | \"activity\";\n };\n\n /**\n * Options for code blocks.\n */\n codeBlock?: CodeBlockOptions;\n\n comments: {\n threadStore: ThreadStore;\n };\n\n /**\n * Use default BlockNote font and reset the styles of <p> <li> <h1> elements etc., that are used in BlockNote.\n *\n * @default true\n */\n defaultStyles: boolean;\n\n /**\n * A dictionary object containing translations for the editor.\n */\n dictionary?: Dictionary & Record<string, any>;\n\n /**\n * Disable internal extensions (based on keys / extension name)\n */\n disableExtensions: string[];\n\n /**\n * An object containing attributes that should be added to HTML elements of the editor.\n *\n * @example { editor: { class: \"my-editor-class\" } }\n */\n domAttributes: Partial<BlockNoteDOMAttributes>;\n\n dropCursor?: (opts: {\n editor: BlockNoteEditor<\n NoInfer<BSchema>,\n NoInfer<ISchema>,\n NoInfer<SSchema>\n >;\n color?: string | false;\n width?: number;\n class?: string;\n }) => Plugin;\n\n /**\n * The content that should be in the editor when it's created, represented as an array of partial block objects.\n */\n initialContent: PartialBlock<\n NoInfer<BSchema>,\n NoInfer<ISchema>,\n NoInfer<SSchema>\n >[];\n\n /**\n * @deprecated, provide placeholders via dictionary instead\n */\n placeholders: Record<\n string | \"default\" | \"emptyDocument\",\n string | undefined\n >;\n\n /**\n * Custom paste handler that can be used to override the default paste behavior.\n * @returns The function should return `true` if the paste event was handled, otherwise it should return `false` if it should be canceled or `undefined` if it should be handled by another handler.\n *\n * @example\n * ```ts\n * pasteHandler: ({ defaultPasteHandler }) => {\n * return defaultPasteHandler({ pasteBehavior: \"prefer-html\" });\n * }\n * ```\n */\n pasteHandler?: (context: {\n event: ClipboardEvent;\n editor: BlockNoteEditor<BSchema, ISchema, SSchema>;\n /**\n * The default paste handler\n * @param context The context object\n * @returns Whether the paste event was handled or not\n */\n defaultPasteHandler: (context?: {\n /**\n * Whether to prioritize Markdown content in `text/plain` over `text/html` when pasting from the clipboard.\n * @default true\n */\n prioritizeMarkdownOverHTML?: boolean;\n /**\n * Whether to parse `text/plain` content from the clipboard as Markdown content.\n * @default true\n */\n plainTextAsMarkdown?: boolean;\n }) => boolean | undefined;\n }) => boolean | undefined;\n\n /**\n * Resolve a URL of a file block to one that can be displayed or downloaded. This can be used for creating authenticated URL or\n * implementing custom protocols / schemes\n * @returns The URL that's\n */\n resolveFileUrl: (url: string) => Promise<string>;\n\n resolveUsers: (userIds: string[]) => Promise<User[]>;\n\n schema: BlockNoteSchema<BSchema, ISchema, SSchema>;\n\n /**\n * A flag indicating whether to set an HTML ID for every block\n *\n * When set to `true`, on each block an id attribute will be set with the block id\n * Otherwise, the HTML ID attribute will not be set.\n *\n * (note that the id is always set on the `data-id` attribute)\n */\n setIdAttribute?: boolean;\n\n /**\n * The detection mode for showing the side menu - \"viewport\" always shows the\n * side menu for the block next to the mouse cursor, while \"editor\" only shows\n * it when hovering the editor or the side menu itself.\n *\n * @default \"viewport\"\n */\n sideMenuDetection: \"viewport\" | \"editor\";\n\n /**\n Select desired behavior when pressing `Tab` (or `Shift-Tab`). Specifically,\n what should happen when a user has selected multiple blocks while a toolbar\n is open:\n - `\"prefer-navigate-ui\"`: Change focus to the toolbar. The user needs to\n first press `Escape` to close the toolbar, and can then indent multiple\n blocks. Better for keyboard accessibility.\n - `\"prefer-indent\"`: Regardless of whether toolbars are open, indent the\n selection of blocks. In this case, it's not possible to navigate toolbars\n with the keyboard.\n\n @default \"prefer-navigate-ui\"\n */\n tabBehavior: \"prefer-navigate-ui\" | \"prefer-indent\";\n\n /**\n * Allows enabling / disabling features of tables.\n */\n tables?: {\n /**\n * Whether to allow splitting and merging cells within a table.\n *\n * @default false\n */\n splitCells?: boolean;\n /**\n * Whether to allow changing the background color of cells.\n *\n * @default false\n */\n cellBackgroundColor?: boolean;\n /**\n * Whether to allow changing the text color of cells.\n *\n * @default false\n */\n cellTextColor?: boolean;\n /**\n * Whether to allow changing cells into headers.\n *\n * @default false\n */\n headers?: boolean;\n };\n\n trailingBlock?: boolean;\n\n /**\n * The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).\n * This method should set when creating the editor as this is application-specific.\n *\n * `undefined` means the application doesn't support file uploads.\n *\n * @param file The file that should be uploaded.\n * @returns The URL of the uploaded file OR an object containing props that should be set on the file block (such as an id)\n */\n uploadFile: (\n file: File,\n blockId?: string,\n ) => Promise<string | Record<string, any>>;\n\n /**\n * additional tiptap options, undocumented\n */\n _tiptapOptions: Partial<EditorOptions>;\n\n /**\n * (experimental) add extra extensions to the editor\n *\n * @deprecated, should use `extensions` instead\n */\n _extensions: Record<\n string,\n | { plugin: Plugin; priority?: number }\n | ((editor: BlockNoteEditor<any, any, any>) => {\n plugin: Plugin;\n priority?: number;\n })\n >;\n\n /**\n * Register\n */\n extensions: Array<BlockNoteExtension | BlockNoteExtensionFactory>;\n\n /**\n * Boolean indicating whether the editor is in headless mode.\n * Headless mode means we can use features like importing / exporting blocks,\n * but there's no underlying editor (UI) instantiated.\n *\n * You probably don't need to set this manually, but use the `server-util` package instead that uses this option internally\n */\n _headless: boolean;\n};\n\nconst blockNoteTipTapOptions = {\n enableInputRules: true,\n enablePasteRules: true,\n enableCoreExtensions: false,\n};\n\nexport class BlockNoteEditor<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema,\n> extends EventEmitter<{\n create: void;\n}> {\n /**\n * The underlying prosemirror schema\n */\n public readonly pmSchema: Schema;\n\n /**\n * extensions that are added to the editor, can be tiptap extensions or prosemirror plugins\n */\n public extensions: Record<string, SupportedExtension> = {};\n\n /**\n * Boolean indicating whether the editor is in headless mode.\n * Headless mode means we can use features like importing / exporting blocks,\n * but there's no underlying editor (UI) instantiated.\n *\n * You probably don't need to set this manually, but use the `server-util` package instead that uses this option internally\n */\n public readonly headless: boolean = false;\n\n public readonly _tiptapEditor: Omit<BlockNoteTipTapEditor, \"view\"> & {\n view: EditorView | undefined;\n contentComponent: any;\n } = undefined as any; // TODO: Type should actually reflect that it can be `undefined` in headless mode\n\n /**\n * Used by React to store a reference to an `ElementRenderer` helper utility to make sure we can render React elements\n * in the correct context (used by `ReactRenderUtil`)\n */\n public elementRenderer: ((node: any, container: HTMLElement) => void) | null =\n null;\n\n /**\n * Cache of all blocks. This makes sure we don't have to \"recompute\" blocks if underlying Prosemirror Nodes haven't changed.\n * This is especially useful when we want to keep track of the same block across multiple operations,\n * with this cache, blocks stay the same object reference (referential equality with ===).\n */\n public blockCache: BlockCache = new WeakMap();\n\n /**\n * The dictionary contains translations for the editor.\n */\n public readonly dictionary: Dictionary & Record<string, any>;\n\n /**\n * The schema of the editor. The schema defines which Blocks, InlineContent, and Styles are available in the editor.\n */\n public readonly schema: BlockNoteSchema<BSchema, ISchema, SSchema>;\n\n public readonly blockImplementations: BlockSpecs;\n public readonly inlineContentImplementations: InlineContentSpecs;\n public readonly styleImplementations: StyleSpecs;\n\n public readonly formattingToolbar: FormattingToolbarProsemirrorPlugin;\n public readonly linkToolbar: LinkToolbarProsemirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly sideMenu: SideMenuProsemirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly suggestionMenus: SuggestionMenuProseMirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly filePanel?: FilePanelProsemirrorPlugin<ISchema, SSchema>;\n public readonly tableHandles?: TableHandlesProsemirrorPlugin<\n ISchema,\n SSchema\n >;\n public readonly comments?: CommentsPlugin;\n\n private readonly showSelectionPlugin: ShowSelectionPlugin;\n\n /**\n * The plugin for forking a document, only defined if in collaboration mode\n */\n public readonly forkYDocPlugin?: ForkYDocPlugin;\n /**\n * The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).\n * This method should set when creating the editor as this is application-specific.\n *\n * `undefined` means the application doesn't support file uploads.\n *\n * @param file The file that should be uploaded.\n * @returns The URL of the uploaded file OR an object containing props that should be set on the file block (such as an id)\n */\n public readonly uploadFile:\n | ((file: File, blockId?: string) => Promise<string | Record<string, any>>)\n | undefined;\n\n private onUploadStartCallbacks: ((blockId?: string) => void)[] = [];\n private onUploadEndCallbacks: ((blockId?: string) => void)[] = [];\n\n public readonly resolveFileUrl?: (url: string) => Promise<string>;\n public readonly resolveUsers?: (userIds: string[]) => Promise<User[]>;\n /**\n * Editor settings\n */\n public readonly settings: {\n tables: {\n splitCells: boolean;\n cellBackgroundColor: boolean;\n cellTextColor: boolean;\n headers: boolean;\n };\n codeBlock: CodeBlockOptions;\n };\n\n public static create<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema,\n >(options: Partial<BlockNoteEditorOptions<BSchema, ISchema, SSchema>> = {}) {\n return new BlockNoteEditor<BSchema, ISchema, SSchema>(options);\n }\n\n protected constructor(\n protected readonly options: Partial<BlockNoteEditorOptions<any, any, any>>,\n ) {\n super();\n const anyOpts = options as any;\n if (anyOpts.onEditorContentChange) {\n throw new Error(\n \"onEditorContentChange initialization option is deprecated, use <BlockNoteView onChange={...} />, the useEditorChange(...) hook, or editor.onChange(...)\",\n );\n }\n\n if (anyOpts.onTextCursorPositionChange) {\n throw new Error(\n \"onTextCursorPositionChange initialization option is deprecated, use <BlockNoteView onSelectionChange={...} />, the useEditorSelectionChange(...) hook, or editor.onSelectionChange(...)\",\n );\n }\n\n if (anyOpts.onEditorReady) {\n throw new Error(\n \"onEditorReady is deprecated. Editor is immediately ready for use after creation.\",\n );\n }\n\n if (anyOpts.editable) {\n throw new Error(\n \"editable initialization option is deprecated, use <BlockNoteView editable={true/false} />, or alternatively editor.isEditable = true/false\",\n );\n }\n\n this.dictionary = options.dictionary || en;\n this.settings = {\n tables: {\n splitCells: options?.tables?.splitCells ?? false,\n cellBackgroundColor: options?.tables?.cellBackgroundColor ?? false,\n cellTextColor: options?.tables?.cellTextColor ?? false,\n headers: options?.tables?.headers ?? false,\n },\n codeBlock: {\n indentLineWithTab: options?.codeBlock?.indentLineWithTab ?? true,\n defaultLanguage: options?.codeBlock?.defaultLanguage ?? \"text\",\n supportedLanguages: options?.codeBlock?.supportedLanguages ?? {},\n createHighlighter: options?.codeBlock?.createHighlighter ?? undefined,\n },\n };\n\n // apply defaults\n const newOptions = {\n defaultStyles: true,\n schema: options.schema || BlockNoteSchema.create(),\n _headless: false,\n ...options,\n placeholders: {\n ...this.dictionary.placeholders,\n ...options.placeholders,\n },\n };\n\n if (newOptions.comments && !newOptions.resolveUsers) {\n throw new Error(\"resolveUsers is required when using comments\");\n }\n\n this.resolveUsers = newOptions.resolveUsers;\n\n // @ts-ignore\n this.schema = newOptions.schema;\n this.blockImplementations = newOptions.schema.blockSpecs;\n this.inlineContentImplementations = newOptions.schema.inlineContentSpecs;\n this.styleImplementations = newOptions.schema.styleSpecs;\n\n this.extensions = getBlockNoteExtensions({\n editor: this,\n domAttributes: newOptions.domAttributes || {},\n blockSpecs: this.schema.blockSpecs,\n styleSpecs: this.schema.styleSpecs,\n inlineContentSpecs: this.schema.inlineContentSpecs,\n collaboration: newOptions.collaboration,\n trailingBlock: newOptions.trailingBlock,\n disableExtensions: newOptions.disableExtensions,\n setIdAttribute: newOptions.setIdAttribute,\n animations: newOptions.animations ?? true,\n tableHandles: checkDefaultBlockTypeInSchema(\"table\", this),\n dropCursor: this.options.dropCursor ?? dropCursor,\n placeholders: newOptions.placeholders,\n tabBehavior: newOptions.tabBehavior,\n sideMenuDetection: newOptions.sideMenuDetection || \"viewport\",\n comments: newOptions.comments,\n pasteHandler: newOptions.pasteHandler,\n });\n\n // add extensions from _tiptapOptions\n (newOptions._tiptapOptions?.extensions || []).forEach((ext) => {\n this.extensions[ext.name] = ext;\n });\n\n // add extensions from options\n for (let ext of newOptions.extensions || []) {\n if (typeof ext === \"function\") {\n // factory\n ext = ext(this);\n }\n const key = (ext.constructor as any).key();\n if (!key) {\n throw new Error(\n `Extension ${ext.constructor.name} does not have a key method`,\n );\n }\n if (this.extensions[key]) {\n throw new Error(\n `Extension ${ext.constructor.name} already exists with key ${key}`,\n );\n }\n this.extensions[key] = ext;\n }\n\n // (when passed in via the deprecated `_extensions` option)\n Object.entries(newOptions._extensions || {}).forEach(([key, ext]) => {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const editor = this;\n\n const instance = typeof ext === \"function\" ? ext(editor) : ext;\n if (!(\"plugin\" in instance)) {\n // Assume it is an Extension/Mark/Node\n this.extensions[key] = instance;\n return;\n }\n\n this.extensions[key] = new (class extends BlockNoteExtension {\n public static key() {\n return key;\n }\n constructor() {\n super();\n this.addProsemirrorPlugin(instance.plugin);\n }\n public get priority() {\n return instance.priority;\n }\n })();\n });\n\n this.formattingToolbar = this.extensions[\"formattingToolbar\"] as any;\n this.linkToolbar = this.extensions[\"linkToolbar\"] as any;\n this.sideMenu = this.extensions[\"sideMenu\"] as any;\n this.suggestionMenus = this.extensions[\"suggestionMenus\"] as any;\n this.filePanel = this.extensions[\"filePanel\"] as any;\n this.tableHandles = this.extensions[\"tableHandles\"] as any;\n this.comments = this.extensions[\"comments\"] as any;\n this.showSelectionPlugin = this.extensions[\"showSelection\"] as any;\n this.forkYDocPlugin = this.extensions[\"forkYDocPlugin\"] as any;\n\n if (newOptions.uploadFile) {\n const uploadFile = newOptions.uploadFile;\n this.uploadFile = async (file, blockId) => {\n this.onUploadStartCallbacks.forEach((callback) =>\n callback.apply(this, [blockId]),\n );\n try {\n return await uploadFile(file, blockId);\n } finally {\n this.onUploadEndCallbacks.forEach((callback) =>\n callback.apply(this, [blockId]),\n );\n }\n };\n }\n\n this.resolveFileUrl = newOptions.resolveFileUrl;\n this.headless = newOptions._headless;\n\n const collaborationEnabled =\n \"ySyncPlugin\" in this.extensions ||\n \"liveblocksExtension\" in this.extensions;\n\n if (collaborationEnabled && newOptions.initialContent) {\n // eslint-disable-next-line no-console\n console.warn(\n \"When using Collaboration, initialContent might cause conflicts, because changes should come from the collaboration provider\",\n );\n }\n\n const initialContent =\n newOptions.initialContent ||\n (collaborationEnabled\n ? [\n {\n type: \"paragraph\",\n id: \"initialBlockId\",\n },\n ]\n : [\n {\n type: \"paragraph\",\n id: UniqueID.options.generateID(),\n },\n ]);\n\n if (!Array.isArray(initialContent) || initialContent.length === 0) {\n throw new Error(\n \"initialContent must be a non-empty array of blocks, received: \" +\n initialContent,\n );\n }\n\n const tiptapExtensions = [\n ...Object.entries(this.extensions).map(([key, ext]) => {\n if (\n ext instanceof Extension ||\n ext instanceof TipTapNode ||\n ext instanceof Mark\n ) {\n // tiptap extension\n return ext;\n }\n\n if (ext instanceof BlockNoteExtension && !ext.plugins.length) {\n return undefined;\n }\n\n // \"blocknote\" extensions (prosemirror plugins)\n return Extension.create({\n name: key,\n priority: ext.priority,\n addProseMirrorPlugins: () => ext.plugins,\n });\n }),\n ].filter((ext): ext is Extension => ext !== undefined);\n\n const tiptapOptions: BlockNoteTipTapEditorOptions = {\n ...blockNoteTipTapOptions,\n ...newOptions._tiptapOptions,\n content: initialContent,\n extensions: tiptapExtensions,\n editorProps: {\n ...newOptions._tiptapOptions?.editorProps,\n attributes: {\n // As of TipTap v2.5.0 the tabIndex is removed when the editor is not\n // editable, so you can't focus it. We want to revert this as we have\n // UI behaviour that relies on it.\n tabIndex: \"0\",\n ...newOptions._tiptapOptions?.editorProps?.attributes,\n ...newOptions.domAttributes?.editor,\n class: mergeCSSClasses(\n \"bn-editor\",\n newOptions.defaultStyles ? \"bn-default-styles\" : \"\",\n newOptions.domAttributes?.editor?.class || \"\",\n ),\n },\n transformPasted,\n },\n };\n\n if (!this.headless) {\n this._tiptapEditor = BlockNoteTipTapEditor.create(\n tiptapOptions,\n this.schema.styleSchema,\n ) as BlockNoteTipTapEditor & {\n view: any;\n contentComponent: any;\n };\n this.pmSchema = this._tiptapEditor.schema;\n } else {\n // In headless mode, we don't instantiate an underlying TipTap editor,\n // but we still need the schema\n this.pmSchema = getSchema(tiptapOptions.extensions!);\n }\n this.pmSchema.cached.blockNoteEditor = this;\n this.emit(\"create\");\n }\n\n /**\n * Stores the currently active transaction, which is the accumulated transaction from all {@link dispatch} calls during a {@link transact} calls\n */\n private activeTransaction: Transaction | null = null;\n\n /**\n * Execute a prosemirror command. This is mostly for backwards compatibility with older code.\n *\n * @note You should prefer the {@link transact} method when possible, as it will automatically handle the dispatching of the transaction and work across blocknote transactions.\n *\n * @example\n * ```ts\n * editor.exec((state, dispatch, view) => {\n * dispatch(state.tr.insertText(\"Hello, world!\"));\n * });\n * ```\n */\n public exec(command: Command) {\n if (this.activeTransaction) {\n throw new Error(\n \"`exec` should not be called within a `transact` call, move the `exec` call outside of the `transact` call\",\n );\n }\n const state = this._tiptapEditor.state;\n const view = this._tiptapEditor.view;\n const dispatch = (tr: Transaction) => this._tiptapEditor.dispatch(tr);\n\n return command(state, dispatch, view);\n }\n\n /**\n * Check if a command can be executed. A command should return `false` if it is not valid in the current state.\n *\n * @example\n * ```ts\n * if (editor.canExec(command)) {\n * // show button\n * } else {\n * // hide button\n * }\n * ```\n */\n public canExec(command: Command): boolean {\n if (this.activeTransaction) {\n throw new Error(\n \"`canExec` should not be called within a `transact` call, move the `canExec` call outside of the `transact` call\",\n );\n }\n const state = this._tiptapEditor.state;\n const view = this._tiptapEditor.view;\n\n return command(state, undefined, view);\n }\n\n /**\n * Execute a function within a \"blocknote transaction\".\n * All changes to the editor within the transaction will be grouped together, so that\n * we can dispatch them as a single operation (thus creating only a single undo step)\n *\n * @note There is no need to dispatch the transaction, as it will be automatically dispatched when the callback is complete.\n *\n * @example\n * ```ts\n * // All changes to the editor will be grouped together\n * editor.transact((tr) => {\n * tr.insertText(\"Hello, world!\");\n * // These two operations will be grouped together in a single undo step\n * editor.transact((tr) => {\n * tr.insertText(\"Hello, world!\");\n * });\n * });\n * ```\n */\n public transact<T>(\n callback: (\n /**\n * The current active transaction, this will automatically be dispatched to the editor when the callback is complete\n * If another `transact` call is made within the callback, it will be passed the same transaction as the parent call.\n */\n tr: Transaction,\n ) => T,\n ): T {\n if (this.activeTransaction) {\n // Already in a transaction, so we can just callback immediately\n return callback(this.activeTransaction);\n }\n\n try {\n // Enter transaction mode, by setting a starting transaction\n this.activeTransaction = this._tiptapEditor.state.tr;\n\n // Capture all dispatch'd transactions\n const result = callback(this.activeTransaction);\n\n // Any transactions captured by the `dispatch` call will be stored in `this.activeTransaction`\n const activeTr = this.activeTransaction;\n\n this.activeTransaction = null;\n if (\n activeTr &&\n // Only dispatch if the transaction was actually modified in some way\n (activeTr.docChanged ||\n activeTr.selectionSet ||\n activeTr.scrolledIntoView ||\n activeTr.storedMarksSet ||\n !activeTr.isGeneric)\n ) {\n // Dispatch the transaction if it was modified\n this._tiptapEditor.dispatch(activeTr);\n }\n\n return result;\n } finally {\n // We wrap this in a finally block to ensure we don't disable future transactions just because of an error in the callback\n this.activeTransaction = null;\n }\n }\n\n // TO DISCUSS\n /**\n * Shorthand to get a typed extension from the editor, by\n * just passing in the extension class.\n *\n * @param ext - The extension class to get\n * @param key - optional, the key of the extension in the extensions object (defaults to the extension name)\n * @returns The extension instance\n */\n public extension<T extends BlockNoteExtension>(\n ext: { new (...args: any[]): T } & typeof BlockNoteExtension,\n key = ext.key(),\n ): T {\n const extension = this.extensions[key] as T;\n if (!extension) {\n throw new Error(`Extension ${key} not found`);\n }\n return extension;\n }\n\n /**\n * Mount the editor to a parent DOM element. Call mount(undefined) to clean up\n *\n * @warning Not needed to call manually when using React, use BlockNoteView to take care of mounting\n */\n public mount = (\n parentElement?: HTMLElement | null,\n contentComponent?: any,\n ) => {\n this._tiptapEditor.mount(this, parentElement, contentComponent);\n };\n\n /**\n * Get the underlying prosemirror state\n * @note Prefer using `editor.transact` to read the current editor state, as that will ensure the state is up to date\n * @see https://prosemirror.net/docs/ref/#state.EditorState\n */\n public get prosemirrorState() {\n if (this.activeTransaction) {\n throw new Error(\n \"`prosemirrorState` should not be called within a `transact` call, move the `prosemirrorState` call outside of the `transact` call or use `editor.transact` to read the current editor state\",\n );\n }\n return this._tiptapEditor.state;\n }\n\n /**\n * Get the underlying prosemirror view\n * @see https://prosemirror.net/docs/ref/#view.EditorView\n */\n public get prosemirrorView() {\n return this._tiptapEditor.view;\n }\n\n public get domElement() {\n return this.prosemirrorView?.dom as HTMLDivElement | undefined;\n }\n\n public isFocused() {\n return this.prosemirrorView?.hasFocus() || false;\n }\n\n public focus() {\n this.prosemirrorView?.focus();\n }\n\n public onUploadStart(callback: (blockId?: string) => void) {\n this.onUploadStartCallbacks.push(callback);\n\n return () => {\n const index = this.onUploadStartCallbacks.indexOf(callback);\n if (index > -1) {\n this.onUploadStartCallbacks.splice(index, 1);\n }\n };\n }\n\n public onUploadEnd(callback: (blockId?: string) => void) {\n this.onUploadEndCallbacks.push(callback);\n\n return () => {\n const index = this.onUploadEndCallbacks.indexOf(callback);\n if (index > -1) {\n this.onUploadEndCallbacks.splice(index, 1);\n }\n };\n }\n\n /**\n * @deprecated, use `editor.document` instead\n */\n public get topLevelBlocks(): Block<BSchema, ISchema, SSchema>[] {\n return this.document;\n }\n\n /**\n * Gets a snapshot of all top-level (non-nested) blocks in the editor.\n * @returns A snapshot of all top-level (non-nested) blocks in the editor.\n */\n public get document(): Block<BSchema, ISchema, SSchema>[] {\n return this.transact((tr) => {\n return docToBlocks(tr.doc, this.pmSchema);\n });\n }\n\n /**\n * Gets a snapshot of an existing block from the editor.\n * @param blockIdentifier The identifier of an existing block that should be\n * retrieved.\n * @returns The block that matches the identifier, or `undefined` if no\n * matching block was found.\n */\n public getBlock(\n blockIdentifier: BlockIdentifier,\n ): Block<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getBlock(tr.doc, blockIdentifier));\n }\n\n /**\n * Gets a snapshot of the previous sibling of an existing block from the\n * editor.\n * @param blockIdentifier The identifier of an existing block for which the\n * previous sibling should be retrieved.\n * @returns The previous sibling of the block that matches the identifier.\n * `undefined` if no matching block was found, or it's the first child/block\n * in the document.\n */\n public getPrevBlock(\n blockIdentifier: BlockIdentifier,\n ): Block<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getPrevBlock(tr.doc, blockIdentifier));\n }\n\n /**\n * Gets a snapshot of the next sibling of an existing block from the editor.\n * @param blockIdentifier The identifier of an existing block for which the\n * next sibling should be retrieved.\n * @returns The next sibling of the block that matches the identifier.\n * `undefined` if no matching block was found, or it's the last child/block in\n * the document.\n */\n public getNextBlock(\n blockIdentifier: BlockIdentifier,\n ): Block<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getNextBlock(tr.doc, blockIdentifier));\n }\n\n /**\n * Gets a snapshot of the parent of an existing block from the editor.\n * @param blockIdentifier The identifier of an existing block for which the\n * parent should be retrieved.\n * @returns The parent of the block that matches the identifier. `undefined`\n * if no matching block was found, or the block isn't nested.\n */\n public getParentBlock(\n blockIdentifier: BlockIdentifier,\n ): Block<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getParentBlock(tr.doc, blockIdentifier));\n }\n\n /**\n * Traverses all blocks in the editor depth-first, and executes a callback for each.\n * @param callback The callback to execute for each block. Returning `false` stops the traversal.\n * @param reverse Whether the blocks should be traversed in reverse order.\n */\n public forEachBlock(\n callback: (block: Block<BSchema, ISchema, SSchema>) => boolean,\n reverse = false,\n ): void {\n const blocks = this.document.slice();\n\n if (reverse) {\n blocks.reverse();\n }\n\n function traverseBlockArray(\n blockArray: Block<BSchema, ISchema, SSchema>[],\n ): boolean {\n for (const block of blockArray) {\n if (callback(block) === false) {\n return false;\n }\n\n const children = reverse\n ? block.children.slice().reverse()\n : block.children;\n\n if (!traverseBlockArray(children)) {\n return false;\n }\n }\n\n return true;\n }\n\n traverseBlockArray(blocks);\n }\n\n /**\n * Executes a callback whenever the editor's contents change.\n * @param callback The callback to execute.\n *\n * @deprecated use {@link BlockNoteEditor.onChange} instead\n */\n public onEditorContentChange(callback: () => void) {\n this._tiptapEditor.on(\"update\", callback);\n }\n\n /**\n * Executes a callback whenever the editor's selection changes.\n * @param callback The callback to execute.\n *\n * @deprecated use `onSelectionChange` instead\n */\n public onEditorSelectionChange(callback: () => void) {\n this._tiptapEditor.on(\"selectionUpdate\", callback);\n }\n\n /**\n * Gets a snapshot of the current text cursor position.\n * @returns A snapshot of the current text cursor position.\n */\n public getTextCursorPosition(): TextCursorPosition<\n BSchema,\n ISchema,\n SSchema\n > {\n return this.transact((tr) => getTextCursorPosition(tr));\n }\n\n /**\n * Sets the text cursor position to the start or end of an existing block. Throws an error if the target block could\n * not be found.\n * @param targetBlock The identifier of an existing block that the text cursor should be moved to.\n * @param placement Whether the text cursor should be placed at the start or end of the block.\n */\n public setTextCursorPosition(\n targetBlock: BlockIdentifier,\n placement: \"start\" | \"end\" = \"start\",\n ) {\n return this.transact((tr) =>\n setTextCursorPosition(tr, targetBlock, placement),\n );\n }\n\n /**\n * Gets a snapshot of the current selection. This contains all blocks (included nested blocks)\n * that the selection spans across.\n *\n * If the selection starts / ends halfway through a block, the returned data will contain the entire block.\n */\n public getSelection(): Selection<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getSelection(tr));\n }\n\n /**\n * Gets a snapshot of the current selection. This contains all blocks (included nested blocks)\n * that the selection spans across.\n *\n * If the selection starts / ends halfway through a block, the returned block will be\n * only the part of the block that is included in the selection.\n */\n public getSelectionCutBlocks() {\n return this.transact((tr) => getSelectionCutBlocks(tr));\n }\n\n /**\n * Sets the selection to a range of blocks.\n * @param startBlock The identifier of the block that should be the start of the selection.\n * @param endBlock The identifier of the block that should be the end of the selection.\n */\n public setSelection(startBlock: BlockIdentifier, endBlock: BlockIdentifier) {\n return this.transact((tr) => setSelection(tr, startBlock, endBlock));\n }\n\n /**\n * Checks if the editor is currently editable, or if it's locked.\n * @returns True if the editor is editable, false otherwise.\n */\n public get isEditable(): boolean {\n if (!this._tiptapEditor) {\n if (!this.headless) {\n throw new Error(\"no editor, but also not headless?\");\n }\n return false;\n }\n return this._tiptapEditor.isEditable === undefined\n ? true\n : this._tiptapEditor.isEditable;\n }\n\n /**\n * Makes the editor editable or locks it, depending on the argument passed.\n * @param editable True to make the editor editable, or false to lock it.\n */\n public set isEditable(editable: boolean) {\n if (!this._tiptapEditor) {\n if (!this.headless) {\n throw new Error(\"no editor, but also not headless?\");\n }\n // not relevant on headless\n return;\n }\n if (this._tiptapEditor.options.editable !== editable) {\n this._tiptapEditor.setEditable(editable);\n }\n }\n\n /**\n * Inserts new blocks into the editor. If a block's `id` is undefined, BlockNote generates one automatically. Throws an\n * error if the reference block could not be found.\n * @param blocksToInsert An array of partial blocks that should be inserted.\n * @param referenceBlock An identifier for an existing block, at which the new blocks should be inserted.\n * @param placement Whether the blocks should be inserted just before, just after, or nested inside the\n * `referenceBlock`.\n */\n public insertBlocks(\n blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" = \"before\",\n ) {\n return this.transact((tr) =>\n insertBlocks(tr, blocksToInsert, referenceBlock, placement),\n );\n }\n\n /**\n * Updates an existing block in the editor. Since updatedBlock is a PartialBlock object, some fields might not be\n * defined. These undefined fields are kept as-is from the existing block. Throws an error if the block to update could\n * not be found.\n * @param blockToUpdate The block that should be updated.\n * @param update A partial block which defines how the existing block should be changed.\n */\n public updateBlock(\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema, ISchema, SSchema>,\n ) {\n return this.transact((tr) => updateBlock(tr, blockToUpdate, update));\n }\n\n /**\n * Removes existing blocks from the editor. Throws an error if any of the blocks could not be found.\n * @param blocksToRemove An array of identifiers for existing blocks that should be removed.\n */\n public removeBlocks(blocksToRemove: BlockIdentifier[]) {\n return this.transact(\n (tr) => removeAndInsertBlocks(tr, blocksToRemove, []).removedBlocks,\n );\n }\n\n /**\n * Replaces existing blocks in the editor with new blocks. If the blocks that should be removed are not adjacent or\n * are at different nesting levels, `blocksToInsert` will be inserted at the position of the first block in\n * `blocksToRemove`. Throws an error if any of the blocks to remove could not be found.\n * @param blocksToRemove An array of blocks that should be replaced.\n * @param blocksToInsert An array of partial blocks to replace the old ones with.\n */\n public replaceBlocks(\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[],\n ) {\n return this.transact((tr) =>\n removeAndInsertBlocks(tr, blocksToRemove, blocksToInsert),\n );\n }\n\n /**\n * Undo the last action.\n */\n public undo() {\n if (this.options.collaboration) {\n return this.exec(undoCommand);\n }\n\n return this.exec(undo);\n }\n\n /**\n * Redo the last action.\n */\n public redo() {\n if (this.options.collaboration) {\n return this.exec(redoCommand);\n }\n return this.exec(redo);\n }\n\n /**\n * Insert a piece of content at the current cursor position.\n *\n * @param content can be a string, or array of partial inline content elements\n */\n public insertInlineContent(\n content: PartialInlineContent<ISchema, SSchema>,\n { updateSelection = false }: { updateSelection?: boolean } = {},\n ) {\n const nodes = inlineContentToNodes(content, this.pmSchema);\n\n this.transact((tr) => {\n insertContentAt(\n tr,\n {\n from: tr.selection.from,\n to: tr.selection.to,\n },\n nodes,\n {\n updateSelection,\n },\n );\n });\n }\n\n /**\n * Gets the active text styles at the text cursor position or at the end of the current selection if it's active.\n */\n public getActiveStyles() {\n return this.transact((tr) => {\n const styles: Styles<SSchema> = {};\n const marks = tr.selection.$to.marks();\n\n for (const mark of marks) {\n const config = this.schema.styleSchema[mark.type.name];\n if (!config) {\n if (\n // Links are not considered styles in blocknote\n mark.type.name !== \"link\" &&\n // \"blocknoteIgnore\" tagged marks (such as comments) are also not considered BlockNote \"styles\"\n !mark.type.spec.blocknoteIgnore\n ) {\n // eslint-disable-next-line no-console\n console.warn(\"mark not found in styleschema\", mark.type.name);\n }\n\n continue;\n }\n if (config.propSchema === \"boolean\") {\n (styles as any)[config.type] = true;\n } else {\n (styles as any)[config.type] = mark.attrs.stringValue;\n }\n }\n\n return styles;\n });\n }\n\n /**\n * Adds styles to the currently selected content.\n * @param styles The styles to add.\n */\n public addStyles(styles: Styles<SSchema>) {\n for (const [style, value] of Object.entries(styles)) {\n const config = this.schema.styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n this._tiptapEditor.commands.setMark(style);\n } else if (config.propSchema === \"string\") {\n this._tiptapEditor.commands.setMark(style, { stringValue: value });\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n /**\n * Removes styles from the currently selected content.\n * @param styles The styles to remove.\n */\n public removeStyles(styles: Styles<SSchema>) {\n for (const style of Object.keys(styles)) {\n this._tiptapEditor.commands.unsetMark(style);\n }\n }\n\n /**\n * Toggles styles on the currently selected content.\n * @param styles The styles to toggle.\n */\n public toggleStyles(styles: Styles<SSchema>) {\n for (const [style, value] of Object.entries(styles)) {\n const config = this.schema.styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n this._tiptapEditor.commands.toggleMark(style);\n } else if (config.propSchema === \"string\") {\n this._tiptapEditor.commands.toggleMark(style, { stringValue: value });\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n /**\n * Gets the currently selected text.\n */\n public getSelectedText() {\n return this.transact((tr) => {\n return tr.doc.textBetween(tr.selection.from, tr.selection.to);\n });\n }\n\n /**\n * Gets the URL of the last link in the current selection, or `undefined` if there are no links in the selection.\n */\n public getSelectedLinkUrl() {\n return this._tiptapEditor.getAttributes(\"link\").href as string | undefined;\n }\n\n /**\n * Creates a new link to replace the selected content.\n * @param url The link URL.\n * @param text The text to display the link with.\n */\n public createLink(url: string, text?: string) {\n if (url === \"\") {\n return;\n }\n const mark = this.pmSchema.mark(\"link\", { href: url });\n this.transact((tr) => {\n const { from, to } = tr.selection;\n\n if (text) {\n tr.insertText(text, from, to).addMark(from, from + text.length, mark);\n } else {\n tr.setSelection(TextSelection.create(tr.doc, to)).addMark(\n from,\n to,\n mark,\n );\n }\n });\n }\n\n /**\n * Checks if the block containing the text cursor can be nested.\n */\n public canNestBlock() {\n return canNestBlock(this);\n }\n\n /**\n * Nests the block containing the text cursor into the block above it.\n */\n public nestBlock() {\n nestBlock(this);\n }\n\n /**\n * Checks if the block containing the text cursor is nested.\n */\n public canUnnestBlock() {\n return canUnnestBlock(this);\n }\n\n /**\n * Lifts the block containing the text cursor out of its parent.\n */\n public unnestBlock() {\n unnestBlock(this);\n }\n\n /**\n * Moves the selected blocks up. If the previous block has children, moves\n * them to the end of its children. If there is no previous block, but the\n * current blocks share a common parent, moves them out of & before it.\n */\n public moveBlocksUp() {\n return moveBlocksUp(this);\n }\n\n /**\n * Moves the selected blocks down. If the next block has children, moves\n * them to the start of its children. If there is no next block, but the\n * current blocks share a common parent, moves them out of & after it.\n */\n public moveBlocksDown() {\n return moveBlocksDown(this);\n }\n\n /**\n * Exports blocks into a simplified HTML string. To better conform to HTML standards, children of blocks which aren't list\n * items are un-nested in the output HTML.\n *\n * @param blocks An array of blocks that should be serialized into HTML.\n * @returns The blocks, serialized as an HTML string.\n */\n public async blocksToHTMLLossy(\n blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document,\n ): Promise<string> {\n const exporter = createExternalHTMLExporter(this.pmSchema, this);\n return exporter.exportBlocks(blocks, {});\n }\n\n /**\n * Serializes blocks into an HTML string in the format that would normally be rendered by the editor.\n *\n * Use this method if you want to server-side render HTML (for example, a blog post that has been edited in BlockNote)\n * and serve it to users without loading the editor on the client (i.e.: displaying the blog post)\n *\n * @param blocks An array of blocks that should be serialized into HTML.\n * @returns The blocks, serialized as an HTML string.\n */\n public async blocksToFullHTML(\n blocks: PartialBlock<BSchema, ISchema, SSchema>[],\n ): Promise<string> {\n const exporter = createInternalHTMLSerializer(this.pmSchema, this);\n return exporter.serializeBlocks(blocks, {});\n }\n /**\n * Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and\n * `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote\n * doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.\n * @param html The HTML string to parse blocks from.\n * @returns The blocks parsed from the HTML string.\n */\n public async tryParseHTMLToBlocks(\n html: string,\n ): Promise<Block<BSchema, ISchema, SSchema>[]> {\n return HTMLToBlocks(html, this.pmSchema);\n }\n\n /**\n * Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of\n * BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.\n * @param blocks An array of blocks that should be serialized into Markdown.\n * @returns The blocks, serialized as a Markdown string.\n */\n public async blocksToMarkdownLossy(\n blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document,\n ): Promise<string> {\n return blocksToMarkdown(blocks, this.pmSchema, this, {});\n }\n\n /**\n * Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on\n * Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it\n * as text.\n * @param markdown The Markdown string to parse blocks from.\n * @returns The blocks parsed from the Markdown string.\n */\n public async tryParseMarkdownToBlocks(\n markdown: string,\n ): Promise<Block<BSchema, ISchema, SSchema>[]> {\n return markdownToBlocks(markdown, this.pmSchema);\n }\n\n /**\n * Updates the user info for the current user that's shown to other collaborators.\n */\n public updateCollaborationUserInfo(user: { name: string; color: string }) {\n if (!this.options.collaboration) {\n throw new Error(\n \"Cannot update collaboration user info when collaboration is disabled.\",\n );\n }\n\n (this.extensions[\"yCursorPlugin\"] as CursorPlugin).updateUser(user);\n }\n\n /**\n * A callback function that runs whenever the editor's contents change.\n *\n * @param callback The callback to execute.\n * @returns A function to remove the callback.\n */\n public onChange(\n callback: (\n editor: BlockNoteEditor<BSchema, ISchema, SSchema>,\n context: {\n /**\n * Returns the blocks that were inserted, updated, or deleted by the change that occurred.\n */\n getChanges(): BlocksChanged<BSchema, ISchema, SSchema>;\n },\n ) => void,\n ) {\n if (this.headless) {\n // Note: would be nice if this is possible in headless mode as well\n return;\n }\n\n const cb = ({\n transaction,\n appendedTransactions,\n }: {\n transaction: Transaction;\n appendedTransactions: Transaction[];\n }) => {\n callback(this, {\n getChanges: () =>\n getBlocksChangedByTransaction(transaction, appendedTransactions),\n });\n };\n\n this._tiptapEditor.on(\"v3-update\", cb);\n\n return () => {\n this._tiptapEditor.off(\"v3-update\", cb);\n };\n }\n\n /**\n * A callback function that runs whenever the text cursor position or selection changes.\n *\n * @param callback The callback to execute.\n * @returns A function to remove the callback.\n */\n public onSelectionChange(\n callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void,\n includeSelectionChangedByRemote?: boolean,\n ) {\n if (this.headless) {\n return;\n }\n\n const cb = (e: { transaction: Transaction }) => {\n if (\n e.transaction.getMeta(ySyncPluginKey) &&\n !includeSelectionChangedByRemote\n ) {\n // selection changed because of a yjs sync (i.e.: other user was typing)\n // we don't want to trigger the callback in this case\n return;\n }\n callback(this);\n };\n\n this._tiptapEditor.on(\"selectionUpdate\", cb);\n\n return () => {\n this._tiptapEditor.off(\"selectionUpdate\", cb);\n };\n }\n\n /**\n * A callback function that runs when the editor has been initialized.\n *\n * This can be useful for plugins to initialize themselves after the editor has been initialized.\n */\n public onCreate(callback: () => void) {\n this.on(\"create\", callback);\n\n return () => {\n this.off(\"create\", callback);\n };\n }\n\n public getSelectionBoundingBox() {\n if (!this.prosemirrorView) {\n return undefined;\n }\n\n const { selection } = this.prosemirrorState;\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n if (isNodeSelection(selection)) {\n const node = this.prosemirrorView.nodeDOM(from) as HTMLElement;\n if (node) {\n return node.getBoundingClientRect();\n }\n }\n\n return posToDOMRect(this.prosemirrorView, from, to);\n }\n\n public get isEmpty() {\n const doc = this.document;\n // Note: only works for paragraphs as default blocks (but for now this is default in blocknote)\n // checking prosemirror directly might be faster\n return (\n doc.length === 0 ||\n (doc.length === 1 &&\n doc[0].type === \"paragraph\" &&\n (doc[0].content as any).length === 0)\n );\n }\n\n public openSuggestionMenu(\n triggerCharacter: string,\n pluginState?: {\n deleteTriggerCharacter?: boolean;\n ignoreQueryLength?: boolean;\n },\n ) {\n if (!this.prosemirrorView) {\n return;\n }\n\n this.focus();\n this.transact((tr) => {\n if (pluginState?.deleteTriggerCharacter) {\n tr.insertText(triggerCharacter);\n }\n tr.scrollIntoView().setMeta(this.suggestionMenus.plugins[0], {\n triggerCharacter: triggerCharacter,\n deleteTriggerCharacter: pluginState?.deleteTriggerCharacter || false,\n ignoreQueryLength: pluginState?.ignoreQueryLength || false,\n });\n });\n }\n\n // `forceSelectionVisible` determines whether the editor selection is shows\n // even when the editor is not focused. This is useful for e.g. creating new\n // links, so the user still sees the affected content when an input field is\n // focused.\n // TODO: Reconsider naming?\n public getForceSelectionVisible() {\n return this.showSelectionPlugin.getEnabled();\n }\n\n public setForceSelectionVisible(forceSelectionVisible: boolean) {\n this.showSelectionPlugin.setEnabled(forceSelectionVisible);\n }\n\n /**\n * This will convert HTML into a format that is compatible with BlockNote.\n */\n private convertHtmlToBlockNoteHtml(html: string) {\n const htmlNode = nestedListsToBlockNoteStructure(html.trim());\n return htmlNode.innerHTML;\n }\n\n /**\n * Paste HTML into the editor. Defaults to converting HTML to BlockNote HTML.\n * @param html The HTML to paste.\n * @param raw Whether to paste the HTML as is, or to convert it to BlockNote HTML.\n */\n public pasteHTML(html: string, raw = false) {\n let htmlToPaste = html;\n if (!raw) {\n htmlToPaste = this.convertHtmlToBlockNoteHtml(html);\n }\n if (!htmlToPaste) {\n return;\n }\n this.prosemirrorView?.pasteHTML(htmlToPaste);\n }\n\n /**\n * Paste text into the editor. Defaults to interpreting text as markdown.\n * @param text The text to paste.\n */\n public pasteText(text: string) {\n return this.prosemirrorView?.pasteText(text);\n }\n\n /**\n * Paste markdown into the editor.\n * @param markdown The markdown to paste.\n */\n public async pasteMarkdown(markdown: string) {\n return this.pasteHTML(await markdownToHTML(markdown));\n }\n}\n","export const COLORS_DEFAULT = {\n gray: {\n text: \"#9b9a97\",\n background: \"#ebeced\",\n },\n brown: {\n text: \"#64473a\",\n background: \"#e9e5e3\",\n },\n red: {\n text: \"#e03e3e\",\n background: \"#fbe4e4\",\n },\n orange: {\n text: \"#d9730d\",\n background: \"#f6e9d9\",\n },\n yellow: {\n text: \"#dfab01\",\n background: \"#fbf3db\",\n },\n green: {\n text: \"#4d6461\",\n background: \"#ddedea\",\n },\n blue: {\n text: \"#0b6e99\",\n background: \"#ddebf1\",\n },\n purple: {\n text: \"#6940a5\",\n background: \"#eae4f2\",\n },\n pink: {\n text: \"#ad1a72\",\n background: \"#f4dfeb\",\n },\n};\n\nexport const COLORS_DARK_MODE_DEFAULT = {\n gray: {\n text: \"#bebdb8\",\n background: \"#9b9a97\",\n },\n brown: {\n text: \"#8e6552\",\n background: \"#64473a\",\n },\n red: {\n text: \"#ec4040\",\n background: \"#be3434\",\n },\n orange: {\n text: \"#e3790d\",\n background: \"#b7600a\",\n },\n yellow: {\n text: \"#dfab01\",\n background: \"#b58b00\",\n },\n green: {\n text: \"#6b8b87\",\n background: \"#4d6461\",\n },\n blue: {\n text: \"#0e87bc\",\n background: \"#0b6e99\",\n },\n purple: {\n text: \"#8552d7\",\n background: \"#6940a5\",\n },\n pink: {\n text: \"#da208f\",\n background: \"#ad1a72\",\n },\n};\n","import { BlockNoteSchema } from \"../editor/BlockNoteSchema.js\";\nimport { COLORS_DEFAULT } from \"../editor/defaultColors.js\";\nimport {\n BlockFromConfig,\n BlockSchema,\n InlineContent,\n InlineContentSchema,\n StyleSchema,\n StyledText,\n Styles,\n} from \"../schema/index.js\";\n\nimport type {\n BlockMapping,\n InlineContentMapping,\n StyleMapping,\n} from \"./mapping.js\";\n\nexport type ExporterOptions = {\n /**\n * A function that can be used to resolve files, images, etc.\n * Exporters might need the binary contents of files like images,\n * which might not always be available from the same origin as the main page.\n * You can use this option to proxy requests through a server you control\n * to avoid cross-origin (CORS) issues.\n *\n * @default uses a BlockNote hosted proxy (https://corsproxy.api.blocknotejs.org/)\n * @param url - The URL of the file to resolve\n * @returns A Promise that resolves to a string (the URL to use instead of the original)\n * or a Blob (you can return the Blob directly if you have already fetched it)\n */\n resolveFileUrl?: (url: string) => Promise<string | Blob>;\n /**\n * Colors to use for background of blocks, font colors, and highlight colors\n */\n colors: typeof COLORS_DEFAULT;\n};\nexport abstract class Exporter<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n RB,\n RI,\n RS,\n TS,\n> {\n public constructor(\n _schema: BlockNoteSchema<B, I, S>, // only used for type inference\n protected readonly mappings: {\n blockMapping: BlockMapping<B, I, S, RB, RI>;\n inlineContentMapping: InlineContentMapping<I, S, RI, TS>;\n styleMapping: StyleMapping<S, RS>;\n },\n public readonly options: ExporterOptions,\n ) {}\n\n public async resolveFile(url: string) {\n if (!this.options?.resolveFileUrl) {\n return (await fetch(url)).blob();\n }\n const ret = await this.options.resolveFileUrl(url);\n if (ret instanceof Blob) {\n return ret;\n }\n return (await fetch(ret)).blob();\n }\n\n public mapStyles(styles: Styles<S>) {\n const stylesArray = Object.entries(styles).map(([key, value]) => {\n const mappedStyle = this.mappings.styleMapping[key](value, this);\n return mappedStyle;\n });\n return stylesArray;\n }\n\n public mapInlineContent(inlineContent: InlineContent<I, S>) {\n return this.mappings.inlineContentMapping[inlineContent.type](\n inlineContent,\n this,\n );\n }\n\n public transformInlineContent(inlineContentArray: InlineContent<I, S>[]) {\n return inlineContentArray.map((ic) => this.mapInlineContent(ic));\n }\n\n public abstract transformStyledText(styledText: StyledText<S>): TS;\n\n public async mapBlock(\n block: BlockFromConfig<B[keyof B], I, S>,\n nestingLevel: number,\n numberedListIndex: number,\n ) {\n return this.mappings.blockMapping[block.type](\n block,\n this,\n nestingLevel,\n numberedListIndex,\n );\n }\n}\n","import { BlockNoteSchema } from \"../editor/BlockNoteSchema.js\";\nimport {\n BlockFromConfigNoChildren,\n BlockSchema,\n InlineContentFromConfig,\n InlineContentSchema,\n StyleSchema,\n Styles,\n} from \"../schema/index.js\";\nimport type { Exporter } from \"./Exporter.js\";\n\n/**\n * Defines a mapping from all block types with a schema to a result type `R`.\n */\nexport type BlockMapping<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n RB,\n RI,\n> = {\n [K in keyof B]: (\n block: BlockFromConfigNoChildren<B[K], I, S>,\n // we don't know the exact types that are supported by the exporter at this point,\n // because the mapping only knows about converting certain types (which might be a subset of the supported types)\n // this is why there are many `any` types here (same for types below)\n exporter: Exporter<any, any, any, RB, RI, any, any>,\n nestingLevel: number,\n numberedListIndex?: number,\n ) => RB | Promise<RB>;\n};\n\n/**\n * Defines a mapping from all inline content types with a schema to a result type R.\n */\nexport type InlineContentMapping<\n I extends InlineContentSchema,\n S extends StyleSchema,\n RI,\n TS,\n> = {\n [K in keyof I]: (\n inlineContent: InlineContentFromConfig<I[K], S>,\n exporter: Exporter<any, I, S, any, RI, any, TS>,\n ) => RI;\n};\n\n/**\n * Defines a mapping from all style types with a schema to a result type R.\n */\nexport type StyleMapping<S extends StyleSchema, RS> = {\n [K in keyof S]: (\n style: Styles<S>[K],\n exporter: Exporter<any, any, any, any, any, RS, any>,\n ) => RS;\n};\n\n/**\n * The mapping factory is a utility function to easily create mappings for\n * a BlockNoteSchema. Using the factory makes it easier to get typescript code completion etc.\n */\nexport function mappingFactory<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(_schema: BlockNoteSchema<B, I, S>) {\n return {\n createBlockMapping: <R, RI>(mapping: BlockMapping<B, I, S, R, RI>) =>\n mapping,\n createInlineContentMapping: <R, RS>(\n mapping: InlineContentMapping<I, S, R, RS>,\n ) => mapping,\n createStyleMapping: <R>(mapping: StyleMapping<S, R>) => mapping,\n };\n}\n","import type { Emoji, EmojiMartData } from \"@emoji-mart/data\";\n\nimport { checkDefaultInlineContentTypeInSchema } from \"../../blocks/defaultBlockTypeGuards.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { DefaultGridSuggestionItem } from \"./DefaultGridSuggestionItem.js\";\n\n// Temporary fix for https://github.com/missive/emoji-mart/pull/929\nlet emojiLoadingPromise:\n | Promise<{\n emojiMart: typeof import(\"emoji-mart\");\n emojiData: EmojiMartData;\n }>\n | undefined;\n\nasync function loadEmojiMart() {\n if (emojiLoadingPromise) {\n return emojiLoadingPromise;\n }\n\n emojiLoadingPromise = (async () => {\n // load dynamically because emoji-mart doesn't specify type: module and breaks in nodejs\n const [emojiMartModule, emojiDataModule] = await Promise.all([\n import(\"emoji-mart\"),\n // use a dynamic import to encourage bundle-splitting\n // and a smaller initial client bundle size\n import(\"@emoji-mart/data\"),\n ]);\n\n const emojiMart =\n \"default\" in emojiMartModule ? emojiMartModule.default : emojiMartModule;\n const emojiData =\n \"default\" in emojiDataModule\n ? (emojiDataModule.default as EmojiMartData)\n : (emojiDataModule as EmojiMartData);\n\n await emojiMart.init({ data: emojiData });\n\n return { emojiMart, emojiData };\n })();\n\n return emojiLoadingPromise;\n}\n\nexport async function getDefaultEmojiPickerItems<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n query: string,\n): Promise<DefaultGridSuggestionItem[]> {\n if (!checkDefaultInlineContentTypeInSchema(\"text\", editor)) {\n return [];\n }\n\n const { emojiData, emojiMart } = await loadEmojiMart();\n\n const emojisToShow =\n query.trim() === \"\"\n ? Object.values(emojiData.emojis)\n : ((await emojiMart!.SearchIndex.search(query)) as Emoji[]);\n\n return emojisToShow.map((emoji) => ({\n id: emoji.skins[0].native,\n onItemClick: () => editor.insertInlineContent(emoji.skins[0].native + \" \"),\n }));\n}\n","/**\n * Combines items by group. This can be used to combine multiple slash menu item arrays,\n * while making sure that items from the same group are adjacent to each other.\n */\nexport function combineByGroup<T extends { group?: string }>(\n items: T[],\n ...additionalItemsArray: {\n group?: string;\n }[][]\n) {\n const combinedItems = [...items];\n for (const additionalItems of additionalItemsArray) {\n for (const additionalItem of additionalItems) {\n const lastItemWithSameGroup = combinedItems.findLastIndex(\n (item) => item.group === additionalItem.group,\n );\n if (lastItemWithSameGroup === -1) {\n combinedItems.push(additionalItem as T);\n } else {\n combinedItems.splice(lastItemWithSameGroup + 1, 0, additionalItem as T);\n }\n }\n }\n return combinedItems;\n}\n"],"names":["removeDuplicates","array","by","seen","item","key","findDuplicates","items","filtered","el","index","UniqueID","Extension","testOptions","v4","element","attributes","defaultIdAttributes","dragSourceElement","transformPasted","Plugin","PluginKey","transactions","oldState","newState","docChanges","transaction","filterTransactions","tr","_a","_b","types","attributeName","generateID","transform","combineTransactionSteps","mapping","getChangedRanges","newRange","newNodes","findChildrenInRange","node","newIds","id","duplicatedNewIds","pos","initialDoc","jsonNode","deleted","view","handleDragstart","event","slice","removeId","fragment","list","nodeWithoutId","Fragment","Slice","isLinkInlineContent","content","isPartialLinkInlineContent","isStyledTextInlineContent","mapTableCell","isTableCell","isPartialTableCell","_c","_d","_e","getColspan","cell","getRowspan","UnreachableCaseError","val","assertEmpty","obj","throwError","dataTest","rest","isAppleOS","formatKeyboardShortcut","shortcut","ctrlText","mergeCSSClasses","classes","c","isSafari","createDefaultBlockDOMOutputSpec","blockName","htmlTag","blockContentHTMLAttributes","inlineContentHTMLAttributes","blockContent","attribute","value","inlineContent","defaultBlockToHTML","block","editor","blockToNode","toDOM","renderSpec","mergeParagraphs","paragraphs","firstParagraph","i","paragraph","defaultProps","inheritedProps","camelToDataKebab","str","filenameFromURL","url","parts","propsToAttributes","propSchema","tiptapAttributes","name","_spec","spec","asNumber","getBlockFromPos","getPos","tipTapEditor","type","blockIdentifier","wrapInBlockStructure","blockType","blockProps","isFileBlock","domAttributes","attr","prop","defaultValue","createStronglyTypedTiptapNode","config","Node","createInternalBlockSpec","implementation","createBlockSpecFromStronglyTypedTiptapNode","requiredExtensions","getBlockSchemaFromSpecs","specs","applyNonSelectableBlockFix","nodeView","getParseRules","customParseFunction","rules","props","createBlockSpec","blockConfig","blockImplementation","HTMLAttributes","div","blockContentDOMAttributes","output","getNearestBlockPos","doc","$pos","depth","allBlockContainerPositions","resolvedPos","position","getBlockInfoWithManualOffset","bnBlockBeforePosOffset","bnBlockNode","bnBlockBeforePos","bnBlockAfterPos","bnBlock","blockGroup","offset","blockContentNode","blockContentBeforePos","blockContentAfterPos","blockGroupNode","blockGroupBeforePos","blockGroupAfterPos","getBlockInfo","posInfo","getBlockInfoFromResolvedPos","getBlockInfoFromSelection","state","getBlockInfoFromTransaction","getPmSchema","trOrNode","getBlockNoteEditor","schema","getBlockNoteSchema","getBlockSchema","getInlineContentSchema","getStyleSchema","getBlockCache","contentNodeToTableContent","contentNode","inlineContentSchema","styleSchema","ret","headerMatrix","rowNode","_offset","rowIndex","row","cellNode","colWidth","cellIndex","child","contentNodeToInlineContent","acc","contentPartial","last","first","isHeader","currentContent","nodeToCustomInlineContent","styles","linkMark","mark","icConfig","nodeToBlock","blockSchema","blockCache","cachedBlock","blockInfo","blockSpec","children","docToBlocks","blocks","prosemirrorSliceToSlicedBlocks","processNode","openStart","openEnd","blockCutAtStart","blockCutAtEnd","blockContainer","isFirstBlock","isLastBlock","childGroup","childBlocks","addInlineContentAttributes","inlineContentType","inlineContentProps","addInlineContentKeyboardShortcuts","createInternalInlineContentSpec","createInlineContentSpecFromTipTapNode","getInlineContentSchemaFromSpecs","getInlineContentParseRules","htmlElement","createInlineContentSpec","inlineContentConfig","inlineContentImplementation","update","inlineContentToNodes","stylePropsToAttributes","addStyleAttributes","styleType","styleValue","createInternalStyleSpec","createStyleSpecFromTipTapMark","getStyleSchemaFromSpecs","getStyleParseRules","createStyleSpec","styleConfig","styleImplementation","Mark","renderResult","getTableCellOccupancyGrid","height","width","getDimensionsOfTable","grid","findNextAvailable","col","j","rowspan","colspan","startRow","startCol","getTableRowsFromOccupancyGrid","occupancyGrid","getAbsoluteTableCells","relativeCellIndices","r","rowWidth","getRelativeTableCells","absoluteCellIndices","occupancyCell","getCellsAtRowHandle","relativeRowIndex","absoluteRow","cells","_v","a","getCellsAtColumnHandle","relativeColumnIndex","absoluteCol","moveColumn","fromColIndex","toColIndex","absoluteSourceCol","absoluteTargetCol","sourceCell","moveRow","fromRowIndex","toRowIndex","absoluteSourceRow","absoluteTargetRow","sourceRow","isCellEmpty","s","cropEmptyRowsOrColumns","removeEmpty","emptyColsOnRight","cellsToRemove","emptyRowsOnBottom","rowsToRemove","addRowsOrColumns","addType","numToAdd","newRow","_","colIndex","canRowBeDraggedInto","draggingIndex","targetRowIndex","targetCells","endRowIndex","startRowIndex","canColumnBeDraggedInto","targetColumnIndex","endColumnIndex","startColumnIndex","areInSameColumn","from","to","anchorAbsoluteCellIndices","headAbsoluteCellIndices","styledTextToNodes","styledText","marks","style","text","linkToNodes","link","styledTextArrayToNodes","nodes","blockOrInlineContentToContentNode","tableContentToNodes","tableContent","rowNodes","headerRows","headerCols","columnWidths","columnNodes","isHeaderRow","isHeaderCol","attrs","absoluteCellIndex","colwidth","groupNode","getNodeById","targetNode","posBeforeNode","isNodeBlock","areBlocksDifferentExcludingChildren","block1","block2","getBlocksChangedByTransaction","appendedTransactions","source","pmSchema","combinedTransaction","changedRanges","prevAffectedBlocks","range","nextAffectedBlocks","nextBlocks","prevBlocks","changes","prevBlock","insertBlocks","blocksToInsert","referenceBlock","placement","nodesToInsert","ReplaceStep","removeAndInsertBlocks","blocksToRemove","idsOfBlocksToRemove","removedBlocks","idOfFirstBlock","removedSize","oldDocSize","newDocSize","notFoundIds","updateBlockCommand","posBeforeBlock","dispatch","updateBlockTr","replaceFromPos","replaceToPos","oldNodeType","newNodeType","newBnBlockNodeType","replaceFromOffset","replaceToOffset","updateChildren","updateBlockContentNode","existingBlock","start","end","contentDepth","startDepth","endDepth","childNodes","updateBlock","blockToUpdate","blockContainerNode","addAttributesAndRemoveClasses","className","serializeInlineContentExternalHTML","serializer","options","dom","serializeBlock","orderedListItemBlockTypes","unorderedListItemBlockTypes","BC_NODE","bc","elementFragment","blockContentDataAttributes","ic","listType","li","childFragment","serializeBlocksToFragment","_f","_g","_h","serializeBlocksExternalHTML","createExternalHTMLExporter","DOMSerializer","html","domFragment","parent","serializeInlineContentInternalHTML","listIndex","serializeBlocks","serializeBlocksInternalHTML","blockDOM","BG_NODE","bg","createInternalHTMLSerializer","parseFigureElement","figureElement","targetTag","targetElement","captionElement","caption","createAddFileButton","buttonText","buttonIcon","addFileButton","addFileButtonIcon","addFileButtonText","addFileButtonMouseDownHandler","addFileButtonClickHandler","FILE_ICON_SVG","createFileNameWithIcon","file","icon","fileName","createFileBlockWrapper","wrapper","destroyUploadStartHandler","blockId","loading","fileNameWithIcon","createFigureWithCaption","figure","createLinkWithCaption","fileCaption","parseAudioElement","audioElement","FILE_AUDIO_ICON_SVG","audioPropSchema","audioBlockConfig","audioRender","audio","downloadUrl","audioParse","parsedFigure","audioToExternalHTML","AudioBlock","shikiParserSymbol","shikiHighlighterPromiseSymbol","defaultCodeBlockPropSchema","CodeBlockContent","inputElement","language","dataLanguage","languages","getLanguageId","pre","contentDOM","select","selectWrapper","handleLanguageChange","option","newNode","globalThisForShiki","highlighter","parser","hasWarned","createHighlightPlugin","parserOptions","createdHighlighter","createParser","InputRule","match","$start","languageName","TextSelection","selection","$from","isTextSelection","isAtEnd","endsWithDoubleNewline","CodeBlock","aliases","BackgroundColorMark","BackgroundColor","TextColorMark","TextColor","parseEmbedElement","embedElement","filePropSchema","fileBlockConfig","fileRender","fileParse","fileToExternalHTML","fileSrcLink","FileBlock","headingPropSchema","HeadingBlockContent","level","chain","Heading","createResizableFileBlockWrapper","resizeHandlesContainerElement","destroy","leftResizeHandle","rightResizeHandle","resizeParams","windowMouseMoveHandler","newWidth","windowMouseUpHandler","wrapperMouseEnterHandler","wrapperMouseLeaveHandler","leftResizeHandleMouseDownHandler","rightResizeHandleMouseDownHandler","parseImageElement","imageElement","previewWidth","FILE_IMAGE_ICON_SVG","imagePropSchema","imageBlockConfig","imageRender","imageWrapper","image","imageParse","imageToExternalHTML","ImageBlock","getListItemContent","_node","DOMParser","clonedNodeDiv","listItemsFirstChild","listItemNode","remainingListItemChildren","listItemsChildren","splitBlockCommand","posInBlock","keepType","keepProps","nearestBlockContainerPos","info","handleEnter","selectionEmpty","commands","bulletListItemPropSchema","BulletListItemBlockContent","BulletListItem","checkListItemPropSchema","checkListItemBlockContent","checkbox","checkboxWrapper","changeHandler","beforeBlockContainerPos","label","CheckListItem","PLUGIN_KEY","NumberedListIndexingPlugin","_transactions","_oldState","modified","newIndex","prevBlockInfo","prevBlockIndex","isFirst","numberedListItemPropSchema","NumberedListItemBlockContent","startIndex","NumberedListItem","paragraphPropSchema","ParagraphBlockContent","Paragraph","quotePropSchema","QuoteBlockContent","Quote","RESIZE_MIN_WIDTH","EMPTY_CELL_WIDTH","EMPTY_CELL_HEIGHT","TableExtension","columnResizing","tableEditing","selectionIsEmpty","selectionIsAtStartOfNode","selectionIsInTableParagraphNode","goToNextCell","extension","context","callOrReturn","getExtensionField","tablePropSchema","TableBlockContent","BlockNoteTableView","TableView","cellMinWidth","tableWrapper","tableWrapperInner","floatingContainer","record","TableParagraph","TableRow","mergeAttributes","parseTableContent","parsedContent","extractedContent","Table","TableHeader","TableCell","parseVideoElement","videoElement","FILE_VIDEO_ICON_SVG","videoPropSchema","videoBlockConfig","videoRender","videoWrapper","video","videoParse","videoToExternalHTML","VideoBlock","defaultBlockSpecs","defaultBlockSchema","defaultStyleSpecs","Bold","Italic","Underline","Strike","Code","defaultStyleSchema","defaultInlineContentSpecs","defaultInlineContentSchema","checkDefaultBlockTypeInSchema","checkDefaultInlineContentTypeInSchema","checkBlockIsDefaultType","checkBlockIsFileBlock","checkBlockIsFileBlockWithPreview","checkBlockIsFileBlockWithPlaceholder","checkBlockTypeHasDefaultProp","checkBlockHasDefaultProp","isTableCellSelection","CellSelection","uploadToTmpFilesDotOrg_DEV_ONLY","body","setSelectionToNextContentEditableBlock","contentType","insertOrUpdateBlock","currentBlock","newBlock","getDefaultSlashMenuItems","insertedBlock","filterSuggestionItems","query","title","alias","removeUndefined","BlockNoteSchema","opts","__publicField","pageBreakConfig","pageBreakRender","pageBreak","pageBreakParse","pageBreakToExternalHTML","PageBreak","pageBreakSchema","withPageBreak","checkPageBreakBlocksInSchema","getPageBreakSlashMenuItems","getBlockSelectionData","anchorBlockPosInfo","NodeSelection","headBlockPosInfo","updateBlockSelectionFromData","data","anchorBlockPos","headBlockPos","flattenColumns","column","moveSelectedBlocksAndSelection","selectionData","checkPlacementIsValid","parentBlock","getMoveUpPlacement","referenceBlockParent","getMoveDownPlacement","nextBlock","moveBlocksUp","moveUpPlacement","moveBlocksDown","moveDownPlacement","sinkListItem","itemType","groupType","$to","nodeBefore","nestedBefore","inner","before","after","ReplaceAroundStep","nestBlock","unnestBlock","canNestBlock","canUnnestBlock","getBlock","getPrevBlock","nodeToConvert","getNextBlock","getParentBlock","$posBeforeNode","parentNode","grandparentNode","insertContentAt","isOnlyTextContent","isOnlyBlockContent","selectionToInsertionEnd","getSelection","$startBlockBeforePos","$endBlockBeforePos","indexToBlock","sharedDepth","endIndex","startIndexAtDepth","childCountAtDepth","setSelection","startBlock","endBlock","startBlockId","endBlockId","anchorPosInfo","headPosInfo","anchorBlockInfo","headBlockInfo","anchorBlockConfig","headBlockConfig","startPos","endPos","tableMap","TableMap","lastCellPos","lastCellNodeSize","getSelectionCutBlocks","selectionInfo","getTextCursorPosition","prevNode","nextNode","setTextCursorPosition","targetBlock","esmDependencies","initializeESMDependencies","vals","removeUnderlines","removeUnderlinesHelper","tree","numChildElements","numElementsAdded","addSpacesToCheckboxes","deps","helper","nextChild","cleanHTMLToMarkdown","cleanHTMLString","blocksToMarkdown","externalHTML","getChildIndex","isWhitespaceNode","liftNestedListsToParent","parentListItem","siblingsAfter","sibling","siblingContainer","createGroups","listItem","_detachedDoc","detachedDoc","nestedListsToBlockNoteStructure","elementOrHTML","HTMLToBlocks","htmlNode","code","properties","result","markdownToHTML","markdown","markdownToBlocks","htmlString","acceptedMIMETypes","checkFileExtensionsMatch","fileExtension1","fileExtension2","checkMIMETypesMatch","mimeType1","mimeType2","types1","types2","insertedBlockId","handleFileInsertion","dataTransfer","format","mimeType","fileBlockConfigs","fileBlockType","isFileExtension","fileBlock","coords","updateData","updatedFileBlock","createDropFileExtension","_view","h1","bold","ul","ol","hr","fences","blockquote","tableHeader","tableDivider","tableRow","isMarkdown","src","handleVSCodePaste","vscode","vscodeData","defaultPasteHandler","prioritizeMarkdownOverHTML","plainTextAsMarkdown","plainText","createPasteFromClipboardExtension","pasteHandler","fragmentToBlocks","fragmentToExternalHTML","selectedFragment","isWithinBlockContent","isWithinTable","fragmentWithoutParents","externalHTMLExporter","selectedFragmentToHTML","clipboardHTML","checkIfSelectionInNonEditableBlock","copyToClipboard","createCopyToClipboardExtension","BackgroundColorExtension","EventEmitter","fn","args","callbacks","callback","BlockNoteExtension","_args","plugin","_CursorPlugin","collaboration","user","clientID","cursorData","cursorElement","cursor","updated","yCursorPlugin","defaultSelectionBuilder","caretElement","labelElement","CursorPlugin","SyncPlugin","ySyncPlugin","UndoPlugin","yUndoPlugin","CommentMark","UserStore","resolveUsers","userIds","missingUsers","users","userId","cb","SET_SELECTED_THREAD_ID","getUpdatedThreadPositions","markType","threadPositions","thisThreadId","currentPosition","CommentsPlugin","threadStore","threads","markThreadId","thread","isOrphan","trimmedFrom","trimmedTo","self","DecorationSet","action","decorations","selectedThreadPosition","Decoration","commentMark","threadId","scrollToThread","pmSelection","ystate","ySyncPluginKey","getRelativeSelection","FilePanelView","pluginKey","pmView","emitUpdate","blockElement","prevState","pluginState","prevPluginState","isOpening","isClosing","filePanelPluginKey","FilePanelProsemirrorPlugin","editorView","prev","FormattingToolbarView","empty","isEmptyTextBlock","isNodeSelection","focusedElement","editorWrapper","e","composing","isSame","ranges","shouldShow","jsdom","nextState","posToDOMRect","formattingToolbarPluginKey","FormattingToolbarProsemirrorPlugin","HardBreak","getParentBlockInfo","beforePos","parentBeforePos","getPrevBlockInfo","indexInParent","prevBlockBeforePos","getBottomNestedBlockInfo","group","newPos","canMerge","nextBlockInfo","mergeBlocks","childBlocksStart","childBlocksEnd","childBlocksRange","mergeBlocksCommand","posBetweenBlocks","bottomNestedBlockInfo","KeyboardShortcutsExtension","handleBackspace","selectionAtBlockStart","isParagraph","parentBlockInfo","columnList","shouldRemoveColumn","shouldRemoveColumnList","isFirstColumn","blockToMove","chainedCommands","lastCellParagraphEndPos","nonEditableBlockContentStartPos","blockContentStartPos","bottomBlock","handleDelete","childContainer","blockAtDocEnd","selectionAtBlockEnd","oldDepth","newDepth","withShift","blockEmpty","blockIndented","blockHardBreakShortcut","newBlockInsertionPos","newBlockContentPos","LinkToolbarView","hoveredLinkElement","posInHoveredLinkMark","resolvedPosInHoveredLinkMark","marksAtPos","getMarkRange","fromMouseOver","prevLinkMark","linkToolbarPluginKey","LinkToolbarProsemirrorPlugin","VALID_LINK_PROTOCOLS","DEFAULT_LINK_PROTOCOL","NodeSelectionKeyboardPlugin","PlaceholderPlugin","placeholders","uniqueEditorSelector","styleEl","nonce","styleSheet","getSelector","additionalSelectors","defaultPlaceholder","emptyPlaceholder","placeholder","blockTypeSelector","onlyBlockSelector","mustBeFocusedSelector","decs","nodeAttributes","PreviousBlockTypePlugin","timeout","_editorView","_prevState","currentTransactionOriginalOldBlockAttrs","oldNodes","findChildren","oldNodesById","oldNode","oldContentNode","newContentNode","newAttrs","oldAttrs","prevAttrs","decorationAttrs","nodeAttr","decoration","ShowSelectionPlugin","dec","enabled","getDraggableBlockFromElement","MultipleNodeSelection","Selection","$anchor","$head","_pos","fromResult","toResult","dragImageElement","blockPositionsFromSelection","beforeFirstBlockPos","afterLastBlockPos","selectionStartInBlockContent","selectionEndInBlockContent","minDepth","startFirstBlockPos","endLastBlockPos","setDragImage","parentClone","getElementIndex","parentElement","firstSelectedBlockIndex","lastSelectedBlockIndex","unsetDragImage","iframes","iframe","inheritedClasses","rootEl","dragStart","draggedBlockInSelection","multipleBlocksSelected","selectedSlice","PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP","getBlockFromCoords","sideMenuDetection","adjustForColumns","elements","getBlockFromMousePos","mousePos","editorBoundingBox","mouseLeftOfEditor","mouseRightOfEditor","rect","SideMenuView","blockContentBoundingBox","parentEditorElement","evt","_event","editorOuterBoundingBox","cursorWithinEditor","sideMenuPluginKey","SideMenuProsemirrorPlugin","editorToMapping","getMapping","Mapping","trackPosition","side","ySyncPluginState","trackedMapLength","relativePosition","absolutePositionToRelativePosition","curYSyncPluginState","relativePositionToAbsolutePosition","findBlock","findParentNode","SuggestionMenuView","decorationNode","suggestionMenuPluginKey","menuName","next","started","stopped","SuggestionMenuProseMirrorPlugin","triggerCharacter","triggerCharacters","suggestionPluginTransactionMeta","trackedPosition","_from","_to","suggestionPluginState","blockNode","createSuggestionMenu","SuggestionAddMark","inline","SuggestionDeleteMark","SuggestionModificationMark","setHiddenDragImage","unsetHiddenDragImage","domCellAround","target","currentTarget","hideElements","selector","elementsToHide","TableHandlesView","tableRect","blockEl","tableBlock","pmNodeInfo","widgetContainer","belowTable","toRightOfTable","hideHandles","cellRect","boundedMouseCoords","tableCellElements","tableCellElement","emitStateUpdate","oldIndex","dispatchDecorationsTransaction","tableHandlesPluginKey","draggingState","newTable","columnWidth","rowCount","colCount","tableBody","TableHandlesProsemirrorPlugin","relativeStartCell","relativeEndCell","tableResolvedPos","startRowResolvedPos","startCellResolvedPos","endRowResolvedPos","endCellResolvedPos","direction","beforeState","addRowBefore","addRowAfter","addColumnBefore","addColumnAfter","deleteRow","deleteColumn","cellsToMerge","mergeCells","relativeCellToSplit","splitCell","$fromCell","$toCell","$fromRow","$toRow","$table","isSelectingTableCells","cellSelection","originalIndex","draggedCellOrientation","rowResolvedPos","cellResolvedPos","decorationPos","widget","TextAlignmentExtension","TextColorExtension","TrailingNode","__","shouldInsertNodeAtEnd","endPosition","_state","lastNode","lastContentNode","BlockAttributes","BlockContainer","HTMLAttr","blockOuter","blockHTMLAttributes","BlockGroup","blockGroupHTMLAttributes","Doc","ForkYDocPlugin","ytype","otherYdoc","ydoc","rootKey","ytypeItem","otherStructs","itemIndex","Y","originalFragment","forkedFragment","yCursorPluginKey","yUndoPluginKey","keepChanges","getBlockNoteExtensions","tiptapExtensions","getTipTapExtensions","ext","disableExtensions","LINKIFY_INITIALIZED","extensions","Gapcursor","Text","Link","styleSpec","inlineContentSpec","History","removeChild","wrapTableRows","f","newItems","prevTable","shouldApplyFix","nestedChild","container","nodeHasSingleChild","nodeHasInlineContent","nodeHasTableContent","_BlockNoteTipTapEditor","TiptapEditor","blockNoteEditor","contentComponent","cache","oldCreateAndFill","pmNodes","b","createDocument","EditorState","selectionHasChanged","focus","blur","markViews","EditorView","oldSetTimeout","BlockNoteTipTapEditor","blockNoteTipTapOptions","BlockNoteEditor","anyOpts","en","newOptions","dropCursor","_i","instance","uploadFile","collaborationEnabled","initialContent","TipTapNode","tiptapOptions","_j","_l","_k","_m","_o","_n","getSchema","command","activeTr","reverse","traverseBlockArray","blockArray","editable","undoCommand","undo","redoCommand","redo","updateSelection","includeSelectionChangedByRemote","forceSelectionVisible","raw","htmlToPaste","COLORS_DEFAULT","COLORS_DARK_MODE_DEFAULT","Exporter","_schema","mappings","inlineContentArray","nestingLevel","numberedListIndex","mappingFactory","emojiLoadingPromise","loadEmojiMart","emojiMartModule","emojiDataModule","emojiMart","emojiData","getDefaultEmojiPickerItems","emoji","combineByGroup","additionalItemsArray","combinedItems","additionalItems","additionalItem","lastItemWithSameGroup"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,SAASA,GAAiBC,GAAYC,IAAK,KAAK,WAAW;AACzD,QAAMC,IAAY,CAAC;AACZ,SAAAF,EAAM,OAAO,CAACG,MAAc;AAC3B,UAAAC,IAAMH,EAAGE,CAAI;AACZ,WAAA,OAAO,UAAU,eAAe,KAAKD,GAAME,CAAG,IACjD,KACCF,EAAKE,CAAG,IAAI;AAAA,EAAA,CAClB;AACH;AAKA,SAASC,GAAeC,GAAY;AAClC,QAAMC,IAAWD,EAAM;AAAA,IACrB,CAACE,GAASC,MAAkBH,EAAM,QAAQE,CAAE,MAAMC;AAAA,EACpD;AAEO,SADYV,GAAiBQ,CAAQ;AAE9C;AAEM,MAAAG,KAAWC,EAAU,OAAO;AAAA,EAChC,MAAM;AAAA;AAAA;AAAA,EAGN,UAAU;AAAA,EACV,aAAa;AACJ,WAAA;AAAA,MACL,eAAe;AAAA,MACf,OAAO,CAAC;AAAA,MACR,gBAAgB;AAAA,MAChB,YAAY,MAAM;AAEhB,YAAI,OAAO,SAAW,OAAgB,OAAe,gBAAgB;AACnE,gBAAMC,IAAe,OAAe;AAChC,iBAAAA,EAAY,WAAW,SACzBA,EAAY,SAAS,IAETA,EAAA,UAGPA,EAAY,OAAO,SAAS;AAAA,QAAA;AAGrC,eAAOC,GAAG;AAAA,MACZ;AAAA,MACA,mBAAmB;AAAA,IACrB;AAAA,EACF;AAAA,EACA,sBAAsB;AACb,WAAA;AAAA,MACL;AAAA,QACE,OAAO,KAAK,QAAQ;AAAA,QACpB,YAAY;AAAA,UACV,CAAC,KAAK,QAAQ,aAAa,GAAG;AAAA,YAC5B,SAAS;AAAA,YACT,WAAW,CAACC,MACVA,EAAQ,aAAa,QAAQ,KAAK,QAAQ,aAAa,EAAE;AAAA,YAC3D,YAAY,CAACC,MAAe;AAC1B,oBAAMC,IAAsB;AAAA,gBAC1B,CAAC,QAAQ,KAAK,QAAQ,aAAa,EAAE,GACnCD,EAAW,KAAK,QAAQ,aAAa;AAAA,cACzC;AACI,qBAAA,KAAK,QAAQ,iBACR;AAAA,gBACL,GAAGC;AAAA,gBACH,IAAID,EAAW,KAAK,QAAQ,aAAa;AAAA,cAC3C,IAEOC;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,wBAAwB;AACtB,QAAIC,IAAyB,MACzBC,IAAkB;AACf,WAAA;AAAA,MACL,IAAIC,EAAO;AAAA,QACT,KAAK,IAAIC,EAAU,UAAU;AAAA,QAC7B,mBAAmB,CAACC,GAAcC,GAAUC,MAAa;AAEvD,gBAAMC,IACJH,EAAa,KAAK,CAACI,MAAgBA,EAAY,UAAU,KACzD,CAACH,EAAS,IAAI,GAAGC,EAAS,GAAG,GACzBG,IACJ,KAAK,QAAQ,qBACbL,EAAa,KAAK,CAACM,MAAO;AACxB,gBAAIC,GAAIC;AACR,mBAAO,EAAG,GAAAA,KAAMD,IAAK,KAAK,SAAS,uBAAuB,QAC1DC,MAAO,WAEHA,EAAG,KAAKD,GAAID,CAAE;AAAA,UAAA,CACnB;AACC,cAAA,CAACH,KAAcE;AACjB;AAEI,gBAAA,EAAE,IAAAC,MAAOJ,GACT,EAAE,OAAAO,GAAO,eAAAC,GAAe,YAAAC,MAAe,KAAK,SAC5CC,IAAYC;AAAA,YAChBZ,EAAS;AAAA,YACTD;AAAA,UACF,GACM,EAAE,SAAAc,MAAYF;AAuEhB,cArEYG,GAAiBH,CAAS,EAElC,QAAQ,CAAC,EAAE,UAAAI,QAAe;AAChC,kBAAMC,IAAWC;AAAA,cACfhB,EAAS;AAAA,cACTc;AAAA,cACA,CAACG,MACQV,EAAM,SAASU,EAAK,KAAK,IAAI;AAAA,YAExC,GACMC,IAASH,EACZ,IAAI,CAAC,EAAE,MAAAE,EAAW,MAAAA,EAAK,MAAMT,CAAa,CAAC,EAC3C,OAAO,CAACW,MAAOA,MAAO,IAAI,GACvBC,IAAmBtC,GAAeoC,CAAM;AAC9C,YAAAH,EAAS,QAAQ,CAAC,EAAE,MAAAE,GAAM,KAAAI,QAAU;AAC9B,kBAAAhB;AAKJ,oBAAMc,KACHd,IAAKD,EAAG,IAAI,OAAOiB,CAAG,OAAO,QAAQhB,MAAO,SACzC,SACAA,EAAG,MAAMG,CAAa;AAC5B,kBAAIW,MAAO,MAAM;AAIf,sBAAMG,IAAavB,EAAS,IAAI,KAAK,cAAiB,EAAA;AAItD,oBAFEA,EAAS,IAAI,QAAQ,cAAcuB,CAAU,MAAM,MAErC;AAEd,wBAAMC,KAAW,KAAK;AAAA,oBACpB,KAAK,UAAUvB,EAAS,IAAI,OAAQ,CAAA;AAAA,kBACtC;AAIE,sBAHFuB,GAAS,QAAQ,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,kBAGxC,KAAK,UAAUA,GAAS,OAAO,MAC/B,KAAK,UAAUD,EAAW,OAAO,CAAC,GAClC;AAEG,oBAAAlB,EAAA,cAAciB,GAAK,QAAW;AAAA,sBAC/B,GAAGJ,EAAK;AAAA,sBACR,CAACT,CAAa,GAAG;AAAA,oBAAA,CAClB;AACD;AAAA,kBAAA;AAAA,gBACF;AAGC,gBAAAJ,EAAA,cAAciB,GAAK,QAAW;AAAA,kBAC/B,GAAGJ,EAAK;AAAA,kBACR,CAACT,CAAa,GAAGC,EAAW;AAAA,gBAAA,CAC7B;AACD;AAAA,cAAA;AAGF,oBAAM,EAAE,SAAAe,EAAQ,IAAIZ,EAAQ,OAAO,EAAE,UAAUS,CAAG;AAElD,cADgBG,KAAWJ,EAAiB,SAASD,CAAE,KAElDf,EAAA,cAAciB,GAAK,QAAW;AAAA,gBAC/B,GAAGJ,EAAK;AAAA,gBACR,CAACT,CAAa,GAAGC,EAAW;AAAA,cAAA,CAC7B;AAAA,YACH,CACD;AAAA,UAAA,CACF,GACG,EAACL,EAAG,MAAM;AAGP,mBAAAA;AAAA,QACT;AAAA;AAAA,QAEA,KAAKqB,GAAM;AACH,gBAAAC,IAAkB,CAACC,MAAe;AAClC,gBAAAtB;AACJ,YAAAX,IACG,GAAAW,IAAKoB,EAAK,IAAI,mBAAmB,QAAQpB,MAAO,WAE7CA,EAAG,SAASsB,EAAM,MAAM,IAE1BF,EAAK,IAAI,gBACT;AAAA,UACN;AACO,wBAAA,iBAAiB,aAAaC,CAAe,GAC7C;AAAA,YACL,UAAU;AACD,qBAAA,oBAAoB,aAAaA,CAAe;AAAA,YAAA;AAAA,UAE3D;AAAA,QACF;AAAA,QACA,OAAO;AAAA;AAAA;AAAA;AAAA,UAIL,iBAAiB;AAAA;AAAA;AAAA,YAGf,MAAM,CAACD,GAAME,MAAe;AACtB,kBAAAtB;AACJ,qBACEX,MAAsB+B,EAAK,IAAI,mBAC7BpB,IAAKsB,EAAM,kBAAkB,QAAQtB,MAAO,SAC1C,SACAA,EAAG,mBAAmB,SAERV,IAAA,KAEAA,IAAA,IAGAD,IAAA,MAEb;AAAA,YACT;AAAA;AAAA,YAEA,OAAO,OACaC,IAAA,IACX;AAAA,UAEX;AAAA;AAAA;AAAA,UAGA,iBAAiB,CAACiC,MAAU;AAC1B,gBAAI,CAACjC;AACI,qBAAAiC;AAET,kBAAM,EAAE,OAAArB,GAAO,eAAAC,EAAc,IAAI,KAAK,SAChCqB,IAAW,CAACC,MAAkB;AAClC,oBAAMC,IAAc,CAAC;AACZ,qBAAAD,EAAA,QAAQ,CAACb,MAAc;AAE9B,oBAAIA,EAAK,QAAQ;AACf,kBAAAc,EAAK,KAAKd,CAAI;AACd;AAAA,gBAAA;AAGF,oBAAI,CAACV,EAAM,SAASU,EAAK,KAAK,IAAI,GAAG;AACnC,kBAAAc,EAAK,KAAKd,EAAK,KAAKY,EAASZ,EAAK,OAAO,CAAC,CAAC;AAC3C;AAAA,gBAAA;AAGI,sBAAAe,IAAgBf,EAAK,KAAK;AAAA,kBAC9B;AAAA,oBACE,GAAGA,EAAK;AAAA,oBACR,CAACT,CAAa,GAAG;AAAA,kBACnB;AAAA,kBACAqB,EAASZ,EAAK,OAAO;AAAA,kBACrBA,EAAK;AAAA,gBACP;AACA,gBAAAc,EAAK,KAAKC,CAAa;AAAA,cAAA,CACxB,GACMC,EAAS,KAAKF,CAAI;AAAA,YAC3B;AAEkB,mBAAApC,IAAA,IACX,IAAIuC;AAAA,cACTL,EAASD,EAAM,OAAO;AAAA,cACtBA,EAAM;AAAA,cACNA,EAAM;AAAA,YACR;AAAA,UAAA;AAAA,QACF;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC;ACzMM,SAASO,GACdC,GACoB;AACpB,SAAOA,EAAQ,SAAS;AAC1B;AAEO,SAASC,GACdD,GAC2B;AAC3B,SAAO,OAAOA,KAAY,YAAYA,EAAQ,SAAS;AACzD;AAEO,SAASE,GACdF,GAC0B;AAC1B,SAAO,OAAOA,KAAY,YAAYA,EAAQ,SAAS;AACzD;AClIO,SAASG,GAIdH,GAIiB;;AACV,SAAAI,GAAYJ,CAAO,IACtB,EAAE,GAAGA,MACLK,GAAmBL,CAAO,IACxB;AAAA,IACE,MAAM;AAAA,IACN,SAAU,CAA6B,EAAA,OAAOA,EAAQ,OAAc;AAAA,IACpE,OAAO;AAAA,MACL,mBAAiB/B,IAAA+B,EAAQ,UAAR,gBAAA/B,EAAe,oBAAmB;AAAA,MACnD,aAAWC,IAAA8B,EAAQ,UAAR,gBAAA9B,EAAe,cAAa;AAAA,MACvC,iBAAeoC,IAAAN,EAAQ,UAAR,gBAAAM,EAAe,kBAAiB;AAAA,MAC/C,WAASC,IAAAP,EAAQ,UAAR,gBAAAO,EAAe,YAAW;AAAA,MACnC,WAASC,IAAAR,EAAQ,UAAR,gBAAAQ,EAAe,YAAW;AAAA,IAAA;AAAA,EACrC,IAEF;AAAA,IACE,MAAM;AAAA,IACN,SAAU,CAAA,EAA6B,OAAOR,CAAc;AAAA,IAC5D,OAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,WAAW;AAAA,MACX,eAAe;AAAA,MACf,SAAS;AAAA,MACT,SAAS;AAAA,IAAA;AAAA,EAEb;AACR;AAEO,SAASK,GAIdL,GAMmC;AACnC,SAEEA,KAAY,QACZ,OAAOA,KAAY,YACnB,CAAC,MAAM,QAAQA,CAAO,KACtBA,EAAQ,SAAS;AAErB;AAEO,SAASI,GAIdJ,GAM4B;AAC5B,SACEK,GAAmBL,CAAO,KAC1BA,EAAQ,UAAU,UAClBA,EAAQ,YAAY;AAExB;AAEO,SAASS,GACdC,GAIQ;AACJ,SAAAN,GAAYM,CAAI,IACXA,EAAK,MAAM,WAAW,IAExB;AACT;AAEO,SAASC,GACdD,GAIQ;AACJ,SAAAN,GAAYM,CAAI,IACXA,EAAK,MAAM,WAAW,IAExB;AACT;AC7GO,MAAME,UAA6B,MAAM;AAAA,EAC9C,YAAYC,GAAY;AAChB,UAAA,qBAAqBA,CAAG,EAAE;AAAA,EAAA;AAEpC;AAEgB,SAAAC,GAAYC,GAA4BC,IAAa,IAAM;AACzE,QAAM,EAAE,aAAaC,GAAU,GAAGC,EAAS,IAAAH;AAE3C,MAAI,OAAO,KAAKG,CAAI,EAAE,SAAS,KAAKF;AAClC,UAAM,IAAI,MAAM,0BAA0B,KAAK,UAAUD,CAAG,CAAC;AAEjE;ACZO,MAAMI,KAAY,MACvB,OAAO,YAAc,QACpB,MAAM,KAAK,UAAU,QAAQ,KAC3B,cAAc,KAAK,UAAU,SAAS,KACrC,cAAc,KAAK,UAAU,SAAS;AAE5B,SAAAC,EAAuBC,GAAkBC,IAAW,QAAQ;AAC1E,SAAIH,OACKE,EAAS,QAAQ,OAAO,GAAG,IAE3BA,EAAS,QAAQ,OAAOC,CAAQ;AAE3C;AAEO,SAASC,KAAmBC,GAAyC;AAC1E,SAAOA,EAAQ,OAAO,CAACC,MAAMA,CAAC,EAAE,KAAK,GAAG;AAC1C;AAEO,MAAMC,KAAW,MACtB,iCAAiC,KAAK,UAAU,SAAS;ACHpD,SAASC,EACdC,GACAC,GACAC,GACAC,GACA;AACM,QAAAC,IAAe,SAAS,cAAc,KAAK;AACjD,EAAAA,EAAa,YAAYT;AAAA,IACvB;AAAA,IACAO,EAA2B;AAAA,EAC7B,GACaE,EAAA,aAAa,qBAAqBJ,CAAS;AACxD,aAAW,CAACK,GAAWC,CAAK,KAAK,OAAO,QAAQJ,CAA0B;AACxE,IAAIG,MAAc,WACHD,EAAA,aAAaC,GAAWC,CAAK;AAIxC,QAAAC,IAAgB,SAAS,cAAcN,CAAO;AACpD,EAAAM,EAAc,YAAYZ;AAAA,IACxB;AAAA,IACAQ,EAA4B;AAAA,EAC9B;AACA,aAAW,CAACE,GAAWC,CAAK,KAAK,OAAO;AAAA,IACtCH;AAAA,EAAA;AAEA,IAAIE,MAAc,WACFE,EAAA,aAAaF,GAAWC,CAAK;AAI/C,SAAAF,EAAa,YAAYG,CAAa,GAE/B;AAAA,IACL,KAAKH;AAAA,IACL,YAAYG;AAAA,EACd;AACF;AAKa,MAAAC,KAAqB,CAKhCC,GACAC,MAIG;AACH,MAAIzD,IAAO0D,GAAYF,GAAOC,EAAO,QAAQ;AAEzC,EAAAzD,EAAK,KAAK,SAAS,qBAErBA,IAAOA,EAAK;AAGR,QAAA2D,IAAQF,EAAO,SAAS,MAAMzD,EAAK,KAAK,IAAI,EAAE,KAAK;AAEzD,MAAI2D,MAAU;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGI,QAAAC,IAAaD,EAAM3D,CAAI;AAE7B,MAAI,OAAO4D,KAAe,YAAY,EAAE,SAASA;AAC/C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGK,SAAAA;AAIT;AAMO,SAASC,GAAgBvF,GAAsB;AAC9C,QAAAwF,IAAaxF,EAAQ,iBAAiB,GAAG;AAC3C,MAAAwF,EAAW,SAAS,GAAG;AACnB,UAAAC,IAAiBD,EAAW,CAAC;AACnC,aAASE,IAAI,GAAGA,IAAIF,EAAW,QAAQE,KAAK;AACpC,YAAAC,IAAYH,EAAWE,CAAC;AACf,MAAAD,EAAA,aAAa,SAASE,EAAU,WAC/CA,EAAU,OAAO;AAAA,IAAA;AAAA,EACnB;AAEJ;AC3GO,MAAMC,IAAe;AAAA,EAC1B,iBAAiB;AAAA,IACf,SAAS;AAAA,EACX;AAAA,EACA,WAAW;AAAA,IACT,SAAS;AAAA,EACX;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,QAAQ,CAAC,QAAQ,UAAU,SAAS,SAAS;AAAA,EAAA;AAEjD,GAOaC,KAAiB,CAAC,mBAAmB,WAAW;ACvBtD,SAASC,GAAiBC,GAAqB;AACpD,SAAO,UAAUA,EAAI,QAAQ,mBAAmB,OAAO,EAAE,YAAY;AACvE;AAEO,SAASC,GAAgBC,GAAqB;AAC7C,QAAAC,IAAQD,EAAI,MAAM,GAAG;AAC3B,SACE,CAACC,EAAM;AAAA,EACPA,EAAMA,EAAM,SAAS,CAAC,MAAM,KAGrBD,IAEFC,EAAMA,EAAM,SAAS,CAAC;AAC/B;ACeO,SAASC,GAAkBC,GAAoC;AACpE,QAAMC,IAA8C,CAAC;AAE9C,gBAAA,QAAQD,CAAU,EACtB,OAAO,CAAC,CAACE,GAAMC,CAAK,MAAM,CAACV,GAAe,SAASS,CAAI,CAAC,EACxD,QAAQ,CAAC,CAACA,GAAME,CAAI,MAAM;AACzB,IAAAH,EAAiBC,CAAI,IAAI;AAAA,MACvB,SAASE,EAAK;AAAA,MACd,aAAa;AAAA;AAAA;AAAA;AAAA,MAIb,WAAW,CAACxG,MAAY;AACtB,cAAM+E,IAAQ/E,EAAQ,aAAa8F,GAAiBQ,CAAI,CAAC;AAEzD,YAAIvB,MAAU;AACL,iBAAA;AAGT,YACGyB,EAAK,YAAY,UAAaA,EAAK,SAAS,aAC5CA,EAAK,YAAY,UAAa,OAAOA,EAAK,WAAY;AAEvD,iBAAIzB,MAAU,SACL,KAGLA,MAAU,UACL,KAGF;AAGT,YACGyB,EAAK,YAAY,UAAaA,EAAK,SAAS,YAC5CA,EAAK,YAAY,UAAa,OAAOA,EAAK,WAAY,UACvD;AACM,gBAAAC,IAAW,WAAW1B,CAAK;AAIjC,iBAFE,CAAC,OAAO,MAAM0B,CAAQ,KAAK,OAAO,SAASA,CAAQ,IAG5CA,IAGF;AAAA,QAAA;AAGF,eAAA1B;AAAA,MACT;AAAA,MACA,YAAY,CAAC9E,MAEJA,EAAWqG,CAAI,MAAME,EAAK,UAC7B;AAAA,QACE,CAACV,GAAiBQ,CAAI,CAAC,GAAGrG,EAAWqG,CAAI;AAAA,MAAA,IAE3C,CAAC;AAAA,IAET;AAAA,EAAA,CACD,GAEID;AACT;AAIO,SAASK,GAOdC,GACAxB,GACAyB,GACAC,GACA;AAEI,MAAA,OAAOF,KAAW;AACpB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAEF,QAAM7E,IAAM6E,EAAO,GAIbG,IAFiBF,EAAa,MAAM,IAAI,QAAQ9E,CAAI,EAAE,KAAK,EAE1B,MAAM;AAE7C,MAAI,CAACgF;AACG,UAAA,IAAI,MAAM,uBAAuB;AAInC,QAAA5B,IAAQC,EAAO,SAAS2B,CAAe;AAMzC,MAAA5B,EAAM,SAAS2B;AACX,UAAA,IAAI,MAAM,2BAA2B;AAGtC,SAAA3B;AACT;AAMO,SAAS6B,GAId/G,GAKAgH,GACAC,GACAb,GACAc,IAAc,IACdC,GAKA;AAEM,QAAAtC,IAAe,SAAS,cAAc,KAAK;AAGjD,MAAIsC,MAAkB;AACpB,eAAW,CAACC,GAAMrC,CAAK,KAAK,OAAO,QAAQoC,CAAa;AACtD,MAAIC,MAAS,WACEvC,EAAA,aAAauC,GAAMrC,CAAK;AAK3C,EAAAF,EAAa,YAAYT;AAAA,IACvB;AAAA,KACA+C,KAAA,gBAAAA,EAAe,UAAS;AAAA,EAC1B,GAEatC,EAAA,aAAa,qBAAqBmC,CAAS;AAIxD,aAAW,CAACK,GAAMtC,CAAK,KAAK,OAAO,QAAQkC,CAAU,GAAG;AAEtD,UAAMK,IADOlB,EAAWiB,CAAI,EACF;AAC1B,IAAI,CAACxB,GAAe,SAASwB,CAAI,KAAKtC,MAAUuC,KAC9CzC,EAAa,aAAaiB,GAAiBuB,CAAI,GAAGtC,CAAK;AAAA,EACzD;AAGF,SAAImC,KACWrC,EAAA,aAAa,mBAAmB,EAAE,GAGpCA,EAAA,YAAY7E,EAAQ,GAAG,GAEhCA,EAAQ,eAAe,WACzBA,EAAQ,WAAW,YAAYoE;AAAA,IAC7B;AAAA,IACApE,EAAQ,WAAW;AAAA,EACrB,IAGK;AAAA,IACL,GAAGA;AAAA,IACH,KAAK6E;AAAA,EACP;AACF;AAaO,SAAS0C,EAQdC,GAAuD;AAChD,SAAAC,GAAK,OAAOD,CAAM;AAC3B;AAIgB,SAAAE,GACdF,GACAG,GAMA;AACO,SAAA;AAAA,IACL,QAAAH;AAAA,IACA,gBAAAG;AAAA,EACF;AACF;AAEgB,SAAAC,GAGdlG,GAAS0E,GAAeyB,GAA8C;AAC/D,SAAAH;AAAA,IACL;AAAA,MACE,MAAMhG,EAAK;AAAA,MACX,SAAUA,EAAK,OAAO,YAAY,YAC9B,WACAA,EAAK,OAAO,YAAY,cACtB,UACA;AAAA,MAKN,YAAA0E;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAA1E;AAAA,MACA,oBAAAmG;AAAA,MACA,gBAAgB5C;AAAA,MAChB,gBAAgBA;AAAA;AAAA,IAAA;AAAA,EAGpB;AACF;AAEO,SAAS6C,GAA8CC,GAAU;AACtE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAK,EAAE,IAAI,CAAC,CAACzI,GAAKyF,CAAK,MAAM,CAACzF,GAAKyF,EAAM,MAAM,CAAC;AAAA,EACjE;AACF;ACtNgB,SAAAiD,GAA2BC,GAAoB9C,GAAgB;AACpE,EAAA8C,EAAA,YAAY,CAAC7F,OAIhBA,EAAM,SAAS,eACjB,WAAW,MAAM;AACR,IAAA+C,EAAA,KAAK,IAAI,KAAK;AAAA,KACpB,EAAE,GAGA;AAEX;AAKgB,SAAA+C,GACdV,GACAW,GACA;AACA,QAAMC,IAAwB;AAAA,IAC5B;AAAA,MACE,KAAK,wBAAwBZ,EAAO,OAAO;AAAA,MAC3C,gBAAgB;AAAA,IAAA;AAAA,EAEpB;AAEA,SAAIW,KACFC,EAAM,KAAK;AAAA,IACT,KAAK;AAAA,IACL,SAAS1G,GAA4B;AAC/B,UAAA,OAAOA,KAAS;AACX,eAAA;AAGH,YAAA2G,IAAQF,KAAA,gBAAAA,EAAsBzG;AAEpC,aAAI2G,MAAU,SACL,KAGFA;AAAA,IAAA;AAAA,EACT,CACD,GAkBID;AACT;AAIgB,SAAAE,GAKdC,GACAC,GACA;AACA,QAAM9G,IAAO6F,EAA8B;AAAA,IACzC,MAAMgB,EAAY;AAAA,IAClB,SAAUA,EAAY,YAAY,WAC9B,YACA;AAAA,IACJ,OAAO;AAAA,IACP,YAAYA,EAAY,gBAAgB;AAAA,IACxC,WAAW;AAAA,IACX,gBAAgB;AACP,aAAApC,GAAkBoC,EAAY,UAAU;AAAA,IACjD;AAAA,IAEA,YAAY;AACH,aAAAL,GAAcK,GAAaC,EAAoB,KAAK;AAAA,IAC7D;AAAA,IAEA,WAAW,EAAE,gBAAAC,KAAkB;AAMvB,YAAAC,IAAM,SAAS,cAAc,KAAK;AACjC,aAAA3B;AAAA,QACL;AAAA,UACE,KAAK2B;AAAA,UACL,YAAYH,EAAY,YAAY,WAAWG,IAAM;AAAA,QACvD;AAAA,QACAH,EAAY;AAAA,QACZ,CAAC;AAAA,QACDA,EAAY;AAAA,QACZA,EAAY;AAAA,QACZE;AAAA,MACF;AAAA,IACF;AAAA,IAEA,cAAc;AACL,aAAA,CAAC,EAAE,QAAA9B,QAAa;;AAEf,cAAAxB,IAAS,KAAK,QAAQ,QAEtBD,IAAQwB;AAAA,UACZC;AAAA,UACAxB;AAAA,UACA,KAAK;AAAA,UACLoD,EAAY;AAAA,QACd,GAEMI,MACJ7H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC,GAEzC8H,IAASJ,EAAoB,OAAOtD,GAAcC,CAAM,GAExD8C,IAAqBlB;AAAA,UACzB6B;AAAA,UACA1D,EAAM;AAAA,UACNA,EAAM;AAAA,UACNqD,EAAY;AAAA,UACZI;AAAA,QACF;AAEI,eAAAJ,EAAY,iBAAiB,MACJP,GAAAC,GAAU,KAAK,MAAM,GAG3CA;AAAA,MACT;AAAA,IAAA;AAAA,EACF,CACD;AAEG,MAAAvG,EAAK,SAAS6G,EAAY;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGF,SAAOb,GAAwBa,GAAa;AAAA,IAC1C,MAAA7G;AAAA,IACA,gBAAgB,CAACwD,GAAOC,MAAW;;AACjC,YAAMwD,MACJ7H,IAAAY,EAAK,QAAQ,kBAAb,gBAAAZ,EAA4B,iBAAgB,CAAC,GAEzC8H,IAASJ,EAAoB,OAAOtD,GAAcC,CAAa;AAE9D,aAAA4B;AAAA,QACL6B;AAAA,QACA1D,EAAM;AAAA,QACNA,EAAM;AAAA,QACNqD,EAAY;AAAA,QACZA,EAAY;AAAA,QACZI;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA,IAGA,gBAAgB,CAACzD,GAAOC,MAAW;;AACjC,YAAMwD,MACJ7H,IAAAY,EAAK,QAAQ,kBAAb,gBAAAZ,EAA4B,iBAAgB,CAAC;AAE/C,UAAI8H,KAAS7H,IAAAyH,EAAoB,mBAApB,gBAAAzH,EAAA;AAAA,QAAAyH;AAAA,QACXtD;AAAA,QACAC;AAAA;AAEF,aAAIyD,MAAW,WACJA,IAAAJ,EAAoB,OAAOtD,GAAcC,CAAa,IAE1D4B;AAAA,QACL6B;AAAA,QACA1D,EAAM;AAAA,QACNA,EAAM;AAAA,QACNqD,EAAY;AAAA,QACZI;AAAA,MACF;AAAA,IAAA;AAAA,EACF,CACD;AACH;ACzMgB,SAAAE,EAAmBC,GAAWhH,GAAa;AACnD,QAAAiH,IAAOD,EAAI,QAAQhH,CAAG;AAI5B,MAAIiH,EAAK,aAAaA,EAAK,UAAU,KAAK,UAAU,SAAS;AACpD,WAAA;AAAA,MACL,eAAeA,EAAK;AAAA,MACpB,MAAMA,EAAK;AAAA,IACb;AAKF,MAAIC,IAAQD,EAAK,OACbrH,IAAOqH,EAAK,KAAKC,CAAK;AAC1B,SAAOA,IAAQ,KAAG;AAChB,QAAItH,EAAK,KAAK,UAAU,SAAS;AACxB,aAAA;AAAA,QACL,eAAeqH,EAAK,OAAOC,CAAK;AAAA,QAChC,MAAAtH;AAAA,MACF;AAGF,IAAAsH,KACOtH,IAAAqH,EAAK,KAAKC,CAAK;AAAA,EAAA;AASxB,QAAMC,IAAuC,CAAC;AAC1C,EAAAH,EAAA,YAAY,CAACpH,GAAMI,MAAQ;AAC7B,IAAIJ,EAAK,KAAK,UAAU,SAAS,KAC/BuH,EAA2B,KAAKnH,CAAG;AAAA,EACrC,CACD,GAGO,QAAA,KAAK,YAAYA,CAAG,uCAAuC;AAEnE,QAAMoH,IAAcJ,EAAI;AAAA,IACtBG,EAA2B,KAAK,CAACE,MAAaA,KAAYrH,CAAG,KAC3DmH,EAA2BA,EAA2B,SAAS,CAAC;AAAA,EACpE;AACO,SAAA;AAAA,IACL,eAAeC,EAAY;AAAA,IAC3B,MAAMA,EAAY;AAAA,EACpB;AACF;AAagB,SAAAE,GACd1H,GACA2H,GACW;AACX,MAAI,CAAC3H,EAAK,KAAK,UAAU,SAAS;AAChC,UAAM,IAAI;AAAA,MACR,8EAA8EA,EAAK,KAAK,IAAI;AAAA,IAC9F;AAGF,QAAM4H,IAAc5H,GACd6H,IAAmBF,GACnBG,IAAkBD,IAAmBD,EAAY,UAEjDG,IAA2B;AAAA,IAC/B,MAAMH;AAAA,IACN,WAAWC;AAAA,IACX,UAAUC;AAAA,EACZ;AAEI,MAAAF,EAAY,KAAK,SAAS,kBAAkB;AAC1C,QAAAzE,GACA6E;AA2BJ,QAzBYJ,EAAA,QAAQ,CAAC5H,GAAMiI,MAAW;AACpC,UAAIjI,EAAK,KAAK,KAAK,UAAU,gBAAgB;AAE3C,cAAMkI,IAAmBlI,GACnBmI,IAAwBN,IAAmBI,IAAS,GACpDG,IAAuBD,IAAwBnI,EAAK;AAE3C,QAAAmD,IAAA;AAAA,UACb,MAAM+E;AAAA,UACN,WAAWC;AAAA,UACX,UAAUC;AAAA,QACZ;AAAA,MACSpI,WAAAA,EAAK,KAAK,SAAS,cAAc;AAC1C,cAAMqI,IAAiBrI,GACjBsI,IAAsBT,IAAmBI,IAAS,GAClDM,IAAqBD,IAAsBtI,EAAK;AAEzC,QAAAgI,IAAA;AAAA,UACX,MAAMK;AAAA,UACN,WAAWC;AAAA,UACX,UAAUC;AAAA,QACZ;AAAA,MAAA;AAAA,IACF,CACD,GAEG,CAACpF;AACH,YAAM,IAAI;AAAA,QACR,6EAA6EyE,CAAW;AAAA,MAC1F;AAGK,WAAA;AAAA,MACL,kBAAkB;AAAA,MAClB,SAAAG;AAAA,MACA,cAAA5E;AAAA,MACA,gBAAgB6E;AAAA,MAChB,eAAe7E,EAAa,KAAK,KAAK;AAAA,IACxC;AAAA,EAAA,OACK;AACL,QAAI,CAAC4E,EAAQ,KAAK,KAAK,UAAU,gBAAgB;AAC/C,YAAM,IAAI;AAAA,QACR,oDAAoDA,EAAQ,IAAI;AAAA,MAClE;AAGK,WAAA;AAAA,MACL,kBAAkB;AAAA,MAClB,SAAAA;AAAA,MACA,gBAAgBA;AAAA,MAChB,eAAeA,EAAQ,KAAK,KAAK;AAAA,IACnC;AAAA,EAAA;AAEJ;AAYO,SAASS,GAAaC,GAAgD;AAC3E,SAAOf,GAA6Be,EAAQ,MAAMA,EAAQ,aAAa;AACzE;AASO,SAASC,GAA4BlB,GAA0B;AAChE,MAAA,CAACA,EAAY;AACf,UAAM,IAAI;AAAA,MACR,oDAAoDA,EAAY,GAAG;AAAA,IACrE;AAEF,SAAOE,GAA6BF,EAAY,WAAWA,EAAY,GAAG;AAC5E;AAQO,SAASmB,EAA0BC,GAAoB;AAC5D,QAAMH,IAAUtB,EAAmByB,EAAM,KAAKA,EAAM,UAAU,MAAM;AAEpE,SAAOJ,GAAaC,CAAO;AAC7B;AAQO,SAASI,GAA4B1J,GAAiB;AAC3D,QAAMsJ,IAAUtB,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,MAAM;AAE9D,SAAOqJ,GAAaC,CAAO;AAC7B;ACpPO,SAASK,EAAYC,GAA4B;AACtD,SAAI,SAASA,IACJA,EAAS,IAAI,KAAK,SAEpBA,EAAS,KAAK;AACvB;AAEA,SAASC,GAIPC,GAAgD;AAChD,SAAOA,EAAO,OAAO;AACvB;AAEO,SAASC,GAIdD,GAAgD;AACzC,SAAAD,GAAmBC,CAAM,EAAE;AAKpC;AAEO,SAASE,GACdF,GACS;AACF,SAAAC,GAAmBD,CAAM,EAAE;AACpC;AAEO,SAASG,GACdH,GACG;AACI,SAAAC,GAAmBD,CAAM,EAAE;AACpC;AAEO,SAASI,GAAsCJ,GAAmB;AAChE,SAAAC,GAAmBD,CAAM,EAAE;AACpC;AAEO,SAASK,GAAcL,GAAgB;AACrC,SAAAD,GAAmBC,CAAM,EAAE;AACpC;ACtBgB,SAAAM,GAGdC,GAAmBC,GAAwBC,GAAgB;;AAC3D,QAAMC,IAA0B;AAAA,IAC9B,MAAM;AAAA,IACN,cAAc,CAAC;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,MAAM,CAAA;AAAA,EACR,GAMMC,IAA4B,CAAC;AAEnC,EAAAJ,EAAY,QAAQ,QAAQ,CAACK,GAASC,GAASC,MAAa;AAC1D,UAAMC,IAAqC;AAAA,MACzC,OAAO,CAAA;AAAA,IACT;AAEA,IAAID,MAAa,KACPF,EAAA,QAAQ,QAAQ,CAACI,MAAa;AAChC,UAAAC,IAAWD,EAAS,MAAM;AAC1B,MAA0BC,KAAa,SAC9BA,IAAA,IAAI,MAAMD,EAAS,MAAM,WAAW,CAAC,EAAE,KAAK,MAAS,IAE9DN,EAAA,aAAa,KAAK,GAAGO,CAAQ;AAAA,IAAA,CAClC,GAGHF,EAAI,QAAQH,EAAQ,QAAQ,QAAQ,IAAI,CAACI,GAAUE,OAC5CP,EAAaG,CAAQ,MACXH,EAAAG,CAAQ,IAAI,CAAC,IAG5BH,EAAaG,CAAQ,EAAEI,CAAS,IAAIF,EAAS,KAAK,SAAS,eAoCpD;AAAA,MACL,MAAM;AAAA,MACN,SApCcA,EAAS,QAAQ,QAC9B;AAAA,QAAI,CAACG,MACJC,GAA2BD,GAAOX,GAAqBC,CAAW;AAAA,MAAA,EAKnE;AAAA,QACC,CAACY,GAAKC,MAAmB;AACnB,cAAA,CAACD,EAAI;AACA,mBAAAC;AAGT,gBAAMC,IAAOF,EAAIA,EAAI,SAAS,CAAC,GACzBG,IAAQF,EAAe,CAAC;AAG9B,iBACEE,KACApJ,GAA0BmJ,CAAI,KAC9BnJ,GAA0BoJ,CAAK,KAC/B,KAAK,UAAUD,EAAK,MAAM,MAAM,KAAK,UAAUC,EAAM,MAAM,KAGtDD,EAAA,QAAQ;AAAA,IAAOC,EAAM,MAC1BH,EAAI,KAAK,GAAGC,EAAe,MAAM,CAAC,CAAC,GAC5BD,MAELA,EAAA,KAAK,GAAGC,CAAc,GACnBD;AAAA,QACT;AAAA,QACA,CAAA;AAAA,MACF;AAAA,MAKA,OAAO;AAAA,QACL,SAASL,EAAS,MAAM;AAAA,QACxB,SAASA,EAAS,MAAM;AAAA,QACxB,iBAAiBA,EAAS,MAAM;AAAA,QAChC,WAAWA,EAAS,MAAM;AAAA,QAC1B,eAAeA,EAAS,MAAM;AAAA,MAAA;AAAA,IAElC,EACD,GAEGN,EAAA,KAAK,KAAKK,CAAG;AAAA,EAAA,CAClB;AAED,WAAShG,IAAI,GAAGA,IAAI4F,EAAa,QAAQ5F;AACvC,KAAI5E,IAAAwK,EAAa5F,CAAC,MAAd,QAAA5E,EAAiB,MAAM,CAACsL,MAAaA,OACnCf,EAAA,cAAcA,EAAI,cAAc,KAAK;AAI7C,WAAS3F,IAAI,GAAGA,MAAI3E,IAAAuK,EAAa,CAAC,MAAd,gBAAAvK,EAAiB,SAAQ2E;AAC3C,IAAI4F,KAAA,QAAAA,EAAc,MAAM,CAACI,MAAQA,EAAIhG,CAAC,OAChC2F,EAAA,cAAcA,EAAI,cAAc,KAAK;AAItC,SAAAA;AACT;AAKgB,SAAAU,GAGdb,GAAmBC,GAAwBC,GAAgB;AAC3D,QAAMvI,IAAmC,CAAC;AAC1C,MAAIwJ;AAIQ,SAAAnB,EAAA,QAAQ,QAAQ,CAACxJ,MAAS;AAGhC,QAAAA,EAAK,KAAK,SAAS,aAAa;AAClC,UAAI2K;AAEE,YAAAtJ,GAA0BsJ,CAAc;AAE1C,UAAAA,EAAe,QAAQ;AAAA;AAAA,iBACdzJ,GAAoByJ,CAAc;AAE3C,UAAAA,EAAe,QAAQA,EAAe,QAAQ,SAAS,CAAC,EAAE,QACxD;AAAA;AAAA;AAEI,gBAAA,IAAI,MAAM,YAAY;AAAA;AAIb,QAAAA,IAAA;AAAA,UACf,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,UACN,QAAQ,CAAA;AAAA,QACV;AAGF;AAAA,IAAA;AAGF,QAAI3K,EAAK,KAAK,SAAS,UAAUA,EAAK,KAAK,SAAS,QAAQ;AAC1D,UAAI,CAACyJ,EAAoBzJ,EAAK,KAAK,IAAI,GAAG;AAExC,gBAAQ,KAAK,oCAAoCA,EAAK,KAAK,IAAI;AAC/D;AAAA,MAAA;AAEF,MAAI2K,MACFxJ,EAAQ,KAAKwJ,CAAc,GACVA,IAAA,SAGXxJ,EAAA;AAAA,QACNyJ,GAA0B5K,GAAMyJ,GAAqBC,CAAW;AAAA,MAClE;AAEA;AAAA,IAAA;AAGF,UAAMmB,IAAoB,CAAC;AACvB,QAAAC;AAEO,eAAAC,KAAQ/K,EAAK;AAClB,UAAA+K,EAAK,KAAK,SAAS;AACV,QAAAD,IAAAC;AAAA,WACN;AACL,cAAMjF,IAAS4D,EAAYqB,EAAK,KAAK,IAAI;AACzC,YAAI,CAACjF,GAAQ;AACP,cAAAiF,EAAK,KAAK,KAAK;AAGjB;AAEF,gBAAM,IAAI,MAAM,SAASA,EAAK,KAAK,IAAI,2BAA2B;AAAA,QAAA;AAEhE,YAAAjF,EAAO,eAAe;AACvB,UAAA+E,EAAe/E,EAAO,IAAI,IAAI;AAAA,iBACtBA,EAAO,eAAe;AAC9B,UAAA+E,EAAe/E,EAAO,IAAI,IAAIiF,EAAK,MAAM;AAAA;AAEpC,gBAAA,IAAIhJ,EAAqB+D,EAAO,UAAU;AAAA,MAClD;AAMJ,IAAI6E,IAEEtJ,GAA0BsJ,CAAc,IACrCG,KAkBH3J,EAAQ,KAAKwJ,CAAc,GACVA,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAMG,EAAS,MAAM;AAAA,MACrB,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM9K,EAAK;AAAA,UACX,QAAA6K;AAAA,QAAA;AAAA,MACF;AAAA,IAEJ,KA1BE,KAAK,UAAUF,EAAe,MAAM,MAAM,KAAK,UAAUE,CAAM,IAG/DF,EAAe,QAAQ3K,EAAK,eAG5BmB,EAAQ,KAAKwJ,CAAc,GACVA,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAM3K,EAAK;AAAA,MACX,QAAA6K;AAAA,IACF,KAiBK3J,GAAoByJ,CAAc,MAEvCG,IAGEH,EAAe,SAASG,EAAS,MAAM,OAGvC,KAAK;AAAA,MACHH,EAAe,QAAQA,EAAe,QAAQ,SAAS,CAAC,EACrD;AAAA,IAAA,MACC,KAAK,UAAUE,CAAM,IAE3BF,EAAe,QAAQA,EAAe,QAAQ,SAAS,CAAC,EAAE,QACxD3K,EAAK,cAGP2K,EAAe,QAAQ,KAAK;AAAA,MAC1B,MAAM;AAAA,MACN,MAAM3K,EAAK;AAAA,MACX,QAAA6K;AAAA,IAAA,CACD,KAIH1J,EAAQ,KAAKwJ,CAAc,GACVA,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAMG,EAAS,MAAM;AAAA,MACrB,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM9K,EAAK;AAAA,UACX,QAAA6K;AAAA,QAAA;AAAA,MACF;AAAA,IAEJ,MAIF1J,EAAQ,KAAKwJ,CAAc,GACVA,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAM3K,EAAK;AAAA,MACX,QAAA6K;AAAA,IACF,MASCC,IAScH,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAMG,EAAS,MAAM;AAAA,MACrB,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM9K,EAAK;AAAA,UACX,QAAA6K;AAAA,QAAA;AAAA,MACF;AAAA,IAEJ,IAlBiBF,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAM3K,EAAK;AAAA,MACX,QAAA6K;AAAA,IACF;AAAA,EAgBJ,CACD,GAEGF,KACFxJ,EAAQ,KAAKwJ,CAAc,GAGtBxJ;AACT;AAEgB,SAAAyJ,GAGd5K,GAAYyJ,GAAwBC,GAAqC;AACzE,MAAI1J,EAAK,KAAK,SAAS,UAAUA,EAAK,KAAK,SAAS;AAC5C,UAAA,IAAI,MAAM,YAAY;AAE9B,QAAM2G,IAAa,CAAC,GACdqE,IAAWvB,EACfzJ,EAAK,KAAK,IACZ;AACW,aAAA,CAAC0F,GAAMrC,CAAK,KAAK,OAAO,QAAQrD,EAAK,KAAK,GAAG;AACtD,QAAI,CAACgL;AACH,YAAM,MAAM,yCAAyChL,EAAK,KAAK,IAAI;AAGrE,UAAM0E,IAAasG,EAAS;AAE5B,IAAItF,KAAQhB,MACViC,EAAMjB,CAAI,IAAIrC;AAAA,EAChB;AAGE,MAAAlC;AAEA,SAAA6J,EAAS,YAAY,WACb7J,IAAAkJ;AAAA,IACRrK;AAAA,IACAyJ;AAAA,IACAC;AAAA,EACF,IAEUvI,IAAA,QAGD;AAAA,IACT,MAAMnB,EAAK,KAAK;AAAA,IAChB,OAAA2G;AAAA,IACA,SAAAxF;AAAA,EACF;AAEF;AAOO,SAAS8J,EAKdjL,GACAiJ,GACAiC,IAAuB/B,GAAeF,CAAM,GAC5CQ,IAAyBL,GAAuBH,CAAM,GACtDS,IAAiBL,GAAeJ,CAAM,GACtCkC,IAAa7B,GAAcL,CAAM,GACX;;AACtB,MAAI,CAACjJ,EAAK,KAAK,UAAU,SAAS;AAChC,UAAM,MAAM,+CAA+CA,EAAK,KAAK,IAAI;AAGrE,QAAAoL,IAAcD,KAAA,gBAAAA,EAAY,IAAInL;AAEpC,MAAIoL;AACK,WAAAA;AAGH,QAAAC,IAAY3D,GAA6B1H,GAAM,CAAC;AAEtD,MAAIE,IAAKmL,EAAU,QAAQ,KAAK,MAAM;AAGtC,EAAInL,MAAO,SACJA,IAAAhC,GAAS,QAAQ,WAAW;AAG7B,QAAAoN,IAAYJ,EAAYG,EAAU,aAAa;AAErD,MAAI,CAACC;AACG,UAAA,MAAM,uCAAuCD,EAAU,aAAa;AAG5E,QAAM1E,IAAa,CAAC;AACpB,aAAW,CAACjB,GAAMrC,CAAK,KAAK,OAAO,QAAQ;AAAA,IACzC,GAAGrD,EAAK;AAAA,IACR,GAAIqL,EAAU,mBAAmBA,EAAU,aAAa,KAAK,QAAQ,CAAA;AAAA,EAAC,CACvE,GAAG;AACF,UAAM3G,IAAa4G,EAAU;AAG3B,IAAA5F,KAAQhB,KACR,EAAEA,EAAWgB,CAAI,EAAE,YAAY,UAAarC,MAAU,YAEtDsD,EAAMjB,CAAI,IAAIrC;AAAA,EAChB;AAGI,QAAAwD,IAAcqE,EAAYG,EAAU,aAAa,GAEjDE,IAAmC,CAAC;AAC1C,GAAAnM,IAAAiM,EAAU,mBAAV,QAAAjM,EAA0B,KAAK,QAAQ,CAACgL,MAAU;AACvC,IAAAmB,EAAA;AAAA,MACPN;AAAA,QACEb;AAAA,QACAnB;AAAA,QACAiC;AAAA,QACAzB;AAAA,QACAC;AAAA,QACAyB;AAAA,MAAA;AAAA,IAEJ;AAAA,EAAA;AAGE,MAAAhK;AAEA,MAAA0F,EAAY,YAAY,UAAU;AAChC,QAAA,CAACwE,EAAU;AACP,YAAA,IAAI,MAAM,YAAY;AAEpB,IAAAlK,IAAAkJ;AAAA,MACRgB,EAAU,aAAa;AAAA,MACvB5B;AAAA,MACAC;AAAA,IACF;AAAA,EAAA,WACS7C,EAAY,YAAY,SAAS;AACtC,QAAA,CAACwE,EAAU;AACP,YAAA,IAAI,MAAM,YAAY;AAEpB,IAAAlK,IAAAoI;AAAA,MACR8B,EAAU,aAAa;AAAA,MACvB5B;AAAA,MACAC;AAAA,IACF;AAAA,EAAA,WACS7C,EAAY,YAAY;AACvB,IAAA1F,IAAA;AAAA;AAEJ,UAAA,IAAIY,EAAqB8E,EAAY,OAAO;AAGpD,QAAMrD,IAAQ;AAAA,IACZ,IAAAtD;AAAA,IACA,MAAM2G,EAAY;AAAA,IAClB,OAAAF;AAAA,IACA,SAAAxF;AAAA,IACA,UAAAoK;AAAA,EACF;AAEY,SAAAJ,KAAA,QAAAA,EAAA,IAAInL,GAAMwD,IAEfA;AACT;AAKO,SAASgI,GAKdpE,GACA6B,GACAiC,IAAuB/B,GAAeF,CAAM,GAC5CQ,IAAyBL,GAAuBH,CAAM,GACtDS,IAAiBL,GAAeJ,CAAM,GACtCkC,IAAa7B,GAAcL,CAAM,GACjC;AACA,QAAMwC,IAAiC,CAAC;AACpC,SAAArE,EAAA,WAAY,YAAY,CAACpH,OACpByL,EAAA;AAAA,IACLR;AAAA,MACEjL;AAAA,MACAiJ;AAAA,MACAiC;AAAA,MACAzB;AAAA,MACAC;AAAA,MACAyB;AAAA,IAAA;AAAA,EAEJ,GACO,GACR,GACMM;AACT;AAqBO,SAASC,GAKd/K,GACAsI,GACAiC,IAAuB/B,GAAeF,CAAM,GAC5CQ,IAAyBL,GAAuBH,CAAM,GACtDS,IAAiBL,GAAeJ,CAAM,GACtCkC,IAAkD7B,GAAcL,CAAM,GActE;AAES,WAAA0C,EACP3L,GACA4L,GACAC,GAKA;AACI,QAAA7L,EAAK,KAAK,SAAS;AACf,YAAA,IAAI,MAAM,YAAY;AAE9B,UAAMyL,IAAiC,CAAC;AACpC,QAAAK,GACAC;AAEJ,WAAA/L,EAAK,QAAQ,CAACgM,GAAgBlC,GAAS7L,MAAU;AAC3C,UAAA+N,EAAe,KAAK,SAAS;AACzB,cAAA,IAAI,MAAM,YAAY;AAE1B,UAAAA,EAAe,eAAe;AAChC;AAEF,UAAIA,EAAe,eAAe,KAAKA,EAAe,aAAa;AACjE,cAAM,IAAI;AAAA,UACR,4CAA4CA,EAAe;AAAA,QAC7D;AAGF,YAAMC,IAAehO,MAAU,GACzBiO,IAAcjO,MAAU+B,EAAK,aAAa;AAEhD,UAAIgM,EAAe,WAAY,KAAK,SAAS,cAAc;AAOzD,YAAI,CAACC;AACG,gBAAA,IAAI,MAAM,YAAY;AAE9B,cAAMtC,IAAMgC;AAAA,UACVK,EAAe;AAAA,UACf,KAAK,IAAI,GAAGJ,IAAY,CAAC;AAAA,UACzBM,IAAc,KAAK,IAAI,GAAGL,IAAU,CAAC,IAAI;AAAA,QAC3C;AACA,QAAAC,IAAkBnC,EAAI,iBAClBuC,MACFH,IAAgBpC,EAAI,gBAEf8B,EAAA,KAAK,GAAG9B,EAAI,MAAM;AACzB;AAAA,MAAA;AAGF,YAAMnG,IAAQyH;AAAA,QACZe;AAAA,QACA/C;AAAA,QACAiC;AAAA,QACAzB;AAAA,QACAC;AAAA,QACAyB;AAAA,MACF,GACMgB,IACJH,EAAe,aAAa,IAAIA,EAAe,MAAM,CAAC,IAAI;AAE5D,UAAII,IAAsC,CAAC;AAC3C,UAAID,GAAY;AACd,cAAMxC,IAAMgC;AAAA,UACVQ;AAAA,UACA;AAAA;AAAA,UACAD,IAAc,KAAK,IAAI,GAAGL,IAAU,CAAC,IAAI;AAAA,QAC3C;AACA,QAAAO,IAAczC,EAAI,QACduC,MACFH,IAAgBpC,EAAI;AAAA,MACtB;AAGF,MAAIuC,KAAe,CAACC,KAAcN,IAAU,MAC1CE,IAAgBvI,EAAM,KAGpByI,KAAgBL,IAAY,MAC9BE,IAAkBtI,EAAM,KAG1BiI,EAAO,KAAK;AAAA,QACV,GAAIjI;AAAA,QACJ,UAAU4I;AAAA,MAAA,CACX;AAAA,IAAA,CACF,GAEM,EAAE,QAAAX,GAAQ,iBAAAK,GAAiB,eAAAC,EAAc;AAAA,EAAA;AAG9C,MAAApL,EAAM,QAAQ,eAAe;AACxB,WAAA;AAAA,MACL,QAAQ,CAAC;AAAA,MACT,iBAAiB;AAAA,MACjB,eAAe;AAAA,IACjB;AAGE,MAAAA,EAAM,QAAQ,eAAe;AAC/B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGK,SAAAgL;AAAA,IACLhL,EAAM,QAAQ;AAAA,IACd,KAAK,IAAIA,EAAM,YAAY,GAAG,CAAC;AAAA,IAC/B,KAAK,IAAIA,EAAM,UAAU,GAAG,CAAC;AAAA,EAC/B;AACF;AChqBO,SAAS0L,GAId/N,GAIAgO,GACAC,GACA7H,GAIA;AAEQ,SAAApG,EAAA,IAAI,aAAa,4BAA4BgO,CAAiB,GAG/D,OAAA,QAAQC,CAAkB,EAC9B,OAAO,CAAC,CAAC5G,GAAMtC,CAAK,MAAM;AACnB,UAAAyB,IAAOJ,EAAWiB,CAAI;AAC5B,WAAOtC,MAAUyB,EAAK;AAAA,EACvB,CAAA,EACA,IAAI,CAAC,CAACa,GAAMtC,CAAK,MACT,CAACe,GAAiBuB,CAAI,GAAGtC,CAAK,CACtC,EACA,QAAQ,CAAC,CAACsC,GAAMtC,CAAK,MAAM/E,EAAQ,IAAI,aAAaqH,GAAMtC,CAAK,CAAC,GAE/D/E,EAAQ,eAAe,UACjBA,EAAA,WAAW,aAAa,iBAAiB,EAAE,GAG9CA;AACT;AAGO,SAASkO,GAGd1G,GAGA;AACO,SAAA;AAAA,IACL,WAAW,CAAC,EAAE,QAAArC,QAAa;AACnB,YAAA+D,IAAc/D,EAAO,MAAM,UAAU;AAE3C,aACEA,EAAO,MAAM,UAAU,SACvB+D,EAAY,KAAA,EAAO,KAAK,SAAS1B,EAAO,QACxC0B,EAAY,iBAAiB;AAAA,IAAA;AAAA,EAGnC;AACF;AAIgB,SAAAiF,GACd3G,GACAG,GACA;AACO,SAAA;AAAA,IACL,QAAAH;AAAA,IACA,gBAAAG;AAAA,EACF;AACF;AAEgB,SAAAyG,GAGd1M,GAAS0E,GAAe;AACjB,SAAA+H;AAAA,IACL;AAAA,MACE,MAAMzM,EAAK;AAAA,MACX,YAAA0E;AAAA,MACA,SAAS1E,EAAK,OAAO,YAAY,YAAY,WAAW;AAAA,IAC1D;AAAA,IACA;AAAA,MACE,MAAAA;AAAA,IAAA;AAAA,EAEJ;AACF;AAEO,SAAS2M,GACdtG,GACA;AACA,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAK,EAAE,IAAI,CAAC,CAACzI,GAAKyF,CAAK,MAAM,CAACzF,GAAKyF,EAAM,MAAM,CAAC;AAAA,EACjE;AACF;ACvDO,SAASuJ,GACd9G,GACgB;AACT,SAAA;AAAA,IACL;AAAA,MACE,KAAK,8BAA8BA,EAAO,IAAI;AAAA,MAC9C,gBAAgB,CAACxH,MAAY;AAC3B,cAAMuO,IAAcvO;AAEhB,eAAAuO,EAAY,QAAQ,iBAAiB,IAChCA,IAGFA,EAAY,cAAc,iBAAiB,KAAKA;AAAA,MAAA;AAAA,IACzD;AAAA,EAEJ;AACF;AAEgB,SAAAC,GAIdC,GACAC,GACsB;AAChB,QAAAhN,IAAO+F,GAAK,OAAO;AAAA,IACvB,MAAMgH,EAAoB;AAAA,IAC1B,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,YAAYA,EAAoB,YAAY;AAAA,IAC5C,MAAMA,EAAoB,YAAY;AAAA,IACtC,SAAUA,EAAoB,YAAY,WACtC,YACA;AAAA,IAEJ,gBAAgB;AACP,aAAAtI,GAAkBsI,EAAoB,UAAU;AAAA,IACzD;AAAA,IAEA,uBAAuB;AACrB,aAAOP,GAAkCO,CAAmB;AAAA,IAC9D;AAAA,IAEA,YAAY;AACV,aAAOH,GAA2BG,CAAmB;AAAA,IACvD;AAAA,IAEA,WAAW,EAAE,MAAA/M,KAAQ;AACb,YAAAyD,IAAS,KAAK,QAAQ,QAEtByD,IAAS8F,EAA4B;AAAA,QACzCpC;AAAA,UACE5K;AAAAA,UACAyD,EAAO,OAAO;AAAA,UACdA,EAAO,OAAO;AAAA,QAChB;AAAA;AAAA,QACA,MAAM;AAAA,QAEN;AAAA,QACAA;AAAA,MACF;AAEO,aAAA4I;AAAA,QACLnF;AAAA,QACA6F,EAAoB;AAAA,QACpB/M,EAAK;AAAA,QACL+M,EAAoB;AAAA,MACtB;AAAA,IACF;AAAA,IAEA,cAAc;AACZ,aAAO,CAAC,EAAE,MAAA/M,GAAM,QAAAiF,QAAa;AACrB,cAAAxB,IAAS,KAAK,QAAQ,QAEtByD,IAAS8F,EAA4B;AAAA,UACzCpC;AAAA,YACE5K;AAAAA,YACAyD,EAAO,OAAO;AAAA,YACdA,EAAO,OAAO;AAAA,UAChB;AAAA;AAAA,UACA,CAACwJ,MAAW;AACN,gBAAA,OAAOhI,KAAW;AACpB;AAGF,kBAAM9D,IAAU+L,EAAqB,CAACD,CAAM,GAAGxJ,EAAO,QAAQ;AAEvD,YAAAA,EAAA;AAAA,cAAS,CAACtE,MACfA,EAAG,YAAY8F,KAAUA,EAAO,IAAIjF,EAAK,UAAUmB,CAAO;AAAA,YAC5D;AAAA,UACF;AAAA,UACAsC;AAAA,QACF;AAEO,eAAA4I;AAAA,UACLnF;AAAA,UACA6F,EAAoB;AAAA,UACpB/M,EAAK;AAAA,UACL+M,EAAoB;AAAA,QACtB;AAAA,MACF;AAAA,IAAA;AAAA,EACF,CACD;AAEM,SAAAL;AAAA,IACL1M;AAAA,IACA+M,EAAoB;AAAA,EACtB;AACF;ACvJO,SAASI,GACdzI,GACY;AACZ,SAAIA,MAAe,YACV,CAAC,IAEH;AAAA,IACL,aAAa;AAAA,MACX,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW,CAACpG,MAAYA,EAAQ,aAAa,YAAY;AAAA,MACzD,YAAY,CAACC,MACXA,EAAW,gBAAgB,SACvB;AAAA,QACE,cAAcA,EAAW;AAAA,MAAA,IAE3B,CAAA;AAAA,IAAC;AAAA,EAEX;AACF;AAKO,SAAS6O,GAId9O,GAIA+O,GACAC,GACA5I,GAIA;AAEQ,SAAApG,EAAA,IAAI,aAAa,mBAAmB+O,CAAS,GAGjD3I,MAAe,YACTpG,EAAA,IAAI,aAAa,cAAcgP,CAAoB,GAGzDhP,EAAQ,eAAe,UACjBA,EAAA,WAAW,aAAa,iBAAiB,EAAE,GAG9CA;AACT;AAIgB,SAAAiP,GACdzH,GACAG,GACA;AACO,SAAA;AAAA,IACL,QAAAH;AAAA,IACA,gBAAAG;AAAA,EACF;AACF;AAEgB,SAAAuH,GAGdzC,GAASrG,GAAe;AACjB,SAAA6I;AAAA,IACL;AAAA,MACE,MAAMxC,EAAK;AAAA,MACX,YAAArG;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAAqG;AAAA,IAAA;AAAA,EAEJ;AACF;AAEO,SAAS0C,GAA8CpH,GAAU;AACtE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAK,EAAE,IAAI,CAAC,CAACzI,GAAKyF,CAAK,MAAM,CAACzF,GAAKyF,EAAM,MAAM,CAAC;AAAA,EACjE;AACF;ACtEO,SAASqK,GAAmB5H,GAAkC;AAC5D,SAAA;AAAA,IACL;AAAA,MACE,KAAK,qBAAqBA,EAAO,IAAI;AAAA,MACrC,gBAAgB,CAACxH,MAAY;AAC3B,cAAMuO,IAAcvO;AAEhB,eAAAuO,EAAY,QAAQ,iBAAiB,IAChCA,IAGFA,EAAY,cAAc,iBAAiB,KAAKA;AAAA,MAAA;AAAA,IACzD;AAAA,EAEJ;AACF;AAEgB,SAAAc,GACdC,GACAC,GACc;AACR,QAAA9C,IAAO+C,GAAK,OAAO;AAAA,IACvB,MAAMF,EAAY;AAAA,IAElB,gBAAgB;AACP,aAAAT,GAAuBS,EAAY,UAAU;AAAA,IACtD;AAAA,IAEA,YAAY;AACV,aAAOF,GAAmBE,CAAW;AAAA,IACvC;AAAA,IAEA,WAAW,EAAE,MAAA7C,KAAQ;AACf,UAAAgD;AAKA,UAAAH,EAAY,eAAe;AAE7B,QAAAG,IAAeF,EAAoB,OAAO;AAAA,eACjCD,EAAY,eAAe;AACpC,QAAAG,IAAeF,EAAoB,OAAO9C,EAAK,MAAM,WAAW;AAAA;AAE1D,cAAA,IAAIhJ,EAAqB6L,EAAY,UAAU;AAIhD,aAAAR;AAAA,QACLW;AAAA,QACAH,EAAY;AAAA,QACZ7C,EAAK,MAAM;AAAA,QACX6C,EAAY;AAAA,MACd;AAAA,IAAA;AAAA,EACF,CACD;AAED,SAAOL,GAAwBK,GAAa;AAAA,IAC1C,MAAA7C;AAAA,EAAA,CACD;AACH;ACqGO,SAASiD,GACdxK,GACe;AACf,QAAM,EAAE,QAAAyK,GAAQ,OAAAC,MAAUC,GAAqB3K,CAAK,GAO9C4K,IAAsB,IAAI,MAAMH,CAAM,EACzC,KAAK,EAAK,EACV,IAAI,MAAM,IAAI,MAAMC,CAAK,EAAE,KAAK,IAAI,CAAC,GAGlCG,IAAoB,CAACrE,GAAasE,MAAgB;AACtD,aAAStK,IAAIgG,GAAKhG,IAAIiK,GAAQjK;AAC5B,eAASuK,IAAID,GAAKC,IAAIL,GAAOK;AAC3B,YAAI,CAACH,EAAKpK,CAAC,EAAEuK,CAAC;AACZ,iBAAO,EAAE,KAAKvK,GAAG,KAAKuK,EAAE;AAK9B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,WAASvE,IAAM,GAAGA,IAAMxG,EAAM,QAAQ,KAAK,QAAQwG;AACxC,aAAAsE,IAAM,GAAGA,IAAM9K,EAAM,QAAQ,KAAKwG,CAAG,EAAE,MAAM,QAAQsE,KAAO;AAC7D,YAAAzM,IAAOP,GAAakC,EAAM,QAAQ,KAAKwG,CAAG,EAAE,MAAMsE,CAAG,CAAC,GACtDE,IAAU1M,GAAWD,CAAI,GACzB4M,IAAU7M,GAAWC,CAAI,GAKzB,EAAE,KAAK6M,GAAU,KAAKC,MAAaN,EAAkBrE,GAAKsE,CAAG;AAGnE,eAAStK,IAAI0K,GAAU1K,IAAI0K,IAAWF,GAASxK;AAC7C,iBAASuK,IAAII,GAAUJ,IAAII,IAAWF,GAASF,KAAK;AAClD,cAAIH,EAAKpK,CAAC,EAAEuK,CAAC;AAEX,kBAAM,IAAI;AAAA,cACR,sDAAsDvK,CAAC,IAAIuK,CAAC;AAAA,YAC9D;AAGG,UAAAH,EAAApK,CAAC,EAAEuK,CAAC,IAAI;AAAA,YACX,KAAAvE;AAAA,YACA,KAAAsE;AAAA,YACA,SAAAE;AAAA,YACA,SAAAC;AAAA,YACA,MAAA5M;AAAA,UACF;AAAA,QAAA;AAAA,IAEJ;AAMG,SAAAuM;AACT;AAOO,SAASQ,GACdC,GACgC;AAG1B,QAAAnR,wBAAW,IAAY;AAEtB,SAAAmR,EAAc,IAAI,CAAC7E,OAEjB;AAAA,IACL,OAAOA,EACJ,IAAI,CAACnI,MACAnE,EAAK,IAAImE,EAAK,MAAM,MAAMA,EAAK,GAAG,IAC7B,MAETnE,EAAK,IAAImE,EAAK,MAAM,MAAMA,EAAK,GAAG,GAC3BA,EAAK,KACb,EACA,OAAO,CAACA,MAAsCA,MAAS,EAAK;AAAA,EACjE,EACD;AACH;AASO,SAASiN,GAIdC,GAIAvL,GAIAqL,IAA+Bb,GAA0BxK,CAAK,GAG9D;AACA,WAASwL,IAAI,GAAGA,IAAIH,EAAc,QAAQG;AACxC,aAASpM,IAAI,GAAGA,IAAIiM,EAAcG,CAAC,EAAE,QAAQpM,KAAK;AAEhD,YAAMf,IAAOgN,EAAcG,CAAC,EAAEpM,CAAC;AAC/B,UACEf,EAAK,QAAQkN,EAAoB,OACjClN,EAAK,QAAQkN,EAAoB;AAEjC,eAAO,EAAE,KAAKC,GAAG,KAAKpM,GAAG,MAAMf,EAAK,KAAK;AAAA,IAC3C;AAIJ,QAAM,IAAI;AAAA,IACR,oEAAoEkN,EAAoB,GAAG,IAAIA,EAAoB,GAAG;AAAA,EACxH;AACF;AAOO,SAASZ,GACd3K,GAUA;AAEM,QAAAyK,IAASzK,EAAM,QAAQ,KAAK;AAGlC,MAAI0K,IAAQ;AACZ,SAAA1K,EAAM,QAAQ,KAAK,QAAQ,CAACwG,MAAQ;AAElC,QAAIiF,IAAW;AACX,IAAAjF,EAAA,MAAM,QAAQ,CAACnI,MAAS;AAC1B,MAAAoN,KAAYrN,GAAWC,CAAI;AAAA,IAAA,CAC5B,GAGOqM,IAAA,KAAK,IAAIA,GAAOe,CAAQ;AAAA,EAAA,CACjC,GAEM,EAAE,QAAAhB,GAAQ,OAAAC,EAAM;AACzB;AAOO,SAASgB,GAIdC,GAIA3L,GAIAqL,IAA+Bb,GAA0BxK,CAAK,GAKlD;;AACZ,QAAM4L,KACJhQ,IAAAyP,EAAcM,EAAoB,GAAG,MAArC,gBAAA/P,EAAyC+P,EAAoB;AAG/D,MAAKC;AAKE,WAAA;AAAA,MACL,KAAKA,EAAc;AAAA,MACnB,KAAKA,EAAc;AAAA,MACnB,MAAMA,EAAc;AAAA,IACtB;AACF;AAiCgB,SAAAC,GACd7L,GACA8L,GACA;;AACM,QAAAT,IAAgBb,GAA0BxK,CAAK;AAErD,MAAI8L,IAAmB,KAAKA,KAAoBT,EAAc;AAC5D,WAAO,CAAC;AAIV,MAAIU,IAAc;AAGlB,WAAS,IAAI,GAAG,IAAID,GAAkB,KAAK;AACzC,UAAMzN,KAAOzC,IAAAyP,EAAcU,CAAW,MAAzB,gBAAAnQ,EAA6B;AAE1C,QAAI,CAACyC;AACH,aAAO,CAAC;AAIV,IAAA0N,KAAe1N,EAAK;AAAA,EAAA;AAItB,QAAM2N,IAAQ,IAAI,MAAMX,EAAc,CAAC,EAAE,MAAM,EAC5C,KAAK,EAAK,EACV,IAAI,CAACY,GAAInB,MACDY;AAAA,IACL,EAAE,KAAKK,GAAa,KAAAjB,EAAI;AAAA,IACxB9K;AAAA,IACAqL;AAAA,EACF,CACD,EACA;AAAA,IACC,CAACa,MACCA,MAAM;AAAA,EACV;AAGF,SAAOF,EAAM,OAAO,CAAC3N,GAAM5D,MAEvBuR,EAAM,UAAU,CAAC,MAAM,EAAE,QAAQ3N,EAAK,OAAO,EAAE,QAAQA,EAAK,GAAG,MAAM5D,CAExE;AACH;AAiCgB,SAAA0R,GACdnM,GACAoM,GACA;;AACM,QAAAf,IAAgBb,GAA0BxK,CAAK;AAErD,MACEoM,IAAsB,KACtBA,KAAuBf,EAAc,CAAC,EAAE;AAExC,WAAO,CAAC;AAIV,MAAIgB,IAAc;AAGlB,WAAS,IAAI,GAAG,IAAID,GAAqB,KAAK;AAC5C,UAAM/N,KAAOzC,IAAAyP,EAAc,CAAC,MAAf,gBAAAzP,EAAmByQ;AAEhC,QAAI,CAAChO;AACH,aAAO,CAAC;AAIV,IAAAgO,KAAehO,EAAK;AAAA,EAAA;AAItB,QAAM2N,IAAQ,IAAI,MAAMX,EAAc,MAAM,EACzC,KAAK,EAAK,EACV,IAAI,CAACY,GAAIzF,MACDkF;AAAA,IACL,EAAE,KAAAlF,GAAK,KAAK6F,EAAY;AAAA,IACxBrM;AAAA,IACAqL;AAAA,EACF,CACD,EACA;AAAA,IACC,CAACa,MACCA,MAAM;AAAA,EACV;AAGF,SAAOF,EAAM,OAAO,CAAC3N,GAAM5D,MAEvBuR,EAAM,UAAU,CAAC,MAAM,EAAE,QAAQ3N,EAAK,OAAO,EAAE,QAAQA,EAAK,GAAG,MAAM5D,CAExE;AACH;AAOO,SAAS6R,GACdtM,GACAuM,GACAC,GACAnB,IAA+Bb,GAA0BxK,CAAK,GAC9B;AAG1B,QAAA,EAAE,KAAKyM,EAAA,IAAsBnB;AAAA,IACjC;AAAA,MACE,KAAK;AAAA,MACL,KAAKiB;AAAA,IACP;AAAA,IACAvM;AAAA,IACAqL;AAAA,EACF,GACM,EAAE,KAAKqB,EAAA,IAAsBpB;AAAA,IACjC;AAAA,MACE,KAAK;AAAA,MACL,KAAKkB;AAAA,IACP;AAAA,IACAxM;AAAA,IACAqL;AAAA,EACF;AAOc,SAAAA,EAAA,QAAQ,CAAC7E,MAAQ;AAE7B,UAAM,CAACmG,CAAU,IAAInG,EAAI,OAAOiG,GAAmB,CAAC;AAChD,IAAAjG,EAAA,OAAOkG,GAAmB,GAAGC,CAAU;AAAA,EAAA,CAC5C,GAEMvB,GAA8BC,CAAa;AACpD;AAOO,SAASuB,GACd5M,GACA6M,GACAC,GACAzB,IAA+Bb,GAA0BxK,CAAK,GAC9B;AAG1B,QAAA,EAAE,KAAK+M,EAAA,IAAsBzB;AAAA,IACjC;AAAA,MACE,KAAKuB;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA7M;AAAA,IACAqL;AAAA,EACF,GACM,EAAE,KAAK2B,EAAA,IAAsB1B;AAAA,IACjC;AAAA,MACE,KAAKwB;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA9M;AAAA,IACAqL;AAAA,EACF,GAOM,CAAC4B,CAAS,IAAI5B,EAAc,OAAO0B,GAAmB,CAAC;AAC/C,SAAA1B,EAAA,OAAO2B,GAAmB,GAAGC,CAAS,GAE7C7B,GAA8BC,CAAa;AACpD;AAOA,SAAS6B,GACP7O,GAGS;AACT,SAAKA,IAGDL,GAAmBK,CAAI,IAClB6O,GAAY7O,EAAK,OAAO,IACtB,OAAOA,KAAS,WAClBA,EAAK,WAAW,IACd,MAAM,QAAQA,CAAI,IACpBA,EAAK;AAAA,IAAM,CAACe,MACjB,OAAOA,KAAM,WACTA,EAAE,WAAW,IACbvB,GAA0BuB,CAAC,IACzBA,EAAE,KAAK,WAAW,IAClBxB,GAA2BwB,CAAC,IAC1B,OAAOA,EAAE,WAAY,WACnBA,EAAE,QAAQ,WAAW,IACrBA,EAAE,QAAQ,MAAM,CAAC+N,MAAMA,EAAE,KAAK,WAAW,CAAC,IAC5C;AAAA,EACV,IAEO,KAnBA;AAqBX;AAOO,SAASC,GACdpN,GACAqN,GACAhC,IAA+Bb,GAA0BxK,CAAK,GAC9B;AAChC,MAAIqN,MAAgB,WAAW;AAE7B,QAAIC,IAAmB;AAEjB,aAAA3G,IAAY0E,EAAc,CAAC,EAAE,SAAS,GAC1C1E,KAAa,KAGG0E,EAAc;AAAA,MAC5B,CAAC7E,MACC0G,GAAY1G,EAAIG,CAAS,EAAE,IAAI,KAAKH,EAAIG,CAAS,EAAE,YAAY;AAAA,IACnE,GALAA;AAUA,MAAA2G;AAGF,aAAS,IAAIjC,EAAc,SAAS,GAAG,KAAK,GAAG,KAAK;AAElD,YAAMkC,IAAgB,KAAK;AAAA,QACzBlC,EAAc,CAAC,EAAE,SAASiC;AAAA,QAC1B;AAAA,MACF;AACA,MAAAjC,EAAc,CAAC,IAAIA,EAAc,CAAC,EAAE,MAAM,GAAGkC,CAAa;AAAA,IAAA;AAG5D,WAAOnC,GAA8BC,CAAa;AAAA,EAAA;AAIpD,MAAImC,IAAoB;AACxB,WAASjH,IAAW8E,EAAc,SAAS,GAAG9E,KAAY,KACxC8E,EAAc9E,CAAQ,EAAE;AAAA,IACtC,CAAClI,MAAS6O,GAAY7O,EAAK,IAAI,KAAKA,EAAK,YAAY;AAAA,EACvD,GAH2DkI;AAQ3D,IAAAiH;AAIF,QAAMC,IAAe,KAAK,IAAID,GAAmBnC,EAAc,SAAS,CAAC;AAEzE,SAAAA,EAAc,OAAOA,EAAc,SAASoC,GAAcA,CAAY,GAE/DrC,GAA8BC,CAAa;AACpD;AAOO,SAASqC,GACd1N,GACA2N,GAMAC,GACAvC,IAA+Bb,GAA0BxK,CAAK,GAC9B;AAChC,QAAM,EAAE,OAAA0K,GAAO,QAAAD,MAAWE,GAAqB3K,CAAK;AAEpD,MAAI2N,MAAY;AAEA,IAAAtC,EAAA,QAAQ,CAAC7E,GAAKD,MAAa;AACvC,UAAIqH,KAAY;AACd,iBAASpN,IAAI,GAAGA,IAAIoN,GAAUpN;AAC5B,UAAAgG,EAAI,KAAK;AAAA,YACP,KAAKD;AAAA,YACL,KAAK,KAAK,IAAI,GAAGC,EAAI,IAAI,CAACgF,MAAMA,EAAE,GAAG,CAAC,IAAI;AAAA,YAC1C,SAAS;AAAA,YACT,SAAS;AAAA,YACT,MAAM1N,GAAa,EAAE;AAAA,UAAA,CACtB;AAAA;AAIH,QAAA0I,EAAI,OAAOkE,IAAQkD,GAAU,KAAKA,CAAQ;AAAA,IAC5C,CACD;AAAA,WAEGA,IAAW;AAEb,aAAS,IAAI,GAAG,IAAIA,GAAU,KAAK;AAC3B,YAAAC,IAAS,IAAI,MAAMnD,CAAK,EAAE,KAAK,IAAI,EAAE,IAAI,CAACoD,GAAGC,OAAc;AAAA,QAC/D,KAAKtD,IAAS;AAAA,QACd,KAAKsD;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,QACT,MAAMjQ,GAAa,EAAE;AAAA,MAAA,EACrB;AACF,MAAAuN,EAAc,KAAKwC,CAAM;AAAA,IAAA;AAAA,MAE7B,CAAWD,IAAW,KAEpBvC,EAAc,OAAOZ,IAASmD,GAAU,KAAKA,CAAQ;AAIzD,SAAOxC,GAA8BC,CAAa;AACpD;AAKgB,SAAA2C,GACdhO,GACAiO,GACAC,GACA;AAEM,QAAAC,IAActC,GAAoB7L,GAAOkO,CAAc;AAI7D,MAAI,CADmBC,EAAY,KAAK,CAAC9P,MAASC,GAAWD,EAAK,IAAI,IAAI,CAAC;AAElE,WAAA;AAGT,MAAI+P,IAAcF,GACdG,IAAgBH;AACR,SAAAC,EAAA,QAAQ,CAAC9P,MAAS;AACtB,UAAA2M,IAAU1M,GAAWD,EAAK,IAAI;AACpC,IAAA+P,IAAc,KAAK,IAAIA,GAAa/P,EAAK,MAAM2M,IAAU,CAAC,GAC1DqD,IAAgB,KAAK,IAAIA,GAAehQ,EAAK,GAAG;AAAA,EAAA,CACjD,GAGsB4P,IAAgBC,IAKnCA,MAAmBE,IACnBF,MAAmBG;AACzB;AAKgB,SAAAC,GACdtO,GACAiO,GACAM,GACA;AAEM,QAAAJ,IAAchC,GAAuBnM,GAAOuO,CAAiB;AAInE,MAAI,CADmBJ,EAAY,KAAK,CAAC9P,MAASD,GAAWC,EAAK,IAAI,IAAI,CAAC;AAElE,WAAA;AAGT,MAAImQ,IAAiBD,GACjBE,IAAmBF;AACX,SAAAJ,EAAA,QAAQ,CAAC9P,MAAS;AACtB,UAAA4M,IAAU7M,GAAWC,EAAK,IAAI;AACpC,IAAAmQ,IAAiB,KAAK,IAAIA,GAAgBnQ,EAAK,MAAM4M,IAAU,CAAC,GAChEwD,IAAmB,KAAK,IAAIA,GAAkBpQ,EAAK,GAAG;AAAA,EAAA,CACvD,GAGuB4P,IAAgBM,IAKpCA,MAAsBC,IACtBD,MAAsBE;AAC5B;AAOgB,SAAAC,GACdC,GACAC,GACA5O,GACA;AAEM,QAAA6O,IAA4BvD,GAAsBqD,GAAM3O,CAAK,GAG7D8O,IAA0BxD,GAAsBsD,GAAI5O,CAAK;AAGxD,SAAA6O,EAA0B,QAAQC,EAAwB;AACnE;AC31BA,SAASC,GACPC,GACAvJ,GACAS,GACApE,GACQ;AACR,QAAMmN,IAAgB,CAAC;AAEZ,aAAA,CAACC,GAAOrP,CAAK,KAAK,OAAO,QAAQmP,EAAW,UAAU,CAAA,CAAE,GAAG;AAC9D,UAAA1M,IAAS4D,EAAYgJ,CAAK;AAChC,QAAI,CAAC5M;AACH,YAAM,IAAI,MAAM,SAAS4M,CAAK,2BAA2B;AAGvD,QAAA5M,EAAO,eAAe;AACxB,MAAA2M,EAAM,KAAKxJ,EAAO,KAAKyJ,CAAK,CAAC;AAAA,aACpB5M,EAAO,eAAe;AACzB,MAAA2M,EAAA,KAAKxJ,EAAO,KAAKyJ,GAAO,EAAE,aAAarP,EAAA,CAAO,CAAC;AAAA;AAE/C,YAAA,IAAItB,EAAqB+D,EAAO,UAAU;AAAA,EAClD;AAKF,SAFwB,CAACR,KAAa,CAAC2D,EAAO,MAAM3D,CAAS,EAAE,KAAK,OASlEkN,EAAW,KAER,MAAM,OAAO,EAGb,OAAO,CAACG,MAASA,EAAK,SAAS,CAAC,EAEhC,IAAI,CAACA,MACAA,MAAS;AAAA,IACJ1J,EAAO,MAAM,UAAa,cAAc,IAExCA,EAAO,KAAK0J,GAAMF,CAAK,CAEjC,IAnBID,EAAW,KAAK,SAAS,IAC5B,CAACvJ,EAAO,KAAKuJ,EAAW,MAAMC,CAAK,CAAC,IACpC,CAAC;AAmBT;AAMA,SAASG,GACPC,GACA5J,GACAS,GACQ;AACR,QAAMoB,IAAW7B,EAAO,MAAM,KAAK,OAAO;AAAA,IACxC,MAAM4J,EAAK;AAAA,EAAA,CACZ;AAED,SAAOC,GAAuBD,EAAK,SAAS5J,GAAQS,CAAW,EAAE;AAAA,IAC/D,CAAC1J,MAAS;AACJ,UAAAA,EAAK,KAAK,SAAS;AACrB,eAAOA,EAAK,KAAK,CAAC,GAAGA,EAAK,OAAO8K,CAAQ,CAAC;AAGxC,UAAA9K,EAAK,KAAK,SAAS;AACd,eAAAA;AAEH,YAAA,IAAI,MAAM,sBAAsB;AAAA,IAAA;AAAA,EAE1C;AACF;AAMA,SAAS8S,GACP3R,GACA8H,GACAS,GACApE,GACQ;AACR,QAAMyN,IAAgB,CAAC;AAEnB,MAAA,OAAO5R,KAAY;AACf,WAAA4R,EAAA;AAAA,MACJ,GAAGR;AAAA,QACD,EAAgB,MAAMpR,GAAS,QAAQ,GAAG;AAAA,QAC1C8H;AAAA,QACAS;AAAA,QACApE;AAAA,MAAA;AAAA,IAEJ,GACOyN;AAGT,aAAWP,KAAcrR;AACjB,IAAA4R,EAAA;AAAA,MACJ,GAAGR,GAAkBC,GAAYvJ,GAAQS,GAAapE,CAAS;AAAA,IACjE;AAEK,SAAAyN;AACT;AAKO,SAAS7F,EAId/J,GACA8F,GACA3D,GACAoE,IAAiBL,GAAeJ,CAAM,GAC9B;AACR,QAAM8J,IAAgB,CAAC;AAEvB,aAAW5R,KAAWgC;AAChB,IAAA,OAAOhC,KAAY,WACf4R,EAAA;AAAA,MACJ,GAAGD,GAAuB3R,GAAS8H,GAAQS,GAAapE,CAAS;AAAA,IACnE,IACSlE,GAA2BD,CAAO,IAC3C4R,EAAM,KAAK,GAAGH,GAAYzR,GAAS8H,GAAQS,CAAW,CAAC,IAC9CrI,GAA0BF,CAAO,IACpC4R,EAAA;AAAA,MACJ,GAAGD,GAAuB,CAAC3R,CAAO,GAAG8H,GAAQS,GAAapE,CAAS;AAAA,IACrE,IAEMyN,EAAA;AAAA,MACJC,GAAkC7R,GAAS8H,GAAQS,CAAW;AAAA,IAChE;AAGG,SAAAqJ;AACT;AAKO,SAASE,GAIdC,GACAjK,GACAS,IAA2BL,GAAeJ,CAAM,GACxC;AACR,QAAMkK,IAAmB,CAAC,GAGpBC,IAAa,IAAI,MAAMF,EAAa,cAAc,CAAC,EAAE,KAAK,EAAI,GAE9DG,IAAa,IAAI,MAAMH,EAAa,cAAc,CAAC,EAAE,KAAK,EAAI,GAE9DI,IAAuCJ,EAAa,gBAAgB,CAAC;AAE3E,WAASnJ,IAAW,GAAGA,IAAWmJ,EAAa,KAAK,QAAQnJ,KAAY;AAChE,UAAAC,IAAMkJ,EAAa,KAAKnJ,CAAQ,GAChCwJ,IAAsB,CAAC,GACvBC,IAAcJ,EAAWrJ,CAAQ;AACvC,aAASI,IAAY,GAAGA,IAAYH,EAAI,MAAM,QAAQG,KAAa;AAC3D,YAAAtI,IAAOmI,EAAI,MAAMG,CAAS,GAC1BsJ,IAAcJ,EAAWlJ,CAAS,GAIlCuJ,IAA2B;AAIjC,UAAIvS,IAAoD;AAGxD,YAAMwS,IAAoB7E;AAAA,QACxB;AAAA,UACE,KAAK/E;AAAA,UACL,KAAKI;AAAA,QACP;AAAA,QACA,EAAiB,SAAS+I,EAAa;AAAA,MACzC;AAGI,UAAAU,IAA0CN,EAC5CK,EAAkB,GACpB,IACI,CAACL,EAAaK,EAAkB,GAAG,CAAC,IACpC;AAEJ,UAAK9R,EAEL,KAAW,OAAOA,KAAS;AACf,QAAAV,IAAA8H,EAAO,KAAKpH,CAAI;AAAA,eACjBL,GAAmBK,CAAI,GAAG;AACnC,QAAIA,EAAK,YACGV,IAAA+L;AAAA,UACRrL,EAAK;AAAA,UACLoH;AAAA,UACA;AAAA,UACAS;AAAA,QACF;AAEI,cAAA+E,IAAU7M,GAAWC,CAAI;AAE/B,QAAI4M,IAAU,MAEDmF,IAAA,IAAI,MAAMnF,CAAO,EAAE,KAAK,EAAK,EAAE,IAAI,CAAC6C,GAAGtN,MAEzCsP,EAAaK,EAAkB,MAAM3P,CAAC,KAAK,MACnD;AAAA,MACH;AAEU,QAAA7C,IAAA+L;AAAA,UACRrL;AAAA,UACAoH;AAAA,UACA;AAAA,UACAS;AAAA,QACF;AAGF,YAAMO,IAAWhB,EAAO,MACtBwK,KAAeD,IAAc,gBAAgB,WAC/C,EAAE;AAAA,QACA;AAAA,UACE,GAAIhS,GAAmBK,CAAI,IAAIA,EAAK,QAAQ,CAAC;AAAA,UAC7C,UAAA+R;AAAA,QACF;AAAA,QACA3K,EAAO,MAAM,eAAkB,cAAcyK,GAAOvS,CAAO;AAAA,MAC7D;AACA,MAAAoS,EAAY,KAAKtJ,CAAQ;AAAA,IAAA;AAGrB,UAAAJ,IAAUZ,EAAO,MAAM,SAAY,cAAc,IAAIsK,CAAW;AACtE,IAAAJ,EAAS,KAAKtJ,CAAO;AAAA,EAAA;AAEhB,SAAAsJ;AACT;AAEA,SAASH,GACPxP,GAGAyF,GACAS,GACA;AACI,MAAAF,GACArE,IAAO3B,EAAM;AAOjB,MAJI2B,MAAS,WACJA,IAAA,cAGL,CAAC8D,EAAO,MAAM9D,CAAI;AACpB,UAAM,IAAI,MAAM,aAAaA,CAAI,sBAAsB;AAGrD,MAAA,CAAC3B,EAAM;AACT,IAAAgG,IAAcP,EAAO,MAAM9D,CAAI,EAAE,cAAc3B,EAAM,KAAK;AAAA,WACjD,OAAOA,EAAM,WAAY,UAAU;AAC5C,UAAMuP,IAAQ7F;AAAA,MACZ,CAAC1J,EAAM,OAAO;AAAA,MACdyF;AAAA,MACA9D;AAAA,MACAuE;AAAA,IACF;AACA,IAAAF,IAAcP,EAAO,MAAM9D,CAAI,EAAE,cAAc3B,EAAM,OAAOuP,CAAK;AAAA,EACxD,WAAA,MAAM,QAAQvP,EAAM,OAAO,GAAG;AACvC,UAAMuP,IAAQ7F;AAAA,MACZ1J,EAAM;AAAA,MACNyF;AAAA,MACA9D;AAAA,MACAuE;AAAA,IACF;AACA,IAAAF,IAAcP,EAAO,MAAM9D,CAAI,EAAE,cAAc3B,EAAM,OAAOuP,CAAK;AAAA,EACxD,WAAAvP,EAAM,QAAQ,SAAS,gBAAgB;AAChD,UAAMuP,IAAQE,GAAoBzP,EAAM,SAASyF,GAAQS,CAAW;AACpE,IAAAF,IAAcP,EAAO,MAAM9D,CAAI,EAAE,cAAc3B,EAAM,OAAOuP,CAAK;AAAA,EAAA;AAEjE,UAAM,IAAIhR,EAAqByB,EAAM,QAAQ,IAAI;AAE5C,SAAAgG;AACT;AAKO,SAAS9F,GACdF,GACAyF,GACAS,IAA2BL,GAAeJ,CAAM,GAChD;AACA,MAAI/I,IAAKsD,EAAM;AAEf,EAAItD,MAAO,WACJA,IAAAhC,GAAS,QAAQ,WAAW;AAGnC,QAAMqN,IAAmB,CAAC;AAE1B,MAAI/H,EAAM;AACG,eAAA4G,KAAS5G,EAAM;AACxB,MAAA+H,EAAS,KAAK7H,GAAY0G,GAAOnB,GAAQS,CAAW,CAAC;AAQzD,MAHE,CAAClG,EAAM;AAAA,EACPyF,EAAO,MAAMzF,EAAM,IAAI,EAAE,UAAU,cAAc,GAE/B;AAGlB,UAAMgG,IAAcwJ;AAAA,MAClBxP;AAAA,MACAyF;AAAA,MACAS;AAAA,IACF,GAEMmK,IACJtI,EAAS,SAAS,IACdtC,EAAO,MAAM,WAAc,cAAc,IAAIsC,CAAQ,IACrD;AAEC,WAAAtC,EAAO,MAAM,eAAkB;AAAA,MACpC;AAAA,QACE,IAAA/I;AAAA,QACA,GAAGsD,EAAM;AAAA,MACX;AAAA,MACAqQ,IAAY,CAACrK,GAAaqK,CAAS,IAAIrK;AAAA,IACzC;AAAA,EAAA,OACF;AAAA,QAAWP,EAAO,MAAMzF,EAAM,IAAI,EAAE,UAAU,SAAS;AAErD,aAAOyF,EAAO,MAAMzF,EAAM,IAAI,EAAE;AAAA,QAC9B;AAAA,UACE,IAAAtD;AAAA,UACA,GAAGsD,EAAM;AAAA,QACX;AAAA,QACA+H;AAAA,MACF;AAEA,UAAM,IAAI;AAAA,MACR,cAAc/H,EAAM,IAAI;AAAA,IAC1B;AAAA;AAEJ;ACnWgB,SAAAsQ,EACd5T,GACAkH,GACmD;AACnD,MAAI2M,GACAC;AAmBA,MAjBJ5M,EAAI,WAAY,YAAY,CAACpH,GAAMI,MAE7B2T,IACK,KAIL,CAACE,GAAYjU,CAAI,KAAKA,EAAK,MAAM,OAAOE,IACnC,MAGI6T,IAAA/T,GACbgU,IAAgB5T,IAAM,GAEf,GACR,GAEG,EAAA2T,MAAe,UAAaC,MAAkB;AAI3C,WAAA;AAAA,MACL,MAAMD;AAAA,MACN,eAAAC;AAAA,IACF;AACF;AAEO,SAASC,GAAYjU,GAAqB;AACxC,SAAAA,EAAK,KAAK,UAAU,SAAS;AACtC;AA2EA,SAASkU,GAKPC,GACAC,GACS;AAIP,SAAAD,EAAO,OAAOC,EAAO,MACrBD,EAAO,SAASC,EAAO,QACvB,KAAK,UAAUD,EAAO,KAAK,MAAM,KAAK,UAAUC,EAAO,KAAK,KAC5D,KAAK,UAAUD,EAAO,OAAO,MAAM,KAAK,UAAUC,EAAO,OAAO;AAEpE;AAQO,SAASC,GAKdpV,GACAqV,IAAsC,IACI;AACtC,MAAAC,IAA4B,EAAE,MAAM,QAAQ;AAE5C,EAAAtV,EAAY,QAAQ,OAAO,IACpBsV,IAAA,EAAE,MAAM,QAAQ,IAChBtV,EAAY,QAAQ,SAAS,MAAM,SACnCsV,IAAA,EAAE,MAAM,OAAO,IACftV,EAAY,QAAQ,UAAU,IAC9BsV,IAAA;AAAA,IACP,MAAMtV,EAAY,QAAQ,UAAU,EAAE,OAAO,SAAS;AAAA,EACxD,IACSA,EAAY,QAAQ,SAAS,MAClCA,EAAY,QAAQ,SAAS,EAAE,sBACxBsV,IAAA;AAAA,IACP,MAAM;AAAA,EACR,IAESA,IAAA;AAAA,IACP,MAAM;AAAA,EACR;AAKE,QAAAC,IAAW1L,EAAY7J,CAAW,GAClCwV,IAAsB/U,GAAwBT,EAAY,QAAQ;AAAA,IACtEA;AAAA,IACA,GAAGqV;AAAA,EAAA,CACJ,GAEKI,IAAgB9U,GAAiB6U,CAAmB,GACpDE,IAAqBD,EACxB,QAAQ,CAACE,MACD7U;AAAA,IACL0U,EAAoB;AAAA,IACpBG,EAAM;AAAA,IACNX;AAAA,EACF,CACD,EACA,IAAI,CAAC,EAAE,MAAAjU,EAAW,MAAAiL,EAAYjL,GAAMwU,CAAQ,CAAC,GAE1CK,IAAqBH,EACxB,QAAQ,CAACE,MACD7U;AAAA,IACL0U,EAAoB;AAAA,IACpBG,EAAM;AAAA,IACNX;AAAA,EACF,CACD,EACA,IAAI,CAAC,EAAE,MAAAjU,EAAW,MAAAiL,EAAYjL,GAAMwU,CAAQ,CAAC,GAE1CM,IAAa,IAAI;AAAA,IACrBD,EAAmB,IAAI,CAACrR,MACf,CAACA,EAAM,IAAIA,CAAK,CACxB;AAAA,EACH,GACMuR,IAAa,IAAI;AAAA,IACrBJ,EAAmB,IAAI,CAACnR,MACf,CAACA,EAAM,IAAIA,CAAK,CACxB;AAAA,EACH,GAEMwR,IAAoD,CAAC;AAG3D,aAAW,CAAC9U,GAAIsD,CAAK,KAAKsR;AACxB,IAAKC,EAAW,IAAI7U,CAAE,KACpB8U,EAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAAxR;AAAA,MACA,QAAA+Q;AAAA,MACA,WAAW;AAAA,IAAA,CACZ;AAKL,aAAW,CAACrU,GAAIsD,CAAK,KAAKuR;AACxB,IAAKD,EAAW,IAAI5U,CAAE,KACpB8U,EAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAAxR;AAAA,MACA,QAAA+Q;AAAA,MACA,WAAW;AAAA,IAAA,CACZ;AAKL,aAAW,CAACrU,GAAIsD,CAAK,KAAKsR;AACpB,QAAAC,EAAW,IAAI7U,CAAE,GAAG;AAChB,YAAA+U,IAAYF,EAAW,IAAI7U,CAAE;AAG/B,MAAAgU,GAAoCe,GAAWzR,CAAK,KACtDwR,EAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,OAAAxR;AAAA,QACA,WAAAyR;AAAA,QACA,QAAAV;AAAA,MAAA,CACD;AAAA,IACH;AAIG,SAAAS;AACT;AC/PO,SAASE,GAKd/V,GACAgW,GACAC,GACAC,IAAgC,UACR;AACxB,QAAMnV,IACJ,OAAOkV,KAAmB,WAAWA,IAAiBA,EAAe,IACjEZ,IAAW1L,EAAY3J,CAAE,GACzBmW,IAAgBH,EAAe;AAAA,IAAI,CAAC3R,MACxCE,GAAYF,GAAOgR,CAAQ;AAAA,EAC7B,GAEM/L,IAAUqL,EAAY5T,GAAIf,EAAG,GAAG;AACtC,MAAI,CAACsJ;AACH,UAAM,IAAI,MAAM,iBAAiBvI,CAAE,YAAY;AAGjD,MAAIE,IAAMqI,EAAQ;AAClB,SAAI4M,MAAc,YAChBjV,KAAOqI,EAAQ,KAAK,WAGnBtJ,EAAA;AAAA,IACD,IAAIoW,GAAYnV,GAAKA,GAAK,IAAIa,EAAMD,EAAS,KAAKsU,CAAa,GAAG,GAAG,CAAC,CAAC;AAAA,EACzE,GAIuBA,EAAc;AAAA,IAAI,CAACtV,MACxCiL,EAAYjL,GAAMwU,CAAQ;AAAA,EAC5B;AAGF;ACxCgB,SAAAgB,GAKdrW,GACAsW,GACAN,GAIA;AACM,QAAAX,IAAW1L,EAAY3J,CAAE,GAGzBmW,IAAwBH,EAAe;AAAA,IAAI,CAAC3R,MAChDE,GAAYF,GAAOgR,CAAQ;AAAA,EAC7B,GAEMkB,IAAsB,IAAI;AAAA,IAC9BD,EAAe;AAAA,MAAI,CAACjS,MAClB,OAAOA,KAAU,WAAWA,IAAQA,EAAM;AAAA,IAAA;AAAA,EAE9C,GACMmS,IAAwC,CAAC,GAEzCC,IACJ,OAAOH,EAAe,CAAC,KAAM,WACzBA,EAAe,CAAC,IAChBA,EAAe,CAAC,EAAE;AACxB,MAAII,IAAc;AAiDd,MA/CJ1W,EAAG,IAAI,YAAY,CAACa,GAAMI,MAAQ;AAE5B,QAAAsV,EAAoB,SAAS;AACxB,aAAA;AAIT,QACE,CAAC1V,EAAK,KAAK,UAAU,SAAS,KAC9B,CAAC0V,EAAoB,IAAI1V,EAAK,MAAM,EAAE;AAE/B,aAAA;AAOT,QAHA2V,EAAc,KAAK1K,EAAYjL,GAAMwU,CAAQ,CAAC,GAC1BkB,EAAA,OAAO1V,EAAK,MAAM,EAAE,GAEpCmV,EAAe,SAAS,KAAKnV,EAAK,MAAM,OAAO4V,GAAgB;AAC3DE,YAAAA,IAAa3W,EAAG,IAAI;AACvB,MAAAA,EAAA,OAAOiB,GAAKkV,CAAa;AACtBS,YAAAA,IAAa5W,EAAG,IAAI;AAE1B,MAAA0W,KAAeC,IAAaC;AAAAA,IAAA;AAGxB,UAAAD,IAAa3W,EAAG,IAAI,UAIpBkI,IAAOlI,EAAG,IAAI,QAAQiB,IAAMyV,CAAW;AAC7C,IACExO,EAAK,KAAK,EAAE,KAAK,SAAS,gBAC1BA,EAAK,KAAKA,EAAK,QAAQ,CAAC,EAAE,KAAK,SAAS,SACxCA,EAAK,KAAK,EAAE,eAAe,IAE3BlI,EAAG,OAAOkI,EAAK,OAAA,GAAUA,EAAK,OAAO,IAErClI,EAAG,OAAOiB,IAAMyV,GAAazV,IAAMyV,IAAc7V,EAAK,QAAQ;AAE1D,UAAA+V,IAAa5W,EAAG,IAAI;AAC1B,WAAA0W,KAAeC,IAAaC,GAErB;AAAA,EAAA,CACR,GAGGL,EAAoB,OAAO,GAAG;AAChC,UAAMM,IAAc,CAAC,GAAGN,CAAmB,EAAE,KAAK;AAAA,CAAI;AAEhD,UAAA;AAAA,MACJ,qEACEM;AAAA,IACJ;AAAA,EAAA;AAQK,SAAA,EAAE,gBAJcV,EAAc;AAAA,IAAI,CAACtV,MACxCiL,EAAYjL,GAAMwU,CAAQ;AAAA,EAC5B,GAEyB,eAAAmB,EAAc;AACzC;AC5Ea,MAAAM,IAAqB,CAKhCC,GACA1S,MAEO,CAAC;AAAA,EACN,IAAArE;AAAA,EACA,UAAAgX;AAAA,OAKIA,KACYC,GAAAjX,GAAI+W,GAAgB1S,CAAK,GAElC;AAIJ,SAAS4S,GAKdjX,GACA+W,GACA1S,GACA6S,GACAC,GACA;AACA,QAAMjL,IAAY3C,GAA4BvJ,EAAG,IAAI,QAAQ+W,CAAc,CAAC,GAEtE1B,IAAW1L,EAAY3J,CAAE;AAE/B,MACEkX,MAAmB,UACnBC,MAAiB,UACjBD,IAAiBC;AAEX,UAAA,IAAI,MAAM,wCAAwC;AAK1D,QAAMC,IAAc/B,EAAS,MAAMnJ,EAAU,aAAa,GACpDmL,IAAchC,EAAS,MAAMhR,EAAM,QAAQ6H,EAAU,aAAa,GAClEoL,IAAqBD,EAAY,UAAU,SAAS,IACtDA,IACAhC,EAAS,MAAM;AAEnB,MAAInJ,EAAU,oBAAoBmL,EAAY,UAAU,cAAc,GAAG;AACvE,UAAME,IACJL,MAAmB,UACnBA,IAAiBhL,EAAU,aAAa,aACxCgL,IAAiBhL,EAAU,aAAa,WACpCgL,IAAiBhL,EAAU,aAAa,YAAY,IACpD,QAEAsL,IACJL,MAAiB,UACjBA,IAAejL,EAAU,aAAa,aACtCiL,IAAejL,EAAU,aAAa,WAClCiL,IAAejL,EAAU,aAAa,YAAY,IAClD;AAES,IAAAuL,GAAApT,GAAOrE,GAAIkM,CAAS,GAGnCwL;AAAA,MACErT;AAAA,MACArE;AAAA,MACAoX;AAAA,MACAC;AAAA,MACAnL;AAAA,MACAqL;AAAA,MACAC;AAAA,IACF;AAAA,EAAA,WACS,CAACtL,EAAU,oBAAoBmL,EAAY,UAAU,SAAS;AACxD,IAAAI,GAAApT,GAAOrE,GAAIkM,CAAS;AAAA,OAG9B;AAQL,UAAMyL,IAAgB7L,EAAYI,EAAU,QAAQ,MAAMmJ,CAAQ;AAC/D,IAAArV,EAAA;AAAA,MACDkM,EAAU,QAAQ;AAAA,MAClBA,EAAU,QAAQ;AAAA,MAClB3H;AAAA,QACE;AAAA,UACE,UAAUoT,EAAc;AAAA;AAAA,UACxB,GAAGtT;AAAA,QACL;AAAA,QACAgR;AAAA,MAAA;AAAA,IAEJ;AAEA;AAAA,EAAA;AAKF,EAAArV,EAAG,cAAckM,EAAU,QAAQ,WAAWoL,GAAoB;AAAA,IAChE,GAAGpL,EAAU,QAAQ,KAAK;AAAA,IAC1B,GAAG7H,EAAM;AAAA,EAAA,CACV;AACH;AAEA,SAASqT,GAKPrT,GACArE,GACAoX,GACAC,GACAnL,GAMAqL,GACAC,GACA;AACM,QAAAnC,IAAW1L,EAAY3J,CAAE;AAC/B,MAAIgC,IAA6B;AAGjC,MAAIqC,EAAM;AACJ,QAAA,OAAOA,EAAM,WAAY;AAEjB,MAAArC,IAAA+L;AAAA,QACR,CAAC1J,EAAM,OAAO;AAAA,QACdgR;AAAA,QACAgC,EAAY;AAAA,MACd;AAAA,aACS,MAAM,QAAQhT,EAAM,OAAO;AAGpC,MAAArC,IAAU+L,EAAqB1J,EAAM,SAASgR,GAAUgC,EAAY,IAAI;AAAA,aAC/DhT,EAAM,QAAQ,SAAS;AACtB,MAAArC,IAAA8R,GAAoBzP,EAAM,SAASgR,CAAQ;AAAA;AAErD,YAAM,IAAIzS,EAAqByB,EAAM,QAAQ,IAAI;AAAA;AAO/C,IAAA+S,EAAY,KAAK,YAAY,MAGtBC,EAAY,KAAK,YAAYD,EAAY,KAAK,YAEvDpV,IAAU,CAAC;AAYf,MAAIA,MAAY;AAEd,IAAAhC,EAAG,cAAckM,EAAU,aAAa,WAAWmL,GAAa;AAAA,MAC9D,GAAGnL,EAAU,aAAa,KAAK;AAAA,MAC/B,GAAG7H,EAAM;AAAA,IAAA,CACV;AAAA,WACQkT,MAAsB,UAAaC,MAAoB,QAAW;AAE3E,IAAAxX,EAAG,cAAckM,EAAU,aAAa,WAAWmL,GAAa;AAAA,MAC9D,GAAGnL,EAAU,aAAa,KAAK;AAAA,MAC/B,GAAG7H,EAAM;AAAA,IAAA,CACV;AAED,UAAMuT,IACJ1L,EAAU,aAAa,YAAY,KAAKqL,KAAqB,IACzDM,IACJ3L,EAAU,aAAa,YACvB,KACCsL,KAAmBtL,EAAU,aAAa,KAAK,QAAQ,OAKpD4L,IAAe9X,EAAG,IAAI,QAAQkM,EAAU,aAAa,SAAS,EAAE,OAChE6L,IAAa/X,EAAG,IAAI,QAAQ4X,CAAK,EAAE,OACnCI,IAAWhY,EAAG,IAAI,QAAQ6X,CAAG,EAAE;AAElC,IAAA7X,EAAA;AAAA,MACD4X;AAAA,MACAC;AAAA,MACA,IAAI/V;AAAA,QACFD,EAAS,KAAKG,CAAO;AAAA,QACrB+V,IAAaD,IAAe;AAAA,QAC5BE,IAAWF,IAAe;AAAA,MAAA;AAAA,IAE9B;AAAA,EAAA;AAKG,IAAA9X,EAAA;AAAA,MACDkM,EAAU,aAAa;AAAA,MACvBA,EAAU,aAAa;AAAA,MACvBmL,EAAY;AAAA,QACV;AAAA,UACE,GAAGnL,EAAU,aAAa,KAAK;AAAA,UAC/B,GAAG7H,EAAM;AAAA,QACX;AAAA,QACArC;AAAA,MAAA;AAAA,IAEJ;AAEJ;AAEA,SAASyV,GAIPpT,GAAoCrE,GAAekM,GAAsB;AACnE,QAAAmJ,IAAW1L,EAAY3J,CAAE;AAC/B,MAAIqE,EAAM,aAAa,UAAaA,EAAM,SAAS,SAAS,GAAG;AAC7D,UAAM4T,IAAa5T,EAAM,SAAS,IAAI,CAAC4G,MAC9B1G,GAAY0G,GAAOoK,CAAQ,CACnC;AAGD,QAAInJ,EAAU;AAIT,MAAAlM,EAAA;AAAA,QACD,IAAIoW;AAAA,UACFlK,EAAU,eAAe,YAAY;AAAA,UACrCA,EAAU,eAAe,WAAW;AAAA,UACpC,IAAIpK,EAAMD,EAAS,KAAKoW,CAAU,GAAG,GAAG,CAAC;AAAA,QAAA;AAAA,MAE7C;AAAA,SACK;AACD,UAAA,CAAC/L,EAAU;AACP,cAAA,IAAI,MAAM,YAAY;AAG3B,MAAAlM,EAAA;AAAA,QACDkM,EAAU,aAAa;AAAA,QACvBmJ,EAAS,MAAM,WAAc,cAAc,IAAI4C,CAAU;AAAA,MAC3D;AAAA,IAAA;AAAA,EACF;AAEJ;AAEO,SAASC,GAKdlY,GACAmY,GACArK,GACAoJ,GACAC,GACsB;AACtB,QAAMpW,IACJ,OAAOoX,KAAkB,WAAWA,IAAgBA,EAAc,IAC9D7O,IAAUqL,EAAY5T,GAAIf,EAAG,GAAG;AACtC,MAAI,CAACsJ;AACH,UAAM,IAAI,MAAM,iBAAiBvI,CAAE,YAAY;AAGjD,EAAAkW;AAAA,IACEjX;AAAA,IACAsJ,EAAQ;AAAA,IACRwE;AAAA,IACAoJ;AAAA,IACAC;AAAA,EACF;AAEM,QAAAiB,IAAqBpY,EAAG,IAC3B,QAAQsJ,EAAQ,gBAAgB,CAAC,EACjC,KAAK,GAEF+L,IAAW1L,EAAY3J,CAAE;AACxB,SAAA8L,EAAYsM,GAAoB/C,CAAQ;AACjD;AC3TA,SAASgD,GAA8BlZ,GAAsB;AAE3D,QAAMmZ,IACJ,MAAM,KAAKnZ,EAAQ,SAAS,EAAE;AAAA,IAC5B,CAACmZ,MAAc,CAACA,EAAU,WAAW,KAAK;AAAA,EAAA,KACvC,CAAC;AAEJ,EAAAA,EAAU,SAAS,IACbnZ,EAAA,YAAYmZ,EAAU,KAAK,GAAG,IAEtCnZ,EAAQ,gBAAgB,OAAO;AAEnC;AAEO,SAASoZ,GAKdjU,GACAN,GACAwU,GACAC,GACA;AACI,MAAA7E;AAGJ,MAAK5P;AAEL,QAAW,OAAOA,KAAiB;AACjC,MAAA4P,IAAQ7F,EAAqB,CAAC/J,CAAY,GAAGM,EAAO,QAAQ;AAAA,aACnD,MAAM,QAAQN,CAAY;AAC3B,MAAA4P,IAAA7F,EAAqB/J,GAAcM,EAAO,QAAQ;AAAA,aACjDN,EAAa,SAAS;AACvB,MAAA4P,IAAAE,GAAoB9P,GAAcM,EAAO,QAAQ;AAAA;AAEnD,YAAA,IAAI1B,EAAqBoB,EAAa,IAAI;AAAA,MAR1C,OAAA,IAAI,MAAM,0BAA0B;AAc5C,QAAM0U,IAAMF,EAAW,kBAAkB3W,EAAS,KAAK+R,CAAK,GAAG6E,CAAO;AAElE,SAAAC,EAAI,aAAa,KACnBL,GAA8BK,CAAkB,GAG3CA;AACT;AAOA,SAASC,GAKPjX,GACA4C,GACAD,GACAmU,GACAI,GACAC,GACAJ,GACA;;AACM,QAAAxQ,KAAMwQ,KAAA,gBAAAA,EAAS,aAAY,UAC3BK,IAAUxU,EAAO,SAAS,MAAM;AAEtC,MAAIkD,IAAQnD,EAAM;AAEd,MAAA,CAACA,EAAM,OAAO;AAChB,IAAAmD,IAAQ,CAAC;AACT,eAAW,CAAC/B,GAAME,CAAI,KAAK,OAAO;AAAA,MAChCrB,EAAO,OAAO,YAAYD,EAAM,IAAW,EAAE;AAAA,IAAA;AAEzC,MAAAsB,EAAK,YAAY,WAClB6B,EAAc/B,CAAI,IAAIE,EAAK;AAAA,EAEhC;AAGI,QAAAoT,KAAK7Y,KAAAD,IAAA6Y,EAAQ,SAAR,gBAAA7Y,EAAc,UAAd,gBAAAC,EAAA;AAAA,IAAAD;AAAA,IACT6Y,EAAQ,OAAO;AAAA,MACb,IAAIzU,EAAM;AAAA,MACV,GAAGmD;AAAA,IACJ,CAAA;AAAA,KAQG+M,IAAQ,MAAM,KAAKwE,EAAG,IAAI,UAAU,GAEpCvO,IAAMlG,EAAO,qBACjBD,EAAM,IACR,EAAE,eAAe,eAAe,EAAE,GAAGA,GAAO,OAAAmD,EAAA,GAAgBlD,CAAa,GAEnE0U,IAAkB/Q,EAAI,uBAAuB;AACnD,MAAIuC,EAAI,IAAI,UAAU,SAAS,kBAAkB,GAAG;AAClD,UAAMyO,IAA6B;AAAA,MACjC,GAAG1E;AAAA,MACH,GAAG,MAAM,KAAK/J,EAAI,IAAI,UAAU;AAAA,IAAA,EAChC;AAAA,MACA,CAACjE,MACCA,EAAK,KAAK,WAAW,MAAM,KAC3BA,EAAK,SAAS,uBACdA,EAAK,SAAS,qBACdA,EAAK,SAAS,4BACdA,EAAK,SAAS,oBACdA,EAAK,SAAS,aACdA,EAAK,SAAS,gBACdA,EAAK,SAAS;AAAA,IAClB;AAGA,eAAWA,KAAQ0S;AAChB,MAAAzO,EAAI,IAAI,WAA4B,aAAajE,EAAK,MAAMA,EAAK,KAAK;AAG3C,IAAA8R,GAAA7N,EAAI,IAAI,UAA0B,GAChEwO,EAAgB,OAAO,GAAG,MAAM,KAAKxO,EAAI,IAAI,UAAU,CAAC;AAAA,EAAA;AAExC,IAAAwO,EAAA,OAAOxO,EAAI,GAAG;AAG5B,MAAAA,EAAI,cAAcnG,EAAM,SAAS;AACnC,UAAM6U,IAAKX;AAAA,MACTjU;AAAA,MACAD,EAAM;AAAA;AAAA,MACNmU;AAAA,MACAC;AAAA,IACF;AAEI,IAAAjO,EAAA,WAAW,YAAY0O,CAAE;AAAA,EAAA;AAG/B,MAAIC;AAOJ,MANIP,EAA0B,IAAIvU,EAAM,IAAK,IAChC8U,IAAA,OACFN,EAA4B,IAAIxU,EAAM,IAAK,MACzC8U,IAAA,OAGTA,GAAU;AACR,UAAA7W,IAAAZ,EAAS,cAAT,gBAAAY,EAAoB,cAAa6W,GAAU;AACvC,YAAAxX,IAAOsG,EAAI,cAAckR,CAAQ;AAEvC,MAAIA,MAAa,SAAQ3R,KAAA,QAAAA,EAAO,WAASA,KAAA,gBAAAA,EAAO,WAAU,KACxD7F,EAAK,aAAa,SAAS6F,EAAM,QAAQ,EAAE,GAE7C9F,EAAS,OAAOC,CAAI;AAAA,IAAA;AAEhB,UAAAyX,IAAKnR,EAAI,cAAc,IAAI;AACjC,IAAAmR,EAAG,OAAOJ,CAAe,GAChBtX,EAAA,UAAW,YAAY0X,CAAE;AAAA,EAAA;AAElC,IAAA1X,EAAS,OAAOsX,CAAe;AAGjC,MAAI3U,EAAM,YAAYA,EAAM,SAAS,SAAS,GAAG;AACzC,UAAAgV,IAAgBpR,EAAI,uBAAuB;AAUjD,QATAqR;AAAA,MACED;AAAA,MACA/U;AAAA,MACAD,EAAM;AAAA,MACNmU;AAAA,MACAI;AAAA,MACAC;AAAA,MACAJ;AAAA,IACF,KAEElW,IAAAb,EAAS,cAAT,gBAAAa,EAAoB,cAAa,UACjCC,IAAAd,EAAS,cAAT,gBAAAc,EAAoB,cAAa;AAGjC,eACE+W,IAAAF,EAAc,eAAd,gBAAAE,EAA0B,cAAa,UACvCC,IAAAH,EAAc,eAAd,gBAAAG,EAA0B,cAAa;AAEvC,QAAA9X,EAAS,UAAW,UAAW,YAAY2X,EAAc,UAAW;AAIpE,IAAA/U,EAAO,SAAS,MAAMD,EAAM,IAAW,EAAE,UAAU,cAAc,IAEnE3C,EAAS,OAAO2X,CAAa,KAGzBI,IAAAjP,EAAA,eAAA,QAAAiP,EAAY,OAAOJ;AAAA,EACzB;AAEJ;AAEA,MAAMC,KAA4B,CAKhC5X,GACA4C,GACAgI,GACAkM,GACAI,GACAC,GACAJ,MACG;AACH,aAAWpU,KAASiI;AAClBqM,IAAAA;AAAAA,MACEjX;AAAA,MACA4C;AAAA,MACAD;AAAA,MACAmU;AAAA,MACAI;AAAA,MACAC;AAAA,MACAJ;AAAA,IACF;AAEJ,GAEaiB,KAA8B,CAKzCpV,GACAgI,GACAkM,GACAI,GACAC,GACAJ,MACG;AAEG,QAAA/W,MADM+W,KAAA,gBAAAA,EAAS,aAAY,UACZ,uBAAuB;AAE5C,SAAAa;AAAA,IACE5X;AAAA,IACA4C;AAAA,IACAgI;AAAA,IACAkM;AAAA,IACAI;AAAA,IACAC;AAAA,IACAJ;AAAA,EACF,GACO/W;AACT,GC1OaiY,KAA6B,CAKxC7P,GACAxF,MACG;AACG,QAAAkU,IAAaoB,GAAc,WAAW9P,CAAM;AAE3C,SAAA;AAAA,IACL,cAAc,CACZwC,GACAmM,MACG;AACH,YAAMoB,IAAOH;AAAA,QACXpV;AAAA,QACAgI;AAAA,QACAkM;AAAA,QACI,oBAAA,IAAY,CAAC,kBAAkB,CAAC;AAAA,QAChC,oBAAA,IAAY,CAAC,kBAAkB,eAAe,CAAC;AAAA,QACnDC;AAAA,MACF,GACM5Q,IAAM,SAAS,cAAc,KAAK;AACxC,aAAAA,EAAI,OAAOgS,CAAI,GACRhS,EAAI;AAAA,IACb;AAAA,IAEA,qBAAqB,CACnB1D,GACAsU,MACG;AACH,YAAMqB,IAAcvB;AAAA,QAClBjU;AAAA,QACAH;AAAA,QACAqU;AAAA,QACAC;AAAA,MACF,GAEMsB,IAAS,SAAS,cAAc,KAAK;AAC3C,aAAAA,EAAO,OAAOD,EAAY,UAAU,EAAI,CAAC,GAElCC,EAAO;AAAA,IAAA;AAAA,EAElB;AACF;AC7DO,SAASC,GAKd1V,GACAN,GACAwU,GACArS,GACAsS,GACA;AACI,MAAA7E;AAGJ,MAAK5P;AAEL,QAAW,OAAOA,KAAiB;AACjC,MAAA4P,IAAQ7F,EAAqB,CAAC/J,CAAY,GAAGM,EAAO,UAAU6B,CAAS;AAAA,aAC9D,MAAM,QAAQnC,CAAY;AACnC,MAAA4P,IAAQ7F,EAAqB/J,GAAcM,EAAO,UAAU6B,CAAS;AAAA,aAC5DnC,EAAa,SAAS;AACvB,MAAA4P,IAAAE,GAAoB9P,GAAcM,EAAO,QAAQ;AAAA;AAEnD,YAAA,IAAI1B,EAAqBoB,EAAa,IAAI;AAAA,MAR1C,OAAA,IAAI,MAAM,0BAA0B;AAgBrC,SAFKwU,EAAW,kBAAkB3W,EAAS,KAAK+R,CAAK,GAAG6E,CAAO;AAGxE;AAEA,SAASE,GAKPrU,GACAD,GACAmU,GACAyB,GACAxB,GACA;;AACA,QAAMK,IAAUxU,EAAO,SAAS,MAAM;AAEtC,MAAIkD,IAAQnD,EAAM;AAEd,MAAA,CAACA,EAAM,OAAO;AAChB,IAAAmD,IAAQ,CAAC;AACT,eAAW,CAAC/B,GAAME,CAAI,KAAK,OAAO;AAAA,MAChCrB,EAAO,OAAO,YAAYD,EAAM,IAAW,EAAE;AAAA,IAAA;AAEzC,MAAAsB,EAAK,YAAY,WAClB6B,EAAc/B,CAAI,IAAIE,EAAK;AAAA,EAEhC;AAII,QAAA6E,IADOlG,EAAO,qBAAqBD,EAAM,IAAW,EAAE,eAC3C,eAAe,EAAE,GAAGA,GAAO,OAAAmD,KAAgBlD,CAAa;AAYrE,MAVAD,EAAM,SAAS,sBAOjBmG,EAAI,IAAI,aAAa,cAAcyP,EAAU,UAAU,GAGrDzP,EAAI,cAAcnG,EAAM,SAAS;AACnC,UAAM6U,IAAKc;AAAA,MACT1V;AAAA,MACAD,EAAM;AAAA;AAAA,MACNmU;AAAA,MACAnU,EAAM;AAAA,MACNoU;AAAA,IACF;AACI,IAAAjO,EAAA,WAAW,YAAY0O,CAAE;AAAA,EAAA;AAK3B,MAFW5U,EAAO,SAAS,MAAMD,EAAM,IAAW,EAE3C,UAAU,SAAS,GAAG;AAC/B,QAAIA,EAAM,YAAYA,EAAM,SAAS,SAAS,GAAG;AAC/C,YAAM3C,IAAWwY;AAAA,QACf5V;AAAA,QACAD,EAAM;AAAA,QACNmU;AAAA,QACAC;AAAA,MACF;AAEI,OAAAxY,IAAAuK,EAAA,eAAA,QAAAvK,EAAY,OAAOyB;AAAA,IAAQ;AAEjC,WAAO8I,EAAI;AAAA,EAAA;AAIP,QAAAuO,KAAKzW,KAAApC,IAAA4Y,EAAQ,SAAR,gBAAA5Y,EAAc,UAAd,gBAAAoC,EAAA;AAAA,IAAApC;AAAA,IACT4Y,EAAQ,OAAO;AAAA,MACb,IAAIzU,EAAM;AAAA,MACV,GAAGmD;AAAA,IACJ,CAAA;AAAA;AAMA,UAAAjF,IAAAwW,EAAA,eAAA,QAAAxW,EAAY,YAAYiI,EAAI,MAE3BnG,EAAM,YAAYA,EAAM,SAAS,SAAS,OAC5C7B,IAAAuW,EAAG,eAAH,QAAAvW,EAAe;AAAA,IACb2X,GAA4B7V,GAAQD,EAAM,UAAUmU,GAAYC,CAAO;AAAA,MAGpEM,EAAG;AACZ;AAEA,SAASmB,GAKP5V,GACAgI,GACAkM,GACAC,GACA;AAEM,QAAA/W,MADM+W,KAAA,gBAAAA,EAAS,aAAY,UACZ,uBAAuB;AAE5C,MAAIwB,IAAY;AAChB,aAAW5V,KAASiI,GAAQ;AACtB,IAAAjI,EAAM,SAAS,qBACjB4V,MAEYA,IAAA;AAEd,UAAMG,IAAWzB;AAAA,MACfrU;AAAA,MACAD;AAAA,MACAmU;AAAA,MACAyB;AAAA,MACAxB;AAAA,IACF;AACA,IAAA/W,EAAS,YAAY0Y,CAAQ;AAAA,EAAA;AAGxB,SAAA1Y;AACT;AAEO,MAAMyY,KAA8B,CAKzC7V,GACAgI,GACAkM,GACAC,MACG;;AACH,QAAM4B,IAAU/V,EAAO,SAAS,MAAM,YAEhCgW,IAAKD,EAAQ,KAAM,MAAOA,EAAQ,OAAO,CAAA,CAAE,CAAC,GAK5C3Y,IAAWwY,GAAgB5V,GAAQgI,GAAQkM,GAAYC,CAAO;AAEjE,UAAAxY,IAAAqa,EAAA,eAAA,QAAAra,EAAY,YAAYyB,IAEpB4Y,EAAG;AACZ,GC7KaC,KAA+B,CAK1CzQ,GACAxF,MACG;AACG,QAAAkU,IAAaoB,GAAc,WAAW9P,CAAM;AAE3C,SAAA;AAAA,IACL,iBAAiB,CACfwC,GACAmM,MAEO0B,GAA4B7V,GAAQgI,GAAQkM,GAAYC,CAAO,EACnE;AAAA,EAEP;AACF,GCrCa+B,KAAqB,CAChCC,GACAC,MACG;AACH,QAAMC,IAAgBF,EAAc;AAAA,IAClCC;AAAA,EACF;AACA,MAAI,CAACC;AACI;AAGH,QAAAC,IAAiBH,EAAc,cAAc,YAAY,GACzDI,KAAUD,KAAA,gBAAAA,EAAgB,gBAAe;AAExC,SAAA,EAAE,eAAAD,GAAe,SAAAE,EAAQ;AAClC,GCZaC,KAAsB,CACjCzW,GACAC,GACAyW,GACAC,MACG;AACG,QAAAC,IAAgB,SAAS,cAAc,KAAK;AAClD,EAAAA,EAAc,YAAY;AAEpB,QAAAC,IAAoB,SAAS,cAAc,KAAK;AACtD,EAAAA,EAAkB,YAAY,2BAC1BF,IACFE,EAAkB,YAAYF,CAAU,IAExCE,EAAkB,YAChB,uQAEJD,EAAc,YAAYC,CAAiB;AAErC,QAAAC,IAAoB,SAAS,cAAc,GAAG;AACpD,EAAAA,EAAkB,YAAY,2BAC9BA,EAAkB,YAChBJ,KAAczW,EAAO,WAAW,YAAY,KAAK,iBACnD2W,EAAc,YAAYE,CAAiB;AAGrC,QAAAC,IAAgC,CAAC7Z,MAAsB;AAC3D,IAAAA,EAAM,eAAe;AAAA,EACvB,GAEM8Z,IAA4B,MAAM;AAC/B,IAAA/W,EAAA;AAAA,MAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,QACvC,OAAAD;AAAA,MACD,CAAA;AAAA,IACH;AAAA,EACF;AACc,SAAA4W,EAAA;AAAA,IACZ;AAAA,IACAG;AAAA,IACA;AAAA,EACF,GACcH,EAAA,iBAAiB,SAASI,GAA2B,EAAI,GAEhE;AAAA,IACL,KAAKJ;AAAA,IACL,SAAS,MAAM;AACC,MAAAA,EAAA;AAAA,QACZ;AAAA,QACAG;AAAA,QACA;AAAA,MACF,GACcH,EAAA;AAAA,QACZ;AAAA,QACAI;AAAA,QACA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF,GC5DaC,KAAgB,uQAEhBC,KAAyB,CACpClX,MAC+C;AACzC,QAAAmX,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY;AAEX,QAAAC,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,gBACjBA,EAAK,YAAYH,IACjBE,EAAK,YAAYC,CAAI;AAEf,QAAAC,IAAW,SAAS,cAAc,GAAG;AAC3C,SAAAA,EAAS,YAAY,gBACZA,EAAA,cAAcrX,EAAM,MAAM,MACnCmX,EAAK,YAAYE,CAAQ,GAElB;AAAA,IACL,KAAKF;AAAA,EACP;AACF,GCdaG,KAAyB,CACpCtX,GACAC,GAKAnF,GACA4b,GACAC,MACG;AACG,QAAAY,IAAU,SAAS,cAAc,KAAK;AAKxC,MAJJA,EAAQ,YAAY,iCAIhBvX,EAAM,MAAM,QAAQ,IAAI;AAC1B,UAAM4W,IAAgBH;AAAA,MACpBzW;AAAA,MACAC;AAAA,MACAyW;AAAA,MACAC;AAAA,IACF;AACQ,IAAAY,EAAA,YAAYX,EAAc,GAAG;AAErC,UAAMY,IAA4BvX,EAAO,cAAc,CAACwX,MAAY;AAC9D,UAAAA,MAAYzX,EAAM,IAAI;AAChB,QAAAuX,EAAA,YAAYX,EAAc,GAAG;AAE/B,cAAAc,IAAU,SAAS,cAAc,KAAK;AAC5C,QAAAA,EAAQ,YAAY,2BACpBA,EAAQ,cAAc,cACtBH,EAAQ,YAAYG,CAAO;AAAA,MAAA;AAAA,IAC7B,CACD;AAEM,WAAA;AAAA,MACL,KAAKH;AAAA,MACL,SAAS,MAAM;AACa,QAAAC,EAAA,GAC1BZ,EAAc,QAAQ;AAAA,MAAA;AAAA,IAE1B;AAAA,EAAA;AAGI,QAAAzQ,IAAkD,EAAE,KAAKoR,EAAQ;AAGvE,MAAIvX,EAAM,MAAM,gBAAgB,MAAS,CAAClF,GAAS;AAE3C,UAAA6c,IAAmBT,GAAuBlX,CAAK;AAC7C,IAAAuX,EAAA,YAAYI,EAAiB,GAAG,GAExCxR,EAAI,UAAU,MAAM;;AAClB,OAAAvK,IAAA+b,EAAiB,YAAjB,QAAA/b,EAAA,KAAA+b;AAAA,IACF;AAAA,EAAA;AAGQ,IAAAJ,EAAA,YAAYzc,EAAQ,GAAG;AAI7B,MAAAkF,EAAM,MAAM,SAAS;AACjB,UAAAwW,IAAU,SAAS,cAAc,GAAG;AAC1C,IAAAA,EAAQ,YAAY,mBACZA,EAAA,cAAcxW,EAAM,MAAM,SAClCuX,EAAQ,YAAYf,CAAO;AAAA,EAAA;AAGtB,SAAArQ;AACT,GC/EayR,KAA0B,CACrC9c,GACA0b,MACG;AACG,QAAAqB,IAAS,SAAS,cAAc,QAAQ,GACxCtB,IAAiB,SAAS,cAAc,YAAY;AAC1D,SAAAA,EAAe,cAAcC,GAE7BqB,EAAO,YAAY/c,CAAO,GAC1B+c,EAAO,YAAYtB,CAAc,GAE1B,EAAE,KAAKsB,EAAO;AACvB,GCZaC,KAAwB,CACnChd,GACA0b,MACG;AACG,QAAAe,IAAU,SAAS,cAAc,KAAK,GACtCQ,IAAc,SAAS,cAAc,GAAG;AAC9C,SAAAA,EAAY,cAAcvB,GAE1Be,EAAQ,YAAYzc,CAAO,GAC3Byc,EAAQ,YAAYQ,CAAW,GAExB;AAAA,IACL,KAAKR;AAAA,EACP;AACF,GCdaS,KAAoB,CAACC,OAGzB,EAAE,KAFGA,EAAa,OAAO,OAEnB,ICaFC,KACX,2xBAEWC,KAAkB;AAAA,EAC7B,iBAAiBzX,EAAa;AAAA;AAAA,EAE9B,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EAEA,aAAa;AAAA,IACX,SAAS;AAAA,EAAA;AAEb,GAEa0X,KAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,YAAYD;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AAAA,EACb,iBAAiB,CAAC,SAAS;AAC7B,GAEaE,KAAc,CACzBrY,GACAC,MACG;AACG,QAAAmX,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAYc;AAEX,QAAAI,IAAQ,SAAS,cAAc,OAAO;AAC5C,SAAAA,EAAM,YAAY,YACdrY,EAAO,iBACTA,EAAO,eAAeD,EAAM,MAAM,GAAG,EAAE,KAAK,CAACuY,MAAgB;AAC3D,IAAAD,EAAM,MAAMC;AAAA,EAAA,CACb,IAEKD,EAAA,MAAMtY,EAAM,MAAM,KAE1BsY,EAAM,WAAW,IACjBA,EAAM,kBAAkB,SACxBA,EAAM,YAAY,IAEXhB;AAAA,IACLtX;AAAA,IACAC;AAAA,IACA,EAAE,KAAKqY,EAAM;AAAA,IACbrY,EAAO,WAAW,YAAY,MAAM;AAAA,IACpCmX,EAAK;AAAA,EACP;AACF,GAEaoB,KAAa,CACxB1d,MACmE;AAC/D,MAAAA,EAAQ,YAAY;AAElB,WAAAA,EAAQ,QAAQ,QAAQ,IACnB,SAGFkd,GAAkBld,CAA2B;AAGlD,MAAAA,EAAQ,YAAY,UAAU;AAC1B,UAAA2d,IAAetC,GAAmBrb,GAAS,OAAO;AACxD,QAAI,CAAC2d;AACI;AAGH,UAAA,EAAE,eAAAnC,GAAe,SAAAE,EAAA,IAAYiC;AAE5B,WAAA;AAAA,MACL,GAAGT,GAAkB1B,CAAiC;AAAA,MACtD,SAAAE;AAAA,IACF;AAAA,EAAA;AAIJ,GAEakC,KAAsB,CACjC1Y,MACG;AACC,MAAA,CAACA,EAAM,MAAM,KAAK;AACd,UAAAwD,IAAM,SAAS,cAAc,GAAG;AACtC,WAAAA,EAAI,cAAc,aAEX;AAAA,MACL,KAAKA;AAAA,IACP;AAAA,EAAA;AAGE,MAAA8U;AAUA,SATAtY,EAAM,MAAM,eACNsY,IAAA,SAAS,cAAc,OAAO,GAChCA,EAAA,MAAMtY,EAAM,MAAM,QAEhBsY,IAAA,SAAS,cAAc,GAAG,GAC5BA,EAAA,OAAOtY,EAAM,MAAM,KACzBsY,EAAM,cAActY,EAAM,MAAM,QAAQA,EAAM,MAAM,MAGlDA,EAAM,MAAM,UACVA,EAAM,MAAM,cACP4X,GAAwBU,GAAOtY,EAAM,MAAM,OAAO,IAElD8X,GAAsBQ,GAAOtY,EAAM,MAAM,OAAO,IAIpD;AAAA,IACL,KAAKsY;AAAA,EACP;AACF,GAEaK,KAAavV,GAAgBgV,IAAkB;AAAA,EAC1D,QAAQC;AAAA,EACR,OAAOG;AAAA,EACP,gBAAgBE;AAClB,CAAC,GChFYE,KAAoB,OAAO,IAAI,uBAAuB,GACtDC,KAAgC,OAAO;AAAA,EAClD;AACF,GACaC,KAA6B;AAAA,EACxC,UAAU;AAAA,IACR,SAAS;AAAA,EAAA;AAEb,GAEMC,KAAmB1W,EAA8B;AAAA,EACrD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa;AACJ,WAAA;AAAA,MACL,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,MACnB,oBAAoB,CAAA;AAAA,IACtB;AAAA,EACF;AAAA,EACA,gBAAgB;AACd,UAAM+R,IAAU,KAAK;AAEd,WAAA;AAAA,MACL,UAAU;AAAA,QACR,SAASA,EAAQ,OAAO,SAAS,UAAU;AAAA,QAC3C,WAAW,CAAC4E,MAAiB;AAC3B,cAAIle,IAAUke,GACVC,IAA0B;AAE9B,WACEne,KAAA,gBAAAA,EAAS,aAAY,UACrBA,KAAA,gBAAAA,EAAS,QAAQ,iBAAgB,gBAEvBA,IAAAA,EAAQ,SAAS,CAAC,KAG1BA,KAAA,gBAAAA,EAAS,aAAY,UACbA,IAAAA,KAAA,gBAAAA,EAAS,SAAS;AAGxB,gBAAAoe,IAAepe,KAAA,gBAAAA,EAAS,aAAa;AAE3C,cAAIoe;AACF,YAAAD,IAAWC,EAAa,YAAY;AAAA,eAC/B;AAEL,kBAAMC,IADa,CAAC,IAAIre,KAAA,gBAAAA,EAAS,UAAU,MAAM,SAAQ,EAAG,EAEzD,OAAO,CAACmZ,MAAcA,EAAU,WAAW,WAAW,CAAC,EACvD,IAAI,CAACA,MAAcA,EAAU,QAAQ,aAAa,EAAE,CAAC;AAEpD,YAAAkF,EAAU,SAAS,MACVF,IAAAE,EAAU,CAAC,EAAE,YAAY;AAAA,UACtC;AAGF,iBAAKF,IAKHG,GAAchF,EAAQ,OAAO,SAAS,WAAW6E,CAAQ,KACzDA,IALO;AAAA,QAOX;AAAA,QACA,YAAY,CAACle,MACJA,EAAW,WACd;AAAA,UACE,OAAO,YAAYA,EAAW,QAAQ;AAAA,UACtC,iBAAiBA,EAAW;AAAA,QAAA,IAE9B,CAAC;AAAA,MACP;AAAA,IAEJ;AAAA,EACF;AAAA,EACA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA;AAAA,QAEL,oBAAoB;AAAA,MAAA;AAAA,IAExB;AAAA,EACF;AAAA,EACA,WAAW,EAAE,gBAAAwI,KAAkB;;AACvB,UAAA8V,IAAM,SAAS,cAAc,KAAK,GAClC,EAAE,KAAAhF,GAAK,YAAAiF,EAAA,IAAeha;AAAA,MAC1B,KAAK;AAAA,MACL;AAAA,QACA1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,MAC7C;AAAA,QACE,KAAIC,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAC;AAAA,QAClD,GAAG0H;AAAA,MAAA;AAAA,IAEP;AAEA,WAAA8Q,EAAI,YAAYiF,CAAU,GAC1BjF,EAAI,YAAYgF,CAAG,GACnBA,EAAI,YAAYC,CAAU,GAEnB;AAAA,MACL,KAAAjF;AAAA,MACA,YAAAiF;AAAA,IACF;AAAA,EACF;AAAA,EACA,cAAc;AACZ,UAAMlF,IAAU,KAAK;AAErB,WAAO,CAAC,EAAE,QAAAnU,GAAQ,MAAAzD,GAAM,QAAAiF,GAAQ,gBAAA8B,QAAqB;;AAC7C,YAAA8V,IAAM,SAAS,cAAc,KAAK,GAClCE,IAAS,SAAS,cAAc,QAAQ,GACxCC,IAAgB,SAAS,cAAc,KAAK,GAC5C,EAAE,KAAAnF,GAAK,YAAAiF,EAAA,IAAeha;AAAA,QAC1B,KAAK;AAAA,QACL;AAAA,QACA;AAAA,UACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,UACjD,GAAG2H;AAAA,QACL;AAAA,UACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,MAC/C,GACM4d,IAAuB,CAACvc,MAAiB;AACvC,cAAA+b,IAAY/b,EAAM,OAA6B;AAErD,QAAA+C,EAAO,SAAS,QAAQ,CAAC,EAAE,IAAAtE,SACzBA,EAAG,iBAAiB8F,KAAU,YAAYwX,CAAQ,GAE3C,GACR;AAAA,MACH;AAEO,oBAAA;AAAA,QACL7E,EAAQ,OAAO,SAAS,UAAU;AAAA,MACpC,EAAE,QAAQ,CAAC,CAAC1X,GAAI,EAAE,MAAA0E,EAAM,CAAA,MAAM;AACtB,cAAAsY,IAAS,SAAS,cAAc,QAAQ;AAE9C,QAAAA,EAAO,QAAQhd,GACfgd,EAAO,OAAOtY,GACdmY,EAAO,YAAYG,CAAM;AAAA,MAAA,CAC1B,GAEDF,EAAc,kBAAkB,SAChCD,EAAO,QACL/c,EAAK,MAAM,YACX4X,EAAQ,OAAO,SAAS,UAAU,iBACpCC,EAAI,YAAYiF,CAAU,GAC1BjF,EAAI,YAAYmF,CAAa,GAC7BnF,EAAI,YAAYgF,CAAG,GACnBA,EAAI,YAAYC,CAAU,GAC1BE,EAAc,YAAYD,CAAM,GACzBA,EAAA,iBAAiB,UAAUE,CAAoB,GAE/C;AAAA,QACL,KAAApF;AAAA,QACA,YAAAiF;AAAA,QACA,QAAQ,CAACK,MACHA,EAAQ,SAAS,KAAK;AAAA,QAM5B,SAAS,MAAM;AACN,UAAAJ,EAAA,oBAAoB,UAAUE,CAAoB;AAAA,QAAA;AAAA,MAE7D;AAAA,IACF;AAAA,EACF;AAAA,EACA,wBAAwB;AACtB,UAAMrF,IAAU,KAAK,SACfwF,IAAqB;AAKvB,QAAAC,GACAC,GACAC,IAAY;AA0DhB,WAAO,CANiBC,GAAsB;AAAA,MAC5C,QApDyB,CAACC,MAAkB;AAC5C,YAAI,CAAC7F,EAAQ,OAAO,SAAS,UAAU;AACrC,iBAAI,QAAQ,IAAI,aAAa,iBAAiB,CAAC2F,MAErC,QAAA;AAAA,YACN;AAAA,UACF,GACYA,IAAA,KAEP,CAAC;AAEV,YAAI,CAACF;AACgB,iBAAAD,EAAAf,EAA6B,IAC9Ce,EAAmBf,EAA6B,KAChDzE,EAAQ,OAAO,SAAS,UAAU,kBAAkB,GAE/CwF,EAAmBf,EAA6B,EAAE;AAAA,YACvD,CAACqB,MAAuB;AACR,cAAAL,IAAAK;AAAA,YAAA;AAAA,UAElB;AAEF,cAAMjB,IAAWG;AAAA,UACfhF,EAAQ,OAAO,SAAS;AAAA,UACxB6F,EAAc;AAAA,QAChB;AAGE,eAAA,CAAChB,KACDA,MAAa,UACbA,MAAa,UACbA,MAAa,eACbA,MAAa,QAEN,CAAC,IAGLY,EAAY,mBAAqB,EAAA,SAASZ,CAAQ,KAIlDa,MACHA,IACEF,EAAmBhB,EAAiB,KACpCuB,GAAaN,CAAkB,GACjCD,EAAmBhB,EAAiB,IAAIkB,IAGnCA,EAAOG,CAAa,KAVlBJ,EAAY,aAAaZ,CAAQ;AAAA,MAW5C;AAAA,MAIE,mBAAmB,CAACzc,MAASA,EAAK,MAAM;AAAA,MACxC,WAAW,CAAC,KAAK,IAAI;AAAA,IAAA,CACtB,CAEsB;AAAA,EACzB;AAAA,EACA,gBAAgB;AACd,UAAM4X,IAAU,KAAK;AAEd,WAAA;AAAA,MACL,IAAIgG,GAAU;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAAgM,GAAO,OAAAiJ,QAAY;AACpC,gBAAMC,IAASlV,EAAM,IAAI,QAAQgM,EAAM,IAAI,GACrCmJ,IAAeF,EAAM,CAAC,EAAE,KAAK,GAC7Btf,IAAa;AAAA,YACjB,UACEqe,GAAchF,EAAQ,OAAO,SAAS,WAAWmG,CAAY,KAC7DA;AAAA,UACJ;AAEA,cACE,CAACD,EACE,KAAK,EAAE,EACP;AAAA,YACCA,EAAO,MAAM,EAAE;AAAA,YACfA,EAAO,WAAW,EAAE;AAAA,YACpB,KAAK;AAAA,UAAA;AAGF,mBAAA;AAGH,UAAAlV,EAAA,GACH,OAAOgM,EAAM,MAAMA,EAAM,EAAE,EAC3B,aAAaA,EAAM,MAAMA,EAAM,MAAM,KAAK,MAAMrW,CAAU,EAC1D,aAAayf,EAAc,OAAOpV,EAAM,GAAG,KAAKgM,EAAM,IAAI,CAAC;AAAA,QAE9D;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EACA,uBAAuB;AACd,WAAA;AAAA,MACL,QAAQ,CAAC,EAAE,QAAAnR,QAAa;AAChB,cAAA,EAAE,WAAAwa,MAAcxa,EAAO,OACvB,EAAE,OAAAya,MAAUD;AAIhB,YAAAxa,EAAO,SAAS,KAAK,IAAI,KACzB,CAACya,EAAM,OAAO,eACdC,GAAgBF,CAAS,GACzB;AAEA,gBAAM9L,IAAO+L,EAAM,MAAMA,EAAM,eAAe;AAE9C,iBAAAza,EAAO,QAAQ,iBAAiB0O,CAAI,EAAE,kBAAkB,IAAI,GAErD;AAAA,QAAA;AAGF,eAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAC,EAAE,QAAA1O,QACD,KAAK,QAAQ,qBAGdA,EAAO,SAAS,KAAK,IAAI,KACpBA,EAAA,SAAS,cAAc,IAAI,GAC3B,MAJA;AAAA,MASX,OAAO,CAAC,EAAE,QAAAA,QAAa;AACrB,cAAM,EAAE,OAAAya,EAAA,IAAUza,EAAO,MAAM;AAE/B,YAAI,CAACA,EAAO,SAAS,KAAK,IAAI;AACrB,iBAAA;AAGT,cAAM2a,IAAUF,EAAM,iBAAiBA,EAAM,OAAO,WAAW,GACzDG,IAAwBH,EAAM,OAAO,YAAY,SAAS;AAAA;AAAA,CAAM;AAElE,eAAA,CAACE,KAAW,CAACC,KACR5a,EAAA,SAAS,cAAc;AAAA,CAAI,GAC3B,MAGFA,EACJ,MAAM,EACN,QAAQ,CAAC,EAAE,IAAAtE,SACVA,EAAG,OAAO+e,EAAM,MAAM,GAAGA,EAAM,GAAG,GAE3B,GACR,EACA,SAAS,EACT,IAAI;AAAA,MACT;AAAA,MACA,eAAe,CAAC,EAAE,QAAAza,QAAa;AAC7B,cAAM,EAAE,OAAAya,EAAA,IAAUza,EAAO,MAAM;AAE/B,eAAKA,EAAO,SAAS,KAAK,IAAI,KAI9BA,EACG,QACA;AAAA,UACCya,EAAM,MAAMA,EAAM,eAAeA,EAAM,OAAO;AAAA,UAC9C;AAAA,YACE,MAAM;AAAA,UAAA;AAAA,UAGT,IAAI,GAEA,MAbE;AAAA,MAaF;AAAA,IAEX;AAAA,EAAA;AAEJ,CAAC,GAEYI,KAAYpY;AAAA,EACvBqW;AAAA,EACAD;AACF;AAEA,SAASM,GACPhF,GACAmG,GACoB;;AACpB,UAAO3e,IAAA,OAAO,QAAQwY,EAAQ,kBAAkB,EAAE;AAAA,IAChD,CAAC,CAAC1X,GAAI,EAAE,SAAAqe,EAAA,CAAS,OACRA,KAAA,gBAAAA,EAAS,SAASR,OAAiB7d,MAAO6d;AAAA,QAF9C,gBAAA3e,EAIH;AACN;ACzbA,MAAMof,KAAsB1Q,GAAK,OAAO;AAAA,EACtC,MAAM;AAAA,EAEN,gBAAgB;AACP,WAAA;AAAA,MACL,aAAa;AAAA,QACX,SAAS;AAAA,QACT,WAAW,CAACxP,MAAYA,EAAQ,aAAa,uBAAuB;AAAA,QACpE,YAAY,CAACC,OAAgB;AAAA,UAC3B,yBAAyBA,EAAW;AAAA,QACtC;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACD,MACL,OAAOA,KAAY,WACd,KAGLA,EAAQ,aAAa,uBAAuB,IACvC;AAAA,UACL,aAAaA,EAAQ,aAAa,uBAAuB;AAAA,QAC3D,IAGK;AAAA,MACT;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAyI,KAAkB;AACtB,WAAA,CAAC,QAAQA,GAAgB,CAAC;AAAA,EAAA;AAErC,CAAC,GAEY0X,KAAkBjR;AAAA,EAC7BgR;AAAA,EACA;AACF,GC5CME,KAAgB5Q,GAAK,OAAO;AAAA,EAChC,MAAM;AAAA,EAEN,gBAAgB;AACP,WAAA;AAAA,MACL,aAAa;AAAA,QACX,SAAS;AAAA,QACT,WAAW,CAACxP,MAAYA,EAAQ,aAAa,iBAAiB;AAAA,QAC9D,YAAY,CAACC,OAAgB;AAAA,UAC3B,mBAAmBA,EAAW;AAAA,QAChC;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACD,MACL,OAAOA,KAAY,WACd,KAGLA,EAAQ,aAAa,iBAAiB,IACjC,EAAE,aAAaA,EAAQ,aAAa,iBAAiB,EAAE,IAGzD;AAAA,MACT;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAyI,KAAkB;AACtB,WAAA,CAAC,QAAQA,GAAgB,CAAC;AAAA,EAAA;AAErC,CAAC,GAEY4X,KAAYnR,GAA8BkR,IAAe,QAAQ,GC1CjEE,KAAoB,CAACC,OAGzB,EAAE,KAFGA,EAAa,OAAO,OAEnB,ICUFC,KAAiB;AAAA,EAC5B,iBAAiB5a,EAAa;AAAA;AAAA,EAE9B,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,SAAS;AAAA,EAAA;AAEb,GAEa6a,KAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,YAAYD;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AACf,GAEaE,KAAa,CACxBxb,GACAC,MAEOqX,GAAuBtX,GAAOC,CAAM,GAGhCwb,KAAY,CAAC3gB,MAAyB;AAC7C,MAAAA,EAAQ,YAAY;AAElB,WAAAA,EAAQ,QAAQ,QAAQ,IACnB,SAGFsgB,GAAkBtgB,CAA2B;AAGlD,MAAAA,EAAQ,YAAY,UAAU;AAC1B,UAAA2d,IAAetC,GAAmBrb,GAAS,OAAO;AACxD,QAAI,CAAC2d;AACI;AAGH,UAAA,EAAE,eAAAnC,GAAe,SAAAE,EAAA,IAAYiC;AAE5B,WAAA;AAAA,MACL,GAAG2C,GAAkB9E,CAAiC;AAAA,MACtD,SAAAE;AAAA,IACF;AAAA,EAAA;AAIJ,GAEakF,KAAqB,CAChC1b,MACG;AACC,MAAA,CAACA,EAAM,MAAM,KAAK;AACd,UAAAwD,IAAM,SAAS,cAAc,GAAG;AACtC,WAAAA,EAAI,cAAc,YAEX;AAAA,MACL,KAAKA;AAAA,IACP;AAAA,EAAA;AAGI,QAAAmY,IAAc,SAAS,cAAc,GAAG;AAI1C,SAHQA,EAAA,OAAO3b,EAAM,MAAM,KAC/B2b,EAAY,cAAc3b,EAAM,MAAM,QAAQA,EAAM,MAAM,KAEtDA,EAAM,MAAM,UACP8X,GAAsB6D,GAAa3b,EAAM,MAAM,OAAO,IAGxD;AAAA,IACL,KAAK2b;AAAA,EACP;AACF,GAEaC,KAAYxY,GAAgBmY,IAAiB;AAAA,EACxD,QAAQC;AAAA,EACR,OAAOC;AAAA,EACP,gBAAgBC;AAClB,CAAC,GCvFYG,KAAoB;AAAA,EAC/B,GAAGnb;AAAA,EACH,OAAO,EAAE,SAAS,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC,EAAW;AAClD,GAEMob,KAAsBzZ,EAA8B;AAAA,EACxD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,gBAAgB;AACd,WAAOpB,GAAkB4a,EAAiB;AAAA,EAC5C;AAAA,EAEA,gBAAgB;AACP,WAAA;AAAA,MACL,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAACE,MAET,IAAI3B,GAAU;AAAA,QACnB,MAAM,IAAI,OAAO,OAAO2B,CAAK,QAAQ;AAAA,QACrC,SAAS,CAAC,EAAE,OAAA3W,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAE/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,OAAAkU;AAAA,cAAA;AAAA,YAEH,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAM3K,EAAM,MAAM,IAAIA,EAAM,IAAI,EAC9C,IAAI;AAAA,QAAA;AAAA,MACT,CACD,CACF;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,aAAa,MAAM;AACjB,cAAMvJ,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAIF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO;AAAA,cACL,OAAO;AAAA,YAAA;AAAA,UAEV,CAAA;AAAA,QACH;AAAA,MACF;AAAA,MACA,aAAa,MAAM;AACjB,cAAMA,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO;AAAA,cACL,OAAO;AAAA,YAAA;AAAA,UAEV,CAAA;AAAA,QACH;AAAA,MACF;AAAA,MACA,aAAa,MAAM;AACjB,cAAMA,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO;AAAA,cACL,OAAO;AAAA,YAAA;AAAA,UAEV,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EACA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,OAAO,EAAE,OAAO,EAAE;AAAA,QAClB,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,OAAO,EAAE,OAAO,EAAE;AAAA,QAClB,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,OAAO,EAAE,OAAO,EAAE;AAAA,QAClB,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,MAAArL,GAAM,gBAAA+G,KAAkB;;AAC5B,WAAAjE;AAAA,MACL,KAAK;AAAA,MACL,IAAI9C,EAAK,MAAM,KAAK;AAAA,MACpB;AAAA,QACE,KAAIZ,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEYogB,KAAUvZ;AAAA,EACrBoZ;AAAA,EACAD;AACF,GC5JaK,KAAkC,CAC7Clc,GACAC,GACAnF,GACAqhB,GACAzF,GACAC,MAC8C;AACxC,QAAA,EAAE,KAAAtC,GAAK,SAAA+H,EAAA,IAAY9E;AAAA,IACvBtX;AAAA,IACAC;AAAA,IACAnF;AAAA,IACA4b;AAAA,IACAC;AAAA,EACF,GACMY,IAAUlD;AAChB,EAAIrU,EAAM,MAAM,OAAOA,EAAM,MAAM,gBAC7BA,EAAM,MAAM,eACduX,EAAQ,MAAM,QAAQ,GAAGvX,EAAM,MAAM,YAAY,OAEjDuX,EAAQ,MAAM,QAAQ;AAIpB,QAAA8E,IAAmB,SAAS,cAAc,KAAK;AACrD,EAAAA,EAAiB,YAAY,oBAC7BA,EAAiB,MAAM,OAAO;AACxB,QAAAC,IAAoB,SAAS,cAAc,KAAK;AACtD,EAAAA,EAAkB,YAAY,oBAC9BA,EAAkB,MAAM,QAAQ;AAI5B,MAAAC,GAOA7R,IAAQ1K,EAAM,MAAM;AAIlB,QAAAwc,IAAyB,CAACtf,MAAsB;;AACpD,QAAI,CAACqf,GAAc;AAEf,MAAA,CAACtc,EAAO,cACRkc,EAA8B,SAASE,CAAgB,KACvDF,EAA8B,SAASG,CAAiB,MAExDH,EAA8B,YAAYE,CAAgB,GAC1DF,EAA8B,YAAYG,CAAiB;AAG7D;AAAA,IAAA;AAGE,QAAAG;AAEA,IAAAzc,EAAM,MAAM,kBAAkB,WAC5Buc,EAAa,eAAe,SAC9BE,IACEF,EAAa,gBACZA,EAAa,iBAAiBrf,EAAM,WAAW,IAElDuf,IACEF,EAAa,gBACZrf,EAAM,UAAUqf,EAAa,kBAAkB,IAGhDA,EAAa,eAAe,SAC9BE,IACEF,EAAa,eACbA,EAAa,iBACbrf,EAAM,UAERuf,IACEF,EAAa,eACbrf,EAAM,UACNqf,EAAa,gBASnB7R,IAAQ,KAAK;AAAA,MACX,KAAK,IAAI+R,GALM,EAKY;AAAA,QAC3B5gB,KAAAD,IAAAqE,EAAO,eAAP,gBAAArE,EAAmB,sBAAnB,gBAAAC,EAAsC,gBAAe,OAAO;AAAA,IAC9D,GACQ0b,EAAA,MAAM,QAAQ,GAAG7M,CAAK;AAAA,EAChC,GAGMgS,IAAuB,CAACxf,MAAsB;AAalD,KAVG,CAACA,EAAM,UACN,CAACqa,EAAQ,SAASra,EAAM,MAAc,KACtC,CAAC+C,EAAO,eACVkc,EAA8B,SAASE,CAAgB,KACvDF,EAA8B,SAASG,CAAiB,MAExDH,EAA8B,YAAYE,CAAgB,GAC1DF,EAA8B,YAAYG,CAAiB,IAGxDC,MAIUA,IAAA,QAEftc,EAAO,YAAYD,GAAO;AAAA,MACxB,OAAO;AAAA,QACL,cAAc0K;AAAA,MAAA;AAAA,IAChB,CACD;AAAA,EACH,GAGMiS,IAA2B,MAAM;AACrC,IAAI1c,EAAO,eACTkc,EAA8B,YAAYE,CAAgB,GAC1DF,EAA8B,YAAYG,CAAiB;AAAA,EAE/D,GAGMM,IAA2B,CAAC1f,MAAsB;AACtD,IACEA,EAAM,kBAAkBmf,KACxBnf,EAAM,kBAAkBof,KAKtBC,KAKFtc,EAAO,cACPkc,EAA8B,SAASE,CAAgB,KACvDF,EAA8B,SAASG,CAAiB,MAExDH,EAA8B,YAAYE,CAAgB,GAC1DF,EAA8B,YAAYG,CAAiB;AAAA,EAE/D,GAIMO,IAAmC,CAAC3f,MAAsB;AAC9D,IAAAA,EAAM,eAAe,GAENqf,IAAA;AAAA,MACb,YAAY;AAAA,MACZ,cAAchF,EAAQ;AAAA,MACtB,gBAAgBra,EAAM;AAAA,IACxB;AAAA,EACF,GACM4f,IAAoC,CAAC5f,MAAsB;AAC/D,IAAAA,EAAM,eAAe,GAENqf,IAAA;AAAA,MACb,YAAY;AAAA,MACZ,cAAchF,EAAQ;AAAA,MACtB,gBAAgBra,EAAM;AAAA,IACxB;AAAA,EACF;AAEO,gBAAA,iBAAiB,aAAasf,CAAsB,GACpD,OAAA,iBAAiB,WAAWE,CAAoB,GAC/CnF,EAAA,iBAAiB,cAAcoF,CAAwB,GACvDpF,EAAA,iBAAiB,cAAcqF,CAAwB,GAC9CP,EAAA;AAAA,IACf;AAAA,IACAQ;AAAA,EACF,GACkBP,EAAA;AAAA,IAChB;AAAA,IACAQ;AAAA,EACF,GAEO;AAAA,IACL,KAAKvF;AAAA,IACL,SAAS,MAAM;AACH,MAAA6E,KAAA,QAAAA,KACH,OAAA,oBAAoB,aAAaI,CAAsB,GACvD,OAAA,oBAAoB,WAAWE,CAAoB,GAClDnF,EAAA,oBAAoB,cAAcoF,CAAwB,GAC1DpF,EAAA,oBAAoB,cAAcqF,CAAwB,GACjDP,EAAA;AAAA,QACf;AAAA,QACAQ;AAAA,MACF,GACkBP,EAAA;AAAA,QAChB;AAAA,QACAQ;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF,GClNaC,KAAoB,CAACC,MAAmC;AAC7D,QAAAjc,IAAMic,EAAa,OAAO,QAC1BC,IAAeD,EAAa,SAAS;AAEpC,SAAA,EAAE,KAAAjc,GAAK,cAAAkc,EAAa;AAC7B,GCUaC,KACX,kaAEWC,KAAkB;AAAA,EAC7B,eAAezc,EAAa;AAAA,EAC5B,iBAAiBA,EAAa;AAAA;AAAA,EAE9B,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EAEA,aAAa;AAAA,IACX,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,EAAA;AAEV,GAEa0c,KAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,YAAYD;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AAAA,EACb,iBAAiB,CAAC,SAAS;AAC7B,GAEaE,KAAc,CACzBrd,GACAC,MACG;AACG,QAAAmX,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY8F;AAEX,QAAAI,IAAe,SAAS,cAAc,KAAK;AACjD,EAAAA,EAAa,YAAY;AAEnB,QAAAC,IAAQ,SAAS,cAAc,KAAK;AAC1C,SAAAA,EAAM,YAAY,mBACdtd,EAAO,iBACTA,EAAO,eAAeD,EAAM,MAAM,GAAG,EAAE,KAAK,CAACuY,MAAgB;AAC3D,IAAAgF,EAAM,MAAMhF;AAAA,EAAA,CACb,IAEKgF,EAAA,MAAMvd,EAAM,MAAM,KAG1Bud,EAAM,MAAMvd,EAAM,MAAM,QAAQA,EAAM,MAAM,WAAW,mBACvDud,EAAM,kBAAkB,SACxBA,EAAM,YAAY,IAClBD,EAAa,YAAYC,CAAK,GAEvBrB;AAAA,IACLlc;AAAA,IACAC;AAAA,IACA,EAAE,KAAKqd,EAAa;AAAA,IACpBA;AAAA,IACArd,EAAO,WAAW,YAAY,MAAM;AAAA,IACpCmX,EAAK;AAAA,EACP;AACF,GAEaoG,KAAa,CACxB1iB,MACmE;AAC/D,MAAAA,EAAQ,YAAY;AAElB,WAAAA,EAAQ,QAAQ,QAAQ,IACnB,SAGFiiB,GAAkBjiB,CAA2B;AAGlD,MAAAA,EAAQ,YAAY,UAAU;AAC1B,UAAA2d,IAAetC,GAAmBrb,GAAS,KAAK;AACtD,QAAI,CAAC2d;AACI;AAGH,UAAA,EAAE,eAAAnC,GAAe,SAAAE,EAAA,IAAYiC;AAE5B,WAAA;AAAA,MACL,GAAGsE,GAAkBzG,CAAiC;AAAA,MACtD,SAAAE;AAAA,IACF;AAAA,EAAA;AAIJ,GAEaiH,KAAsB,CACjCzd,MACG;AACC,MAAA,CAACA,EAAM,MAAM,KAAK;AACd,UAAAwD,IAAM,SAAS,cAAc,GAAG;AACtC,WAAAA,EAAI,cAAc,aAEX;AAAA,MACL,KAAKA;AAAA,IACP;AAAA,EAAA;AAGE,MAAA+Z;AAcA,SAbAvd,EAAM,MAAM,eACNud,IAAA,SAAS,cAAc,KAAK,GAC9BA,EAAA,MAAMvd,EAAM,MAAM,KACxBud,EAAM,MAAMvd,EAAM,MAAM,QAAQA,EAAM,MAAM,WAAW,mBACnDA,EAAM,MAAM,iBACRud,EAAA,QAAQvd,EAAM,MAAM,kBAGpBud,IAAA,SAAS,cAAc,GAAG,GAC5BA,EAAA,OAAOvd,EAAM,MAAM,KACzBud,EAAM,cAAcvd,EAAM,MAAM,QAAQA,EAAM,MAAM,MAGlDA,EAAM,MAAM,UACVA,EAAM,MAAM,cACP4X,GAAwB2F,GAAOvd,EAAM,MAAM,OAAO,IAElD8X,GAAsByF,GAAOvd,EAAM,MAAM,OAAO,IAIpD;AAAA,IACL,KAAKud;AAAA,EACP;AACF,GAEaG,KAAata,GAAgBga,IAAkB;AAAA,EAC1D,QAAQC;AAAA,EACR,OAAOG;AAAA,EACP,gBAAgBC;AAClB,CAAC;AC/Ie,SAAAE,GAIdC,GAIAnY,GAIArE,GACU;;AAYJ,QAAA0Y,IAAS+D,GAAU,WAAWpY,CAAM,GAGpCjJ,IAAOohB,GAKPE,IAAgB,SAAS,cAAc,KAAK;AAEpC,EAAAA,EAAA,aAAa,kBAAkB,YAAY;AAEzD,aAAWlX,KAAS,MAAM,KAAKpK,EAAK,UAAU;AAC5C,IAAAshB,EAAc,YAAYlX,EAAM,UAAU,EAAI,CAAC;AAM7C,MAAA/B,IAAiBiV,EAAO,MAAMgE,GAAe;AAAA,IAC/C,SAASrY,EAAO,MAAM,WAAW,OAAO;AAAA,EAAA,CACzC;AAKD,IAAI5J,KAAAD,IAAAiJ,EAAe,eAAf,gBAAAjJ,EAA2B,eAA3B,gBAAAC,EAAuC,KAAK,UAAS,oBAGvDgJ,IAAiBA,EAAe;AAAA,IAC9BA,EAAe,QAAQ;AAAA,MACrBA,EAAe,WAAW,WAAW,WAAW;AAAA,IAAA;AAAA,EAEpD;AAKI,QAAAkZ,KAAsB9f,IAAA4G,EAAe,eAAf,gBAAA5G,EAA2B;AAGnD,MAAA,EAAC8f,KAAA,QAAAA,EAAqB;AAEjB,WAAAvgB,EAAS,KAAKqH,CAAc;AAMrC,QAAMmZ,IAAevY,EAAO,MAAMrE,CAAI,EAAE;AAAA,IACtC,CAAC;AAAA,IACD2c,EAAoB;AAAA,EACtB,GAIME,IAA4BpZ,EAAe,QAAQ;AAAA;AAAA,IAEvDkZ,EAAoB,WAAW;AAAA,EACjC;AAGA,MAFqCE,EAA0B,OAAO,GAEpC;AAG1B,UAAAC,IAAoBrZ,EAAe,KAAKoZ,CAAyB;AAGhE,WAAAD,EAAa,QAAQ,SAASE,CAAiB;AAAA,EAAA;AAIxD,SAAOF,EAAa;AACtB;AC3GO,MAAMG,KAAoB,CAC/BC,GACAC,GACAC,MAEO,CAAC;AAAA,EACN,OAAAlZ;AAAA,EACA,UAAAuN;AAAA,MAII;AACJ,QAAM4L,IAA2B5a,EAAmByB,EAAM,KAAKgZ,CAAU,GAEnEI,IAAOxZ,GAAauZ,CAAwB;AAE9C,MAAA,CAACC,EAAK;AACR,UAAM,IAAI;AAAA,MACR,6DAA6DJ,CAAU;AAAA,IACzE;AAGF,QAAMtiB,IAAQ;AAAA,IACZ;AAAA,MACE,MAAM0iB,EAAK,QAAQ,KAAK;AAAA;AAAA,MACxB,OAAOF,IAAY,EAAE,GAAGE,EAAK,QAAQ,KAAK,OAAO,IAAI,WAAc,CAAA;AAAA,IACrE;AAAA,IACA;AAAA,MACE,MAAMH,IACFG,EAAK,aAAa,KAAK,OACvBpZ,EAAM,OAAO,MAAM;AAAA,MACvB,OAAOkZ,IAAY,EAAE,GAAGE,EAAK,aAAa,KAAK,UAAU,CAAA;AAAA,IAAC;AAAA,EAE9D;AAEA,SAAI7L,KACFvN,EAAM,GAAG,MAAMgZ,GAAY,GAAGtiB,CAAK,GAG9B;AACT,GC1CW2iB,KAAc,CAACxe,MAA2C;AACrE,QAAM,EAAE,WAAA4H,GAAW,gBAAA6W,EAAA,IAAmBze,EAAO,SAAS,CAACtE,OAC9C;AAAA,IACL,WAAW0J,GAA4B1J,CAAE;AAAA,IACzC,gBAAgBA,EAAG,UAAU,WAAWA,EAAG,UAAU;AAAA,EACvD,EACD;AAEG,MAAA,CAACkM,EAAU;AACN,WAAA;AAET,QAAM,EAAE,SAASW,GAAgB,cAAA7I,EAAiB,IAAAkI;AAElD,SACE,EACElI,EAAa,KAAK,KAAK,SAAS,oBAChCA,EAAa,KAAK,KAAK,SAAS,sBAChCA,EAAa,KAAK,KAAK,SAAS,oBAElC,CAAC+e,IAEM,KAGFze,EAAO,cAAc,SAAS,MAAM,CAAC,EAAE,OAAAmF,GAAO,OAAA4W,GAAO,UAAA2C,QAAe;AAAA,IACzE;AAAA;AAAA,MAEEA,EAAS,QAAQ,MACXhf,EAAa,KAAK,eAAe,IAC5Bgf,EAAS;AAAA,QACdlM,EAAmBjK,EAAe,WAAW;AAAA,UAC3C,MAAM;AAAA,UACN,OAAO,CAAA;AAAA,QACR,CAAA;AAAA,MACH,IAGK,EACR;AAAA;AAAA,IAEH;AAAA;AAAA;AAAA,MAGEmW,EAAS,QAAQ,MACXhf,EAAa,KAAK,aAAa,KAC3Bqc,IACH,kBACA,QAAQmC,GAAkB/Y,EAAM,UAAU,MAAM,EAAI,CAAC,EACrD,IAAI,GAEA,MAGF,EACR;AAAA;AAAA,EAAA,CACJ;AACH,GChDawZ,KAA2B;AAAA,EACtC,GAAGle;AACL,GAEMme,KAA6Bxc,EAA8B;AAAA,EAC/D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA;AAAA;AAAA,EAGP,UAAU;AAAA,EACV,gBAAgB;AACP,WAAA;AAAA;AAAA,MAEL,IAAI+X,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,YAAY;AAAA,QAC7B,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAE/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO,CAAA;AAAA,YACR,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAMuJ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MAEpD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,OAAO,MAAMqN,GAAY,KAAK,QAAQ,MAAM;AAAA,MAC5C,eAAe,MAAM;AACnB,cAAM5W,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAAC/M,MAAY;;AACjB,cAAA,OAAOA,KAAY;AACd,mBAAA;AAGT,gBAAM4a,IAAS5a,EAAQ;AAEvB,iBAAI4a,MAAW,OACN,KAIPA,EAAO,YAAY,QAClBA,EAAO,YAAY,WAAS9Z,IAAA8Z,EAAO,kBAAP,gBAAA9Z,EAAsB,aAAY,OAExD,CAAC,IAGH;AAAA,QACT;AAAA;AAAA;AAAA,QAGA,YAAY,CAACY,GAAMiJ,MACjBkY,GAAmBnhB,GAAMiJ,GAAQ,KAAK,IAAI;AAAA,QAC5C,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAlC,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA;AAAA;AAAA;AAAA,MAIL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEYijB,KAAiBpc;AAAA,EAC5Bmc;AAAA,EACAD;AACF,GCnHaG,KAA0B;AAAA,EACrC,GAAGre;AAAA,EACH,SAAS;AAAA,IACP,SAAS;AAAA,EAAA;AAEb,GAEMse,KAA4B3c,EAA8B;AAAA,EAC9D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,gBAAgB;AACd,WAAOpB,GAAkB8d,EAAuB;AAAA,EAClD;AAAA,EAEA,gBAAgB;AACP,WAAA;AAAA;AAAA,MAEL,IAAI3E,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,gBAAgB;AAAA,QACjC,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAE/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAAS;AAAA,cAAA;AAAA,YAEZ,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAMuJ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MACnD,CACD;AAAA,MACD,IAAIgJ,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,gBAAgB;AAAA,QACjC,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAG/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAAS;AAAA,cAAA;AAAA,YAEZ,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAMuJ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MAEpD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,OAAO,MAAMqN,GAAY,KAAK,QAAQ,MAAM;AAAA,MAC5C,eAAe,MAAM;AACnB,cAAM5W,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAAC/M,MACL,OAAOA,KAAY,YAKnBA,EAAQ,QAAQ,qBAAqB,KAAKA,EAAQ,QAAQ,IAAI,IACzD,KAGJA,EAA6B,SAAS,aAClC,EAAE,SAAUA,EAA6B,QAAQ,IAGnD;AAAA,QAET,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACA,MAAY;;AACjB,cAAA,OAAOA,KAAY;AACd,mBAAA;AAGT,gBAAM4a,IAAS5a,EAAQ;AAEvB,cAAI4a,MAAW;AACN,mBAAA;AAIP,cAAAA,EAAO,YAAY,QAClBA,EAAO,YAAY,WAAS9Z,IAAA8Z,EAAO,kBAAP,gBAAA9Z,EAAsB,aAAY,MAC/D;AACA,kBAAMqjB,IACHnkB,EAAQ;AAAA,cACP;AAAA,YAAA,KACwB;AAE5B,mBAAImkB,MAAa,OACR,KAGF,EAAE,SAASA,EAAS,QAAQ;AAAA,UAAA;AAG9B,iBAAA;AAAA,QACT;AAAA;AAAA;AAAA,QAGA,YAAY,CAACziB,GAAMiJ,MACjBkY,GAAmBnhB,GAAMiJ,GAAQ,KAAK,IAAI;AAAA,QAC5C,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,EAAE,MAAAjJ,GAAM,gBAAA+G,KAAkB;;AAC7B,UAAA0b,IAAW,SAAS,cAAc,OAAO;AAC/C,IAAAA,EAAS,OAAO,YACPA,EAAA,UAAUziB,EAAK,MAAM,SAC1BA,EAAK,MAAM,WACJyiB,EAAA,aAAa,WAAW,EAAE;AAG/B,UAAA,EAAE,KAAA5K,GAAK,YAAAiF,EAAA,IAAeha;AAAA,MAC1B,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAEI,WAAAwY,EAAA,aAAa4K,GAAU3F,CAAU,GAE9B,EAAE,KAAAjF,GAAK,YAAAiF,EAAW;AAAA,EAC3B;AAAA;AAAA;AAAA,EAIA,cAAc;AACZ,WAAO,CAAC,EAAE,MAAA9c,GAAM,QAAAiF,GAAQ,QAAAxB,GAAQ,gBAAAsD,QAAqB;;AAG7C,YAAAgU,IAAU,SAAS,cAAc,KAAK,GACtC2H,IAAkB,SAAS,cAAc,KAAK;AACpD,MAAAA,EAAgB,kBAAkB;AAE5B,YAAAD,IAAW,SAAS,cAAc,OAAO;AAC/C,MAAAA,EAAS,OAAO,YACPA,EAAA,UAAUziB,EAAK,MAAM,SAC1BA,EAAK,MAAM,WACJyiB,EAAA,aAAa,WAAW,EAAE;AAGrC,YAAME,IAAgB,MAAM;AACtB,YAAA,CAAClf,EAAO,YAAY;AAIb,UAAAgf,EAAA,UAAU,CAACA,EAAS;AAC7B;AAAA,QAAA;AAIE,YAAA,OAAOxd,KAAW,WAAW;AAC/B,gBAAM2d,IAA0Bzb;AAAA,YAC9B1D,EAAO,MAAM;AAAA,YACbwB,EAAO;AAAA,UACT;AAEA,cAAI2d,EAAwB,KAAK,KAAK,SAAS;AAC7C,kBAAM,IAAI;AAAA,cACR,qCAAqCA,EAAwB,KAAK,KAAK,IAAI;AAAA,YAC7E;AAGF,eAAK,OAAO,SAAS;AAAA,YACnB3M,EAAmB2M,EAAwB,eAAe;AAAA,cACxD,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAASH,EAAS;AAAA,cAAA;AAAA,YAErB,CAAA;AAAA,UACH;AAAA,QAAA;AAAA,MAEJ;AACS,MAAAA,EAAA,iBAAiB,UAAUE,CAAa;AAE3C,YAAA,EAAE,KAAA9K,GAAK,YAAAiF,EAAA,IAAeha;AAAA,QAC1B,KAAK;AAAA,QACL;AAAA,QACA;AAAA,UACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,UACjD,GAAG2H;AAAA,QACL;AAAA,UACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,MAC/C;AAEI,UAAA,OAAO4F,KAAW,WAAW;AAM/B,cAAM4d,IAAQ,WADE,KAAK,OAAO,MAAM,IAAI,QAAQ5d,GAAQ,EAAE,KAAK,EAAE,MAAM;AAE5D,QAAAwd,EAAA,aAAa,mBAAmBI,CAAK,GAC9C/F,EAAW,KAAK+F;AAAA,MAAA;AAGlB,aAAAhL,EAAI,YAAYiF,CAAU,GAC1BjF,EAAI,YAAYkD,CAAO,GACvBA,EAAQ,YAAY2H,CAAe,GACnC3H,EAAQ,YAAY+B,CAAU,GAC9B4F,EAAgB,YAAYD,CAAQ,GAE7B;AAAA,QACL,KAAA5K;AAAA,QACA,YAAAiF;AAAA,QACA,SAAS,MAAM;AACJ,UAAA2F,EAAA,oBAAoB,UAAUE,CAAa;AAAA,QAAA;AAAA,MAExD;AAAA,IACF;AAAA,EAAA;AAEJ,CAAC,GAEYG,KAAgB5c;AAAA,EAC3Bsc;AAAA,EACAD;AACF,GCtSMQ,KAAa,IAAInkB,EAAU,wBAAwB,GAC5CokB,KAA6B,MACjC,IAAIrkB,EAAO;AAAA,EAChB,KAAKokB;AAAAA,EACL,mBAAmB,CAACE,GAAeC,GAAWnkB,MAAa;AACzD,UAAMI,IAAKJ,EAAS;AACjB,IAAAI,EAAA,QAAQ,wBAAwB,EAAI;AAEvC,QAAIgkB,IAAW;AAKf,WAAApkB,EAAS,IAAI,YAAY,CAACiB,GAAMI,MAAQ;;AAEpC,UAAAJ,EAAK,KAAK,SAAS,oBACnBA,EAAK,WAAY,KAAK,SAAS,oBAC/B;AACA,YAAIojB,IAAW,GAAGpjB,EAAK,WAAY,MAAM,SAAY,CAAC;AAEtD,cAAMqL,IAAY7C,GAAa;AAAA,UAC7B,eAAepI;AAAA,UACf,MAAAJ;AAAA,QAAA,CACD;AAEG,YAAA,CAACqL,EAAU;AACP,gBAAA,IAAI,MAAM,YAAY;AAMxB,cAAA4J,IAAY9V,EAAG,IAAI;AAAA,UACvBkM,EAAU,QAAQ;AAAA,QAAA,EAClB;AAEF,YAAI4J,GAAW;AACb,gBAAMoO,IAAgB7a,GAAa;AAAA,YACjC,eAAe6C,EAAU,QAAQ,YAAY4J,EAAU;AAAA,YACvD,MAAMA;AAAA,UAAA,CACP;AAKD,cAFEoO,EAAc,kBAAkB,oBAEF;AAC1B,gBAAA,CAACA,EAAc;AACX,oBAAA,IAAI,MAAM,YAAY;AAE9B,kBAAMC,IACJD,EAAc,aAAa,KAAK,MAAM;AAExC,YAAAD,KAAY,SAASE,CAAc,IAAI,GAAG,SAAS;AAAA,UAAA;AAAA,QACrD;AAGI,cAAA9Z,IAAc6B,EAAU,aAAa,MACrCpN,IAAQuL,EAAY,MAAM,OAC1B+Z,MACJnkB,IAAA6V,KAAA,gBAAAA,EAAW,eAAX,gBAAA7V,EAAuB,KAAK,UAAS;AAEvC,YAAInB,MAAUmlB,KAAa5Z,EAAY,MAAM,SAAS,CAAC+Z,GAAU;AACpD,UAAAJ,IAAA;AAEX,gBAAM,EAAE,OAAApM,GAAO,GAAGrD,MAAUlK,EAAY;AAExC,UAAArK,EAAG,cAAckM,EAAU,aAAa,WAAW,QAAW;AAAA,YAC5D,GAAGqI;AAAA,YACH,OAAO0P;AAAA,YACP,GAAI,OAAOrM,KAAU,YACnBwM,KAAW;AAAA,cACT,OAAAxM;AAAA,YAAA;AAAA,UACF,CACH;AAAA,QAAA;AAAA,MACH;AAAA,IACF,CACD,GAEMoM,IAAWhkB,IAAK;AAAA,EAAA;AACzB,CACD,GCrEUqkB,KAA6B;AAAA,EACxC,GAAGtf;AAAA,EACH,OAAO,EAAE,SAAS,QAAW,MAAM,SAAS;AAC9C,GAEMuf,KAA+B5d,EAA8B;AAAA,EACjE,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,UAAU;AAAA,EACV,gBAAgB;AACP,WAAA;AAAA,MACL,GAAGpB,GAAkB+e,EAA0B;AAAA;AAAA;AAAA,MAG/C,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,CAACllB,MAAYA,EAAQ,aAAa,YAAY;AAAA,QACzD,YAAY,CAACC,OACJ;AAAA,UACL,cAAcA,EAAW;AAAA,QAC3B;AAAA,MACF;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,gBAAgB;AACP,WAAA;AAAA;AAAA,MAEL,IAAIqf,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,gBAAgB;AAAA,QACjC,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,GAAO,OAAAiJ,QAAY;AACrC,gBAAAxS,IAAY1C,EAA0BC,CAAK;AACjD,cACE,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAClDA,EAAU,kBAAkB;AAE5B;AAEF,gBAAMqY,IAAa,SAAS7F,EAAM,CAAC,CAAC;AAEpC,UAAA2B,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OACGqY,MAAe,KAAK,MACpB;AAAA,gBACC,OAAOA;AAAA,cAAA;AAAA,YAEZ,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAM9O,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MAEpD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,OAAO,MAAMqN,GAAY,KAAK,QAAQ,MAAM;AAAA,MAC5C,eAAe,MAAM;AACnB,cAAM5W,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,wBAAwB;AACf,WAAA,CAAC2X,IAA4B;AAAA,EACtC;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAAC1kB,MAAY;;AACjB,cAAA,OAAOA,KAAY;AACd,mBAAA;AAGT,gBAAM4a,IAAS5a,EAAQ;AAEvB,cAAI4a,MAAW;AACN,mBAAA;AAIP,cAAAA,EAAO,YAAY,QAClBA,EAAO,YAAY,WAAS9Z,IAAA8Z,EAAO,kBAAP,gBAAA9Z,EAAsB,aAAY,MAC/D;AACA,kBAAMskB,IACJ,SAASxK,EAAO,aAAa,OAAO,KAAK,GAAG,KAAK;AAE/C,mBAAA5a,EAAQ,mBAAmBolB,MAAe,IACrC,CAAC,IAGH;AAAA,cACL,OAAOA;AAAA,YACT;AAAA,UAAA;AAGK,iBAAA;AAAA,QACT;AAAA;AAAA;AAAA,QAGA,YAAY,CAAC1jB,GAAMiJ,MACjBkY,GAAmBnhB,GAAMiJ,GAAQ,KAAK,IAAI;AAAA,QAC5C,UAAU;AAAA,QACV,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAlC,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA;AAAA;AAAA;AAAA,MAIL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEYskB,KAAmBzd;AAAA,EAC9Bud;AAAA,EACAD;AACF,GCjKaI,KAAsB;AAAA,EACjC,GAAG1f;AACL,GAEa2f,KAAwBhe,EAA8B;AAAA,EACjE,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,uBAAuB;AACd,WAAA;AAAA,MACL,aAAa,MAAM;AACjB,cAAMwF,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAAC/M,MAAY;;AACrB,iBAAI,OAAOA,KAAY,YAAY,GAACc,IAAAd,EAAQ,gBAAR,QAAAc,EAAqB,UAChD,KAGF,CAAC;AAAA,QACV;AAAA,QACA,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAA2H,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEYykB,KAAY5d;AAAA,EACvB2d;AAAA,EACAD;AACF,GCnEaG,KAAkB;AAAA,EAC7B,GAAG7f;AACL,GAEa8f,KAAoBne,EAA8B;AAAA,EAC7D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,gBAAgB;AACP,WAAA;AAAA;AAAA,MAEL,IAAI+X,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,QAAQ;AAAA,QACzB,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAE/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO,CAAA;AAAA,YACR,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAMuJ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MAEpD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,aAAa,MAAM;AACjB,cAAMvJ,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,UACP,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAtE,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEY4kB,KAAQ/d;AAAA,EACnB8d;AAAA,EACAD;AACF,GC/FaG,KAAmB,IACnBC,KAAmB,KACnBC,KAAoB,IAEpBC,KAAiBlmB,EAAU,OAAO;AAAA,EAC7C,MAAM;AAAA,EAEN,uBAAuB,MACd;AAAA,IACLmmB,GAAe;AAAA,MACb,cAAcJ;AAAA,MACd,qBAAqBC;AAAA;AAAA;AAAA;AAAA,MAIrB,MAAM;AAAA,IAAA,CACP;AAAA,IACDI,GAAa;AAAA,EACf;AAAA,EAGF,uBAAuB;AACd,WAAA;AAAA;AAAA,MAEL,OAAO,MAEH,KAAK,OAAO,MAAM,UAAU,SAC5B,KAAK,OAAO,MAAM,UAAU,MAAM,OAAO,KAAK,SAC5C,oBAEF,KAAK,OAAO,SAAS,cAAc,EAAE,MAAM,aAAa,GAEjD,MAGF;AAAA;AAAA;AAAA,MAIT,WAAW,MAAM;AACT,cAAAtG,IAAY,KAAK,OAAO,MAAM,WAC9BuG,IAAmBvG,EAAU,OAC7BwG,IAA2BxG,EAAU,MAAM,iBAAiB,GAC5DyG,IACJzG,EAAU,MAAM,KAAK,EAAE,KAAK,SAAS;AAEvC,eACEuG,KACAC,KACAC;AAAA,MAEJ;AAAA;AAAA,MAEA,KAAK,MACI,KAAK,OAAO,SAAS;AAAA,QAAQ,CAAC,EAAE,OAAA9b,GAAO,UAAAuN,GAAU,MAAA3V,EACtD,MAAAmkB,GAAa,CAAC,EAAE/b,GAAOuN,GAAU3V,CAAI;AAAA,MACvC;AAAA,MAEF,aAAa,MACJ,KAAK,OAAO,SAAS;AAAA,QAAQ,CAAC,EAAE,OAAAoI,GAAO,UAAAuN,GAAU,MAAA3V,EACtD,MAAAmkB,GAAa,EAAE,EAAE/b,GAAOuN,GAAU3V,CAAI;AAAA,MACxC;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,iBAAiBokB,GAAW;AAC1B,UAAMC,IAAU;AAAA,MACd,MAAMD,EAAU;AAAA,MAChB,SAASA,EAAU;AAAA,MACnB,SAASA,EAAU;AAAA,IACrB;AAEO,WAAA;AAAA,MACL,WAAWE;AAAA,QACTC,GAAkBH,GAAW,aAAaC,CAAO;AAAA,MAAA;AAAA,IAErD;AAAA,EAAA;AAEJ,CAAC,GCnEYG,KAAkB;AAAA,EAC7B,WAAW9gB,EAAa;AAC1B,GAEa+gB,KAAoBpf,EAA8B;AAAA,EAC7D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,WAAW;AAAA,EAEX,OAAO;AAAA,EACP,WAAW;AAAA,EAEX,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,MAAA;AAAA,IAET;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAkB,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAc;AACZ,WAAO,CAAC,EAAE,MAAAW,GAAM,gBAAA+G,QAAqB;;MACnC,MAAMme,UAA2BC,GAAU;AAAA,QACzC,YACSnlB,GACAolB,GACAniB,GACP;AACA,gBAAMjD,GAAMolB,CAAY,GAJjBplB,KAAAA,OAAAA,GACA,KAAA,eAAAolB,GACA,KAAA,6BAAAniB;AAID,gBAAAE,IAAe,SAAS,cAAc,KAAK;AACjD,UAAAA,EAAa,YAAYT;AAAA,YACvB;AAAA,YACAO,EAA2B;AAAA,UAC7B,GACaE,EAAA,aAAa,qBAAqB,OAAO;AACtD,qBAAW,CAACC,GAAWC,CAAK,KAAK,OAAO;AAAA,YACtCJ;AAAA,UAAA;AAEA,YAAIG,MAAc,WACHD,EAAA,aAAaC,GAAWC,CAAK;AAI9C,gBAAMgiB,IAAe,KAAK,KAEpBC,IAAoB,SAAS,cAAc,KAAK;AACtD,UAAAA,EAAkB,YAAY,sBACZA,EAAA,YAAYD,EAAa,UAAW,GAEtDA,EAAa,YAAYC,CAAiB,GAE1CniB,EAAa,YAAYkiB,CAAY;AAC/B,gBAAAE,IAAoB,SAAS,cAAc,KAAK;AACtD,UAAAA,EAAkB,YAAY,2BAC9BA,EAAkB,MAAM,WAAW,YACnCF,EAAa,YAAYE,CAAiB,GAE1C,KAAK,MAAMpiB;AAAA,QAAA;AAAA,QAGb,eAAeqiB,GAAiC;AAE5C,iBAAA,CAAEA,EAAO,OAAuB,QAAQ,qBAAqB,KAC7D,MAAM,eAAeA,CAAM;AAAA,QAAA;AAAA,MAE/B;AAGK,aAAA,IAAIN,EAAmBllB,GAAMmkB,IAAkB;AAAA,QACpD,KAAI/kB,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MAAA,CACJ;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC,GAEK0e,KAAiB5f,EAA8B;AAAA,EACnD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EAET,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACvH,MAAY;AAMrB,cALI,OAAOA,KAAY,YAAY,CAACA,EAAQ,eAKxC,CAACA,EAAQ,QAAQ,qBAAqB;AACjC,mBAAA;AAGT,gBAAM4a,IAAS5a,EAAQ;AAEvB,iBAAI4a,MAAW,OACN,KAGLA,EAAO,YAAY,QAAQA,EAAO,YAAY,OACzC,CAAC,IAGH;AAAA,QACT;AAAA,QACA,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAnS,KAAkB;AACtB,WAAA,CAAC,KAAKA,GAAgB,CAAC;AAAA,EAAA;AAElC,CAAC,GAMY2e,KAAW3f,GAAK,OAAgD;AAAA,EAC3E,MAAM;AAAA,EAEN,aAAa;AACJ,WAAA;AAAA,MACL,gBAAgB,CAAA;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,SAAS;AAAA,EAET,WAAW;AAAA,EACX,OAAO;AAAA,EACP,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,MAAM;AAAA,EACvB;AAAA,EAEA,WAAW,EAAE,gBAAAgB,KAAkB;AACtB,WAAA;AAAA,MACL;AAAA,MACA4e,GAAgB,KAAK,QAAQ,gBAAgB5e,CAAc;AAAA,MAC3D;AAAA,IACF;AAAA,EAAA;AAEJ,CAAC;AAKD,SAAS6e,GAAkB5lB,GAAmBiJ,GAAgB;AAatD,QAAA4c,IAZSxE,GAAU,WAAWpY,CAAM,EAYb,MAAMjJ,GAAM;AAAA,IACvC,SAASiJ,EAAO,MAAM,WAAW,OAAO;AAAA,EAAA,CACzC,GACK6c,IAA6B,CAAC;AAGtB,SAAAD,EAAA,QAAQ,YAAY,CAACzb,MAAU;AAE3C,QAAIA,EAAM;AAER,aAAA0b,EAAiB,KAAK1b,CAAK,GACpB;AAAA,EAGF,CACR,GAEMpJ,EAAS,UAAU8kB,CAAgB;AAC5C;AAEO,MAAMC,KAAQ7f;AAAA,EACnB+e;AAAA,EACAD;AAAA,EACA;AAAA,IACEX;AAAA,IACAoB;AAAA,IACAO,GAAY,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQjB,SAAS;AAAA,MACT,YAAY;AACH,eAAA;AAAA,UACL;AAAA,YACE,KAAK;AAAA;AAAA;AAAA,YAGL,YAAY,CAAChmB,GAAMiJ,MACjB2c,GAAkB5lB,GAAqBiJ,CAAM;AAAA,UAAA;AAAA,QAEnD;AAAA,MAAA;AAAA,IACF,CACD;AAAA,IACDgd,GAAU,OAAO;AAAA,MACf,SAAS;AAAA,MACT,YAAY;AACH,eAAA;AAAA,UACL;AAAA,YACE,KAAK;AAAA;AAAA;AAAA,YAGL,YAAY,CAACjmB,GAAMiJ,MACjB2c,GAAkB5lB,GAAqBiJ,CAAM;AAAA,UAAA;AAAA,QAEnD;AAAA,MAAA;AAAA,IACF,CACD;AAAA,IACDyc;AAAA,EAAA;AAEJ,GCtQaQ,KAAoB,CAACC,MAAmC;AAC7D,QAAA5hB,IAAM4hB,EAAa,OAAO,QAC1B1F,IAAe0F,EAAa,SAAS;AAEpC,SAAA,EAAE,KAAA5hB,GAAK,cAAAkc,EAAa;AAC7B,GCUa2F,KACX,gaAEWC,KAAkB;AAAA,EAC7B,eAAeniB,EAAa;AAAA,EAC5B,iBAAiBA,EAAa;AAAA;AAAA,EAE9B,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EAEA,aAAa;AAAA,IACX,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,EAAA;AAEV,GAEaoiB,KAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,YAAYD;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AAAA,EACb,iBAAiB,CAAC,SAAS;AAC7B,GAEaE,KAAc,CACzB/iB,GACAC,MACG;AACG,QAAAmX,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAYwL;AAEX,QAAAI,IAAe,SAAS,cAAc,KAAK;AACjD,EAAAA,EAAa,YAAY;AAEnB,QAAAC,IAAQ,SAAS,cAAc,OAAO;AAC5C,SAAAA,EAAM,YAAY,mBACdhjB,EAAO,iBACTA,EAAO,eAAeD,EAAM,MAAM,GAAG,EAAE,KAAK,CAACuY,MAAgB;AAC3D,IAAA0K,EAAM,MAAM1K;AAAA,EAAA,CACb,IAEK0K,EAAA,MAAMjjB,EAAM,MAAM,KAE1BijB,EAAM,WAAW,IACjBA,EAAM,kBAAkB,SACxBA,EAAM,YAAY,IACZA,EAAA,QAAQjjB,EAAM,MAAM,cAC1BgjB,EAAa,YAAYC,CAAK,GAEvB/G;AAAA,IACLlc;AAAA,IACAC;AAAA,IACA,EAAE,KAAK+iB,EAAa;AAAA,IACpBA;AAAA,IACA/iB,EAAO,WAAW,YAAY,MAAM;AAAA,IACpCmX,EAAK;AAAA,EACP;AACF,GAEa8L,KAAa,CACxBpoB,MACmE;AAC/D,MAAAA,EAAQ,YAAY;AAElB,WAAAA,EAAQ,QAAQ,QAAQ,IACnB,SAGF4nB,GAAkB5nB,CAA2B;AAGlD,MAAAA,EAAQ,YAAY,UAAU;AAC1B,UAAA2d,IAAetC,GAAmBrb,GAAS,OAAO;AACxD,QAAI,CAAC2d;AACI;AAGH,UAAA,EAAE,eAAAnC,GAAe,SAAAE,EAAA,IAAYiC;AAE5B,WAAA;AAAA,MACL,GAAGiK,GAAkBpM,CAAiC;AAAA,MACtD,SAAAE;AAAA,IACF;AAAA,EAAA;AAIJ,GAEa2M,KAAsB,CACjCnjB,MACG;AACC,MAAA,CAACA,EAAM,MAAM,KAAK;AACd,UAAAwD,IAAM,SAAS,cAAc,GAAG;AACtC,WAAAA,EAAI,cAAc,aAEX;AAAA,MACL,KAAKA;AAAA,IACP;AAAA,EAAA;AAGE,MAAAyf;AAaA,SAZAjjB,EAAM,MAAM,eACNijB,IAAA,SAAS,cAAc,OAAO,GAChCA,EAAA,MAAMjjB,EAAM,MAAM,KACpBA,EAAM,MAAM,iBACRijB,EAAA,QAAQjjB,EAAM,MAAM,kBAGpBijB,IAAA,SAAS,cAAc,GAAG,GAC5BA,EAAA,OAAOjjB,EAAM,MAAM,KACzBijB,EAAM,cAAcjjB,EAAM,MAAM,QAAQA,EAAM,MAAM,MAGlDA,EAAM,MAAM,UACVA,EAAM,MAAM,cACP4X,GAAwBqL,GAAOjjB,EAAM,MAAM,OAAO,IAElD8X,GAAsBmL,GAAOjjB,EAAM,MAAM,OAAO,IAIpD;AAAA,IACL,KAAKijB;AAAA,EACP;AACF,GAEaG,KAAahgB,GAAgB0f,IAAkB;AAAA,EAC1D,QAAQC;AAAA,EACR,OAAOG;AAAA,EACP,gBAAgBC;AAClB,CAAC,GC3HYE,KAAoB;AAAA,EAC/B,WAAW/C;AAAA,EACX,SAASrE;AAAA,EACT,OAAOwE;AAAA,EACP,WAAW3F;AAAA,EACX,gBAAgBgE;AAAA,EAChB,kBAAkBqB;AAAA,EAClB,eAAeb;AAAA,EACf,OAAOiD;AAAA,EACP,MAAM3G;AAAA,EACN,OAAO8B;AAAA,EACP,OAAO0F;AAAA,EACP,OAAOzK;AACT,GAEa2K,KAAqB1gB,GAAwBygB,EAAiB,GAO9DE,KAAoB;AAAA,EAC/B,MAAMvZ,GAA8BwZ,IAAM,SAAS;AAAA,EACnD,QAAQxZ,GAA8ByZ,IAAQ,SAAS;AAAA,EACvD,WAAWzZ,GAA8B0Z,IAAW,SAAS;AAAA,EAC7D,QAAQ1Z,GAA8B2Z,IAAQ,SAAS;AAAA,EACvD,MAAM3Z,GAA8B4Z,IAAM,SAAS;AAAA,EACnD,WAAWzI;AAAA,EACX,iBAAiBF;AACnB,GAEa4I,KAAqB5Z,GAAwBsZ,EAAiB,GAO9DO,KAA4B;AAAA,EACvC,MAAM,EAAE,QAAQ,QAAQ,gBAAgB,CAAA,EAAU;AAAA,EAClD,MAAM,EAAE,QAAQ,QAAQ,gBAAgB,CAAU,EAAA;AACpD,GAEaC,KAA6B5a;AAAA,EACxC2a;AACF;AC9DgB,SAAAE,EAKdliB,GACA7B,GAC0E;AAExE,SAAA6B,KAAa7B,EAAO,OAAO,eAC3BA,EAAO,OAAO,YAAY6B,CAAS,MAAMwhB,GAAmBxhB,CAAS;AAEzE;AAEgB,SAAAmiB,GAKdnb,GACA7I,GAKA;AAEE,SAAA6I,KAAqB7I,EAAO,OAAO,uBACnCA,EAAO,OAAO,oBAAoB6I,CAAiB,MACjDib,GAA2Bjb,CAAiB;AAElD;AAEgB,SAAAob,GAKdpiB,GACA9B,GACAC,GAC+D;AAE7D,SAAAD,EAAM,SAAS8B,KACf9B,EAAM,QAAQC,EAAO,OAAO,eAC5B+jB,EAA8BhkB,EAAM,MAAMC,CAAM;AAEpD;AAEgB,SAAAkkB,GAKdnkB,GACAC,GACiD;AAE9C,SAAAD,EAAM,QAAQC,EAAO,OAAO,eAC3BA,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE,eACxC;AAEJ;AAEgB,SAAAokB,GAKdpkB,GACAC,GAOA;AACA,SACGD,EAAM,QAAQC,EAAO,OAAO,eAC3BA,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE,eACtC,iBAAiBC,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE,cACzD;AAEJ;AAEgB,SAAAqkB,GAIdrkB,GAAuBC,GAAkC;AAEzD,SADeA,EAAO,OAAO,YAAYD,EAAM,IAAI,EACrC,eAAe,CAACA,EAAM,MAAM;AAC5C;AAEgB,SAAAskB,GAKdniB,GACAL,GACA7B,GAaA;AAEE,SAAA6B,KAAa7B,EAAO,OAAO,eAC3BkC,KAAQlC,EAAO,OAAO,YAAY6B,CAAS,EAAE,cAC7C7B,EAAO,OAAO,YAAY6B,CAAS,EAAE,WAAWK,CAAI,MAAMzB,EAAayB,CAAI;AAE/E;AAEgB,SAAAoiB,GAKdpiB,GACAnC,GACAC,GAWA;AACA,SAAOqkB,GAA6BniB,GAAMnC,EAAM,MAAMC,CAAM;AAC9D;AAEO,SAASukB,GACd/J,GAC4B;AAC5B,SAAOA,aAAqBgK;AAC9B;ACnKa,MAAAC,KAAkC,OAC7CvN,MACoB;AACd,QAAAwN,IAAO,IAAI,SAAS;AACrB,SAAAA,EAAA,OAAO,QAAQxN,CAAI,IAMhB,OAJI,MAAM,MAAM,sCAAsC;AAAA,IAC5D,QAAQ;AAAA,IACR,MAAAwN;AAAA,EAAA,CACD,GACiB,KAAK,GAAG,KAAK,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,EACF;AACF;ACFA,SAASC,GAIP3kB,GAAwC;AACpC,MAAAD,IACFC,EAAO,sBAAA,EAAwB,OAC7B4kB,IAAc5kB,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE;AAExD,SAAO6kB,MAAgB,UAAQ;AAE7B,QADQ7kB,IAAAC,EAAO,wBAAwB,WACnCD,MAAU;AACZ;AAEF,IAAA6kB,IAAc5kB,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE,SAI7CC,EAAA,sBAAsBD,GAAO,KAAK;AAAA,EAAA;AAE7C;AAMgB,SAAA8kB,EAKd7kB,GACAD,GACsB;AAChB,QAAA+kB,IAAe9kB,EAAO,sBAAA,EAAwB;AAEhD,MAAA8kB,EAAa,YAAY;AACrB,UAAA,IAAI,MAAM,0DAA0D;AAGxE,MAAAC;AAEJ,SACE,MAAM,QAAQD,EAAa,OAAO,MAChCA,EAAa,QAAQ,WAAW,KAChClnB,GAA0BknB,EAAa,QAAQ,CAAC,CAAC,KACjDA,EAAa,QAAQ,CAAC,EAAE,SAAS,UACjCA,EAAa,QAAQ,CAAC,EAAE,SAAS,OACjCA,EAAa,QAAQ,WAAW,MAEvBC,IAAA/kB,EAAO,YAAY8kB,GAAc/kB,CAAK,GAIjDC,EAAO,sBAAsB+kB,CAAQ,MAE1BA,IAAA/kB,EAAO,aAAa,CAACD,CAAK,GAAG+kB,GAAc,OAAO,EAAE,CAAC,GAChE9kB,EAAO,sBAAsBA,EAAO,sBAAsB,EAAE,SAAU,IAGxE2kB,GAAuC3kB,CAAM,GAEtC+kB;AACT;AAEO,SAASC,GAIdhlB,GAAwC;AACxC,QAAM3F,IAAiC,CAAC;AAEpC,SAAA0pB,EAA8B,WAAW/jB,CAAM,KAC3C3F,EAAA;AAAA,IACJ;AAAA,MACE,aAAa,MAAM;AACjBwqB,QAAAA,EAAoB7kB,GAAQ;AAAA,UAC1B,MAAM;AAAA,UACN,OAAO,EAAE,OAAO,EAAE;AAAA,QAAA,CACnB;AAAA,MACH;AAAA,MACA,OAAOlB,EAAuB,WAAW;AAAA,MACzC,KAAK;AAAA,MACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,IAClC;AAAA,IACA;AAAA,MACE,aAAa,MAAM;AACjB6kB,QAAAA,EAAoB7kB,GAAQ;AAAA,UAC1B,MAAM;AAAA,UACN,OAAO,EAAE,OAAO,EAAE;AAAA,QAAA,CACnB;AAAA,MACH;AAAA,MACA,OAAOlB,EAAuB,WAAW;AAAA,MACzC,KAAK;AAAA,MACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,IAClC;AAAA,IACA;AAAA,MACE,aAAa,MAAM;AACjB6kB,QAAAA,EAAoB7kB,GAAQ;AAAA,UAC1B,MAAM;AAAA,UACN,OAAO,EAAE,OAAO,EAAE;AAAA,QAAA,CACnB;AAAA,MACH;AAAA,MACA,OAAOlB,EAAuB,WAAW;AAAA,MACzC,KAAK;AAAA,MACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,IAAA;AAAA,EAEpC,GAGE+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,KAAK;AAAA,IACL,GAAGA,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,oBAAoB/jB,CAAM,KAC1D3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,aAAa;AAAA,IAC3C,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,kBAAkB/jB,CAAM,KACxD3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,aAAa;AAAA,IAC3C,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,iBAAiB/jB,CAAM,KACvD3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,aAAa;AAAA,IAC3C,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,aAAa/jB,CAAM,KACnD3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,WAAW;AAAA,IACzC,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,aAAa/jB,CAAM,KACnD3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,WAAW;AAAA,IACzC,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,YACJ;AAAA,cACE,OAAO,CAAC,IAAI,IAAI,EAAE;AAAA,YACpB;AAAA,YACA;AAAA,cACE,OAAO,CAAC,IAAI,IAAI,EAAE;AAAA,YAAA;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CACD;AAAA,IACH;AAAA,IACA,OAAO;AAAA,IACP,KAAK;AAAA,IACL,GAAGA,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACX,YAAA4qB,IAAgBJ,EAAoB7kB,GAAQ;AAAA,QAChD,MAAM;AAAA,MAAA,CACP;AAGM,MAAAA,EAAA;AAAA,QAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,UACvC,OAAOilB;AAAA,QACR,CAAA;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,GAAGjlB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACX,YAAA4qB,IAAgBJ,EAAoB7kB,GAAQ;AAAA,QAChD,MAAM;AAAA,MAAA,CACP;AAGM,MAAAA,EAAA;AAAA,QAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,UACvC,OAAOilB;AAAA,QACR,CAAA;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,GAAGjlB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACX,YAAA4qB,IAAgBJ,EAAoB7kB,GAAQ;AAAA,QAChD,MAAM;AAAA,MAAA,CACP;AAGM,MAAAA,EAAA;AAAA,QAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,UACvC,OAAOilB;AAAA,QACR,CAAA;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,GAAGjlB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,QAAQ/jB,CAAM,KAC9C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACX,YAAA4qB,IAAgBJ,EAAoB7kB,GAAQ;AAAA,QAChD,MAAM;AAAA,MAAA,CACP;AAGM,MAAAA,EAAA;AAAA,QAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,UACvC,OAAOilB;AAAA,QACR,CAAA;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,GAAGjlB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGH3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjB,MAAA2F,EAAO,mBAAmB,KAAK;AAAA,QAC7B,wBAAwB;AAAA,QACxB,mBAAmB;AAAA,MAAA,CACpB;AAAA,IACH;AAAA,IACA,KAAK;AAAA,IACL,GAAGA,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAEM3F;AACT;AAEgB,SAAA6qB,GAEd7qB,GAAY8qB,GAAe;AAC3B,SAAO9qB,EAAM;AAAA,IACX,CAAC,EAAE,OAAA+qB,GAAO,SAAAtK,QACRsK,EAAM,YAAc,EAAA,SAASD,EAAM,YAAa,CAAA,KAC/CrK,KACCA,EAAQ;AAAA,MAAO,CAACuK,MACdA,EAAM,cAAc,SAASF,EAAM,YAAa,CAAA;AAAA,MAChD,WAAW;AAAA,EACnB;AACF;AChTA,SAASG,GAA2D7mB,GAAW;AAC7E,SAAKA,KAGE,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAG,EAAE,OAAO,CAAC,GAAGmB,CAAK,MAAMA,MAAU,MAAS;AAAA,EAC/D;AACF;AAEO,MAAM2lB,GAIX;AAAA,EAoDA,YAAYC,GAIT;AAvDa,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAGA;AAAA,IAAAA,EAAA,yBACd;AAEc,IAAAA,EAAA,eACd;AAEc,IAAAA,EAAA,sBAIZ;AAqCF,SAAK,aAAaH,GAAgBE,KAAA,gBAAAA,EAAM,UAAU,KAAKpC,IACvD,KAAK,qBACHkC,GAAgBE,KAAA,gBAAAA,EAAM,kBAAkB,KAAK3B,IAC/C,KAAK,aAAayB,GAAgBE,KAAA,gBAAAA,EAAM,UAAU,KAAKlC,IAElD,KAAA,cAAc3gB,GAAwB,KAAK,UAAU,GAC1D,KAAK,sBAAsBuG;AAAA,MACzB,KAAK;AAAA,IACP,GACK,KAAA,cAAcc,GAAwB,KAAK,UAAU;AAAA,EAAA;AAAA,EA5C5D,OAAc,OAIZmK,GAaC;AACM,WAAA,IAAIoR,GAITpR,CAAO;AAAA,EAAA;AAwBb;ACpGO,MAAMuR,KAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,YAAY,CAAC;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,cAAc;AAChB,GACaC,KAAkB,MAAM;AAC7B,QAAAC,IAAY,SAAS,cAAc,KAAK;AAE9C,SAAAA,EAAU,YAAY,iBACZA,EAAA,aAAa,mBAAmB,EAAE,GAErC;AAAA,IACL,KAAKA;AAAA,EACP;AACF,GACaC,KAAiB,CAC5BhrB,MACkE;AAClE,MAAIA,EAAQ,YAAY,SAASA,EAAQ,aAAa,iBAAiB;AAC9D,WAAA;AAAA,MACL,MAAM;AAAA,IACR;AAIJ,GACairB,KAA0B,MAAM;AACrC,QAAAF,IAAY,SAAS,cAAc,KAAK;AAEpC,SAAAA,EAAA,aAAa,mBAAmB,EAAE,GAErC;AAAA,IACL,KAAKA;AAAA,EACP;AACF,GAEaG,KAAY5iB,GAAgBuiB,IAAiB;AAAA,EACxD,QAAQC;AAAA,EACR,OAAOE;AAAA,EACP,gBAAgBC;AAClB,CAAC,GCxCYE,KAAkBT,GAAgB,OAAO;AAAA,EACpD,YAAY;AAAA,IACV,WAAWQ;AAAA,EAAA;AAEf,CAAC,GAKYE,KAAgB,CAK3BzgB,MAEO+f,GAAgB,OAAO;AAAA,EAC5B,YAAY;AAAA,IACV,GAAG/f,EAAO;AAAA,IACV,GAAGwgB,GAAgB;AAAA,EACrB;AAAA,EACA,oBAAoBxgB,EAAO;AAAA,EAC3B,YAAYA,EAAO;AAAA,CACpB;ACrBI,SAAS0gB,GAIdlmB,GACqE;AAEnE,SAAA,eAAeA,EAAO,OAAO,eAC7BA,EAAO,OAAO,YAAY,cACxBgmB,GAAgB,YAAY;AAElC;AAEO,SAASG,GAIdnmB,GAAwC;AACxC,QAAM3F,IACJ,CAAC;AAEC,SAAA6rB,GAA6BlmB,CAAM,KACrC3F,EAAM,KAAK;AAAA,IACT,GAAG2F,EAAO,WAAW,WAAW;AAAA,IAChC,aAAa,MAAM;AACjB6kB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,KAAK;AAAA,EAAA,CACN,GAGI3F;AACT;ACFA,SAAS+rB,GACPpmB,GACoB;AACb,SAAAA,EAAO,SAAS,CAACtE,MAAO;AAC7B,UAAM2qB,IAAqB3iB,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,MAAM;AAErE,QAAAA,EAAG,qBAAqB8oB;AACnB,aAAA;AAAA,QACL,MAAM;AAAA,QACN,eAAe6B,EAAmB,KAAK,MAAM;AAAA,QAC7C,kBACE3qB,EAAG,UAAU,YAAY,MAAM2qB,EAAmB;AAAA,QACpD,gBACE3qB,EAAG,UAAU,UAAU,MAAM2qB,EAAmB;AAAA,MACpD;AACF,QAAW3qB,EAAG,qBAAqB4qB;AAC1B,aAAA;AAAA,QACL,MAAM;AAAA,QACN,eAAeD,EAAmB,KAAK,MAAM;AAAA,MAC/C;AACK;AACL,YAAME,IAAmB7iB,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,IAAI;AAE9D,aAAA;AAAA,QACL,MAAM;AAAA,QACN,eAAe2qB,EAAmB,KAAK,MAAM;AAAA,QAC7C,aAAaE,EAAiB,KAAK,MAAM;AAAA,QACzC,cAAc7qB,EAAG,UAAU,SAAS2qB,EAAmB;AAAA,QACvD,YAAY3qB,EAAG,UAAU,OAAO6qB,EAAiB;AAAA,MACnD;AAAA,IAAA;AAAA,EACF,CACD;AACH;AAaA,SAASC,GACP9qB,GACA+qB,GACA;;AACA,QAAMC,KAAiB/qB,IAAA0U,EAAYoW,EAAK,eAAe/qB,EAAG,GAAG,MAAtC,gBAAAC,EAAyC;AAChE,MAAI+qB,MAAmB;AACrB,UAAM,IAAI;AAAA,MACR,gCAAgCD,EAAK,aAAa;AAAA,IACpD;AAGE,MAAAjM;AACA,MAAAiM,EAAK,SAAS;AAChB,IAAAjM,IAAYgK,GAAc;AAAA,MACxB9oB,EAAG;AAAA,MACHgrB,IAAiBD,EAAK;AAAA,MACtBC,IAAiBD,EAAK;AAAA,IACxB;AAAA,WACSA,EAAK,SAAS;AACvB,IAAAjM,IAAY8L,GAAc,OAAO5qB,EAAG,KAAKgrB,IAAiB,CAAC;AAAA,OACtD;AACL,UAAMC,KAAe/qB,IAAAyU,EAAYoW,EAAK,aAAa/qB,EAAG,GAAG,MAApC,gBAAAE,EAAuC;AAC5D,QAAI+qB,MAAiB;AACnB,YAAM,IAAI;AAAA,QACR,gCAAgCF,EAAK,WAAW;AAAA,MAClD;AAGF,IAAAjM,IAAYD,EAAc;AAAA,MACxB7e,EAAG;AAAA,MACHgrB,IAAiBD,EAAK;AAAA,MACtBE,IAAeF,EAAK;AAAA,IACtB;AAAA,EAAA;AAGF,EAAA/qB,EAAG,aAAa8e,CAAS;AAC3B;AAQA,SAASoM,GACP5e,GACwB;AACjB,SAAAA,EACJ,IAAI,CAACjI,MACAA,EAAM,SAAS,eACVA,EAAM,SACV,IAAI,CAAC8mB,MAAWD,GAAeC,EAAO,QAAQ,CAAC,EAC/C,KAAK,IAGH;AAAA,IACL,GAAG9mB;AAAA,IACH,UAAU6mB,GAAe7mB,EAAM,QAAQ;AAAA,EACzC,CACD,EACA,KAAK;AACV;AAYgB,SAAA+mB,GACd9mB,GACA2R,GACAC,GACA;AAEO,EAAA5R,EAAA,SAAS,CAACtE,MAAO;;AACtB,UAAMsM,MAASrM,IAAAqE,EAAO,aAAa,MAApB,gBAAArE,EAAuB,WAAU;AAAA,MAC9CqE,EAAO,wBAAwB;AAAA,IACjC,GACM+mB,IAAgBX,GAAsBpmB,CAAM;AAElD,IAAAA,EAAO,aAAagI,CAAM,GAC1BhI,EAAO,aAAa4mB,GAAe5e,CAAM,GAAG2J,GAAgBC,CAAS,GAErE4U,GAA6B9qB,GAAIqrB,CAAa;AAAA,EAAA,CAC/C;AACH;AAMA,SAASC,GAAsBC,GAA6C;AACnE,SAAA,CAACA,KAAeA,EAAY,SAAS;AAC9C;AAYA,SAASC,GACPlnB,GACAwR,GACAyV,GAGY;AACR,MAAAtV,GACAC;AAgBA,MAdCJ,IAKMA,EAAU,SAAS,SAAS,KACrCG,IAAiBH,EAAU,SAASA,EAAU,SAAS,SAAS,CAAC,GACrDI,IAAA,YAEKD,IAAAH,GACLI,IAAA,YATRqV,MACetV,IAAAsV,GACLrV,IAAA,WAWZ,CAACD,KAAkB,CAACC;AACf;AAGH,QAAAuV,IAAuBnnB,EAAO,eAAe2R,CAAc;AAC7D,SAACqV,GAAsBG,CAAoB,IAUxC,EAAE,gBAAAxV,GAAgB,WAAAC,EAAU,IAT1BsV;AAAA,IACLlnB;AAAA,IACA4R,MAAc,UACVD,IACA3R,EAAO,aAAa2R,CAAc;AAAA,IACtCwV;AAAA,EACF;AAIJ;AAYA,SAASC,GACPpnB,GACAqnB,GACAJ,GAGY;AACR,MAAAtV,GACAC;AAgBA,MAdCyV,IAKMA,EAAU,SAAS,SAAS,KACpB1V,IAAA0V,EAAU,SAAS,CAAC,GACzBzV,IAAA,aAEKD,IAAA0V,GACLzV,IAAA,WATRqV,MACetV,IAAAsV,GACLrV,IAAA,UAWZ,CAACD,KAAkB,CAACC;AACf;AAGH,QAAAuV,IAAuBnnB,EAAO,eAAe2R,CAAc;AAC7D,SAACqV,GAAsBG,CAAoB,IAUxC,EAAE,gBAAAxV,GAAgB,WAAAC,EAAU,IAT1BwV;AAAA,IACLpnB;AAAA,IACA4R,MAAc,WACVD,IACA3R,EAAO,aAAa2R,CAAc;AAAA,IACtCwV;AAAA,EACF;AAIJ;AAEO,SAASG,GAAatnB,GAAwC;AACnE,EAAAA,EAAO,SAAS,MAAM;AACd,UAAAwa,IAAYxa,EAAO,aAAa,GAChCD,KAAQya,KAAA,gBAAAA,EAAW,OAAO,OAAMxa,EAAO,wBAAwB,OAE/DunB,IAAkBL;AAAA,MACtBlnB;AAAA,MACAA,EAAO,aAAaD,CAAK;AAAA,MACzBC,EAAO,eAAeD,CAAK;AAAA,IAC7B;AAEA,IAAKwnB,KAILT;AAAA,MACE9mB;AAAA,MACAunB,EAAgB;AAAA,MAChBA,EAAgB;AAAA,IAClB;AAAA,EAAA,CACD;AACH;AAEO,SAASC,GAAexnB,GAAwC;AACrE,EAAAA,EAAO,SAAS,MAAM;AACd,UAAAwa,IAAYxa,EAAO,aAAa,GAChCD,KACJya,KAAA,gBAAAA,EAAW,QAAOA,KAAA,gBAAAA,EAAW,OAAO,UAAS,OAC7Cxa,EAAO,sBAAwB,EAAA,OAE3BynB,IAAoBL;AAAA,MACxBpnB;AAAA,MACAA,EAAO,aAAaD,CAAK;AAAA,MACzBC,EAAO,eAAeD,CAAK;AAAA,IAC7B;AAEA,IAAK0nB,KAILX;AAAA,MACE9mB;AAAA,MACAynB,EAAkB;AAAA,MAClBA,EAAkB;AAAA,IACpB;AAAA,EAAA,CACD;AACH;ACpUA,SAASC,GAAaC,GAAoBC,GAAqB;AACtD,SAAA,SAAUziB,GAAoBuN,GAAsC;AACzE,UAAM,EAAE,OAAA+H,GAAO,KAAAoN,EAAI,IAAI1iB,EAAM,WACvBgM,IAAQsJ,EAAM;AAAA,MAClBoN;AAAA,MACA,CAACtrB,MACCA,EAAK,aAAa,MACjBA,EAAK,KAAK,SAAS,gBAAgBA,EAAK,KAAK,SAAS;AAAA;AAAA,IAC3D;AACA,QAAI,CAAC4U;AACI,aAAA;AAET,UAAM8O,IAAa9O,EAAM;AACzB,QAAI8O,MAAe;AACV,aAAA;AAGT,UAAM6H,IADS3W,EAAM,OACK,MAAM8O,IAAa,CAAC;AAC1C,QAAA6H,EAAW,SAASH;AACf,aAAA;AAET,QAAIjV,GAAU;AACZ,YAAMqV,IACJD,EAAW,aAAaA,EAAW,UAAU,SAASF,GAClDI,IAAQzqB,EAAS,KAAKwqB,IAAeJ,EAAS,WAAW,IAAI,GAC7DzqB,IAAQ,IAAIM;AAAA,QAChBD,EAAS;AAAA,UACPoqB,EAAS,OAAO,MAAMpqB,EAAS,KAAKqqB,EAAU,OAAO,MAAMI,CAAK,CAAC,CAAC;AAAA;AAAA,QACpE;AAAA,QACAD,IAAe,IAAI;AAAA,QACnB;AAAA,MACF,GAEME,IAAS9W,EAAM,OACf+W,IAAQ/W,EAAM;AACpB,MAAAuB;AAAA,QACEvN,EAAM,GACH;AAAA,UACC,IAAIgjB;AAAA,YACFF,KAAUF,IAAe,IAAI;AAAA,YAC7BG;AAAA,YACAD;AAAA,YACAC;AAAA,YACAhrB;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,QACF,EAED,eAAe;AAAA,MACpB;AAAA,IAAA;AAEK,WAAA;AAAA,EACT;AACF;AAEO,SAASkrB,GAAUpoB,GAAwC;AAChE,SAAOA,EAAO;AAAA,IAAK,CAACmF,GAAOuN,MACzBgV;AAAA,MACEviB,EAAM,OAAO,MAAM;AAAA,MACnBA,EAAM,OAAO,MAAM;AAAA,IACrB,EAAEA,GAAOuN,CAAQ;AAAA,EACnB;AACF;AAEO,SAAS2V,GAAYroB,GAAwC;AAC3D,EAAAA,EAAA,cAAc,SAAS,aAAa,gBAAgB;AAC7D;AAEO,SAASsoB,GAAatoB,GAAwC;AAC5D,SAAAA,EAAO,SAAS,CAACtE,MAAO;AAC7B,UAAM,EAAE,SAAS6M,MAAmBnD,GAA4B1J,CAAE;AAElE,WAAOA,EAAG,IAAI,QAAQ6M,EAAe,SAAS,EAAE,eAAe;AAAA,EAAA,CAChE;AACH;AAEO,SAASggB,GAAevoB,GAAwC;AAC9D,SAAAA,EAAO,SAAS,CAACtE,MAAO;AAC7B,UAAM,EAAE,SAAS6M,MAAmBnD,GAA4B1J,CAAE;AAElE,WAAOA,EAAG,IAAI,QAAQ6M,EAAe,SAAS,EAAE,QAAQ;AAAA,EAAA,CACzD;AACH;ACnFgB,SAAAigB,GAKd7kB,GACAhC,GACkC;AAClC,QAAMlF,IACJ,OAAOkF,KAAoB,WAAWA,IAAkBA,EAAgB,IACpEoP,IAAW1L,EAAY1B,CAAG,GAE1BqB,IAAUqL,EAAY5T,GAAIkH,CAAG;AACnC,MAAKqB;AAIE,WAAAwC,EAAYxC,EAAQ,MAAM+L,CAAQ;AAC3C;AAEgB,SAAA0X,GAKd9kB,GACAhC,GACkC;AAClC,QAAMlF,IACJ,OAAOkF,KAAoB,WAAWA,IAAkBA,EAAgB,IAEpEqD,IAAUqL,EAAY5T,GAAIkH,CAAG,GAC7BoN,IAAW1L,EAAY1B,CAAG;AAChC,MAAI,CAACqB;AACI;AAIT,QAAM0jB,IADiB/kB,EAAI,QAAQqB,EAAQ,aAAa,EACnB;AACrC,MAAK0jB;AAIE,WAAAlhB,EAAYkhB,GAAe3X,CAAQ;AAC5C;AAEgB,SAAA4X,GAKdhlB,GACAhC,GACkC;AAClC,QAAMlF,IACJ,OAAOkF,KAAoB,WAAWA,IAAkBA,EAAgB,IACpEqD,IAAUqL,EAAY5T,GAAIkH,CAAG,GAC7BoN,IAAW1L,EAAY1B,CAAG;AAChC,MAAI,CAACqB;AACI;AAMT,QAAM0jB,IAHgB/kB,EAAI;AAAA,IACxBqB,EAAQ,gBAAgBA,EAAQ,KAAK;AAAA,EACvC,EACoC;AACpC,MAAK0jB;AAIE,WAAAlhB,EAAYkhB,GAAe3X,CAAQ;AAC5C;AAEgB,SAAA6X,GAKdjlB,GACAhC,GACkC;AAClC,QAAMlF,IACJ,OAAOkF,KAAoB,WAAWA,IAAkBA,EAAgB,IACpEoP,IAAW1L,EAAY1B,CAAG,GAC1BqB,IAAUqL,EAAY5T,GAAIkH,CAAG;AACnC,MAAI,CAACqB;AACI;AAGT,QAAM6jB,IAAiBllB,EAAI,QAAQqB,EAAQ,aAAa,GAClD8jB,IAAaD,EAAe,KAAK,GACjCE,IAAkBF,EAAe,KAAK,EAAE,GACxCH,IACJK,EAAgB,KAAK,SAAS,QAC1BD,EAAW,KAAK,SAAS,eACvBC,IACAD,IACF;AACN,MAAKJ;AAIE,WAAAlhB,EAAYkhB,GAAe3X,CAAQ;AAC5C;AC7GgB,SAAAiY,GACdttB,GACAsI,GACAsL,GACA6E,IAEI,EAAE,iBAAiB,MACvB;AAMA,MAAI,EAAE,MAAAzF,GAAM,IAAAC,MACV,OAAO3K,KAAa,WAChB,EAAE,MAAMA,GAAU,IAAIA,EAAA,IACtB,EAAE,MAAMA,EAAS,MAAM,IAAIA,EAAS,GAAG,GAEzCilB,IAAoB,IACpBC,IAAqB,IAGrBha,IAAO;AAoBP,MAlBEI,EAAA,QAAQ,CAAC/S,MAAS;AAEtB,IAAAA,EAAK,MAAM,GAEP0sB,KAAqB1sB,EAAK,UAAUA,EAAK,MAAM,WAAW,IAC5D2S,KAAQ3S,EAAK,OAEO0sB,IAAA,IAGDC,IAAAA,IAAqB3sB,EAAK,UAAU;AAAA,EAAA,CAC1D,GAOGmS,MAASC,KAAMua,GAAoB;AACrC,UAAM,EAAE,QAAAzT,EAAO,IAAI/Z,EAAG,IAAI,QAAQgT,CAAI;AAItC,IAFE+G,EAAO,eAAe,CAACA,EAAO,KAAK,KAAK,QAAQ,CAACA,EAAO,eAGhD/G,KAAA,GACFC,KAAA;AAAA,EACR;AAKF,SAAIsa,IAUCvtB,EAAA,WAAWwT,GAAMR,GAAMC,CAAE,IAEzBjT,EAAA,YAAYgT,GAAMC,GAAIW,CAAK,GAI5B6E,EAAQ,mBACVgV,GAAwBztB,GAAIA,EAAG,MAAM,SAAS,GAAG,EAAE,GAG9C;AACT;AC/DO,SAAS0tB,GAId1tB,GAAuD;AACjD,QAAAqV,IAAW1L,EAAY3J,CAAE;AAE/B,MAAIA,EAAG,UAAU,SAAS,UAAUA,EAAG;AAC9B;AAGH,QAAA2tB,IAAuB3tB,EAAG,IAAI;AAAA,IAClCgI,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,IAAI,EAAE;AAAA,EAChD,GACM4tB,IAAqB5tB,EAAG,IAAI;AAAA,IAChCgI,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,EAAE,EAAE;AAAA,EAC9C,GAKM6tB,IAAe,CACnB/uB,GACAqJ,MACyB;AACzB,UAAMlH,IAAM0sB,EAAqB,WAAW7uB,GAAOqJ,CAAK,GAClDtH,IAAOb,EAAG,IAAI,QAAQiB,CAAG,EAAE;AAEjC,QAAI,CAACJ;AACH,YAAM,IAAI;AAAA,QACR,wDAAwDI,CAAG;AAAA,MAC7D;AAGK,WAAA6K,EAAYjL,GAAMwU,CAAQ;AAAA,EACnC,GAEM/I,IAAiC,CAAC,GAElCwhB,IAAcH,EAAqB,YAAYC,EAAmB,GAAG,GACrErJ,IAAaoJ,EAAqB,MAAMG,CAAW,GACnDC,IAAWH,EAAmB,MAAME,CAAW;AAgCjD,MAAAH,EAAqB,QAAQG,GAAa;AAE5C,IAAAxhB,EAAO,KAAKR,EAAY6hB,EAAqB,WAAYtY,CAAQ,CAAC;AAIlE,aAASlN,IAAQwlB,EAAqB,OAAOxlB,IAAQ2lB,GAAa3lB;AAGhE,UAFmBwlB,EAAqB,KAAKxlB,CAAK,EAEnC,KAAK,UAAU,gBAAgB,GAAG;AAC/C,cAAM6lB,IAAoBL,EAAqB,MAAMxlB,CAAK,IAAI,GACxD8lB,IAAoBN,EAAqB,KAAKxlB,CAAK,EAAE;AAI3D,iBAAStD,IAAImpB,GAAmBnpB,IAAIopB,GAAmBppB;AACrD,UAAAyH,EAAO,KAAKuhB,EAAahpB,GAAGsD,CAAK,CAAC;AAAA,MACpC;AAAA,EAEJ;AAGA,IAAAmE,EAAO,KAAKuhB,EAAatJ,GAAYuJ,CAAW,CAAC;AAKnD,WAASjpB,IAAI0f,IAAa,GAAG1f,KAAKkpB,GAAUlpB;AAC1C,IAAAyH,EAAO,KAAKuhB,EAAahpB,GAAGipB,CAAW,CAAC;AAGtC,MAAAxhB,EAAO,WAAW;AACpB,UAAM,IAAI;AAAA,MACR,gEAAgEtM,EAAG,SAAS;AAAA,IAC9E;AAGK,SAAA;AAAA,IACL,QAAAsM;AAAA,EACF;AACF;AAEgB,SAAA4hB,GACdluB,GACAmuB,GACAC,GACA;AACA,QAAMC,IACJ,OAAOF,KAAe,WAAWA,IAAaA,EAAW,IACrDG,IAAa,OAAOF,KAAa,WAAWA,IAAWA,EAAS,IAChE/Y,IAAW1L,EAAY3J,CAAE,GACzB8J,IAASC,GAAmBsL,CAAQ;AAE1C,MAAIgZ,MAAiBC;AACnB,UAAM,IAAI;AAAA,MACR,wEAAwED,CAAY;AAAA,IACtF;AAEF,QAAME,IAAgB5Z,EAAY0Z,GAAcruB,EAAG,GAAG;AACtD,MAAI,CAACuuB;AACH,UAAM,IAAI,MAAM,iBAAiBF,CAAY,YAAY;AAE3D,QAAMG,IAAc7Z,EAAY2Z,GAAYtuB,EAAG,GAAG;AAClD,MAAI,CAACwuB;AACH,UAAM,IAAI,MAAM,iBAAiBF,CAAU,YAAY;AAGnD,QAAAG,IAAkBplB,GAAaklB,CAAa,GAC5CG,IAAgBrlB,GAAamlB,CAAW,GAExCG,IACJ7kB,EAAO,YACL2kB,EAAgB,aAClB,GACIG,IACJ9kB,EAAO,YACL4kB,EAAc,aAChB;AAEF,MACE,CAACD,EAAgB,oBACjBE,EAAkB,YAAY;AAE9B,UAAM,IAAI;AAAA,MACR,mEAAmEN,CAAY;AAAA,IACjF;AAEF,MAAI,CAACK,EAAc,oBAAoBE,EAAgB,YAAY;AACjE,UAAM,IAAI;AAAA,MACR,mEAAmEN,CAAU;AAAA,IAC/E;AAGE,MAAAO,GACAC;AAEA,MAAAH,EAAkB,YAAY,SAAS;AACzC,UAAMI,IAAWC,GAAS,IAAIP,EAAgB,aAAa,IAAI;AAK/D,IAAAI,IAHEJ,EAAgB,aAAa,YAC7BM,EAAS,WAAW,GAAG,GAAGN,EAAgB,aAAa,IAAI,IAC3D,IACwB;AAAA,EAAA;AAEf,IAAAI,IAAAJ,EAAgB,aAAa,YAAY;AAGlD,MAAAG,EAAgB,YAAY,SAAS;AACvC,UAAMG,IAAWC,GAAS,IAAIN,EAAc,aAAa,IAAI,GACvDO,IACJP,EAAc,aAAa,YAC3BK,EAAS;AAAA,MACPA,EAAS,SAAS;AAAA,MAClBA,EAAS,QAAQ;AAAA,MACjBL,EAAc,aAAa;AAAA,IAAA,IAE7B,GACIQ,IAAmBlvB,EAAG,IAAI,QAAQivB,CAAW,EAAE,UAAW;AAChE,IAAAH,IAASG,IAAcC,IAAmB;AAAA,EAAA;AAEjC,IAAAJ,IAAAJ,EAAc,aAAa,WAAW;AAOjD,EAAA1uB,EAAG,aAAa6e,EAAc,OAAO7e,EAAG,KAAK6uB,GAAUC,CAAM,CAAC;AAChE;AAEO,SAASK,GAAsBnvB,GAAiB;AAG/C,QAAAqV,IAAW1L,EAAY3J,CAAE;AAC3B,MAAA4X,IAAQ5X,EAAG,UAAU,OACrB6X,IAAM7X,EAAG,UAAU;AAMhB,SAAA6X,EAAI,gBAAgBA,EAAI,OAAO,WAAW,KAAKA,EAAI,QAAQ;AAChE,IAAAA,IAAM7X,EAAG,IAAI,QAAQ6X,EAAI,MAAM,CAAC;AAIlC,SAAOA,EAAI,iBAAiB,KAAKA,EAAI,QAAQ;AAC3C,IAAAA,IAAM7X,EAAG,IAAI,QAAQ6X,EAAI,MAAM,CAAC;AAIlC,SAAOD,EAAM,iBAAiB,KAAKA,EAAM,QAAQ;AAC/C,IAAAA,IAAQ5X,EAAG,IAAI,QAAQ4X,EAAM,MAAM,CAAC;AAI/B,SAAAA,EAAM,gBAAgBA,EAAM,OAAO,WAAW,KAAKA,EAAM,QAAQ;AACtE,IAAAA,IAAQ5X,EAAG,IAAI,QAAQ4X,EAAM,MAAM,CAAC;AAGtC,QAAMwX,IAAgB7iB;AAAA,IACpBvM,EAAG,IAAI,MAAM4X,EAAM,KAAKC,EAAI,KAAK,EAAI;AAAA,IACrCxC;AAAA,EACF;AAEO,SAAA;AAAA,IACL,OAAO;AAAA,MACL,UAAUuC,EAAM;AAAA,MAChB,QAAQC,EAAI;AAAA,IACd;AAAA,IACA,GAAGuX;AAAA,EACL;AACF;AClPO,SAASC,GAIdrvB,GAAoD;AACpD,QAAM,EAAE,SAAA4I,EAAA,IAAYc,GAA4B1J,CAAE,GAC5CqV,IAAW1L,EAAY3J,EAAG,GAAG,GAE7BqI,IAAcrI,EAAG,IAAI,QAAQ4I,EAAQ,SAAS,GAE9C0mB,IAAWjnB,EAAY,YAGvBknB,IAAWvvB,EAAG,IAAI,QAAQ4I,EAAQ,QAAQ,EAAE;AAGlD,MAAIwkB;AACA,SAAA/kB,EAAY,QAAQ,MAEtB+kB,IAAa/kB,EAAY,KAAK,GACzB+kB,EAAW,KAAK,UAAU,SAAS,MAEtCA,IAAa/kB,EAAY,KAAKA,EAAY,QAAQ,CAAC,KAIhD;AAAA,IACL,OAAOyD,EAAYlD,EAAQ,MAAMyM,CAAQ;AAAA,IACzC,WAAWia,MAAa,OAAO,SAAYxjB,EAAYwjB,GAAUja,CAAQ;AAAA,IACzE,WAAWka,MAAa,OAAO,SAAYzjB,EAAYyjB,GAAUla,CAAQ;AAAA,IACzE,aACE+X,MAAe,SAAY,SAAYthB,EAAYshB,GAAY/X,CAAQ;AAAA,EAC3E;AACF;AAEO,SAASma,GACdxvB,GACAyvB,GACAvZ,IAA6B,SAC7B;AACA,QAAMnV,IAAK,OAAO0uB,KAAgB,WAAWA,IAAcA,EAAY,IACjEpa,IAAW1L,EAAY3J,EAAG,GAAG,GAC7B8J,IAASC,GAAmBsL,CAAQ,GAEpC/L,IAAUqL,EAAY5T,GAAIf,EAAG,GAAG;AACtC,MAAI,CAACsJ;AACH,UAAM,IAAI,MAAM,iBAAiBvI,CAAE,YAAY;AAG3C,QAAA8hB,IAAOxZ,GAAaC,CAAO,GAE3B4f,IACJpf,EAAO,YAAY+Y,EAAK,aAAa,EAAG;AAE1C,MAAIA,EAAK,kBAAkB;AACzB,UAAM7e,IAAe6e,EAAK;AAC1B,QAAIqG,MAAgB,QAAQ;AAC1B,MAAAlpB,EAAG,aAAa4qB,GAAc,OAAO5qB,EAAG,KAAKgE,EAAa,SAAS,CAAC;AACpE;AAAA,IAAA;AAGF,QAAIklB,MAAgB;AAClB,MAAIhT,MAAc,UACblW,EAAA;AAAA,QACD6e,EAAc,OAAO7e,EAAG,KAAKgE,EAAa,YAAY,CAAC;AAAA,MACzD,IAEGhE,EAAA;AAAA,QACD6e,EAAc,OAAO7e,EAAG,KAAKgE,EAAa,WAAW,CAAC;AAAA,MACxD;AAAA,aAEOklB,MAAgB;AACzB,MAAIhT,MAAc,UAIblW,EAAA;AAAA,QACD6e,EAAc,OAAO7e,EAAG,KAAKgE,EAAa,YAAY,CAAC;AAAA,MACzD,IAEGhE,EAAA;AAAA,QACD6e,EAAc,OAAO7e,EAAG,KAAKgE,EAAa,WAAW,CAAC;AAAA,MACxD;AAAA;AAGI,YAAA,IAAIpB,EAAqBsmB,CAAW;AAAA,EAC5C,OACK;AACC,UAAAje,IACJiL,MAAc,UACV2M,EAAK,eAAe,KAAK,aACzBA,EAAK,eAAe,KAAK;AAE/B,IAAA2M,GAAsBxvB,GAAIiL,EAAM,MAAM,IAAIiL,CAAS;AAAA,EAAA;AAEvD;ACjHW,IAAAwZ;AAeX,eAAsBC,KAA4B;AAChD,MAAID;AACK,WAAAA;AAEH,QAAAE,IAAO,MAAM,QAAQ,IAAI;AAAA,IAC7B,OAAO,cAAc;AAAA,IACrB,OAAO,kBAAkB;AAAA,IACzB,OAAO,SAAS;AAAA,IAChB,OAAO,oBAAoB;AAAA,IAC3B,OAAO,eAAe;AAAA,IACtB,OAAO,YAAY;AAAA,IACnB,OAAO,kBAAkB;AAAA,IACzB,OAAO,cAAc;AAAA,IACrB,OAAO,eAAe;AAAA,IACtB,OAAO,eAAe;AAAA,EAAA,CACvB;AAEiB,SAAAF,KAAA;AAAA,IAChB,aAAaE,EAAK,CAAC;AAAA,IACnB,iBAAiBA,EAAK,CAAC;AAAA,IACvB,SAASA,EAAK,CAAC;AAAA,IACf,iBAAiBA,EAAK,CAAC;AAAA,IACvB,cAAcA,EAAK,CAAC;AAAA,IACpB,WAAWA,EAAK,CAAC;AAAA,IACjB,iBAAiBA,EAAK,CAAC;AAAA,IACvB,aAAaA,EAAK,CAAC;AAAA,IACnB,cAAcA,EAAK,CAAC;AAAA,IACpB,cAAcA,EAAK,CAAC;AAAA,EACtB,GAEOF;AACT;AC5CO,SAASG,KAAmB;AAC3B,QAAAC,IAAyB,CAACC,MAAqB;AAC/C,QAAAC,IAAmBD,EAAK,SAAS;AAErC,aAASlrB,IAAI,GAAGA,IAAImrB,GAAkBnrB,KAAK;AACnC,YAAAhE,IAAOkvB,EAAK,SAASlrB,CAAC;AAExB,UAAAhE,EAAK,SAAS,cAEhBivB,EAAuBjvB,CAAI,GAEtBA,EAAqB,YAAY;AAGhC,YAAAA,EAAK,SAAS,SAAS,GAAG;AAC5B,UAAAkvB,EAAK,SAAS,OAAOlrB,GAAG,GAAG,GAAGhE,EAAK,QAAQ;AAErC,gBAAAovB,IAAmBpvB,EAAK,SAAS,SAAS;AAC5B,UAAAmvB,KAAAC,GACfprB,KAAAorB;AAAA,QAAA;AAEA,UAAAF,EAAA,SAAS,OAAOlrB,GAAG,CAAC,GAEzBmrB,KACAnrB;AAAA,IAGN;AAAA,EAEJ;AAEO,SAAAirB;AACT;AC9BO,SAASI,KAAwB;AACtC,QAAMC,IAAOT;AAEb,MAAI,CAACS;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGI,QAAAC,IAAS,CAACL,MAAqB;;AACnC,QAAIA,EAAK,YAAY,YAAYA,EAAK,YAAYA,EAAK,SAAS;AAC9D,eAASlrB,IAAIkrB,EAAK,SAAS,SAAS,GAAGlrB,KAAK,GAAGA,KAAK;AAC5C,cAAAoG,IAAQ8kB,EAAK,SAASlrB,CAAC,GACvBwrB,IACJxrB,IAAI,IAAIkrB,EAAK,SAAS,SAASA,EAAK,SAASlrB,IAAI,CAAC,IAAI;AAGxD,QACEoG,EAAM,SAAS,aACfA,EAAM,YAAY,aAClBhL,IAAAgL,EAAM,eAAN,gBAAAhL,EAAkB,UAAS,eAC3BowB,KAAA,gBAAAA,EAAW,UAAS,aACpBA,EAAU,YAAY,OAItBA,EAAU,UAAU,QAEpBA,EAAU,SAAS;AAAA,UACjB;AAAA,UACA;AAAA,UACAF,EAAK,gBAAgB;AAAA,YACnB,SAAS,eAAe,GAAG;AAAA,UAAA;AAAA,QAE/B,KAEAC,EAAOnlB,CAAmB;AAAA,MAC5B;AAAA,EAGN;AAEO,SAAAmlB;AACT;ACjCO,SAASE,GAAoBC,GAAyB;AAC3D,QAAMJ,IAAOT;AAEb,MAAI,CAACS;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAeF,SAZuBA,EAAK,QACzB,UACA,IAAIA,EAAK,YAAY,SAAS,EAAE,UAAU,GAAM,CAAA,EAChD,IAAIN,EAAgB,EACpB,IAAIK,EAAqB,EACzB,IAAIC,EAAK,aAAa,OAAO,EAC7B,IAAIA,EAAK,UAAU,OAAO,EAC1B,IAAIA,EAAK,gBAAgB,SAAS;AAAA,IACjC,UAAU,EAAE,MAAM,CAACtvB,MAASA,EAAK,MAAM;AAAA,EAAA,CACxC,EACA,YAAY0vB,CAAe,EAER;AACxB;AAEA,eAAsBC,GAKpBlkB,GACAxC,GACAxF,GACAmU,GACiB;AACjB,QAAMkX,GAA0B;AAEhC,QAAMc,IADW9W,GAA2B7P,GAAQxF,CAAM,EAC5B,aAAagI,GAAQmM,CAAO;AAE1D,SAAO6X,GAAoBG,CAAY;AACzC;ACzDA,SAASC,GAAc7vB,GAAe;AACpC,SAAO,MAAM,UAAU,QAAQ,KAAKA,EAAK,cAAe,YAAYA,CAAI;AAC1E;AAEA,SAAS8vB,GAAiB9vB,GAAY;AAC7B,SAAAA,EAAK,aAAa,KAAK,CAAC,KAAK,KAAKA,EAAK,aAAa,EAAE;AAC/D;AAwBA,SAAS+vB,GAAwBzxB,GAAsB;AACrD,EAAAA,EAAQ,iBAAiB,kBAAkB,EAAE,QAAQ,CAACwC,MAAS;AACvD,UAAA7C,IAAQ4xB,GAAc/uB,CAAI,GAC1BkvB,IAAiBlvB,EAAK,eACtBmvB,IAAgB,MAAM,KAAKD,EAAe,UAAU,EAAE;AAAA,MAC1D/xB,IAAQ;AAAA,IACV;AACA,IAAA6C,EAAK,OAAO,GACEmvB,EAAA,QAAQ,CAACC,MAAY;AACjC,MAAAA,EAAQ,OAAO;AAAA,IAAA,CAChB,GAEcF,EAAA,sBAAsB,YAAYlvB,CAAI,GAErDmvB,EAAc,QAAQ,EAAE,QAAQ,CAACC,MAAY;AACvC,UAAAJ,GAAiBI,CAAO;AAC1B;AAEI,YAAAC,IAAmB,SAAS,cAAc,IAAI;AACpD,MAAAA,EAAiB,OAAOD,CAAO,GAC1BpvB,EAAA,sBAAsB,YAAYqvB,CAAgB;AAAA,IAAA,CACxD,GACGH,EAAe,WAAW,WAAW,KACvCA,EAAe,OAAO;AAAA,EACxB,CACD;AACH;AAwBA,SAASI,GAAa9xB,GAAsB;AAC1C,EAAAA,EAAQ,iBAAiB,kBAAkB,EAAE,QAAQ,CAACwC,MAAS;;AAC7D,UAAMuvB,IAAWvvB,EAAK,wBAChBkL,IAAiB,SAAS,cAAc,KAAK;AAE1C,IAAAqkB,EAAA,sBAAsB,YAAYrkB,CAAc,GACzDA,EAAe,OAAOqkB,CAAQ;AAExB,UAAAroB,IAAa,SAAS,cAAc,KAAK;AAI/C,SAHWA,EAAA,aAAa,kBAAkB,YAAY,GACtDgE,EAAe,OAAOhE,CAAU,KAG9B5I,IAAA4M,EAAe,uBAAf,gBAAA5M,EAAmC,cAAa,UAChDC,IAAA2M,EAAe,uBAAf,gBAAA3M,EAAmC,cAAa;AAErC,MAAA2I,EAAA,OAAOgE,EAAe,kBAAkB;AAAA,EACrD,CACD;AACH;AAIA,IAAIskB,KAAgC;AACpC,SAASC,KAAc;AACrB,SACED,OACCA,KAAe,SAAS,eAAe,mBAAmB,OAAO;AAEtE;AAEO,SAASE,GACdC,GACA;AACI,MAAA,OAAOA,KAAkB,UAAU;AACrC,UAAMnyB,IAAUiyB,KAAc,cAAc,KAAK;AACjD,IAAAjyB,EAAQ,YAAYmyB,GACJA,IAAAnyB;AAAA,EAAA;AAElB,SAAAyxB,GAAwBU,CAAa,GACrCL,GAAaK,CAAa,GACnBA;AACT;AChHsB,eAAAC,GAIpB1X,GAAcxE,GAAmD;AAC3D,QAAAmc,IAAWH,GAAgCxX,CAAI,GAO/CuT,IANSlL,GAAU,WAAW7M,CAAQ,EAMlB,MAAMmc,GAAU;AAAA,IACxC,SAASnc,EAAS,MAAM,WAAc,OAAO;AAAA,EAAA,CAC9C,GAEK/I,IAAiC,CAAC;AAExC,WAAS,IAAI,GAAG,IAAI8gB,EAAW,YAAY;AACzC,IAAA9gB,EAAO,KAAKR,EAAYshB,EAAW,MAAM,CAAC,GAAG/X,CAAQ,CAAC;AAGjD,SAAA/I;AACT;ACpBA,SAASmlB,GAAKhoB,GAAY5I,GAAW;AACnC,QAAMqD,IAAQrD,EAAK,QAAQA,EAAK,QAAQ,IAElC6wB,IAAkB,CAAC;AAEzB,EAAI7wB,EAAK,SAEI6wB,EAAA,eAAe,IAAI7wB,EAAK;AAKrC,MAAI8wB,IAAc;AAAA,IAChB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAAD;AAAA,IACA,UAAU,CAAC,EAAE,MAAM,QAAQ,OAAAxtB,EAAO,CAAA;AAAA,EACpC;AAEA,SAAIrD,EAAK,SACP8wB,EAAO,OAAO,EAAE,MAAM9wB,EAAK,KAAK,IAG5B4I,EAAA,MAAM5I,GAAM8wB,CAAM,GACfA,IAAAloB,EAAM,UAAU5I,GAAM8wB,CAAM,GAG5BA,IAAA;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY,CAAC;AAAA,IACb,UAAU,CAACA,CAAM;AAAA,EACnB,GACMloB,EAAA,MAAM5I,GAAM8wB,CAAM,GACjBA;AACT;AAEA,eAAsBC,GAAeC,GAAmC;AAChE,QAAA1B,IAAO,MAAMR,GAA0B;AAe7C,SAbmBQ,EAAK,QACrB,UACA,IAAIA,EAAK,YAAY,OAAO,EAC5B,IAAIA,EAAK,UAAU,OAAO,EAC1B,IAAIA,EAAK,aAAa,SAAS;AAAA,IAC9B,UAAU;AAAA,MACR,GAAIA,EAAK,aAAa;AAAA,MACtBsB,MAAAA;AAAAA,IAAA;AAAA,EACF,CACD,EACA,IAAItB,EAAK,gBAAgB,OAAO,EAChC,YAAY0B,CAAQ,EAEL;AACpB;AAEsB,eAAAC,GAIpBD,GAAkBxc,GAAmD;AAC/D,QAAA0c,IAAa,MAAMH,GAAeC,CAAQ;AAEzC,SAAAN,GAAaQ,GAAY1c,CAAQ;AAC1C;AC7EO,MAAM2c,KAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;ACIA,SAASC,GACPC,GACAC,GACA;AACI,MAAA,CAACD,EAAe,WAAW,GAAG,KAAK,CAACC,EAAe,WAAW,GAAG;AAC7D,UAAA,IAAI,MAAM,qDAAqD;AAGvE,SAAOD,MAAmBC;AAC5B;AAEA,SAASC,GAAoBC,GAAmBC,GAAmB;AAC3D,QAAAC,IAASF,EAAU,MAAM,GAAG,GAC5BG,IAASF,EAAU,MAAM,GAAG;AAE9B,MAAAC,EAAO,WAAW;AACpB,UAAM,IAAI,MAAM,cAAcF,CAAS,4BAA4B;AAEjE,MAAAG,EAAO,WAAW;AACpB,UAAM,IAAI,MAAM,cAAcF,CAAS,4BAA4B;AAGrE,SAAIC,EAAO,CAAC,MAAM,OAAOC,EAAO,CAAC,MAAM,MAC9BD,EAAO,CAAC,MAAMC,EAAO,CAAC,KAE3BD,EAAO,CAAC,MAAM,OAAOC,EAAO,CAAC,MAAM,OAIhCD,EAAO,CAAC,MAAMC,EAAO,CAAC,MAAKD,EAAO,CAAC,MAAMC,EAAO,CAAC;AAC1D;AAEA,SAASrJ,GAKP7kB,GACA2R,GACAoT,GACA;AACI,MAAAoJ;AAGF,SAAA,MAAM,QAAQxc,EAAe,OAAO,KACpCA,EAAe,QAAQ,WAAW,IAElCwc,IAAkBnuB,EAAO,YAAY2R,GAAgBoT,CAAQ,EAAE,KAE/DoJ,IAAkBnuB,EAAO;AAAA,IACvB,CAAC+kB,CAAQ;AAAA,IACTpT;AAAA,IACA;AAAA,EAAA,EACA,CAAC,EAAE,IAGAwc;AACT;AAEsB,eAAAC,GAIpBnxB,GAAmC+C,GAAwC;;AACvE,MAAA,CAACA,EAAO,YAAY;AAEd,YAAA;AAAA,MACN;AAAA,IACF;AACA;AAAA,EAAA;AAGF,QAAMquB,IACJ,kBAAkBpxB,IAAQA,EAAM,eAAeA,EAAM;AACvD,MAAIoxB,MAAiB;AACnB;AAGF,MAAIC,IAAoD;AACxD,aAAWC,KAAYb;AACrB,QAAIW,EAAa,MAAM,SAASE,CAAQ,GAAG;AAChC,MAAAD,IAAAC;AACT;AAAA,IAAA;AAGJ,MAAID,MAAW;AACb;AAGF,QAAMj0B,IAAQg0B,EAAa;AAC3B,MAAI,CAACh0B;AACH;AAGF,EAAA4C,EAAM,eAAe;AAErB,QAAMuxB,IAAmB,OAAO,OAAOxuB,EAAO,OAAO,WAAW,EAAE;AAAA,IAChE,CAACoD,MAAgBA,EAAY;AAAA,EAC/B;AAEA,WAAS7C,IAAI,GAAGA,IAAIlG,EAAM,QAAQkG,KAAK;AAErC,QAAIkuB,IAAgB;AACpB,eAAWnT,KAAmBkT;AAC5B,iBAAWD,KAAYjT,EAAgB,mBAAmB,CAAA,GAAI;AACtD,cAAAoT,IAAkBH,EAAS,WAAW,GAAG,GACzCrX,IAAO7c,EAAMkG,CAAC,EAAE,UAAU;AAEhC,YAAI2W,MAEC,CAACwX,KACAxX,EAAK,QACL4W,GAAoBzzB,EAAMkG,CAAC,EAAE,MAAMguB,CAAQ,KAC5CG,KACCf;AAAA,UACE,MAAMzW,EAAK,KAAK,MAAM,GAAG,EAAE,IAAI;AAAA,UAC/BqX;AAAA,QAAA,IAEJ;AACA,UAAAE,IAAgBnT,EAAgB;AAChC;AAAA,QAAA;AAAA,MAEJ;AAIJ,UAAMpE,IAAO7c,EAAMkG,CAAC,EAAE,UAAU;AAChC,QAAI2W,GAAM;AACR,YAAMyX,IAAY;AAAA,QAChB,MAAMF;AAAA,QACN,OAAO;AAAA,UACL,MAAMvX,EAAK;AAAA,QAAA;AAAA,MAEf;AAEA,UAAIiX;AAEA,UAAAlxB,EAAM,SAAS,SAAS;AACpB,cAAA6nB,IAAe9kB,EAAO,sBAAA,EAAwB;AAClC,QAAAmuB,IAAAtJ,GAAoB7kB,GAAQ8kB,GAAc6J,CAAS;AAAA,MAAA,WAC5D1xB,EAAM,SAAS,QAAQ;AAChC,cAAM2xB,IAAS;AAAA,UACb,MAAO3xB,EAAoB;AAAA,UAC3B,KAAMA,EAAoB;AAAA,QAC5B,GAEMN,KAAMhB,IAAAqE,EAAO,oBAAP,gBAAArE,EAAwB,YAAYizB;AAChD,YAAI,CAACjyB;AACH;AAGgB,QAAAwxB,IAAAnuB,EAAO,SAAS,CAACtE,MAAO;AACxC,gBAAMsJ,IAAUtB,EAAmBhI,EAAG,KAAKiB,EAAI,GAAG;AAC3C,iBAAAkoB;AAAA,YACL7kB;AAAA,YACAA,EAAO,SAASgF,EAAQ,KAAK,MAAM,EAAE;AAAA,YACrC2pB;AAAA,UACF;AAAA,QAAA,CACD;AAAA,MAAA;AAED;AAGF,YAAME,IAAa,MAAM7uB,EAAO,WAAWkX,GAAMiX,CAAe,GAE1DW,IACJ,OAAOD,KAAe,WACjB;AAAA,QACC,OAAO;AAAA,UACL,KAAKA;AAAA,QAAA;AAAA,MACP,IAEF,EAAE,GAAGA,EAAW;AAEf,MAAA7uB,EAAA,YAAYmuB,GAAiBW,CAAgB;AAAA,IAAA;AAAA,EACtD;AAEJ;AChLO,MAAMC,KAA0B,CAKrC/uB,MAEAtF,EAAU,OAA8D;AAAA,EACtE,MAAM;AAAA,EACN,wBAAwB;AACf,WAAA;AAAA,MACL,IAAIQ,EAAO;AAAA,QACT,OAAO;AAAA,UACL,iBAAiB;AAAA,YACf,KAAK8zB,GAAO/xB,GAAO;AACb,kBAAA,CAAC+C,EAAO;AACV;AAGF,kBAAIsuB,IAAoD;AACxD,yBAAWC,KAAYb;AACrB,oBAAIzwB,EAAM,aAAc,MAAM,SAASsxB,CAAQ,GAAG;AACvC,kBAAAD,IAAAC;AACT;AAAA,gBAAA;AAGJ,qBAAID,MAAW,OACN,KAGLA,MAAW,WACbF,GAAoBnxB,GAAO+C,CAAM,GAC1B,MAGF;AAAA,YAAA;AAAA,UACT;AAAA,QACF;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC,GCrDGivB,KAAK,2DAGLC,KAAO,WAAA,sEAAA,GAGP9f,KAAO,4CAGP+d,KAAO,WAAA,gDAAA,GAGPgC,KAAK,4CAGLC,KAAK,oDAGLC,KAAK,2BAGLC,KACJ,oGAGIlK,KAAQ,mEAGRmK,KACJ,+DAGIC,KAAc,sBAGdC,KAAe,mCAGfC,KAAW,sBAOJC,KAAa,CAACC,MACzBX,GAAG,KAAKW,CAAG,KACXV,GAAK,KAAKU,CAAG,KACbxgB,GAAK,KAAKwgB,CAAG,KACbzC,GAAK,KAAKyC,CAAG,KACbT,GAAG,KAAKS,CAAG,KACXR,GAAG,KAAKQ,CAAG,KACXP,GAAG,KAAKO,CAAG,KACXN,GAAO,KAAKM,CAAG,KACfxK,GAAM,KAAKwK,CAAG,KACdL,GAAW,KAAKK,CAAG,KACnBJ,GAAY,KAAKI,CAAG,KACpBH,GAAa,KAAKG,CAAG,KACrBF,GAAS,KAAKE,CAAG;ACzDG,eAAAC,GACpB5yB,GACAF,GACA;AACM,QAAA,EAAE,QAAAyI,MAAWzI,EAAK;AAEpB,MAAA,CAACE,EAAM;AACF,WAAA;AAGT,QAAMiS,IAAOjS,EAAM,cAAe,QAAQ,YAAY;AAEtD,MAAI,CAACiS;AACI,WAAA;AAGL,MAAA,CAAC1J,EAAO,MAAM;AAChB,WAAAzI,EAAK,UAAUmS,CAAI,GACZ;AAGT,QAAM4gB,IAAS7yB,EAAM,cAAe,QAAQ,oBAAoB,GAC1D8yB,IAAaD,IAAS,KAAK,MAAMA,CAAM,IAAI,QAC3C9W,IAAW+W,KAAA,gBAAAA,EAAY;AAE7B,SAAK/W,KAMAjc,EAAA;AAAA,IACH,8BAA8Bic,CAAQ,KAAK9J,EAAK;AAAA,MAC9C;AAAA,MACA;AAAA;AAAA,IAAA,CACD;AAAA,EACH,GAEO,MAZE;AAaX;ACxBA,SAAS8gB,GAAoB;AAAA,EAC3B,OAAA/yB;AAAA,EACA,QAAA+C;AAAA,EACA,4BAAAiwB;AAAA,EACA,qBAAAC;AACF,GAKG;;AASD,MANsBlwB,EAAO;AAAA,IAC3B,CAACtE,MACCA,EAAG,UAAU,MAAM,OAAO,KAAK,KAAK,QACpCA,EAAG,UAAU,IAAI,OAAO,KAAK,KAAK;AAAA,EACtC,GAEmB;AACjB,UAAM+qB,KAAO9qB,IAAAsB,EAAM,kBAAN,gBAAAtB,EAAqB,QAAQ;AAE1C,QAAI8qB;AACF,aAAAzmB,EAAO,UAAUymB,CAAI,GAEd;AAAA,EACT;AAGE,MAAA6H;AACJ,aAAWC,KAAYb;AACrB,QAAIzwB,EAAM,cAAe,MAAM,SAASsxB,CAAQ,GAAG;AACxC,MAAAD,IAAAC;AACT;AAAA,IAAA;AAIJ,MAAI,CAACD;AACI,WAAA;AAGT,MAAIA,MAAW;AACK,WAAAuB,GAAA5yB,GAAO+C,EAAO,eAAgB,GACzC;AAGT,MAAIsuB,MAAW;AACb,WAAAF,GAAoBnxB,GAAO+C,CAAM,GAC1B;AAGT,QAAMymB,IAAOxpB,EAAM,cAAe,QAAQqxB,CAAM;AAEhD,MAAIA,MAAW;AAEN,WAAAtuB,EAAA,UAAUymB,GAAM,EAAI,GACpB;AAGT,MAAI6H,MAAW;AACb,WAAAtuB,EAAO,cAAcymB,CAAI,GAClB;AAGT,MAAIwJ,GAA4B;AAE9B,UAAME,IAAYlzB,EAAM,cAAe,QAAQ,YAAY;AAEvD,QAAA0yB,GAAWQ,CAAS;AACtB,aAAAnwB,EAAO,cAAcmwB,CAAS,GACvB;AAAA,EACT;AAGF,SAAI7B,MAAW,eACbtuB,EAAO,UAAUymB,CAAI,GACd,MAGLyJ,KACFlwB,EAAO,cAAcymB,CAAI,GAClB,OAGTzmB,EAAO,UAAUymB,CAAI,GACd;AACT;AAEO,MAAM2J,KAAoC,CAK/CpwB,GACAqwB,MAKA31B,EAAU,OAAO;AAAA,EACf,MAAM;AAAA,EACN,wBAAwB;AACf,WAAA;AAAA,MACL,IAAIQ,EAAO;AAAA,QACT,OAAO;AAAA,UACL,iBAAiB;AAAA,YACf,MAAM8zB,GAAO/xB,GAAO;AAGd,kBAFJA,EAAM,eAAe,GAEjB,EAAC+C,EAAO;AAIZ,uBAAOqwB,EAAa;AAAA,kBAClB,OAAApzB;AAAA,kBACA,QAAA+C;AAAA,kBACA,qBAAqB,CAAC;AAAA,oBACpB,4BAAAiwB,IAA6B;AAAA,oBAC7B,qBAAAC,IAAsB;AAAA,kBACxB,IAAI,OACKF,GAAoB;AAAA,oBACzB,OAAA/yB;AAAA,oBACA,QAAA+C;AAAA,oBACA,4BAAAiwB;AAAA,oBACA,qBAAAC;AAAA,kBAAA,CACD;AAAA,gBACH,CACD;AAAA,YAAA;AAAA,UACH;AAAA,QACF;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC;AC1II,SAASI,GAIdlzB,GAAoB;AAGpB,QAAM4K,IAAqC,CAAC;AACnC,SAAA5K,EAAA,YAAY,CAACb,MAAS;;AACvB,UAAAwU,IAAW1L,EAAY9I,CAAI;AAC7B,WAAAA,EAAK,KAAK,SAAS,sBACjBZ,IAAAY,EAAK,eAAL,gBAAAZ,EAAiB,KAAK,UAAS,eAoB1B,KAIPY,EAAK,KAAK,SAAS,gBAAgBA,EAAK,eAAe,MAEpDX,IAAAW,EAAA,eAAA,QAAAX,EAAY,QAAQ,CAAC+K,MAAU;AAClC,MAAAqB,EAAO,KAAKR,EAAYb,GAAOoK,CAAQ,CAAC;AAAA,IAAA,IAEnC,MAGLxU,EAAK,KAAK,UAAU,SAAS,KAC/ByL,EAAO,KAAKR,EAAYjL,GAAMwU,CAAQ,CAAC,GAEhC,MAEF;AAAA,EAAA,CACR,GACM/I;AACT;AC5CA,SAASuoB,GAKPxzB,GACAyzB,GACAxwB,GACA;;AACA,MAAIywB,IAAuB;AACrB,QAAAC,IAAgB3zB,EAAK,MAAM,qBAAqBynB;AAEtD,MAAI,CAACkM,GAAe;AAIZ,UAAAC,IAAyB5zB,EAAK,MAAM,IAAI;AAAA,MAC5CA,EAAK,MAAM,UAAU;AAAA,MACrBA,EAAK,MAAM,UAAU;AAAA,MACrB;AAAA,IAAA,EACA,SAEI+K,IAAW,CAAC;AAClB,aAASvH,IAAI,GAAGA,IAAIowB,EAAuB,YAAYpwB;AACrD,MAAAuH,EAAS,KAAK6oB,EAAuB,MAAMpwB,CAAC,CAAC;AAG/C,IAAAkwB,IACE3oB,EAAS;AAAA,MACP,CAACnB,MACCA,EAAM,KAAK,UAAU,SAAS,KAC9BA,EAAM,KAAK,SAAS,gBACpBA,EAAM,KAAK,KAAK,UAAU;AAAA,IAAA,MACxB,QACJ8pB,MACiBD,IAAAG;AAAA,EACrB;AAGE,MAAAxE;AAEJ,QAAMyE,IAAuBvb;AAAA,IAC3BtY,EAAK,MAAM;AAAA,IACXiD;AAAA,EACF;AAEA,MAAI0wB,GAAe;AACjB,MAAI/0B,IAAA60B,EAAiB,eAAjB,gBAAA70B,EAA6B,KAAK,UAAS,YAG7C60B,IAAmBA,EAAiB,WAAW;AAKjD,UAAM5b,IAAK9O;AAAA,MACT0qB;AAAA,MACAxwB,EAAO,OAAO;AAAA,MACdA,EAAO,OAAO;AAAA,IAChB;AAGA,IAAAmsB,IAAe,UAAUyE,EAAqB;AAAA,MAC5Chc;AAAA,MACA,CAAA;AAAA,IACD,CAAA;AAAA,aACQ6b,GAAsB;AAG/B,UAAM7b,IAAKhO;AAAA,MACT4pB;AAAA,MACAxwB,EAAO,OAAO;AAAA,MACdA,EAAO,OAAO;AAAA,IAChB;AACA,IAAAmsB,IAAeyE,EAAqB,oBAAoBhc,GAAI,CAAA,CAAE;AAAA,EAAA,OACzD;AACC,UAAA5M,IAASsoB,GAAiBE,CAAgB;AAChD,IAAArE,IAAeyE,EAAqB,aAAa5oB,GAAQ,CAAA,CAAE;AAAA,EAAA;AAEtD,SAAAmkB;AACT;AAEgB,SAAA0E,GAKd9zB,GACAiD,GAKA;AAME,EAAA,UAAUjD,EAAK,MAAM,aACpBA,EAAK,MAAM,UAAU,KAAc,KAAK,KAAK,UAAU,kBAEjDiD,EAAA;AAAA,IAAS,CAACtE,MACfA,EAAG;AAAA,MACD,IAAI4qB,GAAc5qB,EAAG,IAAI,QAAQqB,EAAK,MAAM,UAAU,OAAO,CAAC,CAAC;AAAA,IAAA;AAAA,EAEnE;AAIF,QAAM+zB,IAAwB/zB,EAAK;AAAA,IACjCA,EAAK,MAAM,UAAU,QAAQ;AAAA,IAC7B,IAAI,WAEAyzB,IAAmBzzB,EAAK,MAAM,UAAU,QAAU,EAAA,SAElDovB,IAAeoE;AAAA,IACnBxzB;AAAA,IACAyzB;AAAA,IACAxwB;AAAA,EACF,GAEMutB,IAAWvB,GAAoBG,CAAY;AAE1C,SAAA,EAAE,eAAA2E,GAAe,cAAA3E,GAAc,UAAAoB,EAAS;AACjD;AAEA,MAAMwD,KAAqC,MAAM;AAGzC,QAAAvW,IAAY,OAAO,aAAa;AAClC,MAAA,CAACA,KAAaA,EAAU;AACnB,WAAA;AAQT,MAAIje,IAAOie,EAAU;AACrB,SAAOje,KAAM;AACX,QACEA,aAAgB,eAChBA,EAAK,aAAa,iBAAiB,MAAM;AAElC,aAAA;AAGT,IAAAA,IAAOA,EAAK;AAAA,EAAA;AAGP,SAAA;AACT,GAEMy0B,KAAkB,CAKtBhxB,GACAjD,GACAE,MACG;AAEH,EAAAA,EAAM,eAAe,GACrBA,EAAM,cAAe,UAAU;AAE/B,QAAM,EAAE,eAAA6zB,GAAe,cAAA3E,GAAc,UAAAoB,EAAa,IAAAsD;AAAA,IAChD9zB;AAAA,IACAiD;AAAA,EACF;AAIM,EAAA/C,EAAA,cAAe,QAAQ,kBAAkB6zB,CAAa,GACtD7zB,EAAA,cAAe,QAAQ,aAAakvB,CAAY,GAChDlvB,EAAA,cAAe,QAAQ,cAAcswB,CAAQ;AACrD,GAEa0D,KAAiC,CAK5CjxB,MAEAtF,EAAU,OAA8D;AAAA,EACtE,MAAM;AAAA,EACN,wBAAwB;AACf,WAAA;AAAA,MACL,IAAIQ,EAAO;AAAA,QACT,OAAO;AAAA,UACL,iBAAiB;AAAA,YACf,KAAK6B,GAAME,GAAO;AAChB,qBAAI8zB,QAIYC,GAAAhxB,GAAQjD,GAAME,CAAK,GAE5B;AAAA,YACT;AAAA,YACA,IAAIF,GAAME,GAAO;AACf,qBAAI8zB,SAIYC,GAAAhxB,GAAQjD,GAAME,CAAK,GAC/BF,EAAK,YACPA,EAAK,SAASA,EAAK,MAAM,GAAG,iBAAiB,IAGxC;AAAA,YACT;AAAA;AAAA;AAAA;AAAA,YAIA,UAAUA,GAAME,GAAO;AAOrB,kBALI,EAAE,UAAUF,EAAK,MAAM,cAMxBA,EAAK,MAAM,UAAU,KAAc,KAAK,KAAK,UAC9C;AAEA;AAIK,cAAAiD,EAAA;AAAA,gBAAS,CAACtE,MACfA,EAAG;AAAA,kBACD,IAAI4qB;AAAA,oBACF5qB,EAAG,IAAI,QAAQqB,EAAK,MAAM,UAAU,OAAO,CAAC;AAAA,kBAAA;AAAA,gBAC9C;AAAA,cAEJ,GAGAE,EAAM,eAAe,GACrBA,EAAM,aAAc,UAAU;AAE9B,oBAAM,EAAE,eAAA6zB,GAAe,cAAA3E,GAAc,UAAAoB,EACnC,IAAAsD,GAAuB9zB,GAAMiD,CAAM;AAI/B,qBAAA/C,EAAA,aAAc,QAAQ,kBAAkB6zB,CAAa,GACrD7zB,EAAA,aAAc,QAAQ,aAAakvB,CAAY,GAC/ClvB,EAAA,aAAc,QAAQ,cAAcswB,CAAQ,GAG3C;AAAA,YAAA;AAAA,UACT;AAAA,QACF;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC,GCvRU2D,KAA2Bx2B,EAAU,OAAO;AAAA,EACvD,MAAM;AAAA,EAEN,sBAAsB;AACb,WAAA;AAAA,MACL;AAAA,QACE,OAAO,CAAC,kBAAkB,aAAa,aAAa;AAAA,QACpD,YAAY;AAAA,UACV,iBAAiB;AAAA,YACf,SAAS+F,EAAa,gBAAgB;AAAA,YACtC,WAAW,CAAC5F,MACVA,EAAQ,aAAa,uBAAuB,IACxCA,EAAQ,aAAa,uBAAuB,IAC5C4F,EAAa,gBAAgB;AAAA,YACnC,YAAY,CAAC3F,MAETA,EAAW,oBACX2F,EAAa,gBAAgB,UAEtB,CAAC,IAEH;AAAA,cACL,yBAAyB3F,EAAW;AAAA,YACtC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC;ACrBM,MAAMq2B,GAA4C;AAAA,EAAlD;AAEG;AAAA,IAAA1L,EAAA,mBAA2C,CAAC;AAAA;AAAA,EAE7C,GACLxoB,GACAm0B,GACA;AACA,WAAK,KAAK,UAAUn0B,CAAK,MAClB,KAAA,UAAUA,CAAK,IAAI,CAAC,IAG3B,KAAK,UAAUA,CAAK,EAAE,KAAKm0B,CAAE,GAEtB,MAAM,KAAK,IAAIn0B,GAAOm0B,CAAE;AAAA,EAAA;AAAA,EAGvB,KACRn0B,MACGo0B,GACH;AACM,UAAAC,IAAY,KAAK,UAAUr0B,CAAK;AAEtC,IAAIq0B,KACFA,EAAU,QAAQ,CAACC,MAAaA,EAAS,MAAM,MAAMF,CAAI,CAAC;AAAA,EAC5D;AAAA,EAGK,IACLp0B,GACAm0B,GACA;AACM,UAAAE,IAAY,KAAK,UAAUr0B,CAAK;AAEtC,IAAIq0B,MACEF,IACG,KAAA,UAAUn0B,CAAK,IAAIq0B,EAAU,OAAO,CAACC,MAAaA,MAAaH,CAAE,IAE/D,OAAA,KAAK,UAAUn0B,CAAK;AAAA,EAE/B;AAAA,EAGQ,qBAA2B;AACnC,SAAK,YAAY,CAAC;AAAA,EAAA;AAEtB;ACvDO,MAAeu0B,UAEZL,GAAqB;AAAA;AAAA,EAe7B,eAAeM,GAAc;AACrB,UAAA;AAPQ,IAAAhM,EAAA,iBAAoB,CAAC;AAAA,EAO7B;AAAA,EAfR,OAAc,MAAc;AACpB,UAAA,IAAI,MAAM,qDAAqD;AAAA,EAAA;AAAA,EAG7D,qBAAqBiM,GAAgB;AACxC,SAAA,QAAQ,KAAKA,CAAM;AAAA,EAAA;AAAA,EAI1B,IAAW,WAA+B;AAAA,EACjC;AASX;ACdO,MAAMC,KAAN,MAAMA,WAAqBH,EAAmB;AAAA,EAUnD,YACUI,GAOR;AACM,UAAA;AAdA,IAAAnM,EAAA;AACA,IAAAA,EAAA;AA+DA,IAAAA,EAAA,sBAAe,CAACoM,GAAyBC,MAAqB;AACpE,UAAIC,IAAa,KAAK,uBAAuB,IAAID,CAAQ;AAEzD,UAAI,CAACC,GAAY;AACf,cAAMC,KACJ,KAAK,cAAc,gBAAgBL,GAAa,qBAChDE,CAAI;AAEF,QAAA,KAAK,cAAc,qBAAqB,aAC5BG,EAAA,iBAAiB,cAAc,MAAM;AACjD,gBAAMC,IAAS,KAAK,uBAAuB,IAAIH,CAAQ;AAChD,UAAAG,EAAA,QAAQ,aAAa,eAAe,EAAE,GAEzCA,EAAO,gBACT,aAAaA,EAAO,WAAW,GAC1B,KAAA,uBAAuB,IAAIH,GAAU;AAAA,YACxC,SAASG,EAAO;AAAA,YAChB,aAAa;AAAA,UAAA,CACd;AAAA,QACH,CACD,GAEaD,EAAA,iBAAiB,cAAc,MAAM;AACjD,gBAAMC,IAAS,KAAK,uBAAuB,IAAIH,CAAQ;AAElD,eAAA,uBAAuB,IAAIA,GAAU;AAAA,YACxC,SAASG,EAAO;AAAA,YAChB,aAAa,WAAW,MAAM;AACrB,cAAAA,EAAA,QAAQ,gBAAgB,aAAa;AAAA,YAAA,GAC3C,GAAI;AAAA,UAAA,CACR;AAAA,QAAA,CACF,IAGUF,IAAA;AAAA,UACX,SAASC;AAAA,UACT,aAAa;AAAA,QACf,GAEK,KAAA,uBAAuB,IAAIF,GAAUC,CAAU;AAAA,MAAA;AAGtD,aAAOA,EAAW;AAAA,IACpB;AAEO,IAAAtM,EAAA,oBAAa,CAACoM,MAIf;AACJ,WAAK,SAAS,UAAU,mBAAmB,QAAQA,CAAI;AAAA,IACzD;AA7GU,SAAA,gBAAAD,GASR,KAAK,WAAWA,EAAc,UACzB,KAAA,6CAA6B,IAAI,GAEtC,KAAK,SAAS,UAAU,mBAAmB,QAAQA,EAAc,IAAI,GAEjEA,EAAc,qBAAqB,YACrC,KAAK,SAAS,UAAU;AAAA,MACtB;AAAA,MACA,CAAC;AAAA,QACC,SAAAM;AAAA,MAAA,MAKI;AACJ,mBAAWJ,KAAYI,GAAS;AAC9B,gBAAMD,IAAS,KAAK,uBAAuB,IAAIH,CAAQ;AAEvD,UAAIG,MACKA,EAAA,QAAQ,aAAa,eAAe,EAAE,GAEzCA,EAAO,eACT,aAAaA,EAAO,WAAW,GAG5B,KAAA,uBAAuB,IAAIH,GAAU;AAAA,YACxC,SAASG,EAAO;AAAA,YAChB,aAAa,WAAW,MAAM;AACrB,cAAAA,EAAA,QAAQ,gBAAgB,aAAa;AAAA,YAAA,GAC3C,GAAI;AAAA,UAAA,CACR;AAAA,QACH;AAAA,MACF;AAAA,IAEJ,GAGG,KAAA;AAAA,MACHE,GAAc,KAAK,SAAS,WAAW;AAAA,QACrC,kBAAkBC;AAAA,QAClB,eAAe,KAAK;AAAA,MACrB,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA7DF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA+DT,IAAW,WAAW;AACb,WAAA;AAAA,EAAA;AAgFX;AAxBE3M,EA1HWkM,IA0HG,uBAAsB,CAACE,MAA4B;AACzD,QAAAG,IAAgB,SAAS,cAAc,MAAM;AAErC,EAAAA,EAAA,UAAU,IAAI,+BAA+B;AAErD,QAAAK,IAAe,SAAS,cAAc,MAAM;AACrC,EAAAA,EAAA,aAAa,qBAAqB,OAAO,GACzCA,EAAA,UAAU,IAAI,gCAAgC,GAC3DA,EAAa,aAAa,SAAS,qBAAqBR,EAAK,KAAK,EAAE;AAE9D,QAAAS,IAAe,SAAS,cAAc,MAAM;AAErC,SAAAA,EAAA,UAAU,IAAI,gCAAgC,GAC3DA,EAAa,aAAa,SAAS,qBAAqBT,EAAK,KAAK,EAAE,GACpES,EAAa,aAAa,SAAS,eAAeT,EAAK,IAAI,GAAG,IAAI,GAErDQ,EAAA,aAAaC,GAAc,IAAI,GAE5CN,EAAc,aAAa,SAAS,eAAe,GAAQ,GAAG,IAAI,GACpDA,EAAA,aAAaK,GAAc,IAAI,GAC7CL,EAAc,aAAa,SAAS,eAAe,GAAQ,GAAG,IAAI,GAE3DA;AACT;AAjJK,IAAMO,KAANZ;ACPA,MAAMa,WAAmBhB,EAAmB;AAAA,EACjD,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,YAAYp0B,GAAyB;AAC7B,UAAA,GACD,KAAA,qBAAqBq1B,GAAYr1B,CAAQ,CAAC;AAAA,EAAA;AAAA,EAGjD,IAAW,WAAW;AACb,WAAA;AAAA,EAAA;AAEX;ACdO,MAAMs1B,WAAmBlB,EAAmB;AAAA,EACjD,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,cAAc;AACN,UAAA,GACD,KAAA,qBAAqBmB,IAAa;AAAA,EAAA;AAAA,EAGzC,IAAW,WAAW;AACb,WAAA;AAAA,EAAA;AAEX;ACda,MAAAC,KAAcvoB,GAAK,OAAO;AAAA,EACrC,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa;AAAA,EAEb,gBAAgB;AAEP,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAKL,QAAQ;AAAA,QACN,WAAW,CAACxP,MAAY,CAAC,CAACA,EAAQ,aAAa,aAAa;AAAA,QAC5D,YAAY,CAACC,MACHA,EAAmC,SACvC;AAAA,UACE,eAAe;AAAA,QAAA,IAEjB,CAAC;AAAA,QAEP,SAAS;AAAA,MACX;AAAA,MACA,UAAU;AAAA,QACR,WAAW,CAACD,MAAYA,EAAQ,aAAa,mBAAmB;AAAA,QAChE,YAAY,CAACC,OACJ;AAAA,UACL,qBAAsBA,EAAoC;AAAA,QAC5D;AAAA,QAEF,SAAS;AAAA,MAAA;AAAA,IAEb;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAwI,KAA2D;AAC/D,WAAA;AAAA,MACL;AAAA,MACA4e,GAAgB5e,GAAgB;AAAA,QAC9B,OAAO;AAAA,MACR,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,uBAAuB;AAAA,EACxC;AAAA,EAEA,iBAAiB6d,GAAW;AACtB,WAAAA,EAAU,SAAS,YACd;AAAA,MACL,iBAAiB;AAAA,IACnB,IAEK,CAAC;AAAA,EAAA;AAEZ,CAAC;AClDM,MAAM0R,WAAkC1B,GAAkB;AAAA,EAMxD,YACY2B,GACjB;AACM,UAAA;AARA,IAAArN,EAAA,uCAAgC,IAAI;AAGpC;AAAA,IAAAA,EAAA,0CAAmB,IAAY;AAGpB,SAAA,eAAAqN;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAQnB,MAAa,UAAUC,GAAmB;AACxC,UAAMC,IAAeD,EAAQ;AAAA,MAC3B,CAACt2B,MAAO,CAAC,KAAK,UAAU,IAAIA,CAAE,KAAK,CAAC,KAAK,aAAa,IAAIA,CAAE;AAAA,IAC9D;AAEI,QAAAu2B,EAAa,WAAW,GAI5B;AAAA,iBAAWv2B,KAAMu2B;AACV,aAAA,aAAa,IAAIv2B,CAAE;AAGtB,UAAA;AACF,cAAMw2B,IAAQ,MAAM,KAAK,aAAaD,CAAY;AAClD,mBAAWnB,KAAQoB;AACjB,eAAK,UAAU,IAAIpB,EAAK,IAAIA,CAAI;AAE7B,aAAA,KAAK,UAAU,KAAK,SAAS;AAAA,MAAA,UAClC;AACA,mBAAWp1B,KAAMu2B;AAIV,eAAA,aAAa,OAAOv2B,CAAE;AAAA,MAC7B;AAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQK,QAAQy2B,GAA+B;AACrC,WAAA,KAAK,UAAU,IAAIA,CAAM;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS3B,UAAUC,GAAiD;AACzD,WAAA,KAAK,GAAG,UAAUA,CAAE;AAAA,EAAA;AAE/B;ACzDA,MAAM7T,KAAa,IAAInkB,EAAU,oBAAoB,GAC/Ci4B,KAAyB;AAY/B,SAASC,GAA0B1vB,GAAW2vB,GAAkB;AACxD,QAAAC,wBAAsB,IAA0C;AAGlE,SAAA5vB,EAAA,YAAY,CAACpH,GAAMI,MAAQ;AACxB,IAAAJ,EAAA,MAAM,QAAQ,CAAC+K,MAAS;AACvB,UAAAA,EAAK,KAAK,SAASgsB,GAAU;AACzB,cAAAE,IAAgBlsB,EAAK,MACxB;AACH,YAAI,CAACksB;AACH;AAEF,cAAM9kB,IAAO/R,GACPgS,IAAKD,IAAOnS,EAAK,UAIjBk3B,IAAkBF,EAAgB,IAAIC,CAAY,KAAK;AAAA,UAC3D,MAAM;AAAA,UACN,IAAI;AAAA,QACN;AACA,QAAAD,EAAgB,IAAIC,GAAc;AAAA,UAChC,MAAM,KAAK,IAAI9kB,GAAM+kB,EAAgB,IAAI;AAAA,UACzC,IAAI,KAAK,IAAI9kB,GAAI8kB,EAAgB,EAAE;AAAA,QAAA,CACpC;AAAA,MAAA;AAAA,IACH,CACD;AAAA,EAAA,CACF,GACMF;AACT;AAEO,MAAMG,WAAuBlC,EAAmB;AAAA,EA0ErD,YACmBxxB,GACD2zB,GACCL,GACjB;AACM,UAAA;AA1EQ,IAAA7N,EAAA;AAKR;AAAA;AAAA;AAAA,IAAAA,EAAA,wBAAiB;AAKjB;AAAA;AAAA;AAAA,IAAAA,EAAA;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,6CACF,IAAI;AAaF;AAAA;AAAA;AAAA,IAAAA,EAAA,gCAAyB,CAACmO,MAAqC;AAChE,WAAA,OAAO,SAAS,CAACl4B,MAAO;AAC3B,QAAAA,EAAG,IAAI,YAAY,CAACa,GAAMI,MAAQ;AAC3B,UAAAJ,EAAA,MAAM,QAAQ,CAAC+K,MAAS;AAC3B,gBAAIA,EAAK,KAAK,SAAS,KAAK,UAAU;AACpC,oBAAMgsB,IAAWhsB,EAAK,MAChBusB,IAAevsB,EAAK,MAAM,UAC1BwsB,IAASF,EAAQ,IAAIC,CAAY,GACjCE,IAAW,CAAC,EAAE,CAACD,KAAUA,EAAO,YAAYA,EAAO;AAErD,kBAAAC,MAAazsB,EAAK,MAAM,QAAQ;AAClC,sBAAM0sB,IAAc,KAAK,IAAIr3B,GAAK,CAAC,GAC7Bs3B,IAAY,KAAK;AAAA,kBACrBt3B,IAAMJ,EAAK;AAAA,kBACXb,EAAG,IAAI,QAAQ,OAAO;AAAA,kBACtBA,EAAG,IAAI,QAAQ,OAAO;AAAA,gBACxB;AACG,gBAAAA,EAAA,WAAWs4B,GAAaC,GAAW3sB,CAAI,GACvC5L,EAAA;AAAA,kBACDs4B;AAAA,kBACAC;AAAA,kBACAX,EAAS,OAAO;AAAA,oBACd,GAAGhsB,EAAK;AAAA,oBACR,QAAQysB;AAAA,kBACT,CAAA;AAAA,gBACH,GAEIA,KAAY,KAAK,qBAAqBF,MAExC,KAAK,mBAAmB,QACxB,KAAK,gBAAgB;AAAA,cACvB;AAAA,YACF;AAAA,UACF,CACD;AAAA,QAAA,CACF;AAAA,MAAA,CACF;AAAA,IACH;AAGmB,aAAA,SAAA7zB,GACD,KAAA,cAAA2zB,GACC,KAAA,WAAAL,GAIb,CAACtzB,EAAO;AACJ,YAAA,IAAI,MAAM,uCAAuC;AAEzD,SAAK,YAAY,IAAI6yB,GAAgB7yB,EAAO,YAAY,GAInD,KAAA,YAAY,UAAU,KAAK,sBAAsB,GAEtDA,EAAO,SAAS,MAAM;AAEpB,WAAK,uBAAuB,KAAK,YAAY,WAAA,CAAY,GACzDA,EAAO,kBAAkB,MAAM;AAC7B,QAAI,KAAK,mBACP,KAAK,iBAAiB,IACtB,KAAK,gBAAgB;AAAA,MACvB,CACD;AAAA,IAAA,CACF;AAGD,UAAMk0B,IAAO;AAER,SAAA;AAAA,MACH,IAAIh5B,EAA4B;AAAA,QAC9B,KAAKokB;AAAAA,QACL,OAAO;AAAA,UACL,OAAO;AACE,mBAAA;AAAA,cACL,aAAa6U,EAAc;AAAA,YAC7B;AAAA,UACF;AAAA,UACA,MAAMz4B,GAAIyJ,GAAO;AACT,kBAAAivB,IAAS14B,EAAG,QAAQ4jB,EAAU;AAEpC,gBAAI,CAAC5jB,EAAG,cAAc,CAAC04B;AACd,qBAAAjvB;AAIH,kBAAAouB,IAAkB73B,EAAG,aACvB23B,GAA0B33B,EAAG,KAAKw4B,EAAK,QAAQ,IAC/CA,EAAK;AAET,aAAIX,EAAgB,OAAO,KAAKW,EAAK,gBAAgB,OAAO,OAE1DA,EAAK,kBAAkBX,GACvBW,EAAK,gBAAgB;AAIvB,kBAAMG,IAAc,CAAC;AAErB,gBAAIH,EAAK,kBAAkB;AACzB,oBAAMI,IAAyBf,EAAgB;AAAA,gBAC7CW,EAAK;AAAA,cACP;AAEA,cAAII,KACUD,EAAA;AAAA,gBACVE,EAAW;AAAA,kBACTD,EAAuB;AAAA,kBACvBA,EAAuB;AAAA,kBACvB;AAAA,oBACE,OAAO;AAAA,kBAAA;AAAA,gBACT;AAAA,cAEJ;AAAA,YACF;AAGK,mBAAA;AAAA,cACL,aAAaH,EAAc,OAAOz4B,EAAG,KAAK24B,CAAW;AAAA,YACvD;AAAA,UAAA;AAAA,QAEJ;AAAA,QACA,OAAO;AAAA,UACL,YAAYlvB,GAAO;;AACjB,qBACEma,IAAAA,GAAW,SAASna,CAAK,MAAzBma,gBAAAA,EAA4B,gBAAe6U,EAAc;AAAA,UAE7D;AAAA;AAAA;AAAA;AAAA,UAIA,aAAa,CAACp3B,GAAMJ,GAAKM,MAAU;AAC7B,gBAAAA,EAAM,WAAW;AACnB;AAGF,kBAAMV,IAAOQ,EAAK,MAAM,IAAI,OAAOJ,CAAG;AAEtC,gBAAI,CAACJ,GAAM;AACT,cAAA23B,EAAK,aAAa,MAAS;AAC3B;AAAA,YAAA;AAGI,kBAAAM,IAAcj4B,EAAK,MAAM;AAAA,cAC7B,CAAC+K,MACCA,EAAK,KAAK,SAASgsB,KAAYhsB,EAAK,MAAM,WAAW;AAAA,YACzD,GAEMmtB,IAAWD,KAAA,gBAAAA,EAAa,MAAM;AAC/B,YAAAN,EAAA,aAAaO,GAAU,EAAK;AAAA,UAAA;AAAA,QACnC;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA3LF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAsBD,kBAAkB;AACxB,SAAK,KAAK,UAAU;AAAA,MAClB,kBAAkB,KAAK;AAAA,MACvB,gBAAgB,KAAK;AAAA,MACrB,iBAAiB,KAAK;AAAA,IAAA,CACvB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAqKI,SACLlD,GAKA;AACO,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAM5B,aAAakD,GAA8BC,IAAiB,IAAM;;AACnE,QAAA,KAAK,qBAAqBD,MAG9B,KAAK,mBAAmBA,GACxB,KAAK,gBAAgB,GACrB,KAAK,OAAO;AAAA,MAAS,CAAC/4B,MACpBA,EAAG,QAAQ4jB,IAAY;AAAA,QACrB,MAAM8T;AAAA,MACP,CAAA;AAAA,IACH,GAEIqB,KAAYC,IAAgB;AAC9B,YAAMJ,IAAyB,KAAK,gBAAgB,IAAIG,CAAQ;AAEhE,UAAI,CAACH;AACH;AAMA,OAAA14B,KAAAD,IAAA,KAAK,OAAO,oBAAZ,gBAAAA,EAA6B,SAAS24B,EAAuB,MAC1D,SADH,QAAA14B,EAEC,eAAe;AAAA,QAChB,UAAU;AAAA,QACV,OAAO;AAAA,MAAA;AAAA,IACR;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAMK,sBAAsB;AAC3B,SAAK,iBAAiB,IACtB,KAAK,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,qBAAqB;AAC1B,SAAK,iBAAiB,IACtB,KAAK,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,MAAa,aAAauY,GAMvB;AACD,UAAM2f,IAAS,MAAM,KAAK,YAAY,aAAa3f,CAAO;AAEtD,QAAA,KAAK,YAAY,qBAAqB;AAKlC,YAAApX,IAAO,KAAK,OAAO,iBACnB43B,IAAc53B,EAAK,MAAM,WAEzB63B,IAASC,GAAe,SAAS93B,EAAK,KAAK,GAE3Cyd,IAAY;AAAA,QAChB,aAAa;AAAA,UACX,MAAMma,EAAY;AAAA,UAClB,QAAQA,EAAY;AAAA,QACtB;AAAA,QACA,KAAKC,IACDE,GAAqBF,EAAO,SAAS73B,EAAK,KAAK,IAC/C;AAAA;AAAA,MACN;AAEM,YAAA,KAAK,YAAY,oBAAoB;AAAA,QACzC,UAAU+2B,EAAO;AAAA,QACjB,WAAAtZ;AAAA,MAAA,CACD;AAAA,IAAA;AAGD,WAAK,OAAO,cAAc,SAAS,QAAQ,KAAK,UAAU;AAAA,QACxD,QAAQ;AAAA,QACR,UAAUsZ,EAAO;AAAA,MAAA,CAClB;AAAA,EACH;AAEJ;AC9UO,MAAMiB,GAEb;AAAA,EAIE,YACmB/0B,GAKAg1B,GACAC,GACjBC,GACA;AAZK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AA6BP,IAAAA,EAAA,0BAAmB,MAAM;;AACnB,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAGA;AAAA,IAAA8pB,EAAA,0BAAmB,MAAM;;AACnB,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAEA,IAAA8pB,EAAA,uBAAgB,MAAM;;AAChB,WAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,MAAM;AACd,cAAAw5B,IAAe,KAAK,OAAO,KAAK;AAAA,UACpC,8CAA8C,KAAK,MAAM,MAAM,EAAE;AAAA,QACnE;AACA,YAAI,CAACA;AACH;AAEG,aAAA,MAAM,eAAeA,EAAa,sBAAsB,GAC7D,KAAK,WAAW;AAAA,MAAA;AAAA,IAEpB;AAoCA,IAAA1P,EAAA,mBAAY,MAAM;;AACZ,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AA7FmB,SAAA,SAAAqE,GAKA,KAAA,YAAAg1B,GACA,KAAA,SAAAC,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,+CAA+C;AAGjE,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEAD,EAAO,IAAI,iBAAiB,aAAa,KAAK,gBAAgB,GAC9DA,EAAO,IAAI,iBAAiB,aAAa,KAAK,gBAAgB,GAK9DA,EAAO,KAAK,iBAAiB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAAA,EA+BjE,OAAOl4B,GAAkBq4B,GAAwB;;AAC/C,UAAMC,IAAc,KAAK,UAAU,SAASt4B,EAAK,KAAK,GAChDu4B,IAAkB,KAAK,UAAU,SAASF,CAAS;AAErD,QAAA,GAACz5B,IAAA,KAAK,UAAL,QAAAA,EAAY,UAAQ05B,KAAA,QAAAA,EAAa,UAAS,KAAK,OAAO,YAAY;AAC/D,YAAAF,IAAe,KAAK,OAAO,KAAK;AAAA,QACpC,8CAA8CE,EAAY,MAAM,EAAE;AAAA,MACpE;AACA,UAAI,CAACF;AACH;AAEF,WAAK,QAAQ;AAAA,QACX,MAAM;AAAA,QACN,cAAcA,EAAa,sBAAsB;AAAA,QACjD,OAAOE,EAAY;AAAA,MACrB,GAEA,KAAK,WAAW;AAEhB;AAAA,IAAA;AAGF,UAAME,KAAYF,KAAA,gBAAAA,EAAa,UAAS,EAACC,KAAA,QAAAA,EAAiB,QACpDE,IAAY,EAACH,KAAA,QAAAA,EAAa,WAASC,KAAA,gBAAAA,EAAiB;AAC1D,IAAIC,KAAa,KAAK,SAAS,CAAC,KAAK,MAAM,SACzC,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW,IAEdC,OAAa55B,IAAA,KAAK,UAAL,QAAAA,EAAY,UAC3B,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,EAClB;AAAA,EAUF,UAAU;AACR,SAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,gBAAgB,GAEtE,KAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,gBAAgB,GAEtE,KAAK,OAAO,KAAK,oBAAoB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAE3E;AAEA,MAAM65B,KAAqB,IAAIt6B;AAAA,EAC7B;AACF;AAEO,MAAMu6B,WAGHlE,EAAmB;AAAA,EAO3B,YAAYxxB,GAAgE;AACpE,UAAA;AAHA,IAAAylB,EAAA;AAgED,IAAAA,EAAA,mBAAY,MAAM;;AAAA,cAAA9pB,IAAA,KAAK,SAAL,gBAAAA,EAAW;AAAA;AA5D7B,SAAA;AAAA,MACH,IAAIT,EAED;AAAA,QACD,KAAKu6B;AAAA,QACL,MAAM,CAACE,OACL,KAAK,OAAO,IAAIZ;AAAA,UACd/0B;AAAA,UACAy1B;AAAA,UACAE;AAAA,UACA,CAACxwB,MAAU;AACJ,iBAAA,KAAK,UAAUA,CAAK;AAAA,UAAA;AAAA,QAE7B,GACO,KAAK;AAAA,QAEd,OAAO;AAAA,UACL,eAAe,CAAC6pB,GAAO/xB,MAAyB;;AAC9C,mBAAIA,EAAM,QAAQ,YAAY,KAAK,UACjCtB,IAAA,KAAK,SAAL,QAAAA,EAAW,aACJ,MAEF;AAAA,UAAA;AAAA,QAEX;AAAA,QACA,OAAO;AAAA,UACL,MAAM,OACG;AAAA,YACL,OAAO;AAAA,UACT;AAAA,UAEF,OAAO,CAACH,GAAao6B,MAAS;AACtB,kBAAAzwB,IACJ3J,EAAY,QAAQi6B,EAAkB;AAExC,mBAAItwB,MAKF,CAAC3J,EAAY,QAAQq5B,EAAc,MAClCr5B,EAAY,gBAAgBA,EAAY,cAElC,EAAE,OAAO,OAAU,IAErBo6B;AAAA,UAAA;AAAA,QACT;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EAzDF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA2DT,IAAW,QAAQ;;AACV,aAAAh6B,KAAAD,IAAA,KAAK,SAAL,gBAAAA,EAAW,UAAX,gBAAAC,EAAkB,SAAQ;AAAA,EAAA;AAAA,EAG5B,SAAS21B,GAAiD;AACxD,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAIrC;ACnMO,MAAMsE,GAA4C;AAAA,EA0CvD,YACmB71B,GAKAi1B,GACjBC,GACA;AAjDK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,qBAAc;AAEd,IAAAA,EAAA,oBAKS,CAAC,EAAE,MAAA1oB,GAAM,OAAAoI,GAAO,MAAAuJ,GAAM,IAAAC,QAAS;AACvC,YAAA,EAAE,KAAAhL,GAAK,WAAA6W,EAAA,IAAcrV,GACrB,EAAE,OAAA2wB,MAAUtb,GAKZub,IACJ,CAACpyB,EAAI,YAAY+K,GAAMC,CAAE,EAAE,UAAU+L,GAAgBvV,EAAM,SAAS;AAUtE,UANEqV,EAAU,MAAM,OAAO,KAAK,KAAK,QAChCwb,GAAgBxb,CAAS,KAAKA,EAAU,KAAK,KAAK,KAAK,QAKtDsb,KAASC;AACJ,eAAA;AAGT,YAAME,IAAiB,SAAS;AAChC,aAAI,GAAC,KAAK,6BAA6BA,CAAc,KAAKl5B,EAAK;AAAA,IAKjE;AAiCA,IAAA0oB,EAAA,qBAAc,CAACxoB,MAAsB;;AACnC,UAAI,KAAK,aAAa;AACpB,aAAK,cAAc;AAEnB;AAAA,MAAA;AAGI,YAAAi5B,IAAgB,KAAK,OAAO,IAAI;AAItC;AAAA,MAEEj5B,KACAA,EAAM;AAAA,OAELi5B,MAAmBj5B,EAAM,iBACxBi5B,EAAc,SAASj5B,EAAM,aAAqB,KACjDA,EAAM,cAA8B;AAAA,QACnC;AAAA,MACF,OAKAtB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAEA,IAAA8pB,EAAA,sCAA+B,CAAC5qB,MAAyB;AACvD,UAAI,CAACA;AACI,eAAA;AAEH,YAAAq7B,IAAgB,KAAK,OAAO,IAAI;AACtC,aAAKA,IAIEA,EAAc,SAASr7B,CAAO,IAH5B;AAAA,IAIX;AAEA,IAAA4qB,EAAA,8BAAuB,CAAC0Q,MAAkB;AACxC,MAAK,KAAK,6BAA6BA,EAAE,MAAc,MACrD,KAAK,cAAc;AAAA,IAEvB;AAEA,IAAA1Q,EAAA,wBAAiB,MAAM;AACrB,MAAI,KAAK,gBACP,KAAK,cAAc,IACnB,WAAW,MAAM,KAAK,OAAO,KAAK,MAAM,CAAC;AAAA,IAE7C;AAGA;AAAA,IAAAA,EAAA,qBAAc,MAAM;;AACd,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAEA,IAAA8pB,EAAA,uBAAgB,MAAM;;AAChB,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACT,KAAA,MAAM,eAAe,KAAK,wBAAwB,GACvD,KAAK,WAAW;AAAA,IAEpB;AA+EA,IAAA8pB,EAAA,mBAAY,MAAM;;AACZ,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAvLmB,SAAA,SAAAqE,GAKA,KAAA,SAAAi1B,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACR,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAGF,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEAD,EAAO,IAAI,iBAAiB,aAAa,KAAK,oBAAoB,GAClEA,EAAO,KAAK,iBAAiB,WAAW,KAAK,cAAc,GAC3DA,EAAO,IAAI,iBAAiB,aAAa,KAAK,WAAW,GACzDA,EAAO,IAAI,iBAAiB,YAAY,KAAK,WAAW,GACxDA,EAAO,IAAI,iBAAiB,QAAQ,KAAK,WAAW,GAKpDA,EAAO,KAAK,iBAAiB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAAA,EA0EjE,OAAOl4B,GAAkB1B,GAAwB;;AAKzC,UAAA,EAAE,OAAA8J,GAAO,WAAAixB,EAAA,IAAcr5B,GACvB,EAAE,KAAA4G,GAAK,WAAA6W,EAAA,IAAcrV,GACrBkxB,IACJh7B,KAAYA,EAAS,IAAI,GAAGsI,CAAG,KAAKtI,EAAS,UAAU,GAAGmf,CAAS;AAErE,QAAI4b,KAAaC;AACf;AAII,UAAA,EAAE,QAAAC,MAAW9b,GACb9L,IAAO,KAAK,IAAI,GAAG4nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,MAAM,GAAG,CAAC,GACzDxC,IAAK,KAAK,IAAI,GAAG2nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,IAAI,GAAG,CAAC,GAErDolB,IAAa,KAAK,WAAW;AAAA,MACjC,MAAAx5B;AAAA,MACA,OAAAoI;AAAA,MACA,MAAAuJ;AAAA,MACA,IAAAC;AAAA,IAAA,CACD,GAKK6nB,IAAQ,OAAO,MAAM,UAAU,iBAAmB;AAGxD,QAAI,CAAC,KAAK,gBAAgBD,KAAc,KAAK,gBAAgB,CAACC,GAAO;AAMnE,YAAMC,IAAY;AAAA,QAChB,MAAM;AAAA,QACN,cAAc,KAAK,wBAAwB;AAAA,MAC7C;AAEA,OACEA,EAAU,WAAS96B,IAAA,KAAK,UAAL,gBAAAA,EAAY,SAC/B86B,EAAU,aAAa,OAAa,QAAA76B,IAAA,KAAK,UAAL,gBAAAA,EAAY,aAAa,eAE7D,KAAK,QAAQ66B,GACb,KAAK,WAAW;AAGlB;AAAA,IAAA;AAIF,SACEz4B,IAAA,KAAK,UAAL,QAAAA,EAAY,QACZ,CAAC,KAAK,gBACL,CAACu4B,KAAc,KAAK,eAAe,CAAC,KAAK,OAAO,aACjD;AACA,WAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAEhB;AAAA,IAAA;AAAA,EACF;AAAA,EAGF,UAAU;AACR,SAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,oBAAoB,GAC1E,KAAK,OAAO,KAAK,oBAAoB,WAAW,KAAK,cAAc,GACnE,KAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,WAAW,GACjE,KAAK,OAAO,IAAI,oBAAoB,YAAY,KAAK,WAAW,GAChE,KAAK,OAAO,IAAI,oBAAoB,QAAQ,KAAK,WAAW,GAE5D,KAAK,OAAO,KAAK,oBAAoB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAAA,EAUzE,0BAA0B;AAClB,UAAA,EAAE,OAAApxB,MAAU,KAAK,QACjB,EAAE,WAAAqV,MAAcrV,GAGhB,EAAE,QAAAmxB,MAAW9b,GACb9L,IAAO,KAAK,IAAI,GAAG4nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,MAAM,GAAG,CAAC,GACzDxC,IAAK,KAAK,IAAI,GAAG2nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,IAAI,GAAG,CAAC;AAEvD,QAAA6kB,GAAgBxb,CAAS,GAAG;AAC9B,YAAMje,IAAO,KAAK,OAAO,QAAQmS,CAAI;AACrC,UAAInS;AACF,eAAOA,EAAK,sBAAsB;AAAA,IACpC;AAGF,WAAOm6B,GAAa,KAAK,QAAQhoB,GAAMC,CAAE;AAAA,EAAA;AAE7C;AAEO,MAAMgoB,KAA6B,IAAIx7B;AAAA,EAC5C;AACF;AAEO,MAAMy7B,WAA2CpF,EAAmB;AAAA,EAOzE,YAAYxxB,GAAwC;AAC5C,UAAA;AAHA,IAAAylB,EAAA;AAkCD,IAAAA,EAAA,mBAAY,MAAM,KAAK,KAAM,UAAU;AA9BvC,SAAA;AAAA,MACH,IAAIvqB,EAAO;AAAA,QACT,KAAKy7B;AAAA,QACL,MAAM,CAAChB,OACL,KAAK,OAAO,IAAIE,GAAsB71B,GAAQ21B,GAAY,CAACxwB,MAAU;AAC9D,eAAA,KAAK,UAAUA,CAAK;AAAA,QAAA,CAC1B,GACM,KAAK;AAAA,QAEd,OAAO;AAAA,UACL,eAAe,CAAC6pB,GAAO/xB,MACjBA,EAAM,QAAQ,YAAY,KAAK,SACjC,KAAK,KAAM,UAAU,GACd,MAEF;AAAA,QACT;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA3BF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA6BT,IAAW,QAAQ;;AACV,aAAArB,KAAAD,IAAA,KAAK,SAAL,gBAAAA,EAAW,UAAX,gBAAAC,EAAkB,SAAQ;AAAA,EAAA;AAAA,EAG5B,SAAS21B,GAAmD;AAC1D,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAIrC;ACzSa,MAAAsF,KAAYv0B,GAAK,OAAO;AAAA,EACnC,MAAM;AAAA,EAEN,QAAQ;AAAA,EAER,OAAO;AAAA,EAEP,YAAY;AAAA,EAEZ,sBAAsB;AAAA,EAEtB,UAAU;AAAA,EAEV,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,MAAM;AAAA,EACvB;AAAA,EAEA,WAAW,EAAE,gBAAAgB,KAAkB;AAC7B,WAAO,CAAC,MAAM4e,GAAgB,KAAK,QAAQ,gBAAgB5e,CAAc,CAAC;AAAA,EAC5E;AAAA,EAEA,aAAa;AACJ,WAAA;AAAA;AAAA,EAAA;AAEX,CAAC,GCtBYwzB,KAAqB,CAACnzB,GAAWozB,MAAsB;AAC5D,QAAAnzB,IAAOD,EAAI,QAAQozB,CAAS;AAE9B,MAAAnzB,EAAK,SAAS;AACT;AAIT,QAAMozB,IAAkBpzB,EAAK;AAAA,IAC3BA,EAAK,MAAMA,EAAK,QAAQ,CAAC;AAAA,IACzBA,EAAK,QAAQ;AAAA,EACf;AAKO,SAHiBqB;AAAA,IACtBtB,EAAI,QAAQqzB,CAAe;AAAA,EAC7B;AAEF,GAMaC,KAAmB,CAACtzB,GAAWozB,MAAsB;AAC1D,QAAAnzB,IAAOD,EAAI,QAAQozB,CAAS,GAE5BG,IAAgBtzB,EAAK,MAAM;AAEjC,MAAIszB,MAAkB;AACb;AAGT,QAAMC,IAAqBvzB,EAAK,WAAWszB,IAAgB,CAAC;AAKrD,SAHejyB;AAAA,IACpBtB,EAAI,QAAQwzB,CAAkB;AAAA,EAChC;AAEF,GAWaC,KAA2B,CAACzzB,GAAWiE,MAAyB;AAC3E,SAAOA,EAAU,kBAAgB;AACzB,UAAAyvB,IAAQzvB,EAAU,eAAe,MAEjC0vB,IAAS3zB,EACZ,QAAQiE,EAAU,eAAe,YAAY,CAAC,EAC9C,WAAWyvB,EAAM,aAAa,CAAC;AAClC,IAAAzvB,IAAY3C,GAA4BtB,EAAI,QAAQ2zB,CAAM,CAAC;AAAA,EAAA;AAGtD,SAAA1vB;AACT,GAEM2vB,KAAW,CAAC3X,GAA0B4X,MAExC5X,EAAc,oBACdA,EAAc,aAAa,KAAK,KAAK,KAAK,YAAY,aACtDA,EAAc,aAAa,KAAK,aAAa,KAC7C4X,EAAc,oBACdA,EAAc,aAAa,KAAK,KAAK,KAAK,YAAY,WAIpDC,KAAc,CAClBtyB,GACAuN,GACAkN,GACA4X,MACG;AAEC,MAAA,CAACA,EAAc;AACjB,UAAM,IAAI;AAAA,MACR,wCAAwCA,EAAc,QAAQ,SAAS,oCAAoC5X,EAAc,QAAQ,SAAS;AAAA,IAC5I;AAKF,MAAI4X,EAAc,gBAAgB;AAC1B,UAAAE,IAAmBvyB,EAAM,IAAI;AAAA,MACjCqyB,EAAc,eAAe,YAAY;AAAA,IAC3C,GACMG,IAAiBxyB,EAAM,IAAI;AAAA,MAC/BqyB,EAAc,eAAe,WAAW;AAAA,IAC1C,GACMI,IAAmBF,EAAiB,WAAWC,CAAc;AAEnE,QAAIjlB,GAAU;AACZ,YAAM/V,IAAMwI,EAAM,IAAI,QAAQqyB,EAAc,QAAQ,SAAS;AAC7D,MAAAryB,EAAM,GAAG,KAAKyyB,GAAmBj7B,EAAI,KAAK;AAAA,IAAA;AAAA,EAC5C;AAMF,MAAI+V,GAAU;AACR,QAAA,CAACkN,EAAc;AACjB,YAAM,IAAI;AAAA,QACR,wCAAwC4X,EAAc,QAAQ,SAAS,oCAAoC5X,EAAc,QAAQ,SAAS;AAAA,MAC5I;AAIF,IAAAlN;AAAA,MACEvN,EAAM,GAAG;AAAA,QACPya,EAAc,aAAa,WAAW;AAAA,QACtC4X,EAAc,aAAa,YAAY;AAAA,MAAA;AAAA,IAE3C;AAAA,EAAA;AAGK,SAAA;AACT,GAEaK,KACX,CAACC,MACD,CAAC;AAAA,EACC,OAAA3yB;AAAA,EACA,UAAAuN;AACF,MAGM;AACJ,QAAM9O,IAAOuB,EAAM,IAAI,QAAQ2yB,CAAgB,GACzCN,IAAgBvyB,GAA4BrB,CAAI,GAEhDgc,IAAgBqX;AAAA,IACpB9xB,EAAM;AAAA,IACNqyB,EAAc,QAAQ;AAAA,EACxB;AAEA,MAAI,CAAC5X;AACI,WAAA;AAGT,QAAMmY,IAAwBX;AAAA,IAC5BjyB,EAAM;AAAA,IACNya;AAAA,EACF;AAEA,SAAK2X,GAASQ,GAAuBP,CAAa,IAI3CC,GAAYtyB,GAAOuN,GAAUqlB,GAAuBP,CAAa,IAH/D;AAIX,GCvJWQ,KAA6Bt9B,EAAU,OAGjD;AAAA,EACD,UAAU;AAAA;AAAA;AAAA,EAIV,uBAAuB;AAEf,UAAAu9B,IAAkB,MACtB,KAAK,OAAO,SAAS,MAAM,CAAC,EAAE,OAAAlc,GAAO,UAAA2C,QAAe;AAAA;AAAA,MAElD,MAAMA,EAAS,gBAAgB;AAAA;AAAA,MAE/B,MAAMA,EAAS,cAAc;AAAA;AAAA,MAE7B,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAGT,cAAMswB,IACJ/yB,EAAM,UAAU,SAASyC,EAAU,aAAa,YAAY,GACxDuwB,IACJvwB,EAAU,aAAa,KAAK,KAAK,SAAS;AAExC,eAAAswB,KAAyB,CAACC,IACrBzZ,EAAS;AAAA,UACdlM,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH,IAGK;AAAA,MAAA,CACR;AAAA;AAAA,MAEH,MACE8W,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAEH,cAAA,EAAE,cAAAlI,MAAiBkI;AAKzB,eAFEzC,EAAM,UAAU,SAASzF,EAAa,YAAY,IAG3Cgf,EAAS,aAAa,gBAAgB,IAGxC;AAAA,MAAA,CACR;AAAA;AAAA;AAAA,MAGH,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAET,cAAM,EAAE,SAASW,GAAgB,cAAA7I,EAAiB,IAAAkI,GAE5CswB,IACJ/yB,EAAM,UAAU,SAASzF,EAAa,YAAY,GAC9C+e,IAAiBtZ,EAAM,UAAU,OAEjC2yB,IAAmBvvB,EAAe;AAExC,eAAI2vB,KAAyBzZ,IACpB1C,EAAA,EACJ,QAAQ8b,GAAmBC,CAAgB,CAAC,EAC5C,eAAe,EACf,IAAI,IAGF;AAAA,MAAA,CACR;AAAA,MACH,MACEpZ,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,GAAO,UAAAuN,QAAe;AAElC,cAAA9K,IAAY1C,EAA0BC,CAAK;AAiBjD,YAhBI,CAACyC,EAAU,oBAOX,EAFFzC,EAAM,UAAU,SAASyC,EAAU,aAAa,YAAY,MAMxCqvB;AAAA,UACpB9xB,EAAM;AAAA,UACNyC,EAAU,QAAQ;AAAA,QACpB;AAIS,iBAAA;AAGT,cAAMwwB,IAAkBtB;AAAA,UACtB3xB,EAAM;AAAA,UACNyC,EAAU,QAAQ;AAAA,QACpB;AAEI,aAAAwwB,KAAA,gBAAAA,EAAiB,mBAAkB;AAC9B,iBAAA;AAGT,cAAMvR,IAASuR,GAETC,IAAavB;AAAA,UACjB3xB,EAAM;AAAA,UACN0hB,EAAO,QAAQ;AAAA,QACjB;AACI,aAAAwR,KAAA,gBAAAA,EAAY,mBAAkB;AAC1B,gBAAA,IAAI,MAAM,uCAAuC;AAGzD,cAAMC,IACJzR,EAAO,eAAgB,KAAK,eAAe,GAEvC0R,IACJD,KACAD,EAAW,eAAgB,KAAK,eAAe,GAE3CG,IACJH,EAAW,eAAgB,KAAK,eAChCxR,EAAO,QAAQ;AAEjB,YAAInU,GAAU;AACN,gBAAA+lB,IAActzB,EAAM,IAAI;AAAA,YAC5ByC,EAAU,QAAQ;AAAA,YAClBA,EAAU,QAAQ;AAAA,YAClB;AAAA,UACF;AAWA,cAAI2wB;AACF,gBAAIC,GAAe;AACjB,cAAArzB,EAAM,GAAG;AAAA,gBACP,IAAIgjB;AAAA;AAAA,kBAEFkQ,EAAW,QAAQ;AAAA,kBACnBA,EAAW,QAAQ;AAAA;AAAA,kBAEnBxR,EAAO,QAAQ,WAAW;AAAA,kBAC1BwR,EAAW,QAAQ,WAAW;AAAA,kBAC9BI;AAAA,kBACAA,EAAY;AAAA;AAAA,kBACZ;AAAA,gBAAA;AAAA,cAEJ;AACA,oBAAM97B,IAAMwI,EAAM,GAAG,IAAI,QAAQ0hB,EAAO,QAAQ,SAAS;AACzD,cAAA1hB,EAAM,GAAG,aAAaoV,EAAc,QAAQ5d,GAAKA,CAAG,CAAC;AAAA,YAAA,OAChD;AAEL,cAAAwI,EAAM,GAAG;AAAA,gBACP,IAAIgjB;AAAA;AAAA,kBAEFkQ,EAAW,QAAQ;AAAA,kBACnBA,EAAW,QAAQ;AAAA;AAAA,kBAEnBA,EAAW,QAAQ,YAAY;AAAA,kBAC/BxR,EAAO,QAAQ,YAAY;AAAA,kBAC3B4R;AAAA,kBACA;AAAA;AAAA,kBACA;AAAA,gBAAA;AAAA,cAEJ;AACM,oBAAA97B,IAAMwI,EAAM,GAAG,IAAI;AAAA,gBACvBA,EAAM,GAAG,QAAQ,IAAI0hB,EAAO,QAAQ,YAAY,CAAC;AAAA,cACnD;AACA,cAAA1hB,EAAM,GAAG,aAAaoV,EAAc,QAAQ5d,GAAKA,CAAG,CAAC;AAAA,YAAA;AAAA,mBAE9C27B;AACT,gBAAIE,GAAe;AAEjB,cAAArzB,EAAM,GAAG;AAAA,gBACP0hB,EAAO,QAAQ;AAAA,gBACfA,EAAO,QAAQ;AAAA,cACjB,GAGA1hB,EAAM,GAAG;AAAA,gBACPkzB,EAAW,QAAQ;AAAA,gBACnBI,EAAY;AAAA,cACd;AAEM,oBAAA97B,IAAMwI,EAAM,GAAG,IAAI;AAAA,gBACvBkzB,EAAW,QAAQ;AAAA,cACrB;AACA,cAAAlzB,EAAM,GAAG,aAAaoV,EAAc,QAAQ5d,GAAKA,CAAG,CAAC;AAAA,YAAA;AAGrD,cAAAwI,EAAM,GAAG;AAAA,gBACP0hB,EAAO,QAAQ,YAAY;AAAA,gBAC3BA,EAAO,QAAQ,YAAY;AAAA,cAC7B;AAAA,eAEG;AAEL,YAAA1hB,EAAM,GAAG;AAAA,cACPyC,EAAU,QAAQ;AAAA,cAClBA,EAAU,QAAQ;AAAA,YACpB,GACI4wB,IAEFrzB,EAAM,GAAG;AAAA,cACPkzB,EAAW,QAAQ,YAAY;AAAA,cAC/BI,EAAY;AAAA,YACd,IAGAtzB,EAAM,GAAG;AAAA,cACP0hB,EAAO,QAAQ,YAAY;AAAA,cAC3B4R,EAAY;AAAA,YACd;AAEI,kBAAA97B,IAAMwI,EAAM,GAAG,IAAI,QAAQ0hB,EAAO,QAAQ,YAAY,CAAC;AAC7D,YAAA1hB,EAAM,GAAG,aAAaoV,EAAc,QAAQ5d,GAAKA,CAAG,CAAC;AAAA,UAAA;AAAA,QACvD;AAGK,eAAA;AAAA,MAAA,CACR;AAAA;AAAA;AAAA,MAGH,MACE+hB,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAOT,YAHEA,EAAU,aAAa,KAAK,eAAe,KAC3CA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,WAEpC;AACd,gBAAMgY,IAAgBqX;AAAA,YACpB9xB,EAAM;AAAA,YACNyC,EAAU,QAAQ;AAAA,UACpB;AACA,cAAI,CAACgY,KAAiB,CAACA,EAAc;AAC5B,mBAAA;AAGT,cAAI8Y,IAAkB3c,EAAM;AAE5B,cACE6D,EAAc,aAAa,KAAK,KAAK,KAAK,YAC1C,aACA;AAKA,kBAAM+Y,IAJmB/wB,EAAU,QAAQ,YAAY,IACJ,IACH,IACT,IACU;AAEjD,YAAA8wB,IAAkBA,EAAgB;AAAA,cAChCC;AAAA,YACF;AAAA,UAAA,WAEA/Y,EAAc,aAAa,KAAK,KAAK,KAAK,YAAY,IACtD;AACA,kBAAMgZ,IACJhZ,EAAc,aAAa,WAC3BA,EAAc,aAAa,KAAK;AAElC,YAAA8Y,IAAkBA,EAAgB;AAAA,cAChCE;AAAA,YACF;AAAA,UAAA,OACK;AACL,kBAAMC,IACJjZ,EAAc,aAAa,WAC3BA,EAAc,aAAa,KAAK;AAGhC,YAAA8Y,IAAAA,EAAgB,iBAAiBG,CAAoB;AAAA,UAAA;AAGzD,iBAAOH,EACJ,YAAY;AAAA,YACX,MAAM9wB,EAAU,QAAQ;AAAA,YACxB,IAAIA,EAAU,QAAQ;AAAA,UAAA,CACvB,EACA,eAAe,EACf,IAAI;AAAA,QAAA;AAGF,eAAA;AAAA,MAAA,CACR;AAAA;AAAA;AAAA;AAAA,MAIH,MACE8W,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAE7C,YAAA,CAACyC,EAAU;AAEP,gBAAA,IAAI,MAAM,MAAM;AAGxB,cAAMswB,IACJ/yB,EAAM,UAAU,SAASyC,EAAU,aAAa,YAAY,GACxD6W,IAAiBtZ,EAAM,UAAU,OAEjCya,IAAgBqX;AAAA,UACpB9xB,EAAM;AAAA,UACNyC,EAAU,QAAQ;AAAA,QACpB;AAEI,YAAAgY,KAAiBsY,KAAyBzZ,GAAgB;AAC5D,gBAAMqa,IAAc1B;AAAA,YAClBjyB,EAAM;AAAA,YACNya;AAAA,UACF;AAEI,cAAA,CAACkZ,EAAY;AAET,kBAAA,IAAI,MAAM,MAAM;AASxB,cALEA,EAAY,aAAa,KAAK,KAAK,KAAK,YAAY,MACnDA,EAAY,aAAa,KAAK,KAAK,KAAK,YACvC,aACAA,EAAY,aAAa,KAAK,eAAe;AAG/C,mBAAO/c,EACJ,EAAA;AAAA,cACC;AAAA,gBACE,MAAMnU,EAAU,QAAQ;AAAA,gBACxB,IAAIA,EAAU,QAAQ;AAAA,cACxB;AAAA,cACAkxB,EAAY,QAAQ;AAAA,cAErB,YAAY;AAAA,cACX,MAAMA,EAAY,QAAQ;AAAA,cAC1B,IAAIA,EAAY,QAAQ;AAAA,YACzB,CAAA,EACA,IAAI;AAAA,QACT;AAGK,eAAA;AAAA,MACR,CAAA;AAAA,IAAA,CACJ,GAEGC,IAAe,MACnB,KAAK,OAAO,SAAS,MAAM,CAAC,EAAE,UAAAra,QAAe;AAAA;AAAA,MAE3C,MAAMA,EAAS,gBAAgB;AAAA;AAAA;AAAA;AAAA,MAI/B,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AAExB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAEH,cAAA;AAAA,UACJ,SAASW;AAAA,UACT,cAAA7I;AAAA,UACA,gBAAAs5B;AAAA,QAAA,IACEpxB,GAEE,EAAE,OAAA/D,EAAM,IAAIsB,EAAM,IAAI,QAAQoD,EAAe,SAAS,GACtD0wB,IACJ1wB,EAAe,aAAapD,EAAM,IAAI,WAAW,GAC7C+zB,IACJ/zB,EAAM,UAAU,SAASzF,EAAa,WAAW,GAC7C+e,IAAiBtZ,EAAM,UAAU;AAGvC,YACE,CAAC8zB,KACDC,KACAza,KACA,EANqBua,MAAmB,SAOxC;AACA,cAAIG,IAAWt1B,GACXyzB,IAAS/uB,EAAe,WAAW,GACnC6wB,IAAWj0B,EAAM,IAAI,QAAQmyB,CAAM,EAAE;AAEzC,iBAAO8B,IAAWD;AACL,YAAAA,IAAAC,GACD9B,KAAA,GACV8B,IAAWj0B,EAAM,IAAI,QAAQmyB,CAAM,EAAE;AAGvC,iBAAO5Y,EAAS,QAAQmZ,GAAmBP,IAAS,CAAC,CAAC;AAAA,QAAA;AAGjD,eAAA;AAAA,MACR,CAAA;AAAA,IAAA,CACJ,GAEG9Y,IAAc,CAAC6a,IAAY,OACxB,KAAK,OAAO,SAAS,MAAM,CAAC,EAAE,UAAA3a,QAAe;AAAA;AAAA;AAAA,MAGlD,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAET,cAAM,EAAE,SAASW,GAAgB,cAAA7I,EAAiB,IAAAkI,GAE5C,EAAE,OAAA/D,EAAM,IAAIsB,EAAM,IAAI,QAAQoD,EAAe,SAAS,GAEtD2vB,IACJ/yB,EAAM,UAAU,QAAQ,iBAAiB,GACrCsZ,IACJtZ,EAAM,UAAU,WAAWA,EAAM,UAAU,MACvCm0B,IAAa55B,EAAa,KAAK,eAAe,GAC9C65B,IAAgB11B,IAAQ;AAG5B,eAAAq0B,KACAzZ,KACA6a,KACAC,IAEO7a,EAAS,aAAa,gBAAgB,IAGxC;AAAA,MAAA,CACR;AAAA;AAAA,MAEH,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK,GAE3Cq0B,IACJ,KAAK,QAAQ,OAAO,OAAO,YAAY5xB,EAAU,aAAa,EAC3D,qBAAqB;AAE1B,eAAI4xB,MAA2B,SACtB;AAAA;AAAA;AAAA,UAMNA,MAA2B,iBAAiBH;AAAA;AAAA,UAG7CG,MAA2B,UAEpB9a,EAAS,cAAc;AAAA,YAC5B,MAAM;AAAA,UAAA,CACP,IAGI;AAAA;AAAA,MAAA,CACR;AAAA;AAAA;AAAA,MAGH,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,GAAO,UAAAuN,QAAe;AAClC,cAAA9K,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAET,cAAM,EAAE,SAASW,GAAgB,cAAA7I,EAAiB,IAAAkI,GAE5CswB,IACJ/yB,EAAM,UAAU,QAAQ,iBAAiB,GACrCsZ,IACJtZ,EAAM,UAAU,WAAWA,EAAM,UAAU,MACvCm0B,IAAa55B,EAAa,KAAK,eAAe;AAEhD,YAAAw4B,KAAyBzZ,KAAkB6a,GAAY;AACzD,gBAAMG,IAAuBlxB,EAAe,UACtCmxB,IAAqBD,IAAuB;AAElD,cAAI/mB,GAAU;AACZ,kBAAMqS,IACJ5f,EAAM,OAAO,MAAM,eAAkB,cAAc;AAErD,YAAAA,EAAM,GACH,OAAOs0B,GAAsB1U,CAAQ,EACrC,eAAe,GAClB5f,EAAM,GAAG;AAAA,cACP,IAAIoV,EAAcpV,EAAM,IAAI,QAAQu0B,CAAkB,CAAC;AAAA,YACzD;AAAA,UAAA;AAGK,iBAAA;AAAA,QAAA;AAGF,eAAA;AAAA,MAAA,CACR;AAAA;AAAA;AAAA,MAGH,MACEhb,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,GAAO,OAAA4W,QAAY;AAC/B,cAAAnU,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAEH,cAAA,EAAE,cAAAlI,MAAiBkI,GAEnBswB,IACJ/yB,EAAM,UAAU,QAAQ,iBAAiB;AAG3C,eAFmBzF,EAAa,KAAK,eAAe,IAiB7C,MAdCqc,EAAA,EACH,kBACA;AAAA,UACCmC;AAAA,YACE/Y,EAAM,UAAU;AAAA,YAChB+yB;AAAA,YACAA;AAAA,UAAA;AAAA,UAGH,IAAI,GAEA;AAAA,MAIV,CAAA;AAAA,IAAA,CACJ;AAGI,WAAA;AAAA,MACL,WAAWD;AAAA,MACX,QAAQc;AAAA,MACR,OAAO,MAAMva,EAAY;AAAA,MACzB,eAAe,MAAMA,EAAY,EAAI;AAAA;AAAA;AAAA,MAGrC,KAAK,MAAM;;AACT,eACE,KAAK,QAAQ,gBAAgB,qBAC5B7iB,IAAA,KAAK,QAAQ,OAAO,sBAApB,QAAAA,EAAuC,UACtCC,IAAA,KAAK,QAAQ,OAAO,gBAApB,QAAAA,EAAiC,UACjCoC,IAAA,KAAK,QAAQ,OAAO,cAApB,QAAAA,EAA+B,SAG1B,KAEFoqB,GAAU,KAAK,QAAQ,MAAM;AAAA,MAEtC;AAAA,MACA,aAAa,MAAM;;AACjB,eACE,KAAK,QAAQ,gBAAgB,qBAC5BzsB,IAAA,KAAK,QAAQ,OAAO,sBAApB,QAAAA,EAAuC,UACtCC,IAAA,KAAK,QAAQ,OAAO,gBAApB,QAAAA,EAAiC,UACjCoC,IAAA,KAAK,QAAQ,OAAO,cAApB,QAAAA,EAA+B,SAG1B,MAEJ,KAAA,OAAO,SAAS,aAAa,gBAAgB,GAC3C;AAAA,MACT;AAAA,MACA,qBAAqB,OACd,KAAA,QAAQ,OAAO,aAAa,GAC1B;AAAA,MAET,uBAAuB,OAChB,KAAA,QAAQ,OAAO,eAAe,GAC5B;AAAA,MAET,SAAS,MAAM,KAAK,QAAQ,OAAO,KAAK;AAAA,MACxC,SAAS,MAAM,KAAK,QAAQ,OAAO,KAAK;AAAA,MACxC,eAAe,MAAM,KAAK,QAAQ,OAAO,KAAK;AAAA,IAChD;AAAA,EAAA;AAEJ,CAAC;AC7kBD,MAAM27B,GAAsC;AAAA,EAiB1C,YACmB35B,GACAi1B,GACjBC,GACA;AApBK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AAEP,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AA2CA,IAAAA,EAAA,0BAAmB,CAACxoB,MAAsB;AAOxC,UALA,KAAK,uBAAuB,QAC5B,KAAK,4BAA4B,QAEjC,KAAK,oBAAoB,GAGvBA,EAAM,kBAAkB,qBACxBA,EAAM,OAAO,aAAa,KAC1B;AAGA,cAAM28B,IAAqB38B,EAAM,QAC3B48B,IACJ,KAAK,OAAO,SAASD,GAAoB,CAAC,IAAI,GAC1CE,IACJ,KAAK,OAAO,MAAM,IAAI,QAAQD,CAAoB,GAC9CE,IAAaD,EAA6B,MAAM;AAEtD,mBAAWxyB,KAAQyyB;AAEf,cAAAzyB,EAAK,KAAK,SAAS,KAAK,OAAO,MAAM,OAAO,KAAK,MAAM,EAAE,KAAK,MAC9D;AACA,iBAAK,uBAAuBA,GAC5B,KAAK,4BACH0yB,GAAaF,GAA8BxyB,EAAK,MAAMA,EAAK,KAAK,KAChE;AAEF;AAAA,UAAA;AAAA,MAEJ;AAGF,kBAAK,qBAAqB,GAEnB;AAAA,IACT;AAEA,IAAAme,EAAA,sBAAe,CAACxoB,MAAsB;;AAC9B,YAAAi5B,IAAgB,KAAK,OAAO,IAAI;AAEtC;AAAA,MAEE,KAAK;AAAA,MAELj5B,KACAA,EAAM;AAAA,MAEN,EACEi5B,MAAmBj5B,EAAM,UACzBi5B,EAAc,SAASj5B,EAAM,MAAc,OAGzCtB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAGtB;AAEA,IAAA8pB,EAAA,uBAAgB,MAAM;;AAChB,MAAA,KAAK,aAAa,WAChB9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,eAAe+6B;AAAA,QACxB,KAAK;AAAA,QACL,KAAK,cAAe;AAAA,QACpB,KAAK,cAAe;AAAA,MACtB,GACA,KAAK,WAAW;AAAA,IAGtB;AA8HA,IAAAjR,EAAA,mBAAY,MAAM;;AACZ,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAnPmB,SAAA,SAAAqE,GACA,KAAA,SAAAi1B,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,iDAAiD;AAGnE,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEA,KAAK,uBAAuB,MAAM;AAC3B,WAAA,kBAAkB,WAAW,MAAM;AACtC,aAAK,OAAO,KAAK,QAAQ,QAAW,EAAI;AAAA,SACvC,GAAG;AAAA,IACR,GAEA,KAAK,sBAAsB,OACrB,KAAK,oBACP,aAAa,KAAK,eAAe,GACjC,KAAK,kBAAkB,SAGlB,KAGT,KAAK,OAAO,IAAI,iBAAiB,aAAa,KAAK,gBAAgB,GACnE,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GAKA,KAAK,OAAO,KAAK,iBAAiB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAAA,EA6EtE,SAASp0B,GAAaoO,GAAc;;AAC7B,SAAA,OAAO,SAAS,CAACxT,MAAO;AACrB,YAAAqV,IAAW1L,EAAY3J,CAAE;AAC/B,MAAAA,EAAG,WAAWwT,GAAM,KAAK,cAAe,MAAM,KAAK,cAAe,EAAE,GACjExT,EAAA;AAAA,QACD,KAAK,cAAe;AAAA,QACpB,KAAK,cAAe,OAAOwT,EAAK;AAAA,QAChC6B,EAAS,KAAK,QAAQ,EAAE,MAAMjQ,EAAK,CAAA;AAAA,MACrC;AAAA,IAAA,CACD,GACD,KAAK,OAAO,MAAM,IAEdnF,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,EAClB;AAAA,EAGF,aAAa;;AACX,SAAK,OAAO;AAAA,MAAS,CAACD,MACpBA,EACG;AAAA,QACC,KAAK,cAAe;AAAA,QACpB,KAAK,cAAe;AAAA,QACpB,KAAK,SAAU;AAAA,MAAA,EAEhB,QAAQ,mBAAmB,EAAI;AAAA,IACpC,GACA,KAAK,OAAO,MAAM,IAEdC,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,EAClB;AAAA,EAGF,OAAOoB,GAAkB1B,GAAwB4+B,IAAgB,IAAO;;AAChE,UAAA,EAAE,OAAA90B,MAAUpI;AAOlB,QAJE1B,KACAA,EAAS,UAAU,SAAS8J,EAAM,UAAU,QAC5C9J,EAAS,UAAU,OAAO8J,EAAM,UAAU,MAE9B,CAAC,KAAK,OAAO;AACzB;AAIF,UAAM+0B,IAAe,KAAK;AAY1B,QATA,KAAK,WAAW,QAChB,KAAK,gBAAgB,QAGrB,KAAK,0BAA0B,QAC/B,KAAK,+BAA+B,QAIhC,KAAK,OAAO,MAAM,UAAU,OAAO;AACrC,YAAMH,IAAa,KAAK,OAAO,MAAM,UAAU,MAAM,MAAM;AAE3D,iBAAWzyB,KAAQyyB;AAEf,YAAAzyB,EAAK,KAAK,SAAS,KAAK,OAAO,MAAM,OAAO,KAAK,MAAM,EAAE,KAAK,MAC9D;AACA,eAAK,0BAA0BA,GAC/B,KAAK,+BACH0yB;AAAA,YACE,KAAK,OAAO,MAAM,UAAU;AAAA,YAC5B1yB,EAAK;AAAA,YACLA,EAAK;AAAA,UAAA,KACF;AAEP;AAAA,QAAA;AAAA,IAEJ;AAcF,QAXI,KAAK,wBAAwB2yB,MAC/B,KAAK,WAAW,KAAK,sBACrB,KAAK,gBAAgB,KAAK,4BAIxB,KAAK,4BACP,KAAK,WAAW,KAAK,yBACrB,KAAK,gBAAgB,KAAK,+BAGxB,KAAK,YAAY,KAAK,OAAO,YAAY;AAC3C,WAAK,QAAQ;AAAA,QACX,MAAM;AAAA,QACN,cAAcvD;AAAA,UACZ,KAAK;AAAA,UACL,KAAK,cAAe;AAAA,UACpB,KAAK,cAAe;AAAA,QACtB;AAAA,QACA,KAAK,KAAK,SAAU,MAAM;AAAA,QAC1B,MAAM,KAAK,OAAO,MAAM,IAAI;AAAA,UAC1B,KAAK,cAAe;AAAA,UACpB,KAAK,cAAe;AAAA,QAAA;AAAA,MAExB,GACA,KAAK,WAAW;AAEhB;AAAA,IAAA;AAKA,SAAA/6B,IAAA,KAAK,UAAL,QAAAA,EAAY,QACZu+B,MACC,CAAC,KAAK,YAAY,CAAC,KAAK,OAAO,aAChC;AACA,WAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAEhB;AAAA,IAAA;AAAA,EACF;AAAA,EAUF,UAAU;AACR,SAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,gBAAgB,GACtE,KAAK,OAAO,KAAK,oBAAoB,UAAU,KAAK,eAAe,EAAI,GACvE,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EAAA;AAEJ;AAEa,MAAAC,KAAuB,IAAIh/B,EAAU,mBAAmB;AAE9D,MAAMi/B,WAIH5I,EAAmB;AAAA,EAO3B,YAAYxxB,GAAwC;AAC5C,UAAA;AAHA,IAAAylB,EAAA;AAiCD;AAAA;AAAA;AAAA,IAAAA,EAAA,kBAAW,CAAC3kB,GAAaoO,MAAiB;AAC1C,WAAA,KAAM,SAASpO,GAAKoO,CAAI;AAAA,IAC/B;AAKO;AAAA;AAAA;AAAA,IAAAuW,EAAA,oBAAa,MAAM;AACxB,WAAK,KAAM,WAAW;AAAA,IACxB;AASO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,wBAAiB,MAAM;AAC5B,WAAK,KAAM,qBAAqB;AAAA,IAClC;AASO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,uBAAgB,MAAM;AAC3B,WAAK,KAAM,oBAAoB;AAAA,IACjC;AAMO,IAAAA,EAAA,mBAAY,MAAM,KAAK,KAAM,UAAU;AAlEvC,SAAA;AAAA,MACH,IAAIvqB,EAAO;AAAA,QACT,KAAKi/B;AAAA,QACL,MAAM,CAACxE,OACL,KAAK,OAAO,IAAIgE,GAAgB35B,GAAQ21B,GAAY,CAACxwB,MAAU;AACxD,eAAA,KAAK,UAAUA,CAAK;AAAA,QAAA,CAC1B,GACM,KAAK;AAAA,QAEd,OAAO;AAAA,UACL,eAAe,CAAC6pB,GAAO/xB,MACjBA,EAAM,QAAQ,YAAY,KAAK,SACjC,KAAK,KAAM,UAAU,GACd,MAEF;AAAA,QACT;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA3BF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA6BF,SAASs0B,GAA6C;AACpD,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAAA,EAuCnC,IAAW,QAAQ;;AACV,aAAA31B,KAAAD,IAAA,KAAK,SAAL,gBAAAA,EAAW,UAAX,gBAAAC,EAAkB,SAAQ;AAAA,EAAA;AAIrC;AC3XO,MAAMy+B,KAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACaC,KAAwB,SCT/Bhb,KAAa,IAAInkB,EAAU,yBAAyB;AAenD,MAAMo/B,WAAoC/I,EAAmB;AAAA,EAClE,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,cAAc;AACN,UAAA,GACD,KAAA;AAAA,MACH,IAAIt2B,EAAO;AAAA,QACT,KAAKokB;AAAAA,QACL,OAAO;AAAA,UACL,eAAe,CAACviB,GAAME,MAAU;AAE1B,gBAAA,UAAUF,EAAK,MAAM,WAAW;AAE9B,kBAAAE,EAAM,WAAWA,EAAM;AAClB,uBAAA;AAGL,kBAAAA,EAAM,IAAI,WAAW;AACvB,uBAAAA,EAAM,eAAe,GAEd;AAGT,kBACEA,EAAM,QAAQ,WACd,CAACA,EAAM,YACP,CAACA,EAAM,UACP,CAACA,EAAM,WACP,CAACA,EAAM,SACP;AACM,sBAAAvB,IAAKqB,EAAK,MAAM;AACjB,uBAAAA,EAAA;AAAA,kBACHrB,EACG;AAAA,oBACCqB,EAAK,MAAM,GAAG,UAAU,IAAI,MAAM;AAAA,oBAClCA,EAAK,MAAM,OAAO,MAAM,UAAa,cAAc;AAAA,kBAAA,EAEpD;AAAA,oBACC,IAAIwd;AAAA,sBACF7e,EAAG,IAAI,QAAQqB,EAAK,MAAM,GAAG,UAAU,IAAI,MAAM,IAAI,CAAC;AAAA,oBAAA;AAAA,kBACxD;AAAA,gBAEN,GAEO;AAAA,cAAA;AAAA,YACT;AAGK,mBAAA;AAAA,UAAA;AAAA,QACT;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ;ACpEA,MAAMuiB,KAAa,IAAInkB,EAAU,uBAAuB;AAEjD,MAAMq/B,WAA0BhJ,EAAmB;AAAA,EACxD,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,YACExxB,GACAy6B,GAIA;AACM,UAAA,GACD,KAAA;AAAA,MACH,IAAIv/B,EAAO;AAAA,QACT,KAAKokB;AAAAA,QACL,MAAM,CAACviB,MAAS;;AACR,gBAAA29B,IAAuB,wBAAwB9/B,GAAI,CAAA;AACpD,UAAAmC,EAAA,IAAI,UAAU,IAAI29B,CAAoB;AACrC,gBAAAC,IAAU,SAAS,cAAc,OAAO,GAExCC,IAAQ56B,EAAO,cAAc,QAAQ;AAC3C,UAAI46B,KACMD,EAAA,aAAa,SAASC,CAAK,KAGjCj/B,IAAAqE,EAAO,oBAAP,gBAAArE,EAAwB,iBAAgB,aACnCqE,EAAA,gBAAgB,KAAK,OAAO26B,CAAO,KAE1C/+B,IAAAoE,EAAO,oBAAP,QAAApE,EAAwB,KAAK,KAAK,YAAY++B;AAGhD,gBAAME,IAAaF,EAAQ,OAErBG,IAAc,CAACC,IAAsB,OACzC,IAAIL,CAAoB,qBAAqBK,CAAmB;AAE9D,cAAA;AAEI,kBAAA;AAAA,cACJ,SAASC;AAAA,cACT,eAAeC;AAAA,cACf,GAAGr8B;AAAA,YAAA,IACD67B;AAGJ,uBAAW,CAAC54B,GAAWq5B,CAAW,KAAK,OAAO,QAAQt8B,CAAI,GAAG;AACrD,oBAAAu8B,IAAoB,uBAAuBt5B,CAAS;AAE/C,cAAAg5B,EAAA;AAAA,gBACT,GAAGC,EAAYK,CAAiB,CAAC,eAAe,KAAK;AAAA,kBACnDD;AAAA,gBAAA,CACD;AAAA,cACH;AAAA,YAAA;AAGF,kBAAME,IAAoB,8BACpBC,IAAwB;AAGnB,YAAAR,EAAA;AAAA,cACT,GAAGC,EAAYM,CAAiB,CAAC,eAAe,KAAK;AAAA,gBACnDH;AAAA,cAAA,CACD;AAAA,YACH,GAGWJ,EAAA;AAAA,cACT,GAAGC,EAAYO,CAAqB,CAAC,eAAe,KAAK;AAAA,gBACvDL;AAAA,cAAA,CACD;AAAA,YACH;AAAA,mBACO7E,GAAG;AAEF,oBAAA;AAAA,cACN;AAAA,cACAA;AAAA,YACF;AAAA,UAAA;AAGK,iBAAA;AAAA,YACL,SAAS,MAAM;;AACT,gBAAAx6B,IAAAqE,EAAO,oBAAP,gBAAArE,EAAwB,iBAAgB,aACnCqE,EAAA,gBAAgB,KAAK,YAAY26B,CAAO,KAE/C/+B,IAAAoE,EAAO,oBAAP,QAAApE,EAAwB,KAAK,KAAK,YAAY++B;AAAA,YAChD;AAAA,UAEJ;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,aAAa,CAACx1B,MAAU;AAChB,kBAAA,EAAE,KAAAxB,GAAK,WAAA6W,EAAA,IAAcrV;AAW3B,gBATI,CAACnF,EAAO,cAIR,CAACwa,EAAU,SAKXA,EAAU,MAAM,OAAO,KAAK,KAAK;AACnC;AAGF,kBAAM8gB,IAAO,CAAC;AAId,YAAIn2B,EAAM,IAAI,QAAQ,SAAS,KACxBm2B,EAAA;AAAA,cACH/G,EAAW,KAAK,GAAG,GAAG;AAAA,gBACpB,4BAA4B;AAAA,cAC7B,CAAA;AAAA,YACH;AAGF,kBAAM3wB,IAAO4W,EAAU,SACjBje,IAAOqH,EAAK;AAEd,gBAAArH,EAAK,QAAQ,SAAS,GAAG;AACrB,oBAAA0rB,IAASrkB,EAAK,OAAO;AAEtB,cAAA03B,EAAA;AAAA,gBACH/G,EAAW,KAAKtM,GAAQA,IAAS1rB,EAAK,UAAU;AAAA,kBAC9C,6BAA6B;AAAA,gBAC9B,CAAA;AAAA,cACH;AAAA,YAAA;AAGK,mBAAA43B,EAAc,OAAOxwB,GAAK23B,CAAI;AAAA,UAAA;AAAA,QACvC;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ;AC7IA,MAAMhc,KAAa,IAAInkB,EAAU,iBAAiB,GAE5CogC,KAAyC;AAAA;AAAA,EAE7C,OAAO;AAAA;AAAA,EAEP,OAAO;AAAA;AAAA,EAEP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,gBAAgB;AAClB;AAUO,MAAMC,WAAgChK,EAAmB;AAAA,EAC9D,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,cAAc;AACN,UAAA;AACF,QAAAiK;AACC,SAAA;AAAA,MACH,IAAIvgC,EAAO;AAAA,QACT,KAAKokB;AAAAA,QACL,KAAKoc,GAAa;AACT,iBAAA;AAAA,YACL,QAAQ,OAAO3+B,GAAM4+B,MAAe;;AAC9B,gBAAAhgC,IAAA,KAAK,QAAL,gBAAAA,EAAU,SAASoB,EAAK,OAAO,cAAc,QAAO,MAGtD0+B,IAAU,WAAW,MAAM;AACpB,gBAAA1+B,EAAA;AAAA,kBACHA,EAAK,MAAM,GAAG,QAAQuiB,IAAY,EAAE,aAAa,GAAM,CAAA;AAAA,gBACzD;AAAA,iBACC,CAAC;AAAA,YAER;AAAA,YACA,SAAS,MAAM;AACb,cAAImc,KACF,aAAaA,CAAO;AAAA,YACtB;AAAA,UAEJ;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,OAAO;AACE,mBAAA;AAAA;AAAA,cAEL,8BAA8B,CAAC;AAAA;AAAA,cAE/B,iCAAiC,CAAC;AAAA;AAAA,cAElC,mCAAmB,IAAY;AAAA,YACjC;AAAA,UACF;AAAA,UAEA,MAAMjgC,GAAao6B,GAAMv6B,GAAUC,GAAU;AAIvC,gBAHJs6B,EAAK,kCAAkC,CAAC,GACxCA,EAAK,cAAc,MAAM,GAErB,CAACp6B,EAAY,cAAcH,EAAS,IAAI,GAAGC,EAAS,GAAG;AAClD,qBAAAs6B;AAuBT,kBAAMgG,IAA0C,CAAC,GAE3CC,IAAWC;AAAA,cACfzgC,EAAS;AAAA,cACT,CAACkB,MAASA,EAAK,MAAM;AAAA,YACvB,GACMw/B,IAAe,IAAI;AAAA,cACvBF,EAAS,IAAI,CAACt/B,MAAS,CAACA,EAAK,KAAK,MAAM,IAAIA,CAAI,CAAC;AAAA,YACnD,GACMF,IAAWy/B;AAAA,cACfxgC,EAAS;AAAA,cACT,CAACiB,MAASA,EAAK,MAAM;AAAA,YACvB;AAGA,uBAAWA,KAAQF,GAAU;AAC3B,oBAAM2/B,IAAUD,EAAa,IAAIx/B,EAAK,KAAK,MAAM,EAAE,GAE7C0/B,IAAiBD,KAAA,gBAAAA,EAAS,KAAK,YAC/BE,IAAiB3/B,EAAK,KAAK;AAE7B,kBAAAy/B,KAAWC,KAAkBC,GAAgB;AAC/C,sBAAMC,IAAW;AAAA,kBACf,OAAOD,EAAe,MAAM;AAAA,kBAC5B,OAAOA,EAAe,MAAM;AAAA,kBAC5B,MAAMA,EAAe,KAAK;AAAA,kBAC1B,OAAO5gC,EAAS,IAAI,QAAQiB,EAAK,GAAG,EAAE;AAAA,gBACxC;AAEA,oBAAI6/B,IAAW;AAAA,kBACb,OAAOH,EAAe,MAAM;AAAA,kBAC5B,OAAOA,EAAe,MAAM;AAAA,kBAC5B,MAAMA,EAAe,KAAK;AAAA,kBAC1B,OAAO5gC,EAAS,IAAI,QAAQ2gC,EAAQ,GAAG,EAAE;AAAA,gBAC3C;AAEA,gBAAAJ,EAAwCr/B,EAAK,KAAK,MAAM,EAAE,IACxD6/B,GASE5gC,EAAY,QAAQ,sBAAsB,MAGxCe,EAAK,KAAK,MAAM,MAAMq5B,EAAK,iCAC7BwG,IACExG,EAAK,6BAA6Br5B,EAAK,KAAK,MAAM,EAAE,IAKpD4/B,EAAS,SAAS,uBACpBC,EAAS,QAAQD,EAAS,SAI9BvG,EAAK,gCAAgCr5B,EAAK,KAAK,MAAM,EAAE,IACrD6/B,GAGE,KAAK,UAAUA,CAAQ,MAAM,KAAK,UAAUD,CAAQ,MACrDC,EAAiB,cAAc,IAC9BA,EAAS,QAAQD,EAAS,OAY5BvG,EAAK,cAAc,IAAIr5B,EAAK,KAAK,MAAM,EAAE;AAAA,cAC3C;AAAA,YACF;AAGF,mBAAAq5B,EAAK,+BACHgG,GAEKhG;AAAA,UAAA;AAAA,QAEX;AAAA,QACA,OAAO;AAAA,UACL,YAAYzwB,GAAO;AACX,kBAAAkwB,IAAe,KAAgB,SAASlwB,CAAK;AAC/C,gBAAAkwB,EAAY,cAAc,SAAS;AAC9B;AAGT,kBAAMhB,IAA4B,CAAC;AAEnC,mBAAAlvB,EAAM,IAAI,YAAY,CAAC5I,GAAMI,MAAQ;AAKnC,kBAJI,CAACJ,EAAK,MAAM,MAIZ,CAAC84B,EAAY,cAAc,IAAI94B,EAAK,MAAM,EAAE;AAC9C;AAGF,oBAAM8/B,IACJhH,EAAY,gCAAgC94B,EAAK,MAAM,EAAE,GACrD+/B,IAAuB,CAAC;AAE9B,yBAAW,CAACC,GAAUh+B,CAAG,KAAK,OAAO,QAAQ89B,CAAS;AACpD,gBAAAC,EAAgB,eAAef,GAAegB,CAAQ,CAAC,IACrDh+B,KAAO;AASX,oBAAMi+B,IAAajI,EAAW,KAAK53B,GAAKA,IAAMJ,EAAK,UAAU;AAAA,gBAC3D,GAAG+/B;AAAA,cAAA,CACJ;AAED,cAAAjI,EAAY,KAAKmI,CAAU;AAAA,YAAA,CAC5B,GAEMrI,EAAc,OAAOhvB,EAAM,KAAKkvB,CAAW;AAAA,UAAA;AAAA,QACpD;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ;ACpOA,MAAM/U,KAAa,IAAInkB,EAAU,0BAA0B;AAOpD,MAAMshC,WAA4BjL,EAAmB;AAAA,EAOnD,YAA6BxxB,GAAwC;AACpE,UAAA;AAHA,IAAAylB,EAAA,iBAAU;AAEkB,SAAA,SAAAzlB,GAE7B,KAAA;AAAA,MACH,IAAI9E,EAAO;AAAA,QACT,KAAKokB;AAAA,QACL,OAAO;AAAA,UACL,aAAa,CAACna,MAAU;AAChB,kBAAA,EAAE,KAAAxB,GAAK,WAAA6W,EAAA,IAAcrV;AAEvB,gBAAA,CAAC,KAAK;AACR,qBAAOgvB,EAAc;AAGvB,kBAAMuI,IAAMnI,EAAW,OAAO/Z,EAAU,MAAMA,EAAU,IAAI;AAAA,cAC1D,uBAAuB;AAAA,YAAA,CACxB;AAED,mBAAO2Z,EAAc,OAAOxwB,GAAK,CAAC+4B,CAAG,CAAC;AAAA,UAAA;AAAA,QACxC;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA3BF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA6BF,WAAWC,GAAkB;AAC9B,IAAA,KAAK,YAAYA,MAIrB,KAAK,UAAUA,GAEV,KAAA,OAAO,SAAS,CAACjhC,MAAOA,EAAG,QAAQ4jB,IAAY,CAAA,CAAE,CAAC;AAAA,EAAA;AAAA,EAGlD,aAAa;AAClB,WAAO,KAAK;AAAA,EAAA;AAEhB;ACtDgB,SAAAsd,GACd/hC,GACAkC,GACA;;AAEE,SAAAlC,KACAA,EAAQ,iBACRA,EAAQ,kBAAkBkC,EAAK,SAC/BpB,IAAAd,EAAQ,iBAAR,gBAAAc,EAAA,KAAAd,GAAuB,uBAAsB;AAE7C,IAAAA,IAAUA,EAAQ;AAEpB,QAAIe,IAAAf,EAAQ,iBAAR,gBAAAe,EAAA,KAAAf,GAAuB,uBAAsB;AAGjD,WAAO,EAAE,MAAMA,GAAwB,IAAIA,EAAQ,aAAa,SAAS,EAAG;AAC9E;ACFO,MAAMgiC,WAA8BC,GAAU;AAAA,EAGnD,YAAYC,GAAsBC,GAAoB;AACpD,UAAMD,GAASC,CAAK;AAHtB,IAAAvX,EAAA;AAMQ,UAAAqD,IAAaiU,EAAQ,KAAK;AAEhC,SAAK,QAAQ,CAAC,GACNA,EAAA,IAAI,aAAaA,EAAQ,KAAKC,EAAM,KAAK,CAACzgC,GAAM0gC,GAAMxnB,MAAW;AACvE,UAAIA,MAAW,QAAQA,EAAO,GAAGqT,CAAU;AACpC,oBAAA,MAAM,KAAKvsB,CAAI,GACb;AAAA,IAET,CACD;AAAA,EAAA;AAAA,EAGH,OAAO,OAAOoH,GAAW+K,GAAcC,IAAKD,GAA6B;AAChE,WAAA,IAAImuB,GAAsBl5B,EAAI,QAAQ+K,CAAI,GAAG/K,EAAI,QAAQgL,CAAE,CAAC;AAAA,EAAA;AAAA,EAGrE,UAAiB;AACR,WAAA,IAAInR,EAAMD,EAAS,KAAK,KAAK,KAAK,GAAG,GAAG,CAAC;AAAA,EAAA;AAAA,EAGlD,GAAGid,GAA+B;AAShC,QARI,EAAEA,aAAqBqiB,OAIvB,KAAK,MAAM,WAAWriB,EAAU,MAAM,UAItC,KAAK,SAASA,EAAU,QAAQ,KAAK,OAAOA,EAAU;AACjD,aAAA;AAGT,aAASja,IAAI,GAAGA,IAAI,KAAK,MAAM,QAAQA;AACjC,UAAA,CAAC,KAAK,MAAMA,CAAC,EAAE,GAAGia,EAAU,MAAMja,CAAC,CAAC;AAC/B,eAAA;AAIJ,WAAA;AAAA,EAAA;AAAA,EAGT,IAAIoD,GAAWzH,GAA8B;AAC3C,UAAMghC,IAAahhC,EAAQ,UAAU,KAAK,IAAI,GACxCihC,IAAWjhC,EAAQ,UAAU,KAAK,EAAE;AAE1C,WAAIihC,EAAS,UACJL,GAAU,KAAKn5B,EAAI,QAAQu5B,EAAW,GAAG,CAAC,IAG/CA,EAAW,UACNJ,GAAU,KAAKn5B,EAAI,QAAQw5B,EAAS,GAAG,CAAC,IAG1C,IAAIN;AAAA,MACTl5B,EAAI,QAAQu5B,EAAW,GAAG;AAAA,MAC1Bv5B,EAAI,QAAQw5B,EAAS,GAAG;AAAA,IAC1B;AAAA,EAAA;AAAA,EAGF,SAAc;AACL,WAAA,EAAE,MAAM,iBAAiB,QAAQ,KAAK,QAAQ,MAAM,KAAK,KAAK;AAAA,EAAA;AAEzE;AAEAL,GAAU,OAAO,iBAAiBD,EAAqB;ACtEvD,IAAIO;AAWJ,SAASC,GAA4B7iB,GAAsB7W,GAAW;AAIhE,MAAA25B,GACAC;AAOE,QAAAC,IACJ75B,EAAI,QAAQ6W,EAAU,IAAI,EAAE,OAAO,KAAK,KAAK,UAAU,gBACnDijB,IACJ95B,EAAI,QAAQ6W,EAAU,EAAE,EAAE,OAAO,KAAK,KAAK,UAAU,gBAGjDkjB,IAAW,KAAK,IAAIljB,EAAU,QAAQ,OAAOA,EAAU,MAAM,KAAK;AAExE,MAAIgjB,KAAgCC,GAA4B;AAI9D,UAAME,IAAqBnjB,EAAU,MAAM,MAAMkjB,IAAW,CAAC,GACvDE,IAAkBpjB,EAAU,IAAI,IAAIkjB,IAAW,CAAC;AAGtD,IAAAJ,IAAsB35B,EAAI,QAAQg6B,IAAqB,CAAC,EAAE,KAC1DJ,IAAoB55B,EAAI,QAAQi6B,IAAkB,CAAC,EAAE;AAAA,EAAA;AAErD,IAAAN,IAAsB9iB,EAAU,MAChC+iB,IAAoB/iB,EAAU;AAGhC,SAAO,EAAE,MAAM8iB,GAAqB,IAAIC,EAAkB;AAC5D;AAEA,SAASM,GAAa9gC,GAAkB2R,GAAcC,IAAKD,GAAM;AAC/D,EAAIA,MAASC,MAELA,KAAA5R,EAAK,MAAM,IAAI,QAAQ2R,IAAO,CAAC,EAAE,OAAO;AAIhD,QAAMovB,IAAc/gC,EAAK,SAAS2R,CAAI,EAAE,KAAK,UAAU,EAAI,GACrD+G,IAAS1Y,EAAK,SAAS2R,CAAI,EAAE,MAE7BqvB,IAAkB,CAACC,GAAwB3nB,MAC/C,MAAM,UAAU,QAAQ,KAAK2nB,EAAc,UAAU3nB,CAAa,GAE9D4nB,IAA0BF;AAAA,IAC9BtoB;AAAA;AAAA,IAEA1Y,EAAK,SAAS2R,IAAO,CAAC,EAAE,KAAK;AAAA,EAC/B,GACMwvB,IAAyBH;AAAA,IAC7BtoB;AAAA;AAAA,IAEA1Y,EAAK,SAAS4R,IAAK,CAAC,EAAE,KAAK;AAAA,EAC7B;AAEA,WAASpO,IAAIkV,EAAO,oBAAoB,GAAGlV,KAAK,GAAGA;AAC7C,KAAAA,IAAI29B,KAA0B39B,IAAI09B,MACpCH,EAAY,YAAYA,EAAY,SAASv9B,CAAC,CAAC;AAKnD,EAAA49B,GAAephC,EAAK,IAAI,GACLqgC,IAAAU;AAKb,QAAAM,IAAUhB,EAAiB,qBAAqB,QAAQ;AAC9D,WAAS78B,IAAI,GAAGA,IAAI69B,EAAQ,QAAQ79B,KAAK;AACjC,UAAA89B,IAASD,EAAQ79B,CAAC,GAClBkV,IAAS4oB,EAAO;AAEtB,IAAI5oB,KACFA,EAAO,YAAY4oB,CAAM;AAAA,EAC3B;AAMF,QAAMC,IADUvhC,EAAK,IAAI,UAAU,MAAM,GAAG,EAEzC;AAAA,IACC,CAACiX,MACCA,MAAc,iBACdA,MAAc,aACdA,MAAc;AAAA,EAAA,EAEjB,KAAK,GAAG;AAEMopB,EAAAA,EAAA,YACfA,EAAiB,YAAY,sBAAsBkB,GAEjDvhC,EAAK,gBAAgB,aAClBA,EAAA,KAAK,YAAYqgC,CAAgB,IAEjCrgC,EAAA,KAAK,KAAK,YAAYqgC,CAAgB;AAE/C;AAEO,SAASe,GAAeI,GAA+B;AAC5D,EAAInB,MAAqB,WACnBmB,aAAkB,aACpBA,EAAO,YAAYnB,CAAgB,IAE5BmB,EAAA,KAAK,YAAYnB,CAAgB,GAGvBA,IAAA;AAEvB;AAEgB,SAAAoB,GAKd,GACAz+B,GACAC,GACA;AACI,MAAA,CAAC,EAAE;AACL;AAGF,QAAMjD,IAAOiD,EAAO;AACpB,MAAI,CAACjD;AACH;AAGF,QAAMiI,IAAUqL,EAAYtQ,EAAM,IAAIhD,EAAK,MAAM,GAAG;AACpD,MAAI,CAACiI;AACH,UAAM,IAAI,MAAM,iBAAiBjF,EAAM,EAAE,YAAY;AAEvD,QAAMpD,IAAMqI,EAAQ;AAEpB,MAAIrI,KAAO,MAAM;AACT,UAAA6d,IAAYzd,EAAK,MAAM,WACvB4G,IAAM5G,EAAK,MAAM,KAEjB,EAAE,MAAA2R,GAAM,IAAAC,EAAA,IAAO0uB,GAA4B7iB,GAAW7W,CAAG,GAEzD86B,IAA0B/vB,KAAQ/R,KAAOA,IAAMgS,GAC/C+vB,IACJlkB,EAAU,QAAQ,KAAA,MAAWA,EAAU,MAAM,UAC7CA,aAAqBqiB;AAEvB,IAAI4B,KAA2BC,KACxB3hC,EAAA;AAAA,MACHA,EAAK,MAAM,GAAG,aAAa8/B,GAAsB,OAAOl5B,GAAK+K,GAAMC,CAAE,CAAC;AAAA,IACxE,GACakvB,GAAA9gC,GAAM2R,GAAMC,CAAE,MAEtB5R,EAAA;AAAA,MACHA,EAAK,MAAM,GAAG,aAAaupB,GAAc,OAAOvpB,EAAK,MAAM,KAAKJ,CAAG,CAAC;AAAA,IACtE,GACAkhC,GAAa9gC,GAAMJ,CAAG;AAGxB,UAAMgiC,IAAgB5hC,EAAK,MAAM,UAAU,QAAQ,GAC7CyI,IAASxF,EAAO,UAEhB8wB,IACJ/zB,EAAK,sBAAsB4hC,CAAa,EAAE,IAAI,WAE1C/N,IAAuBvb,GAA2B7P,GAAQxF,CAAM,GAEhEgI,IAASsoB,GAAiBqO,EAAc,OAAO,GAC/CxS,IAAeyE,EAAqB,aAAa5oB,GAAQ,CAAA,CAAE,GAE3DmoB,IAAYnE,GAAoBG,CAAY;AAElD,MAAE,aAAa,UAAU,GACvB,EAAA,aAAa,QAAQ,kBAAkB2E,CAAa,GACpD,EAAA,aAAa,QAAQ,aAAa3E,CAAY,GAC9C,EAAA,aAAa,QAAQ,cAAcgE,CAAS,GAC9C,EAAE,aAAa,gBAAgB,QAC/B,EAAE,aAAa,aAAaiN,GAAmB,GAAG,CAAC;AAAA,EAAA;AAEvD;ACvLA,MAAMwB,KAAiD;AAEvD,SAASC,GACP9hC,GACA6xB,GACAkQ,GACAC,IAAmB,IACnB;AACM,QAAAC,IAAWjiC,EAAK,KAAK;AAAA;AAAA,IAEzB6xB,EAAO,QAAQkQ,MAAsB,WAAW,KAAK;AAAA,IACrDlQ,EAAO;AAAA,EACT;AAEA,aAAW/zB,KAAWmkC;AACpB,QAAKjiC,EAAK,IAAI,SAASlC,CAAO;AAI9B,aAAIkkC,KACalkC,EAAQ,QAAQ,6BAA6B,IAEnDgkC;AAAA,QACL9hC;AAAA,QACA;AAAA,UACE,MAAM6xB,EAAO,OAAO;AAAA;AAAA,UACpB,KAAKA,EAAO;AAAA,QACd;AAAA,QACAkQ;AAAA,QACA;AAAA,MACF,IAGGlC,GAA6B/hC,GAASkC,CAAI;AAGrD;AAEA,SAASkiC,GACPC,GAIAniC,GACA+hC,GAC+C;AAK3C,MAAA,CAAC/hC,EAAK,IAAI;AACZ;AAGF,QAAMoiC,IACJpiC,EAAK,IAAI,WACT,sBAAsB,GAKlB6xB,IAAS;AAAA,IACb,MAAMsQ,EAAS;AAAA,IACf,KAAKA,EAAS;AAAA,EAChB,GAEME,IAAoBxQ,EAAO,OAAOuQ,EAAkB,MACpDE,IAAqBzQ,EAAO,OAAOuQ,EAAkB;AAG3D,EAAIL,MAAsB,eACpBM,MACKxQ,EAAA,OAAOuQ,EAAkB,OAAO,KAGrCE,MACKzQ,EAAA,OAAOuQ,EAAkB,QAAQ;AAI5C,MAAIp/B,IAAQ8+B,GAAmB9hC,GAAM6xB,GAAQkQ,CAAiB;AAE1D,MAAA,CAACO,KAAsBt/B,GAAO;AAW1B,UAAAu/B,IAAOv/B,EAAM,KAAK,sBAAsB;AACvC,IAAA6uB,EAAA,OAAO0Q,EAAK,QAAQ,IAC3Bv/B,IAAQ8+B,GAAmB9hC,GAAM6xB,GAAQ,YAAY,EAAK;AAAA,EAAA;AAGrD,SAAA7uB;AACT;AAKO,MAAMw/B,GAKb;AAAA,EAYE,YACmBv/B,GACA8+B,GACA7J,GACjBC,GACA;AAhBK,IAAAzP,EAAA;AACS,IAAAA,EAAA;AAER,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAED,IAAAA,EAAA,oBAAa;AAEb,IAAAA,EAAA,sBAAe;AAwDtB,IAAAA,EAAA,qBAAc,CAACtgB,MAAwC;AACrD,WAAK,QAAQA,GACR,KAAA,WAAW,KAAK,KAAK;AAAA,IAC5B;AAEA,IAAAsgB,EAAA,iCAA0B,MAAM;;AAC9B,UAAI,KAAK,cAAc,CAAC,KAAK;AAC3B;AAGF,YAAM1lB,IAAQk/B;AAAA,QACZ,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAGA,UAAI,CAACl/B,KAAS,CAAC,KAAK,OAAO,YAAY;AACjC,SAAApE,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IACb,KAAA,YAAY,KAAK,KAAK;AAG7B;AAAA,MAAA;AAIF,WACEC,IAAA,KAAK,UAAL,QAAAA,EAAY,UACZoC,IAAA,KAAK,iBAAL,QAAAA,EAAmB,aAAa,iBAChCC,IAAA,KAAK,iBAAL,gBAAAA,EAAmB,aAAa,gBAAe8B,EAAM;AAErD;AAGF,WAAK,eAAeA,EAAM;AAIpB,YAAAL,IAAeK,EAAM,KAAK;AAEhC,UAAKL,KAOD,KAAK,OAAO,YAAY;AACpB,cAAA8/B,IAA0B9/B,EAAa,sBAAsB,GAC7DmnB,IAAS9mB,EAAM,KAAK,QAAQ,yBAAyB;AAC3D,aAAK,YAAY;AAAA,UACf,MAAM;AAAA,UACN,cAAc,IAAI;AAAA,YAChB8mB;AAAA;AAAA;AAAA;AAAA;AAAA,cAKIA,EAAO,kBAAmB,wBAAwB;AAAA,gBAEhD,KAAK,OAAO,IAAI,WAChB,sBAAwB,EAAA;AAAA,YAC9B2Y,EAAwB;AAAA,YACxBA,EAAwB;AAAA,YACxBA,EAAwB;AAAA,UAC1B;AAAA,UACA,OAAO,KAAK,OAAO;AAAA,YACjB,KAAK,aAAc,aAAa,SAAS;AAAA,UAAA;AAAA,QAC3C,CACD;AAAA,MAAA;AAAA,IAEL;AAEA,IAAA/Z,EAAA,gBAAS,CAACxoB,MAAqB;;AAGzB,UAAA,KAAK,OAAO,aAAa;AAC3B;AAGG,WAAA,OAAO,cAAc,SAAS,KAAK;AAIxC,YAAMwiC,IACJxiC,EAAM,kBAAkB,UACnBtB,IAAAsB,EAAM,kBAAkB,cACrBA,EAAM,SACNA,EAAM,OAAO,kBAFhB,gBAAAtB,EAGE,QAAQ,kBAAiB;AAyChC,UArCE8jC,MAKE,CAAC,KAAK,gBAAgB,KAAK,OAAO,QAAQA,IAI5C,KAAK,OAAO;AAAA,QACV,KAAK,OAAO,MAAM,GAAG;AAAA,UACnBllB,EAAc;AAAA,YACZ,KAAK,OAAO,MAAM,GAAG;AAAA,YACrB,KAAK,OAAO,MAAM,GAAG,UAAU;AAAA,UAAA;AAAA,QACjC;AAAA,MAEJ,IACS,KAAK,gBAAgB,KAAK,OAAO,QAAQklB,KAYlD;AAAA,QACE,MAAM,KAAK,OAAO,SAAS,KAAK,OAAO,MAAM,GAAG,iBAAiB;AAAA,QACjE;AAAA,MACF,IAKF,KAAK,sBAAsB,YAC1BxiC,EAAc,aACf,GAACrB,IAAAqB,EAAM,iBAAN,QAAArB,EAAoB,MAAM,SAAS;AAEpC;AAGI,YAAAe,IAAM,KAAK,OAAO,YAAY;AAAA,QAClC,MAAMM,EAAM;AAAA,QACZ,KAAKA,EAAM;AAAA,MAAA,CACZ;AAED,UAAI,CAACN,KAAOA,EAAI,WAAW,IAAI;AAMvB,cAAA+iC,IAAM,KAAK,qBAAqBziC,CAAK;AAEtC,aAAA,OAAO,IAAI,cAAcyiC,CAAG;AAAA,MAAA;AAAA,IAErC;AAEA,IAAAja,EAAA,mBAAY,MAAM;AAKhB,WAAK,OAAO,WAAW;AAAA,IACzB;AAoBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,qBAAc,CAACxoB,MAAqB;;AAClC,YAAMsY,KAAO5Z,IAAAsB,EAAM,iBAAN,gBAAAtB,EAAoB,QAAQ;AACzC,UAAI,CAAC4Z;AACH;AAGE,UAAA,KAAK,OAAO;AACR,cAAA,IAAI,MAAM,wDAAwD;AAGpE,YAAA1a,IAAU,SAAS,cAAc,KAAK;AAC5C,MAAAA,EAAQ,YAAY0a;AAGd,YAAAhZ,IADSqhB,GAAU,WAAW,KAAK,OAAO,MAAM,MAAM,EACxC,MAAM/iB,GAAS;AAAA,QACjC,SAAS,KAAK,OAAO,MAAM,OAAO,MAAM,WAAc,OAAO;AAAA,MAAA,CAC9D;AAED,WAAK,OAAO,WAAW;AAAA,QACrB,OAAO,IAAI2C,EAAMjB,EAAK,SAAS,GAAG,CAAC;AAAA,QACnC,MAAM;AAAA,MACR;AAAA,IACF;AAOA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAkpB,EAAA,oBAAa,CAACxoB,MAAqB;;AAE/B,UAAA,KAAK,sBAAsB,YAC1BA,EAAc,aACf,GAACtB,IAAAsB,EAAM,iBAAN,QAAAtB,EAAoB,MAAM,SAAS;AAEpC;AAGI,YAAAgB,IAAM,KAAK,OAAO,YAAY;AAAA,QAClC,MAAMM,EAAM;AAAA,QACZ,KAAKA,EAAM;AAAA,MAAA,CACZ;AAEG,UAAA,CAACN,KAAQA,EAAI,WAAW,MAAM,KAAK,OAAO,IAAI,YAAa;AACvD,cAAA+iC,IAAM,KAAK,qBAAqBziC,CAAK;AAEtC,aAAA,OAAO,IAAI,cAAcyiC,CAAG;AAAA,MAAA;AAAA,IAErC;AAEA,IAAAja,EAAA,mBAAY,CAACka,MAA0B;;AACrC,OAAIhkC,IAAA,KAAK,UAAL,QAAAA,EAAY,QAAQ,KAAK,OAAO,gBAElC,KAAK,MAAM,OAAO,IACb,KAAA,WAAW,KAAK,KAAK;AAAA,IAE9B;AAEA,IAAA8pB,EAAA,qBAAc,CAACxoB,MAAsB;;AACnC,UAAI,KAAK;AACP;AAGF,WAAK,WAAW,EAAE,GAAGA,EAAM,SAAS,GAAGA,EAAM,QAAQ;AAIrD,YAAM2iC,IAAyB,KAAK,OAAO,IAAI,sBAAsB,GAC/DC,IACJ,KAAK,SAAS,IAAID,EAAuB,QACzC,KAAK,SAAS,IAAIA,EAAuB,SACzC,KAAK,SAAS,IAAIA,EAAuB,OACzC,KAAK,SAAS,IAAIA,EAAuB,QAGrC1J,IAAgB,KAAK,OAAO,IAAK;AAIvC;AAAA;AAAA,QAEE2J;AAAA,QAEA5iC,KACAA,EAAM;AAAA,QAEN,EACEi5B,MAAkBj5B,EAAM,UACxBi5B,EAAc,SAASj5B,EAAM,MAAqB;AAAA,QAEpD;AACI,SAAAtB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IACb,KAAA,WAAW,KAAK,KAAK;AAG5B;AAAA,MAAA;AAGF,WAAK,wBAAwB;AAAA,IAC/B;AA0DA,IAAA8pB,EAAA,kBAAW,MAAM;;AACX,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,eAAe,KAAK,aAAc,sBAAsB,GAC9D,KAAA,WAAW,KAAK,KAAK;AAAA,IAE9B;AA7YmB,SAAA,SAAAqE,GACA,KAAA,oBAAA8+B,GACA,KAAA,SAAA7J,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,8CAA8C;AAGhE,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GAC0B7J,GAAA,GAG1B,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GAGA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GAKA4J,EAAO,KAAK,iBAAiB,UAAU,KAAK,UAAU,EAAI;AAAA,EAAA;AAAA,EA8RpD,qBAAqBh4B,GAAkB;AAC7C,UAAMyiC,IAAM,IAAI,MAAMziC,EAAM,MAAMA,CAAK,GACjCkiC,IACJ,KAAK,OAAO,IAAI,WAChB,sBAAsB;AACxB,WAAAO,EAAI,UAAUziC,EAAM,SACpByiC,EAAI,UAAUziC,EAAM,SAElBA,EAAM,UAAUkiC,EAAkB,QAClCliC,EAAM,UACJkiC,EAAkB,OAChBA,EAAkB,QAChBP,KAGNc,EAAI,UACFP,EAAkB,OACjBA,EAAkB,QACjBP,KACA,IAEJ3hC,EAAM,UAAUkiC,EAAkB,SAClCliC,EAAM,UACJkiC,EAAkB,QAChBA,EAAkB,QAChBP,KAGNc,EAAI,UACFP,EAAkB,QACjBA,EAAkB,QACjBP,KACA,KAEJ3hC,EAAM,UAAUkiC,EAAkB,QAClCliC,EAAM,UAAUkiC,EAAkB,WAGlCO,EAAI,UACFP,EAAkB,OAClBP,KACEO,EAAkB,QAClB,IAGNO,EAAI,UAAU,KAAK;AAAA,MACjB,KAAK,IAAIziC,EAAM,SAASkiC,EAAkB,GAAG;AAAA,MAC7CA,EAAkB,MAAMA,EAAkB;AAAA,IAC5C,GAEAO,EAAI,eAAeziC,EAAM,cACrByiC,EAAA,iBAAiB,MAAMziC,EAAM,eAAe,GAChDyiC,EAAI,YAAY,IACTA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBT,OAAO1Q,GAAmBoG,GAAwB;;AAE5C,IADe,CAACA,EAAU,IAAI,GAAG,KAAK,OAAO,MAAM,GAAG,OACxCz5B,IAAA,KAAK,UAAL,QAAAA,EAAY,SAC5B,KAAK,wBAAwB;AAAA,EAC/B;AAAA,EAGF,UAAU;;AACJ,KAAAA,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IACb,KAAA,WAAW,KAAK,KAAK,IAE5B,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK,oBAAoB,UAAU,KAAK,UAAU,EAAI;AAAA,EAAA;AAEtE;AAEa,MAAAmkC,KAAoB,IAAI3kC,EAAU,gBAAgB;AAExD,MAAM4kC,WAIHvO,EAAmB;AAAA,EAO3B,YACmBxxB,GACjB8+B,GACA;AACM,UAAA;AAND,IAAArZ,EAAA;AAgCP;AAAA;AAAA;AAAA,IAAAA,EAAA,wBAAiB,CACfxoB,GAIA8C,MACG;AACH,MAAI,KAAK,SACP,KAAK,KAAK,eAAe,KAGjBy+B,GAAAvhC,GAAO8C,GAAO,KAAK,MAAM;AAAA,IACrC;AAKA;AAAA;AAAA;AAAA,IAAA0lB,EAAA,sBAAe,MAAM;AACf,MAAA,KAAK,OAAO,mBACC0Y,GAAA,KAAK,OAAO,gBAAgB,IAAI,GAG7C,KAAK,SACP,KAAK,KAAK,eAAe;AAAA,IAE7B;AAMA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA1Y,EAAA,oBAAa,MAAM;AACjB,WAAK,KAAM,aAAa,IACnB,KAAA,KAAM,MAAO,OAAO,IACzB,KAAK,KAAM,WAAW,KAAK,KAAM,KAAM;AAAA,IACzC;AAMA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,sBAAe,MAAM;AACnB,WAAK,KAAM,aAAa,IACnB,KAAA,KAAM,MAAO,OAAO,IACzB,KAAK,KAAM,WAAW,KAAK,KAAM,KAAM;AAAA,IACzC;AA1EmB,SAAA,SAAAzlB,GAIZ,KAAA;AAAA,MACH,IAAI9E,EAAO;AAAA,QACT,KAAK4kC;AAAA,QACL,MAAM,CAACnK,OACL,KAAK,OAAO,IAAI4J;AAAA,UACdv/B;AAAA,UACA8+B;AAAA,UACAnJ;AAAA,UACA,CAACxwB,MAAU;AACJ,iBAAA,KAAK,UAAUA,CAAK;AAAA,UAAA;AAAA,QAE7B,GACO,KAAK;AAAA,MAEf,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA1BF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA4BF,SAASosB,GAAyD;AAChE,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAoDrC;ACxqBA,MAAMyO,yBAAsB,IAA6C;AAKzE,SAASC,GAAWjgC,GAAwC;AACtD,MAAAggC,GAAgB,IAAIhgC,CAAM;AAErB,WAAAggC,GAAgB,IAAIhgC,CAAM;AAE7B,QAAA9D,IAAU,IAAIgkC,GAAQ;AAC5B,SAAAlgC,EAAO,cAAc,GAAG,eAAe,CAAC,EAAE,aAAAxE,QAAkB;AAClD,IAAAU,EAAA,cAAcV,EAAY,OAAO;AAAA,EAAA,CAC1C,GACMwE,EAAA,cAAc,GAAG,WAAW,MAAM;AAEvC,IAAAggC,GAAgB,OAAOhgC,CAAM;AAAA,EAAA,CAC9B,GAGeggC,GAAA,IAAIhgC,GAAQ9D,CAAO,GAE5BA;AACT;AAaO,SAASikC,GAIdngC,GAIAgE,GAIAo8B,IAAyB,QACX;AACd,QAAMC,IAAmBxL,GAAe;AAAA,IACtC70B,EAAO,cAAc;AAAA,EACvB;AAKA,MAAI,CAACqgC,GAAkB;AAGf,UAAAnkC,IAAU+jC,GAAWjgC,CAAM,GAG3BsgC,IAAmBpkC,EAAQ,KAAK;AAEtC,WAAO,MACOA,EAET,MAAMokC,CAAgB,EACtB,IAAIt8B,GAAUo8B,MAAS,SAAS,KAAK,CAAC;AAAA,EAG3C;AAGF,QAAMG,IAAmBC;AAAA;AAAA,IAEvBx8B,KAAYo8B,MAAS,UAAU,IAAI;AAAA,IACnCC,EAAiB,QAAQ;AAAA,IACzBA,EAAiB,QAAQ;AAAA,EAC3B;AAEA,SAAO,MAAM;AACX,UAAMI,IAAsB5L,GAAe;AAAA,MACzC70B,EAAO,cAAc;AAAA,IACvB,GACMrD,IAAM+jC;AAAA,MACVD,EAAoB;AAAA,MACpBA,EAAoB,QAAQ;AAAA,MAC5BF;AAAA,MACAE,EAAoB,QAAQ;AAAA,IAC9B;AAGA,QAAI9jC,MAAQ;AACJ,YAAA,IAAI,MAAM,4CAA4C;AAGvD,WAAAA,KAAOyjC,MAAS,UAAU,KAAK;AAAA,EACxC;AACF;ACnGA,MAAMO,KAAYC,GAAe,CAACrkC,MAASA,EAAK,KAAK,SAAS,gBAAgB;AAO9E,MAAMskC,GAIJ;AAAA,EAMA,YACmB7gC,GACjBk1B,GACA;AARK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AACC,IAAAA,EAAA;AACR,IAAAA,EAAA;AA2BA,IAAAA,EAAA,sBAAe,MAAM;;AACf,WAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,MAAM;AACd,cAAAmlC,KAAiBllC,IAAA,KAAK,WAAL,gBAAAA,EAAa;AAAA,UAClC,wBAAwB,KAAK,YAAa,YAAY;AAAA;AAExD,YAAI,CAACklC;AACH;AAEG,aAAA,MAAM,eAAeA,EAAe,sBAAsB,GAC1D,KAAA,WAAW,KAAK,YAAa,gBAAiB;AAAA,MAAA;AAAA,IAEvD;AAiDA,IAAArb,EAAA,mBAAY,MAAM;AACX,WAAA,OAAO,SAAS,CAAC/pB,MAAOA,EAAG,QAAQqlC,IAAyB,IAAI,CAAC;AAAA,IACxE;AAEA,IAAAtb,EAAA,oBAAa,MAAM;AACb,MAAA,KAAK,gBAAgB,UAIzB,KAAK,OAAO,cACT,MAAA,EACA,QAEA,YAAY;AAAA,QACX,MACE,KAAK,YAAY,cAAc,KAC9B,KAAK,YAAY,yBACd,KAAK,YAAY,iBAAkB,SACnC;AAAA,QACN,IAAI,KAAK,OAAO,SAAS,CAAC/pB,MAAOA,EAAG,UAAU,IAAI;AAAA,MACnD,CAAA,EACA,IAAI;AAAA,IACT;;AA1GmB,SAAA,SAAAsE,GAGjB,KAAK,cAAc,QAEd,KAAA,aAAa,CAACghC,MAAqB;;AAClC,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,qDAAqD;AAGvE,MAAA9L,EAAW8L,GAAU;AAAA,QACnB,GAAG,KAAK;AAAA,QACR,oBAAmBrlC,IAAA,KAAK,gBAAL,gBAAAA,EAAkB;AAAA,MAAA,CACtC;AAAA,IACH,GAEK,KAAA,UAASA,IAAA,KAAK,OAAO,oBAAZ,gBAAAA,EAA6B,OAK3CC,IAAA,KAAK,WAAL,QAAAA,EAAa,iBAAiB,UAAU,KAAK,cAAc;AAAA,EAAI;AAAA,EAgBjE,OAAOmB,GAAkBq4B,GAAwB;;AACzC,UAAAQ,IACJmL,GAAwB,SAAS3L,CAAS,GACtC6L,IAA8BF,GAAwB;AAAA,MAC1DhkC,EAAK;AAAA,IACP,GAGMmkC,IAAUtL,MAAS,UAAaqL,MAAS,QACzCE,IAAUvL,MAAS,UAAaqL,MAAS;AAI/C,QAAI,CAACC,KAAW,EAHAtL,MAAS,UAAaqL,MAAS,WAGnB,CAACE;AAC3B;AAKF,QAFK,KAAA,cAAcA,IAAUvL,IAAOqL,GAEhCE,KAAW,CAAC,KAAK,OAAO,YAAY;AACtC,MAAI,KAAK,UACP,KAAK,MAAM,OAAO,KAEf,KAAA,WAAW,KAAK,YAAa,gBAAgB;AAElD;AAAA,IAAA;AAGI,UAAAL,KAAiBnlC,IAAA,KAAK,WAAL,gBAAAA,EAAa;AAAA,MAClC,wBAAwB,KAAK,YAAa,YAAY;AAAA;AAGpD,IAAA,KAAK,OAAO,cAAcmlC,MAC5B,KAAK,QAAQ;AAAA,MACX,MAAM;AAAA,MACN,cAAcA,EAAe,sBAAsB;AAAA,MACnD,OAAO,KAAK,YAAa;AAAA,IAC3B,GAEK,KAAA,WAAW,KAAK,YAAa,gBAAiB;AAAA,EACrD;AAAA,EAGF,UAAU;;AACR,KAAAnlC,IAAA,KAAK,WAAL,QAAAA,EAAa,oBAAoB,UAAU,KAAK,cAAc;AAAA,EAAI;AA0BtE;AAaA,MAAMolC,KAA0B,IAAI5lC,EAAU,sBAAsB;AAY7D,MAAMimC,WAIH5P,EAAmB;AAAA,EAQ3B,YAAYxxB,GAAwC;AAC5C,UAAA;AAJA,IAAAylB,EAAA;AACA,IAAAA,EAAA,2BAA8B,CAAC;AAmMvC,IAAAA,EAAA,6BAAsB,CAAC4b,MAA6B;AAC7C,WAAA,kBAAkB,KAAKA,CAAgB;AAAA,IAC9C;AAGA;AAAA,IAAA5b,EAAA,gCAAyB,CAAC4b,MAA6B;AAChD,WAAA,oBAAoB,KAAK,kBAAkB;AAAA,QAC9C,CAACliC,MAAMA,MAAMkiC;AAAA,MACf;AAAA,IACF;AAEA,IAAA5b,EAAA,mBAAY,MAAM,KAAK,KAAM,UAAU;AAEvC,IAAAA,EAAA,oBAAa,MAAM,KAAK,KAAM,WAAW;AA5MvC,UAAM6b,IAAoB,KAAK;AAC1B,SAAA;AAAA,MACH,IAAIpmC,EAAO;AAAA,QACT,KAAK6lC;AAAA,QAEL,MAAM,OACJ,KAAK,OAAO,IAAIF;AAAA,UACd7gC;AAAA,UACA,CAACqhC,GAAkBl8B,MAAU;AAC3B,iBAAK,KAAK,UAAUk8B,CAAgB,IAAIl8B,CAAK;AAAA,UAAA;AAAA,QAEjD,GACO,KAAK;AAAA,QAGd,OAAO;AAAA;AAAA,UAEL,OAA8B;AAAA,UAE9B;AAAA;AAAA,UAGA,OAAO,CACL3J,GACAo6B,GACAnW,GACAnkB,MAC0B;AAO1B,gBALIE,EAAY,QAAQ,qBAAqB,MAAM,UAK/CA,EAAY,UAAU,MAAM,OAAO,KAAK,KAAK;AACxC,qBAAAo6B;AAKH,kBAAA2L,IAIK/lC,EAAY,QAAQulC,EAAuB;AAEtD,gBACE,OAAOQ,KAAoC,YAC3CA,MAAoC,MACpC;AACA,cAAI3L,KAEF,KAAK,UAAU;AAEjB,oBAAM4L,IAAkBrB;AAAA,gBACtBngC;AAAA,gBACA1E,EAAS,UAAU;AAAA,gBAEjBimC,EAAgC,iBAAiB;AAAA,cACrD;AACO,qBAAA;AAAA,gBACL,kBACEA,EAAgC;AAAA,gBAClC,wBACEA,EAAgC,2BAChC;AAAA;AAAA,gBAEF,eAAe,MACbC,EAAgB,IAChBD,EAAgC,iBAAiB;AAAA,gBACnD,OAAO;AAAA,gBACP,cAAc,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,UAAU,CAAC;AAAA,gBAC1D,mBACEA,KAAA,gBAAAA,EAAiC;AAAA,cACrC;AAAA,YAAA;AAIF,gBAAI3L,MAAS;AACJ,qBAAAA;AAIT;AAAA;AAAA,cAEEt6B,EAAS,UAAU,SAASA,EAAS,UAAU;AAAA,cAE/CimC,MAAoC;AAAA;AAAA,cAGpC/lC,EAAY,QAAQ,OAAO,KAC3BA,EAAY,QAAQ,MAAM,KAC1BA,EAAY,QAAQ,SAAS;AAAA,cAE5Bo6B,EAAK,qBAAqB,UACzBt6B,EAAS,UAAU,OAAOs6B,EAAK,cAAc;AAAA,cAE/C,CAACt6B,EAAS,UAAU,MAAM;AAAA,gBACxBA,EAAS,IAAI,QAAQs6B,EAAK,cAAe,CAAA;AAAA,cAAA;AAAA;AAGpC;AAGH,kBAAAqL,IAAO,EAAE,GAAGrL,EAAK;AAGlB,mBAAAqL,EAAA,QAAQ3lC,EAAS,IAAI;AAAA,cACxBs6B,EAAK,cAAc;AAAA,cACnBt6B,EAAS,UAAU;AAAA,YACrB,GAEO2lC;AAAA,UAAA;AAAA,QAEX;AAAA,QAEA,OAAO;AAAA,UACL,gBAAgBlkC,GAAM0kC,GAAOC,GAAKxyB,GAAM;AAClC,mBAAAoyB,EAAkB,SAASpyB,CAAI,KACjCnS,EAAK,SAASA,EAAK,MAAM,GAAG,WAAWmS,CAAI,CAAC,GACvCnS,EAAA;AAAA,cACHA,EAAK,MAAM,GACR,QAAQgkC,IAAyB;AAAA,gBAChC,kBAAkB7xB;AAAA,cACnB,CAAA,EACA,eAAe;AAAA,YACpB,GAEO,MAEF;AAAA,UACT;AAAA;AAAA,UAGA,YAAY/J,GAAO;AACX,kBAAAw8B,IACJ,KACA,SAASx8B,CAAK;AAEhB,gBAAIw8B,MAA0B;AACrB,qBAAA;AAKL,gBAAA,CAACA,EAAsB,wBAAwB;AAC3C,oBAAAC,IAAYjB,GAAUx7B,EAAM,SAAS;AAC3C,kBAAIy8B;AACK,uBAAAzN,EAAc,OAAOhvB,EAAM,KAAK;AAAA,kBACrCovB,EAAW;AAAA,oBACTqN,EAAU;AAAA,oBACVA,EAAU,MAAMA,EAAU,KAAK;AAAA,oBAC/B;AAAA,sBACE,UAAU;AAAA,sBACV,OAAO;AAAA,sBACP,sBAAsBD,EAAsB;AAAA,oBAAA;AAAA,kBAC9C;AAAA,gBACF,CACD;AAAA,YACH;AAGK,mBAAAxN,EAAc,OAAOhvB,EAAM,KAAK;AAAA,cACrCovB,EAAW;AAAA,gBACToN,EAAsB,cAAA,IACpBA,EAAsB,iBAAkB;AAAA,gBAC1CA,EAAsB,cAAc;AAAA,gBACpC;AAAA,kBACE,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,sBAAsBA,EAAsB;AAAA,gBAAA;AAAA,cAC9C;AAAA,YACF,CACD;AAAA,UAAA;AAAA,QACH;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA1LF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA4LF,SACLN,GACA9P,GACA;AACA,WAAK,KAAK,kBAAkB,SAAS8P,CAAgB,KACnD,KAAK,oBAAoBA,CAAgB,GAGpC,KAAK,GAAG,UAAUA,CAAgB,IAAI9P,CAAQ;AAAA,EAAA;AAAA,EAkBvD,IAAW,QAAQ;;AACV,aAAA31B,KAAAD,IAAA,KAAK,SAAL,gBAAAA,EAAW,UAAX,gBAAAC,EAAkB,SAAQ;AAAA,EAAA;AAErC;AAEgB,SAAAimC,GAId7hC,GAAwCqhC,GAA0B;AAC3D,EAAArhC,EAAA,gBAAgB,oBAAoBqhC,CAAgB;AAC7D;ACnYa,MAAAS,KAAoBz3B,GAAK,OAAO;AAAA,EAC3C,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AAAA,EACV,gBAAgB;AACP,WAAA;AAAA,MACL,IAAI,EAAE,SAAS,MAAM,UAAU,SAAS;AAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EACA,iBAAiB8W,GAAW;AACtB,WAAAA,EAAU,SAAS,cACd,CAAC,IAEH;AAAA,MACL,iBAAiB;AAAA,MACjB,WAAW;AAAA,MAEX,MAAM7Z,GAAMy6B,GAAQ;AACX,eAAA;AAAA,UACL;AAAA,UACA;AAAA,YACE,WAAW,OAAOz6B,EAAK,MAAM,EAAK;AAAA,YAClC,eAAe,OAAOy6B,CAAM;AAAA,YAC5B,GAAI,CAACA,KAAU,EAAE,OAAO,oBAAoB;AAAA;AAAA,UAC9C;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR;AAAA,UACE,KAAK;AAAA,UACL,SAASxlC,GAAM;AACb,mBAAKA,EAAK,QAAQ,KAGX;AAAA,cACL,IAAI,SAASA,EAAK,QAAQ,IAAO,EAAE;AAAA,YACrC,IAJS;AAAA,UAIT;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC,GAEYylC,KAAuB33B,GAAK,OAAO;AAAA,EAC9C,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AAAA,EACV,gBAAgB;AACP,WAAA;AAAA,MACL,IAAI,EAAE,SAAS,MAAM,UAAU,SAAS;AAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EACA,iBAAiB8W,GAAW;AACtB,WAAAA,EAAU,SAAS,aACd,CAAC,IAEH;AAAA,MACL,iBAAiB;AAAA,MACjB,WAAW;AAAA;AAAA;AAAA;AAAA,MAKX,MAAM7Z,GAAMy6B,GAAQ;AACX,eAAA;AAAA,UACL;AAAA,UACA;AAAA,YACE,WAAW,OAAOz6B,EAAK,MAAM,EAAK;AAAA,YAClC,eAAe,OAAOy6B,CAAM;AAAA,YAC5B,GAAI,CAACA,KAAU,EAAE,OAAO,oBAAoB;AAAA;AAAA,UAC9C;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR;AAAA,UACE,KAAK;AAAA,UACL,SAASxlC,GAAM;AACb,mBAAKA,EAAK,QAAQ,KAGX;AAAA,cACL,IAAI,SAASA,EAAK,QAAQ,IAAO,EAAE;AAAA,YACrC,IAJS;AAAA,UAIT;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC,GAEY0lC,KAA6B53B,GAAK,OAAO;AAAA,EACpD,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AAAA,EACV,gBAAgB;AAEP,WAAA;AAAA,MACL,IAAI,EAAE,SAAS,MAAM,UAAU,SAAS;AAAA,MACxC,MAAM,EAAE,UAAU,SAAS;AAAA,MAC3B,UAAU,EAAE,SAAS,MAAM,UAAU,cAAc;AAAA,MACnD,eAAe,EAAE,SAAS,KAAK;AAAA,MAC/B,UAAU,EAAE,SAAS,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,iBAAiB8W,GAAW;AACtB,WAAAA,EAAU,SAAS,iBACd,CAAC,IAEH;AAAA,MACL,iBAAiB;AAAA,MACjB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQX,MAAM7Z,GAAMy6B,GAAQ;AACX,eAAA;AAAA,UACLA,IAAS,SAAS;AAAA,UAClB;AAAA,YACE,aAAa;AAAA,YACb,WAAW,OAAOz6B,EAAK,MAAM,EAAK;AAAA,YAClC,iBAAiBA,EAAK,MAAM;AAAA,YAC5B,qBAAqB,KAAK,UAAUA,EAAK,MAAM,aAAgB;AAAA;AAAA,YAE/D,oBAAoB,KAAK,UAAUA,EAAK,MAAM,QAAW;AAAA,UAC3D;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR;AAAA,UACE,KAAK;AAAA,UACL,SAAS/K,GAAM;AACb,mBAAKA,EAAK,QAAQ,KAGX;AAAA,cACL,IAAI,SAASA,EAAK,QAAQ,IAAO,EAAE;AAAA,cACnC,MAAMA,EAAK,QAAQ;AAAA,cACnB,eAAeA,EAAK,QAAQ;AAAA,cAC5B,UAAUA,EAAK,QAAQ;AAAA,YACzB,IAPS;AAAA,UAOT;AAAA,QAEJ;AAAA,QACA;AAAA,UACE,KAAK;AAAA,UACL,SAASA,GAAM;AACb,mBAAKA,EAAK,QAAQ,KAGX;AAAA,cACL,IAAI,SAASA,EAAK,QAAQ,IAAO,EAAE;AAAA,cACnC,MAAMA,EAAK,QAAQ;AAAA,cACnB,eAAeA,EAAK,QAAQ;AAAA,YAC9B,IANS;AAAA,UAMT;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC;ACnID,IAAI6gC;AA4BJ,SAAS8E,GAAmB3D,GAA+B;AACzD,EAAInB,MAIeA,IAAA,SAAS,cAAc,KAAK,GAC/CA,EAAiB,YAAY,KAC7BA,EAAiB,MAAM,UAAU,KACjCA,EAAiB,MAAM,SAAS,OAChCA,EAAiB,MAAM,QAAQ,OAC3BmB,aAAkB,WACbA,EAAA,KAAK,YAAYnB,CAAgB,IAExCmB,EAAO,YAAYnB,CAAgB;AAEvC;AAEA,SAAS+E,GAAqB5D,GAA+B;AAC3D,EAAInB,MACEmB,aAAkB,WACbA,EAAA,KAAK,YAAYnB,CAAgB,IAExCmB,EAAO,YAAYnB,CAAgB,GAElBA,IAAA;AAEvB;AAEA,SAAShR,GAAc7vB,GAAe;AACpC,SAAO,MAAM,UAAU,QAAQ,KAAKA,EAAK,cAAe,YAAYA,CAAI;AAC1E;AAIA,SAAS6lC,GAAcC,GAAiB;AACtC,MAAIC,IAAqCD;AACzC,SACEC,KACAA,EAAc,aAAa,QAC3BA,EAAc,aAAa,QAC3B,CAACA,EAAc,UAAU,SAAS,cAAc,KAChD;AACA,QAAIA,EAAc,UAAU,SAAS,aAAa;AACzC;AAET,UAAM7sB,IAA4B6sB,EAAc;AAEhD,QAAI,CAAC7sB,KAAU,EAAEA,aAAkB;AAC1B;AAEO,IAAA6sB,IAAA7sB;AAAA,EAAA;AAGlB,SAAO6sB,EAAc,aAAa,QAAQA,EAAc,aAAa,OACjE;AAAA,IACE,MAAM;AAAA,IACN,SAASA;AAAA,IACT,WAAWA,EAAc,QAAQ,OAAO;AAAA,EAAA,IAE1C;AAAA,IACE,MAAM;AAAA,IACN,SAASA;AAAA,IACT,WAAWA,EAAc,cAAc,OAAO;AAAA,EAChD;AACN;AAGA,SAASC,GAAaC,GAAkBjE,GAA+B;AAC/D,QAAAkE,IAAiBlE,EAAO,iBAAiBiE,CAAQ;AAEvD,WAASjiC,IAAI,GAAGA,IAAIkiC,EAAe,QAAQliC;AACxC,IAAAkiC,EAAeliC,CAAC,EAAkB,MAAM,aAAa;AAE1D;AAEO,MAAMmiC,GAIb;AAAA,EAcE,YACmB1iC,GAKAi1B,GACjBC,GACA;AArBK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA,oBAAa;AAEb,IAAAA,EAAA,oBAA0C;AAE1C,IAAAA,EAAA,yBAAkC;AAiCzC,IAAAA,EAAA,8BAAuB,MAAM;AAC3B,WAAK,aAAa;AAAA,IACpB;AAEA,IAAAA,EAAA,wBAAiB,CAACxoB,MAAsB;AACtC,WAAK,aAAa,MAClB,KAAK,iBAAiBA,CAAK;AAAA,IAC7B;AAEA,IAAAwoB,EAAA,0BAAmB,CAACxoB,MAAsB;;AAUtC,UATE,KAAK,cAIL,KAAK,eAAe,eAKtB,EAAEA,EAAM,kBAAkB,YAC1B,CAAC,KAAK,OAAO,IAAI,SAASA,EAAM,MAAM;AAEtC;AAGI,YAAAolC,IAASD,GAAcnlC,EAAM,MAAM;AAGvC,WAAAolC,KAAA,gBAAAA,EAAQ,UAAS,UACjB,KAAK,eAAe,UACpB,GAAC1mC,IAAA,KAAK,UAAL,QAAAA,EAAY,gBACb;AAEA,aAAK,aAAa,cAEdC,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,MAAM,4BAA4B,IACvC,KAAK,MAAM,+BAA+B,IAC1C,KAAK,WAAW;AAElB;AAAA,MAAA;AAGF,UAAI,CAACymC,KAAU,CAAC,KAAK,OAAO,YAAY;AAClC,SAAArkC,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,MAAM,4BAA4B,IACvC,KAAK,MAAM,+BAA+B,IAC1C,KAAK,WAAW;AAElB;AAAA,MAAA;AAGE,UAAA,CAACqkC,EAAO;AACV;AAGI,YAAAM,IAAYN,EAAO,UAAU,sBAAsB,GAEnDO,IAAUhG,GAA6ByF,EAAO,SAAS,KAAK,MAAM;AACxE,UAAI,CAACO;AACH;AAEF,WAAK,eAAeA,EAAQ;AAExB,UAAAC;AAIE,YAAAC,IAAa,KAAK,OAAO;AAAA,QAAS,CAACpnC,MACvC2U,EAAYuyB,EAAQ,IAAIlnC,EAAG,GAAG;AAAA,MAChC;AACA,UAAI,CAAConC;AACH,cAAM,IAAI,MAAM,iBAAiBF,EAAQ,EAAE,YAAY;AAGzD,YAAM7iC,IAAQyH;AAAA,QACZs7B,EAAW;AAAA,QACX,KAAK,OAAO;AAAA,QACZ,KAAK,OAAO,OAAO;AAAA,QACnB,KAAK,OAAO,OAAO;AAAA,QACnB,KAAK,OAAO,OAAO;AAAA,MACrB;AAOA,UALI7e,GAAwB,SAASlkB,GAAO,KAAK,MAAM,MAChD,KAAA,WAAW+iC,EAAW,gBAAgB,GAC9BD,IAAA9iC,IAGX,CAAC8iC;AACH;AAGF,WAAK,UAAUD,EAAQ;AACvB,YAAMG,KAAkB9kC,IAAAokC,EAAO,QAC5B,QAAQ,eAAe,MADF,gBAAApkC,EAEpB,cAAc;AAEd,WAAAokC,KAAA,gBAAAA,EAAQ,UAAS,WAAW;AAG9B,cAAMW,IACJ/lC,EAAM,WAAW0lC,EAAU,SAAS;AAAA,QACpC1lC,EAAM,UAAU0lC,EAAU,SAAS,IAC/BM,IACJhmC,EAAM,WAAW0lC,EAAU,QAAQ,KACnC1lC,EAAM,UAAU0lC,EAAU,QAAQ,IAG9BO,IACJjmC,EAAM,UAAU0lC,EAAU,SAAS1lC,EAAM,UAAU0lC,EAAU;AAE/D,aAAK,QAAQ;AAAA,UACX,GAAG,KAAK;AAAA,UACR,MAAM;AAAA,UACN,2BAA2BK;AAAA,UAC3B,8BAA8BC;AAAA,UAC9B,mBAAmBN;AAAA,UACnB,OAAOE;AAAA,UACP,iBAAAE;AAAA,UACA,UAAUG,MAA0BhlC,IAAA,KAAK,UAAL,OAAZ,SAAYA,EAAY;AAAA,UAChD,UAAUglC,MAA0BjuB,IAAA,KAAK,UAAL,OAAZ,SAAYA,EAAY;AAAA,UAChD,kBAAkBiuB,MAEdhuB,IAAA,KAAK,UAAL,OADA,SACAA,EAAY;AAAA,QAClB;AAAA,MAAA,OACK;AACC,cAAApH,IAAWse,GAAciW,EAAO,OAAO,GACvC/7B,IAAW8lB,GAAciW,EAAO,QAAQ,aAAc,GACtDc,IAAWd,EAAO,QAAQ,sBAAsB;AAEtD,YACE,KAAK,UAAU,UACf,KAAK,MAAM,QACX,KAAK,YAAYO,EAAQ,MACzB,KAAK,MAAM,aAAat8B,KACxB,KAAK,MAAM,aAAawH;AAGxB;AAGF,aAAK,QAAQ;AAAA,UACX,MAAM;AAAA,UACN,8BACEA,MAAa+0B,EAAW,QAAQ,KAAK,CAAC,EAAE,MAAM,SAAS;AAAA,UACzD,2BACEv8B,MAAau8B,EAAW,QAAQ,KAAK,SAAS;AAAA,UAChD,mBAAmBF;AAAA,UAEnB,OAAOE;AAAA,UACP,eAAe;AAAA,UACf,kBAAkBM;AAAA,UAClB,UAAAr1B;AAAA,UACA,UAAAxH;AAAA,UAEA,iBAAAy8B;AAAA,QACF;AAAA,MAAA;AAEF,kBAAK,WAAW,GAET;AAAA,IACT;AAEA,IAAAtd,EAAA,yBAAkB,CAACxoB,MAAqB;;AAClC,YAAAtB,IAAA,KAAK,UAAL,gBAAAA,EAAY,mBAAkB;AAChC;AAGF,MAAAsB,EAAM,eAAe,GACrBA,EAAM,aAAc,aAAa,QAEjCslC;AAAA,QACE;AAAA,QACA,KAAK,OAAO;AAAA,MACd;AAKA,YAAMa,IAAqB;AAAA,QACzB,MAAM,KAAK;AAAA,UACT,KAAK,IAAInmC,EAAM,SAAS,KAAK,MAAM,kBAAkB,OAAO,CAAC;AAAA,UAC7D,KAAK,MAAM,kBAAkB,QAAQ;AAAA,QACvC;AAAA,QACA,KAAK,KAAK;AAAA,UACR,KAAK,IAAIA,EAAM,SAAS,KAAK,MAAM,kBAAkB,MAAM,CAAC;AAAA,UAC5D,KAAK,MAAM,kBAAkB,SAAS;AAAA,QAAA;AAAA,MAE1C,GAIMomC,IAAoB,KAAK,OAAO,KACnC,kBAAkBD,EAAmB,MAAMA,EAAmB,GAAG,EACjE;AAAA,QACC,CAACvoC,MAAYA,EAAQ,YAAY,QAAQA,EAAQ,YAAY;AAAA,MAC/D;AACE,UAAAwoC,EAAkB,WAAW;AAC/B;AAEI,YAAAC,IAAmBD,EAAkB,CAAC;AAE5C,UAAIE,IAAkB;AAGhB,YAAAj9B,IAAW8lB,GAAckX,EAAiB,aAAc,GACxDx1B,IAAWse,GAAckX,CAAgB,GAIzCE,IACJ,KAAK,MAAM,cAAc,2BAA2B,QAChD,KAAK,MAAM,WACX,KAAK,MAAM,UAKXC,KAHJ,KAAK,MAAM,cAAc,2BAA2B,QAChDn9B,IACAwH,OAC8C01B;AAIpD,OAAI,KAAK,MAAM,aAAal9B,KAAY,KAAK,MAAM,aAAawH,OAC9D,KAAK,MAAM,WAAWxH,GACtB,KAAK,MAAM,WAAWwH,GAEjB,KAAA,MAAM,mBAAmBw1B,EAAiB,sBAAsB,GAEnDC,IAAA;AAKd,YAAArE,IACJ,KAAK,MAAM,cAAc,2BAA2B,QAChDkE,EAAmB,MACnBA,EAAmB;AACzB,MAAI,KAAK,MAAM,cAAc,aAAalE,MACnC,KAAA,MAAM,cAAc,WAAWA,GAElBqE,IAAA,KAIhBA,KACF,KAAK,WAAW,GAKdE,KACG,KAAA,OAAO,SAAS,CAAC/nC,MAAOA,EAAG,QAAQgoC,IAAuB,EAAI,CAAC;AAAA,IAExE;AAEA,IAAAje,EAAA,qBAAc,CAACxoB,MAAqB;AAElC,UADA,KAAK,aAAa,MACd,KAAK,UAAU,UAAa,KAAK,MAAM,kBAAkB;AACpD,eAAA;AAGT,UACE,KAAK,MAAM,aAAa,UACxB,KAAK,MAAM,aAAa;AAExB,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAGF,MAAAA,EAAM,eAAe;AAErB,YAAM,EAAE,eAAA0mC,GAAe,UAAA71B,GAAU,UAAAxH,MAAa,KAAK,OAE7CuJ,IAAe,KAAK,MAAM,MAAM,QAAQ;AAE1C,UAAA8zB,EAAc,2BAA2B,OAAO;AAClD,YACE,CAAC51B;AAAA,UACC,KAAK,MAAM;AAAA,UACX41B,EAAc;AAAA,UACdr9B;AAAA,QAAA;AAIK,iBAAA;AAET,cAAMs9B,IAAWj3B;AAAA,UACf,KAAK,MAAM;AAAA,UACXg3B,EAAc;AAAA,UACdr9B;AAAA,QACF;AACA,aAAK,OAAO,YAAY,KAAK,MAAM,OAAO;AAAA,UACxC,MAAM;AAAA,UACN,SAAS;AAAA,YACP,GAAG,KAAK,MAAM,MAAM;AAAA,YACpB,MAAMs9B;AAAA,UAAA;AAAA,QACR,CACD;AAAA,MAAA,OACI;AACL,YACE,CAACv1B;AAAA,UACC,KAAK,MAAM;AAAA,UACXs1B,EAAc;AAAA,UACd71B;AAAA,QAAA;AAIK,iBAAA;AAET,cAAM81B,IAAWv3B;AAAA,UACf,KAAK,MAAM;AAAA,UACXs3B,EAAc;AAAA,UACd71B;AAAA,QACF,GACM,CAAC+1B,CAAW,IAAIh0B,EAAa,OAAO8zB,EAAc,eAAe,CAAC;AAC3D,QAAA9zB,EAAA,OAAO/B,GAAU,GAAG+1B,CAAW,GAC5C,KAAK,OAAO,YAAY,KAAK,MAAM,OAAO;AAAA,UACxC,MAAM;AAAA,UACN,SAAS;AAAA,YACP,GAAG,KAAK,MAAM,MAAM;AAAA,YACpB,cAAAh0B;AAAA,YACA,MAAM+zB;AAAA,UAAA;AAAA,QACR,CACD;AAAA,MAAA;AAKH,kBAAK,OAAO,sBAAsB,KAAK,MAAM,MAAM,EAAE,GAE9C;AAAA,IACT;AA5WmB,SAAA,SAAA5jC,GAKA,KAAA,SAAAi1B,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,kDAAkD;AAGpE,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEAD,EAAO,IAAI,iBAAiB,aAAa,KAAK,gBAAgB,GAC9DA,EAAO,IAAI,iBAAiB,aAAa,KAAK,oBAAoB,GAC3D,OAAA,iBAAiB,WAAW,KAAK,cAAc,GAEtDA,EAAO,KAAK;AAAA,MACV;AAAA,MACA,KAAK;AAAA,IACP,GACAA,EAAO,KAAK;AAAA,MACV;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EAAA;AAAA;AAAA,EAmVF,SAAS;;AACP,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,MAAM;AAC7B;AAKF,QADK,KAAA,MAAM,QAAQ,KAAK,OAAO,SAAS,KAAK,MAAM,MAAM,EAAE,GAEzD,CAAC,KAAK,MAAM,SACZ,KAAK,MAAM,MAAM,SAAS;AAAA;AAAA,IAG1B,GAACt5B,IAAA,KAAK,iBAAL,QAAAA,EAAmB,cACpB;AACA,WAAK,MAAM,OAAO,IAClB,KAAK,MAAM,4BAA4B,IACvC,KAAK,MAAM,+BAA+B,IAC1C,KAAK,WAAW;AAEhB;AAAA,IAAA;AAGF,UAAM,EAAE,QAAQmoC,GAAU,OAAOC,EAAa,IAAAr5B;AAAA,MAC5C,KAAK,MAAM;AAAA,IACb;AAEA,IACE,KAAK,MAAM,aAAa,UACxB,KAAK,MAAM,aAAa,WAKpB,KAAK,MAAM,YAAYo5B,MACpB,KAAA,MAAM,WAAWA,IAAW,IAE/B,KAAK,MAAM,YAAYC,MACpB,KAAA,MAAM,WAAWA,IAAW;AAKrC,UAAMC,IAAY,KAAK,aAAc,cAAc,OAAO;AAE1D,QAAI,CAACA;AACH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QACE,KAAK,MAAM,aAAa,UACxB,KAAK,MAAM,aAAa,QACxB;AAEA,YAAM5lC,IADM4lC,EAAU,SAAS,KAAK,MAAM,QAAQ,EACjC,SAAS,KAAK,MAAM,QAAQ;AAC7C,MAAI5lC,IACG,KAAA,MAAM,mBAAmBA,EAAK,sBAAsB,KAEzD,KAAK,MAAM,WAAW,QACtB,KAAK,MAAM,WAAW;AAAA,IACxB;AAEG,SAAA,MAAM,oBAAoB4lC,EAAU,sBAAsB,GAE/D,KAAK,WAAW;AAAA,EAAA;AAAA,EAGlB,UAAU;AACR,SAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,gBAAgB,GAC/D,OAAA,oBAAoB,WAAW,KAAK,cAAc,GACzD,KAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,oBAAoB,GAC1E,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EAAA;AAEJ;AAEa,MAAAN,KAAwB,IAAIvoC,EAAU,oBAAoB;AAEhE,MAAM8oC,WAGHzS,EAAmB;AAAA,EAO3B,YACmBxxB,GAKjB;AACM,UAAA;AATA,IAAAylB,EAAA;AAiLR;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,sBAAe,CAACxoB,MAGV;AAEF,UAAA,KAAK,KAAM,UAAU,UACrB,KAAK,KAAM,MAAM,aAAa;AAE9B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAoBE,UAjBC,KAAA,KAAM,MAAM,gBAAgB;AAAA,QAC/B,wBAAwB;AAAA,QACxB,eAAe,KAAK,KAAM,MAAM;AAAA,QAChC,UAAUA,EAAM;AAAA,MAClB,GACA,KAAK,KAAM,WAAW,GAEtB,KAAK,OAAO;AAAA,QAAS,CAACvB,MACpBA,EAAG,QAAQgoC,IAAuB;AAAA,UAChC,wBACE,KAAK,KAAM,MAAO,cAAe;AAAA,UACnC,eAAe,KAAK,KAAM,MAAO;AAAA,UACjC,UAAU,KAAK,KAAM,MAAO;AAAA,UAC5B,UAAU,KAAK,KAAM;AAAA,QACtB,CAAA;AAAA,MACH,GAEI,CAAC,KAAK,OAAO;AACT,cAAA,IAAI,MAAM,8BAA8B;AAG7B,MAAAxB,GAAA,KAAK,OAAO,gBAAgB,IAAI,GACnDjlC,EAAM,aAAc,aAAamgC,GAAmB,GAAG,CAAC,GACxDngC,EAAM,aAAc,gBAAgB;AAAA,IACtC;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAwoB,EAAA,sBAAe,CAACxoB,MAGV;AAEF,UAAA,KAAK,KAAM,UAAU,UACrB,KAAK,KAAM,MAAM,aAAa;AAE9B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAoBE,UAjBC,KAAA,KAAM,MAAM,gBAAgB;AAAA,QAC/B,wBAAwB;AAAA,QACxB,eAAe,KAAK,KAAM,MAAM;AAAA,QAChC,UAAUA,EAAM;AAAA,MAClB,GACA,KAAK,KAAM,WAAW,GAEtB,KAAK,OAAO;AAAA,QAAS,CAACvB,MACpBA,EAAG,QAAQgoC,IAAuB;AAAA,UAChC,wBACE,KAAK,KAAM,MAAO,cAAe;AAAA,UACnC,eAAe,KAAK,KAAM,MAAO;AAAA,UACjC,UAAU,KAAK,KAAM,MAAO;AAAA,UAC5B,UAAU,KAAK,KAAM;AAAA,QACtB,CAAA;AAAA,MACH,GAEI,CAAC,KAAK,OAAO;AACT,cAAA,IAAI,MAAM,8BAA8B;AAG7B,MAAAxB,GAAA,KAAK,OAAO,gBAAgB,IAAI,GACnDjlC,EAAM,aAAc,aAAamgC,GAAmB,GAAG,CAAC,GACxDngC,EAAM,aAAc,gBAAgB;AAAA,IACtC;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAwoB,EAAA,iBAAU,MAAM;AACV,UAAA,KAAK,KAAM,UAAU;AACvB,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAQE,UALC,KAAA,KAAM,MAAM,gBAAgB,QACjC,KAAK,KAAM,WAAW,GAEjB,KAAA,OAAO,SAAS,CAAC/pB,MAAOA,EAAG,QAAQgoC,IAAuB,IAAI,CAAC,GAEhE,CAAC,KAAK,OAAO;AACT,cAAA,IAAI,MAAM,8BAA8B;AAG3B,MAAAvB,GAAA,KAAK,OAAO,gBAAgB,IAAI;AAAA,IACvD;AAMA;AAAA;AAAA;AAAA;AAAA,IAAA1c,EAAA,uBAAgB,MAAM;AACpB,WAAK,KAAM,aAAa;AAAA,IAC1B;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,yBAAkB,MAAM;AACtB,WAAK,KAAM,aAAa;AAAA,IAC1B;AAEA,IAAAA,EAAA,6BAAsB,CACpB1lB,GACA8L,MAEOD,GAAoB7L,GAAO8L,CAAgB;AAMpD;AAAA;AAAA;AAAA,IAAA4Z,EAAA,gCAAyB,CACvB1lB,GACAoM,MAEOD,GAAuBnM,GAAOoM,CAAmB;AAOlD;AAAA;AAAA;AAAA;AAAA,IAAAsZ,EAAA,0BAAmB,CACzBtgB,GACA++B,GACAC,IAAuCD,MACpC;AACH,YAAMnnC,IAAO,KAAK;AAElB,UAAI,CAACA;AACG,cAAA,IAAI,MAAM,oCAAoC;AAGtD,YAAMqnC,IAAmBj/B,EAAM,IAAI,QAAQpI,EAAK,WAAY,CAAC,GACvDsnC,IAAsBl/B,EAAM,IAAI;AAAA,QACpCi/B,EAAiB,WAAWF,EAAkB,GAAG,IAAI;AAAA,MACvD,GACMI,IAAuBn/B,EAAM,IAAI;AAAA;AAAA,QAErCk/B,EAAoB,WAAWH,EAAkB,GAAG;AAAA,MACtD,GACMK,IAAoBp/B,EAAM,IAAI;AAAA,QAClCi/B,EAAiB,WAAWD,EAAgB,GAAG,IAAI;AAAA,MACrD,GACMK,IAAqBr/B,EAAM,IAAI;AAAA;AAAA,QAEnCo/B,EAAkB,WAAWJ,EAAgB,GAAG;AAAA,MAClD,GAGMzoC,IAAKyJ,EAAM;AAGd,aAAAzJ,EAAA;AAAA,QACD,IAAI8oB,GAAc8f,GAAsBE,CAAkB;AAAA,MAC5D,GAGOr/B,EAAM,MAAMzJ,CAAE;AAAA,IACvB;AAKA;AAAA;AAAA;AAAA,IAAA+pB,EAAA,wBAAiB,CACfjrB,GACAiqC,MAGG;AACH,WAAK,OAAO,KAAK,CAACC,GAAahyB,MAAa;AAC1C,cAAMvN,IAAQ,KAAK;AAAA,UACjBu/B;AAAA,UACAD,EAAU,gBAAgB,QACtB,EAAE,KAAKjqC,GAAO,KAAK,EACnB,IAAA,EAAE,KAAK,GAAG,KAAKA,EAAM;AAAA,QAC3B;AAEI,eAAAiqC,EAAU,gBAAgB,QACxBA,EAAU,SAAS,UACdE,GAAax/B,GAAOuN,CAAQ,IAE5BkyB,GAAYz/B,GAAOuN,CAAQ,IAGhC+xB,EAAU,SAAS,SACdI,GAAgB1/B,GAAOuN,CAAQ,IAE/BoyB,GAAe3/B,GAAOuN,CAAQ;AAAA,MAEzC,CACD;AAAA,IACH;AAKA;AAAA;AAAA;AAAA,IAAA+S,EAAA,2BAAoB,CAClBjrB,GACAiqC,MAEIA,MAAc,QACT,KAAK,OAAO,KAAK,CAACC,GAAahyB,MAAa;AAC3C,YAAAvN,IAAQ,KAAK,iBAAiBu/B,GAAa;AAAA,QAC/C,KAAKlqC;AAAA,QACL,KAAK;AAAA,MAAA,CACN;AACM,aAAAuqC,GAAU5/B,GAAOuN,CAAQ;AAAA,IAAA,CACjC,IAEM,KAAK,OAAO,KAAK,CAACgyB,GAAahyB,MAAa;AAC3C,YAAAvN,IAAQ,KAAK,iBAAiBu/B,GAAa;AAAA,QAC/C,KAAK;AAAA,QACL,KAAKlqC;AAAA,MAAA,CACN;AACM,aAAAwqC,GAAa7/B,GAAOuN,CAAQ;AAAA,IAAA,CACpC;AAOL;AAAA;AAAA;AAAA,IAAA+S,EAAA,oBAAa,CAACwf,MAIL,KAAK,OAAO,KAAK,CAACP,GAAahyB,MAAa;AAC3C,YAAAvN,IAAQ8/B,IACV,KAAK;AAAA,QACHP;AAAA,QACAO,EAAa;AAAA,QACbA,EAAa;AAAA,MAAA,IAEfP;AAEG,aAAAQ,GAAW//B,GAAOuN,CAAQ;AAAA,IAAA,CAClC;AAOH;AAAA;AAAA;AAAA;AAAA,IAAA+S,EAAA,mBAAY,CAAC0f,MACJ,KAAK,OAAO,KAAK,CAACT,GAAahyB,MAAa;AACjD,YAAMvN,IAAQggC,IACV,KAAK,iBAAiBT,GAAaS,CAAmB,IACtDT;AAEG,aAAAU,GAAUjgC,GAAOuN,CAAQ;AAAA,IAAA,CACjC;AAOH;AAAA;AAAA;AAAA;AAAA,IAAA+S,EAAA,0BAAmB,MAYV,KAAK,OAAO,SAAS,CAAC/pB,MAAO;AAClC,YAAM8e,IAAY9e,EAAG;AAErB,UAAI2pC,IAAY7qB,EAAU,OACtB8qB,IAAU9qB,EAAU;AACpB,UAAA+J,GAAqB/J,CAAS,GAAG;AAG7B,cAAA,EAAE,QAAA8b,MAAW9b;AACZ,QAAA8b,EAAA,QAAQ,CAACnlB,MAAU;AACxB,UAAAk0B,IAAYl0B,EAAM,MAAM,IAAIk0B,KAAal0B,EAAM,KAAK,GACpDm0B,IAAUn0B,EAAM,IAAI,IAAIm0B,KAAWn0B,EAAM,GAAG;AAAA,QAAA,CAC7C;AAAA,MAAA,WAKDk0B,IAAY3pC,EAAG,IAAI;AAAA,QACjB8e,EAAU,MAAM,MAAMA,EAAU,MAAM,eAAe;AAAA,MACvD,GACA8qB,IAAU5pC,EAAG,IAAI;AAAA,QACf8e,EAAU,IAAI,MAAMA,EAAU,IAAI,eAAe;AAAA,MACnD,GAGI6qB,EAAU,QAAQ,KAAKC,EAAQ,QAAQ;AAClC;AAKL,YAAAC,IAAW7pC,EAAG,IAAI;AAAA,QACtB2pC,EAAU,MAAMA,EAAU,eAAe;AAAA,MAC3C,GACMG,IAAS9pC,EAAG,IAAI,QAAQ4pC,EAAQ,MAAMA,EAAQ,eAAe,CAAC,GAG9DG,IAAS/pC,EAAG,IAAI,QAAQ6pC,EAAS,MAAMA,EAAS,eAAe,CAAC,GAGhEj5B,IAAe+4B,EAAU,MAAME,EAAS,KAAK,GAC7C34B,IAAe24B,EAAS,MAAME,EAAO,KAAK,GAC1Cl5B,IAAa+4B,EAAQ,MAAME,EAAO,KAAK,GACvC34B,IAAa24B,EAAO,MAAMC,EAAO,KAAK,GAEtC15B,IAA+B,CAAC;AACtC,eAASxF,IAAMqG,GAAcrG,KAAOsG,GAAYtG;AAC9C,iBAASsE,IAAMyB,GAAczB,KAAO0B,GAAY1B;AAC9C,UAAAkB,EAAM,KAAK,EAAE,KAAAxF,GAAK,KAAAsE,EAAA,CAAK;AAIpB,aAAA;AAAA,QACL,MAAM;AAAA,UACJ,KAAK+B;AAAA,UACL,KAAKN;AAAA,QACP;AAAA,QACA,IAAI;AAAA,UACF,KAAKO;AAAA,UACL,KAAKN;AAAA,QACP;AAAA,QACA,OAAAR;AAAA,MACF;AAAA,IAAA,CACD;AAQH;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA0Z,EAAA,2BAAoB,CAClB1lB,MAIO,KAAK,OAAO,SAAS,CAACrE,MAAO;AAClC,YAAMgqC,IAAwBnhB,GAAqB7oB,EAAG,SAAS,IAC3DA,EAAG,YACH;AAGF,UAAA,CAACgqC,KACD,CAAC3lC;AAAA,MAED2lC,EAAsB,OAAO,UAAU;AAEhC;AAGH,YAAAC,IAAgB,KAAK,iBAAiB;AAE5C,UAAKA;AAIL,eAAIl3B,GAAgBk3B,EAAc,MAAMA,EAAc,IAAI5lC,CAAK,IACtD,aAGF;AAAA,IAAA,CACR;AAGH,IAAA0lB,EAAA,gCAAyB,CACvB1lB,GACAqN,MAEOD,GAAuBpN,GAAOqN,CAAW;AAGlD,IAAAqY,EAAA,0BAAmB,CACjB1lB,GACA2N,GACAC,MAEOF,GAAiB1N,GAAO2N,GAASC,CAAQ;AApkB/B,SAAA,SAAA3N,GAOZ,KAAA;AAAA,MACH,IAAI9E,EAAO;AAAA,QACT,KAAKwoC;AAAA,QACL,MAAM,CAAC/N,OACL,KAAK,OAAO,IAAI+M,GAAiB1iC,GAAQ21B,GAAY,CAACxwB,MAAU;AACzD,eAAA,KAAK,UAAUA,CAAK;AAAA,QAAA,CAC1B,GACM,KAAK;AAAA;AAAA;AAAA,QAId,OAAO;AAAA,UACL,aAAa,CAACA,MAAU;AACtB,gBACE,KAAK,SAAS,UACd,KAAK,KAAK,UAAU,UACpB,KAAK,KAAK,MAAM,kBAAkB,UAClC,KAAK,KAAK,aAAa;AAEvB;AAGF,kBAAMwa,IACJ,KAAK,KAAK,MAAM,cAAc,2BAA2B,QACrD,KAAK,KAAK,MAAM,WAChB,KAAK,KAAK,MAAM;AAEtB,gBAAIA,MAAa;AACf;AAGF,kBAAM0U,IAA4B,CAAC,GAC7B,EAAE,OAAAt0B,GAAO,eAAA4jC,EAAc,IAAI,KAAK,KAAK,OACrC,EAAE,eAAAiC,GAAe,wBAAAC,EAAA,IAA2BlC;AAOlD,gBACEhkB,MAAaimB,KACb,CAAC7lC,KACA8lC,MAA2B,SAC1B,CAAC93B,GAAoBhO,GAAO6lC,GAAejmB,CAAQ,KACpDkmB,MAA2B,SAC1B,CAACx3B,GAAuBtO,GAAO6lC,GAAejmB,CAAQ;AAExD,qBAAOwU,EAAc,OAAOhvB,EAAM,KAAKkvB,CAAW;AAIpD,kBAAM+P,IAAmBj/B,EAAM,IAAI,QAAQ,KAAK,KAAK,WAAW,CAAC;AAEjE,mBACE,KAAK,KAAK,MAAM,cAAc,2BAA2B,QAEtCyG;AAAA,cACjB,KAAK,KAAK,MAAM;AAAA,cAChB+T;AAAA,YACF,EAEW,QAAQ,CAAC,EAAE,KAAApZ,GAAK,KAAAsE,QAAU;AAE7B,oBAAAi7B,IAAiB3gC,EAAM,IAAI;AAAA,gBAC/Bi/B,EAAiB,WAAW79B,CAAG,IAAI;AAAA,cACrC,GAGMw/B,IAAkB5gC,EAAM,IAAI;AAAA,gBAChC2gC,EAAe,WAAWj7B,CAAG,IAAI;AAAA,cACnC,GACMrE,IAAWu/B,EAAgB,KAAK,GAIhCC,IACJD,EAAgB,OACfpmB,IAAWimB,IAAgBp/B,EAAS,WAAW,IAAI;AAC1C,cAAA6tB,EAAA;AAAA;AAAA,gBAEVE,EAAW,OAAOyR,GAAe,MAAM;AAC/B,wBAAAC,IAAS,SAAS,cAAc,KAAK;AAC3C,yBAAAA,EAAO,YAAY,wBACnBA,EAAO,MAAM,OAAO,KACpBA,EAAO,MAAM,QAAQ,KAMjBtmB,IAAWimB,IACbK,EAAO,MAAM,SAAS,SAEtBA,EAAO,MAAM,MAAM,QAErBA,EAAO,MAAM,SAAS,OAEfA;AAAA,gBACR,CAAA;AAAA,cACH;AAAA,YAAA,CACD,IAEqB/5B;AAAA,cACpB,KAAK,KAAK,MAAM;AAAA,cAChByT;AAAA,YACF,EAEc,QAAQ,CAAC,EAAE,KAAApZ,GAAK,KAAAsE,QAAU;AAEhC,oBAAAi7B,IAAiB3gC,EAAM,IAAI;AAAA,gBAC/Bi/B,EAAiB,WAAW79B,CAAG,IAAI;AAAA,cACrC,GAGMw/B,IAAkB5gC,EAAM,IAAI;AAAA,gBAChC2gC,EAAe,WAAWj7B,CAAG,IAAI;AAAA,cACnC,GACMrE,IAAWu/B,EAAgB,KAAK,GAKhCC,IACJD,EAAgB,OACfpmB,IAAWimB,IAAgBp/B,EAAS,WAAW,IAAI;AAE1C,cAAA6tB,EAAA;AAAA;AAAA,gBAEVE,EAAW,OAAOyR,GAAe,MAAM;AAC/B,wBAAAC,IAAS,SAAS,cAAc,KAAK;AAC3C,yBAAAA,EAAO,YAAY,wBACnBA,EAAO,MAAM,MAAM,KACnBA,EAAO,MAAM,SAAS,KAMlBtmB,IAAWimB,IACbK,EAAO,MAAM,QAAQ,SAErBA,EAAO,MAAM,OAAO,QAEtBA,EAAO,MAAM,QAAQ,OAEdA;AAAA,gBACR,CAAA;AAAA,cACH;AAAA,YAAA,CACD,GAGI9R,EAAc,OAAOhvB,EAAM,KAAKkvB,CAAW;AAAA,UAAA;AAAA,QACpD;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA1KF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA4KF,SAAS9C,GAAoD;AAC3D,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AA+ZrC;ACvrCa,MAAA2U,KAAyBxrC,EAAU,OAAO;AAAA,EACrD,MAAM;AAAA,EAEN,sBAAsB;AACb,WAAA;AAAA,MACL;AAAA;AAAA;AAAA,QAGE,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,YAAY;AAAA,UACV,eAAe;AAAA,YACb,SAAS;AAAA,YACT,WAAW,CAACG,MACHA,EAAQ,aAAa,qBAAqB;AAAA,YAEnD,YAAY,CAACC,MACPA,EAAW,kBAAkB,SACxB,CAAC,IAEH;AAAA,cACL,uBAAuBA,EAAW;AAAA,YACpC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC,GCnCYqrC,KAAqBzrC,EAAU,OAAO;AAAA,EACjD,MAAM;AAAA,EAEN,sBAAsB;AACb,WAAA;AAAA,MACL;AAAA,QACE,OAAO,CAAC,kBAAkB,aAAa,aAAa;AAAA,QACpD,YAAY;AAAA,UACV,WAAW;AAAA,YACT,SAAS+F,EAAa,UAAU;AAAA,YAChC,WAAW,CAAC5F,MACVA,EAAQ,aAAa,iBAAiB,IAClCA,EAAQ,aAAa,iBAAiB,IACtC4F,EAAa,UAAU;AAAA,YAC7B,YAAY,CAAC3F,MACPA,EAAW,cAAc2F,EAAa,UAAU,UAC3C,CAAC,IAEH;AAAA,cACL,mBAAmB3F,EAAW;AAAA,YAChC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC,GCZYsrC,KAAe1rC,EAAU,OAA4B;AAAA,EAChE,MAAM;AAAA,EAEN,wBAAwB;AACtB,UAAMg3B,IAAS,IAAIv2B,EAAU,KAAK,IAAI;AAK/B,WAAA;AAAA,MACL,IAAID,EAAO;AAAA,QACT,KAAKw2B;AAAA,QACL,mBAAmB,CAAC7jB,GAAGw4B,GAAIlhC,MAAU;AACnC,gBAAM,EAAE,KAAAxB,GAAK,IAAAjI,GAAI,QAAA8J,EAAW,IAAAL,GACtBmhC,IAAwB5U,EAAO,SAASvsB,CAAK,GAC7CohC,IAAc5iC,EAAI,QAAQ,OAAO,GACjCjC,IAAO8D,EAAO,MAAM,gBACpBof,IAAcpf,EAAO,MAAM;AACjC,cAAK8gC;AAIL,mBAAO5qC,EAAG;AAAA,cACR6qC;AAAA,cACA7kC,EAAK,OAAO,QAAWkjB,EAAY,OAAQ,CAAA;AAAA,YAC7C;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,MAAM,CAAC/W,GAAG24B,MAAW;AAAA,UAGrB;AAAA,UACA,OAAO,CAAC9qC,GAAIkE,MAAU;AAChB,gBAAA,CAAClE,EAAG;AACC,qBAAAkE;AAGL,gBAAA6mC,IAAW/qC,EAAG,IAAI;AAEtB,gBAAI,CAAC+qC,KAAYA,EAAS,KAAK,SAAS;AAChC,oBAAA,IAAI,MAAM,qBAAqB;AAKvC,gBAFAA,IAAWA,EAAS,WAEhB,CAACA,KAAYA,EAAS,KAAK,SAAS;AAC/B,qBAAA;AAGT,kBAAMC,IAAkBD,EAAS;AAEjC,gBAAI,CAACC;AACG,oBAAA,IAAI,MAAM,uBAAuB;AAKzC,mBACED,EAAS,WAAW,KACpBC,EAAgB,KAAK,KAAK,YAAY;AAAA,UAAA;AAAA,QAE1C;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC,GC7EKC,KAA0C;AAAA,EAC9C,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,aAAa;AACf,GAKaC,KAAiBtkC,GAAK,OAGhC;AAAA,EACD,MAAM;AAAA,EACN,OAAO;AAAA;AAAA,EAEP,SAAS;AAAA;AAAA,EAET,UAAU;AAAA,EACV,UAAU;AAAA,EACV,OAAO;AAAA,EACP,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK,wBAAwB,KAAK,OAAO;AAAA,QACzC,UAAU,CAACzH,MAAY;AACjB,cAAA,OAAOA,KAAY;AACd,mBAAA;AAGT,gBAAMoV,IAAgC,CAAC;AACvC,qBAAW,CAACssB,GAAUsK,CAAQ,KAAK,OAAO,QAAQF,EAAe;AAC3D,YAAA9rC,EAAQ,aAAagsC,CAAQ,MAC/B52B,EAAMssB,CAAQ,IAAI1hC,EAAQ,aAAagsC,CAAQ;AAI5C,iBAAA52B;AAAA,QAAA;AAAA,MAEX;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAA3M,KAAkB;;AACvB,UAAAwjC,IAAa,SAAS,cAAc,KAAK;AAC/C,IAAAA,EAAW,YAAY,kBACZA,EAAA,aAAa,kBAAkB,YAAY;AACtD,eAAW,CAACnnC,GAAWC,CAAK,KAAK,OAAO,QAAQ0D,CAAc;AAC5D,MAAI3D,MAAc,WACLmnC,EAAA,aAAannC,GAAWC,CAAK;AAI5C,UAAMmnC,IAAsB;AAAA,MAC1B,KAAIprC,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,UAAS,CAAC;AAAA,MAC1C,GAAG2H;AAAA,IACL,GACMvD,IAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,EAAM,YAAYd,EAAgB,YAAY8nC,EAAoB,KAAK,GACjEhnC,EAAA,aAAa,kBAAkB,KAAK,IAAI;AAC9C,eAAW,CAACJ,GAAWC,CAAK,KAAK,OAAO,QAAQmnC,CAAmB;AACjE,MAAIpnC,MAAc,WACVI,EAAA,aAAaJ,GAAWC,CAAK;AAIvC,WAAAknC,EAAW,YAAY/mC,CAAK,GAErB;AAAA,MACL,KAAK+mC;AAAA,MACL,YAAY/mC;AAAA,IACd;AAAA,EAAA;AAEJ,CAAC,GCnFYinC,KAAa1kC,GAAK,OAE5B;AAAA,EACD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACzH,MACL,OAAOA,KAAY,WACd,KAGLA,EAAQ,aAAa,gBAAgB,MAAM,eAEtC,OAGF;AAAA,MACT;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAyI,KAAkB;;AAC7B,UAAM2jC,IAA2B;AAAA,MAC/B,KAAItrC,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,eAAc,CAAC;AAAA,MAC/C,GAAG2H;AAAA,IACL,GACMiB,IAAa,SAAS,cAAc,KAAK;AAC/C,IAAAA,EAAW,YAAYtF;AAAA,MACrB;AAAA,MACAgoC,EAAyB;AAAA,IAC3B,GACW1iC,EAAA,aAAa,kBAAkB,YAAY;AACtD,eAAW,CAAC5E,GAAWC,CAAK,KAAK,OAAO,QAAQqnC,CAAwB;AACtE,MAAItnC,MAAc,WACL4E,EAAA,aAAa5E,GAAWC,CAAK;AAIrC,WAAA;AAAA,MACL,KAAK2E;AAAA,MACL,YAAYA;AAAA,IACd;AAAA,EAAA;AAEJ,CAAC,GCnDY2iC,KAAM5kC,GAAK,OAAO;AAAA,EAC7B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AACT,CAAC;ACUM,MAAM6kC,WAAuB3V,EAEjC;AAAA,EAQD,YAAY;AAAA,IACV,QAAAxxB;AAAA,IACA,eAAA4xB;AAAA,EAAA,GAIC;AACD,UAAM5xB,CAAM;AAVN,IAAAylB,EAAA;AACA,IAAAA,EAAA;AA4DA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA;AAlDN,SAAK,SAASzlB,GACd,KAAK,gBAAgB4xB;AAAA,EAAA;AAAA,EAhBvB,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAqBD,oBACNwV,GACAC,GACG;AACH,UAAMC,IAAOF,EAAM;AACf,QAAAA,EAAM,UAAU,MAAM;AAKxB,YAAMG,IAAU,MAAM,KAAKD,EAAK,MAAM,KAAM,CAAA,EAAE;AAAA,QAC5C,CAACntC,MAAQmtC,EAAK,MAAM,IAAIntC,CAAG,MAAMitC;AAAA,MACnC;AACA,UAAIG,KAAW;AACP,cAAA,IAAI,MAAM,mCAAmC;AAErD,aAAOF,EAAU,IAAIE,GAASH,EAAM,WAA0B;AAAA,IAAA,OACzD;AAIL,YAAMI,IAAYJ,EAAM,OAClBK,IACJJ,EAAU,MAAM,QAAQ,IAAIG,EAAU,GAAG,MAAM,KAAK,CAAC,GACjDE,IAAYC,GAAE,YAAYF,GAAcD,EAAU,GAAG,KAAK;AAGhE,aAFkBC,EAAaC,CAAS,EACT,QACX;AAAA,IAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOF,IAAW,qBAAqB;AAC9B,WAAO,KAAK,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBvB,OAAO;AACZ,QAAI,KAAK;AACP;AAGI,UAAAE,IAAmB,KAAK,cAAc;AAE5C,QAAI,CAACA;AACG,YAAA,IAAI,MAAM,0BAA0B;AAGtC,UAAAjkC,IAAM,IAAIgkC,GAAE,IAAI;AAEtB,IAAAA,GAAE,YAAYhkC,GAAKgkC,GAAE,oBAAoBC,EAAiB,GAAI,CAAC;AAG/D,UAAMC,IAAiB,KAAK,oBAAoBD,GAAkBjkC,CAAG;AAErE,SAAK,cAAc;AAAA,MACjB,kBAAAikC;AAAA,MACA,gBAAAC;AAAA,IACF,GAGK,KAAA,OAAO,cAAc,iBAAiB;AAAA,MACzCC;AAAA,MACAC;AAAA,MACAlT;AAAA,IAAA,CACD,GAED,KAAK,OAAO,cAAc;AAAA,MACxB,IAAIrC,GAAWqV,CAAc,EAAE,QAAQ,CAAC;AAAA,IAC1C,GACK,KAAA,OAAO,cAAc,eAAe,IAAInV,KAAa,QAAQ,CAAC,CAAC,GAE/D,KAAA,KAAK,UAAU,EAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQnB,MAAM,EAAE,aAAAsV,KAAyC;AAClD,QAAA,CAAC,KAAK;AACR;AAGG,SAAA,OAAO,cAAc,iBAAiBnT,EAAc,GACpD,KAAA,OAAO,cAAc,iBAAiBkT,EAAc;AAEzD,UAAM,EAAE,kBAAAH,GAAkB,gBAAAC,EAAe,IAAI,KAAK;AAClD,QAAIG,GAAa;AAEf,YAAMx+B,IAASm+B,GAAE,oBAAoBE,EAAe,GAAI;AACtD,MAAAF,GAAA,YAAYC,EAAiB,KAAMp+B,CAAM;AAAA,IAAA;AAE7C,SAAK,OAAO,WAAW,cAAiB,IAAIgpB,GAAWoV,CAAgB,GACvE,KAAK,OAAO,WAAW,gBAAmB,IAAIrV;AAAA,MAC5C,KAAK;AAAA,IACP,GACA,KAAK,OAAO,WAAW,cAAiB,IAAIG,GAAW,GAEvD,KAAK,OAAO,cAAc;AAAA,MACxB,KAAK,OAAO,WAAW,YAAe,QAAQ,CAAC;AAAA,IACjD,GACA,KAAK,OAAO,cAAc;AAAA,MACxB,KAAK,OAAO,WAAW,cAAiB,QAAQ,CAAC;AAAA,IACnD,GACA,KAAK,OAAO,cAAc;AAAA,MACxB,KAAK,OAAO,WAAW,YAAe,QAAQ,CAAC;AAAA,IACjD,GAEA,KAAK,cAAc,QACd,KAAA,KAAK,UAAU,EAAK;AAAA,EAAA;AAE7B;ACvEa,MAAAuV,KAAyB,CAKpCziB,MACG;;AACH,QAAMtf,IAA0C,CAAC,GAC3CgiC,IAAmBC,GAAoB3iB,CAAI;AAEjD,aAAW4iB,KAAOF;AACZ,IAAAhiC,EAAAkiC,EAAI,IAAI,IAAIA;AAGlB,EAAI5iB,EAAK,kBACPtf,EAAI,cAAiB,IAAIssB,GAAWhN,EAAK,cAAc,QAAQ,GAC3Dtf,EAAA,cAAiB,IAAIwsB,GAAW,IAEhC/2B,IAAA6pB,EAAK,cAAc,aAAnB,QAAA7pB,EAA6B,cAC/BuK,EAAI,gBAAmB,IAAIqsB,GAAa/M,EAAK,aAAa,IAExDtf,EAAA,iBAAoB,IAAIihC,GAAe;AAAA,IACzC,QAAQ3hB,EAAK;AAAA,IACb,eAAeA,EAAK;AAAA,EAAA,CACrB,IAKCtf,EAAA,oBAAuB,IAAI0wB;AAAA,IAC7BpR,EAAK;AAAA,EACP,GACAtf,EAAI,cAAiB,IAAIk0B,GAA6B5U,EAAK,MAAM,GAC7Dtf,EAAA,WAAc,IAAI65B;AAAA,IACpBva,EAAK;AAAA,IACLA,EAAK;AAAA,EACP,GACAtf,EAAI,kBAAqB,IAAIk7B,GAAgC5b,EAAK,MAAM,GACxEtf,EAAI,YAAe,IAAIwvB,GAA2BlQ,EAAK,MAAa,GACpEtf,EAAI,cAAiB,IAAIs0B,GAAkBhV,EAAK,QAAQA,EAAK,YAAY,IAErEA,EAAK,cAAc,QACjBtf,EAAA,aAAgB,IAAIs1B,GAAwB,IAG9ChW,EAAK,iBACPtf,EAAI,eAAkB,IAAI+9B,GAA8Bze,EAAK,MAAa,IAGxEtf,EAAA,wBAA2B,IAAIq0B,GAA4B,GAE/Dr0B,EAAI,gBAAmB,IAAIu2B,GAAoBjX,EAAK,MAAM,GAEtDA,EAAK,aACHtf,EAAA,WAAc,IAAIwtB;AAAA,IACpBlO,EAAK;AAAA,IACLA,EAAK,SAAS;AAAA,IACdoN,GAAY;AAAA,EACd;AAGI,QAAAyV,IAA8B7iB,EAAK,qBAAqB,CAAC;AAC/D,aAAW4iB,KAAOC;AAChB,WAAOniC,EAAIkiC,CAAG;AAGT,SAAAliC;AACT;AAEA,IAAIoiC,KAAsB;AAK1B,MAAMH,KAAsB,CAK1B3iB,MACG;AACH,QAAM0iB,IAAmC;AAAA,IACvCK,GAAW;AAAA,IACXA,GAAW;AAAA,IACXA,GAAW;AAAA,IACXA,GAAW;AAAA,IACXA,GAAW;AAAA;AAAA,IAGXC;AAAA;AAAA,IAGA9tC,EAAU,OAAO;AAAA,MACf,MAAM;AAAA,MACN,uBAAuB,MAAM;AAAA,QAC3B8qB,EAAK,WAAW;AAAA,UACd,OAAO;AAAA,UACP,OAAO;AAAA,UACP,QAAQA,EAAK;AAAA,QACd,CAAA;AAAA,MAAA;AAAA,IACH,CACD;AAAA,IAED/qB,GAAS,UAAU;AAAA;AAAA,MAEjB,OAAO,CAAC,kBAAkB,cAAc,QAAQ;AAAA,MAChD,gBAAgB+qB,EAAK;AAAA,IAAA,CACtB;AAAA,IACDqR;AAAA;AAAA;AAAA,IAIA4R;AAAA;AAAA,IAGA3G;AAAA,IACAE;AAAA,IACAC;AAAA,IACAyG,GAAK,OAAO;AAAA,MACV,WAAW;AAAA,IACZ,CAAA,EAAE,UAAU;AAAA,MACX,iBAAiBpO;AAAA;AAAA,MAEjB,WAAWgO,KAAsB,KAAKjO;AAAA,IAAA,CACvC;AAAA,IACD,GAAG,OAAO,OAAO7U,EAAK,UAAU,EAAE,IAAI,CAACmjB,MAC9BA,EAAU,eAAe,KAAK,UAAU;AAAA,MAC7C,QAAQnjB,EAAK;AAAA,IAAA,CACd,CACF;AAAA,IAED2gB;AAAA,IAEAjV;AAAA,IACAgV;AAAA;AAAA,IAGAxrC,EAAU,OAAO;AAAA,MACf,MAAM;AAAA,MACN,uBAAuB;AACd,eAAA;AAAA,UACL,QAAQ,MACF8qB,EAAK,OAAO,gBAAgB,QAEvB,KAEF,KAAK,OAAO,SAAS,KAAK;AAAA,QAErC;AAAA,MAAA;AAAA,IACF,CACD;AAAA;AAAA,IAGD0hB;AAAA,IACAN,GAAe,UAAU;AAAA,MACvB,QAAQphB,EAAK;AAAA,MACb,eAAeA,EAAK;AAAA,IAAA,CACrB;AAAA,IACDwS,GAA2B,UAAU;AAAA,MACnC,QAAQxS,EAAK;AAAA,MACb,aAAaA,EAAK;AAAA,IAAA,CACnB;AAAA,IACDwhB,GAAW,UAAU;AAAA,MACnB,eAAexhB,EAAK;AAAA,IAAA,CACrB;AAAA,IACD,GAAG,OAAO,OAAOA,EAAK,kBAAkB,EACrC,OAAO,CAACvZ,MAAMA,EAAE,WAAW,UAAUA,EAAE,WAAW,MAAM,EACxD,IAAI,CAAC28B,MACGA,EAAkB,eAAgB,KAAK,UAAU;AAAA,MACtD,QAAQpjB,EAAK;AAAA,IAAA,CACd,CACF;AAAA,IAEH,GAAG,OAAO,OAAOA,EAAK,UAAU,EAAE,QAAQ,CAAC3d,MAClC;AAAA;AAAA,MAEL,IAAIA,EAAU,eAAe,sBAAsB,CAAI,GAAA;AAAA,QAAI,CAACugC,MAC1DA,EAAI,UAAU;AAAA,UACZ,QAAQ5iB,EAAK;AAAA,UACb,eAAeA,EAAK;AAAA,QACrB,CAAA;AAAA,MACH;AAAA;AAAA,MAEA3d,EAAU,eAAe,KAAK,UAAU;AAAA,QACtC,QAAQ2d,EAAK;AAAA,QACb,eAAeA,EAAK;AAAA,MACrB,CAAA;AAAA,IACH,CACD;AAAA,IACDyL,GAA+BzL,EAAK,MAAM;AAAA,IAC1C4K;AAAA,MACE5K,EAAK;AAAA,MACLA,EAAK,iBACF,CAACpE,MAKIA,EAAQ,oBAAoB;AAAA,IACtC;AAAA,IACA2N,GAAwBvJ,EAAK,MAAM;AAAA;AAAA;AAAA,IAInC,GAAIA,EAAK,kBAAkB,UAAaA,EAAK,gBACzC,CAAC4gB,EAAY,IACb,CAAC;AAAA,IACL,GAAI5gB,EAAK,WAAW,CAACoN,EAAW,IAAI,CAAA;AAAA,EACtC;AAEsB,SAAA0V,KAAA,IAEjB9iB,EAAK,iBAER0iB,EAAiB,KAAKW,EAAO,GAGxBX;AACT;AC1TA,SAASY,GAAYvsC,GAAgB,GAAW;AAC9C,QAAMuL,IAAkB,CAAC;AACzB,SAAAvL,EAAK,QAAQ,CAACoK,GAAOkH,GAAGtN,MAAM;AAC5B,IAAIA,MAAM,KACRuH,EAAS,KAAKnB,CAAK;AAAA,EACrB,CACD,GACMpJ,EAAS,KAAKuK,CAAQ;AAC/B;AAQgB,SAAAihC,GAAcC,GAAaxjC,GAAgB;AACzD,QAAMyjC,IAAkB,CAAC;AACzB,WAAS1oC,IAAI,GAAGA,IAAIyoC,EAAE,YAAYzoC;AAChC,QAAIyoC,EAAE,MAAMzoC,CAAC,EAAE,KAAK,SAAS;AAEzB,UAAA0oC,EAAS,SAAS,KAClBA,EAASA,EAAS,SAAS,CAAC,EAAE,KAAK,SAAS,SAC5C;AAEA,cAAMC,IAAYD,EAASA,EAAS,SAAS,CAAC,GACxCrF,IAAWsF,EAAU,KAAKA,EAAU,QAAQ,SAASF,EAAE,MAAMzoC,CAAC,CAAC,CAAC;AAC7D,QAAA0oC,EAAAA,EAAS,SAAS,CAAC,IAAIrF;AAAA,MAAA,OAC3B;AAEC,cAAAA,IAAWp+B,EAAO,MAAM,MAAM;AAAA,UAClC;AAAA,UACAwjC,EAAE,MAAMzoC,CAAC;AAAA,QACX;AACA,QAAA0oC,EAAS,KAAKrF,CAAQ;AAAA,MAAA;AAAA;AAGxB,MAAAqF,EAAS,KAAKD,EAAE,MAAMzoC,CAAC,CAAC;AAGxB,SAAAyoC,IAAAzrC,EAAS,KAAK0rC,CAAQ,GACnBD;AACT;AAegB,SAAA/tC,GAAgBiC,GAAcH,GAAkB;AAC9D,MAAIisC,IAAIzrC,EAAS,KAAKL,EAAM,OAAO;AAGnC,MAFA8rC,IAAID,GAAcC,GAAGjsC,EAAK,MAAM,MAAM,GAElC,CAACosC,GAAeH,GAAGjsC,CAAI;AAEzB,WAAO,IAAIS,EAAMwrC,GAAG9rC,EAAM,WAAWA,EAAM,OAAO;AAGpD,WAASqD,IAAI,GAAGA,IAAIyoC,EAAE,YAAYzoC;AAChC,QAAIyoC,EAAE,MAAMzoC,CAAC,EAAE,KAAK,KAAK,UAAU,gBAAgB;AACjD,YAAM7C,IAAU,CAACsrC,EAAE,MAAMzoC,CAAC,CAAC;AAKzB,UAAAA,IAAI,IAAIyoC,EAAE,cACVA,EAAE,MAAMzoC,IAAI,CAAC,EAAE,KAAK,SAAS,cAC7B;AACM,cAAA6oC,IAAcJ,EACjB,MAAMzoC,IAAI,CAAC,EACX,MAAM,CAAC,EACP,MAAM,CAAC;AAGR,SAAA6oC,EAAY,KAAK,SAAS,oBAC1BA,EAAY,KAAK,SAAS,sBAC1BA,EAAY,KAAK,SAAS,qBAE1B1rC,EAAQ,KAAKsrC,EAAE,MAAMzoC,IAAI,CAAC,CAAC,GACvByoC,IAAAF,GAAYE,GAAGzoC,IAAI,CAAC;AAAA,MAC1B;AAEF,YAAM8oC,IAAYtsC,EAAK,MAAM,OAAO,MAAM,eAAe;AAAA,QACvD;AAAA,QACAW;AAAA,MACF;AACI,MAAAsrC,IAAAA,EAAE,aAAazoC,GAAG8oC,CAAS;AAAA,IAAA;AAGnC,SAAO,IAAI7rC,EAAMwrC,GAAG9rC,EAAM,WAAWA,EAAM,OAAO;AACpD;AAOA,SAASisC,GAAe/rC,GAAoBL,GAAkB;;AACtD,QAAAusC,IAAqBlsC,EAAS,eAAe,GAC7CmsC,MACJ5tC,IAAAyB,EAAS,eAAT,gBAAAzB,EAAqB,KAAK,KAAK,aAAY,WACvC6tC,MACJ5tC,IAAAwB,EAAS,eAAT,gBAAAxB,EAAqB,KAAK,KAAK,aAAY;AAE7C,MAAI0tC,GAAoB;AACtB,QAAIC;AAIK,aAAA;AAGT,QAAIC,GAAqB;AAIjB,YAAA5hC,IAAY1C,EAA0BnI,EAAK,KAAK;AACtD,UAAI6K,EAAU;AASZ,eAAO,EAPLA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY;AAAA,IAQtD;AAAA,EACF;AAGK,SAAA;AACT;ACvHO,MAAM6hC,KAAN,MAAMA,WAA8BC,GAAa;AAAA,EAyB5C,YACRv1B,GACAlO,GACA;AAYA,UAAM,EAAE,GAAGkO,GAAS,SAAS,QAAW;AAvClC,IAAAsR,EAAA;AA6QD;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,eAAQ,CACbkkB,GACA9uC,GACA+uC,MACG;AACH,MAAK/uC,KAGH,KAAK,QAAQ,UAAUA,GAClB,KAAA,sBAAsB8uC,GAAiBC,CAAgB,KAH5D,KAAK,QAAQ;AAAA,IAKjB;AAtOE,UAAMpkC,IAAS,KAAK;AAChB,QAAAqkC;AACE,UAAAC,IAAmBtkC,EAAO,MAAM,IAAI;AACzC,IAAAA,EAAO,MAAM,IAAY,gBAAgB,IAAI6rB,MAAc;AAC1D,UAAIwY;AACK,eAAAA;AAET,YAAM3jC,IAAM4jC,EAAiB,MAAMtkC,EAAO,MAAM,KAAK6rB,CAAI,GAGnDx0B,IAAW,KAAK,MAAM,KAAK,UAAUqJ,EAAK,OAAA,CAAQ,CAAC;AACzD,aAAArJ,EAAS,QAAQ,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,kBAElCgtC,IAAAvnC,GAAK,SAASkD,GAAQ3I,CAAQ,GAC/BgtC;AAAA,IACT;AAEI,QAAAlmC;AAEA,QAAA;AACI,YAAAomC,IAAU51B,KAAA,gBAAAA,EAAS,QAAQ;AAAA,QAAI,CAAC61B,MACpC/pC,GAAY+pC,GAAG,KAAK,QAAQ/jC,CAAW,EAAE,OAAO;AAAA;AAE5C,MAAAtC,IAAAsmC;AAAA,QACJ;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,SAASF;AAAA,YAAA;AAAA,UACX;AAAA,QAEJ;AAAA,QACA,KAAK;AAAA,QACL,KAAK,QAAQ;AAAA,MACf;AAAA,aACO5T,GAAG;AAEF,oBAAA;AAAA,QACN;AAAA,QACAA;AAAA,MACF,GACM,IAAI;AAAA,QACR,sEACE,CAAC,KAAK,UAAUhiB,EAAQ,OAAO;AAAA,MACnC;AAAA,IAAA;AAMG,SAAA,SAAS+1B,GAAY,OAAO;AAAA,MAC/B,KAAAvmC;AAAA,MACA,QAAQ,KAAK;AAAA;AAAA,IAAA,CAEd;AAAA,EAAA;AAAA,EAGH,IAAI,QAAQ;AACV,WAAI,KAAK,SACF,KAAA,SAAS,KAAK,KAAK,QAEnB,KAAK;AAAA,EAAA;AAAA,EAGd,SAASnI,GAA0B;AAC7B,QAAA,CAAC,KAAK,MAAM;AAEd,WAAK,SAAS,KAAK,MAAM,MAAMA,CAAW,GAC1C,KAAK,KAAK,eAAe;AAAA,QACvB,QAAQ;AAAA,QACR,aAAAA;AAAA,MAAA,CACD;AACD;AAAA,IAAA;AAQE,QAAA,KAAK,KAAK;AACZ;AAGF,QAAI,KAAK,wBAAwB;AAE9B,WAAa,oBAAoBA,CAAW;AAE7C;AAAA,IAAA;AAGI,UAAA,EAAE,OAAA2J,GAAO,cAAc0L,EAAA,IAC3B,KAAK,MAAM,iBAAiBrV,CAAW,GACnC2uC,IAAsB,CAAC,KAAK,MAAM,UAAU,GAAGhlC,EAAM,SAAS;AAEpE,SAAK,KAAK,qBAAqB;AAAA,MAC7B,QAAQ;AAAA,MACR,aAAA3J;AAAA,MACA,WAAW2J;AAAA,IAAA,CACZ,GACI,KAAA,KAAK,YAAYA,CAAK,GAC3B,KAAK,KAAK,eAAe;AAAA,MACvB,QAAQ;AAAA,MACR,aAAA3J;AAAA,IAAA,CACD,GAEG2uC,KACF,KAAK,KAAK,mBAAmB;AAAA,MAC3B,QAAQ;AAAA,MACR,aAAA3uC;AAAA,IAAA,CACD;AAGG,UAAA4uC,IAAQ5uC,EAAY,QAAQ,OAAO,GACnC6uC,IAAO7uC,EAAY,QAAQ,MAAM;AAkBvC,IAhBI4uC,KACF,KAAK,KAAK,SAAS;AAAA,MACjB,QAAQ;AAAA,MACR,OAAOA,EAAM;AAAA,MACb,aAAA5uC;AAAA,IAAA,CACD,GAGC6uC,KACF,KAAK,KAAK,QAAQ;AAAA,MAChB,QAAQ;AAAA,MACR,OAAOA,EAAK;AAAA,MACZ,aAAA7uC;AAAA,IAAA,CACD,GAGC,GAACA,EAAY,cAAcA,EAAY,QAAQ,eAAe,OAIlE,KAAK,KAAK,UAAU;AAAA,MAClB,QAAQ;AAAA,MACR,aAAAA;AAAA,IAAA,CACD,GACD,KAAK,KAAK,aAAa;AAAA,MACrB,QAAQ;AAAA,MACR,aAAAA;AAAA,MACA,sBAAsBqV,EAAqB,MAAM,CAAC;AAAA,IAAA,CACnD;AAAA,EAAA;AAAA;AAAA;AAAA,EAKH,qBAAqB;AACnB,QAAI,KAAK;AACP,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEG,SAAA,SAAS,KAAK,MAAM,YAAY;AAAA,MACnC,SAAS,KAAK,iBAAiB;AAAA,IAAA,CAChC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMK,sBACN84B,GACAC,GACA;AACC,SAAa,mBAAmBA;AAEjC,UAAMU,IAAiB,CAAC;AACxB,SAAK,iBAAiB,WAAW,QAAQ,CAACnpB,MAAc;AACtD,MAAIA,EAAU,SAAS,UAAUA,EAAU,OAAO,gBAGhDmpB,EAAUnpB,EAAU,IAAI,IACtBA,EAAU,OAAO,YAAYwoB,CAAe;AAAA,IAChD,CACD,GAED,KAAK,OAAO,IAAIY;AAAA,MACd,EAAE,OAAO,KAAK,QAAQ,QAAe;AAAA;AAAA,MACrC;AAAA,QACE,GAAG,KAAK,QAAQ;AAAA;AAAA,QAEhB,qBAAqB,KAAK,SAAS,KAAK,IAAI;AAAA,QAC5C,OAAO,KAAK;AAAA,QACZ,WAAAD;AAAA,QACA,WAAW,KAAK,iBAAiB;AAAA,MAAA;AAAA,IAErC;AAOM,UAAAhvC,IAAW,KAAK,MAAM,YAAY;AAAA,MACtC,SAAS,KAAK,iBAAiB;AAAA,IAAA,CAChC;AAEI,SAAA,KAAK,YAAYA,CAAQ,GAI9B,KAAK,SAAS;AAAA,MACZ,KAAK,QAAQ,aACX,KAAK,QAAQ,QAAQ,aAAa,mBAAmB,MAAM;AAAA,MAC7D,EAAE,gBAAgB,GAAM;AAAA,IAC1B,GACA,KAAK,KAAK,UAAU,EAAE,QAAQ,MAAM,GACpC,KAAK,gBAAgB;AAAA,EAAA;AAoBzB;AAvREmqB,EAHWgkB,IAGG,UAAS,CACrBt1B,GACAlO,MACG;;AAIG,QAAAukC,KAAgB7uC,IAAA,yCAAY,WAAZ,gBAAAA,EAAoB;AAC1C,EAAI,SAAOC,IAAA,yCAAY,WAAZ,gBAAAA,EAAoB,cAAe,QACjC,WAAA,OAAO,aAAc,MACvB;AAGP,MAAA;AACK,WAAA,IAAI6tC,GAAsBt1B,GAASlO,CAAW;AAAA,EAAA,UACrD;AACA,IAAIukC,MACF,WAAW,OAAO,aAAaA;AAAA,EACjC;AAEJ;AAvBK,IAAMC,KAANhB;AA4RNgB,GAAsB,UAAkB,aAAa,WAAY;AAOhE,OAAK,QAAQ,UAAU,KAAK,QAAQ,SAAS;AAC/C;ACuFA,MAAMC,KAAyB;AAAA,EAC7B,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,sBAAsB;AACxB;AAEO,MAAMC,WAIHxZ,GAEP;AAAA,EAyHS,YACWhd,GACnB;;AACM,UAAA;AAxHQ;AAAA;AAAA;AAAA,IAAAsR,EAAA;AAKT;AAAA;AAAA;AAAA,IAAAA,EAAA,oBAAiD,CAAC;AASzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,kBAAoB;AAEpB,IAAAA,EAAA;AAST;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,yBACL;AAOK;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,wCAA6B,QAAQ;AAK5B;AAAA;AAAA;AAAA,IAAAA,EAAA;AAKA;AAAA;AAAA;AAAA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAKA,IAAAA,EAAA;AAKA,IAAAA,EAAA;AAKA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAIA,IAAAA,EAAA;AAEC,IAAAA,EAAA;AAKD;AAAA;AAAA;AAAA,IAAAA,EAAA;AAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA;AAIR,IAAAA,EAAA,gCAAyD,CAAC;AAC1D,IAAAA,EAAA,8BAAuD,CAAC;AAEhD,IAAAA,EAAA;AACA,IAAAA,EAAA;AAIA;AAAA;AAAA;AAAA,IAAAA,EAAA;AAkSR;AAAA;AAAA;AAAA,IAAAA,EAAA,2BAAwC;AA4IzC;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,eAAQ,CACbuY,GACA4L,MACG;AACH,WAAK,cAAc,MAAM,MAAM5L,GAAe4L,CAAgB;AAAA,IAChE;AAhaqB,SAAA,UAAAz1B;AAGnB,UAAMy2B,IAAUz2B;AAChB,QAAIy2B,EAAQ;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QAAIA,EAAQ;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QAAIA,EAAQ;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QAAIA,EAAQ;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGG,SAAA,aAAaz2B,EAAQ,cAAc02B,IACxC,KAAK,WAAW;AAAA,MACd,QAAQ;AAAA,QACN,cAAYlvC,IAAAwY,KAAA,gBAAAA,EAAS,WAAT,gBAAAxY,EAAiB,eAAc;AAAA,QAC3C,uBAAqBC,IAAAuY,KAAA,gBAAAA,EAAS,WAAT,gBAAAvY,EAAiB,wBAAuB;AAAA,QAC7D,iBAAeoC,IAAAmW,KAAA,gBAAAA,EAAS,WAAT,gBAAAnW,EAAiB,kBAAiB;AAAA,QACjD,WAASC,IAAAkW,KAAA,gBAAAA,EAAS,WAAT,gBAAAlW,EAAiB,YAAW;AAAA,MACvC;AAAA,MACA,WAAW;AAAA,QACT,qBAAmBC,IAAAiW,KAAA,gBAAAA,EAAS,cAAT,gBAAAjW,EAAoB,sBAAqB;AAAA,QAC5D,mBAAiB+W,IAAAd,KAAA,gBAAAA,EAAS,cAAT,gBAAAc,EAAoB,oBAAmB;AAAA,QACxD,sBAAoBC,IAAAf,KAAA,gBAAAA,EAAS,cAAT,gBAAAe,EAAoB,uBAAsB,CAAC;AAAA,QAC/D,qBAAmBC,IAAAhB,KAAA,gBAAAA,EAAS,cAAT,gBAAAgB,EAAoB,sBAAqB;AAAA,MAAA;AAAA,IAEhE;AAGA,UAAM21B,IAAa;AAAA,MACjB,eAAe;AAAA,MACf,QAAQ32B,EAAQ,UAAUoR,GAAgB,OAAO;AAAA,MACjD,WAAW;AAAA,MACX,GAAGpR;AAAA,MACH,cAAc;AAAA,QACZ,GAAG,KAAK,WAAW;AAAA,QACnB,GAAGA,EAAQ;AAAA,MAAA;AAAA,IAEf;AAEA,QAAI22B,EAAW,YAAY,CAACA,EAAW;AAC/B,YAAA,IAAI,MAAM,8CAA8C;AAGhE,SAAK,eAAeA,EAAW,cAG/B,KAAK,SAASA,EAAW,QACpB,KAAA,uBAAuBA,EAAW,OAAO,YACzC,KAAA,+BAA+BA,EAAW,OAAO,oBACjD,KAAA,uBAAuBA,EAAW,OAAO,YAE9C,KAAK,aAAa7C,GAAuB;AAAA,MACvC,QAAQ;AAAA,MACR,eAAe6C,EAAW,iBAAiB,CAAC;AAAA,MAC5C,YAAY,KAAK,OAAO;AAAA,MACxB,YAAY,KAAK,OAAO;AAAA,MACxB,oBAAoB,KAAK,OAAO;AAAA,MAChC,eAAeA,EAAW;AAAA,MAC1B,eAAeA,EAAW;AAAA,MAC1B,mBAAmBA,EAAW;AAAA,MAC9B,gBAAgBA,EAAW;AAAA,MAC3B,YAAYA,EAAW,cAAc;AAAA,MACrC,cAAc/mB,EAA8B,SAAS,IAAI;AAAA,MACzD,YAAY,KAAK,QAAQ,cAAcgnB;AAAA,MACvC,cAAcD,EAAW;AAAA,MACzB,aAAaA,EAAW;AAAA,MACxB,mBAAmBA,EAAW,qBAAqB;AAAA,MACnD,UAAUA,EAAW;AAAA,MACrB,cAAcA,EAAW;AAAA,IAAA,CAC1B,MAGAE,IAAAF,EAAW,mBAAX,gBAAAE,EAA2B,eAAc,CAAA,GAAI,QAAQ,CAAC5C,MAAQ;AACxD,WAAA,WAAWA,EAAI,IAAI,IAAIA;AAAA,IAAA,CAC7B;AAGD,aAASA,KAAO0C,EAAW,cAAc,CAAA,GAAI;AACvC,MAAA,OAAO1C,KAAQ,eAEjBA,IAAMA,EAAI,IAAI;AAEV,YAAAjuC,IAAOiuC,EAAI,YAAoB,IAAI;AACzC,UAAI,CAACjuC;AACH,cAAM,IAAI;AAAA,UACR,aAAaiuC,EAAI,YAAY,IAAI;AAAA,QACnC;AAEE,UAAA,KAAK,WAAWjuC,CAAG;AACrB,cAAM,IAAI;AAAA,UACR,aAAaiuC,EAAI,YAAY,IAAI,4BAA4BjuC,CAAG;AAAA,QAClE;AAEG,WAAA,WAAWA,CAAG,IAAIiuC;AAAA,IAAA;AAuCzB,QAnCO,OAAA,QAAQ0C,EAAW,eAAe,CAAA,CAAE,EAAE,QAAQ,CAAC,CAAC3wC,GAAKiuC,CAAG,MAAM;AAInE,YAAM6C,IAAW,OAAO7C,KAAQ,aAAaA,EAF9B,IAEwC,IAAIA;AACvD,UAAA,EAAE,YAAY6C,IAAW;AAEtB,aAAA,WAAW9wC,CAAG,IAAI8wC;AACvB;AAAA,MAAA;AAGF,WAAK,WAAW9wC,CAAG,IAAI,IAAK,cAAcq3B,EAAmB;AAAA,QAC3D,OAAc,MAAM;AACX,iBAAAr3B;AAAA,QAAA;AAAA,QAET,cAAc;AACN,gBAAA,GACD,KAAA,qBAAqB8wC,EAAS,MAAM;AAAA,QAAA;AAAA,QAE3C,IAAW,WAAW;AACpB,iBAAOA,EAAS;AAAA,QAAA;AAAA,MAClB,EACC;AAAA,IAAA,CACJ,GAEI,KAAA,oBAAoB,KAAK,WAAW,mBACpC,KAAA,cAAc,KAAK,WAAW,aAC9B,KAAA,WAAW,KAAK,WAAW,UAC3B,KAAA,kBAAkB,KAAK,WAAW,iBAClC,KAAA,YAAY,KAAK,WAAW,WAC5B,KAAA,eAAe,KAAK,WAAW,cAC/B,KAAA,WAAW,KAAK,WAAW,UAC3B,KAAA,sBAAsB,KAAK,WAAW,eACtC,KAAA,iBAAiB,KAAK,WAAW,gBAElCH,EAAW,YAAY;AACzB,YAAMI,IAAaJ,EAAW;AACzB,WAAA,aAAa,OAAO5zB,GAAMM,OAAY;AACzC,aAAK,uBAAuB;AAAA,UAAQ,CAAC+Z,MACnCA,EAAS,MAAM,MAAM,CAAC/Z,EAAO,CAAC;AAAA,QAChC;AACI,YAAA;AACK,iBAAA,MAAM0zB,EAAWh0B,GAAMM,EAAO;AAAA,QAAA,UACrC;AACA,eAAK,qBAAqB;AAAA,YAAQ,CAAC+Z,MACjCA,EAAS,MAAM,MAAM,CAAC/Z,EAAO,CAAC;AAAA,UAChC;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA;AAGF,SAAK,iBAAiBszB,EAAW,gBACjC,KAAK,WAAWA,EAAW;AAE3B,UAAMK,IACJ,iBAAiB,KAAK,cACtB,yBAAyB,KAAK;AAE5B,IAAAA,KAAwBL,EAAW,kBAE7B,QAAA;AAAA,MACN;AAAA,IACF;AAGI,UAAAM,IACJN,EAAW,mBACVK,IACG;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,IAAI;AAAA,MAAA;AAAA,IACN,IAEF;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,IAAI1wC,GAAS,QAAQ,WAAW;AAAA,MAAA;AAAA,IAClC;AAGR,QAAI,CAAC,MAAM,QAAQ2wC,CAAc,KAAKA,EAAe,WAAW;AAC9D,YAAM,IAAI;AAAA,QACR,mEACEA;AAAA,MACJ;AAGF,UAAMlD,IAAmB;AAAA,MACvB,GAAG,OAAO,QAAQ,KAAK,UAAU,EAAE,IAAI,CAAC,CAAC/tC,GAAKiuC,CAAG,MAAM;AACrD,YACEA,aAAe1tC,KACf0tC,aAAeiD,MACfjD,aAAe/9B;AAGR,iBAAA+9B;AAGT,YAAI,EAAAA,aAAe5W,KAAsB,CAAC4W,EAAI,QAAQ;AAKtD,iBAAO1tC,EAAU,OAAO;AAAA,YACtB,MAAMP;AAAA,YACN,UAAUiuC,EAAI;AAAA,YACd,uBAAuB,MAAMA,EAAI;AAAA,UAAA,CAClC;AAAA,MACF,CAAA;AAAA,IACD,EAAA,OAAO,CAACA,MAA0BA,MAAQ,MAAS,GAE/CkD,IAA8C;AAAA,MAClD,GAAGZ;AAAA,MACH,GAAGI,EAAW;AAAA,MACd,SAASM;AAAA,MACT,YAAYlD;AAAA,MACZ,aAAa;AAAA,QACX,IAAGqD,IAAAT,EAAW,mBAAX,gBAAAS,EAA2B;AAAA,QAC9B,YAAY;AAAA;AAAA;AAAA;AAAA,UAIV,UAAU;AAAA,UACV,IAAGC,KAAAC,IAAAX,EAAW,mBAAX,gBAAAW,EAA2B,gBAA3B,gBAAAD,EAAwC;AAAA,UAC3C,IAAGE,IAAAZ,EAAW,kBAAX,gBAAAY,EAA0B;AAAA,UAC7B,OAAOzsC;AAAA,YACL;AAAA,YACA6rC,EAAW,gBAAgB,sBAAsB;AAAA,cACjDa,KAAAC,IAAAd,EAAW,kBAAX,gBAAAc,EAA0B,WAA1B,gBAAAD,EAAkC,UAAS;AAAA,UAAA;AAAA,QAE/C;AAAA,QACA,iBAAA1wC;AAAA,MAAA;AAAA,IAEJ;AAEI,IAAC,KAAK,WAYH,KAAA,WAAW4wC,GAAUP,EAAc,UAAW,KAXnD,KAAK,gBAAgBb,GAAsB;AAAA,MACzCa;AAAA,MACA,KAAK,OAAO;AAAA,IACd,GAIK,KAAA,WAAW,KAAK,cAAc,SAMhC,KAAA,SAAS,OAAO,kBAAkB,MACvC,KAAK,KAAK,QAAQ;AAAA,EAAA;AAAA,EAlRpB,OAAc,OAIZn3B,IAAsE,IAAI;AACnE,WAAA,IAAIw2B,GAA2Cx2B,CAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiSxD,KAAK23B,GAAkB;AAC5B,QAAI,KAAK;AACP,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEI,UAAA3mC,IAAQ,KAAK,cAAc,OAC3BpI,IAAO,KAAK,cAAc;AAGzB,WAAA+uC,EAAQ3mC,GAFE,CAACzJ,MAAoB,KAAK,cAAc,SAASA,CAAE,GAEpCqB,CAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAe/B,QAAQ+uC,GAA2B;AACxC,QAAI,KAAK;AACP,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEI,UAAA3mC,IAAQ,KAAK,cAAc,OAC3BpI,IAAO,KAAK,cAAc;AAEzB,WAAA+uC,EAAQ3mC,GAAO,QAAWpI,CAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBhC,SACLw0B,GAOG;AACH,QAAI,KAAK;AAEA,aAAAA,EAAS,KAAK,iBAAiB;AAGpC,QAAA;AAEG,WAAA,oBAAoB,KAAK,cAAc,MAAM;AAG5C,YAAAlE,IAASkE,EAAS,KAAK,iBAAiB,GAGxCwa,IAAW,KAAK;AAEtB,kBAAK,oBAAoB,MAEvBA;AAAA,OAECA,EAAS,cACRA,EAAS,gBACTA,EAAS,oBACTA,EAAS,kBACT,CAACA,EAAS,cAGP,KAAA,cAAc,SAASA,CAAQ,GAG/B1e;AAAA,IAAA,UACP;AAEA,WAAK,oBAAoB;AAAA,IAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYK,UACL+a,GACAjuC,IAAMiuC,EAAI,OACP;AACG,UAAAjnB,IAAY,KAAK,WAAWhnB,CAAG;AACrC,QAAI,CAACgnB;AACH,YAAM,IAAI,MAAM,aAAahnB,CAAG,YAAY;AAEvC,WAAAgnB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBT,IAAW,mBAAmB;AAC5B,QAAI,KAAK;AACP,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,WAAO,KAAK,cAAc;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5B,IAAW,kBAAkB;AAC3B,WAAO,KAAK,cAAc;AAAA,EAAA;AAAA,EAG5B,IAAW,aAAa;;AACtB,YAAOxlB,IAAA,KAAK,oBAAL,gBAAAA,EAAsB;AAAA,EAAA;AAAA,EAGxB,YAAY;;AACV,aAAAA,IAAA,KAAK,oBAAL,gBAAAA,EAAsB,eAAc;AAAA,EAAA;AAAA,EAGtC,QAAQ;;AACb,KAAAA,IAAA,KAAK,oBAAL,QAAAA,EAAsB;AAAA,EAAM;AAAA,EAGvB,cAAc41B,GAAsC;AACpD,gBAAA,uBAAuB,KAAKA,CAAQ,GAElC,MAAM;AACX,YAAM/2B,IAAQ,KAAK,uBAAuB,QAAQ+2B,CAAQ;AAC1D,MAAI/2B,IAAQ,MACL,KAAA,uBAAuB,OAAOA,GAAO,CAAC;AAAA,IAE/C;AAAA,EAAA;AAAA,EAGK,YAAY+2B,GAAsC;AAClD,gBAAA,qBAAqB,KAAKA,CAAQ,GAEhC,MAAM;AACX,YAAM/2B,IAAQ,KAAK,qBAAqB,QAAQ+2B,CAAQ;AACxD,MAAI/2B,IAAQ,MACL,KAAA,qBAAqB,OAAOA,GAAO,CAAC;AAAA,IAE7C;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMF,IAAW,iBAAqD;AAC9D,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,IAAW,WAA+C;AACjD,WAAA,KAAK,SAAS,CAACkB,MACbqM,GAAYrM,EAAG,KAAK,KAAK,QAAQ,CACzC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUI,SACLiG,GAC8C;AACvC,WAAA,KAAK,SAAS,CAACjG,MAAO8sB,GAAS9sB,EAAG,KAAKiG,CAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYzD,aACLA,GAC8C;AACvC,WAAA,KAAK,SAAS,CAACjG,MAAO+sB,GAAa/sB,EAAG,KAAKiG,CAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW7D,aACLA,GAC8C;AACvC,WAAA,KAAK,SAAS,CAACjG,MAAOitB,GAAajtB,EAAG,KAAKiG,CAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU7D,eACLA,GAC8C;AACvC,WAAA,KAAK,SAAS,CAACjG,MAAOktB,GAAeltB,EAAG,KAAKiG,CAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ/D,aACL4vB,GACAya,IAAU,IACJ;AACA,UAAAhkC,IAAS,KAAK,SAAS,MAAM;AAEnC,IAAIgkC,KACFhkC,EAAO,QAAQ;AAGjB,aAASikC,EACPC,GACS;AACT,iBAAWnsC,KAASmsC,GAAY;AAC1B,YAAA3a,EAASxxB,CAAK,MAAM;AACf,iBAAA;AAGH,cAAA+H,IAAWkkC,IACbjsC,EAAM,SAAS,QAAQ,YACvBA,EAAM;AAEN,YAAA,CAACksC,EAAmBnkC,CAAQ;AACvB,iBAAA;AAAA,MACT;AAGK,aAAA;AAAA,IAAA;AAGT,IAAAmkC,EAAmBjkC,CAAM;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,sBAAsBupB,GAAsB;AAC5C,SAAA,cAAc,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnC,wBAAwBA,GAAsB;AAC9C,SAAA,cAAc,GAAG,mBAAmBA,CAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5C,wBAIL;AACA,WAAO,KAAK,SAAS,CAAC71B,MAAOqvB,GAAsBrvB,CAAE,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASjD,sBACLyvB,GACAvZ,IAA6B,SAC7B;AACA,WAAO,KAAK;AAAA,MAAS,CAAClW,MACpBwvB,GAAsBxvB,GAAIyvB,GAAavZ,CAAS;AAAA,IAClD;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASK,eAAiE;AACtE,WAAO,KAAK,SAAS,CAAClW,MAAO0tB,GAAa1tB,CAAE,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUxC,wBAAwB;AAC7B,WAAO,KAAK,SAAS,CAACA,MAAOmvB,GAAsBnvB,CAAE,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjD,aAAamuB,GAA6BC,GAA2B;AACnE,WAAA,KAAK,SAAS,CAACpuB,MAAOkuB,GAAaluB,GAAImuB,GAAYC,CAAQ,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrE,IAAW,aAAsB;AAC3B,QAAA,CAAC,KAAK,eAAe;AACnB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,mCAAmC;AAE9C,aAAA;AAAA,IAAA;AAET,WAAO,KAAK,cAAc,eAAe,SACrC,KACA,KAAK,cAAc;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzB,IAAW,WAAWqiB,GAAmB;AACnC,QAAA,CAAC,KAAK,eAAe;AACnB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,mCAAmC;AAGrD;AAAA,IAAA;AAEF,IAAI,KAAK,cAAc,QAAQ,aAAaA,KACrC,KAAA,cAAc,YAAYA,CAAQ;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWK,aACLz6B,GACAC,GACAC,IAAgC,UAChC;AACA,WAAO,KAAK;AAAA,MAAS,CAAClW,MACpB+V,GAAa/V,GAAIgW,GAAgBC,GAAgBC,CAAS;AAAA,IAC5D;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUK,YACLiC,GACArK,GACA;AACO,WAAA,KAAK,SAAS,CAAC9N,MAAOkY,GAAYlY,GAAImY,GAAerK,CAAM,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO9D,aAAawI,GAAmC;AACrD,WAAO,KAAK;AAAA,MACV,CAACtW,MAAOqW,GAAsBrW,GAAIsW,GAAgB,CAAE,CAAA,EAAE;AAAA,IACxD;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUK,cACLA,GACAN,GACA;AACA,WAAO,KAAK;AAAA,MAAS,CAAChW,MACpBqW,GAAsBrW,GAAIsW,GAAgBN,CAAc;AAAA,IAC1D;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMK,OAAO;AACR,WAAA,KAAK,QAAQ,gBACR,KAAK,KAAK06B,EAAW,IAGvB,KAAK,KAAKC,EAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,OAAO;AACR,WAAA,KAAK,QAAQ,gBACR,KAAK,KAAKC,EAAW,IAEvB,KAAK,KAAKC,EAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhB,oBACL7uC,GACA,EAAE,iBAAA8uC,IAAkB,GAAM,IAAmC,CAAA,GAC7D;AACA,UAAMl9B,IAAQ7F,EAAqB/L,GAAS,KAAK,QAAQ;AAEpD,SAAA,SAAS,CAAChC,MAAO;AACpB,MAAAstB;AAAA,QACEttB;AAAA,QACA;AAAA,UACE,MAAMA,EAAG,UAAU;AAAA,UACnB,IAAIA,EAAG,UAAU;AAAA,QACnB;AAAA,QACA4T;AAAA,QACA;AAAA,UACE,iBAAAk9B;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA,CACD;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMI,kBAAkB;AAChB,WAAA,KAAK,SAAS,CAAC9wC,MAAO;AAC3B,YAAM0L,IAA0B,CAAC,GAC3B4H,IAAQtT,EAAG,UAAU,IAAI,MAAM;AAErC,iBAAW4L,KAAQ0H,GAAO;AACxB,cAAM3M,IAAS,KAAK,OAAO,YAAYiF,EAAK,KAAK,IAAI;AACrD,YAAI,CAACjF,GAAQ;AACX;AAAA,UAEEiF,EAAK,KAAK,SAAS;AAAA,UAEnB,CAACA,EAAK,KAAK,KAAK,mBAGhB,QAAQ,KAAK,iCAAiCA,EAAK,KAAK,IAAI;AAG9D;AAAA,QAAA;AAEE,QAAAjF,EAAO,eAAe,YACvB+E,EAAe/E,EAAO,IAAI,IAAI,KAE9B+E,EAAe/E,EAAO,IAAI,IAAIiF,EAAK,MAAM;AAAA,MAC5C;AAGK,aAAAF;AAAA,IAAA,CACR;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOI,UAAUA,GAAyB;AACxC,eAAW,CAAC6H,GAAOrP,CAAK,KAAK,OAAO,QAAQwH,CAAM,GAAG;AACnD,YAAM/E,IAAS,KAAK,OAAO,YAAY4M,CAAK;AAC5C,UAAI,CAAC5M;AACH,cAAM,IAAI,MAAM,SAAS4M,CAAK,2BAA2B;AAEvD,UAAA5M,EAAO,eAAe;AACnB,aAAA,cAAc,SAAS,QAAQ4M,CAAK;AAAA,eAChC5M,EAAO,eAAe;AAC/B,aAAK,cAAc,SAAS,QAAQ4M,GAAO,EAAE,aAAarP,GAAO;AAAA;AAE3D,cAAA,IAAItB,EAAqB+D,EAAO,UAAU;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOK,aAAa+E,GAAyB;AAC3C,eAAW6H,KAAS,OAAO,KAAK7H,CAAM;AAC/B,WAAA,cAAc,SAAS,UAAU6H,CAAK;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAOK,aAAa7H,GAAyB;AAC3C,eAAW,CAAC6H,GAAOrP,CAAK,KAAK,OAAO,QAAQwH,CAAM,GAAG;AACnD,YAAM/E,IAAS,KAAK,OAAO,YAAY4M,CAAK;AAC5C,UAAI,CAAC5M;AACH,cAAM,IAAI,MAAM,SAAS4M,CAAK,2BAA2B;AAEvD,UAAA5M,EAAO,eAAe;AACnB,aAAA,cAAc,SAAS,WAAW4M,CAAK;AAAA,eACnC5M,EAAO,eAAe;AAC/B,aAAK,cAAc,SAAS,WAAW4M,GAAO,EAAE,aAAarP,GAAO;AAAA;AAE9D,cAAA,IAAItB,EAAqB+D,EAAO,UAAU;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMK,kBAAkB;AAChB,WAAA,KAAK,SAAS,CAAC3G,MACbA,EAAG,IAAI,YAAYA,EAAG,UAAU,MAAMA,EAAG,UAAU,EAAE,CAC7D;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMI,qBAAqB;AAC1B,WAAO,KAAK,cAAc,cAAc,MAAM,EAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3C,WAAWoF,GAAaoO,GAAe;AAC5C,QAAIpO,MAAQ;AACV;AAEI,UAAAwG,IAAO,KAAK,SAAS,KAAK,QAAQ,EAAE,MAAMxG,GAAK;AAChD,SAAA,SAAS,CAACpF,MAAO;AACpB,YAAM,EAAE,MAAAgT,GAAM,IAAAC,EAAG,IAAIjT,EAAG;AAExB,MAAIwT,IACCxT,EAAA,WAAWwT,GAAMR,GAAMC,CAAE,EAAE,QAAQD,GAAMA,IAAOQ,EAAK,QAAQ5H,CAAI,IAEpE5L,EAAG,aAAa6e,EAAc,OAAO7e,EAAG,KAAKiT,CAAE,CAAC,EAAE;AAAA,QAChDD;AAAA,QACAC;AAAA,QACArH;AAAA,MACF;AAAA,IACF,CACD;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMI,eAAe;AACpB,WAAOghB,GAAa,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMnB,YAAY;AACjB,IAAAF,GAAU,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMT,iBAAiB;AACtB,WAAOG,GAAe,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,cAAc;AACnB,IAAAF,GAAY,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQX,eAAe;AACpB,WAAOf,GAAa,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQnB,iBAAiB;AACtB,WAAOE,GAAe,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU5B,MAAa,kBACXxf,IAAoD,KAAK,UACxC;AAEjB,WADiBqN,GAA2B,KAAK,UAAU,IAAI,EAC/C,aAAarN,GAAQ,EAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYzC,MAAa,iBACXA,GACiB;AAEjB,WADiBiO,GAA6B,KAAK,UAAU,IAAI,EACjD,gBAAgBjO,GAAQ,EAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS5C,MAAa,qBACXuN,GAC6C;AACtC,WAAA0X,GAAa1X,GAAM,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASzC,MAAa,sBACXvN,IAAoD,KAAK,UACxC;AACjB,WAAOkkB,GAAiBlkB,GAAQ,KAAK,UAAU,MAAM,CAAA,CAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUzD,MAAa,yBACXulB,GAC6C;AACtC,WAAAC,GAAiBD,GAAU,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAM1C,4BAA4BsE,GAAuC;AACpE,QAAA,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGD,SAAK,WAAW,cAAkC,WAAWA,CAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS7D,SACLN,GASA;AACA,QAAI,KAAK;AAEP;AAGF,UAAM4B,IAAK,CAAC;AAAA,MACV,aAAA33B;AAAA,MACA,sBAAAqV;AAAA,IAAA,MAII;AACJ,MAAA0gB,EAAS,MAAM;AAAA,QACb,YAAY,MACV3gB,GAA8BpV,GAAaqV,CAAoB;AAAA,MAAA,CAClE;AAAA,IACH;AAEK,gBAAA,cAAc,GAAG,aAAasiB,CAAE,GAE9B,MAAM;AACN,WAAA,cAAc,IAAI,aAAaA,CAAE;AAAA,IACxC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASK,kBACL5B,GACAkb,GACA;AACA,QAAI,KAAK;AACP;AAGI,UAAAtZ,IAAK,CAACgD,MAAoC;AAC9C,MACEA,EAAE,YAAY,QAAQtB,EAAc,KACpC,CAAC4X,KAMHlb,EAAS,IAAI;AAAA,IACf;AAEK,gBAAA,cAAc,GAAG,mBAAmB4B,CAAE,GAEpC,MAAM;AACN,WAAA,cAAc,IAAI,mBAAmBA,CAAE;AAAA,IAC9C;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQK,SAAS5B,GAAsB;AAC/B,gBAAA,GAAG,UAAUA,CAAQ,GAEnB,MAAM;AACN,WAAA,IAAI,UAAUA,CAAQ;AAAA,IAC7B;AAAA,EAAA;AAAA,EAGK,0BAA0B;AAC3B,QAAA,CAAC,KAAK;AACD;AAGH,UAAA,EAAE,WAAA/W,MAAc,KAAK,kBAGrB,EAAE,QAAA8b,MAAW9b,GACb9L,IAAO,KAAK,IAAI,GAAG4nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,MAAM,GAAG,CAAC,GACzDxC,IAAK,KAAK,IAAI,GAAG2nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,IAAI,GAAG,CAAC;AAEvD,QAAA6kB,GAAgBxb,CAAS,GAAG;AAC9B,YAAMje,IAAO,KAAK,gBAAgB,QAAQmS,CAAI;AAC9C,UAAInS;AACF,eAAOA,EAAK,sBAAsB;AAAA,IACpC;AAGF,WAAOm6B,GAAa,KAAK,iBAAiBhoB,GAAMC,CAAE;AAAA,EAAA;AAAA,EAGpD,IAAW,UAAU;AACnB,UAAMhL,IAAM,KAAK;AAGjB,WACEA,EAAI,WAAW,KACdA,EAAI,WAAW,KACdA,EAAI,CAAC,EAAE,SAAS,eACfA,EAAI,CAAC,EAAE,QAAgB,WAAW;AAAA,EAAA;AAAA,EAIlC,mBACL09B,GACAhM,GAIA;AACI,IAAC,KAAK,oBAIV,KAAK,MAAM,GACN,KAAA,SAAS,CAAC35B,MAAO;AACpB,MAAI25B,KAAA,QAAAA,EAAa,0BACf35B,EAAG,WAAW2lC,CAAgB,GAEhC3lC,EAAG,iBAAiB,QAAQ,KAAK,gBAAgB,QAAQ,CAAC,GAAG;AAAA,QAC3D,kBAAA2lC;AAAA,QACA,yBAAwBhM,KAAA,gBAAAA,EAAa,2BAA0B;AAAA,QAC/D,oBAAmBA,KAAA,gBAAAA,EAAa,sBAAqB;AAAA,MAAA,CACtD;AAAA,IAAA,CACF;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQI,2BAA2B;AACzB,WAAA,KAAK,oBAAoB,WAAW;AAAA,EAAA;AAAA,EAGtC,yBAAyBqX,GAAgC;AACzD,SAAA,oBAAoB,WAAWA,CAAqB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMnD,2BAA2Bn3B,GAAc;AAE/C,WADiBwX,GAAgCxX,EAAK,KAAA,CAAM,EAC5C;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQX,UAAUA,GAAco3B,IAAM,IAAO;;AAC1C,QAAIC,IAAcr3B;AAIlB,IAHKo3B,MACWC,IAAA,KAAK,2BAA2Br3B,CAAI,IAE/Cq3B,OAGAjxC,IAAA,KAAA,oBAAA,QAAAA,EAAiB,UAAUixC;AAAA,EAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtC,UAAU19B,GAAc;;AACtB,YAAAvT,IAAA,KAAK,oBAAL,gBAAAA,EAAsB,UAAUuT;AAAA,EAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7C,MAAa,cAAcqe,GAAkB;AAC3C,WAAO,KAAK,UAAU,MAAMD,GAAeC,CAAQ,CAAC;AAAA,EAAA;AAExD;AC5vDO,MAAMsf,KAAiB;AAAA,EAC5B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EAAA;AAEhB,GAEaC,KAA2B;AAAA,EACtC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EAAA;AAEhB;ACvCO,MAAeC,GAQpB;AAAA,EACO,YACLC,GACmBC,GAKH94B,GAChB;AANmB,SAAA,WAAA84B,GAKH,KAAA,UAAA94B;AAAA,EAAA;AAAA,EAGlB,MAAa,YAAYrT,GAAa;;AAChC,QAAA,GAACnF,IAAA,KAAK,YAAL,QAAAA,EAAc;AACjB,cAAQ,MAAM,MAAMmF,CAAG,GAAG,KAAK;AAEjC,UAAMoF,IAAM,MAAM,KAAK,QAAQ,eAAepF,CAAG;AACjD,WAAIoF,aAAe,OACVA,KAED,MAAM,MAAMA,CAAG,GAAG,KAAK;AAAA,EAAA;AAAA,EAG1B,UAAUkB,GAAmB;AAK3B,WAJa,OAAO,QAAQA,CAAM,EAAE,IAAI,CAAC,CAACjN,GAAKyF,CAAK,MACrC,KAAK,SAAS,aAAazF,CAAG,EAAEyF,GAAO,IAAI,CAEhE;AAAA,EACM;AAAA,EAGF,iBAAiBC,GAAoC;AAC1D,WAAO,KAAK,SAAS,qBAAqBA,EAAc,IAAI;AAAA,MAC1DA;AAAA,MACA;AAAA,IACF;AAAA,EAAA;AAAA,EAGK,uBAAuBqtC,GAA2C;AACvE,WAAOA,EAAmB,IAAI,CAACt4B,MAAO,KAAK,iBAAiBA,CAAE,CAAC;AAAA,EAAA;AAAA,EAKjE,MAAa,SACX7U,GACAotC,GACAC,GACA;AACA,WAAO,KAAK,SAAS,aAAartC,EAAM,IAAI;AAAA,MAC1CA;AAAA,MACA;AAAA,MACAotC;AAAA,MACAC;AAAA,IACF;AAAA,EAAA;AAEJ;ACvCO,SAASC,GAIdL,GAAmC;AAC5B,SAAA;AAAA,IACL,oBAAoB,CAAQ9wC,MAC1BA;AAAA,IACF,4BAA4B,CAC1BA,MACGA;AAAA,IACL,oBAAoB,CAAIA,MAAgCA;AAAA,EAC1D;AACF;AC9DA,IAAIoxC;AAOJ,eAAeC,KAAgB;AAC7B,SAAID,OAIJA,MAAuB,YAAY;AAEjC,UAAM,CAACE,GAAiBC,CAAe,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC3D,OAAO,YAAY;AAAA;AAAA;AAAA,MAGnB,OAAO,kBAAkB;AAAA,IAAA,CAC1B,GAEKC,IACJ,aAAaF,IAAkBA,EAAgB,UAAUA,GACrDG,IACJ,aAAaF,IACRA,EAAgB,UAChBA;AAEP,iBAAMC,EAAU,KAAK,EAAE,MAAMC,GAAW,GAEjC,EAAE,WAAAD,GAAW,WAAAC,EAAU;AAAA,EAAA,GAC7B,GAEIL;AACT;AAEsB,eAAAM,GAKpB5tC,GACAmlB,GACsC;AACtC,MAAI,CAACnB,GAAsC,QAAQhkB,CAAM;AACvD,WAAO,CAAC;AAGV,QAAM,EAAE,WAAA2tC,GAAW,WAAAD,EAAU,IAAI,MAAMH,GAAc;AAO9C,UAJLpoB,EAAM,KAAK,MAAM,KACb,OAAO,OAAOwoB,EAAU,MAAM,IAC5B,MAAMD,EAAW,YAAY,OAAOvoB,CAAK,GAE7B,IAAI,CAAC0oB,OAAW;AAAA,IAClC,IAAIA,EAAM,MAAM,CAAC,EAAE;AAAA,IACnB,aAAa,MAAM7tC,EAAO,oBAAoB6tC,EAAM,MAAM,CAAC,EAAE,SAAS,GAAG;AAAA,EAAA,EACzE;AACJ;ACnEgB,SAAAC,GACdzzC,MACG0zC,GAGH;AACM,QAAAC,IAAgB,CAAC,GAAG3zC,CAAK;AAC/B,aAAW4zC,KAAmBF;AAC5B,eAAWG,KAAkBD,GAAiB;AAC5C,YAAME,IAAwBH,EAAc;AAAA,QAC1C,CAAC9zC,MAASA,EAAK,UAAUg0C,EAAe;AAAA,MAC1C;AACA,MAAIC,MAA0B,KAC5BH,EAAc,KAAKE,CAAmB,IAEtCF,EAAc,OAAOG,IAAwB,GAAG,GAAGD,CAAmB;AAAA,IACxE;AAGG,SAAAF;AACT;"}
1
+ {"version":3,"file":"blocknote.js","sources":["../src/extensions/UniqueID/UniqueID.ts","../src/schema/inlineContent/types.ts","../src/util/table.ts","../src/util/typescript.ts","../src/util/browser.ts","../src/blocks/defaultBlockHelpers.ts","../src/blocks/defaultProps.ts","../src/util/string.ts","../src/schema/blocks/internal.ts","../src/schema/blocks/createSpec.ts","../src/api/getBlockInfoFromPos.ts","../src/api/pmUtil.ts","../src/api/nodeConversions/nodeToBlock.ts","../src/schema/inlineContent/internal.ts","../src/schema/inlineContent/createSpec.ts","../src/schema/styles/internal.ts","../src/schema/styles/createSpec.ts","../src/api/blockManipulation/tables/tables.ts","../src/api/nodeConversions/blockToNode.ts","../src/api/nodeUtil.ts","../src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts","../src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts","../src/api/blockManipulation/commands/updateBlock/updateBlock.ts","../src/api/exporters/html/util/serializeBlocksExternalHTML.ts","../src/api/exporters/html/externalHTMLExporter.ts","../src/api/exporters/html/util/serializeBlocksInternalHTML.ts","../src/api/exporters/html/internalHTMLSerializer.ts","../src/blocks/FileBlockContent/helpers/parse/parseFigureElement.ts","../src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts","../src/blocks/FileBlockContent/helpers/render/createFileNameWithIcon.ts","../src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.ts","../src/blocks/FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.ts","../src/blocks/FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.ts","../src/blocks/AudioBlockContent/parseAudioElement.ts","../src/blocks/AudioBlockContent/AudioBlockContent.ts","../src/blocks/CodeBlockContent/CodeBlockContent.ts","../src/extensions/BackgroundColor/BackgroundColorMark.ts","../src/extensions/TextColor/TextColorMark.ts","../src/blocks/FileBlockContent/helpers/parse/parseEmbedElement.ts","../src/blocks/FileBlockContent/FileBlockContent.ts","../src/blocks/HeadingBlockContent/HeadingBlockContent.ts","../src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts","../src/blocks/ImageBlockContent/parseImageElement.ts","../src/blocks/ImageBlockContent/ImageBlockContent.ts","../src/blocks/ListItemBlockContent/getListItemContent.ts","../src/api/blockManipulation/commands/splitBlock/splitBlock.ts","../src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","../src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","../src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts","../src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","../src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","../src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","../src/blocks/QuoteBlockContent/QuoteBlockContent.ts","../src/blocks/TableBlockContent/TableExtension.ts","../src/blocks/TableBlockContent/TableBlockContent.ts","../src/blocks/VideoBlockContent/parseVideoElement.ts","../src/blocks/VideoBlockContent/VideoBlockContent.ts","../src/blocks/defaultBlocks.ts","../src/blocks/defaultBlockTypeGuards.ts","../src/blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","../src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts","../src/editor/BlockNoteSchema.ts","../src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts","../src/blocks/PageBreakBlockContent/schema.ts","../src/blocks/PageBreakBlockContent/getPageBreakSlashMenuItems.ts","../src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts","../src/api/blockManipulation/commands/nestBlock/nestBlock.ts","../src/api/blockManipulation/getBlock/getBlock.ts","../src/api/blockManipulation/insertContentAt.ts","../src/api/blockManipulation/selections/selection.ts","../src/api/blockManipulation/selections/textCursorPosition.ts","../src/util/esmDependencies.ts","../src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","../src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts","../src/api/exporters/markdown/markdownExporter.ts","../src/api/parsers/html/util/nestedLists.ts","../src/api/parsers/html/parseHTML.ts","../src/api/parsers/markdown/parseMarkdown.ts","../src/api/clipboard/fromClipboard/acceptedMIMETypes.ts","../src/api/clipboard/fromClipboard/handleFileInsertion.ts","../src/api/clipboard/fromClipboard/fileDropExtension.ts","../src/api/parsers/markdown/detectMarkdown.ts","../src/api/clipboard/fromClipboard/handleVSCodePaste.ts","../src/api/clipboard/fromClipboard/pasteExtension.ts","../src/api/nodeConversions/fragmentToBlocks.ts","../src/api/clipboard/toClipboard/copyExtension.ts","../src/extensions/BackgroundColor/BackgroundColorExtension.ts","../src/util/EventEmitter.ts","../src/editor/BlockNoteExtension.ts","../src/extensions/Collaboration/CursorPlugin.ts","../src/extensions/Collaboration/SyncPlugin.ts","../src/extensions/Collaboration/UndoPlugin.ts","../src/extensions/Comments/CommentMark.ts","../src/extensions/Comments/userstore/UserStore.ts","../src/extensions/Comments/CommentsPlugin.ts","../src/extensions/FilePanel/FilePanelPlugin.ts","../src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","../src/extensions/HardBreak/HardBreak.ts","../src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts","../src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts","../src/extensions/LinkToolbar/LinkToolbarPlugin.ts","../src/extensions/LinkToolbar/protocols.ts","../src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts","../src/extensions/Placeholder/PlaceholderPlugin.ts","../src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","../src/extensions/ShowSelection/ShowSelectionPlugin.ts","../src/extensions/getDraggableBlockFromElement.ts","../src/extensions/SideMenu/MultipleNodeSelection.ts","../src/extensions/SideMenu/dragging.ts","../src/extensions/SideMenu/SideMenuPlugin.ts","../src/api/positionMapping.ts","../src/extensions/SuggestionMenu/SuggestionPlugin.ts","../src/extensions/Suggestions/SuggestionMarks.ts","../src/extensions/TableHandles/TableHandlesPlugin.ts","../src/extensions/TextAlignment/TextAlignmentExtension.ts","../src/extensions/TextColor/TextColorExtension.ts","../src/extensions/TrailingNode/TrailingNodeExtension.ts","../src/pm-nodes/BlockContainer.ts","../src/pm-nodes/BlockGroup.ts","../src/pm-nodes/Doc.ts","../src/extensions/Collaboration/ForkYDocPlugin.ts","../src/editor/BlockNoteExtensions.ts","../src/editor/transformPasted.ts","../src/editor/BlockNoteTipTapEditor.ts","../src/editor/BlockNoteEditor.ts","../src/editor/defaultColors.ts","../src/exporter/Exporter.ts","../src/exporter/mapping.ts","../src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts","../src/util/combineByGroup.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n Extension,\n findChildrenInRange,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport { Fragment, Slice } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { v4 } from \"uuid\";\n\n/**\n * Code from Tiptap UniqueID extension (https://tiptap.dev/api/extensions/unique-id)\n * This extension is licensed under MIT (even though it's part of Tiptap pro).\n *\n * If you're a user of BlockNote, we still recommend to support their awesome work and become a sponsor!\n * https://tiptap.dev/pro\n */\n\n/**\n * Removes duplicated values within an array.\n * Supports numbers, strings and objects.\n */\nfunction removeDuplicates(array: any, by = JSON.stringify) {\n const seen: any = {};\n return array.filter((item: any) => {\n const key = by(item);\n return Object.prototype.hasOwnProperty.call(seen, key)\n ? false\n : (seen[key] = true);\n });\n}\n\n/**\n * Returns a list of duplicated items within an array.\n */\nfunction findDuplicates(items: any) {\n const filtered = items.filter(\n (el: any, index: number) => items.indexOf(el) !== index,\n );\n const duplicates = removeDuplicates(filtered);\n return duplicates;\n}\n\nconst UniqueID = Extension.create({\n name: \"uniqueID\",\n // we’ll set a very high priority to make sure this runs first\n // and is compatible with `appendTransaction` hooks of other extensions\n priority: 10000,\n addOptions() {\n return {\n attributeName: \"id\",\n types: [],\n setIdAttribute: false,\n generateID: () => {\n // Use mock ID if tests are running.\n if (typeof window !== \"undefined\" && (window as any).__TEST_OPTIONS) {\n const testOptions = (window as any).__TEST_OPTIONS;\n if (testOptions.mockID === undefined) {\n testOptions.mockID = 0;\n } else {\n testOptions.mockID++;\n }\n\n return testOptions.mockID.toString() as string;\n }\n\n return v4();\n },\n filterTransaction: null,\n };\n },\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n [this.options.attributeName]: {\n default: null,\n parseHTML: (element) =>\n element.getAttribute(`data-${this.options.attributeName}`),\n renderHTML: (attributes) => {\n const defaultIdAttributes = {\n [`data-${this.options.attributeName}`]:\n attributes[this.options.attributeName],\n };\n if (this.options.setIdAttribute) {\n return {\n ...defaultIdAttributes,\n id: attributes[this.options.attributeName],\n };\n } else {\n return defaultIdAttributes;\n }\n },\n },\n },\n },\n ];\n },\n // check initial content for missing ids\n // onCreate() {\n // // Don’t do this when the collaboration extension is active\n // // because this may update the content, so Y.js tries to merge these changes.\n // // This leads to empty block nodes.\n // // See: https://github.com/ueberdosis/tiptap/issues/2400\n // if (\n // this.editor.extensionManager.extensions.find(\n // (extension) => extension.name === \"collaboration\"\n // )\n // ) {\n // return;\n // }\n // const { view, state } = this.editor;\n // const { tr, doc } = state;\n // const { types, attributeName, generateID } = this.options;\n // const nodesWithoutId = findChildren(doc, (node) => {\n // return (\n // types.includes(node.type.name) && node.attrs[attributeName] === null\n // );\n // });\n // nodesWithoutId.forEach(({ node, pos }) => {\n // tr.setNodeMarkup(pos, undefined, {\n // ...node.attrs,\n // [attributeName]: generateID(),\n // });\n // });\n // tr.setMeta(\"addToHistory\", false);\n // view.dispatch(tr);\n // },\n addProseMirrorPlugins() {\n let dragSourceElement: any = null;\n let transformPasted = false;\n return [\n new Plugin({\n key: new PluginKey(\"uniqueID\"),\n appendTransaction: (transactions, oldState, newState) => {\n // console.log(\"appendTransaction\");\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n const filterTransactions =\n this.options.filterTransaction &&\n transactions.some((tr) => {\n let _a, _b;\n return !((_b = (_a = this.options).filterTransaction) === null ||\n _b === void 0\n ? void 0\n : _b.call(_a, tr));\n });\n if (!docChanges || filterTransactions) {\n return;\n }\n const { tr } = newState;\n const { types, attributeName, generateID } = this.options;\n const transform = combineTransactionSteps(\n oldState.doc,\n transactions as any,\n );\n const { mapping } = transform;\n // get changed ranges based on the old state\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange }) => {\n const newNodes = findChildrenInRange(\n newState.doc,\n newRange,\n (node) => {\n return types.includes(node.type.name);\n },\n );\n const newIds = newNodes\n .map(({ node }) => node.attrs[attributeName])\n .filter((id) => id !== null);\n const duplicatedNewIds = findDuplicates(newIds);\n newNodes.forEach(({ node, pos }) => {\n let _a;\n // instead of checking `node.attrs[attributeName]` directly\n // we look at the current state of the node within `tr.doc`.\n // this helps to prevent adding new ids to the same node\n // if the node changed multiple times within one transaction\n const id =\n (_a = tr.doc.nodeAt(pos)) === null || _a === void 0\n ? void 0\n : _a.attrs[attributeName];\n if (id === null) {\n // edge case, when using collaboration, yjs will set the id to null in `_forceRerender`\n // when loading the editor\n // this checks for this case and keeps it at initialBlockId so there will be no change\n const initialDoc = oldState.doc.type.createAndFill()!.content;\n const wasInitial =\n oldState.doc.content.findDiffStart(initialDoc) === null;\n\n if (wasInitial) {\n // the old state was the \"initial content\"\n const jsonNode = JSON.parse(\n JSON.stringify(newState.doc.toJSON()),\n );\n jsonNode.content[0].content[0].attrs.id = \"initialBlockId\";\n // would the new state with the fix also be the \"initial content\"?\n if (\n JSON.stringify(jsonNode.content) ===\n JSON.stringify(initialDoc.toJSON())\n ) {\n // yes, apply the fix\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: \"initialBlockId\",\n });\n return;\n }\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n });\n return;\n }\n // check if the node doesn’t exist in the old state\n const { deleted } = mapping.invert().mapResult(pos);\n const newNode = deleted && duplicatedNewIds.includes(id);\n if (newNode) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n });\n }\n });\n });\n if (!tr.steps.length) {\n return;\n }\n return tr;\n },\n // we register a global drag handler to track the current drag source element\n view(view) {\n const handleDragstart = (event: any) => {\n let _a;\n dragSourceElement = (\n (_a = view.dom.parentElement) === null || _a === void 0\n ? void 0\n : _a.contains(event.target)\n )\n ? view.dom.parentElement\n : null;\n };\n window.addEventListener(\"dragstart\", handleDragstart);\n return {\n destroy() {\n window.removeEventListener(\"dragstart\", handleDragstart);\n },\n };\n },\n props: {\n // `handleDOMEvents` is called before `transformPasted` so we can do\n // some checks before. However, `transformPasted` only runs when\n // editor content is pasted - not external content.\n handleDOMEvents: {\n // only create new ids for dropped content while holding `alt`\n // or content is dragged from another editor\n drop: (view, event: any) => {\n let _a;\n if (\n dragSourceElement !== view.dom.parentElement ||\n ((_a = event.dataTransfer) === null || _a === void 0\n ? void 0\n : _a.effectAllowed) === \"copy\"\n ) {\n transformPasted = true;\n } else {\n transformPasted = false;\n }\n\n dragSourceElement = null;\n\n return false;\n },\n // always create new ids on pasted content\n paste: () => {\n transformPasted = true;\n return false;\n },\n },\n // we’ll remove ids for every pasted node\n // so we can create a new one within `appendTransaction`\n transformPasted: (slice) => {\n if (!transformPasted) {\n return slice;\n }\n const { types, attributeName } = this.options;\n const removeId = (fragment: any) => {\n const list: any[] = [];\n fragment.forEach((node: any) => {\n // don’t touch text nodes\n if (node.isText) {\n list.push(node);\n return;\n }\n // check for any other child nodes\n if (!types.includes(node.type.name)) {\n list.push(node.copy(removeId(node.content)));\n return;\n }\n // remove id\n const nodeWithoutId = node.type.create(\n {\n ...node.attrs,\n [attributeName]: null,\n },\n removeId(node.content),\n node.marks,\n );\n list.push(nodeWithoutId);\n });\n return Fragment.from(list);\n };\n // reset check\n transformPasted = false;\n return new Slice(\n removeId(slice.content),\n slice.openStart,\n slice.openEnd,\n );\n },\n },\n }),\n ];\n },\n});\n\nexport { UniqueID as default, UniqueID };\n","import { Node } from \"@tiptap/core\";\nimport { PropSchema, Props } from \"../propTypes.js\";\nimport { StyleSchema, Styles } from \"../styles/types.js\";\n\nexport type CustomInlineContentConfig = {\n type: string;\n content: \"styled\" | \"none\"; // | \"plain\"\n readonly propSchema: PropSchema;\n // content: \"inline\" | \"none\" | \"table\";\n};\n// InlineContentConfig contains the \"schema\" info about an InlineContent type\n// i.e. what props it supports, what content it supports, etc.\nexport type InlineContentConfig = CustomInlineContentConfig | \"text\" | \"link\";\n\n// InlineContentImplementation contains the \"implementation\" info about an InlineContent element\n// such as the functions / Nodes required to render and / or serialize it\n// @ts-ignore\nexport type InlineContentImplementation<T extends InlineContentConfig> =\n T extends \"link\" | \"text\"\n ? undefined\n : {\n node: Node;\n };\n\n// Container for both the config and implementation of InlineContent,\n// and the type of `implementation` is based on that of the config\nexport type InlineContentSpec<T extends InlineContentConfig> = {\n config: T;\n implementation: InlineContentImplementation<T>;\n};\n\n// A Schema contains all the types (Configs) supported in an editor\n// The keys are the \"type\" of InlineContent elements\nexport type InlineContentSchema = Record<string, InlineContentConfig>;\n\nexport type InlineContentSpecs = {\n text: { config: \"text\"; implementation: undefined };\n link: { config: \"link\"; implementation: undefined };\n} & Record<string, InlineContentSpec<InlineContentConfig>>;\n\nexport type InlineContentSchemaFromSpecs<T extends InlineContentSpecs> = {\n [K in keyof T]: T[K][\"config\"];\n};\n\nexport type CustomInlineContentFromConfig<\n I extends CustomInlineContentConfig,\n S extends StyleSchema,\n> = {\n type: I[\"type\"];\n props: Props<I[\"propSchema\"]>;\n content: I[\"content\"] extends \"styled\"\n ? StyledText<S>[]\n : I[\"content\"] extends \"plain\"\n ? string\n : I[\"content\"] extends \"none\"\n ? undefined\n : never;\n};\n\nexport type InlineContentFromConfig<\n I extends InlineContentConfig,\n S extends StyleSchema,\n> = I extends \"text\"\n ? StyledText<S>\n : I extends \"link\"\n ? Link<S>\n : I extends CustomInlineContentConfig\n ? CustomInlineContentFromConfig<I, S>\n : never;\n\nexport type PartialCustomInlineContentFromConfig<\n I extends CustomInlineContentConfig,\n S extends StyleSchema,\n> = {\n type: I[\"type\"];\n props?: Props<I[\"propSchema\"]>;\n content?: I[\"content\"] extends \"styled\"\n ? StyledText<S>[] | string\n : I[\"content\"] extends \"plain\"\n ? string\n : I[\"content\"] extends \"none\"\n ? undefined\n : never;\n};\n\nexport type PartialInlineContentFromConfig<\n I extends InlineContentConfig,\n S extends StyleSchema,\n> = I extends \"text\"\n ? string | StyledText<S>\n : I extends \"link\"\n ? PartialLink<S>\n : I extends CustomInlineContentConfig\n ? PartialCustomInlineContentFromConfig<I, S>\n : never;\n\nexport type StyledText<T extends StyleSchema> = {\n type: \"text\";\n text: string;\n styles: Styles<T>;\n};\n\nexport type Link<T extends StyleSchema> = {\n type: \"link\";\n href: string;\n content: StyledText<T>[];\n};\n\nexport type PartialLink<T extends StyleSchema> = Omit<Link<T>, \"content\"> & {\n content: string | Link<T>[\"content\"];\n};\n\nexport type InlineContent<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = InlineContentFromConfig<I[keyof I], T>;\n\ntype PartialInlineContentElement<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = PartialInlineContentFromConfig<I[keyof I], T>;\n\nexport type PartialInlineContent<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = PartialInlineContentElement<I, T>[] | string;\n\nexport function isLinkInlineContent<T extends StyleSchema>(\n content: InlineContent<any, T>,\n): content is Link<T> {\n return content.type === \"link\";\n}\n\nexport function isPartialLinkInlineContent<T extends StyleSchema>(\n content: PartialInlineContentElement<any, T>,\n): content is PartialLink<T> {\n return typeof content !== \"string\" && content.type === \"link\";\n}\n\nexport function isStyledTextInlineContent<T extends StyleSchema>(\n content: PartialInlineContentElement<any, T>,\n): content is StyledText<T> {\n return typeof content !== \"string\" && content.type === \"text\";\n}\n","import type {\n InlineContentSchema,\n StyleSchema,\n PartialInlineContent,\n InlineContent,\n} from \"../schema\";\nimport { PartialTableCell, TableCell } from \"../schema/blocks/types.js\";\n\n/**\n * This will map a table cell to a TableCell object.\n * This is useful for when we want to get the full table cell object from a partial table cell.\n * It is guaranteed to return a new TableCell object.\n */\nexport function mapTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | TableCell<T, S>,\n): TableCell<T, S> {\n return isTableCell(content)\n ? { ...content }\n : isPartialTableCell(content)\n ? {\n type: \"tableCell\",\n content: ([] as InlineContent<T, S>[]).concat(content.content as any),\n props: {\n backgroundColor: content.props?.backgroundColor ?? \"default\",\n textColor: content.props?.textColor ?? \"default\",\n textAlignment: content.props?.textAlignment ?? \"left\",\n colspan: content.props?.colspan ?? 1,\n rowspan: content.props?.rowspan ?? 1,\n },\n }\n : {\n type: \"tableCell\",\n content: ([] as InlineContent<T, S>[]).concat(content as any),\n props: {\n backgroundColor: \"default\",\n textColor: \"default\",\n textAlignment: \"left\",\n colspan: 1,\n rowspan: 1,\n },\n };\n}\n\nexport function isPartialTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | TableCell<T, S>\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | undefined\n | null,\n): content is PartialTableCell<T, S> {\n return (\n content !== undefined &&\n content !== null &&\n typeof content !== \"string\" &&\n !Array.isArray(content) &&\n content.type === \"tableCell\"\n );\n}\n\nexport function isTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | TableCell<T, S>\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | undefined\n | null,\n): content is TableCell<T, S> {\n return (\n isPartialTableCell(content) &&\n content.props !== undefined &&\n content.content !== undefined\n );\n}\n\nexport function getColspan(\n cell:\n | TableCell<any, any>\n | PartialTableCell<any, any>\n | PartialInlineContent<any, any>,\n): number {\n if (isTableCell(cell)) {\n return cell.props.colspan ?? 1;\n }\n return 1;\n}\n\nexport function getRowspan(\n cell:\n | TableCell<any, any>\n | PartialTableCell<any, any>\n | PartialInlineContent<any, any>,\n): number {\n if (isTableCell(cell)) {\n return cell.props.rowspan ?? 1;\n }\n return 1;\n}\n","export class UnreachableCaseError extends Error {\n constructor(val: never) {\n super(`Unreachable case: ${val}`);\n }\n}\n\nexport function assertEmpty(obj: Record<string, never>, throwError = true) {\n const { \"data-test\": dataTest, ...rest } = obj; // exclude data-test\n\n if (Object.keys(rest).length > 0 && throwError) {\n throw new Error(\"Object must be empty \" + JSON.stringify(obj));\n }\n}\n\n// TODO: change for built-in version of typescript 5.4 after upgrade\nexport type NoInfer<T> = [T][T extends any ? 0 : never];\n","export const isAppleOS = () =>\n typeof navigator !== \"undefined\" &&\n (/Mac/.test(navigator.platform) ||\n (/AppleWebKit/.test(navigator.userAgent) &&\n /Mobile\\/\\w+/.test(navigator.userAgent)));\n\nexport function formatKeyboardShortcut(shortcut: string, ctrlText = \"Ctrl\") {\n if (isAppleOS()) {\n return shortcut.replace(\"Mod\", \"⌘\");\n } else {\n return shortcut.replace(\"Mod\", ctrlText);\n }\n}\n\nexport function mergeCSSClasses(...classes: (string | false | undefined)[]) {\n return classes.filter((c) => c).join(\" \");\n}\n\nexport const isSafari = () =>\n /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n","import { blockToNode } from \"../api/nodeConversions/blockToNode.js\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport type {\n BlockNoDefaults,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../schema/index.js\";\nimport { mergeCSSClasses } from \"../util/browser.js\";\n\n// Function that creates a ProseMirror `DOMOutputSpec` for a default block.\n// Since all default blocks have the same structure (`blockContent` div with a\n// `inlineContent` element inside), this function only needs the block's name\n// for the `data-content-type` attribute of the `blockContent` element and the\n// HTML tag of the `inlineContent` element, as well as any HTML attributes to\n// add to those.\nexport function createDefaultBlockDOMOutputSpec(\n blockName: string,\n htmlTag: string,\n blockContentHTMLAttributes: Record<string, string>,\n inlineContentHTMLAttributes: Record<string, string>,\n) {\n const blockContent = document.createElement(\"div\");\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n blockContentHTMLAttributes.class,\n );\n blockContent.setAttribute(\"data-content-type\", blockName);\n for (const [attribute, value] of Object.entries(blockContentHTMLAttributes)) {\n if (attribute !== \"class\") {\n blockContent.setAttribute(attribute, value);\n }\n }\n\n const inlineContent = document.createElement(htmlTag);\n inlineContent.className = mergeCSSClasses(\n \"bn-inline-content\",\n inlineContentHTMLAttributes.class,\n );\n for (const [attribute, value] of Object.entries(\n inlineContentHTMLAttributes,\n )) {\n if (attribute !== \"class\") {\n inlineContent.setAttribute(attribute, value);\n }\n }\n\n blockContent.appendChild(inlineContent);\n\n return {\n dom: blockContent,\n contentDOM: inlineContent,\n };\n}\n\n// Function used to convert default blocks to HTML. It uses the corresponding\n// node's `renderHTML` method to do the conversion by using a default\n// `DOMSerializer`.\nexport const defaultBlockToHTML = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n block: BlockNoDefaults<BSchema, I, S>,\n editor: BlockNoteEditor<BSchema, I, S>,\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} => {\n let node = blockToNode(block, editor.pmSchema);\n\n if (node.type.name === \"blockContainer\") {\n // for regular blocks, get the toDOM spec from the blockContent node\n node = node.firstChild!;\n }\n\n const toDOM = editor.pmSchema.nodes[node.type.name].spec.toDOM;\n\n if (toDOM === undefined) {\n throw new Error(\n \"This block has no default HTML serialization as its corresponding TipTap node doesn't implement `renderHTML`.\",\n );\n }\n\n const renderSpec = toDOM(node);\n\n if (typeof renderSpec !== \"object\" || !(\"dom\" in renderSpec)) {\n throw new Error(\n \"Cannot use this block's default HTML serialization as its corresponding TipTap node's `renderHTML` function does not return an object with the `dom` property.\",\n );\n }\n\n return renderSpec as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n};\n\n// Function that merges all paragraphs into a single one separated by line breaks.\n// This is used when parsing blocks like list items and table cells, as they may\n// contain multiple paragraphs that ProseMirror will not be able to handle\n// properly.\nexport function mergeParagraphs(element: HTMLElement) {\n const paragraphs = element.querySelectorAll(\"p\");\n if (paragraphs.length > 1) {\n const firstParagraph = paragraphs[0];\n for (let i = 1; i < paragraphs.length; i++) {\n const paragraph = paragraphs[i];\n firstParagraph.innerHTML += \"<br>\" + paragraph.innerHTML;\n paragraph.remove();\n }\n }\n}\n","import type { Props, PropSchema } from \"../schema/index.js\";\n\n// TODO: this system should probably be moved / refactored.\n// The dependency from schema on this file doesn't make sense\n\nexport const defaultProps = {\n backgroundColor: {\n default: \"default\" as const,\n },\n textColor: {\n default: \"default\" as const,\n },\n textAlignment: {\n default: \"left\" as const,\n values: [\"left\", \"center\", \"right\", \"justify\"] as const,\n },\n} satisfies PropSchema;\n\nexport type DefaultProps = Props<typeof defaultProps>;\n\n// Default props which are set on `blockContainer` nodes rather than\n// `blockContent` nodes. Ensures that they are not redundantly added to\n// a custom block's TipTap node attributes.\nexport const inheritedProps = [\"backgroundColor\", \"textColor\"];\n","export function camelToDataKebab(str: string): string {\n return \"data-\" + str.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\nexport function filenameFromURL(url: string): string {\n const parts = url.split(\"/\");\n if (\n !parts.length || // invalid?\n parts[parts.length - 1] === \"\" // for example, URL ends in a directory-like trailing slash\n ) {\n // in this case just return the original url\n return url;\n }\n return parts[parts.length - 1];\n}\n","import {\n Attribute,\n Attributes,\n Editor,\n Extension,\n Node,\n NodeConfig,\n} from \"@tiptap/core\";\nimport { defaultBlockToHTML } from \"../../blocks/defaultBlockHelpers.js\";\nimport { inheritedProps } from \"../../blocks/defaultProps.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { mergeCSSClasses } from \"../../util/browser.js\";\nimport { camelToDataKebab } from \"../../util/string.js\";\nimport { InlineContentSchema } from \"../inlineContent/types.js\";\nimport { PropSchema, Props } from \"../propTypes.js\";\nimport { StyleSchema } from \"../styles/types.js\";\nimport {\n BlockConfig,\n BlockSchemaFromSpecs,\n BlockSchemaWithBlock,\n BlockSpec,\n BlockSpecs,\n SpecificBlock,\n TiptapBlockImplementation,\n} from \"./types.js\";\n\n// Function that uses the 'propSchema' of a blockConfig to create a TipTap\n// node's `addAttributes` property.\n// TODO: extract function\nexport function propsToAttributes(propSchema: PropSchema): Attributes {\n const tiptapAttributes: Record<string, Attribute> = {};\n\n Object.entries(propSchema)\n .filter(([name, _spec]) => !inheritedProps.includes(name))\n .forEach(([name, spec]) => {\n tiptapAttributes[name] = {\n default: spec.default,\n keepOnSplit: true,\n // Props are displayed in kebab-case as HTML attributes. If a prop's\n // value is the same as its default, we don't display an HTML\n // attribute for it.\n parseHTML: (element) => {\n const value = element.getAttribute(camelToDataKebab(name));\n\n if (value === null) {\n return null;\n }\n\n if (\n (spec.default === undefined && spec.type === \"boolean\") ||\n (spec.default !== undefined && typeof spec.default === \"boolean\")\n ) {\n if (value === \"true\") {\n return true;\n }\n\n if (value === \"false\") {\n return false;\n }\n\n return null;\n }\n\n if (\n (spec.default === undefined && spec.type === \"number\") ||\n (spec.default !== undefined && typeof spec.default === \"number\")\n ) {\n const asNumber = parseFloat(value);\n const isNumeric =\n !Number.isNaN(asNumber) && Number.isFinite(asNumber);\n\n if (isNumeric) {\n return asNumber;\n }\n\n return null;\n }\n\n return value;\n },\n renderHTML: (attributes) => {\n // don't render to html if the value is the same as the default\n return attributes[name] !== spec.default\n ? {\n [camelToDataKebab(name)]: attributes[name],\n }\n : {};\n },\n };\n });\n\n return tiptapAttributes;\n}\n\n// Used to figure out which block should be rendered. This block is then used to\n// create the node view.\nexport function getBlockFromPos<\n BType extends string,\n Config extends BlockConfig,\n BSchema extends BlockSchemaWithBlock<BType, Config>,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n getPos: (() => number) | boolean,\n editor: BlockNoteEditor<BSchema, I, S>,\n tipTapEditor: Editor,\n type: BType,\n) {\n // Gets position of the node\n if (typeof getPos === \"boolean\") {\n throw new Error(\n \"Cannot find node position as getPos is a boolean, not a function.\",\n );\n }\n const pos = getPos();\n // Gets parent blockContainer node\n const blockContainer = tipTapEditor.state.doc.resolve(pos!).node();\n // Gets block identifier\n const blockIdentifier = blockContainer.attrs.id;\n\n if (!blockIdentifier) {\n throw new Error(\"Block doesn't have id\");\n }\n\n // Gets the block\n const block = editor.getBlock(blockIdentifier)! as SpecificBlock<\n BSchema,\n BType,\n I,\n S\n >;\n if (block.type !== type) {\n throw new Error(\"Block type does not match\");\n }\n\n return block;\n}\n\n// Function that wraps the `dom` element returned from 'blockConfig.render' in a\n// `blockContent` div, which contains the block type and props as HTML\n// attributes. If `blockConfig.render` also returns a `contentDOM`, it also adds\n// an `inlineContent` class to it.\nexport function wrapInBlockStructure<\n BType extends string,\n PSchema extends PropSchema,\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n },\n blockType: BType,\n blockProps: Props<PSchema>,\n propSchema: PSchema,\n isFileBlock = false,\n domAttributes?: Record<string, string>,\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n} {\n // Creates `blockContent` element\n const blockContent = document.createElement(\"div\");\n\n // Adds custom HTML attributes\n if (domAttributes !== undefined) {\n for (const [attr, value] of Object.entries(domAttributes)) {\n if (attr !== \"class\") {\n blockContent.setAttribute(attr, value);\n }\n }\n }\n // Sets blockContent class\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n domAttributes?.class || \"\",\n );\n // Sets content type attribute\n blockContent.setAttribute(\"data-content-type\", blockType);\n // Adds props as HTML attributes in kebab-case with \"data-\" prefix. Skips props\n // which are already added as HTML attributes to the parent `blockContent`\n // element (inheritedProps) and props set to their default values.\n for (const [prop, value] of Object.entries(blockProps)) {\n const spec = propSchema[prop];\n const defaultValue = spec.default;\n if (!inheritedProps.includes(prop) && value !== defaultValue) {\n blockContent.setAttribute(camelToDataKebab(prop), value);\n }\n }\n // Adds file block attribute\n if (isFileBlock) {\n blockContent.setAttribute(\"data-file-block\", \"\");\n }\n\n blockContent.appendChild(element.dom);\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.className = mergeCSSClasses(\n \"bn-inline-content\",\n element.contentDOM.className,\n );\n }\n\n return {\n ...element,\n dom: blockContent,\n };\n}\n\n// Helper type to keep track of the `name` and `content` properties after calling Node.create.\ntype StronglyTypedTipTapNode<\n Name extends string,\n Content extends\n | \"inline*\"\n | \"tableRow+\"\n | \"blockContainer+\"\n | \"column column+\"\n | \"\",\n> = Node & { name: Name; config: { content: Content } };\n\nexport function createStronglyTypedTiptapNode<\n Name extends string,\n Content extends\n | \"inline*\"\n | \"tableRow+\"\n | \"blockContainer+\"\n | \"column column+\"\n | \"\",\n>(config: NodeConfig & { name: Name; content: Content }) {\n return Node.create(config) as StronglyTypedTipTapNode<Name, Content>; // force re-typing (should be safe as it's type-checked from the config)\n}\n\n// This helper function helps to instantiate a blockspec with a\n// config and implementation that conform to the type of Config\nexport function createInternalBlockSpec<T extends BlockConfig>(\n config: T,\n implementation: TiptapBlockImplementation<\n T,\n any,\n InlineContentSchema,\n StyleSchema\n >,\n) {\n return {\n config,\n implementation,\n } satisfies BlockSpec<T, any, InlineContentSchema, StyleSchema>;\n}\n\nexport function createBlockSpecFromStronglyTypedTiptapNode<\n T extends Node,\n P extends PropSchema,\n>(node: T, propSchema: P, requiredExtensions?: Array<Extension | Node>) {\n return createInternalBlockSpec(\n {\n type: node.name as T[\"name\"],\n content: (node.config.content === \"inline*\"\n ? \"inline\"\n : node.config.content === \"tableRow+\"\n ? \"table\"\n : \"none\") as T[\"config\"][\"content\"] extends \"inline*\"\n ? \"inline\"\n : T[\"config\"][\"content\"] extends \"tableRow+\"\n ? \"table\"\n : \"none\",\n propSchema,\n },\n {\n node,\n requiredExtensions,\n toInternalHTML: defaultBlockToHTML,\n toExternalHTML: defaultBlockToHTML,\n // parse: () => undefined, // parse rules are in node already\n },\n );\n}\n\nexport function getBlockSchemaFromSpecs<T extends BlockSpecs>(specs: T) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config]),\n ) as BlockSchemaFromSpecs<T>;\n}\n","import { Editor } from \"@tiptap/core\";\nimport { TagParseRule } from \"@tiptap/pm/model\";\nimport { NodeView } from \"@tiptap/pm/view\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { InlineContentSchema } from \"../inlineContent/types.js\";\nimport { StyleSchema } from \"../styles/types.js\";\nimport {\n createInternalBlockSpec,\n createStronglyTypedTiptapNode,\n getBlockFromPos,\n propsToAttributes,\n wrapInBlockStructure,\n} from \"./internal.js\";\nimport {\n BlockConfig,\n BlockFromConfig,\n BlockSchemaWithBlock,\n PartialBlockFromConfig,\n} from \"./types.js\";\n\n// restrict content to \"inline\" and \"none\" only\nexport type CustomBlockConfig = BlockConfig & {\n content: \"inline\" | \"none\";\n};\n\nexport type CustomBlockImplementation<\n T extends CustomBlockConfig,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = {\n render: (\n /**\n * The custom block to render\n */\n block: BlockFromConfig<T, I, S>,\n /**\n * The BlockNote editor instance\n * This is typed generically. If you want an editor with your custom schema, you need to\n * cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`\n */\n editor: BlockNoteEditor<BlockSchemaWithBlock<T[\"type\"], T>, I, S>,\n // (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations\n // or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n };\n // Exports block to external HTML. If not defined, the output will be the same\n // as `render(...).dom`. Used to create clipboard data when pasting outside\n // BlockNote.\n // TODO: Maybe can return undefined to ignore when serializing?\n toExternalHTML?: (\n block: BlockFromConfig<T, I, S>,\n editor: BlockNoteEditor<BlockSchemaWithBlock<T[\"type\"], T>, I, S>,\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n parse?: (\n el: HTMLElement,\n ) => PartialBlockFromConfig<T, I, S>[\"props\"] | undefined;\n};\n\n// Function that causes events within non-selectable blocks to be handled by the\n// browser instead of the editor.\nexport function applyNonSelectableBlockFix(nodeView: NodeView, editor: Editor) {\n nodeView.stopEvent = (event) => {\n // Blurs the editor on mouse down as the block is non-selectable. This is\n // mainly done to prevent UI elements like the formatting toolbar from being\n // visible while content within a non-selectable block is selected.\n if (event.type === \"mousedown\") {\n setTimeout(() => {\n editor.view.dom.blur();\n }, 10);\n }\n\n return true;\n };\n}\n\n// Function that uses the 'parse' function of a blockConfig to create a\n// TipTap node's `parseHTML` property. This is only used for parsing content\n// from the clipboard.\nexport function getParseRules(\n config: BlockConfig,\n customParseFunction: CustomBlockImplementation<any, any, any>[\"parse\"],\n) {\n const rules: TagParseRule[] = [\n {\n tag: \"[data-content-type=\" + config.type + \"]\",\n contentElement: \".bn-inline-content\",\n },\n ];\n\n if (customParseFunction) {\n rules.push({\n tag: \"*\",\n getAttrs(node: string | HTMLElement) {\n if (typeof node === \"string\") {\n return false;\n }\n\n const props = customParseFunction?.(node);\n\n if (props === undefined) {\n return false;\n }\n\n return props;\n },\n });\n }\n // getContent(node, schema) {\n // const block = blockConfig.parse?.(node as HTMLElement);\n //\n // if (block !== undefined && block.content !== undefined) {\n // return Fragment.from(\n // typeof block.content === \"string\"\n // ? schema.text(block.content)\n // : inlineContentToNodes(block.content, schema)\n // );\n // }\n //\n // return Fragment.empty;\n // },\n // });\n // }\n\n return rules;\n}\n\n// A function to create custom block for API consumers\n// we want to hide the tiptap node from API consumers and provide a simpler API surface instead\nexport function createBlockSpec<\n T extends CustomBlockConfig,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockConfig: T,\n blockImplementation: CustomBlockImplementation<NoInfer<T>, I, S>,\n) {\n const node = createStronglyTypedTiptapNode({\n name: blockConfig.type as T[\"type\"],\n content: (blockConfig.content === \"inline\"\n ? \"inline*\"\n : \"\") as T[\"content\"] extends \"inline\" ? \"inline*\" : \"\",\n group: \"blockContent\",\n selectable: blockConfig.isSelectable ?? true,\n isolating: true,\n addAttributes() {\n return propsToAttributes(blockConfig.propSchema);\n },\n\n parseHTML() {\n return getParseRules(blockConfig, blockImplementation.parse);\n },\n\n renderHTML({ HTMLAttributes }) {\n // renderHTML is used for copy/pasting content from the editor back into\n // the editor, so we need to make sure the `blockContent` element is\n // structured correctly as this is what's used for parsing blocks. We\n // just render a placeholder div inside as the `blockContent` element\n // already has all the information needed for proper parsing.\n const div = document.createElement(\"div\");\n return wrapInBlockStructure(\n {\n dom: div,\n contentDOM: blockConfig.content === \"inline\" ? div : undefined,\n },\n blockConfig.type,\n {},\n blockConfig.propSchema,\n blockConfig.isFileBlock,\n HTMLAttributes,\n );\n },\n\n addNodeView() {\n return ({ getPos }) => {\n // Gets the BlockNote editor instance\n const editor = this.options.editor;\n // Gets the block\n const block = getBlockFromPos(\n getPos,\n editor,\n this.editor,\n blockConfig.type,\n );\n // Gets the custom HTML attributes for `blockContent` nodes\n const blockContentDOMAttributes =\n this.options.domAttributes?.blockContent || {};\n\n const output = blockImplementation.render(block as any, editor);\n\n const nodeView: NodeView = wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes,\n );\n\n if (blockConfig.isSelectable === false) {\n applyNonSelectableBlockFix(nodeView, this.editor);\n }\n\n return nodeView;\n };\n },\n });\n\n if (node.name !== blockConfig.type) {\n throw new Error(\n \"Node name does not match block type. This is a bug in BlockNote.\",\n );\n }\n\n return createInternalBlockSpec(blockConfig, {\n node,\n toInternalHTML: (block, editor) => {\n const blockContentDOMAttributes =\n node.options.domAttributes?.blockContent || {};\n\n const output = blockImplementation.render(block as any, editor as any);\n\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockConfig.isFileBlock,\n blockContentDOMAttributes,\n );\n },\n // TODO: this should not have wrapInBlockStructure and generally be a lot simpler\n // post-processing in externalHTMLExporter should not be necessary\n toExternalHTML: (block, editor) => {\n const blockContentDOMAttributes =\n node.options.domAttributes?.blockContent || {};\n\n let output = blockImplementation.toExternalHTML?.(\n block as any,\n editor as any,\n );\n if (output === undefined) {\n output = blockImplementation.render(block as any, editor as any);\n }\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes,\n );\n },\n });\n}\n","import { Node, ResolvedPos } from \"prosemirror-model\";\nimport { EditorState, Transaction } from \"prosemirror-state\";\n\ntype SingleBlockInfo = {\n node: Node;\n beforePos: number;\n afterPos: number;\n};\n\nexport type BlockInfo = {\n /**\n * The outer node that represents a BlockNote block. This is the node that has the ID.\n * Most of the time, this will be a blockContainer node, but it could also be a Column or ColumnList\n */\n bnBlock: SingleBlockInfo;\n /**\n * The type of BlockNote block that this node represents.\n * When dealing with a blockContainer, this is retrieved from the blockContent node, otherwise it's retrieved from the bnBlock node.\n */\n blockNoteType: string;\n} & (\n | {\n // In case we're not dealing with a BlockContainer, we're dealing with a \"wrapper node\" (like a Column or ColumnList), so it will always have children\n\n /**\n * The Prosemirror node that holds block.children. For non-blockContainer, this node will be the same as bnBlock.\n */\n childContainer: SingleBlockInfo;\n isBlockContainer: false;\n }\n | {\n /**\n * The Prosemirror node that holds block.children. For blockContainers, this is the blockGroup node, if it exists.\n */\n childContainer?: SingleBlockInfo;\n /**\n * The Prosemirror node that wraps block.content and has most of the props\n */\n blockContent: SingleBlockInfo;\n /**\n * Whether bnBlock is a blockContainer node\n */\n isBlockContainer: true;\n }\n);\n\n/**\n * Retrieves the position just before the nearest block node in a ProseMirror\n * doc, relative to a position. If the position is within a block node or its\n * descendants, the position just before it is returned. If the position is not\n * within a block node or its descendants, the position just before the next\n * closest block node is returned. If the position is beyond the last block, the\n * position just before the last block is returned.\n * @param doc The ProseMirror doc.\n * @param pos An integer position in the document.\n * @returns The position just before the nearest blockContainer node.\n */\nexport function getNearestBlockPos(doc: Node, pos: number) {\n const $pos = doc.resolve(pos);\n\n // Checks if the position provided is already just before a block node, in\n // which case we return the position.\n if ($pos.nodeAfter && $pos.nodeAfter.type.isInGroup(\"bnBlock\")) {\n return {\n posBeforeNode: $pos.pos,\n node: $pos.nodeAfter,\n };\n }\n\n // Checks the node containing the position and its ancestors until a\n // block node is found and returned.\n let depth = $pos.depth;\n let node = $pos.node(depth);\n while (depth > 0) {\n if (node.type.isInGroup(\"bnBlock\")) {\n return {\n posBeforeNode: $pos.before(depth),\n node: node,\n };\n }\n\n depth--;\n node = $pos.node(depth);\n }\n\n // If the position doesn't lie within a block node, we instead find the\n // position of the next closest one. If the position is beyond the last block,\n // we return the position of the last block. While running `doc.descendants`\n // is expensive, this case should be very rarely triggered. However, it's\n // possible for the position to sometimes be beyond the last block node. This\n // is a problem specifically when using the collaboration plugin.\n const allBlockContainerPositions: number[] = [];\n doc.descendants((node, pos) => {\n if (node.type.isInGroup(\"bnBlock\")) {\n allBlockContainerPositions.push(pos);\n }\n });\n\n // eslint-disable-next-line no-console\n console.warn(`Position ${pos} is not within a blockContainer node.`);\n\n const resolvedPos = doc.resolve(\n allBlockContainerPositions.find((position) => position >= pos) ||\n allBlockContainerPositions[allBlockContainerPositions.length - 1],\n );\n return {\n posBeforeNode: resolvedPos.pos,\n node: resolvedPos.nodeAfter!,\n };\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block in a\n * BlockNote document. This includes the main `blockContainer` node, the\n * `blockContent` node with the block's main body, and the optional `blockGroup`\n * node which contains the block's children. As well as the nodes, also returns\n * the ProseMirror positions just before & after each node.\n * @param node The main `blockContainer` node that the block information should\n * be retrieved from,\n * @param bnBlockBeforePosOffset the position just before the\n * `blockContainer` node in the document.\n */\nexport function getBlockInfoWithManualOffset(\n node: Node,\n bnBlockBeforePosOffset: number,\n): BlockInfo {\n if (!node.type.isInGroup(\"bnBlock\")) {\n throw new Error(\n `Attempted to get bnBlock node at position but found node of different type ${node.type.name}`,\n );\n }\n\n const bnBlockNode = node;\n const bnBlockBeforePos = bnBlockBeforePosOffset;\n const bnBlockAfterPos = bnBlockBeforePos + bnBlockNode.nodeSize;\n\n const bnBlock: SingleBlockInfo = {\n node: bnBlockNode,\n beforePos: bnBlockBeforePos,\n afterPos: bnBlockAfterPos,\n };\n\n if (bnBlockNode.type.name === \"blockContainer\") {\n let blockContent: SingleBlockInfo | undefined;\n let blockGroup: SingleBlockInfo | undefined;\n\n bnBlockNode.forEach((node, offset) => {\n if (node.type.spec.group === \"blockContent\") {\n // console.log(beforePos, offset);\n const blockContentNode = node;\n const blockContentBeforePos = bnBlockBeforePos + offset + 1;\n const blockContentAfterPos = blockContentBeforePos + node.nodeSize;\n\n blockContent = {\n node: blockContentNode,\n beforePos: blockContentBeforePos,\n afterPos: blockContentAfterPos,\n };\n } else if (node.type.name === \"blockGroup\") {\n const blockGroupNode = node;\n const blockGroupBeforePos = bnBlockBeforePos + offset + 1;\n const blockGroupAfterPos = blockGroupBeforePos + node.nodeSize;\n\n blockGroup = {\n node: blockGroupNode,\n beforePos: blockGroupBeforePos,\n afterPos: blockGroupAfterPos,\n };\n }\n });\n\n if (!blockContent) {\n throw new Error(\n `blockContainer node does not contain a blockContent node in its children: ${bnBlockNode}`,\n );\n }\n\n return {\n isBlockContainer: true,\n bnBlock,\n blockContent,\n childContainer: blockGroup,\n blockNoteType: blockContent.node.type.name,\n };\n } else {\n if (!bnBlock.node.type.isInGroup(\"childContainer\")) {\n throw new Error(\n `bnBlock node is not in the childContainer group: ${bnBlock.node}`,\n );\n }\n\n return {\n isBlockContainer: false,\n bnBlock: bnBlock,\n childContainer: bnBlock,\n blockNoteType: bnBlock.node.type.name,\n };\n }\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block in a\n * BlockNote document. This includes the main `blockContainer` node, the\n * `blockContent` node with the block's main body, and the optional `blockGroup`\n * node which contains the block's children. As well as the nodes, also returns\n * the ProseMirror positions just before & after each node.\n * @param posInfo An object with the main `blockContainer` node that the block\n * information should be retrieved from, and the position just before it in the\n * document.\n */\nexport function getBlockInfo(posInfo: { posBeforeNode: number; node: Node }) {\n return getBlockInfoWithManualOffset(posInfo.node, posInfo.posBeforeNode);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block from a\n * resolved position just before the `blockContainer` node in the document that\n * corresponds to it.\n * @param resolvedPos The resolved position just before the `blockContainer`\n * node.\n */\nexport function getBlockInfoFromResolvedPos(resolvedPos: ResolvedPos) {\n if (!resolvedPos.nodeAfter) {\n throw new Error(\n `Attempted to get blockContainer node at position ${resolvedPos.pos} but a node at this position does not exist`,\n );\n }\n return getBlockInfoWithManualOffset(resolvedPos.nodeAfter, resolvedPos.pos);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block. The\n * block chosen is the one currently containing the current ProseMirror\n * selection.\n * @param state The ProseMirror editor state.\n */\nexport function getBlockInfoFromSelection(state: EditorState) {\n const posInfo = getNearestBlockPos(state.doc, state.selection.anchor);\n\n return getBlockInfo(posInfo);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block. The\n * block chosen is the one currently containing the current ProseMirror\n * selection.\n * @param tr The ProseMirror transaction.\n */\nexport function getBlockInfoFromTransaction(tr: Transaction) {\n const posInfo = getNearestBlockPos(tr.doc, tr.selection.anchor);\n\n return getBlockInfo(posInfo);\n}\n","import type { Node, Schema } from \"prosemirror-model\";\nimport { Transform } from \"prosemirror-transform\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport { BlockNoteSchema } from \"../editor/BlockNoteSchema.js\";\nimport type { BlockSchema } from \"../schema/blocks/types.js\";\nimport type { InlineContentSchema } from \"../schema/inlineContent/types.js\";\nimport type { StyleSchema } from \"../schema/styles/types.js\";\n\nexport function getPmSchema(trOrNode: Transform | Node) {\n if (\"doc\" in trOrNode) {\n return trOrNode.doc.type.schema;\n }\n return trOrNode.type.schema;\n}\n\nfunction getBlockNoteEditor<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(schema: Schema): BlockNoteEditor<BSchema, I, S> {\n return schema.cached.blockNoteEditor as BlockNoteEditor<BSchema, I, S>;\n}\n\nexport function getBlockNoteSchema<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(schema: Schema): BlockNoteSchema<BSchema, I, S> {\n return getBlockNoteEditor(schema).schema as unknown as BlockNoteSchema<\n BSchema,\n I,\n S\n >;\n}\n\nexport function getBlockSchema<BSchema extends BlockSchema>(\n schema: Schema,\n): BSchema {\n return getBlockNoteSchema(schema).blockSchema as BSchema;\n}\n\nexport function getInlineContentSchema<I extends InlineContentSchema>(\n schema: Schema,\n): I {\n return getBlockNoteSchema(schema).inlineContentSchema as I;\n}\n\nexport function getStyleSchema<S extends StyleSchema>(schema: Schema): S {\n return getBlockNoteSchema(schema).styleSchema as S;\n}\n\nexport function getBlockCache(schema: Schema) {\n return getBlockNoteEditor(schema).blockCache;\n}\n","import { Mark, Node, Schema, Slice } from \"@tiptap/pm/model\";\nimport type { Block } from \"../../blocks/defaultBlocks.js\";\nimport UniqueID from \"../../extensions/UniqueID/UniqueID.js\";\nimport type {\n BlockSchema,\n CustomInlineContentConfig,\n CustomInlineContentFromConfig,\n InlineContent,\n InlineContentFromConfig,\n InlineContentSchema,\n StyleSchema,\n Styles,\n TableCell,\n TableContent,\n} from \"../../schema/index.js\";\nimport {\n isLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types.js\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport { getBlockInfoWithManualOffset } from \"../getBlockInfoFromPos.js\";\nimport {\n getBlockCache,\n getBlockSchema,\n getInlineContentSchema,\n getStyleSchema,\n} from \"../pmUtil.js\";\n\n/**\n * Converts an internal (prosemirror) table node contentto a BlockNote Tablecontent\n */\nexport function contentNodeToTableContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(contentNode: Node, inlineContentSchema: I, styleSchema: S) {\n const ret: TableContent<I, S> = {\n type: \"tableContent\",\n columnWidths: [],\n headerRows: undefined,\n headerCols: undefined,\n rows: [],\n };\n\n /**\n * A matrix of boolean values indicating whether a cell is a header.\n * The first index is the row index, the second index is the cell index.\n */\n const headerMatrix: boolean[][] = [];\n\n contentNode.content.forEach((rowNode, _offset, rowIndex) => {\n const row: TableContent<I, S>[\"rows\"][0] = {\n cells: [],\n };\n\n if (rowIndex === 0) {\n rowNode.content.forEach((cellNode) => {\n let colWidth = cellNode.attrs.colwidth as null | undefined | number[];\n if (colWidth === undefined || colWidth === null) {\n colWidth = new Array(cellNode.attrs.colspan ?? 1).fill(undefined);\n }\n ret.columnWidths.push(...colWidth);\n });\n }\n\n row.cells = rowNode.content.content.map((cellNode, cellIndex) => {\n if (!headerMatrix[rowIndex]) {\n headerMatrix[rowIndex] = [];\n }\n // Mark the cell as a header if it is a tableHeader node.\n headerMatrix[rowIndex][cellIndex] = cellNode.type.name === \"tableHeader\";\n // Convert cell content to inline content and merge adjacent styled text nodes\n const content = cellNode.content.content\n .map((child) =>\n contentNodeToInlineContent(child, inlineContentSchema, styleSchema),\n )\n // The reason that we merge this content is that we allow table cells to contain multiple tableParagraph nodes\n // So that we can leverage prosemirror-tables native merging\n // If the schema only allowed a single tableParagraph node, then the merging would not work and cause prosemirror to fit the content into a new cell\n .reduce(\n (acc, contentPartial) => {\n if (!acc.length) {\n return contentPartial;\n }\n\n const last = acc[acc.length - 1];\n const first = contentPartial[0];\n\n // Only merge if the last and first content are both styled text nodes and have the same styles\n if (\n first &&\n isStyledTextInlineContent(last) &&\n isStyledTextInlineContent(first) &&\n JSON.stringify(last.styles) === JSON.stringify(first.styles)\n ) {\n // Join them together if they have the same styles\n last.text += \"\\n\" + first.text;\n acc.push(...contentPartial.slice(1));\n return acc;\n }\n acc.push(...contentPartial);\n return acc;\n },\n [] as InlineContent<I, S>[],\n );\n\n return {\n type: \"tableCell\",\n content,\n props: {\n colspan: cellNode.attrs.colspan,\n rowspan: cellNode.attrs.rowspan,\n backgroundColor: cellNode.attrs.backgroundColor,\n textColor: cellNode.attrs.textColor,\n textAlignment: cellNode.attrs.textAlignment,\n },\n } satisfies TableCell<I, S>;\n });\n\n ret.rows.push(row);\n });\n\n for (let i = 0; i < headerMatrix.length; i++) {\n if (headerMatrix[i]?.every((isHeader) => isHeader)) {\n ret.headerRows = (ret.headerRows ?? 0) + 1;\n }\n }\n\n for (let i = 0; i < headerMatrix[0]?.length; i++) {\n if (headerMatrix?.every((row) => row[i])) {\n ret.headerCols = (ret.headerCols ?? 0) + 1;\n }\n }\n\n return ret;\n}\n\n/**\n * Converts an internal (prosemirror) content node to a BlockNote InlineContent array.\n */\nexport function contentNodeToInlineContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(contentNode: Node, inlineContentSchema: I, styleSchema: S) {\n const content: InlineContent<any, S>[] = [];\n let currentContent: InlineContent<any, S> | undefined = undefined;\n\n // Most of the logic below is for handling links because in ProseMirror links are marks\n // while in BlockNote links are a type of inline content\n contentNode.content.forEach((node) => {\n // hardBreak nodes do not have an InlineContent equivalent, instead we\n // add a newline to the previous node.\n if (node.type.name === \"hardBreak\") {\n if (currentContent) {\n // Current content exists.\n if (isStyledTextInlineContent(currentContent)) {\n // Current content is text.\n currentContent.text += \"\\n\";\n } else if (isLinkInlineContent(currentContent)) {\n // Current content is a link.\n currentContent.content[currentContent.content.length - 1].text +=\n \"\\n\";\n } else {\n throw new Error(\"unexpected\");\n }\n } else {\n // Current content does not exist.\n currentContent = {\n type: \"text\",\n text: \"\\n\",\n styles: {},\n };\n }\n\n return;\n }\n\n if (node.type.name !== \"link\" && node.type.name !== \"text\") {\n if (!inlineContentSchema[node.type.name]) {\n // eslint-disable-next-line no-console\n console.warn(\"unrecognized inline content type\", node.type.name);\n return;\n }\n if (currentContent) {\n content.push(currentContent);\n currentContent = undefined;\n }\n\n content.push(\n nodeToCustomInlineContent(node, inlineContentSchema, styleSchema),\n );\n\n return;\n }\n\n const styles: Styles<S> = {};\n let linkMark: Mark | undefined;\n\n for (const mark of node.marks) {\n if (mark.type.name === \"link\") {\n linkMark = mark;\n } else {\n const config = styleSchema[mark.type.name];\n if (!config) {\n if (mark.type.spec.blocknoteIgnore) {\n // at this point, we don't want to show certain marks (such as comments)\n // in the BlockNote JSON output. These marks should be tagged with \"blocknoteIgnore\" in the spec\n continue;\n }\n throw new Error(`style ${mark.type.name} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n (styles as any)[config.type] = true;\n } else if (config.propSchema === \"string\") {\n (styles as any)[config.type] = mark.attrs.stringValue;\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n // Parsing links and text.\n // Current content exists.\n if (currentContent) {\n // Current content is text.\n if (isStyledTextInlineContent(currentContent)) {\n if (!linkMark) {\n // Node is text (same type as current content).\n if (\n JSON.stringify(currentContent.styles) === JSON.stringify(styles)\n ) {\n // Styles are the same.\n currentContent.text += node.textContent;\n } else {\n // Styles are different.\n content.push(currentContent);\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n } else {\n // Node is a link (different type to current content).\n content.push(currentContent);\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n } else if (isLinkInlineContent(currentContent)) {\n // Current content is a link.\n if (linkMark) {\n // Node is a link (same type as current content).\n // Link URLs are the same.\n if (currentContent.href === linkMark.attrs.href) {\n // Styles are the same.\n if (\n JSON.stringify(\n currentContent.content[currentContent.content.length - 1]\n .styles,\n ) === JSON.stringify(styles)\n ) {\n currentContent.content[currentContent.content.length - 1].text +=\n node.textContent;\n } else {\n // Styles are different.\n currentContent.content.push({\n type: \"text\",\n text: node.textContent,\n styles,\n });\n }\n } else {\n // Link URLs are different.\n content.push(currentContent);\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n } else {\n // Node is text (different type to current content).\n content.push(currentContent);\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n } else {\n // TODO\n }\n }\n // Current content does not exist.\n else {\n // Node is text.\n if (!linkMark) {\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n // Node is a link.\n else {\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n }\n });\n\n if (currentContent) {\n content.push(currentContent);\n }\n\n return content as InlineContent<I, S>[];\n}\n\nexport function nodeToCustomInlineContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(node: Node, inlineContentSchema: I, styleSchema: S): InlineContent<I, S> {\n if (node.type.name === \"text\" || node.type.name === \"link\") {\n throw new Error(\"unexpected\");\n }\n const props: any = {};\n const icConfig = inlineContentSchema[\n node.type.name\n ] as CustomInlineContentConfig;\n for (const [attr, value] of Object.entries(node.attrs)) {\n if (!icConfig) {\n throw Error(\"ic node is of an unrecognized type: \" + node.type.name);\n }\n\n const propSchema = icConfig.propSchema;\n\n if (attr in propSchema) {\n props[attr] = value;\n }\n }\n\n let content: CustomInlineContentFromConfig<any, any>[\"content\"];\n\n if (icConfig.content === \"styled\") {\n content = contentNodeToInlineContent(\n node,\n inlineContentSchema,\n styleSchema,\n ) as any; // TODO: is this safe? could we have Links here that are undesired?\n } else {\n content = undefined;\n }\n\n const ic = {\n type: node.type.name,\n props,\n content,\n } as InlineContentFromConfig<I[keyof I], S>;\n return ic;\n}\n\n/**\n * Convert a Prosemirror node to a BlockNote block.\n *\n * TODO: test changes\n */\nexport function nodeToBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n node: Node,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache = getBlockCache(schema),\n): Block<BSchema, I, S> {\n if (!node.type.isInGroup(\"bnBlock\")) {\n throw Error(\"Node should be a bnBlock, but is instead: \" + node.type.name);\n }\n\n const cachedBlock = blockCache?.get(node);\n\n if (cachedBlock) {\n return cachedBlock;\n }\n\n const blockInfo = getBlockInfoWithManualOffset(node, 0);\n\n let id = blockInfo.bnBlock.node.attrs.id;\n\n // Only used for blocks converted from other formats.\n if (id === null) {\n id = UniqueID.options.generateID();\n }\n\n const blockSpec = blockSchema[blockInfo.blockNoteType];\n\n if (!blockSpec) {\n throw Error(\"Block is of an unrecognized type: \" + blockInfo.blockNoteType);\n }\n\n const props: any = {};\n for (const [attr, value] of Object.entries({\n ...node.attrs,\n ...(blockInfo.isBlockContainer ? blockInfo.blockContent.node.attrs : {}),\n })) {\n const propSchema = blockSpec.propSchema;\n\n if (\n attr in propSchema &&\n !(propSchema[attr].default === undefined && value === undefined)\n ) {\n props[attr] = value;\n }\n }\n\n const blockConfig = blockSchema[blockInfo.blockNoteType];\n\n const children: Block<BSchema, I, S>[] = [];\n blockInfo.childContainer?.node.forEach((child) => {\n children.push(\n nodeToBlock(\n child,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n ),\n );\n });\n\n let content: Block<any, any, any>[\"content\"];\n\n if (blockConfig.content === \"inline\") {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n content = contentNodeToInlineContent(\n blockInfo.blockContent.node,\n inlineContentSchema,\n styleSchema,\n );\n } else if (blockConfig.content === \"table\") {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n content = contentNodeToTableContent(\n blockInfo.blockContent.node,\n inlineContentSchema,\n styleSchema,\n );\n } else if (blockConfig.content === \"none\") {\n content = undefined;\n } else {\n throw new UnreachableCaseError(blockConfig.content);\n }\n\n const block = {\n id,\n type: blockConfig.type,\n props,\n content,\n children,\n } as Block<BSchema, I, S>;\n\n blockCache?.set(node, block);\n\n return block;\n}\n\n/**\n * Convert a Prosemirror document to a BlockNote document (array of blocks)\n */\nexport function docToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache = getBlockCache(schema),\n) {\n const blocks: Block<BSchema, I, S>[] = [];\n doc.firstChild!.descendants((node) => {\n blocks.push(\n nodeToBlock(\n node,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n ),\n );\n return false;\n });\n return blocks;\n}\n\n/**\n *\n * Parse a Prosemirror Slice into a BlockNote selection. The prosemirror schema looks like this:\n *\n * <blockGroup>\n * <blockContainer> (main content of block)\n * <p, heading, etc.>\n * <blockGroup> (only if blocks has children)\n * <blockContainer> (child block)\n * <p, heading, etc.>\n * </blockContainer>\n * <blockContainer> (child block 2)\n * <p, heading, etc.>\n * </blockContainer>\n * </blockContainer>\n * </blockGroup>\n * </blockGroup>\n *\n */\nexport function prosemirrorSliceToSlicedBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n slice: Slice,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache: WeakMap<Node, Block<BSchema, I, S>> = getBlockCache(schema),\n): {\n /**\n * The blocks that are included in the selection.\n */\n blocks: Block<BSchema, I, S>[];\n /**\n * If a block was \"cut\" at the start of the selection, this will be the id of the block that was cut.\n */\n blockCutAtStart: string | undefined;\n /**\n * If a block was \"cut\" at the end of the selection, this will be the id of the block that was cut.\n */\n blockCutAtEnd: string | undefined;\n} {\n // console.log(JSON.stringify(slice.toJSON()));\n function processNode(\n node: Node,\n openStart: number,\n openEnd: number,\n ): {\n blocks: Block<BSchema, I, S>[];\n blockCutAtStart: string | undefined;\n blockCutAtEnd: string | undefined;\n } {\n if (node.type.name !== \"blockGroup\") {\n throw new Error(\"unexpected\");\n }\n const blocks: Block<BSchema, I, S>[] = [];\n let blockCutAtStart: string | undefined;\n let blockCutAtEnd: string | undefined;\n\n node.forEach((blockContainer, _offset, index) => {\n if (blockContainer.type.name !== \"blockContainer\") {\n throw new Error(\"unexpected\");\n }\n if (blockContainer.childCount === 0) {\n return;\n }\n if (blockContainer.childCount === 0 || blockContainer.childCount > 2) {\n throw new Error(\n \"unexpected, blockContainer.childCount: \" + blockContainer.childCount,\n );\n }\n\n const isFirstBlock = index === 0;\n const isLastBlock = index === node.childCount - 1;\n\n if (blockContainer.firstChild!.type.name === \"blockGroup\") {\n // this is the parent where a selection starts within one of its children,\n // e.g.:\n // A\n // ├── B\n // selection starts within B, then this blockContainer is A, but we don't care about A\n // so let's descend into B and continue processing\n if (!isFirstBlock) {\n throw new Error(\"unexpected\");\n }\n const ret = processNode(\n blockContainer.firstChild!,\n Math.max(0, openStart - 1),\n isLastBlock ? Math.max(0, openEnd - 1) : 0,\n );\n blockCutAtStart = ret.blockCutAtStart;\n if (isLastBlock) {\n blockCutAtEnd = ret.blockCutAtEnd;\n }\n blocks.push(...ret.blocks);\n return;\n }\n\n const block = nodeToBlock(\n blockContainer,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n );\n const childGroup =\n blockContainer.childCount > 1 ? blockContainer.child(1) : undefined;\n\n let childBlocks: Block<BSchema, I, S>[] = [];\n if (childGroup) {\n const ret = processNode(\n childGroup,\n 0, // TODO: can this be anything other than 0?\n isLastBlock ? Math.max(0, openEnd - 1) : 0,\n );\n childBlocks = ret.blocks;\n if (isLastBlock) {\n blockCutAtEnd = ret.blockCutAtEnd;\n }\n }\n\n if (isLastBlock && !childGroup && openEnd > 1) {\n blockCutAtEnd = block.id;\n }\n\n if (isFirstBlock && openStart > 1) {\n blockCutAtStart = block.id;\n }\n\n blocks.push({\n ...(block as any),\n children: childBlocks,\n });\n });\n\n return { blocks, blockCutAtStart, blockCutAtEnd };\n }\n\n if (slice.content.childCount === 0) {\n return {\n blocks: [],\n blockCutAtStart: undefined,\n blockCutAtEnd: undefined,\n };\n }\n\n if (slice.content.childCount !== 1) {\n throw new Error(\n \"slice must be a single block, did you forget includeParents=true?\",\n );\n }\n\n return processNode(\n slice.content.firstChild!,\n Math.max(slice.openStart - 1, 0),\n Math.max(slice.openEnd - 1, 0),\n );\n}\n","import { KeyboardShortcutCommand, Node } from \"@tiptap/core\";\n\nimport { camelToDataKebab } from \"../../util/string.js\";\nimport { PropSchema, Props } from \"../propTypes.js\";\nimport {\n CustomInlineContentConfig,\n InlineContentConfig,\n InlineContentImplementation,\n InlineContentSchemaFromSpecs,\n InlineContentSpec,\n InlineContentSpecs,\n} from \"./types.js\";\n\n// Function that adds necessary classes and attributes to the `dom` element\n// returned from a custom inline content's 'render' function, to ensure no data\n// is lost on internal copy & paste.\nexport function addInlineContentAttributes<\n IType extends string,\n PSchema extends PropSchema,\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n },\n inlineContentType: IType,\n inlineContentProps: Props<PSchema>,\n propSchema: PSchema,\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} {\n // Sets content type attribute\n element.dom.setAttribute(\"data-inline-content-type\", inlineContentType);\n // Adds props as HTML attributes in kebab-case with \"data-\" prefix. Skips props\n // set to their default values.\n Object.entries(inlineContentProps)\n .filter(([prop, value]) => {\n const spec = propSchema[prop];\n return value !== spec.default;\n })\n .map(([prop, value]) => {\n return [camelToDataKebab(prop), value];\n })\n .forEach(([prop, value]) => element.dom.setAttribute(prop, value));\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return element;\n}\n\n// see https://github.com/TypeCellOS/BlockNote/pull/435\nexport function addInlineContentKeyboardShortcuts<\n T extends CustomInlineContentConfig,\n>(\n config: T,\n): {\n [p: string]: KeyboardShortcutCommand;\n} {\n return {\n Backspace: ({ editor }) => {\n const resolvedPos = editor.state.selection.$from;\n\n return (\n editor.state.selection.empty &&\n resolvedPos.node().type.name === config.type &&\n resolvedPos.parentOffset === 0\n );\n },\n };\n}\n\n// This helper function helps to instantiate a InlineContentSpec with a\n// config and implementation that conform to the type of Config\nexport function createInternalInlineContentSpec<T extends InlineContentConfig>(\n config: T,\n implementation: InlineContentImplementation<T>,\n) {\n return {\n config,\n implementation,\n } satisfies InlineContentSpec<T>;\n}\n\nexport function createInlineContentSpecFromTipTapNode<\n T extends Node,\n P extends PropSchema,\n>(node: T, propSchema: P) {\n return createInternalInlineContentSpec(\n {\n type: node.name as T[\"name\"],\n propSchema,\n content: node.config.content === \"inline*\" ? \"styled\" : \"none\",\n },\n {\n node,\n },\n );\n}\n\nexport function getInlineContentSchemaFromSpecs<T extends InlineContentSpecs>(\n specs: T,\n) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config]),\n ) as InlineContentSchemaFromSpecs<T>;\n}\n","import { Node } from \"@tiptap/core\";\n\nimport { TagParseRule } from \"@tiptap/pm/model\";\nimport { inlineContentToNodes } from \"../../api/nodeConversions/blockToNode.js\";\nimport { nodeToCustomInlineContent } from \"../../api/nodeConversions/nodeToBlock.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { propsToAttributes } from \"../blocks/internal.js\";\nimport { Props } from \"../propTypes.js\";\nimport { StyleSchema } from \"../styles/types.js\";\nimport {\n addInlineContentAttributes,\n addInlineContentKeyboardShortcuts,\n createInlineContentSpecFromTipTapNode,\n} from \"./internal.js\";\nimport {\n CustomInlineContentConfig,\n InlineContentFromConfig,\n InlineContentSpec,\n PartialCustomInlineContentFromConfig,\n} from \"./types.js\";\n\n// TODO: support serialization\n\nexport type CustomInlineContentImplementation<\n T extends CustomInlineContentConfig,\n // B extends BlockSchema,\n // I extends InlineContentSchema,\n S extends StyleSchema,\n> = {\n render: (\n /**\n * The custom inline content to render\n */\n inlineContent: InlineContentFromConfig<T, S>,\n updateInlineContent: (\n update: PartialCustomInlineContentFromConfig<T, S>,\n ) => void,\n /**\n * The BlockNote editor instance\n * This is typed generically. If you want an editor with your custom schema, you need to\n * cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`\n */\n editor: BlockNoteEditor<any, any, S>,\n // (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations\n // or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n // destroy?: () => void;\n };\n};\n\nexport function getInlineContentParseRules(\n config: CustomInlineContentConfig,\n): TagParseRule[] {\n return [\n {\n tag: `[data-inline-content-type=\"${config.type}\"]`,\n contentElement: (element) => {\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.matches(\"[data-editable]\")) {\n return htmlElement;\n }\n\n return htmlElement.querySelector(\"[data-editable]\") || htmlElement;\n },\n },\n ];\n}\n\nexport function createInlineContentSpec<\n T extends CustomInlineContentConfig,\n S extends StyleSchema,\n>(\n inlineContentConfig: T,\n inlineContentImplementation: CustomInlineContentImplementation<T, S>,\n): InlineContentSpec<T> {\n const node = Node.create({\n name: inlineContentConfig.type,\n inline: true,\n group: \"inline\",\n selectable: inlineContentConfig.content === \"styled\",\n atom: inlineContentConfig.content === \"none\",\n content: (inlineContentConfig.content === \"styled\"\n ? \"inline*\"\n : \"\") as T[\"content\"] extends \"styled\" ? \"inline*\" : \"\",\n\n addAttributes() {\n return propsToAttributes(inlineContentConfig.propSchema);\n },\n\n addKeyboardShortcuts() {\n return addInlineContentKeyboardShortcuts(inlineContentConfig);\n },\n\n parseHTML() {\n return getInlineContentParseRules(inlineContentConfig);\n },\n\n renderHTML({ node }) {\n const editor = this.options.editor;\n\n const output = inlineContentImplementation.render(\n nodeToCustomInlineContent(\n node,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n ) as any as InlineContentFromConfig<T, S>, // TODO: fix cast\n () => {\n // No-op\n },\n editor,\n );\n\n return addInlineContentAttributes(\n output,\n inlineContentConfig.type,\n node.attrs as Props<T[\"propSchema\"]>,\n inlineContentConfig.propSchema,\n );\n },\n\n addNodeView() {\n return ({ node, getPos }) => {\n const editor = this.options.editor as BlockNoteEditor<any, any, S>;\n\n const output = inlineContentImplementation.render(\n nodeToCustomInlineContent(\n node,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n ) as any as InlineContentFromConfig<T, S>, // TODO: fix cast\n (update) => {\n if (typeof getPos === \"boolean\") {\n return;\n }\n\n const content = inlineContentToNodes([update], editor.pmSchema);\n\n editor.transact((tr) =>\n tr.replaceWith(getPos(), getPos() + node.nodeSize, content),\n );\n },\n editor,\n );\n\n return addInlineContentAttributes(\n output,\n inlineContentConfig.type,\n node.attrs as Props<T[\"propSchema\"]>,\n inlineContentConfig.propSchema,\n );\n };\n },\n });\n\n return createInlineContentSpecFromTipTapNode(\n node,\n inlineContentConfig.propSchema,\n ) as InlineContentSpec<T>; // TODO: fix cast\n}\n","import { Attributes, Mark } from \"@tiptap/core\";\nimport {\n StyleConfig,\n StyleImplementation,\n StylePropSchema,\n StyleSchemaFromSpecs,\n StyleSpec,\n StyleSpecs,\n} from \"./types.js\";\n\nexport function stylePropsToAttributes(\n propSchema: StylePropSchema,\n): Attributes {\n if (propSchema === \"boolean\") {\n return {};\n }\n return {\n stringValue: {\n default: undefined,\n keepOnSplit: true,\n parseHTML: (element) => element.getAttribute(\"data-value\"),\n renderHTML: (attributes) =>\n attributes.stringValue !== undefined\n ? {\n \"data-value\": attributes.stringValue,\n }\n : {},\n },\n };\n}\n\n// Function that adds necessary classes and attributes to the `dom` element\n// returned from a custom style's 'render' function, to ensure no data is lost\n// on internal copy & paste.\nexport function addStyleAttributes<\n SType extends string,\n PSchema extends StylePropSchema,\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n },\n styleType: SType,\n styleValue: PSchema extends \"boolean\" ? undefined : string,\n propSchema: PSchema,\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} {\n // Sets content type attribute\n element.dom.setAttribute(\"data-style-type\", styleType);\n // Adds style value as an HTML attribute in kebab-case with \"data-\" prefix, if\n // the style takes a string value.\n if (propSchema === \"string\") {\n element.dom.setAttribute(\"data-value\", styleValue as string);\n }\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return element;\n}\n\n// This helper function helps to instantiate a stylespec with a\n// config and implementation that conform to the type of Config\nexport function createInternalStyleSpec<T extends StyleConfig>(\n config: T,\n implementation: StyleImplementation,\n) {\n return {\n config,\n implementation,\n } satisfies StyleSpec<T>;\n}\n\nexport function createStyleSpecFromTipTapMark<\n T extends Mark,\n P extends StylePropSchema,\n>(mark: T, propSchema: P) {\n return createInternalStyleSpec(\n {\n type: mark.name as T[\"name\"],\n propSchema,\n },\n {\n mark,\n },\n );\n}\n\nexport function getStyleSchemaFromSpecs<T extends StyleSpecs>(specs: T) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config]),\n ) as StyleSchemaFromSpecs<T>;\n}\n","import { Mark } from \"@tiptap/core\";\n\nimport { ParseRule } from \"@tiptap/pm/model\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport {\n addStyleAttributes,\n createInternalStyleSpec,\n stylePropsToAttributes,\n} from \"./internal.js\";\nimport { StyleConfig, StyleSpec } from \"./types.js\";\n\nexport type CustomStyleImplementation<T extends StyleConfig> = {\n render: T[\"propSchema\"] extends \"boolean\"\n ? () => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n }\n : (value: string) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n};\n\n// TODO: support serialization\n\nexport function getStyleParseRules(config: StyleConfig): ParseRule[] {\n return [\n {\n tag: `[data-style-type=\"${config.type}\"]`,\n contentElement: (element) => {\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.matches(\"[data-editable]\")) {\n return htmlElement;\n }\n\n return htmlElement.querySelector(\"[data-editable]\") || htmlElement;\n },\n },\n ];\n}\n\nexport function createStyleSpec<T extends StyleConfig>(\n styleConfig: T,\n styleImplementation: CustomStyleImplementation<T>,\n): StyleSpec<T> {\n const mark = Mark.create({\n name: styleConfig.type,\n\n addAttributes() {\n return stylePropsToAttributes(styleConfig.propSchema);\n },\n\n parseHTML() {\n return getStyleParseRules(styleConfig);\n },\n\n renderHTML({ mark }) {\n let renderResult: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n if (styleConfig.propSchema === \"boolean\") {\n // @ts-ignore not sure why this is complaining\n renderResult = styleImplementation.render();\n } else if (styleConfig.propSchema === \"string\") {\n renderResult = styleImplementation.render(mark.attrs.stringValue);\n } else {\n throw new UnreachableCaseError(styleConfig.propSchema);\n }\n\n // const renderResult = styleImplementation.render();\n return addStyleAttributes(\n renderResult,\n styleConfig.type,\n mark.attrs.stringValue,\n styleConfig.propSchema,\n );\n },\n });\n\n return createInternalStyleSpec(styleConfig, {\n mark,\n });\n}\n","import { DefaultBlockSchema } from \"../../../blocks/defaultBlocks.js\";\nimport {\n BlockFromConfigNoChildren,\n PartialTableContent,\n TableCell,\n TableContent,\n} from \"../../../schema/blocks/types.js\";\nimport {\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../../schema/index.js\";\nimport {\n getColspan,\n getRowspan,\n isPartialTableCell,\n mapTableCell,\n} from \"../../../util/table.js\";\n\n/**\n * Here be dragons.\n *\n * Tables are complex because of rowspan and colspan behavior.\n * The majority of this file is concerned with translating between \"relative\" and \"absolute\" indices.\n *\n * The following diagram may help explain the relationship between the different indices:\n *\n * One-based indexing of rows and columns in a table:\n * | 1-1 | 1-2 | 1-3 |\n * | 2-1 | 2-2 | 2-3 |\n * | 3-1 | 3-2 | 3-3 |\n *\n * A complicated table with colspans and rowspans:\n * | 1-1 | 1-2 | 1-2 |\n * | 2-1 | 2-1 | 2-2 |\n * | 2-1 | 2-1 | 3-1 |\n *\n * You can see here that we have:\n * - two cells that contain the value \"1-2\", because it has a colspan of 2.\n * - four cells that contain the value \"2-1\", because it has a rowspan of 2 and a colspan of 2.\n *\n * This would be represented in block note json (roughly) as:\n * [\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"1,1\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1\n * },\n * },\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"1,2\"],\n * \"props\": {\n * \"colspan\": 2,\n * \"rowspan\": 1\n * }\n * }\n * ],\n * },\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"2,1\"],\n * \"props\": {\n * \"colspan\": 2,\n * \"rowspan\": 2\n * }\n * },\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"2,2\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1\n * }\n * ],\n * },\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"3,1\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1,\n * }\n * }\n * ]\n * }\n * ]\n *\n * Which maps cleanly to the following HTML:\n *\n * <table>\n * <tr>\n * <td>1-1</td>\n * <td colspan=\"2\">1-2</td>\n * </tr>\n * <tr>\n * <td rowspan=\"2\" colspan=\"2\">2-1</td>\n * <td>2-2</td>\n * </tr>\n * <tr>\n * <td>3-1</td>\n * </tr>\n * </table>\n *\n * We have a problem though, from the block json, there is no way to tell that the cell \"2-1\" is the second cell in the second row.\n * To resolve this, we created the occupancy grid, which is a grid of all the cells in the table, as though they were only 1x1 cells.\n * See {@link OccupancyGrid} for more information.\n *\n */\n\n/**\n * Relative cell indices are relative to the table block's content.\n *\n * This is a sparse representation of the table and is how HTML and BlockNote JSON represent tables.\n *\n * For example, if we have a table with a rowspan of 2, the second row may only have 1 element in a 2x2 table.\n *\n * ```\n * // Visual representation of the table\n * | 1-1 | 1-2 | // has 2 cells\n * | 1-1 | 2-2 | // has only 1 cell\n * // Relative cell indices\n * [{ row: 1, col: 1, rowspan: 2 }, { row: 1, col: 2 }] // has 2 cells\n * [{ row: 1, col: 2 }] // has only 1 cell\n * ```\n */\nexport type RelativeCellIndices = {\n row: number;\n col: number;\n};\n\n/**\n * Absolute cell indices are relative to the table's layout (it's {@link OccupancyGrid}).\n *\n * It is as though the table is a grid of 1x1 cells, and any colspan or rowspan results in multiple 1x1 cells being occupied.\n *\n * For example, if we have a table with a colspan of 2, it will occupy 2 cells in the layout grid.\n *\n * ```\n * // Visual representation of the table\n * | 1-1 | 1-1 | // has 2 cells\n * | 2-1 | 2-2 | // has 2 cell\n * // Absolute cell indices\n * [{ row: 1, col: 1, colspan: 2 }, { row: 1, col: 2, colspan: 2 }] // has 2 cells\n * [{ row: 1, col: 1 }, { row: 1, col: 2 }] // has 2 cells\n * ```\n */\nexport type AbsoluteCellIndices = {\n row: number;\n col: number;\n};\n\n/**\n * An occupancy grid is a grid of the occupied cells in the table.\n * It is used to track the occupied cells in the table to know where to place the next cell.\n *\n * Since it allows us to resolve cell indices both {@link RelativeCellIndices} and {@link AbsoluteCellIndices}, it is the core data structure for table operations.\n */\ntype OccupancyGrid = (RelativeCellIndices & {\n /**\n * The rowspan of the cell.\n */\n rowspan: number;\n /**\n * The colspan of the cell.\n */\n colspan: number;\n /**\n * The cell.\n */\n cell: TableCell<any, any>;\n})[][];\n\n/**\n * This will return the {@link OccupancyGrid} of the table.\n * By laying out the table as though it were a grid of 1x1 cells, we can easily track where the cells are located (both relatively and absolutely).\n *\n * @returns an {@link OccupancyGrid}\n */\nexport function getTableCellOccupancyGrid(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n): OccupancyGrid {\n const { height, width } = getDimensionsOfTable(block);\n\n /**\n * Create a grid to track occupied cells\n * This is used because rowspans and colspans take up multiple spaces\n * So, we need to track the occupied cells in the grid to know where to place the next cell\n */\n const grid: OccupancyGrid = new Array(height)\n .fill(false)\n .map(() => new Array(width).fill(null));\n\n // Find the next unoccupied cell in the table, row-major order\n const findNextAvailable = (row: number, col: number) => {\n for (let i = row; i < height; i++) {\n for (let j = col; j < width; j++) {\n if (!grid[i][j]) {\n return { row: i, col: j };\n }\n }\n }\n\n throw new Error(\n \"Unable to create occupancy grid for table, no more available cells\",\n );\n };\n\n // Build up the grid, trying to fill in the cells with the correct relative row and column indices\n for (let row = 0; row < block.content.rows.length; row++) {\n for (let col = 0; col < block.content.rows[row].cells.length; col++) {\n const cell = mapTableCell(block.content.rows[row].cells[col]);\n const rowspan = getRowspan(cell);\n const colspan = getColspan(cell);\n\n // Rowspan and colspan complicate things, by taking up multiple cells in the grid\n // We need to iterate over the cells that the rowspan and colspan take up\n // and fill in the grid with the correct relative row and column indices\n const { row: startRow, col: startCol } = findNextAvailable(row, col);\n\n // Fill in the rowspan X colspan cells, starting from the next available cell, with the correct relative row and column indices\n for (let i = startRow; i < startRow + rowspan; i++) {\n for (let j = startCol; j < startCol + colspan; j++) {\n if (grid[i][j]) {\n // The cell is already occupied, the table is malformed\n throw new Error(\n `Unable to create occupancy grid for table, cell at ${i},${j} is already occupied`,\n );\n }\n\n grid[i][j] = {\n row,\n col,\n rowspan,\n colspan,\n cell,\n };\n }\n }\n }\n }\n\n // console.log(grid);\n\n return grid;\n}\n\n/**\n * Given an {@link OccupancyGrid}, this will return the {@link TableContent} rows.\n *\n * @note This will remove duplicates from the occupancy grid. And does no bounds checking for validity of the occupancy grid.\n */\nexport function getTableRowsFromOccupancyGrid(\n occupancyGrid: OccupancyGrid,\n): TableContent<any, any>[\"rows\"] {\n // Because a cell can have a rowspan or colspan, it can occupy multiple cells in the occupancy grid\n // So, we need to remove duplicates from the occupancy grid before we can return the table rows\n const seen = new Set<string>();\n\n return occupancyGrid.map((row) => {\n // Just read out the cells in the occupancy grid, removing duplicates\n return {\n cells: row\n .map((cell) => {\n if (seen.has(cell.row + \":\" + cell.col)) {\n return false;\n }\n seen.add(cell.row + \":\" + cell.col);\n return cell.cell;\n })\n .filter((cell): cell is TableCell<any, any> => cell !== false),\n };\n });\n}\n\n/**\n * This will resolve the relative cell indices within the table block to the absolute cell indices within the table, accounting for colspan and rowspan.\n *\n * @note It will return only the first cell (i.e. top-left) that matches the relative cell indices. To find the other absolute cell indices this cell occupies, you can assume it is the rowspan and colspan number of cells away from the top-left cell.\n *\n * @returns The {@link AbsoluteCellIndices} and the {@link TableCell} at the absolute position.\n */\nexport function getAbsoluteTableCells(\n /**\n * The relative position of the cell in the table.\n */\n relativeCellIndices: RelativeCellIndices,\n /**\n * The table block containing the cell.\n */\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n /**\n * The occupancy grid of the table.\n */\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): AbsoluteCellIndices & {\n cell: TableCell<any, any>;\n} {\n for (let r = 0; r < occupancyGrid.length; r++) {\n for (let c = 0; c < occupancyGrid[r].length; c++) {\n // console.log(r, c, occupancyGrid);\n const cell = occupancyGrid[r][c];\n if (\n cell.row === relativeCellIndices.row &&\n cell.col === relativeCellIndices.col\n ) {\n return { row: r, col: c, cell: cell.cell };\n }\n }\n }\n\n throw new Error(\n `Unable to resolve relative table cell indices for table, cell at ${relativeCellIndices.row},${relativeCellIndices.col} is not occupied`,\n );\n}\n\n/**\n * This will get the dimensions of the table block.\n *\n * @returns The height and width of the table.\n */\nexport function getDimensionsOfTable(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n): {\n /**\n * The number of rows in the table.\n */\n height: number;\n /**\n * The number of columns in the table.\n */\n width: number;\n} {\n // Due to the way we store the table, the height is always the number of rows\n const height = block.content.rows.length;\n\n // Calculating the width is a bit more complex, as it is the maximum width of any row\n let width = 0;\n block.content.rows.forEach((row) => {\n // Find the width of the row by summing the colspan of each cell\n let rowWidth = 0;\n row.cells.forEach((cell) => {\n rowWidth += getColspan(cell);\n });\n\n // Update the width if the row is wider than the current width\n width = Math.max(width, rowWidth);\n });\n\n return { height, width };\n}\n\n/**\n * This will resolve the absolute cell indices within the table block to the relative cell indices within the table, accounting for colspan and rowspan.\n *\n * @returns The {@link RelativeCellIndices} and the {@link TableCell} at the relative position.\n */\nexport function getRelativeTableCells(\n /**\n * The {@link AbsoluteCellIndices} of the cell in the table.\n */\n absoluteCellIndices: AbsoluteCellIndices,\n /**\n * The table block containing the cell.\n */\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n /**\n * The occupancy grid of the table.\n */\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n):\n | (RelativeCellIndices & {\n cell: TableContent<any, any>[\"rows\"][number][\"cells\"][number];\n })\n | undefined {\n const occupancyCell =\n occupancyGrid[absoluteCellIndices.row]?.[absoluteCellIndices.col];\n\n // Double check that the cell can be accessed\n if (!occupancyCell) {\n // The cell is not occupied, so it is invalid\n return undefined;\n }\n\n return {\n row: occupancyCell.row,\n col: occupancyCell.col,\n cell: occupancyCell.cell,\n };\n}\n\n/**\n * This will get all the cells within a relative row of a table block.\n *\n * This method always starts the search for the row at the first column of the table.\n *\n * ```\n * // Visual representation of a table\n * | A | B | C |\n * | | D | E |\n * | F | G | H |\n * // \"A\" has a rowspan of 2\n *\n * // getCellsAtRowHandle(0)\n * // returns [\n * { row: 0, col: 0, cell: \"A\" },\n * { row: 0, col: 1, cell: \"B\" },\n * { row: 0, col: 2, cell: \"C\" },\n * ]\n *\n * // getCellsAtColumnHandle(1)\n * // returns [\n * { row: 1, col: 0, cell: \"F\" },\n * { row: 1, col: 1, cell: \"G\" },\n * { row: 1, col: 2, cell: \"H\" },\n * ]\n * ```\n *\n * As you can see, you may not be able to retrieve all nodes given a relative row index, as cells can span multiple rows.\n *\n * @returns All of the cells associated with the relative row of the table. (All cells that have the same relative row index)\n */\nexport function getCellsAtRowHandle(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeRowIndex: RelativeCellIndices[\"row\"],\n) {\n const occupancyGrid = getTableCellOccupancyGrid(block);\n\n if (relativeRowIndex < 0 || relativeRowIndex >= occupancyGrid.length) {\n return [];\n }\n\n // First need to resolve the relative row index to an absolute row index\n let absoluteRow = 0;\n\n // Jump through the occupied cells ${relativeCellIndices.row} times to find the absolute row position\n for (let i = 0; i < relativeRowIndex; i++) {\n const cell = occupancyGrid[absoluteRow]?.[0];\n\n if (!cell) {\n return [];\n }\n\n // Skip the cells that the rowspan takes up\n absoluteRow += cell.rowspan;\n }\n\n // Then for each column, get the cell at the absolute row index as a relative cell index\n const cells = new Array(occupancyGrid[0].length)\n .fill(false)\n .map((_v, col) => {\n return getRelativeTableCells(\n { row: absoluteRow, col },\n block,\n occupancyGrid,\n );\n })\n .filter(\n (a): a is RelativeCellIndices & { cell: TableCell<any, any> } =>\n a !== undefined,\n );\n\n // Filter out duplicates based on row and col properties\n return cells.filter((cell, index) => {\n return (\n cells.findIndex((c) => c.row === cell.row && c.col === cell.col) === index\n );\n });\n}\n\n/**\n * This will get all the cells within a relative column of a table block.\n *\n * This method always starts the search for the column at the first row of the table.\n *\n * ```\n * // Visual representation of a table\n * | A | B |\n * | C | D | E |\n * | F | G | H |\n * // \"A\" has a colspan of 2\n *\n * // getCellsAtColumnHandle(0)\n * // returns [\n * { row: 0, col: 0, cell: \"A\" },\n * { row: 1, col: 0, cell: \"C\" },\n * { row: 2, col: 0, cell: \"F\" },\n * ]\n *\n * // getCellsAtColumnHandle(1)\n * // returns [\n * { row: 0, col: 1, cell: \"B\" },\n * { row: 1, col: 2, cell: \"E\" },\n * { row: 2, col: 2, cell: \"F\" },\n * ]\n * ```\n *\n * As you can see, you may not be able to retrieve all nodes given a relative column index, as cells can span multiple columns.\n *\n * @returns All of the cells associated with the relative column of the table. (All cells that have the same relative column index)\n */\nexport function getCellsAtColumnHandle(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeColumnIndex: RelativeCellIndices[\"col\"],\n) {\n const occupancyGrid = getTableCellOccupancyGrid(block);\n\n if (\n relativeColumnIndex < 0 ||\n relativeColumnIndex >= occupancyGrid[0].length\n ) {\n return [];\n }\n\n // First need to resolve the relative column index to an absolute column index\n let absoluteCol = 0;\n\n // Now that we've already resolved the absolute row position, we can jump through the occupied cells ${relativeCellIndices.col} times to find the absolute column position\n for (let i = 0; i < relativeColumnIndex; i++) {\n const cell = occupancyGrid[0]?.[absoluteCol];\n\n if (!cell) {\n return [];\n }\n\n // Skip the cells that the colspan takes up\n absoluteCol += cell.colspan;\n }\n\n // Then for each row, get the cell at the absolute column index as a relative cell index\n const cells = new Array(occupancyGrid.length)\n .fill(false)\n .map((_v, row) => {\n return getRelativeTableCells(\n { row, col: absoluteCol },\n block,\n occupancyGrid,\n );\n })\n .filter(\n (a): a is RelativeCellIndices & { cell: TableCell<any, any> } =>\n a !== undefined,\n );\n\n // Filter out duplicates based on row and col properties\n return cells.filter((cell, index) => {\n return (\n cells.findIndex((c) => c.row === cell.row && c.col === cell.col) === index\n );\n });\n}\n\n/**\n * This moves a column from one index to another.\n *\n * @note This is a destructive operation, it will modify the provided {@link OccupancyGrid} in place.\n */\nexport function moveColumn(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n fromColIndex: RelativeCellIndices[\"col\"],\n toColIndex: RelativeCellIndices[\"col\"],\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n // To move cells in a column, we need to layout the whole table\n // and then move the cells accordingly.\n const { col: absoluteSourceCol } = getAbsoluteTableCells(\n {\n row: 0,\n col: fromColIndex,\n },\n block,\n occupancyGrid,\n );\n const { col: absoluteTargetCol } = getAbsoluteTableCells(\n {\n row: 0,\n col: toColIndex,\n },\n block,\n occupancyGrid,\n );\n\n /**\n * Currently, this function assumes that the caller has already checked that the source and target columns are valid.\n * Such as by using {@link canColumnBeDraggedInto}. In the future, we may want to have the move logic be smarter\n * and handle invalid column indices in some way.\n */\n occupancyGrid.forEach((row) => {\n // Move the cell to the target column\n const [sourceCell] = row.splice(absoluteSourceCol, 1);\n row.splice(absoluteTargetCol, 0, sourceCell);\n });\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This moves a row from one index to another.\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function moveRow(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n fromRowIndex: RelativeCellIndices[\"row\"],\n toRowIndex: RelativeCellIndices[\"row\"],\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n // To move cells in a column, we need to layout the whole table\n // and then move the cells accordingly.\n const { row: absoluteSourceRow } = getAbsoluteTableCells(\n {\n row: fromRowIndex,\n col: 0,\n },\n block,\n occupancyGrid,\n );\n const { row: absoluteTargetRow } = getAbsoluteTableCells(\n {\n row: toRowIndex,\n col: 0,\n },\n block,\n occupancyGrid,\n );\n\n /**\n * Currently, this function assumes that the caller has already checked that the source and target rows are valid.\n * Such as by using {@link canRowBeDraggedInto}. In the future, we may want to have the move logic be smarter\n * and handle invalid row indices in some way.\n */\n const [sourceRow] = occupancyGrid.splice(absoluteSourceRow, 1);\n occupancyGrid.splice(absoluteTargetRow, 0, sourceRow);\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This will check if a cell is empty.\n *\n * @returns True if the cell is empty, false otherwise.\n */\nfunction isCellEmpty(\n cell:\n | PartialTableContent<any, any>[\"rows\"][number][\"cells\"][number]\n | undefined,\n): boolean {\n if (!cell) {\n return true;\n }\n if (isPartialTableCell(cell)) {\n return isCellEmpty(cell.content);\n } else if (typeof cell === \"string\") {\n return cell.length === 0;\n } else if (Array.isArray(cell)) {\n return cell.every((c) =>\n typeof c === \"string\"\n ? c.length === 0\n : isStyledTextInlineContent(c)\n ? c.text.length === 0\n : isPartialLinkInlineContent(c)\n ? typeof c.content === \"string\"\n ? c.content.length === 0\n : c.content.every((s) => s.text.length === 0)\n : false,\n );\n } else {\n return false;\n }\n}\n\n/**\n * This will remove empty rows or columns from the table.\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function cropEmptyRowsOrColumns(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n removeEmpty: \"columns\" | \"rows\",\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n if (removeEmpty === \"columns\") {\n // strips empty columns on the right\n let emptyColsOnRight = 0;\n for (\n let cellIndex = occupancyGrid[0].length - 1;\n cellIndex >= 0;\n cellIndex--\n ) {\n const isEmpty = occupancyGrid.every(\n (row) =>\n isCellEmpty(row[cellIndex].cell) && row[cellIndex].colspan === 1,\n );\n if (!isEmpty) {\n break;\n }\n\n emptyColsOnRight++;\n }\n\n for (let i = occupancyGrid.length - 1; i >= 0; i--) {\n // We maintain at least one cell, even if all the cells are empty\n const cellsToRemove = Math.max(\n occupancyGrid[i].length - emptyColsOnRight,\n 1,\n );\n occupancyGrid[i] = occupancyGrid[i].slice(0, cellsToRemove);\n }\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n }\n\n // strips empty rows at the bottom\n let emptyRowsOnBottom = 0;\n for (let rowIndex = occupancyGrid.length - 1; rowIndex >= 0; rowIndex--) {\n const isEmpty = occupancyGrid[rowIndex].every(\n (cell) => isCellEmpty(cell.cell) && cell.rowspan === 1,\n );\n if (!isEmpty) {\n break;\n }\n\n emptyRowsOnBottom++;\n }\n\n // We maintain at least one row, even if all the rows are empty\n const rowsToRemove = Math.min(emptyRowsOnBottom, occupancyGrid.length - 1);\n\n occupancyGrid.splice(occupancyGrid.length - rowsToRemove, rowsToRemove);\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This will add a specified number of rows or columns to the table (filling with empty cells).\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function addRowsOrColumns(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n addType: \"columns\" | \"rows\",\n /**\n * The number of rows or columns to add.\n *\n * @note if negative, it will remove rows or columns.\n */\n numToAdd: number,\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n const { width, height } = getDimensionsOfTable(block);\n\n if (addType === \"columns\") {\n // Add empty columns to the right\n occupancyGrid.forEach((row, rowIndex) => {\n if (numToAdd >= 0) {\n for (let i = 0; i < numToAdd; i++) {\n row.push({\n row: rowIndex,\n col: Math.max(...row.map((r) => r.col)) + 1,\n rowspan: 1,\n colspan: 1,\n cell: mapTableCell(\"\"),\n });\n }\n } else {\n // Remove columns on the right\n row.splice(width + numToAdd, -1 * numToAdd);\n }\n });\n } else {\n if (numToAdd > 0) {\n // Add empty rows to the bottom\n for (let i = 0; i < numToAdd; i++) {\n const newRow = new Array(width).fill(null).map((_, colIndex) => ({\n row: height + i,\n col: colIndex,\n rowspan: 1,\n colspan: 1,\n cell: mapTableCell(\"\"),\n }));\n occupancyGrid.push(newRow);\n }\n } else if (numToAdd < 0) {\n // Remove rows at the bottom\n occupancyGrid.splice(height + numToAdd, -1 * numToAdd);\n }\n }\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * Checks if a row can be safely dropped at the target row index without splitting merged cells.\n */\nexport function canRowBeDraggedInto(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n draggingIndex: RelativeCellIndices[\"row\"],\n targetRowIndex: RelativeCellIndices[\"row\"],\n) {\n // Check cells at the target row\n const targetCells = getCellsAtRowHandle(block, targetRowIndex);\n\n // If no cells have rowspans > 1, dragging is always allowed\n const hasMergedCells = targetCells.some((cell) => getRowspan(cell.cell) > 1);\n if (!hasMergedCells) {\n return true;\n }\n\n let endRowIndex = targetRowIndex;\n let startRowIndex = targetRowIndex;\n targetCells.forEach((cell) => {\n const rowspan = getRowspan(cell.cell);\n endRowIndex = Math.max(endRowIndex, cell.row + rowspan - 1);\n startRowIndex = Math.min(startRowIndex, cell.row);\n });\n\n // Check the direction of the drag\n const isDraggingDown = draggingIndex < targetRowIndex;\n\n // Allow dragging only at the start/end of merged cells\n // Otherwise, the target row was within a merged cell which we don't allow\n return isDraggingDown\n ? targetRowIndex === endRowIndex\n : targetRowIndex === startRowIndex;\n}\n\n/**\n * Checks if a column can be safely dropped at the target column index without splitting merged cells.\n */\nexport function canColumnBeDraggedInto(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n draggingIndex: RelativeCellIndices[\"col\"],\n targetColumnIndex: RelativeCellIndices[\"col\"],\n) {\n // Check cells at the target column\n const targetCells = getCellsAtColumnHandle(block, targetColumnIndex);\n\n // If no cells have colspans > 1, dragging is always allowed\n const hasMergedCells = targetCells.some((cell) => getColspan(cell.cell) > 1);\n if (!hasMergedCells) {\n return true;\n }\n\n let endColumnIndex = targetColumnIndex;\n let startColumnIndex = targetColumnIndex;\n targetCells.forEach((cell) => {\n const colspan = getColspan(cell.cell);\n endColumnIndex = Math.max(endColumnIndex, cell.col + colspan - 1);\n startColumnIndex = Math.min(startColumnIndex, cell.col);\n });\n\n // Check the direction of the drag\n const isDraggingRight = draggingIndex < targetColumnIndex;\n\n // Allow dragging only at the start/end of merged cells\n // Otherwise, the target column was within a merged cell which we don't allow\n return isDraggingRight\n ? targetColumnIndex === endColumnIndex\n : targetColumnIndex === startColumnIndex;\n}\n\n/**\n * Checks if two cells are in the same column.\n *\n * @returns True if the cells are in the same column, false otherwise.\n */\nexport function areInSameColumn(\n from: RelativeCellIndices,\n to: RelativeCellIndices,\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n) {\n // Table indices are relative to the table, so we need to resolve the absolute cell indices\n const anchorAbsoluteCellIndices = getAbsoluteTableCells(from, block);\n\n // Table indices are relative to the table, so we need to resolve the absolute cell indices\n const headAbsoluteCellIndices = getAbsoluteTableCells(to, block);\n\n // Compare the column indices to determine the merge direction\n return anchorAbsoluteCellIndices.col === headAbsoluteCellIndices.col;\n}\n","import { Attrs, Fragment, Mark, Node, Schema } from \"@tiptap/pm/model\";\n\nimport UniqueID from \"../../extensions/UniqueID/UniqueID.js\";\nimport type {\n InlineContentSchema,\n PartialCustomInlineContentFromConfig,\n PartialInlineContent,\n PartialLink,\n PartialTableContent,\n StyleSchema,\n StyledText,\n} from \"../../schema\";\n\nimport type { PartialBlock } from \"../../blocks/defaultBlocks\";\nimport {\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types.js\";\nimport { getColspan, isPartialTableCell } from \"../../util/table.js\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport { getAbsoluteTableCells } from \"../blockManipulation/tables/tables.js\";\nimport { getStyleSchema } from \"../pmUtil.js\";\n\n/**\n * Convert a StyledText inline element to a\n * prosemirror text node with the appropriate marks\n */\nfunction styledTextToNodes<T extends StyleSchema>(\n styledText: StyledText<T>,\n schema: Schema,\n styleSchema: T,\n blockType?: string,\n): Node[] {\n const marks: Mark[] = [];\n\n for (const [style, value] of Object.entries(styledText.styles || {})) {\n const config = styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n\n if (config.propSchema === \"boolean\") {\n if (value) {\n marks.push(schema.mark(style));\n }\n } else if (config.propSchema === \"string\") {\n if (value) {\n marks.push(schema.mark(style, { stringValue: value }));\n }\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n\n const parseHardBreaks = !blockType || !schema.nodes[blockType].spec.code;\n\n if (!parseHardBreaks) {\n return styledText.text.length > 0\n ? [schema.text(styledText.text, marks)]\n : [];\n }\n\n return (\n styledText.text\n // Splits text & line breaks.\n .split(/(\\n)/g)\n // If the content ends with a line break, an empty string is added to the\n // end, which this removes.\n .filter((text) => text.length > 0)\n // Converts text & line breaks to nodes.\n .map((text) => {\n if (text === \"\\n\") {\n return schema.nodes[\"hardBreak\"].createChecked();\n } else {\n return schema.text(text, marks);\n }\n })\n );\n}\n\n/**\n * Converts a Link inline content element to\n * prosemirror text nodes with the appropriate marks\n */\nfunction linkToNodes(\n link: PartialLink<StyleSchema>,\n schema: Schema,\n styleSchema: StyleSchema,\n): Node[] {\n const linkMark = schema.marks.link.create({\n href: link.href,\n });\n\n return styledTextArrayToNodes(link.content, schema, styleSchema).map(\n (node) => {\n if (node.type.name === \"text\") {\n return node.mark([...node.marks, linkMark]);\n }\n\n if (node.type.name === \"hardBreak\") {\n return node;\n }\n throw new Error(\"unexpected node type\");\n },\n );\n}\n\n/**\n * Converts an array of StyledText inline content elements to\n * prosemirror text nodes with the appropriate marks\n */\nfunction styledTextArrayToNodes<S extends StyleSchema>(\n content: string | StyledText<S>[],\n schema: Schema,\n styleSchema: S,\n blockType?: string,\n): Node[] {\n const nodes: Node[] = [];\n\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextToNodes(\n { type: \"text\", text: content, styles: {} },\n schema,\n styleSchema,\n blockType,\n ),\n );\n return nodes;\n }\n\n for (const styledText of content) {\n nodes.push(\n ...styledTextToNodes(styledText, schema, styleSchema, blockType),\n );\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function inlineContentToNodes<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockContent: PartialInlineContent<I, S>,\n schema: Schema,\n blockType?: string,\n styleSchema: S = getStyleSchema(schema),\n): Node[] {\n const nodes: Node[] = [];\n\n for (const content of blockContent) {\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextArrayToNodes(content, schema, styleSchema, blockType),\n );\n } else if (isPartialLinkInlineContent(content)) {\n nodes.push(...linkToNodes(content, schema, styleSchema));\n } else if (isStyledTextInlineContent(content)) {\n nodes.push(\n ...styledTextArrayToNodes([content], schema, styleSchema, blockType),\n );\n } else {\n nodes.push(\n blockOrInlineContentToContentNode(content, schema, styleSchema),\n );\n }\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function tableContentToNodes<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tableContent: PartialTableContent<I, S>,\n schema: Schema,\n styleSchema: StyleSchema = getStyleSchema(schema),\n): Node[] {\n const rowNodes: Node[] = [];\n // Header rows and columns are used to determine the type of the cell\n // If headerRows is 1, then the first row is a header row\n const headerRows = new Array(tableContent.headerRows ?? 0).fill(true);\n // If headerCols is 1, then the first column is a header column\n const headerCols = new Array(tableContent.headerCols ?? 0).fill(true);\n\n const columnWidths: (number | undefined)[] = tableContent.columnWidths ?? [];\n\n for (let rowIndex = 0; rowIndex < tableContent.rows.length; rowIndex++) {\n const row = tableContent.rows[rowIndex];\n const columnNodes: Node[] = [];\n const isHeaderRow = headerRows[rowIndex];\n for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex++) {\n const cell = row.cells[cellIndex];\n const isHeaderCol = headerCols[cellIndex];\n /**\n * The attributes of the cell to apply to the node\n */\n const attrs: Attrs | undefined = undefined;\n /**\n * The content of the cell to apply to the node\n */\n let content: Fragment | Node | readonly Node[] | null = null;\n\n // Colwidths are absolutely referenced to the table, so we need to resolve the relative cell index to the absolute cell index\n const absoluteCellIndex = getAbsoluteTableCells(\n {\n row: rowIndex,\n col: cellIndex,\n },\n { type: \"table\", content: tableContent } as any,\n );\n\n // Assume the column width is the width of the cell at the absolute cell index\n let colwidth: (number | undefined)[] | null = columnWidths[\n absoluteCellIndex.col\n ]\n ? [columnWidths[absoluteCellIndex.col]]\n : null;\n\n if (!cell) {\n // No-op\n } else if (typeof cell === \"string\") {\n content = schema.text(cell);\n } else if (isPartialTableCell(cell)) {\n if (cell.content) {\n content = inlineContentToNodes(\n cell.content,\n schema,\n \"tableParagraph\",\n styleSchema,\n );\n }\n const colspan = getColspan(cell);\n\n if (colspan > 1) {\n // If the cell has a > 1 colspan, we need to get the column width for each cell in the span\n colwidth = new Array(colspan).fill(false).map((_, i) => {\n // Starting from the absolute column index, get the column width for each cell in the span\n return columnWidths[absoluteCellIndex.col + i] ?? undefined;\n });\n }\n } else {\n content = inlineContentToNodes(\n cell,\n schema,\n \"tableParagraph\",\n styleSchema,\n );\n }\n\n const cellNode = schema.nodes[\n isHeaderCol || isHeaderRow ? \"tableHeader\" : \"tableCell\"\n ].createChecked(\n {\n ...(isPartialTableCell(cell) ? cell.props : {}),\n colwidth,\n },\n schema.nodes[\"tableParagraph\"].createChecked(attrs, content),\n );\n columnNodes.push(cellNode);\n }\n\n const rowNode = schema.nodes[\"tableRow\"].createChecked({}, columnNodes);\n rowNodes.push(rowNode);\n }\n return rowNodes;\n}\n\nfunction blockOrInlineContentToContentNode(\n block:\n | PartialBlock<any, any, any>\n | PartialCustomInlineContentFromConfig<any, any>,\n schema: Schema,\n styleSchema: StyleSchema,\n) {\n let contentNode: Node;\n let type = block.type;\n\n // TODO: needed? came from previous code\n if (type === undefined) {\n type = \"paragraph\";\n }\n\n if (!schema.nodes[type]) {\n throw new Error(`node type ${type} not found in schema`);\n }\n\n if (!block.content) {\n contentNode = schema.nodes[type].createChecked(block.props);\n } else if (typeof block.content === \"string\") {\n const nodes = inlineContentToNodes(\n [block.content],\n schema,\n type,\n styleSchema,\n );\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else if (Array.isArray(block.content)) {\n const nodes = inlineContentToNodes(\n block.content,\n schema,\n type,\n styleSchema,\n );\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else if (block.content.type === \"tableContent\") {\n const nodes = tableContentToNodes(block.content, schema, styleSchema);\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n return contentNode;\n}\n\n/**\n * Converts a BlockNote block to a Prosemirror node.\n */\nexport function blockToNode(\n block: PartialBlock<any, any, any>,\n schema: Schema,\n styleSchema: StyleSchema = getStyleSchema(schema),\n) {\n let id = block.id;\n\n if (id === undefined) {\n id = UniqueID.options.generateID();\n }\n\n const children: Node[] = [];\n\n if (block.children) {\n for (const child of block.children) {\n children.push(blockToNode(child, schema, styleSchema));\n }\n }\n\n const isBlockContent =\n !block.type || // can happen if block.type is not defined (this should create the default node)\n schema.nodes[block.type].isInGroup(\"blockContent\");\n\n if (isBlockContent) {\n // Blocks with a type that matches \"blockContent\" group always need to be wrapped in a blockContainer\n\n const contentNode = blockOrInlineContentToContentNode(\n block,\n schema,\n styleSchema,\n );\n\n const groupNode =\n children.length > 0\n ? schema.nodes[\"blockGroup\"].createChecked({}, children)\n : undefined;\n\n return schema.nodes[\"blockContainer\"].createChecked(\n {\n id: id,\n ...block.props,\n },\n groupNode ? [contentNode, groupNode] : contentNode,\n );\n } else if (schema.nodes[block.type].isInGroup(\"bnBlock\")) {\n // this is a bnBlock node like Column or ColumnList that directly translates to a prosemirror node\n return schema.nodes[block.type].createChecked(\n {\n id: id,\n ...block.props,\n },\n children,\n );\n } else {\n throw new Error(\n `block type ${block.type} doesn't match blockContent or bnBlock group`,\n );\n }\n}\n","import {\n combineTransactionSteps,\n findChildrenInRange,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport type { Node } from \"prosemirror-model\";\nimport type { Transaction } from \"prosemirror-state\";\nimport {\n Block,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n DefaultStyleSchema,\n} from \"../blocks/defaultBlocks.js\";\nimport type { BlockSchema } from \"../schema/index.js\";\nimport type { InlineContentSchema } from \"../schema/inlineContent/types.js\";\nimport type { StyleSchema } from \"../schema/styles/types.js\";\nimport { nodeToBlock } from \"./nodeConversions/nodeToBlock.js\";\nimport { getPmSchema } from \"./pmUtil.js\";\n\n/**\n * Get a TipTap node by id\n */\nexport function getNodeById(\n id: string,\n doc: Node,\n): { node: Node; posBeforeNode: number } | undefined {\n let targetNode: Node | undefined = undefined;\n let posBeforeNode: number | undefined = undefined;\n\n doc.firstChild!.descendants((node, pos) => {\n // Skips traversing nodes after node with target ID has been found.\n if (targetNode) {\n return false;\n }\n\n // Keeps traversing nodes if block with target ID has not been found.\n if (!isNodeBlock(node) || node.attrs.id !== id) {\n return true;\n }\n\n targetNode = node;\n posBeforeNode = pos + 1;\n\n return false;\n });\n\n if (targetNode === undefined || posBeforeNode === undefined) {\n return undefined;\n }\n\n return {\n node: targetNode,\n posBeforeNode: posBeforeNode,\n };\n}\n\nexport function isNodeBlock(node: Node): boolean {\n return node.type.isInGroup(\"bnBlock\");\n}\n\n/**\n * This attributes the changes to a specific source.\n */\nexport type BlockChangeSource =\n | {\n /**\n * When an event is triggered by the local user, the source is \"local\".\n * This is the default source.\n */\n type: \"local\";\n }\n | {\n /**\n * When an event is triggered by a paste operation, the source is \"paste\".\n */\n type: \"paste\";\n }\n | {\n /**\n * When an event is triggered by a drop operation, the source is \"drop\".\n */\n type: \"drop\";\n }\n | {\n /**\n * When an event is triggered by an undo or redo operation, the source is \"undo\" or \"redo\".\n * @note Y.js undo/redo are not differentiated.\n */\n type: \"undo\" | \"redo\" | \"undo-redo\";\n }\n | {\n /**\n * When an event is triggered by a remote user, the source is \"remote\".\n */\n type: \"yjs-remote\";\n };\n\nexport type BlocksChanged<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema,\n> = Array<\n {\n /**\n * The affected block.\n */\n block: Block<BSchema, ISchema, SSchema>;\n /**\n * The source of the change.\n */\n source: BlockChangeSource;\n } & (\n | {\n type: \"insert\" | \"delete\";\n /**\n * Insert and delete changes don't have a previous block.\n */\n prevBlock: undefined;\n }\n | {\n type: \"update\";\n /**\n * The block before the update.\n */\n prevBlock: Block<BSchema, ISchema, SSchema>;\n }\n )\n>;\n\n/**\n * Compares two blocks, ignoring their children.\n * Returns true if the blocks are different (excluding children).\n */\nfunction areBlocksDifferentExcludingChildren<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema,\n>(\n block1: Block<BSchema, ISchema, SSchema>,\n block2: Block<BSchema, ISchema, SSchema>,\n): boolean {\n // TODO use an actual diff algorithm\n // Compare all properties except children\n return (\n block1.id !== block2.id ||\n block1.type !== block2.type ||\n JSON.stringify(block1.props) !== JSON.stringify(block2.props) ||\n JSON.stringify(block1.content) !== JSON.stringify(block2.content)\n );\n}\n\n/**\n * Get the blocks that were changed by a transaction.\n * @param transaction The transaction to get the changes from.\n * @param editor The editor to get the changes from.\n * @returns The blocks that were changed by the transaction.\n */\nexport function getBlocksChangedByTransaction<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema,\n>(\n transaction: Transaction,\n appendedTransactions: Transaction[] = [],\n): BlocksChanged<BSchema, ISchema, SSchema> {\n let source: BlockChangeSource = { type: \"local\" };\n\n if (transaction.getMeta(\"paste\")) {\n source = { type: \"paste\" };\n } else if (transaction.getMeta(\"uiEvent\") === \"drop\") {\n source = { type: \"drop\" };\n } else if (transaction.getMeta(\"history$\")) {\n source = {\n type: transaction.getMeta(\"history$\").redo ? \"redo\" : \"undo\",\n };\n } else if (transaction.getMeta(\"y-sync$\")) {\n if (transaction.getMeta(\"y-sync$\").isUndoRedoOperation) {\n source = {\n type: \"undo-redo\",\n };\n } else {\n source = {\n type: \"yjs-remote\",\n };\n }\n }\n\n // Get affected blocks before and after the change\n const pmSchema = getPmSchema(transaction);\n const combinedTransaction = combineTransactionSteps(transaction.before, [\n transaction,\n ...appendedTransactions,\n ]);\n\n const changedRanges = getChangedRanges(combinedTransaction);\n const prevAffectedBlocks = changedRanges\n .flatMap((range) => {\n return findChildrenInRange(\n combinedTransaction.before,\n range.oldRange,\n isNodeBlock,\n );\n })\n .map(({ node }) => nodeToBlock(node, pmSchema));\n\n const nextAffectedBlocks = changedRanges\n .flatMap((range) => {\n return findChildrenInRange(\n combinedTransaction.doc,\n range.newRange,\n isNodeBlock,\n );\n })\n .map(({ node }) => nodeToBlock(node, pmSchema));\n\n const nextBlocks = new Map(\n nextAffectedBlocks.map((block) => {\n return [block.id, block];\n }),\n );\n const prevBlocks = new Map(\n prevAffectedBlocks.map((block) => {\n return [block.id, block];\n }),\n );\n\n const changes: BlocksChanged<BSchema, ISchema, SSchema> = [];\n\n // Inserted blocks are blocks that were not in the previous state and are in the next state\n for (const [id, block] of nextBlocks) {\n if (!prevBlocks.has(id)) {\n changes.push({\n type: \"insert\",\n block,\n source,\n prevBlock: undefined,\n });\n }\n }\n\n // Deleted blocks are blocks that were in the previous state but not in the next state\n for (const [id, block] of prevBlocks) {\n if (!nextBlocks.has(id)) {\n changes.push({\n type: \"delete\",\n block,\n source,\n prevBlock: undefined,\n });\n }\n }\n\n // Updated blocks are blocks that were in the previous state and are in the next state\n for (const [id, block] of nextBlocks) {\n if (prevBlocks.has(id)) {\n const prevBlock = prevBlocks.get(id)!;\n\n // Only include the update if the block itself changed (excluding children)\n if (areBlocksDifferentExcludingChildren(prevBlock, block)) {\n changes.push({\n type: \"update\",\n block,\n prevBlock,\n source,\n });\n }\n }\n }\n\n return changes;\n}\n","import { Fragment, Slice } from \"prosemirror-model\";\nimport type { Transaction } from \"prosemirror-state\";\nimport { ReplaceStep } from \"prosemirror-transform\";\nimport { Block, PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema/index.js\";\nimport { blockToNode } from \"../../../nodeConversions/blockToNode.js\";\nimport { nodeToBlock } from \"../../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../../nodeUtil.js\";\nimport { getPmSchema } from \"../../../pmUtil.js\";\n\nexport function insertBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tr: Transaction,\n blocksToInsert: PartialBlock<BSchema, I, S>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" = \"before\",\n): Block<BSchema, I, S>[] {\n const id =\n typeof referenceBlock === \"string\" ? referenceBlock : referenceBlock.id;\n const pmSchema = getPmSchema(tr);\n const nodesToInsert = blocksToInsert.map((block) =>\n blockToNode(block, pmSchema),\n );\n\n const posInfo = getNodeById(id, tr.doc);\n if (!posInfo) {\n throw new Error(`Block with ID ${id} not found`);\n }\n\n let pos = posInfo.posBeforeNode;\n if (placement === \"after\") {\n pos += posInfo.node.nodeSize;\n }\n\n tr.step(\n new ReplaceStep(pos, pos, new Slice(Fragment.from(nodesToInsert), 0, 0)),\n );\n\n // Now that the `PartialBlock`s have been converted to nodes, we can\n // re-convert them into full `Block`s.\n const insertedBlocks = nodesToInsert.map((node) =>\n nodeToBlock(node, pmSchema),\n );\n\n return insertedBlocks;\n}\n","import type { Node } from \"prosemirror-model\";\nimport type { Transaction } from \"prosemirror-state\";\nimport type { Block, PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport type {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema/index.js\";\nimport { blockToNode } from \"../../../nodeConversions/blockToNode.js\";\nimport { nodeToBlock } from \"../../../nodeConversions/nodeToBlock.js\";\nimport { getPmSchema } from \"../../../pmUtil.js\";\n\nexport function removeAndInsertBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tr: Transaction,\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema, I, S>[],\n): {\n insertedBlocks: Block<BSchema, I, S>[];\n removedBlocks: Block<BSchema, I, S>[];\n} {\n const pmSchema = getPmSchema(tr);\n // Converts the `PartialBlock`s to ProseMirror nodes to insert them into the\n // document.\n const nodesToInsert: Node[] = blocksToInsert.map((block) =>\n blockToNode(block, pmSchema),\n );\n\n const idsOfBlocksToRemove = new Set<string>(\n blocksToRemove.map((block) =>\n typeof block === \"string\" ? block : block.id,\n ),\n );\n const removedBlocks: Block<BSchema, I, S>[] = [];\n\n const idOfFirstBlock =\n typeof blocksToRemove[0] === \"string\"\n ? blocksToRemove[0]\n : blocksToRemove[0].id;\n let removedSize = 0;\n\n tr.doc.descendants((node, pos) => {\n // Skips traversing nodes after all target blocks have been removed.\n if (idsOfBlocksToRemove.size === 0) {\n return false;\n }\n\n // Keeps traversing nodes if block with target ID has not been found.\n if (\n !node.type.isInGroup(\"bnBlock\") ||\n !idsOfBlocksToRemove.has(node.attrs.id)\n ) {\n return true;\n }\n\n // Saves the block that is being deleted.\n removedBlocks.push(nodeToBlock(node, pmSchema));\n idsOfBlocksToRemove.delete(node.attrs.id);\n\n if (blocksToInsert.length > 0 && node.attrs.id === idOfFirstBlock) {\n const oldDocSize = tr.doc.nodeSize;\n tr.insert(pos, nodesToInsert);\n const newDocSize = tr.doc.nodeSize;\n\n removedSize += oldDocSize - newDocSize;\n }\n\n const oldDocSize = tr.doc.nodeSize;\n // Checks if the block is the only child of its parent. In this case, we\n // need to delete the parent `blockGroup` node instead of just the\n // `blockContainer`.\n const $pos = tr.doc.resolve(pos - removedSize);\n if (\n $pos.node().type.name === \"blockGroup\" &&\n $pos.node($pos.depth - 1).type.name !== \"doc\" &&\n $pos.node().childCount === 1\n ) {\n tr.delete($pos.before(), $pos.after());\n } else {\n tr.delete(pos - removedSize, pos - removedSize + node.nodeSize);\n }\n const newDocSize = tr.doc.nodeSize;\n removedSize += oldDocSize - newDocSize;\n\n return false;\n });\n\n // Throws an error if now all blocks could be found.\n if (idsOfBlocksToRemove.size > 0) {\n const notFoundIds = [...idsOfBlocksToRemove].join(\"\\n\");\n\n throw Error(\n \"Blocks with the following IDs could not be found in the editor: \" +\n notFoundIds,\n );\n }\n\n // Converts the nodes created from `blocksToInsert` into full `Block`s.\n const insertedBlocks = nodesToInsert.map((node) =>\n nodeToBlock(node, pmSchema),\n );\n\n return { insertedBlocks, removedBlocks };\n}","import {\n Fragment,\n type NodeType,\n type Node as PMNode,\n Slice,\n} from \"prosemirror-model\";\nimport type { Transaction } from \"prosemirror-state\";\n\nimport { ReplaceStep, Transform } from \"prosemirror-transform\";\nimport type { Block, PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport type {\n BlockIdentifier,\n BlockSchema,\n} from \"../../../../schema/blocks/types.js\";\nimport type { InlineContentSchema } from \"../../../../schema/inlineContent/types.js\";\nimport type { StyleSchema } from \"../../../../schema/styles/types.js\";\nimport { UnreachableCaseError } from \"../../../../util/typescript.js\";\nimport {\n type BlockInfo,\n getBlockInfoFromResolvedPos,\n} from \"../../../getBlockInfoFromPos.js\";\nimport {\n blockToNode,\n inlineContentToNodes,\n tableContentToNodes,\n} from \"../../../nodeConversions/blockToNode.js\";\nimport { nodeToBlock } from \"../../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../../nodeUtil.js\";\nimport { getPmSchema } from \"../../../pmUtil.js\";\n\n// for compatibility with tiptap. TODO: remove as we want to remove dependency on tiptap command interface\nexport const updateBlockCommand = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n posBeforeBlock: number,\n block: PartialBlock<BSchema, I, S>,\n) => {\n return ({\n tr,\n dispatch,\n }: {\n tr: Transaction;\n dispatch?: () => void;\n }): boolean => {\n if (dispatch) {\n updateBlockTr(tr, posBeforeBlock, block);\n }\n return true;\n };\n};\n\nexport function updateBlockTr<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tr: Transform,\n posBeforeBlock: number,\n block: PartialBlock<BSchema, I, S>,\n replaceFromPos?: number,\n replaceToPos?: number,\n) {\n const blockInfo = getBlockInfoFromResolvedPos(tr.doc.resolve(posBeforeBlock));\n\n const pmSchema = getPmSchema(tr);\n\n if (\n replaceFromPos !== undefined &&\n replaceToPos !== undefined &&\n replaceFromPos > replaceToPos\n ) {\n throw new Error(\"Invalid replaceFromPos or replaceToPos\");\n }\n\n // Adds blockGroup node with child blocks if necessary.\n\n const oldNodeType = pmSchema.nodes[blockInfo.blockNoteType];\n const newNodeType = pmSchema.nodes[block.type || blockInfo.blockNoteType];\n const newBnBlockNodeType = newNodeType.isInGroup(\"bnBlock\")\n ? newNodeType\n : pmSchema.nodes[\"blockContainer\"];\n\n if (blockInfo.isBlockContainer && newNodeType.isInGroup(\"blockContent\")) {\n const replaceFromOffset =\n replaceFromPos !== undefined &&\n replaceFromPos > blockInfo.blockContent.beforePos &&\n replaceFromPos < blockInfo.blockContent.afterPos\n ? replaceFromPos - blockInfo.blockContent.beforePos - 1\n : undefined;\n\n const replaceToOffset =\n replaceToPos !== undefined &&\n replaceToPos > blockInfo.blockContent.beforePos &&\n replaceToPos < blockInfo.blockContent.afterPos\n ? replaceToPos - blockInfo.blockContent.beforePos - 1\n : undefined;\n\n updateChildren(block, tr, blockInfo);\n // The code below determines the new content of the block.\n // or \"keep\" to keep as-is\n updateBlockContentNode(\n block,\n tr,\n oldNodeType,\n newNodeType,\n blockInfo,\n replaceFromOffset,\n replaceToOffset,\n );\n } else if (!blockInfo.isBlockContainer && newNodeType.isInGroup(\"bnBlock\")) {\n updateChildren(block, tr, blockInfo);\n // old node was a bnBlock type (like column or columnList) and new block as well\n // No op, we just update the bnBlock below (at end of function) and have already updated the children\n } else {\n // switching from blockContainer to non-blockContainer or v.v.\n // currently breaking for column slash menu items converting empty block\n // to column.\n\n // currently, we calculate the new node and replace the entire node with the desired new node.\n // for this, we do a nodeToBlock on the existing block to get the children.\n // it would be cleaner to use a ReplaceAroundStep, but this is a bit simpler and it's quite an edge case\n const existingBlock = nodeToBlock(blockInfo.bnBlock.node, pmSchema);\n tr.replaceWith(\n blockInfo.bnBlock.beforePos,\n blockInfo.bnBlock.afterPos,\n blockToNode(\n {\n children: existingBlock.children, // if no children are passed in, use existing children\n ...block,\n },\n pmSchema,\n ),\n );\n\n return;\n }\n\n // Adds all provided props as attributes to the parent blockContainer node too, and also preserves existing\n // attributes.\n tr.setNodeMarkup(blockInfo.bnBlock.beforePos, newBnBlockNodeType, {\n ...blockInfo.bnBlock.node.attrs,\n ...block.props,\n });\n}\n\nfunction updateBlockContentNode<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n block: PartialBlock<BSchema, I, S>,\n tr: Transform,\n oldNodeType: NodeType,\n newNodeType: NodeType,\n blockInfo: {\n childContainer?:\n | { node: PMNode; beforePos: number; afterPos: number }\n | undefined;\n blockContent: { node: PMNode; beforePos: number; afterPos: number };\n },\n replaceFromOffset?: number,\n replaceToOffset?: number,\n) {\n const pmSchema = getPmSchema(tr);\n let content: PMNode[] | \"keep\" = \"keep\";\n\n // Has there been any custom content provided?\n if (block.content) {\n if (typeof block.content === \"string\") {\n // Adds a single text node with no marks to the content.\n content = inlineContentToNodes(\n [block.content],\n pmSchema,\n newNodeType.name,\n );\n } else if (Array.isArray(block.content)) {\n // Adds a text node with the provided styles converted into marks to the content,\n // for each InlineContent object.\n content = inlineContentToNodes(block.content, pmSchema, newNodeType.name);\n } else if (block.content.type === \"tableContent\") {\n content = tableContentToNodes(block.content, pmSchema);\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n } else {\n // no custom content has been provided, use existing content IF possible\n // Since some block types contain inline content and others don't,\n // we either need to call setNodeMarkup to just update type &\n // attributes, or replaceWith to replace the whole blockContent.\n if (oldNodeType.spec.content === \"\") {\n // keep old content, because it's empty anyway and should be compatible with\n // any newContentType\n } else if (newNodeType.spec.content !== oldNodeType.spec.content) {\n // the content type changed, replace the previous content\n content = [];\n } else {\n // keep old content, because the content type is the same and should be compatible\n }\n }\n\n // Now, changes the blockContent node type and adds the provided props\n // as attributes. Also preserves all existing attributes that are\n // compatible with the new type.\n //\n // Use either setNodeMarkup or replaceWith depending on whether the\n // content is being replaced or not.\n if (content === \"keep\") {\n // use setNodeMarkup to only update the type and attributes\n tr.setNodeMarkup(blockInfo.blockContent.beforePos, newNodeType, {\n ...blockInfo.blockContent.node.attrs,\n ...block.props,\n });\n } else if (replaceFromOffset !== undefined || replaceToOffset !== undefined) {\n // first update markup of the containing node\n tr.setNodeMarkup(blockInfo.blockContent.beforePos, newNodeType, {\n ...blockInfo.blockContent.node.attrs,\n ...block.props,\n });\n\n const start =\n blockInfo.blockContent.beforePos + 1 + (replaceFromOffset ?? 0);\n const end =\n blockInfo.blockContent.beforePos +\n 1 +\n (replaceToOffset ?? blockInfo.blockContent.node.content.size);\n\n // for content like table cells (where the blockcontent has nested PM nodes),\n // we need to figure out the correct openStart and openEnd for the slice when replacing\n\n const contentDepth = tr.doc.resolve(blockInfo.blockContent.beforePos).depth;\n const startDepth = tr.doc.resolve(start).depth;\n const endDepth = tr.doc.resolve(end).depth;\n\n tr.replace(\n start,\n end,\n new Slice(\n Fragment.from(content),\n startDepth - contentDepth - 1,\n endDepth - contentDepth - 1,\n ),\n );\n } else {\n // use replaceWith to replace the content and the block itself\n // also reset the selection since replacing the block content\n // sets it to the next block.\n tr.replaceWith(\n blockInfo.blockContent.beforePos,\n blockInfo.blockContent.afterPos,\n newNodeType.createChecked(\n {\n ...blockInfo.blockContent.node.attrs,\n ...block.props,\n },\n content,\n ),\n );\n }\n}\n\nfunction updateChildren<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(block: PartialBlock<BSchema, I, S>, tr: Transform, blockInfo: BlockInfo) {\n const pmSchema = getPmSchema(tr);\n if (block.children !== undefined && block.children.length > 0) {\n const childNodes = block.children.map((child) => {\n return blockToNode(child, pmSchema);\n });\n\n // Checks if a blockGroup node already exists.\n if (blockInfo.childContainer) {\n // Replaces all child nodes in the existing blockGroup with the ones created earlier.\n\n // use a replacestep to avoid the fitting algorithm\n tr.step(\n new ReplaceStep(\n blockInfo.childContainer.beforePos + 1,\n blockInfo.childContainer.afterPos - 1,\n new Slice(Fragment.from(childNodes), 0, 0),\n ),\n );\n } else {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n // Inserts a new blockGroup containing the child nodes created earlier.\n tr.insert(\n blockInfo.blockContent.afterPos,\n pmSchema.nodes[\"blockGroup\"].createChecked({}, childNodes),\n );\n }\n }\n}\n\nexport function updateBlock<\n BSchema extends BlockSchema = any,\n I extends InlineContentSchema = any,\n S extends StyleSchema = any,\n>(\n tr: Transaction,\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema, I, S>,\n replaceFromPos?: number,\n replaceToPos?: number,\n): Block<BSchema, I, S> {\n const id =\n typeof blockToUpdate === \"string\" ? blockToUpdate : blockToUpdate.id;\n const posInfo = getNodeById(id, tr.doc);\n if (!posInfo) {\n throw new Error(`Block with ID ${id} not found`);\n }\n\n updateBlockTr(\n tr,\n posInfo.posBeforeNode,\n update,\n replaceFromPos,\n replaceToPos,\n );\n\n const blockContainerNode = tr.doc\n .resolve(posInfo.posBeforeNode + 1) // TODO: clean?\n .node();\n\n const pmSchema = getPmSchema(tr);\n return nodeToBlock(blockContainerNode, pmSchema);\n}\n","import { DOMSerializer, Fragment } from \"prosemirror-model\";\n\nimport { PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema/index.js\";\nimport { UnreachableCaseError } from \"../../../../util/typescript.js\";\nimport {\n inlineContentToNodes,\n tableContentToNodes,\n} from \"../../../nodeConversions/blockToNode.js\";\n\nfunction addAttributesAndRemoveClasses(element: HTMLElement) {\n // Removes all BlockNote specific class names.\n const className =\n Array.from(element.classList).filter(\n (className) => !className.startsWith(\"bn-\"),\n ) || [];\n\n if (className.length > 0) {\n element.className = className.join(\" \");\n } else {\n element.removeAttribute(\"class\");\n }\n}\n\nexport function serializeInlineContentExternalHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<any, I, S>,\n blockContent: PartialBlock<BSchema, I, S>[\"content\"],\n serializer: DOMSerializer,\n options?: { document?: Document },\n) {\n let nodes: any;\n\n // TODO: reuse function from nodeconversions?\n if (!blockContent) {\n throw new Error(\"blockContent is required\");\n } else if (typeof blockContent === \"string\") {\n nodes = inlineContentToNodes([blockContent], editor.pmSchema);\n } else if (Array.isArray(blockContent)) {\n nodes = inlineContentToNodes(blockContent, editor.pmSchema);\n } else if (blockContent.type === \"tableContent\") {\n nodes = tableContentToNodes(blockContent, editor.pmSchema);\n } else {\n throw new UnreachableCaseError(blockContent.type);\n }\n\n // We call the prosemirror serializer here because it handles Marks and Inline Content nodes nicely.\n // If we'd want to support custom serialization or externalHTML for Inline Content, we'd have to implement\n // a custom serializer here.\n const dom = serializer.serializeFragment(Fragment.from(nodes), options);\n\n if (dom.nodeType === 1 /* Node.ELEMENT_NODE */) {\n addAttributesAndRemoveClasses(dom as HTMLElement);\n }\n\n return dom;\n}\n\n/**\n * TODO: there's still quite some logic that handles getting and filtering properties,\n * we should make sure the `toExternalHTML` methods of default blocks actually handle this,\n * instead of the serializer.\n */\nfunction serializeBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n fragment: DocumentFragment,\n editor: BlockNoteEditor<BSchema, I, S>,\n block: PartialBlock<BSchema, I, S>,\n serializer: DOMSerializer,\n orderedListItemBlockTypes: Set<string>,\n unorderedListItemBlockTypes: Set<string>,\n options?: { document?: Document },\n) {\n const doc = options?.document ?? document;\n const BC_NODE = editor.pmSchema.nodes[\"blockContainer\"];\n\n let props = block.props;\n // set default props in case we were passed a partial block\n if (!block.props) {\n props = {};\n for (const [name, spec] of Object.entries(\n editor.schema.blockSchema[block.type as any].propSchema,\n )) {\n if (spec.default !== undefined) {\n (props as any)[name] = spec.default;\n }\n }\n }\n\n const bc = BC_NODE.spec?.toDOM?.(\n BC_NODE.create({\n id: block.id,\n ...props,\n }),\n ) as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n // the container node is just used as a workaround to get some block-level attributes.\n // we should change toExternalHTML so that this is not necessary\n const attrs = Array.from(bc.dom.attributes);\n\n const ret = editor.blockImplementations[\n block.type as any\n ].implementation.toExternalHTML({ ...block, props } as any, editor as any);\n\n const elementFragment = doc.createDocumentFragment();\n if (ret.dom.classList.contains(\"bn-block-content\")) {\n const blockContentDataAttributes = [\n ...attrs,\n ...Array.from(ret.dom.attributes),\n ].filter(\n (attr) =>\n attr.name.startsWith(\"data\") &&\n attr.name !== \"data-content-type\" &&\n attr.name !== \"data-file-block\" &&\n attr.name !== \"data-node-view-wrapper\" &&\n attr.name !== \"data-node-type\" &&\n attr.name !== \"data-id\" &&\n attr.name !== \"data-index\" &&\n attr.name !== \"data-editable\",\n );\n\n // ret.dom = ret.dom.firstChild! as any;\n for (const attr of blockContentDataAttributes) {\n (ret.dom.firstChild! as HTMLElement).setAttribute(attr.name, attr.value);\n }\n\n addAttributesAndRemoveClasses(ret.dom.firstChild! as HTMLElement);\n elementFragment.append(...Array.from(ret.dom.childNodes));\n } else {\n elementFragment.append(ret.dom);\n }\n\n if (ret.contentDOM && block.content) {\n const ic = serializeInlineContentExternalHTML(\n editor,\n block.content as any, // TODO\n serializer,\n options,\n );\n\n ret.contentDOM.appendChild(ic);\n }\n\n let listType = undefined;\n if (orderedListItemBlockTypes.has(block.type!)) {\n listType = \"OL\";\n } else if (unorderedListItemBlockTypes.has(block.type!)) {\n listType = \"UL\";\n }\n\n if (listType) {\n if (fragment.lastChild?.nodeName !== listType) {\n const list = doc.createElement(listType);\n\n if (listType === \"OL\" && props?.start && props?.start !== 1) {\n list.setAttribute(\"start\", props.start + \"\");\n }\n fragment.append(list);\n }\n const li = doc.createElement(\"li\");\n li.append(elementFragment);\n fragment.lastChild!.appendChild(li);\n } else {\n fragment.append(elementFragment);\n }\n\n if (block.children && block.children.length > 0) {\n const childFragment = doc.createDocumentFragment();\n serializeBlocksToFragment(\n childFragment,\n editor,\n block.children,\n serializer,\n orderedListItemBlockTypes,\n unorderedListItemBlockTypes,\n options,\n );\n if (\n fragment.lastChild?.nodeName === \"UL\" ||\n fragment.lastChild?.nodeName === \"OL\"\n ) {\n // add nested lists to the last list item\n while (\n childFragment.firstChild?.nodeName === \"UL\" ||\n childFragment.firstChild?.nodeName === \"OL\"\n ) {\n fragment.lastChild!.lastChild!.appendChild(childFragment.firstChild!);\n }\n }\n\n if (editor.pmSchema.nodes[block.type as any].isInGroup(\"blockContent\")) {\n // default \"blockContainer\" style blocks are flattened (no \"nested block\" support) for externalHTML, so append the child fragment to the outer fragment\n fragment.append(childFragment);\n } else {\n // for columns / column lists, do use nesting\n ret.contentDOM?.append(childFragment);\n }\n }\n}\n\nconst serializeBlocksToFragment = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n fragment: DocumentFragment,\n editor: BlockNoteEditor<BSchema, I, S>,\n blocks: PartialBlock<BSchema, I, S>[],\n serializer: DOMSerializer,\n orderedListItemBlockTypes: Set<string>,\n unorderedListItemBlockTypes: Set<string>,\n options?: { document?: Document },\n) => {\n for (const block of blocks) {\n serializeBlock(\n fragment,\n editor,\n block,\n serializer,\n orderedListItemBlockTypes,\n unorderedListItemBlockTypes,\n options,\n );\n }\n};\n\nexport const serializeBlocksExternalHTML = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n blocks: PartialBlock<BSchema, I, S>[],\n serializer: DOMSerializer,\n orderedListItemBlockTypes: Set<string>,\n unorderedListItemBlockTypes: Set<string>,\n options?: { document?: Document },\n) => {\n const doc = options?.document ?? document;\n const fragment = doc.createDocumentFragment();\n\n serializeBlocksToFragment(\n fragment,\n editor,\n blocks,\n serializer,\n orderedListItemBlockTypes,\n unorderedListItemBlockTypes,\n options,\n );\n return fragment;\n};\n","import { DOMSerializer, Schema } from \"prosemirror-model\";\n\nimport { PartialBlock } from \"../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContent,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport {\n serializeBlocksExternalHTML,\n serializeInlineContentExternalHTML,\n} from \"./util/serializeBlocksExternalHTML.js\";\n\n// Used to export BlockNote blocks and ProseMirror nodes to HTML for use outside\n// the editor. Blocks are exported using the `toExternalHTML` method in their\n// `blockSpec`, or `toInternalHTML` if `toExternalHTML` is not defined.\n//\n// The HTML created by this serializer is different to what's rendered by the\n// editor to the DOM. This also means that data is likely to be lost when\n// converting back to original blocks. The differences in the output HTML are:\n// 1. It doesn't include the `blockGroup` and `blockContainer` wrappers meaning\n// that nesting is not preserved for non-list-item blocks.\n// 2. `li` items in the output HTML are wrapped in `ul` or `ol` elements.\n// 3. While nesting for list items is preserved, other types of blocks nested\n// inside a list are un-nested and a new list is created after them.\n// 4. The HTML is wrapped in a single `div` element.\n\n// Needs to be sync because it's used in drag handler event (SideMenuPlugin)\n// Ideally, call `await initializeESMDependencies()` before calling this function\nexport const createExternalHTMLExporter = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>,\n) => {\n const serializer = DOMSerializer.fromSchema(schema);\n\n return {\n exportBlocks: (\n blocks: PartialBlock<BSchema, I, S>[],\n options: { document?: Document },\n ) => {\n const html = serializeBlocksExternalHTML(\n editor,\n blocks,\n serializer,\n new Set<string>([\"numberedListItem\"]),\n new Set<string>([\"bulletListItem\", \"checkListItem\"]),\n options,\n );\n const div = document.createElement(\"div\");\n div.append(html);\n return div.innerHTML;\n },\n\n exportInlineContent: (\n inlineContent: InlineContent<I, S>[],\n options: { document?: Document },\n ) => {\n const domFragment = serializeInlineContentExternalHTML(\n editor,\n inlineContent as any,\n serializer,\n options,\n );\n\n const parent = document.createElement(\"div\");\n parent.append(domFragment.cloneNode(true));\n\n return parent.innerHTML;\n },\n };\n};\n","import { DOMSerializer, Fragment } from \"prosemirror-model\";\n\nimport { PartialBlock } from \"../../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema/index.js\";\nimport { UnreachableCaseError } from \"../../../../util/typescript.js\";\nimport {\n inlineContentToNodes,\n tableContentToNodes,\n} from \"../../../nodeConversions/blockToNode.js\";\n\nexport function serializeInlineContentInternalHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<any, I, S>,\n blockContent: PartialBlock<BSchema, I, S>[\"content\"],\n serializer: DOMSerializer,\n blockType?: string,\n options?: { document?: Document },\n) {\n let nodes: any;\n\n // TODO: reuse function from nodeconversions?\n if (!blockContent) {\n throw new Error(\"blockContent is required\");\n } else if (typeof blockContent === \"string\") {\n nodes = inlineContentToNodes([blockContent], editor.pmSchema, blockType);\n } else if (Array.isArray(blockContent)) {\n nodes = inlineContentToNodes(blockContent, editor.pmSchema, blockType);\n } else if (blockContent.type === \"tableContent\") {\n nodes = tableContentToNodes(blockContent, editor.pmSchema);\n } else {\n throw new UnreachableCaseError(blockContent.type);\n }\n\n // We call the prosemirror serializer here because it handles Marks and Inline Content nodes nicely.\n // If we'd want to support custom serialization or externalHTML for Inline Content, we'd have to implement\n // a custom serializer here.\n const dom = serializer.serializeFragment(Fragment.from(nodes), options);\n\n return dom;\n}\n\nfunction serializeBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n block: PartialBlock<BSchema, I, S>,\n serializer: DOMSerializer,\n listIndex: number,\n options?: { document?: Document },\n) {\n const BC_NODE = editor.pmSchema.nodes[\"blockContainer\"];\n\n let props = block.props;\n // set default props in case we were passed a partial block\n if (!block.props) {\n props = {};\n for (const [name, spec] of Object.entries(\n editor.schema.blockSchema[block.type as any].propSchema,\n )) {\n if (spec.default !== undefined) {\n (props as any)[name] = spec.default;\n }\n }\n }\n\n const impl = editor.blockImplementations[block.type as any].implementation;\n const ret = impl.toInternalHTML({ ...block, props } as any, editor as any);\n\n if (block.type === \"numberedListItem\") {\n // This is a workaround to make sure there's a list index set.\n // Normally, this is set on the internal prosemirror nodes by the NumberedListIndexingPlugin,\n // but:\n // - (a) this information is not available on the Blocks passed to the serializer. (we only have access to BlockNote Blocks)\n // - (b) the NumberedListIndexingPlugin might not even have run, because we can manually call blocksToFullHTML\n // with blocks that are not part of the active document\n ret.dom.setAttribute(\"data-index\", listIndex.toString());\n }\n\n if (ret.contentDOM && block.content) {\n const ic = serializeInlineContentInternalHTML(\n editor,\n block.content as any, // TODO\n serializer,\n block.type,\n options,\n );\n ret.contentDOM.appendChild(ic);\n }\n\n const pmType = editor.pmSchema.nodes[block.type as any];\n\n if (pmType.isInGroup(\"bnBlock\")) {\n if (block.children && block.children.length > 0) {\n const fragment = serializeBlocks(\n editor,\n block.children,\n serializer,\n options,\n );\n\n ret.contentDOM?.append(fragment);\n }\n return ret.dom;\n }\n\n // wrap the block in a blockContainer\n const bc = BC_NODE.spec?.toDOM?.(\n BC_NODE.create({\n id: block.id,\n ...props,\n }),\n ) as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n bc.contentDOM?.appendChild(ret.dom);\n\n if (block.children && block.children.length > 0) {\n bc.contentDOM?.appendChild(\n serializeBlocksInternalHTML(editor, block.children, serializer, options),\n );\n }\n return bc.dom;\n}\n\nfunction serializeBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n blocks: PartialBlock<BSchema, I, S>[],\n serializer: DOMSerializer,\n options?: { document?: Document },\n) {\n const doc = options?.document ?? document;\n const fragment = doc.createDocumentFragment();\n\n let listIndex = 0;\n for (const block of blocks) {\n if (block.type === \"numberedListItem\") {\n listIndex++;\n } else {\n listIndex = 0;\n }\n const blockDOM = serializeBlock(\n editor,\n block,\n serializer,\n listIndex,\n options,\n );\n fragment.appendChild(blockDOM);\n }\n\n return fragment;\n}\n\nexport const serializeBlocksInternalHTML = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n blocks: PartialBlock<BSchema, I, S>[],\n serializer: DOMSerializer,\n options?: { document?: Document },\n) => {\n const BG_NODE = editor.pmSchema.nodes[\"blockGroup\"];\n\n const bg = BG_NODE.spec!.toDOM!(BG_NODE.create({})) as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n const fragment = serializeBlocks(editor, blocks, serializer, options);\n\n bg.contentDOM?.appendChild(fragment);\n\n return bg.dom;\n};\n","import { DOMSerializer, Schema } from \"prosemirror-model\";\nimport { PartialBlock } from \"../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { serializeBlocksInternalHTML } from \"./util/serializeBlocksInternalHTML.js\";\n// Used to serialize BlockNote blocks and ProseMirror nodes to HTML without\n// losing data. Blocks are exported using the `toInternalHTML` method in their\n// `blockSpec`.\n//\n// The HTML created by this serializer is the same as what's rendered by the\n// editor to the DOM. This means that it retains the same structure as the\n// editor, including the `blockGroup` and `blockContainer` wrappers. This also\n// means that it can be converted back to the original blocks without any data\n// loss.\nexport const createInternalHTMLSerializer = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>,\n) => {\n const serializer = DOMSerializer.fromSchema(schema);\n\n return {\n serializeBlocks: (\n blocks: PartialBlock<BSchema, I, S>[],\n options: { document?: Document },\n ) => {\n return serializeBlocksInternalHTML(editor, blocks, serializer, options)\n .outerHTML;\n },\n };\n};\n","export const parseFigureElement = (\n figureElement: HTMLElement,\n targetTag: string,\n) => {\n const targetElement = figureElement.querySelector(\n targetTag,\n ) as HTMLElement | null;\n if (!targetElement) {\n return undefined;\n }\n\n const captionElement = figureElement.querySelector(\"figcaption\");\n const caption = captionElement?.textContent ?? undefined;\n\n return { targetElement, caption };\n};\n","import type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport { BlockFromConfig, FileBlockConfig } from \"../../../../schema/index.js\";\n\nexport const createAddFileButton = (\n block: BlockFromConfig<FileBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n buttonText?: string,\n buttonIcon?: HTMLElement,\n) => {\n const addFileButton = document.createElement(\"div\");\n addFileButton.className = \"bn-add-file-button\";\n\n const addFileButtonIcon = document.createElement(\"div\");\n addFileButtonIcon.className = \"bn-add-file-button-icon\";\n if (buttonIcon) {\n addFileButtonIcon.appendChild(buttonIcon);\n } else {\n addFileButtonIcon.innerHTML =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3 8L9.00319 2H19.9978C20.5513 2 21 2.45531 21 2.9918V21.0082C21 21.556 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5501 3 20.9932V8ZM10 4V9H5V20H19V4H10Z\"></path></svg>';\n }\n addFileButton.appendChild(addFileButtonIcon);\n\n const addFileButtonText = document.createElement(\"p\");\n addFileButtonText.className = \"bn-add-file-button-text\";\n addFileButtonText.innerHTML =\n buttonText || editor.dictionary.file_blocks.file.add_button_text;\n addFileButton.appendChild(addFileButtonText);\n\n // Prevents focus from moving to the button.\n const addFileButtonMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n };\n // Opens the file toolbar.\n const addFileButtonClickHandler = () => {\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: block,\n }),\n );\n };\n addFileButton.addEventListener(\n \"mousedown\",\n addFileButtonMouseDownHandler,\n true,\n );\n addFileButton.addEventListener(\"click\", addFileButtonClickHandler, true);\n\n return {\n dom: addFileButton,\n destroy: () => {\n addFileButton.removeEventListener(\n \"mousedown\",\n addFileButtonMouseDownHandler,\n true,\n );\n addFileButton.removeEventListener(\n \"click\",\n addFileButtonClickHandler,\n true,\n );\n },\n };\n};\n","import { BlockFromConfig, FileBlockConfig } from \"../../../../schema/index.js\";\n\nexport const FILE_ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3 8L9.00319 2H19.9978C20.5513 2 21 2.45531 21 2.9918V21.0082C21 21.556 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5501 3 20.9932V8ZM10 4V9H5V20H19V4H10Z\"></path></svg>`;\n\nexport const createFileNameWithIcon = (\n block: BlockFromConfig<FileBlockConfig, any, any>,\n): { dom: HTMLElement; destroy?: () => void } => {\n const file = document.createElement(\"div\");\n file.className = \"bn-file-name-with-icon\";\n\n const icon = document.createElement(\"div\");\n icon.className = \"bn-file-icon\";\n icon.innerHTML = FILE_ICON_SVG;\n file.appendChild(icon);\n\n const fileName = document.createElement(\"p\");\n fileName.className = \"bn-file-name\";\n fileName.textContent = block.props.name;\n file.appendChild(fileName);\n\n return {\n dom: file,\n };\n};\n","import type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n BlockSchemaWithBlock,\n FileBlockConfig,\n} from \"../../../../schema/index.js\";\nimport { createAddFileButton } from \"./createAddFileButton.js\";\nimport { createFileNameWithIcon } from \"./createFileNameWithIcon.js\";\n\nexport const createFileBlockWrapper = (\n block: BlockFromConfig<FileBlockConfig, any, any>,\n editor: BlockNoteEditor<\n BlockSchemaWithBlock<FileBlockConfig[\"type\"], FileBlockConfig>,\n any,\n any\n >,\n element?: { dom: HTMLElement; destroy?: () => void },\n buttonText?: string,\n buttonIcon?: HTMLElement,\n) => {\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"bn-file-block-content-wrapper\";\n\n // Show the add file button if the file has not been uploaded yet. Change to\n // show a loader if a file upload for the block begins.\n if (block.props.url === \"\") {\n const addFileButton = createAddFileButton(\n block,\n editor,\n buttonText,\n buttonIcon,\n );\n wrapper.appendChild(addFileButton.dom);\n\n const destroyUploadStartHandler = editor.onUploadStart((blockId) => {\n if (blockId === block.id) {\n wrapper.removeChild(addFileButton.dom);\n\n const loading = document.createElement(\"div\");\n loading.className = \"bn-file-loading-preview\";\n loading.textContent = \"Loading...\";\n wrapper.appendChild(loading);\n }\n });\n\n return {\n dom: wrapper,\n destroy: () => {\n destroyUploadStartHandler();\n addFileButton.destroy();\n },\n };\n }\n\n const ret: { dom: HTMLElement; destroy?: () => void } = { dom: wrapper };\n\n // Show the file preview, or the file name and icon.\n if (block.props.showPreview === false || !element) {\n // Show file name and icon.\n const fileNameWithIcon = createFileNameWithIcon(block);\n wrapper.appendChild(fileNameWithIcon.dom);\n\n ret.destroy = () => {\n fileNameWithIcon.destroy?.();\n };\n } else {\n // Show file preview.\n wrapper.appendChild(element.dom);\n }\n\n // Show the caption if there is one.\n if (block.props.caption) {\n const caption = document.createElement(\"p\");\n caption.className = \"bn-file-caption\";\n caption.textContent = block.props.caption;\n wrapper.appendChild(caption);\n }\n\n return ret;\n};\n","export const createFigureWithCaption = (\n element: HTMLElement,\n caption: string,\n) => {\n const figure = document.createElement(\"figure\");\n const captionElement = document.createElement(\"figcaption\");\n captionElement.textContent = caption;\n\n figure.appendChild(element);\n figure.appendChild(captionElement);\n\n return { dom: figure };\n};\n","export const createLinkWithCaption = (\n element: HTMLElement,\n caption: string,\n) => {\n const wrapper = document.createElement(\"div\");\n const fileCaption = document.createElement(\"p\");\n fileCaption.textContent = caption;\n\n wrapper.appendChild(element);\n wrapper.appendChild(fileCaption);\n\n return {\n dom: wrapper,\n };\n};\n","export const parseAudioElement = (audioElement: HTMLAudioElement) => {\n const url = audioElement.src || undefined;\n\n return { url };\n};\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n createBlockSpec,\n FileBlockConfig,\n Props,\n PropSchema,\n} from \"../../schema/index.js\";\nimport { defaultProps } from \"../defaultProps.js\";\n\nimport { parseFigureElement } from \"../FileBlockContent/helpers/parse/parseFigureElement.js\";\nimport { createFileBlockWrapper } from \"../FileBlockContent/helpers/render/createFileBlockWrapper.js\";\nimport { createFigureWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.js\";\nimport { createLinkWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.js\";\nimport { parseAudioElement } from \"./parseAudioElement.js\";\n\nexport const FILE_AUDIO_ICON_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M2 16.0001H5.88889L11.1834 20.3319C11.2727 20.405 11.3846 20.4449 11.5 20.4449C11.7761 20.4449 12 20.2211 12 19.9449V4.05519C12 3.93977 11.9601 3.8279 11.887 3.73857C11.7121 3.52485 11.3971 3.49335 11.1834 3.66821L5.88889 8.00007H2C1.44772 8.00007 1 8.44778 1 9.00007V15.0001C1 15.5524 1.44772 16.0001 2 16.0001ZM23 12C23 15.292 21.5539 18.2463 19.2622 20.2622L17.8445 18.8444C19.7758 17.1937 21 14.7398 21 12C21 9.26016 19.7758 6.80629 17.8445 5.15557L19.2622 3.73779C21.5539 5.75368 23 8.70795 23 12ZM18 12C18 10.0883 17.106 8.38548 15.7133 7.28673L14.2842 8.71584C15.3213 9.43855 16 10.64 16 12C16 13.36 15.3213 14.5614 14.2842 15.2841L15.7133 16.7132C17.106 15.6145 18 13.9116 18 12Z\"></path></svg>';\n\nexport const audioPropSchema = {\n backgroundColor: defaultProps.backgroundColor,\n // File name.\n name: {\n default: \"\" as const,\n },\n // File url.\n url: {\n default: \"\" as const,\n },\n // File caption.\n caption: {\n default: \"\" as const,\n },\n\n showPreview: {\n default: true,\n },\n} satisfies PropSchema;\n\nexport const audioBlockConfig = {\n type: \"audio\" as const,\n propSchema: audioPropSchema,\n content: \"none\",\n isFileBlock: true,\n fileBlockAccept: [\"audio/*\"],\n} satisfies FileBlockConfig;\n\nexport const audioRender = (\n block: BlockFromConfig<typeof audioBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n) => {\n const icon = document.createElement(\"div\");\n icon.innerHTML = FILE_AUDIO_ICON_SVG;\n\n const audio = document.createElement(\"audio\");\n audio.className = \"bn-audio\";\n if (editor.resolveFileUrl) {\n editor.resolveFileUrl(block.props.url).then((downloadUrl) => {\n audio.src = downloadUrl;\n });\n } else {\n audio.src = block.props.url;\n }\n audio.controls = true;\n audio.contentEditable = \"false\";\n audio.draggable = false;\n\n return createFileBlockWrapper(\n block,\n editor,\n { dom: audio },\n editor.dictionary.file_blocks.audio.add_button_text,\n icon.firstElementChild as HTMLElement,\n );\n};\n\nexport const audioParse = (\n element: HTMLElement,\n): Partial<Props<typeof audioBlockConfig.propSchema>> | undefined => {\n if (element.tagName === \"AUDIO\") {\n // Ignore if parent figure has already been parsed.\n if (element.closest(\"figure\")) {\n return undefined;\n }\n\n return parseAudioElement(element as HTMLAudioElement);\n }\n\n if (element.tagName === \"FIGURE\") {\n const parsedFigure = parseFigureElement(element, \"audio\");\n if (!parsedFigure) {\n return undefined;\n }\n\n const { targetElement, caption } = parsedFigure;\n\n return {\n ...parseAudioElement(targetElement as HTMLAudioElement),\n caption,\n };\n }\n\n return undefined;\n};\n\nexport const audioToExternalHTML = (\n block: BlockFromConfig<typeof audioBlockConfig, any, any>,\n) => {\n if (!block.props.url) {\n const div = document.createElement(\"p\");\n div.textContent = \"Add audio\";\n\n return {\n dom: div,\n };\n }\n\n let audio;\n if (block.props.showPreview) {\n audio = document.createElement(\"audio\");\n audio.src = block.props.url;\n } else {\n audio = document.createElement(\"a\");\n audio.href = block.props.url;\n audio.textContent = block.props.name || block.props.url;\n }\n\n if (block.props.caption) {\n if (block.props.showPreview) {\n return createFigureWithCaption(audio, block.props.caption);\n } else {\n return createLinkWithCaption(audio, block.props.caption);\n }\n }\n\n return {\n dom: audio,\n };\n};\n\nexport const AudioBlock = createBlockSpec(audioBlockConfig, {\n render: audioRender,\n parse: audioParse,\n toExternalHTML: audioToExternalHTML,\n});\n","import type { HighlighterGeneric } from \"@shikijs/types\";\nimport { InputRule, isTextSelection } from \"@tiptap/core\";\nimport { TextSelection } from \"@tiptap/pm/state\";\nimport { Parser, createHighlightPlugin } from \"prosemirror-highlight\";\nimport { createParser } from \"prosemirror-highlight/shiki\";\nimport { BlockNoteEditor } from \"../../index.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\n\nexport type CodeBlockOptions = {\n /**\n * Whether to indent lines with a tab when the user presses `Tab` in a code block.\n *\n * @default true\n */\n indentLineWithTab?: boolean;\n /**\n * The default language to use for code blocks.\n *\n * @default \"text\"\n */\n defaultLanguage?: string;\n /**\n * The languages that are supported in the editor.\n *\n * @example\n * {\n * javascript: {\n * name: \"JavaScript\",\n * aliases: [\"js\"],\n * },\n * typescript: {\n * name: \"TypeScript\",\n * aliases: [\"ts\"],\n * },\n * }\n */\n supportedLanguages: Record<\n string,\n {\n /**\n * The display name of the language.\n */\n name: string;\n /**\n * Aliases for this language.\n */\n aliases?: string[];\n }\n >;\n /**\n * The highlighter to use for code blocks.\n */\n createHighlighter?: () => Promise<HighlighterGeneric<any, any>>;\n};\n\ntype CodeBlockConfigOptions = {\n editor: BlockNoteEditor<any, any, any>;\n};\n\nexport const shikiParserSymbol = Symbol.for(\"blocknote.shikiParser\");\nexport const shikiHighlighterPromiseSymbol = Symbol.for(\n \"blocknote.shikiHighlighterPromise\",\n);\nexport const defaultCodeBlockPropSchema = {\n language: {\n default: \"text\",\n },\n} satisfies PropSchema;\n\nconst CodeBlockContent = createStronglyTypedTiptapNode({\n name: \"codeBlock\",\n content: \"inline*\",\n group: \"blockContent\",\n marks: \"insertion deletion modification\",\n code: true,\n defining: true,\n addOptions() {\n return {\n defaultLanguage: \"text\",\n indentLineWithTab: true,\n supportedLanguages: {},\n };\n },\n addAttributes() {\n const options = this.options as CodeBlockConfigOptions;\n\n return {\n language: {\n default: options.editor.settings.codeBlock.defaultLanguage,\n parseHTML: (inputElement) => {\n let element = inputElement as HTMLElement | null;\n let language: string | null = null;\n\n if (\n element?.tagName === \"DIV\" &&\n element?.dataset.contentType === \"codeBlock\"\n ) {\n element = element.children[0] as HTMLElement | null;\n }\n\n if (element?.tagName === \"PRE\") {\n element = element?.children[0] as HTMLElement | null;\n }\n\n const dataLanguage = element?.getAttribute(\"data-language\");\n\n if (dataLanguage) {\n language = dataLanguage.toLowerCase();\n } else {\n const classNames = [...(element?.className.split(\" \") || [])];\n const languages = classNames\n .filter((className) => className.startsWith(\"language-\"))\n .map((className) => className.replace(\"language-\", \"\"));\n\n if (languages.length > 0) {\n language = languages[0].toLowerCase();\n }\n }\n\n if (!language) {\n return null;\n }\n\n return (\n getLanguageId(options.editor.settings.codeBlock, language) ??\n language\n );\n },\n renderHTML: (attributes) => {\n return attributes.language\n ? {\n class: `language-${attributes.language}`,\n \"data-language\": attributes.language,\n }\n : {};\n },\n },\n };\n },\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"pre\",\n // contentElement: \"code\",\n preserveWhitespace: \"full\",\n },\n ];\n },\n renderHTML({ HTMLAttributes }) {\n const pre = document.createElement(\"pre\");\n const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(\n this.name,\n \"code\",\n this.options.domAttributes?.blockContent || {},\n {\n ...(this.options.domAttributes?.inlineContent || {}),\n ...HTMLAttributes,\n },\n );\n\n dom.removeChild(contentDOM);\n dom.appendChild(pre);\n pre.appendChild(contentDOM);\n\n return {\n dom,\n contentDOM,\n };\n },\n addNodeView() {\n const options = this.options as CodeBlockConfigOptions;\n\n return ({ editor, node, getPos, HTMLAttributes }) => {\n const pre = document.createElement(\"pre\");\n const select = document.createElement(\"select\");\n const selectWrapper = document.createElement(\"div\");\n const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(\n this.name,\n \"code\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n const handleLanguageChange = (event: Event) => {\n const language = (event.target as HTMLSelectElement).value;\n\n editor.commands.command(({ tr }) => {\n tr.setNodeAttribute(getPos(), \"language\", language);\n\n return true;\n });\n };\n\n Object.entries(\n options.editor.settings.codeBlock.supportedLanguages,\n ).forEach(([id, { name }]) => {\n const option = document.createElement(\"option\");\n\n option.value = id;\n option.text = name;\n select.appendChild(option);\n });\n\n selectWrapper.contentEditable = \"false\";\n select.value =\n node.attrs.language ||\n options.editor.settings.codeBlock.defaultLanguage;\n dom.removeChild(contentDOM);\n dom.appendChild(selectWrapper);\n dom.appendChild(pre);\n pre.appendChild(contentDOM);\n selectWrapper.appendChild(select);\n select.addEventListener(\"change\", handleLanguageChange);\n\n return {\n dom,\n contentDOM,\n update: (newNode) => {\n if (newNode.type !== this.type) {\n return false;\n }\n\n return true;\n },\n destroy: () => {\n select.removeEventListener(\"change\", handleLanguageChange);\n },\n };\n };\n },\n addProseMirrorPlugins() {\n const options = this.options as CodeBlockConfigOptions;\n const globalThisForShiki = globalThis as {\n [shikiHighlighterPromiseSymbol]?: Promise<HighlighterGeneric<any, any>>;\n [shikiParserSymbol]?: Parser;\n };\n\n let highlighter: HighlighterGeneric<any, any> | undefined;\n let parser: Parser | undefined;\n let hasWarned = false;\n const lazyParser: Parser = (parserOptions) => {\n if (!options.editor.settings.codeBlock.createHighlighter) {\n if (process.env.NODE_ENV === \"development\" && !hasWarned) {\n // eslint-disable-next-line no-console\n console.log(\n \"For syntax highlighting of code blocks, you must provide a `codeBlock.createHighlighter` function\",\n );\n hasWarned = true;\n }\n return [];\n }\n if (!highlighter) {\n globalThisForShiki[shikiHighlighterPromiseSymbol] =\n globalThisForShiki[shikiHighlighterPromiseSymbol] ||\n options.editor.settings.codeBlock.createHighlighter();\n\n return globalThisForShiki[shikiHighlighterPromiseSymbol].then(\n (createdHighlighter) => {\n highlighter = createdHighlighter;\n },\n );\n }\n const language = getLanguageId(\n options.editor.settings.codeBlock,\n parserOptions.language!,\n );\n\n if (\n !language ||\n language === \"text\" ||\n language === \"none\" ||\n language === \"plaintext\" ||\n language === \"txt\"\n ) {\n return [];\n }\n\n if (!highlighter.getLoadedLanguages().includes(language)) {\n return highlighter.loadLanguage(language);\n }\n\n if (!parser) {\n parser =\n globalThisForShiki[shikiParserSymbol] ||\n createParser(highlighter as any);\n globalThisForShiki[shikiParserSymbol] = parser;\n }\n\n return parser(parserOptions);\n };\n\n const shikiLazyPlugin = createHighlightPlugin({\n parser: lazyParser,\n languageExtractor: (node) => node.attrs.language,\n nodeTypes: [this.name],\n });\n\n return [shikiLazyPlugin];\n },\n addInputRules() {\n const options = this.options as CodeBlockConfigOptions;\n\n return [\n new InputRule({\n find: /^```(.*?)\\s$/,\n handler: ({ state, range, match }) => {\n const $start = state.doc.resolve(range.from);\n const languageName = match[1].trim();\n const attributes = {\n language:\n getLanguageId(options.editor.settings.codeBlock, languageName) ??\n languageName,\n };\n\n if (\n !$start\n .node(-1)\n .canReplaceWith(\n $start.index(-1),\n $start.indexAfter(-1),\n this.type,\n )\n ) {\n return null;\n }\n\n state.tr\n .delete(range.from, range.to)\n .setBlockType(range.from, range.from, this.type, attributes)\n .setSelection(TextSelection.create(state.tr.doc, range.from));\n\n return;\n },\n }),\n ];\n },\n addKeyboardShortcuts() {\n return {\n Delete: ({ editor }) => {\n const { selection } = editor.state;\n const { $from } = selection;\n\n // When inside empty codeblock, on `DELETE` key press, delete the codeblock\n if (\n editor.isActive(this.name) &&\n !$from.parent.textContent &&\n isTextSelection(selection)\n ) {\n // Get the start position of the codeblock for node selection\n const from = $from.pos - $from.parentOffset - 2;\n\n editor.chain().setNodeSelection(from).deleteSelection().run();\n\n return true;\n }\n\n return false;\n },\n Tab: ({ editor }) => {\n if (!this.options.indentLineWithTab) {\n return false;\n }\n if (editor.isActive(this.name)) {\n editor.commands.insertContent(\" \");\n return true;\n }\n\n return false;\n },\n Enter: ({ editor }) => {\n const { $from } = editor.state.selection;\n\n if (!editor.isActive(this.name)) {\n return false;\n }\n\n const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2;\n const endsWithDoubleNewline = $from.parent.textContent.endsWith(\"\\n\\n\");\n\n if (!isAtEnd || !endsWithDoubleNewline) {\n editor.commands.insertContent(\"\\n\");\n return true;\n }\n\n return editor\n .chain()\n .command(({ tr }) => {\n tr.delete($from.pos - 2, $from.pos);\n\n return true;\n })\n .exitCode()\n .run();\n },\n \"Shift-Enter\": ({ editor }) => {\n const { $from } = editor.state.selection;\n\n if (!editor.isActive(this.name)) {\n return false;\n }\n\n editor\n .chain()\n .insertContentAt(\n $from.pos - $from.parentOffset + $from.parent.nodeSize,\n {\n type: \"paragraph\",\n },\n )\n .run();\n\n return true;\n },\n };\n },\n});\n\nexport const CodeBlock = createBlockSpecFromStronglyTypedTiptapNode(\n CodeBlockContent,\n defaultCodeBlockPropSchema,\n);\n\nfunction getLanguageId(\n options: CodeBlockOptions,\n languageName: string,\n): string | undefined {\n return Object.entries(options.supportedLanguages).find(\n ([id, { aliases }]) => {\n return aliases?.includes(languageName) || id === languageName;\n },\n )?.[0];\n}\n","import { Mark } from \"@tiptap/core\";\nimport { createStyleSpecFromTipTapMark } from \"../../schema/index.js\";\n\nconst BackgroundColorMark = Mark.create({\n name: \"backgroundColor\",\n\n addAttributes() {\n return {\n stringValue: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-background-color\"),\n renderHTML: (attributes) => ({\n \"data-background-color\": attributes.stringValue,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.hasAttribute(\"data-background-color\")) {\n return {\n stringValue: element.getAttribute(\"data-background-color\"),\n };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n});\n\nexport const BackgroundColor = createStyleSpecFromTipTapMark(\n BackgroundColorMark,\n \"string\",\n);\n","import { Mark } from \"@tiptap/core\";\nimport { createStyleSpecFromTipTapMark } from \"../../schema/index.js\";\n\nconst TextColorMark = Mark.create({\n name: \"textColor\",\n\n addAttributes() {\n return {\n stringValue: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-text-color\"),\n renderHTML: (attributes) => ({\n \"data-text-color\": attributes.stringValue,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.hasAttribute(\"data-text-color\")) {\n return { stringValue: element.getAttribute(\"data-text-color\") };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n});\n\nexport const TextColor = createStyleSpecFromTipTapMark(TextColorMark, \"string\");\n","export const parseEmbedElement = (embedElement: HTMLEmbedElement) => {\n const url = embedElement.src || undefined;\n\n return { url };\n};\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n FileBlockConfig,\n PropSchema,\n createBlockSpec,\n} from \"../../schema/index.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { parseEmbedElement } from \"./helpers/parse/parseEmbedElement.js\";\nimport { parseFigureElement } from \"./helpers/parse/parseFigureElement.js\";\nimport { createFileBlockWrapper } from \"./helpers/render/createFileBlockWrapper.js\";\nimport { createLinkWithCaption } from \"./helpers/toExternalHTML/createLinkWithCaption.js\";\n\nexport const filePropSchema = {\n backgroundColor: defaultProps.backgroundColor,\n // File name.\n name: {\n default: \"\" as const,\n },\n // File url.\n url: {\n default: \"\" as const,\n },\n // File caption.\n caption: {\n default: \"\" as const,\n },\n} satisfies PropSchema;\n\nexport const fileBlockConfig = {\n type: \"file\" as const,\n propSchema: filePropSchema,\n content: \"none\",\n isFileBlock: true,\n} satisfies FileBlockConfig;\n\nexport const fileRender = (\n block: BlockFromConfig<typeof fileBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n) => {\n return createFileBlockWrapper(block, editor);\n};\n\nexport const fileParse = (element: HTMLElement) => {\n if (element.tagName === \"EMBED\") {\n // Ignore if parent figure has already been parsed.\n if (element.closest(\"figure\")) {\n return undefined;\n }\n\n return parseEmbedElement(element as HTMLEmbedElement);\n }\n\n if (element.tagName === \"FIGURE\") {\n const parsedFigure = parseFigureElement(element, \"embed\");\n if (!parsedFigure) {\n return undefined;\n }\n\n const { targetElement, caption } = parsedFigure;\n\n return {\n ...parseEmbedElement(targetElement as HTMLEmbedElement),\n caption,\n };\n }\n\n return undefined;\n};\n\nexport const fileToExternalHTML = (\n block: BlockFromConfig<typeof fileBlockConfig, any, any>,\n) => {\n if (!block.props.url) {\n const div = document.createElement(\"p\");\n div.textContent = \"Add file\";\n\n return {\n dom: div,\n };\n }\n\n const fileSrcLink = document.createElement(\"a\");\n fileSrcLink.href = block.props.url;\n fileSrcLink.textContent = block.props.name || block.props.url;\n\n if (block.props.caption) {\n return createLinkWithCaption(fileSrcLink, block.props.caption);\n }\n\n return {\n dom: fileSrcLink,\n };\n};\n\nexport const FileBlock = createBlockSpec(fileBlockConfig, {\n render: fileRender,\n parse: fileParse,\n toExternalHTML: fileToExternalHTML,\n});\n","import { InputRule } from \"@tiptap/core\";\nimport { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../api/getBlockInfoFromPos.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n propsToAttributes,\n} from \"../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../defaultProps.js\";\n\nexport const headingPropSchema = {\n ...defaultProps,\n level: { default: 1, values: [1, 2, 3] as const },\n} satisfies PropSchema;\n\nconst HeadingBlockContent = createStronglyTypedTiptapNode({\n name: \"heading\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addAttributes() {\n return propsToAttributes(headingPropSchema);\n },\n\n addInputRules() {\n return [\n ...[1, 2, 3].map((level) => {\n // Creates a heading of appropriate level when starting with \"#\", \"##\", or \"###\".\n return new InputRule({\n find: new RegExp(`^(#{${level}})\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"heading\",\n props: {\n level: level as any,\n },\n }),\n )\n // Removes the \"#\" character(s) used to set the heading.\n .deleteRange({ from: range.from, to: range.to })\n .run();\n },\n });\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Alt-1\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n // call updateBlockCommand\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"heading\",\n props: {\n level: 1 as any,\n },\n }),\n );\n },\n \"Mod-Alt-2\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"heading\",\n props: {\n level: 2 as any,\n },\n }),\n );\n },\n \"Mod-Alt-3\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"heading\",\n props: {\n level: 3 as any,\n },\n }),\n );\n },\n };\n },\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"h1\",\n attrs: { level: 1 },\n node: \"heading\",\n },\n {\n tag: \"h2\",\n attrs: { level: 2 },\n node: \"heading\",\n },\n {\n tag: \"h3\",\n attrs: { level: 3 },\n node: \"heading\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n `h${node.attrs.level}`,\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const Heading = createBlockSpecFromStronglyTypedTiptapNode(\n HeadingBlockContent,\n headingPropSchema,\n);\n","import type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport { BlockFromConfig, FileBlockConfig } from \"../../../../schema/index.js\";\nimport { createFileBlockWrapper } from \"./createFileBlockWrapper.js\";\n\nexport const createResizableFileBlockWrapper = (\n block: BlockFromConfig<FileBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n element: { dom: HTMLElement; destroy?: () => void },\n resizeHandlesContainerElement: HTMLElement,\n buttonText: string,\n buttonIcon: HTMLElement,\n): { dom: HTMLElement; destroy: () => void } => {\n const { dom, destroy } = createFileBlockWrapper(\n block,\n editor,\n element,\n buttonText,\n buttonIcon,\n );\n const wrapper = dom;\n if (block.props.url && block.props.showPreview) {\n if (block.props.previewWidth) {\n wrapper.style.width = `${block.props.previewWidth}px`;\n } else {\n wrapper.style.width = \"fit-content\";\n }\n }\n\n const leftResizeHandle = document.createElement(\"div\");\n leftResizeHandle.className = \"bn-resize-handle\";\n leftResizeHandle.style.left = \"4px\";\n const rightResizeHandle = document.createElement(\"div\");\n rightResizeHandle.className = \"bn-resize-handle\";\n rightResizeHandle.style.right = \"4px\";\n\n // Temporary parameters set when the user begins resizing the element, used to\n // calculate the new width of the element.\n let resizeParams:\n | {\n handleUsed: \"left\" | \"right\";\n initialWidth: number;\n initialClientX: number;\n }\n | undefined;\n let width = block.props.previewWidth! as number;\n\n // Updates the element width with an updated width depending on the cursor X\n // offset from when the resize began, and which resize handle is being used.\n const windowMouseMoveHandler = (event: MouseEvent) => {\n if (!resizeParams) {\n if (\n !editor.isEditable &&\n resizeHandlesContainerElement.contains(leftResizeHandle) &&\n resizeHandlesContainerElement.contains(rightResizeHandle)\n ) {\n resizeHandlesContainerElement.removeChild(leftResizeHandle);\n resizeHandlesContainerElement.removeChild(rightResizeHandle);\n }\n\n return;\n }\n\n let newWidth: number;\n\n if (block.props.textAlignment === \"center\") {\n if (resizeParams.handleUsed === \"left\") {\n newWidth =\n resizeParams.initialWidth +\n (resizeParams.initialClientX - event.clientX) * 2;\n } else {\n newWidth =\n resizeParams.initialWidth +\n (event.clientX - resizeParams.initialClientX) * 2;\n }\n } else {\n if (resizeParams.handleUsed === \"left\") {\n newWidth =\n resizeParams.initialWidth +\n resizeParams.initialClientX -\n event.clientX;\n } else {\n newWidth =\n resizeParams.initialWidth +\n event.clientX -\n resizeParams.initialClientX;\n }\n }\n\n // Min element width in px.\n const minWidth = 64;\n\n // Ensures the element is not wider than the editor and not narrower than a\n // predetermined minimum width.\n width = Math.min(\n Math.max(newWidth, minWidth),\n editor.domElement?.firstElementChild?.clientWidth || Number.MAX_VALUE,\n );\n wrapper.style.width = `${width}px`;\n };\n // Stops mouse movements from resizing the element and updates the block's\n // `width` prop to the new value.\n const windowMouseUpHandler = (event: MouseEvent) => {\n // Hides the drag handles if the cursor is no longer over the element.\n if (\n (!event.target ||\n !wrapper.contains(event.target as Node) ||\n !editor.isEditable) &&\n resizeHandlesContainerElement.contains(leftResizeHandle) &&\n resizeHandlesContainerElement.contains(rightResizeHandle)\n ) {\n resizeHandlesContainerElement.removeChild(leftResizeHandle);\n resizeHandlesContainerElement.removeChild(rightResizeHandle);\n }\n\n if (!resizeParams) {\n return;\n }\n\n resizeParams = undefined;\n\n editor.updateBlock(block, {\n props: {\n previewWidth: width,\n },\n });\n };\n\n // Shows the resize handles when hovering over the wrapper with the cursor.\n const wrapperMouseEnterHandler = () => {\n if (editor.isEditable) {\n resizeHandlesContainerElement.appendChild(leftResizeHandle);\n resizeHandlesContainerElement.appendChild(rightResizeHandle);\n }\n };\n // Hides the resize handles when the cursor leaves the wrapper, unless the\n // cursor moves to one of the resize handles.\n const wrapperMouseLeaveHandler = (event: MouseEvent) => {\n if (\n event.relatedTarget === leftResizeHandle ||\n event.relatedTarget === rightResizeHandle\n ) {\n return;\n }\n\n if (resizeParams) {\n return;\n }\n\n if (\n editor.isEditable &&\n resizeHandlesContainerElement.contains(leftResizeHandle) &&\n resizeHandlesContainerElement.contains(rightResizeHandle)\n ) {\n resizeHandlesContainerElement.removeChild(leftResizeHandle);\n resizeHandlesContainerElement.removeChild(rightResizeHandle);\n }\n };\n\n // Sets the resize params, allowing the user to begin resizing the element by\n // moving the cursor left or right.\n const leftResizeHandleMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n resizeParams = {\n handleUsed: \"left\",\n initialWidth: wrapper.clientWidth,\n initialClientX: event.clientX,\n };\n };\n const rightResizeHandleMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n resizeParams = {\n handleUsed: \"right\",\n initialWidth: wrapper.clientWidth,\n initialClientX: event.clientX,\n };\n };\n\n window.addEventListener(\"mousemove\", windowMouseMoveHandler);\n window.addEventListener(\"mouseup\", windowMouseUpHandler);\n wrapper.addEventListener(\"mouseenter\", wrapperMouseEnterHandler);\n wrapper.addEventListener(\"mouseleave\", wrapperMouseLeaveHandler);\n leftResizeHandle.addEventListener(\n \"mousedown\",\n leftResizeHandleMouseDownHandler,\n );\n rightResizeHandle.addEventListener(\n \"mousedown\",\n rightResizeHandleMouseDownHandler,\n );\n\n return {\n dom: wrapper,\n destroy: () => {\n destroy?.();\n window.removeEventListener(\"mousemove\", windowMouseMoveHandler);\n window.removeEventListener(\"mouseup\", windowMouseUpHandler);\n wrapper.removeEventListener(\"mouseenter\", wrapperMouseEnterHandler);\n wrapper.removeEventListener(\"mouseleave\", wrapperMouseLeaveHandler);\n leftResizeHandle.removeEventListener(\n \"mousedown\",\n leftResizeHandleMouseDownHandler,\n );\n rightResizeHandle.removeEventListener(\n \"mousedown\",\n rightResizeHandleMouseDownHandler,\n );\n },\n };\n};\n","export const parseImageElement = (imageElement: HTMLImageElement) => {\n const url = imageElement.src || undefined;\n const previewWidth = imageElement.width || undefined;\n\n return { url, previewWidth };\n};\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n createBlockSpec,\n FileBlockConfig,\n Props,\n PropSchema,\n} from \"../../schema/index.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { parseFigureElement } from \"../FileBlockContent/helpers/parse/parseFigureElement.js\";\nimport { createFigureWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.js\";\nimport { createLinkWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.js\";\nimport { createResizableFileBlockWrapper } from \"../FileBlockContent/helpers/render/createResizableFileBlockWrapper.js\";\nimport { parseImageElement } from \"./parseImageElement.js\";\n\nexport const FILE_IMAGE_ICON_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M5 11.1005L7 9.1005L12.5 14.6005L16 11.1005L19 14.1005V5H5V11.1005ZM4 3H20C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3ZM15.5 10C14.6716 10 14 9.32843 14 8.5C14 7.67157 14.6716 7 15.5 7C16.3284 7 17 7.67157 17 8.5C17 9.32843 16.3284 10 15.5 10Z\"></path></svg>';\n\nexport const imagePropSchema = {\n textAlignment: defaultProps.textAlignment,\n backgroundColor: defaultProps.backgroundColor,\n // File name.\n name: {\n default: \"\" as const,\n },\n // File url.\n url: {\n default: \"\" as const,\n },\n // File caption.\n caption: {\n default: \"\" as const,\n },\n\n showPreview: {\n default: true,\n },\n // File preview width in px.\n previewWidth: {\n default: undefined,\n type: \"number\",\n },\n} satisfies PropSchema;\n\nexport const imageBlockConfig = {\n type: \"image\" as const,\n propSchema: imagePropSchema,\n content: \"none\",\n isFileBlock: true,\n fileBlockAccept: [\"image/*\"],\n} satisfies FileBlockConfig;\n\nexport const imageRender = (\n block: BlockFromConfig<typeof imageBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n) => {\n const icon = document.createElement(\"div\");\n icon.innerHTML = FILE_IMAGE_ICON_SVG;\n\n const imageWrapper = document.createElement(\"div\");\n imageWrapper.className = \"bn-visual-media-wrapper\";\n\n const image = document.createElement(\"img\");\n image.className = \"bn-visual-media\";\n if (editor.resolveFileUrl) {\n editor.resolveFileUrl(block.props.url).then((downloadUrl) => {\n image.src = downloadUrl;\n });\n } else {\n image.src = block.props.url;\n }\n\n image.alt = block.props.name || block.props.caption || \"BlockNote image\";\n image.contentEditable = \"false\";\n image.draggable = false;\n imageWrapper.appendChild(image);\n\n return createResizableFileBlockWrapper(\n block,\n editor,\n { dom: imageWrapper },\n imageWrapper,\n editor.dictionary.file_blocks.image.add_button_text,\n icon.firstElementChild as HTMLElement,\n );\n};\n\nexport const imageParse = (\n element: HTMLElement,\n): Partial<Props<typeof imageBlockConfig.propSchema>> | undefined => {\n if (element.tagName === \"IMG\") {\n // Ignore if parent figure has already been parsed.\n if (element.closest(\"figure\")) {\n return undefined;\n }\n\n return parseImageElement(element as HTMLImageElement);\n }\n\n if (element.tagName === \"FIGURE\") {\n const parsedFigure = parseFigureElement(element, \"img\");\n if (!parsedFigure) {\n return undefined;\n }\n\n const { targetElement, caption } = parsedFigure;\n\n return {\n ...parseImageElement(targetElement as HTMLImageElement),\n caption,\n };\n }\n\n return undefined;\n};\n\nexport const imageToExternalHTML = (\n block: BlockFromConfig<typeof imageBlockConfig, any, any>,\n) => {\n if (!block.props.url) {\n const div = document.createElement(\"p\");\n div.textContent = \"Add image\";\n\n return {\n dom: div,\n };\n }\n\n let image;\n if (block.props.showPreview) {\n image = document.createElement(\"img\");\n image.src = block.props.url;\n image.alt = block.props.name || block.props.caption || \"BlockNote image\";\n if (block.props.previewWidth) {\n image.width = block.props.previewWidth;\n }\n } else {\n image = document.createElement(\"a\");\n image.href = block.props.url;\n image.textContent = block.props.name || block.props.url;\n }\n\n if (block.props.caption) {\n if (block.props.showPreview) {\n return createFigureWithCaption(image, block.props.caption);\n } else {\n return createLinkWithCaption(image, block.props.caption);\n }\n }\n\n return {\n dom: image,\n };\n};\n\nexport const ImageBlock = createBlockSpec(imageBlockConfig, {\n render: imageRender,\n parse: imageParse,\n toExternalHTML: imageToExternalHTML,\n});\n","import { DOMParser, Fragment, Schema } from \"prosemirror-model\";\n\n/**\n * This function is used to parse the content of a list item external HTML node.\n *\n * Due to a change in how prosemirror-model handles parsing elements, we have additional flexibility in how we can \"fit\" content into a list item.\n *\n * We've decided to take an approach that is similar to Notion. The core rules of the algorithm are:\n *\n * - If the first child of an `li` has ONLY text content, take the text content, and flatten it into the list item. Subsequent siblings are carried over as is, as children of the list item.\n * - e.g. `<li><h1>Hello</h1><p>World</p></li> -> <li>Hello<blockGroup><blockContainer><p>World</p></blockContainer></blockGroup></li>`\n * - Else, take the content and insert it as children instead.\n * - e.g. `<li><img src=\"url\" /></li> -> <li><p></p><blockGroup><blockContainer><img src=\"url\" /></blockContainer></blockGroup></li>`\n *\n * This ensures that a list item's content is always valid ProseMirror content. Smoothing over differences between how external HTML may be rendered, and how ProseMirror expects content to be structured.\n */\nexport function getListItemContent(\n /**\n * The `li` element to parse.\n */\n _node: Node,\n /**\n * The schema to use for parsing.\n */\n schema: Schema,\n /**\n * The name of the list item node.\n */\n name: string,\n): Fragment {\n /**\n * To actually implement this algorithm, we need to leverage ProseMirror's \"fitting\" algorithm.\n * Where, if content is parsed which doesn't fit into the current node, it will be moved into the parent node.\n *\n * This allows us to parse multiple pieces of content from within the list item (even though it normally would not match the list item's schema) and \"throw\" the excess content into the list item's children.\n *\n * The expected return value is a `Fragment` which contains the list item's content as the first element, and the children wrapped in a blockGroup node. Like so:\n * ```\n * Fragment<[Node<Text>, Node<BlockGroup<Node<BlockContainer<any>>>>]>\n * ```\n */\n const parser = DOMParser.fromSchema(schema);\n\n // TODO: This will be unnecessary in the future: https://github.com/ProseMirror/prosemirror-model/commit/166188d4f9db96eb86fb7de62e72049c86c9dd79\n const node = _node as HTMLElement;\n\n // Move the `li` element's content into a new `div` element\n // This is a hacky workaround to not re-trigger list item parsing,\n // when we are looking to understand what the list item's content actually is, in terms of the schema.\n const clonedNodeDiv = document.createElement(\"div\");\n // Mark the `div` element as a `blockGroup` to make the parsing easier.\n clonedNodeDiv.setAttribute(\"data-node-type\", \"blockGroup\");\n // Clone all children of the `li` element into the new `div` element\n for (const child of Array.from(node.childNodes)) {\n clonedNodeDiv.appendChild(child.cloneNode(true));\n }\n\n // Parses children of the `li` element into a `blockGroup` with `blockContainer` node children\n // This is the structure of list item children, so parsing into this structure allows for\n // easy separation of list item content from child list item content.\n let blockGroupNode = parser.parse(clonedNodeDiv, {\n topNode: schema.nodes.blockGroup.create(),\n });\n\n // There is an edge case where a list item's content may contain a `<input>` element.\n // Causing it to be recognized as a `checkListItem`.\n // We want to skip this, and just parse the list item's content as is.\n if (blockGroupNode.firstChild?.firstChild?.type.name === \"checkListItem\") {\n // We skip the first child, by cutting it out of the `blockGroup` node.\n // and continuing with the rest of the algorithm.\n blockGroupNode = blockGroupNode.copy(\n blockGroupNode.content.cut(\n blockGroupNode.firstChild.firstChild.nodeSize + 2,\n ),\n );\n }\n\n // Structure above is `blockGroup<blockContainer<any>[]>`\n // We want to extract the first `blockContainer` node's content, and see if it is a text block.\n const listItemsFirstChild = blockGroupNode.firstChild?.firstChild;\n\n // If the first node is not a text block, then it's first child is not compatible with the list item node.\n if (!listItemsFirstChild?.isTextblock) {\n // So, we do not try inserting anything into the list item, and instead return anything we found as children for the list item.\n return Fragment.from(blockGroupNode);\n }\n\n // If it is a text block, then we know it only contains text content.\n // So, we extract it, and insert its content into the `listItemNode`.\n // The remaining nodes in the `blockGroup` stay in-place.\n const listItemNode = schema.nodes[name].create(\n {},\n listItemsFirstChild.content,\n );\n\n // We have `blockGroup<listItemsFirstChild, ...blockContainer<any>[]>`\n // We want to extract out the rest of the nodes as `<...blockContainer<any>[]>`\n const remainingListItemChildren = blockGroupNode.content.cut(\n // +2 for the `blockGroup` node's start and end markers\n listItemsFirstChild.nodeSize + 2,\n );\n const hasRemainingListItemChildren = remainingListItemChildren.size > 0;\n\n if (hasRemainingListItemChildren) {\n // Copy the remaining list item children back into the `blockGroup` node.\n // This will make it back into: `blockGroup<...blockContainer<any>[]>`\n const listItemsChildren = blockGroupNode.copy(remainingListItemChildren);\n\n // Return the `listItem` node's content, then add the parsed children after to be lifted out by ProseMirror \"fitting\" algorithm.\n return listItemNode.content.addToEnd(listItemsChildren);\n }\n\n // Otherwise, just return the `listItem` node's content.\n return listItemNode.content;\n}\n","import { EditorState } from \"prosemirror-state\";\n\nimport {\n getBlockInfo,\n getNearestBlockPos,\n} from \"../../../getBlockInfoFromPos.js\";\n\nexport const splitBlockCommand = (\n posInBlock: number,\n keepType?: boolean,\n keepProps?: boolean,\n) => {\n return ({\n state,\n dispatch,\n }: {\n state: EditorState;\n dispatch: ((args?: any) => any) | undefined;\n }) => {\n const nearestBlockContainerPos = getNearestBlockPos(state.doc, posInBlock);\n\n const info = getBlockInfo(nearestBlockContainerPos);\n\n if (!info.isBlockContainer) {\n throw new Error(\n `BlockContainer expected when calling splitBlock, position ${posInBlock}`,\n );\n }\n\n const types = [\n {\n type: info.bnBlock.node.type, // always keep blockcontainer type\n attrs: keepProps ? { ...info.bnBlock.node.attrs, id: undefined } : {},\n },\n {\n type: keepType\n ? info.blockContent.node.type\n : state.schema.nodes[\"paragraph\"],\n attrs: keepProps ? { ...info.blockContent.node.attrs } : {},\n },\n ];\n\n if (dispatch) {\n state.tr.split(posInBlock, 2, types);\n }\n\n return true;\n };\n};\n","import { splitBlockCommand } from \"../../api/blockManipulation/commands/splitBlock/splitBlock.js\";\nimport { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromTransaction } from \"../../api/getBlockInfoFromPos.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\n\nexport const handleEnter = (editor: BlockNoteEditor<any, any, any>) => {\n const { blockInfo, selectionEmpty } = editor.transact((tr) => {\n return {\n blockInfo: getBlockInfoFromTransaction(tr),\n selectionEmpty: tr.selection.anchor === tr.selection.head,\n };\n });\n\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { bnBlock: blockContainer, blockContent } = blockInfo;\n\n if (\n !(\n blockContent.node.type.name === \"bulletListItem\" ||\n blockContent.node.type.name === \"numberedListItem\" ||\n blockContent.node.type.name === \"checkListItem\"\n ) ||\n !selectionEmpty\n ) {\n return false;\n }\n\n return editor._tiptapEditor.commands.first(({ state, chain, commands }) => [\n () =>\n // Changes list item block to a paragraph block if the content is empty.\n commands.command(() => {\n if (blockContent.node.childCount === 0) {\n return commands.command(\n updateBlockCommand(blockContainer.beforePos, {\n type: \"paragraph\",\n props: {},\n }),\n );\n }\n\n return false;\n }),\n\n () =>\n // Splits the current block, moving content inside that's after the cursor\n // to a new block of the same type below.\n commands.command(() => {\n if (blockContent.node.childCount > 0) {\n chain()\n .deleteSelection()\n .command(splitBlockCommand(state.selection.from, true))\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n};\n","import { InputRule } from \"@tiptap/core\";\nimport { updateBlockCommand } from \"../../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../../api/getBlockInfoFromPos.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../../defaultProps.js\";\nimport { getListItemContent } from \"../getListItemContent.js\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts.js\";\n\nexport const bulletListItemPropSchema = {\n ...defaultProps,\n} satisfies PropSchema;\n\nconst BulletListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"bulletListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n // This is to make sure that check list parse rules run before, since they\n // both parse `li` elements but check lists are more specific.\n priority: 90,\n addInputRules() {\n return [\n // Creates an unordered list when starting with \"-\", \"+\", or \"*\".\n new InputRule({\n find: new RegExp(`^[-+*]\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"bulletListItem\",\n props: {},\n }),\n )\n // Removes the \"-\", \"+\", or \"*\" character used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.options.editor),\n \"Mod-Shift-8\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"bulletListItem\",\n props: {},\n }),\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"UL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement?.tagName === \"UL\")\n ) {\n return {};\n }\n\n return false;\n },\n // As `li` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n getListItemContent(node, schema, this.name),\n node: \"bulletListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n // We use a <p> tag, because for <li> tags we'd need a <ul> element to put\n // them in to be semantically correct, which we can't have due to the\n // schema.\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const BulletListItem = createBlockSpecFromStronglyTypedTiptapNode(\n BulletListItemBlockContent,\n bulletListItemPropSchema,\n);\n","import { InputRule } from \"@tiptap/core\";\nimport { updateBlockCommand } from \"../../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport {\n getBlockInfoFromSelection,\n getNearestBlockPos,\n} from \"../../../api/getBlockInfoFromPos.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n propsToAttributes,\n} from \"../../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../../defaultProps.js\";\nimport { getListItemContent } from \"../getListItemContent.js\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts.js\";\n\nexport const checkListItemPropSchema = {\n ...defaultProps,\n checked: {\n default: false,\n },\n} satisfies PropSchema;\n\nconst checkListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"checkListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addAttributes() {\n return propsToAttributes(checkListItemPropSchema);\n },\n\n addInputRules() {\n return [\n // Creates a checklist when starting with \"[]\" or \"[X]\".\n new InputRule({\n find: new RegExp(`\\\\[\\\\s*\\\\]\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"checkListItem\",\n props: {\n checked: false as any,\n },\n }),\n )\n // Removes the characters used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n new InputRule({\n find: new RegExp(`\\\\[[Xx]\\\\]\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"checkListItem\",\n props: {\n checked: true as any,\n },\n }),\n )\n // Removes the characters used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.options.editor),\n \"Mod-Shift-9\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"checkListItem\",\n props: {},\n }),\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"input\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n // Ignore if we already parsed an ancestor list item to avoid double-parsing.\n if (element.closest(\"[data-content-type]\") || element.closest(\"li\")) {\n return false;\n }\n\n if ((element as HTMLInputElement).type === \"checkbox\") {\n return { checked: (element as HTMLInputElement).checked };\n }\n\n return false;\n },\n node: \"checkListItem\",\n },\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"UL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement?.tagName === \"UL\")\n ) {\n const checkbox =\n (element.querySelector(\n \"input[type=checkbox]\",\n ) as HTMLInputElement) || null;\n\n if (checkbox === null) {\n return false;\n }\n\n return { checked: checkbox.checked };\n }\n\n return false;\n },\n // As `li` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n getListItemContent(node, schema, this.name),\n node: \"checkListItem\",\n },\n ];\n },\n\n // Since there is no HTML checklist element, there isn't really any\n // standardization for what checklists should look like in the DOM. GDocs'\n // and Notion's aren't cross compatible, for example. This implementation\n // has a semantically correct DOM structure (though missing a label for the\n // checkbox) which is also converted correctly to Markdown by remark.\n renderHTML({ node, HTMLAttributes }) {\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.checked = node.attrs.checked;\n if (node.attrs.checked) {\n checkbox.setAttribute(\"checked\", \"\");\n }\n\n const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(\n this.name,\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n\n dom.insertBefore(checkbox, contentDOM);\n\n return { dom, contentDOM };\n },\n\n // Need to render node view since the checkbox needs to be able to update the\n // node. This is only possible with a node view as it exposes `getPos`.\n addNodeView() {\n return ({ node, getPos, editor, HTMLAttributes }) => {\n // Need to wrap certain elements in a div or keyboard navigation gets\n // confused.\n const wrapper = document.createElement(\"div\");\n const checkboxWrapper = document.createElement(\"div\");\n checkboxWrapper.contentEditable = \"false\";\n\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.checked = node.attrs.checked;\n if (node.attrs.checked) {\n checkbox.setAttribute(\"checked\", \"\");\n }\n\n const changeHandler = () => {\n if (!editor.isEditable) {\n // This seems like the most effective way of blocking the checkbox\n // from being toggled, as event.preventDefault() does not stop it for\n // \"click\" or \"change\" events.\n checkbox.checked = !checkbox.checked;\n return;\n }\n\n // TODO: test\n if (typeof getPos !== \"boolean\") {\n const beforeBlockContainerPos = getNearestBlockPos(\n editor.state.doc,\n getPos(),\n );\n\n if (beforeBlockContainerPos.node.type.name !== \"blockContainer\") {\n throw new Error(\n `Expected blockContainer node, got ${beforeBlockContainerPos.node.type.name}`,\n );\n }\n\n this.editor.commands.command(\n updateBlockCommand(beforeBlockContainerPos.posBeforeNode, {\n type: \"checkListItem\",\n props: {\n checked: checkbox.checked as any,\n },\n }),\n );\n }\n };\n checkbox.addEventListener(\"change\", changeHandler);\n\n const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(\n this.name,\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n\n if (typeof getPos !== \"boolean\") {\n // Since `node` is a blockContent node, we have to get the block ID from\n // the parent blockContainer node. This means we can't add the label in\n // `renderHTML` as we can't use `getPos` and therefore can't get the\n // parent blockContainer node.\n const blockID = this.editor.state.doc.resolve(getPos()).node().attrs.id;\n const label = \"label-\" + blockID;\n checkbox.setAttribute(\"aria-labelledby\", label);\n contentDOM.id = label;\n }\n\n dom.removeChild(contentDOM);\n dom.appendChild(wrapper);\n wrapper.appendChild(checkboxWrapper);\n wrapper.appendChild(contentDOM);\n checkboxWrapper.appendChild(checkbox);\n\n return {\n dom,\n contentDOM,\n destroy: () => {\n checkbox.removeEventListener(\"change\", changeHandler);\n },\n };\n };\n },\n});\n\nexport const CheckListItem = createBlockSpecFromStronglyTypedTiptapNode(\n checkListItemBlockContent,\n checkListItemPropSchema,\n);\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { getBlockInfo } from \"../../../api/getBlockInfoFromPos.js\";\n\n// ProseMirror Plugin which automatically assigns indices to ordered list items per nesting level.\nconst PLUGIN_KEY = new PluginKey(`numbered-list-indexing`);\nexport const NumberedListIndexingPlugin = () => {\n return new Plugin({\n key: PLUGIN_KEY,\n appendTransaction: (_transactions, _oldState, newState) => {\n const tr = newState.tr;\n tr.setMeta(\"numberedListIndexing\", true);\n\n let modified = false;\n\n // Traverses each node the doc using DFS, so blocks which are on the same nesting level will be traversed in the\n // same order they appear. This means the index of each list item block can be calculated by incrementing the\n // index of the previous list item block.\n newState.doc.descendants((node, pos) => {\n if (\n node.type.name === \"blockContainer\" &&\n node.firstChild!.type.name === \"numberedListItem\"\n ) {\n let newIndex = `${node.firstChild!.attrs[\"start\"] || 1}`;\n\n const blockInfo = getBlockInfo({\n posBeforeNode: pos,\n node,\n });\n\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n\n // Checks if this block is the start of a new ordered list, i.e. if it's the first block in the document, the\n // first block in its nesting level, or the previous block is not an ordered list item.\n\n const prevBlock = tr.doc.resolve(\n blockInfo.bnBlock.beforePos,\n ).nodeBefore;\n\n if (prevBlock) {\n const prevBlockInfo = getBlockInfo({\n posBeforeNode: blockInfo.bnBlock.beforePos - prevBlock.nodeSize,\n node: prevBlock,\n });\n\n const isPrevBlockOrderedListItem =\n prevBlockInfo.blockNoteType === \"numberedListItem\";\n\n if (isPrevBlockOrderedListItem) {\n if (!prevBlockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n const prevBlockIndex =\n prevBlockInfo.blockContent.node.attrs[\"index\"];\n\n newIndex = (parseInt(prevBlockIndex) + 1).toString();\n }\n }\n\n const contentNode = blockInfo.blockContent.node;\n const index = contentNode.attrs[\"index\"];\n const isFirst =\n prevBlock?.firstChild?.type.name !== \"numberedListItem\";\n\n if (index !== newIndex || (contentNode.attrs.start && !isFirst)) {\n modified = true;\n\n const { start, ...attrs } = contentNode.attrs;\n\n tr.setNodeMarkup(blockInfo.blockContent.beforePos, undefined, {\n ...attrs,\n index: newIndex,\n ...(typeof start === \"number\" &&\n isFirst && {\n start,\n }),\n });\n }\n }\n });\n\n return modified ? tr : null;\n },\n });\n};\n","import { InputRule } from \"@tiptap/core\";\nimport { updateBlockCommand } from \"../../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../../api/getBlockInfoFromPos.js\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n propsToAttributes,\n} from \"../../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../../defaultProps.js\";\nimport { getListItemContent } from \"../getListItemContent.js\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts.js\";\nimport { NumberedListIndexingPlugin } from \"./NumberedListIndexingPlugin.js\";\n\nexport const numberedListItemPropSchema = {\n ...defaultProps,\n start: { default: undefined, type: \"number\" },\n} satisfies PropSchema;\n\nconst NumberedListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"numberedListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n priority: 90,\n addAttributes() {\n return {\n ...propsToAttributes(numberedListItemPropSchema),\n // the index attribute is only used internally (it's not part of the blocknote schema)\n // that's why it's defined explicitly here, and not part of the prop schema\n index: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-index\"),\n renderHTML: (attributes) => {\n return {\n \"data-index\": attributes.index,\n };\n },\n },\n };\n },\n\n addInputRules() {\n return [\n // Creates an ordered list when starting with \"1.\".\n new InputRule({\n find: new RegExp(`^(\\\\d+)\\\\.\\\\s$`),\n handler: ({ state, chain, range, match }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\" ||\n blockInfo.blockNoteType === \"numberedListItem\"\n ) {\n return;\n }\n const startIndex = parseInt(match[1]);\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"numberedListItem\",\n props:\n (startIndex === 1 && {}) ||\n ({\n start: startIndex,\n } as any),\n }),\n )\n // Removes the \"1.\" characters used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.options.editor),\n \"Mod-Shift-7\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"numberedListItem\",\n props: {},\n }),\n );\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [NumberedListIndexingPlugin()];\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"OL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement?.tagName === \"OL\")\n ) {\n const startIndex =\n parseInt(parent.getAttribute(\"start\") || \"1\") || 1;\n\n if (element.previousSibling || startIndex === 1) {\n return {};\n }\n\n return {\n start: startIndex,\n };\n }\n\n return false;\n },\n // As `li` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n getListItemContent(node, schema, this.name),\n priority: 300,\n node: \"numberedListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n // We use a <p> tag, because for <li> tags we'd need an <ol> element to\n // put them in to be semantically correct, which we can't have due to the\n // schema.\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const NumberedListItem = createBlockSpecFromStronglyTypedTiptapNode(\n NumberedListItemBlockContent,\n numberedListItemPropSchema,\n);\n","import { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../api/getBlockInfoFromPos.js\";\nimport {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../defaultProps.js\";\n\nexport const paragraphPropSchema = {\n ...defaultProps,\n};\n\nexport const ParagraphBlockContent = createStronglyTypedTiptapNode({\n name: \"paragraph\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Alt-0\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"paragraph\",\n props: {},\n }),\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"p\",\n getAttrs: (element) => {\n if (typeof element === \"string\" || !element.textContent?.trim()) {\n return false;\n }\n\n return {};\n },\n node: \"paragraph\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const Paragraph = createBlockSpecFromStronglyTypedTiptapNode(\n ParagraphBlockContent,\n paragraphPropSchema,\n);\n","import {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema/index.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { getBlockInfoFromSelection } from \"../../api/getBlockInfoFromPos.js\";\nimport { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { InputRule } from \"@tiptap/core\";\n\nexport const quotePropSchema = {\n ...defaultProps,\n};\n\nexport const QuoteBlockContent = createStronglyTypedTiptapNode({\n name: \"quote\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addInputRules() {\n return [\n // Creates a block quote when starting with \">\".\n new InputRule({\n find: new RegExp(`^>\\\\s$`),\n handler: ({ state, chain, range }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return;\n }\n\n chain()\n .command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"quote\",\n props: {},\n }),\n )\n // Removes the \">\" character used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Alt-q\": () => {\n const blockInfo = getBlockInfoFromSelection(this.editor.state);\n if (\n !blockInfo.isBlockContainer ||\n blockInfo.blockContent.node.type.spec.content !== \"inline*\"\n ) {\n return true;\n }\n\n return this.editor.commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"quote\",\n }),\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Parse from internal HTML.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n contentElement: \".bn-inline-content\",\n },\n // Parse from external HTML.\n {\n tag: \"blockquote\",\n node: \"quote\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"blockquote\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n});\n\nexport const Quote = createBlockSpecFromStronglyTypedTiptapNode(\n QuoteBlockContent,\n quotePropSchema,\n);\n","import { callOrReturn, Extension, getExtensionField } from \"@tiptap/core\";\nimport { columnResizing, goToNextCell, tableEditing } from \"prosemirror-tables\";\n\nexport const RESIZE_MIN_WIDTH = 35;\nexport const EMPTY_CELL_WIDTH = 120;\nexport const EMPTY_CELL_HEIGHT = 31;\n\nexport const TableExtension = Extension.create({\n name: \"BlockNoteTableExtension\",\n\n addProseMirrorPlugins: () => {\n return [\n columnResizing({\n cellMinWidth: RESIZE_MIN_WIDTH,\n defaultCellMinWidth: EMPTY_CELL_WIDTH,\n // We set this to null as we implement our own node view in the table\n // block content. This node view is the same as what's used by default,\n // but is wrapped in a `blockContent` HTML element.\n View: null,\n }),\n tableEditing(),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n // Makes enter create a new line within the cell.\n Enter: () => {\n if (\n this.editor.state.selection.empty &&\n this.editor.state.selection.$head.parent.type.name ===\n \"tableParagraph\"\n ) {\n this.editor.commands.insertContent({ type: \"hardBreak\" });\n\n return true;\n }\n\n return false;\n },\n // Ensures that backspace won't delete the table if the text cursor is at\n // the start of a cell and the selection is empty.\n Backspace: () => {\n const selection = this.editor.state.selection;\n const selectionIsEmpty = selection.empty;\n const selectionIsAtStartOfNode = selection.$head.parentOffset === 0;\n const selectionIsInTableParagraphNode =\n selection.$head.node().type.name === \"tableParagraph\";\n\n return (\n selectionIsEmpty &&\n selectionIsAtStartOfNode &&\n selectionIsInTableParagraphNode\n );\n },\n // Enables navigating cells using the tab key.\n Tab: () => {\n return this.editor.commands.command(({ state, dispatch, view }) =>\n goToNextCell(1)(state, dispatch, view),\n );\n },\n \"Shift-Tab\": () => {\n return this.editor.commands.command(({ state, dispatch, view }) =>\n goToNextCell(-1)(state, dispatch, view),\n );\n },\n };\n },\n\n extendNodeSchema(extension) {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n };\n\n return {\n tableRole: callOrReturn(\n getExtensionField(extension, \"tableRole\", context),\n ),\n };\n },\n});\n","import { Node, mergeAttributes } from \"@tiptap/core\";\nimport { TableCell } from \"@tiptap/extension-table-cell\";\nimport { TableHeader } from \"@tiptap/extension-table-header\";\nimport { DOMParser, Fragment, Node as PMNode, Schema } from \"prosemirror-model\";\nimport { TableView } from \"prosemirror-tables\";\nimport { NodeView } from \"prosemirror-view\";\nimport {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema/index.js\";\nimport { mergeCSSClasses } from \"../../util/browser.js\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { EMPTY_CELL_WIDTH, TableExtension } from \"./TableExtension.js\";\n\nexport const tablePropSchema = {\n textColor: defaultProps.textColor,\n};\n\nexport const TableBlockContent = createStronglyTypedTiptapNode({\n name: \"table\",\n content: \"tableRow+\",\n group: \"blockContent\",\n tableRole: \"table\",\n\n marks: \"deletion insertion modification\",\n isolating: true,\n\n parseHTML() {\n return [\n {\n tag: \"table\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"table\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {},\n );\n },\n\n // This node view is needed for the `columnResizing` plugin. By default, the\n // plugin adds its own node view, which overrides how the node is rendered vs\n // `renderHTML`. This means that the wrapping `blockContent` HTML element is\n // no longer rendered. The `columnResizing` plugin uses the `TableView` as its\n // default node view. `BlockNoteTableView` extends it by wrapping it in a\n // `blockContent` element, so the DOM structure is consistent with other block\n // types.\n addNodeView() {\n return ({ node, HTMLAttributes }) => {\n class BlockNoteTableView extends TableView {\n constructor(\n public node: PMNode,\n public cellMinWidth: number,\n public blockContentHTMLAttributes: Record<string, string>,\n ) {\n super(node, cellMinWidth);\n\n const blockContent = document.createElement(\"div\");\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n blockContentHTMLAttributes.class,\n );\n blockContent.setAttribute(\"data-content-type\", \"table\");\n for (const [attribute, value] of Object.entries(\n blockContentHTMLAttributes,\n )) {\n if (attribute !== \"class\") {\n blockContent.setAttribute(attribute, value);\n }\n }\n\n const tableWrapper = this.dom;\n\n const tableWrapperInner = document.createElement(\"div\");\n tableWrapperInner.className = \"tableWrapper-inner\";\n tableWrapperInner.appendChild(tableWrapper.firstChild!);\n\n tableWrapper.appendChild(tableWrapperInner);\n\n blockContent.appendChild(tableWrapper);\n const floatingContainer = document.createElement(\"div\");\n floatingContainer.className = \"table-widgets-container\";\n floatingContainer.style.position = \"relative\";\n tableWrapper.appendChild(floatingContainer);\n\n this.dom = blockContent;\n }\n\n ignoreMutation(record: MutationRecord): boolean {\n return (\n !(record.target as HTMLElement).closest(\".tableWrapper-inner\") ||\n super.ignoreMutation(record)\n );\n }\n }\n\n return new BlockNoteTableView(node, EMPTY_CELL_WIDTH, {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n }) as NodeView; // needs cast, tiptap types (wrongly) doesn't support return tableview here\n };\n },\n});\n\nconst TableParagraph = createStronglyTypedTiptapNode({\n name: \"tableParagraph\",\n group: \"tableContent\",\n content: \"inline*\",\n\n parseHTML() {\n return [\n {\n tag: \"p\",\n getAttrs: (element) => {\n if (typeof element === \"string\" || !element.textContent) {\n return false;\n }\n\n // Only parse in internal HTML.\n if (!element.closest(\"[data-content-type]\")) {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (parent.tagName === \"TD\" || parent.tagName === \"TH\") {\n return {};\n }\n\n return false;\n },\n node: \"tableParagraph\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"p\", HTMLAttributes, 0];\n },\n});\n\n/**\n * This extension allows you to create table rows.\n * @see https://www.tiptap.dev/api/nodes/table-row\n */\nexport const TableRow = Node.create<{ HTMLAttributes: Record<string, any> }>({\n name: \"tableRow\",\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n content: \"(tableCell | tableHeader)+\",\n\n tableRole: \"row\",\n marks: \"deletion insertion modification\",\n parseHTML() {\n return [{ tag: \"tr\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"tr\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n 0,\n ];\n },\n});\n\n/*\n * This will flatten a node's content to fit into a table cell's paragraph.\n */\nfunction parseTableContent(node: HTMLElement, schema: Schema) {\n const parser = DOMParser.fromSchema(schema);\n\n // This will parse the content of the table paragraph as though it were a blockGroup.\n // Resulting in a structure like:\n // <blockGroup>\n // <blockContainer>\n // <p>Hello</p>\n // </blockContainer>\n // <blockContainer>\n // <p>Hello</p>\n // </blockContainer>\n // </blockGroup>\n const parsedContent = parser.parse(node, {\n topNode: schema.nodes.blockGroup.create(),\n });\n const extractedContent: PMNode[] = [];\n\n // Try to extract any content within the blockContainer.\n parsedContent.content.descendants((child) => {\n // As long as the child is an inline node, we can append it to the fragment.\n if (child.isInline) {\n // And append it to the fragment\n extractedContent.push(child);\n return false;\n }\n\n return undefined;\n });\n\n return Fragment.fromArray(extractedContent);\n}\n\nexport const Table = createBlockSpecFromStronglyTypedTiptapNode(\n TableBlockContent,\n tablePropSchema,\n [\n TableExtension,\n TableParagraph,\n TableHeader.extend({\n /**\n * We allow table headers and cells to have multiple tableContent nodes because\n * when merging cells, prosemirror-tables will concat the contents of the cells naively.\n * This would cause that content to overflow into other cells when prosemirror tries to enforce the cell structure.\n *\n * So, we manually fix this up when reading back in the `nodeToBlock` and only ever place a single tableContent back into the cell.\n */\n content: \"tableContent+\",\n parseHTML() {\n return [\n {\n tag: \"th\",\n // As `th` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n parseTableContent(node as HTMLElement, schema),\n },\n ];\n },\n }),\n TableCell.extend({\n content: \"tableContent+\",\n parseHTML() {\n return [\n {\n tag: \"td\",\n // As `td` elements can contain multiple paragraphs, we need to merge their contents\n // into a single one so that ProseMirror can parse everything correctly.\n getContent: (node, schema) =>\n parseTableContent(node as HTMLElement, schema),\n },\n ];\n },\n }),\n TableRow,\n ],\n);\n","export const parseVideoElement = (videoElement: HTMLVideoElement) => {\n const url = videoElement.src || undefined;\n const previewWidth = videoElement.width || undefined;\n\n return { url, previewWidth };\n};\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n createBlockSpec,\n FileBlockConfig,\n Props,\n PropSchema,\n} from \"../../schema/index.js\";\nimport { defaultProps } from \"../defaultProps.js\";\nimport { parseFigureElement } from \"../FileBlockContent/helpers/parse/parseFigureElement.js\";\nimport { createFigureWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.js\";\nimport { createLinkWithCaption } from \"../FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.js\";\nimport { createResizableFileBlockWrapper } from \"../FileBlockContent/helpers/render/createResizableFileBlockWrapper.js\";\nimport { parseVideoElement } from \"./parseVideoElement.js\";\n\nexport const FILE_VIDEO_ICON_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M2 3.9934C2 3.44476 2.45531 3 2.9918 3H21.0082C21.556 3 22 3.44495 22 3.9934V20.0066C22 20.5552 21.5447 21 21.0082 21H2.9918C2.44405 21 2 20.5551 2 20.0066V3.9934ZM8 5V19H16V5H8ZM4 5V7H6V5H4ZM18 5V7H20V5H18ZM4 9V11H6V9H4ZM18 9V11H20V9H18ZM4 13V15H6V13H4ZM18 13V15H20V13H18ZM4 17V19H6V17H4ZM18 17V19H20V17H18Z\"></path></svg>';\n\nexport const videoPropSchema = {\n textAlignment: defaultProps.textAlignment,\n backgroundColor: defaultProps.backgroundColor,\n // File name.\n name: {\n default: \"\" as const,\n },\n // File url.\n url: {\n default: \"\" as const,\n },\n // File caption.\n caption: {\n default: \"\" as const,\n },\n\n showPreview: {\n default: true,\n },\n // File preview width in px.\n previewWidth: {\n default: undefined,\n type: \"number\",\n },\n} satisfies PropSchema;\n\nexport const videoBlockConfig = {\n type: \"video\" as const,\n propSchema: videoPropSchema,\n content: \"none\",\n isFileBlock: true,\n fileBlockAccept: [\"video/*\"],\n} satisfies FileBlockConfig;\n\nexport const videoRender = (\n block: BlockFromConfig<typeof videoBlockConfig, any, any>,\n editor: BlockNoteEditor<any, any, any>,\n) => {\n const icon = document.createElement(\"div\");\n icon.innerHTML = FILE_VIDEO_ICON_SVG;\n\n const videoWrapper = document.createElement(\"div\");\n videoWrapper.className = \"bn-visual-media-wrapper\";\n\n const video = document.createElement(\"video\");\n video.className = \"bn-visual-media\";\n if (editor.resolveFileUrl) {\n editor.resolveFileUrl(block.props.url).then((downloadUrl) => {\n video.src = downloadUrl;\n });\n } else {\n video.src = block.props.url;\n }\n video.controls = true;\n video.contentEditable = \"false\";\n video.draggable = false;\n video.width = block.props.previewWidth;\n videoWrapper.appendChild(video);\n\n return createResizableFileBlockWrapper(\n block,\n editor,\n { dom: videoWrapper },\n videoWrapper,\n editor.dictionary.file_blocks.video.add_button_text,\n icon.firstElementChild as HTMLElement,\n );\n};\n\nexport const videoParse = (\n element: HTMLElement,\n): Partial<Props<typeof videoBlockConfig.propSchema>> | undefined => {\n if (element.tagName === \"VIDEO\") {\n // Ignore if parent figure has already been parsed.\n if (element.closest(\"figure\")) {\n return undefined;\n }\n\n return parseVideoElement(element as HTMLVideoElement);\n }\n\n if (element.tagName === \"FIGURE\") {\n const parsedFigure = parseFigureElement(element, \"video\");\n if (!parsedFigure) {\n return undefined;\n }\n\n const { targetElement, caption } = parsedFigure;\n\n return {\n ...parseVideoElement(targetElement as HTMLVideoElement),\n caption,\n };\n }\n\n return undefined;\n};\n\nexport const videoToExternalHTML = (\n block: BlockFromConfig<typeof videoBlockConfig, any, any>,\n) => {\n if (!block.props.url) {\n const div = document.createElement(\"p\");\n div.textContent = \"Add video\";\n\n return {\n dom: div,\n };\n }\n\n let video;\n if (block.props.showPreview) {\n video = document.createElement(\"video\");\n video.src = block.props.url;\n if (block.props.previewWidth) {\n video.width = block.props.previewWidth;\n }\n } else {\n video = document.createElement(\"a\");\n video.href = block.props.url;\n video.textContent = block.props.name || block.props.url;\n }\n\n if (block.props.caption) {\n if (block.props.showPreview) {\n return createFigureWithCaption(video, block.props.caption);\n } else {\n return createLinkWithCaption(video, block.props.caption);\n }\n }\n\n return {\n dom: video,\n };\n};\n\nexport const VideoBlock = createBlockSpec(videoBlockConfig, {\n render: videoRender,\n parse: videoParse,\n toExternalHTML: videoToExternalHTML,\n});\n","import Bold from \"@tiptap/extension-bold\";\nimport Code from \"@tiptap/extension-code\";\nimport Italic from \"@tiptap/extension-italic\";\nimport Strike from \"@tiptap/extension-strike\";\nimport Underline from \"@tiptap/extension-underline\";\nimport { BackgroundColor } from \"../extensions/BackgroundColor/BackgroundColorMark.js\";\nimport { TextColor } from \"../extensions/TextColor/TextColorMark.js\";\nimport {\n BlockNoDefaults,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n PartialBlockNoDefaults,\n StyleSchema,\n StyleSpecs,\n createStyleSpecFromTipTapMark,\n getBlockSchemaFromSpecs,\n getInlineContentSchemaFromSpecs,\n getStyleSchemaFromSpecs,\n} from \"../schema/index.js\";\n\nimport { AudioBlock } from \"./AudioBlockContent/AudioBlockContent.js\";\nimport { CodeBlock } from \"./CodeBlockContent/CodeBlockContent.js\";\nimport { FileBlock } from \"./FileBlockContent/FileBlockContent.js\";\nimport { Heading } from \"./HeadingBlockContent/HeadingBlockContent.js\";\nimport { ImageBlock } from \"./ImageBlockContent/ImageBlockContent.js\";\nimport { BulletListItem } from \"./ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.js\";\nimport { CheckListItem } from \"./ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.js\";\nimport { NumberedListItem } from \"./ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.js\";\nimport { Paragraph } from \"./ParagraphBlockContent/ParagraphBlockContent.js\";\nimport { Quote } from \"./QuoteBlockContent/QuoteBlockContent.js\";\nimport { Table } from \"./TableBlockContent/TableBlockContent.js\";\nimport { VideoBlock } from \"./VideoBlockContent/VideoBlockContent.js\";\n\nexport const defaultBlockSpecs = {\n paragraph: Paragraph,\n heading: Heading,\n quote: Quote,\n codeBlock: CodeBlock,\n bulletListItem: BulletListItem,\n numberedListItem: NumberedListItem,\n checkListItem: CheckListItem,\n table: Table,\n file: FileBlock,\n image: ImageBlock,\n video: VideoBlock,\n audio: AudioBlock,\n} satisfies BlockSpecs;\n\nexport const defaultBlockSchema = getBlockSchemaFromSpecs(defaultBlockSpecs);\n\n// underscore is used that in case a user overrides DefaultBlockSchema,\n// they can still access the original default block schema\nexport type _DefaultBlockSchema = typeof defaultBlockSchema;\nexport type DefaultBlockSchema = _DefaultBlockSchema;\n\nexport const defaultStyleSpecs = {\n bold: createStyleSpecFromTipTapMark(Bold, \"boolean\"),\n italic: createStyleSpecFromTipTapMark(Italic, \"boolean\"),\n underline: createStyleSpecFromTipTapMark(Underline, \"boolean\"),\n strike: createStyleSpecFromTipTapMark(Strike, \"boolean\"),\n code: createStyleSpecFromTipTapMark(Code, \"boolean\"),\n textColor: TextColor,\n backgroundColor: BackgroundColor,\n} satisfies StyleSpecs;\n\nexport const defaultStyleSchema = getStyleSchemaFromSpecs(defaultStyleSpecs);\n\n// underscore is used that in case a user overrides DefaultStyleSchema,\n// they can still access the original default style schema\nexport type _DefaultStyleSchema = typeof defaultStyleSchema;\nexport type DefaultStyleSchema = _DefaultStyleSchema;\n\nexport const defaultInlineContentSpecs = {\n text: { config: \"text\", implementation: {} as any },\n link: { config: \"link\", implementation: {} as any },\n} satisfies InlineContentSpecs;\n\nexport const defaultInlineContentSchema = getInlineContentSchemaFromSpecs(\n defaultInlineContentSpecs,\n);\n\n// underscore is used that in case a user overrides DefaultInlineContentSchema,\n// they can still access the original default inline content schema\nexport type _DefaultInlineContentSchema = typeof defaultInlineContentSchema;\nexport type DefaultInlineContentSchema = _DefaultInlineContentSchema;\n\nexport type PartialBlock<\n BSchema extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema,\n> = PartialBlockNoDefaults<BSchema, I, S>;\n\nexport type Block<\n BSchema extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema,\n> = BlockNoDefaults<BSchema, I, S>;\n","import { CellSelection } from \"prosemirror-tables\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport {\n BlockFromConfig,\n BlockSchema,\n FileBlockConfig,\n InlineContentSchema,\n StyleSchema,\n} from \"../schema/index.js\";\nimport {\n Block,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n defaultBlockSchema,\n defaultInlineContentSchema,\n} from \"./defaultBlocks.js\";\nimport { defaultProps } from \"./defaultProps.js\";\nimport { Selection } from \"prosemirror-state\";\n\nexport function checkDefaultBlockTypeInSchema<\n BlockType extends keyof DefaultBlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockType: BlockType,\n editor: BlockNoteEditor<any, I, S>,\n): editor is BlockNoteEditor<{ Type: DefaultBlockSchema[BlockType] }, I, S> {\n return (\n blockType in editor.schema.blockSchema &&\n editor.schema.blockSchema[blockType] === defaultBlockSchema[blockType]\n );\n}\n\nexport function checkDefaultInlineContentTypeInSchema<\n InlineContentType extends keyof DefaultInlineContentSchema,\n B extends BlockSchema,\n S extends StyleSchema,\n>(\n inlineContentType: InlineContentType,\n editor: BlockNoteEditor<B, any, S>,\n): editor is BlockNoteEditor<\n B,\n { Type: DefaultInlineContentSchema[InlineContentType] },\n S\n> {\n return (\n inlineContentType in editor.schema.inlineContentSchema &&\n editor.schema.inlineContentSchema[inlineContentType] ===\n defaultInlineContentSchema[inlineContentType]\n );\n}\n\nexport function checkBlockIsDefaultType<\n BlockType extends keyof DefaultBlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockType: BlockType,\n block: Block<any, I, S>,\n editor: BlockNoteEditor<any, I, S>,\n): block is BlockFromConfig<DefaultBlockSchema[BlockType], I, S> {\n return (\n block.type === blockType &&\n block.type in editor.schema.blockSchema &&\n checkDefaultBlockTypeInSchema(block.type, editor)\n );\n}\n\nexport function checkBlockIsFileBlock<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n block: Block<any, I, S>,\n editor: BlockNoteEditor<B, I, S>,\n): block is BlockFromConfig<FileBlockConfig, I, S> {\n return (\n (block.type in editor.schema.blockSchema &&\n editor.schema.blockSchema[block.type].isFileBlock) ||\n false\n );\n}\n\nexport function checkBlockIsFileBlockWithPreview<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n block: Block<any, I, S>,\n editor: BlockNoteEditor<B, I, S>,\n): block is BlockFromConfig<\n FileBlockConfig & {\n propSchema: Required<FileBlockConfig[\"propSchema\"]>;\n },\n I,\n S\n> {\n return (\n (block.type in editor.schema.blockSchema &&\n editor.schema.blockSchema[block.type].isFileBlock &&\n \"showPreview\" in editor.schema.blockSchema[block.type].propSchema) ||\n false\n );\n}\n\nexport function checkBlockIsFileBlockWithPlaceholder<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(block: Block<B, I, S>, editor: BlockNoteEditor<B, I, S>) {\n const config = editor.schema.blockSchema[block.type];\n return config.isFileBlock && !block.props.url;\n}\n\nexport function checkBlockTypeHasDefaultProp<\n Prop extends keyof typeof defaultProps,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n prop: Prop,\n blockType: string,\n editor: BlockNoteEditor<any, I, S>,\n): editor is BlockNoteEditor<\n {\n [BT in string]: {\n type: BT;\n propSchema: {\n [P in Prop]: (typeof defaultProps)[P];\n };\n content: \"table\" | \"inline\" | \"none\";\n };\n },\n I,\n S\n> {\n return (\n blockType in editor.schema.blockSchema &&\n prop in editor.schema.blockSchema[blockType].propSchema &&\n editor.schema.blockSchema[blockType].propSchema[prop] === defaultProps[prop]\n );\n}\n\nexport function checkBlockHasDefaultProp<\n Prop extends keyof typeof defaultProps,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n prop: Prop,\n block: Block<any, I, S>,\n editor: BlockNoteEditor<any, I, S>,\n): block is BlockFromConfig<\n {\n type: string;\n propSchema: {\n [P in Prop]: (typeof defaultProps)[P];\n };\n content: \"table\" | \"inline\" | \"none\";\n },\n I,\n S\n> {\n return checkBlockTypeHasDefaultProp(prop, block.type, editor);\n}\n\nexport function isTableCellSelection(\n selection: Selection,\n): selection is CellSelection {\n return selection instanceof CellSelection;\n}\n","/**\n * Uploads a file to tmpfiles.org and returns the URL to the uploaded file.\n *\n * @warning This function should only be used for development purposes, replace with your own backend!\n */\nexport const uploadToTmpFilesDotOrg_DEV_ONLY = async (\n file: File,\n): Promise<string> => {\n const body = new FormData();\n body.append(\"file\", file);\n\n const ret = await fetch(\"https://tmpfiles.org/api/v1/upload\", {\n method: \"POST\",\n body: body,\n });\n return (await ret.json()).data.url.replace(\n \"tmpfiles.org/\",\n \"tmpfiles.org/dl/\",\n );\n};\n","import { Block, PartialBlock } from \"../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\n\nimport { checkDefaultBlockTypeInSchema } from \"../../blocks/defaultBlockTypeGuards.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n isStyledTextInlineContent,\n} from \"../../schema/index.js\";\nimport { formatKeyboardShortcut } from \"../../util/browser.js\";\nimport { DefaultSuggestionItem } from \"./DefaultSuggestionItem.js\";\n\n// Sets the editor's text cursor position to the next content editable block,\n// so either a block with inline content or a table. The last block is always a\n// paragraph, so this function won't try to set the cursor position past the\n// last block.\nfunction setSelectionToNextContentEditableBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n let block: Block<BSchema, I, S> | undefined =\n editor.getTextCursorPosition().block;\n let contentType = editor.schema.blockSchema[block.type].content;\n\n while (contentType === \"none\") {\n block = editor.getTextCursorPosition().nextBlock;\n if (block === undefined) {\n return;\n }\n contentType = editor.schema.blockSchema[block.type].content as\n | \"inline\"\n | \"table\"\n | \"none\";\n editor.setTextCursorPosition(block, \"end\");\n }\n}\n\n// Checks if the current block is empty or only contains a slash, and if so,\n// updates the current block instead of inserting a new one below. If the new\n// block doesn't contain editable content, the cursor is moved to the next block\n// that does.\nexport function insertOrUpdateBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n block: PartialBlock<BSchema, I, S>,\n): Block<BSchema, I, S> {\n const currentBlock = editor.getTextCursorPosition().block;\n\n if (currentBlock.content === undefined) {\n throw new Error(\"Slash Menu open in a block that doesn't contain content.\");\n }\n\n let newBlock: Block<BSchema, I, S>;\n\n if (\n Array.isArray(currentBlock.content) &&\n ((currentBlock.content.length === 1 &&\n isStyledTextInlineContent(currentBlock.content[0]) &&\n currentBlock.content[0].type === \"text\" &&\n currentBlock.content[0].text === \"/\") ||\n currentBlock.content.length === 0)\n ) {\n newBlock = editor.updateBlock(currentBlock, block);\n // We make sure to reset the cursor position to the new block as calling\n // `updateBlock` may move it out. This generally happens when the content\n // changes, or the update makes the block multi-column.\n editor.setTextCursorPosition(newBlock);\n } else {\n newBlock = editor.insertBlocks([block], currentBlock, \"after\")[0];\n editor.setTextCursorPosition(editor.getTextCursorPosition().nextBlock!);\n }\n\n setSelectionToNextContentEditableBlock(editor);\n\n return newBlock;\n}\n\nexport function getDefaultSlashMenuItems<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n const items: DefaultSuggestionItem[] = [];\n\n if (checkDefaultBlockTypeInSchema(\"heading\", editor)) {\n items.push(\n {\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 1 },\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-1\"),\n key: \"heading\",\n ...editor.dictionary.slash_menu.heading,\n },\n {\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 2 },\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-2\"),\n key: \"heading_2\",\n ...editor.dictionary.slash_menu.heading_2,\n },\n {\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 3 },\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-3\"),\n key: \"heading_3\",\n ...editor.dictionary.slash_menu.heading_3,\n },\n );\n }\n\n if (checkDefaultBlockTypeInSchema(\"quote\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"quote\",\n });\n },\n key: \"quote\",\n ...editor.dictionary.slash_menu.quote,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"numberedListItem\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"numberedListItem\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Shift-7\"),\n key: \"numbered_list\",\n ...editor.dictionary.slash_menu.numbered_list,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"bulletListItem\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"bulletListItem\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Shift-8\"),\n key: \"bullet_list\",\n ...editor.dictionary.slash_menu.bullet_list,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"checkListItem\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"checkListItem\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Shift-9\"),\n key: \"check_list\",\n ...editor.dictionary.slash_menu.check_list,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"paragraph\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"paragraph\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-0\"),\n key: \"paragraph\",\n ...editor.dictionary.slash_menu.paragraph,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"codeBlock\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"codeBlock\",\n });\n },\n badge: formatKeyboardShortcut(\"Mod-Alt-c\"),\n key: \"code_block\",\n ...editor.dictionary.slash_menu.code_block,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"table\", editor)) {\n items.push({\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"table\",\n content: {\n type: \"tableContent\",\n rows: [\n {\n cells: [\"\", \"\", \"\"],\n },\n {\n cells: [\"\", \"\", \"\"],\n },\n ],\n },\n });\n },\n badge: undefined,\n key: \"table\",\n ...editor.dictionary.slash_menu.table,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"image\", editor)) {\n items.push({\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"image\",\n });\n\n // Immediately open the file toolbar\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: insertedBlock,\n }),\n );\n },\n key: \"image\",\n ...editor.dictionary.slash_menu.image,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"video\", editor)) {\n items.push({\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"video\",\n });\n\n // Immediately open the file toolbar\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: insertedBlock,\n }),\n );\n },\n key: \"video\",\n ...editor.dictionary.slash_menu.video,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"audio\", editor)) {\n items.push({\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"audio\",\n });\n\n // Immediately open the file toolbar\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: insertedBlock,\n }),\n );\n },\n key: \"audio\",\n ...editor.dictionary.slash_menu.audio,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"file\", editor)) {\n items.push({\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"file\",\n });\n\n // Immediately open the file toolbar\n editor.transact((tr) =>\n tr.setMeta(editor.filePanel!.plugins[0], {\n block: insertedBlock,\n }),\n );\n },\n key: \"file\",\n ...editor.dictionary.slash_menu.file,\n });\n }\n\n items.push({\n onItemClick: () => {\n editor.openSuggestionMenu(\":\", {\n deleteTriggerCharacter: true,\n ignoreQueryLength: true,\n });\n },\n key: \"emoji\",\n ...editor.dictionary.slash_menu.emoji,\n });\n\n return items;\n}\n\nexport function filterSuggestionItems<\n T extends { title: string; aliases?: readonly string[] },\n>(items: T[], query: string) {\n return items.filter(\n ({ title, aliases }) =>\n title.toLowerCase().includes(query.toLowerCase()) ||\n (aliases &&\n aliases.filter((alias) =>\n alias.toLowerCase().includes(query.toLowerCase()),\n ).length !== 0),\n );\n}\n","import {\n defaultBlockSpecs,\n defaultInlineContentSpecs,\n defaultStyleSpecs,\n} from \"../blocks/defaultBlocks.js\";\nimport type {\n BlockNoDefaults,\n PartialBlockNoDefaults,\n} from \"../schema/blocks/types.js\";\nimport {\n BlockSchema,\n BlockSchemaFromSpecs,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSchemaFromSpecs,\n InlineContentSpecs,\n StyleSchema,\n StyleSchemaFromSpecs,\n StyleSpecs,\n getBlockSchemaFromSpecs,\n getInlineContentSchemaFromSpecs,\n getStyleSchemaFromSpecs,\n} from \"../schema/index.js\";\nimport type { BlockNoteEditor } from \"./BlockNoteEditor.js\";\n\nfunction removeUndefined<T extends Record<string, any> | undefined>(obj: T): T {\n if (!obj) {\n return obj;\n }\n return Object.fromEntries(\n Object.entries(obj).filter(([, value]) => value !== undefined),\n ) as T;\n}\n\nexport class BlockNoteSchema<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema,\n> {\n public readonly blockSpecs: BlockSpecs;\n public readonly inlineContentSpecs: InlineContentSpecs;\n public readonly styleSpecs: StyleSpecs;\n\n public readonly blockSchema: BSchema;\n public readonly inlineContentSchema: ISchema;\n public readonly styleSchema: SSchema;\n\n // Helper so that you can use typeof schema.BlockNoteEditor\n public readonly BlockNoteEditor: BlockNoteEditor<BSchema, ISchema, SSchema> =\n \"only for types\" as any;\n\n public readonly Block: BlockNoDefaults<BSchema, ISchema, SSchema> =\n \"only for types\" as any;\n\n public readonly PartialBlock: PartialBlockNoDefaults<\n BSchema,\n ISchema,\n SSchema\n > = \"only for types\" as any;\n\n public static create<\n BSpecs extends BlockSpecs = typeof defaultBlockSpecs,\n ISpecs extends InlineContentSpecs = typeof defaultInlineContentSpecs,\n SSpecs extends StyleSpecs = typeof defaultStyleSpecs,\n >(options?: {\n /**\n * A list of custom block types that should be available in the editor.\n */\n blockSpecs?: BSpecs;\n /**\n * A list of custom InlineContent types that should be available in the editor.\n */\n inlineContentSpecs?: ISpecs;\n /**\n * A list of custom Styles that should be available in the editor.\n */\n styleSpecs?: SSpecs;\n }) {\n return new BlockNoteSchema<\n BlockSchemaFromSpecs<BSpecs>,\n InlineContentSchemaFromSpecs<ISpecs>,\n StyleSchemaFromSpecs<SSpecs>\n >(options);\n // as BlockNoteSchema<\n // BlockSchemaFromSpecs<BSpecs>,\n // InlineContentSchemaFromSpecs<ISpecs>,\n // StyleSchemaFromSpecs<SSpecs>\n // >;\n }\n\n constructor(opts?: {\n blockSpecs?: BlockSpecs;\n inlineContentSpecs?: InlineContentSpecs;\n styleSpecs?: StyleSpecs;\n }) {\n this.blockSpecs = removeUndefined(opts?.blockSpecs) || defaultBlockSpecs;\n this.inlineContentSpecs =\n removeUndefined(opts?.inlineContentSpecs) || defaultInlineContentSpecs;\n this.styleSpecs = removeUndefined(opts?.styleSpecs) || defaultStyleSpecs;\n\n this.blockSchema = getBlockSchemaFromSpecs(this.blockSpecs) as any;\n this.inlineContentSchema = getInlineContentSchemaFromSpecs(\n this.inlineContentSpecs,\n ) as any;\n this.styleSchema = getStyleSchemaFromSpecs(this.styleSpecs) as any;\n }\n}\n","import {\n createBlockSpec,\n CustomBlockConfig,\n Props,\n} from \"../../schema/index.js\";\n\nexport const pageBreakConfig = {\n type: \"pageBreak\" as const,\n propSchema: {},\n content: \"none\",\n isFileBlock: false,\n isSelectable: false,\n} satisfies CustomBlockConfig;\nexport const pageBreakRender = () => {\n const pageBreak = document.createElement(\"div\");\n\n pageBreak.className = \"bn-page-break\";\n pageBreak.setAttribute(\"data-page-break\", \"\");\n\n return {\n dom: pageBreak,\n };\n};\nexport const pageBreakParse = (\n element: HTMLElement,\n): Partial<Props<typeof pageBreakConfig.propSchema>> | undefined => {\n if (element.tagName === \"DIV\" && element.hasAttribute(\"data-page-break\")) {\n return {\n type: \"pageBreak\",\n };\n }\n\n return undefined;\n};\nexport const pageBreakToExternalHTML = () => {\n const pageBreak = document.createElement(\"div\");\n\n pageBreak.setAttribute(\"data-page-break\", \"\");\n\n return {\n dom: pageBreak,\n };\n};\n\nexport const PageBreak = createBlockSpec(pageBreakConfig, {\n render: pageBreakRender,\n parse: pageBreakParse,\n toExternalHTML: pageBreakToExternalHTML,\n});\n","import { BlockNoteSchema } from \"../../editor/BlockNoteSchema.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { PageBreak } from \"./PageBreakBlockContent.js\";\n\nexport const pageBreakSchema = BlockNoteSchema.create({\n blockSpecs: {\n pageBreak: PageBreak,\n },\n});\n\n/**\n * Adds page break support to the given schema.\n */\nexport const withPageBreak = <\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n schema: BlockNoteSchema<B, I, S>,\n) => {\n return BlockNoteSchema.create({\n blockSpecs: {\n ...schema.blockSpecs,\n ...pageBreakSchema.blockSpecs,\n },\n inlineContentSpecs: schema.inlineContentSpecs,\n styleSpecs: schema.styleSpecs,\n }) as any as BlockNoteSchema<\n // typescript needs some help here\n B & {\n pageBreak: typeof PageBreak.config;\n },\n I,\n S\n >;\n};\n","import { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { DefaultSuggestionItem } from \"../../extensions/SuggestionMenu/DefaultSuggestionItem.js\";\nimport { insertOrUpdateBlock } from \"../../extensions/SuggestionMenu/getDefaultSlashMenuItems.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { pageBreakSchema } from \"./schema.js\";\n\nexport function checkPageBreakBlocksInSchema<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<any, I, S>,\n): editor is BlockNoteEditor<typeof pageBreakSchema.blockSchema, I, S> {\n return (\n \"pageBreak\" in editor.schema.blockSchema &&\n editor.schema.blockSchema[\"pageBreak\"] ===\n pageBreakSchema.blockSchema[\"pageBreak\"]\n );\n}\n\nexport function getPageBreakSlashMenuItems<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n const items: (Omit<DefaultSuggestionItem, \"key\"> & { key: \"page_break\" })[] =\n [];\n\n if (checkPageBreakBlocksInSchema(editor)) {\n items.push({\n ...editor.dictionary.slash_menu.page_break,\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"pageBreak\",\n });\n },\n key: \"page_break\",\n });\n }\n\n return items;\n}\n","import {\n NodeSelection,\n Selection,\n TextSelection,\n Transaction,\n} from \"prosemirror-state\";\nimport { CellSelection } from \"prosemirror-tables\";\n\nimport { Block } from \"../../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor\";\nimport { BlockIdentifier } from \"../../../../schema/index.js\";\nimport { getNearestBlockPos } from \"../../../getBlockInfoFromPos.js\";\nimport { getNodeById } from \"../../../nodeUtil.js\";\n\ntype BlockSelectionData = (\n | {\n type: \"text\";\n headBlockId: string;\n anchorOffset: number;\n headOffset: number;\n }\n | {\n type: \"node\";\n }\n | {\n type: \"cell\";\n anchorCellOffset: number;\n headCellOffset: number;\n }\n) & {\n anchorBlockId: string;\n};\n\n/**\n * `getBlockSelectionData` and `updateBlockSelectionFromData` are used to save\n * and restore the selection within a block, when the block is moved. This is\n * done by first saving the offsets of the anchor and head from the before\n * positions of their surrounding blocks, as well as the IDs of those blocks. We\n * can then recreate the selection by finding the blocks with those IDs, getting\n * their before positions, and adding the offsets to those positions.\n * @param editor The BlockNote editor instance to get the selection data from.\n */\nfunction getBlockSelectionData(\n editor: BlockNoteEditor<any, any, any>,\n): BlockSelectionData {\n return editor.transact((tr) => {\n const anchorBlockPosInfo = getNearestBlockPos(tr.doc, tr.selection.anchor);\n\n if (tr.selection instanceof CellSelection) {\n return {\n type: \"cell\" as const,\n anchorBlockId: anchorBlockPosInfo.node.attrs.id,\n anchorCellOffset:\n tr.selection.$anchorCell.pos - anchorBlockPosInfo.posBeforeNode,\n headCellOffset:\n tr.selection.$headCell.pos - anchorBlockPosInfo.posBeforeNode,\n };\n } else if (tr.selection instanceof NodeSelection) {\n return {\n type: \"node\" as const,\n anchorBlockId: anchorBlockPosInfo.node.attrs.id,\n };\n } else {\n const headBlockPosInfo = getNearestBlockPos(tr.doc, tr.selection.head);\n\n return {\n type: \"text\" as const,\n anchorBlockId: anchorBlockPosInfo.node.attrs.id,\n headBlockId: headBlockPosInfo.node.attrs.id,\n anchorOffset: tr.selection.anchor - anchorBlockPosInfo.posBeforeNode,\n headOffset: tr.selection.head - headBlockPosInfo.posBeforeNode,\n };\n }\n });\n}\n\n/**\n * `getBlockSelectionData` and `updateBlockSelectionFromData` are used to save\n * and restore the selection within a block, when the block is moved. This is\n * done by first saving the offsets of the anchor and head from the before\n * positions of their surrounding blocks, as well as the IDs of those blocks. We\n * can then recreate the selection by finding the blocks with those IDs, getting\n * their before positions, and adding the offsets to those positions.\n * @param tr The transaction to update the selection in.\n * @param data The selection data to update the selection with (generated by\n * `getBlockSelectionData`).\n */\nfunction updateBlockSelectionFromData(\n tr: Transaction,\n data: BlockSelectionData,\n) {\n const anchorBlockPos = getNodeById(data.anchorBlockId, tr.doc)?.posBeforeNode;\n if (anchorBlockPos === undefined) {\n throw new Error(\n `Could not find block with ID ${data.anchorBlockId} to update selection`,\n );\n }\n\n let selection: Selection;\n if (data.type === \"cell\") {\n selection = CellSelection.create(\n tr.doc,\n anchorBlockPos + data.anchorCellOffset,\n anchorBlockPos + data.headCellOffset,\n );\n } else if (data.type === \"node\") {\n selection = NodeSelection.create(tr.doc, anchorBlockPos + 1);\n } else {\n const headBlockPos = getNodeById(data.headBlockId, tr.doc)?.posBeforeNode;\n if (headBlockPos === undefined) {\n throw new Error(\n `Could not find block with ID ${data.headBlockId} to update selection`,\n );\n }\n\n selection = TextSelection.create(\n tr.doc,\n anchorBlockPos + data.anchorOffset,\n headBlockPos + data.headOffset,\n );\n }\n\n tr.setSelection(selection);\n}\n\n/**\n * Replaces any `columnList` blocks with the children of their columns. This is\n * done here instead of in `getSelection` as we still need to remove the entire\n * `columnList` node but only insert the `blockContainer` nodes inside it.\n * @param blocks The blocks to flatten.\n */\nfunction flattenColumns(\n blocks: Block<any, any, any>[],\n): Block<any, any, any>[] {\n return blocks\n .map((block) => {\n if (block.type === \"columnList\") {\n return block.children\n .map((column) => flattenColumns(column.children))\n .flat();\n }\n\n return {\n ...block,\n children: flattenColumns(block.children),\n };\n })\n .flat();\n}\n\n/**\n * Removes the selected blocks from the editor, then inserts them before/after a\n * reference block. Also updates the selection to match the original selection\n * using `getBlockSelectionData` and `updateBlockSelectionFromData`.\n * @param editor The BlockNote editor instance to move the blocks in.\n * @param referenceBlock The reference block to insert the selected blocks\n * before/after.\n * @param placement Whether to insert the selected blocks before or after the\n * reference block.\n */\nexport function moveSelectedBlocksAndSelection(\n editor: BlockNoteEditor<any, any, any>,\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\",\n) {\n // We want this to be a single step in the undo history\n editor.transact((tr) => {\n const blocks = editor.getSelection()?.blocks || [\n editor.getTextCursorPosition().block,\n ];\n const selectionData = getBlockSelectionData(editor);\n\n editor.removeBlocks(blocks);\n editor.insertBlocks(flattenColumns(blocks), referenceBlock, placement);\n\n updateBlockSelectionFromData(tr, selectionData);\n });\n}\n\n// Checks if a block is in a valid place after being moved. This check is\n// primitive at the moment and only returns false if the block's parent is a\n// `columnList` block. This is because regular blocks cannot be direct children\n// of `columnList` blocks.\nfunction checkPlacementIsValid(parentBlock?: Block<any, any, any>): boolean {\n return !parentBlock || parentBlock.type !== \"columnList\";\n}\n\n// Gets the placement for moving a block up. This has 3 cases:\n// 1. If the block has a previous sibling without children, the placement is\n// before it.\n// 2. If the block has a previous sibling with children, the placement is after\n// the last child.\n// 3. If the block has no previous sibling, but is nested, the placement is\n// before its parent.\n// If the placement is invalid, the function is called recursively until a valid\n// placement is found. Returns undefined if no valid placement is found, meaning\n// the block is already at the top of the document.\nfunction getMoveUpPlacement(\n editor: BlockNoteEditor<any, any, any>,\n prevBlock?: Block<any, any, any>,\n parentBlock?: Block<any, any, any>,\n):\n | { referenceBlock: BlockIdentifier; placement: \"before\" | \"after\" }\n | undefined {\n let referenceBlock: Block<any, any, any> | undefined;\n let placement: \"before\" | \"after\" | undefined;\n\n if (!prevBlock) {\n if (parentBlock) {\n referenceBlock = parentBlock;\n placement = \"before\";\n }\n } else if (prevBlock.children.length > 0) {\n referenceBlock = prevBlock.children[prevBlock.children.length - 1];\n placement = \"after\";\n } else {\n referenceBlock = prevBlock;\n placement = \"before\";\n }\n\n // Case when the block is already at the top of the document.\n if (!referenceBlock || !placement) {\n return undefined;\n }\n\n const referenceBlockParent = editor.getParentBlock(referenceBlock);\n if (!checkPlacementIsValid(referenceBlockParent)) {\n return getMoveUpPlacement(\n editor,\n placement === \"after\"\n ? referenceBlock\n : editor.getPrevBlock(referenceBlock),\n referenceBlockParent,\n );\n }\n\n return { referenceBlock, placement };\n}\n\n// Gets the placement for moving a block down. This has 3 cases:\n// 1. If the block has a next sibling without children, the placement is after\n// it.\n// 2. If the block has a next sibling with children, the placement is before the\n// first child.\n// 3. If the block has no next sibling, but is nested, the placement is\n// after its parent.\n// If the placement is invalid, the function is called recursively until a valid\n// placement is found. Returns undefined if no valid placement is found, meaning\n// the block is already at the bottom of the document.\nfunction getMoveDownPlacement(\n editor: BlockNoteEditor<any, any, any>,\n nextBlock?: Block<any, any, any>,\n parentBlock?: Block<any, any, any>,\n):\n | { referenceBlock: BlockIdentifier; placement: \"before\" | \"after\" }\n | undefined {\n let referenceBlock: Block<any, any, any> | undefined;\n let placement: \"before\" | \"after\" | undefined;\n\n if (!nextBlock) {\n if (parentBlock) {\n referenceBlock = parentBlock;\n placement = \"after\";\n }\n } else if (nextBlock.children.length > 0) {\n referenceBlock = nextBlock.children[0];\n placement = \"before\";\n } else {\n referenceBlock = nextBlock;\n placement = \"after\";\n }\n\n // Case when the block is already at the bottom of the document.\n if (!referenceBlock || !placement) {\n return undefined;\n }\n\n const referenceBlockParent = editor.getParentBlock(referenceBlock);\n if (!checkPlacementIsValid(referenceBlockParent)) {\n return getMoveDownPlacement(\n editor,\n placement === \"before\"\n ? referenceBlock\n : editor.getNextBlock(referenceBlock),\n referenceBlockParent,\n );\n }\n\n return { referenceBlock, placement };\n}\n\nexport function moveBlocksUp(editor: BlockNoteEditor<any, any, any>) {\n editor.transact(() => {\n const selection = editor.getSelection();\n const block = selection?.blocks[0] || editor.getTextCursorPosition().block;\n\n const moveUpPlacement = getMoveUpPlacement(\n editor,\n editor.getPrevBlock(block),\n editor.getParentBlock(block),\n );\n\n if (!moveUpPlacement) {\n return;\n }\n\n moveSelectedBlocksAndSelection(\n editor,\n moveUpPlacement.referenceBlock,\n moveUpPlacement.placement,\n );\n });\n}\n\nexport function moveBlocksDown(editor: BlockNoteEditor<any, any, any>) {\n editor.transact(() => {\n const selection = editor.getSelection();\n const block =\n selection?.blocks[selection?.blocks.length - 1] ||\n editor.getTextCursorPosition().block;\n\n const moveDownPlacement = getMoveDownPlacement(\n editor,\n editor.getNextBlock(block),\n editor.getParentBlock(block),\n );\n\n if (!moveDownPlacement) {\n return;\n }\n\n moveSelectedBlocksAndSelection(\n editor,\n moveDownPlacement.referenceBlock,\n moveDownPlacement.placement,\n );\n });\n}\n","import { Fragment, NodeType, Slice } from \"prosemirror-model\";\nimport { EditorState, Transaction } from \"prosemirror-state\";\nimport { ReplaceAroundStep } from \"prosemirror-transform\";\n\nimport { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor.js\";\nimport { getBlockInfoFromTransaction } from \"../../../getBlockInfoFromPos.js\";\n\n// TODO: Unit tests\n/**\n * This is a modified version of https://github.com/ProseMirror/prosemirror-schema-list/blob/569c2770cbb8092d8f11ea53ecf78cb7a4e8f15a/src/schema-list.ts#L232\n *\n * The original function derives too many information from the parentnode and itemtype\n */\nfunction sinkListItem(itemType: NodeType, groupType: NodeType) {\n return function (state: EditorState, dispatch?: (tr: Transaction) => void) {\n const { $from, $to } = state.selection;\n const range = $from.blockRange(\n $to,\n (node) =>\n node.childCount > 0 &&\n (node.type.name === \"blockGroup\" || node.type.name === \"column\"), // change necessary to not look at first item child type\n );\n if (!range) {\n return false;\n }\n const startIndex = range.startIndex;\n if (startIndex === 0) {\n return false;\n }\n const parent = range.parent;\n const nodeBefore = parent.child(startIndex - 1);\n if (nodeBefore.type !== itemType) {\n return false;\n }\n if (dispatch) {\n const nestedBefore =\n nodeBefore.lastChild && nodeBefore.lastChild.type === groupType; // change necessary to check groupType instead of parent.type\n const inner = Fragment.from(nestedBefore ? itemType.create() : null);\n const slice = new Slice(\n Fragment.from(\n itemType.create(null, Fragment.from(groupType.create(null, inner))), // change necessary to create \"groupType\" instead of parent.type\n ),\n nestedBefore ? 3 : 1,\n 0,\n );\n\n const before = range.start;\n const after = range.end;\n dispatch(\n state.tr\n .step(\n new ReplaceAroundStep(\n before - (nestedBefore ? 3 : 1),\n after,\n before,\n after,\n slice,\n 1,\n true,\n ),\n )\n .scrollIntoView(),\n );\n }\n return true;\n };\n}\n\nexport function nestBlock(editor: BlockNoteEditor<any, any, any>) {\n return editor.exec((state, dispatch) =>\n sinkListItem(\n state.schema.nodes[\"blockContainer\"],\n state.schema.nodes[\"blockGroup\"],\n )(state, dispatch),\n );\n}\n\nexport function unnestBlock(editor: BlockNoteEditor<any, any, any>) {\n editor._tiptapEditor.commands.liftListItem(\"blockContainer\");\n}\n\nexport function canNestBlock(editor: BlockNoteEditor<any, any, any>) {\n return editor.transact((tr) => {\n const { bnBlock: blockContainer } = getBlockInfoFromTransaction(tr);\n\n return tr.doc.resolve(blockContainer.beforePos).nodeBefore !== null;\n });\n}\n\nexport function canUnnestBlock(editor: BlockNoteEditor<any, any, any>) {\n return editor.transact((tr) => {\n const { bnBlock: blockContainer } = getBlockInfoFromTransaction(tr);\n\n return tr.doc.resolve(blockContainer.beforePos).depth > 1;\n });\n}\n","import type { Node } from \"prosemirror-model\";\nimport type { Block } from \"../../../blocks/defaultBlocks.js\";\nimport type {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { nodeToBlock } from \"../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../nodeUtil.js\";\nimport { getPmSchema } from \"../../pmUtil.js\";\n\nexport function getBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n blockIdentifier: BlockIdentifier,\n): Block<BSchema, I, S> | undefined {\n const id =\n typeof blockIdentifier === \"string\" ? blockIdentifier : blockIdentifier.id;\n const pmSchema = getPmSchema(doc);\n\n const posInfo = getNodeById(id, doc);\n if (!posInfo) {\n return undefined;\n }\n\n return nodeToBlock(posInfo.node, pmSchema);\n}\n\nexport function getPrevBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n blockIdentifier: BlockIdentifier,\n): Block<BSchema, I, S> | undefined {\n const id =\n typeof blockIdentifier === \"string\" ? blockIdentifier : blockIdentifier.id;\n\n const posInfo = getNodeById(id, doc);\n const pmSchema = getPmSchema(doc);\n if (!posInfo) {\n return undefined;\n }\n\n const $posBeforeNode = doc.resolve(posInfo.posBeforeNode);\n const nodeToConvert = $posBeforeNode.nodeBefore;\n if (!nodeToConvert) {\n return undefined;\n }\n\n return nodeToBlock(nodeToConvert, pmSchema);\n}\n\nexport function getNextBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n blockIdentifier: BlockIdentifier,\n): Block<BSchema, I, S> | undefined {\n const id =\n typeof blockIdentifier === \"string\" ? blockIdentifier : blockIdentifier.id;\n const posInfo = getNodeById(id, doc);\n const pmSchema = getPmSchema(doc);\n if (!posInfo) {\n return undefined;\n }\n\n const $posAfterNode = doc.resolve(\n posInfo.posBeforeNode + posInfo.node.nodeSize,\n );\n const nodeToConvert = $posAfterNode.nodeAfter;\n if (!nodeToConvert) {\n return undefined;\n }\n\n return nodeToBlock(nodeToConvert, pmSchema);\n}\n\nexport function getParentBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n blockIdentifier: BlockIdentifier,\n): Block<BSchema, I, S> | undefined {\n const id =\n typeof blockIdentifier === \"string\" ? blockIdentifier : blockIdentifier.id;\n const pmSchema = getPmSchema(doc);\n const posInfo = getNodeById(id, doc);\n if (!posInfo) {\n return undefined;\n }\n\n const $posBeforeNode = doc.resolve(posInfo.posBeforeNode);\n const parentNode = $posBeforeNode.node();\n const grandparentNode = $posBeforeNode.node(-1);\n const nodeToConvert =\n grandparentNode.type.name !== \"doc\"\n ? parentNode.type.name === \"blockGroup\"\n ? grandparentNode\n : parentNode\n : undefined;\n if (!nodeToConvert) {\n return undefined;\n }\n\n return nodeToBlock(nodeToConvert, pmSchema);\n}\n","import { selectionToInsertionEnd } from \"@tiptap/core\";\nimport { Node } from \"prosemirror-model\";\n\nimport type { Transaction } from \"prosemirror-state\";\n\n// similar to tiptap insertContentAt\nexport function insertContentAt(\n tr: Transaction,\n position: number | { from: number; to: number },\n nodes: Node[],\n options: {\n updateSelection: boolean;\n } = { updateSelection: true },\n) {\n // don’t dispatch an empty fragment because this can lead to strange errors\n // if (content.toString() === \"<>\") {\n // return true;\n // }\n\n let { from, to } =\n typeof position === \"number\"\n ? { from: position, to: position }\n : { from: position.from, to: position.to };\n\n let isOnlyTextContent = true;\n let isOnlyBlockContent = true;\n // const nodes = isFragment(content) ? content : [content];\n\n let text = \"\";\n\n nodes.forEach((node) => {\n // check if added node is valid\n node.check();\n\n if (isOnlyTextContent && node.isText && node.marks.length === 0) {\n text += node.text;\n } else {\n isOnlyTextContent = false;\n }\n\n isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;\n });\n\n // check if we can replace the wrapping node by\n // the newly inserted content\n // example:\n // replace an empty paragraph by an inserted image\n // instead of inserting the image below the paragraph\n if (from === to && isOnlyBlockContent) {\n const { parent } = tr.doc.resolve(from);\n const isEmptyTextBlock =\n parent.isTextblock && !parent.type.spec.code && !parent.childCount;\n\n if (isEmptyTextBlock) {\n from -= 1;\n to += 1;\n }\n }\n\n // if there is only plain text we have to use `insertText`\n // because this will keep the current marks\n if (isOnlyTextContent) {\n // if value is string, we can use it directly\n // otherwise if it is an array, we have to join it\n // if (Array.isArray(value)) {\n // tr.insertText(value.map((v) => v.text || \"\").join(\"\"), from, to);\n // } else if (typeof value === \"object\" && !!value && !!value.text) {\n // tr.insertText(value.text, from, to);\n // } else {\n // tr.insertText(value as string, from, to);\n // }\n tr.insertText(text, from, to);\n } else {\n tr.replaceWith(from, to, nodes);\n }\n\n // set cursor at end of inserted content\n if (options.updateSelection) {\n selectionToInsertionEnd(tr, tr.steps.length - 1, -1);\n }\n\n return true;\n}\n","import { TextSelection, type Transaction } from \"prosemirror-state\";\nimport { TableMap } from \"prosemirror-tables\";\n\nimport { Block } from \"../../../blocks/defaultBlocks.js\";\nimport { Selection } from \"../../../editor/selectionTypes.js\";\nimport {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { getBlockInfo, getNearestBlockPos } from \"../../getBlockInfoFromPos.js\";\nimport {\n nodeToBlock,\n prosemirrorSliceToSlicedBlocks,\n} from \"../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../nodeUtil.js\";\nimport { getBlockNoteSchema, getPmSchema } from \"../../pmUtil.js\";\n\nexport function getSelection<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(tr: Transaction): Selection<BSchema, I, S> | undefined {\n const pmSchema = getPmSchema(tr);\n // Return undefined if the selection is collapsed or a node is selected.\n if (tr.selection.empty || \"node\" in tr.selection) {\n return undefined;\n }\n\n const $startBlockBeforePos = tr.doc.resolve(\n getNearestBlockPos(tr.doc, tr.selection.from).posBeforeNode,\n );\n const $endBlockBeforePos = tr.doc.resolve(\n getNearestBlockPos(tr.doc, tr.selection.to).posBeforeNode,\n );\n\n // Converts the node at the given index and depth around `$startBlockBeforePos`\n // to a block. Used to get blocks at given indices at the shared depth and\n // at the depth of `$startBlockBeforePos`.\n const indexToBlock = (\n index: number,\n depth?: number,\n ): Block<BSchema, I, S> => {\n const pos = $startBlockBeforePos.posAtIndex(index, depth);\n const node = tr.doc.resolve(pos).nodeAfter;\n\n if (!node) {\n throw new Error(\n `Error getting selection - node not found at position ${pos}`,\n );\n }\n\n return nodeToBlock(node, pmSchema);\n };\n\n const blocks: Block<BSchema, I, S>[] = [];\n // Minimum depth at which the blocks share a common ancestor.\n const sharedDepth = $startBlockBeforePos.sharedDepth($endBlockBeforePos.pos);\n const startIndex = $startBlockBeforePos.index(sharedDepth);\n const endIndex = $endBlockBeforePos.index(sharedDepth);\n\n // In most cases, we want to return the blocks spanned by the selection at the\n // shared depth. However, when the block in which the selection starts is at a\n // higher depth than the shared depth, we omit the first block at the shared\n // depth. Instead, we include the first block at its depth, and any blocks at\n // a higher index up to the shared depth. The following example illustrates\n // this:\n // - id-0\n // - id-1\n // - >|id-2\n // - id-3\n // - id-4\n // - id-5\n // - id-6\n // - id-7\n // - id-8\n // - id-9|<\n // - id-10\n // Here, each block is represented by its ID, and the selection is represented\n // by the `>|` and `|<` markers. So the selection starts in block `id-2` and\n // ends in block `id-8`. In this case, the shared depth is 0, since the blocks\n // `id-6`, `id-7`, and `id-8` set the shared depth, as they are the least\n // nested blocks spanned by the selection. Therefore, these blocks are all\n // added to the `blocks` array. However, the selection starts in block `id-2`,\n // which is at a higher depth than the shared depth. So we add block `id-2` to\n // the `blocks` array, as well as any later siblings (in this case, `id-3`),\n // and move up one level of depth. The ancestor of block `id-2` at this depth\n // is block `id-1`, so we add all its later siblings to the `blocks` array as\n // well, again moving up one level of depth. Since we're now at the shared\n // depth, we are done. The final `blocks` array for this example would be:\n // [ id-2, id-3, id-4, id-6, id-7, id-8, id-9 ]\n if ($startBlockBeforePos.depth > sharedDepth) {\n // Adds the block that the selection starts in.\n blocks.push(nodeToBlock($startBlockBeforePos.nodeAfter!, pmSchema));\n\n // Traverses all depths from the depth of the block in which the selection\n // starts, up to the shared depth.\n for (let depth = $startBlockBeforePos.depth; depth > sharedDepth; depth--) {\n const parentNode = $startBlockBeforePos.node(depth);\n\n if (parentNode.type.isInGroup(\"childContainer\")) {\n const startIndexAtDepth = $startBlockBeforePos.index(depth) + 1;\n const childCountAtDepth = $startBlockBeforePos.node(depth).childCount;\n\n // Adds all blocks after the index of the block in which the selection\n // starts (or its ancestors at lower depths).\n for (let i = startIndexAtDepth; i < childCountAtDepth; i++) {\n blocks.push(indexToBlock(i, depth));\n }\n }\n }\n } else {\n // Adds the first block spanned by the selection at the shared depth.\n blocks.push(indexToBlock(startIndex, sharedDepth));\n }\n\n // Adds all blocks spanned by the selection at the shared depth, excluding\n // the first.\n for (let i = startIndex + 1; i <= endIndex; i++) {\n blocks.push(indexToBlock(i, sharedDepth));\n }\n\n if (blocks.length === 0) {\n throw new Error(\n `Error getting selection - selection doesn't span any blocks (${tr.selection})`,\n );\n }\n\n return {\n blocks,\n };\n}\n\nexport function setSelection(\n tr: Transaction,\n startBlock: BlockIdentifier,\n endBlock: BlockIdentifier,\n) {\n const startBlockId =\n typeof startBlock === \"string\" ? startBlock : startBlock.id;\n const endBlockId = typeof endBlock === \"string\" ? endBlock : endBlock.id;\n const pmSchema = getPmSchema(tr);\n const schema = getBlockNoteSchema(pmSchema);\n\n if (startBlockId === endBlockId) {\n throw new Error(\n `Attempting to set selection with the same anchor and head blocks (id ${startBlockId})`,\n );\n }\n const anchorPosInfo = getNodeById(startBlockId, tr.doc);\n if (!anchorPosInfo) {\n throw new Error(`Block with ID ${startBlockId} not found`);\n }\n const headPosInfo = getNodeById(endBlockId, tr.doc);\n if (!headPosInfo) {\n throw new Error(`Block with ID ${endBlockId} not found`);\n }\n\n const anchorBlockInfo = getBlockInfo(anchorPosInfo);\n const headBlockInfo = getBlockInfo(headPosInfo);\n\n const anchorBlockConfig =\n schema.blockSchema[\n anchorBlockInfo.blockNoteType as keyof typeof schema.blockSchema\n ];\n const headBlockConfig =\n schema.blockSchema[\n headBlockInfo.blockNoteType as keyof typeof schema.blockSchema\n ];\n\n if (\n !anchorBlockInfo.isBlockContainer ||\n anchorBlockConfig.content === \"none\"\n ) {\n throw new Error(\n `Attempting to set selection anchor in block without content (id ${startBlockId})`,\n );\n }\n if (!headBlockInfo.isBlockContainer || headBlockConfig.content === \"none\") {\n throw new Error(\n `Attempting to set selection anchor in block without content (id ${endBlockId})`,\n );\n }\n\n let startPos: number;\n let endPos: number;\n\n if (anchorBlockConfig.content === \"table\") {\n const tableMap = TableMap.get(anchorBlockInfo.blockContent.node);\n const firstCellPos =\n anchorBlockInfo.blockContent.beforePos +\n tableMap.positionAt(0, 0, anchorBlockInfo.blockContent.node) +\n 1;\n startPos = firstCellPos + 2;\n } else {\n startPos = anchorBlockInfo.blockContent.beforePos + 1;\n }\n\n if (headBlockConfig.content === \"table\") {\n const tableMap = TableMap.get(headBlockInfo.blockContent.node);\n const lastCellPos =\n headBlockInfo.blockContent.beforePos +\n tableMap.positionAt(\n tableMap.height - 1,\n tableMap.width - 1,\n headBlockInfo.blockContent.node,\n ) +\n 1;\n const lastCellNodeSize = tr.doc.resolve(lastCellPos).nodeAfter!.nodeSize;\n endPos = lastCellPos + lastCellNodeSize - 2;\n } else {\n endPos = headBlockInfo.blockContent.afterPos - 1;\n }\n\n // TODO: We should polish up the `MultipleNodeSelection` and use that instead.\n // Right now it's missing a few things like a jsonID and styling to show\n // which nodes are selected. `TextSelection` is ok for now, but has the\n // restriction that the start/end blocks must have content.\n tr.setSelection(TextSelection.create(tr.doc, startPos, endPos));\n}\n\nexport function getSelectionCutBlocks(tr: Transaction) {\n // TODO: fix image node selection\n\n const pmSchema = getPmSchema(tr);\n let start = tr.selection.$from;\n let end = tr.selection.$to;\n\n // the selection moves below are used to make sure `prosemirrorSliceToSlicedBlocks` returns\n // the correct information about whether content is cut at the start or end of a block\n\n // if the end is at the end of a node (|</span></p>) move it forward so we include all closing tags (</span></p>|)\n while (end.parentOffset >= end.parent.nodeSize - 2 && end.depth > 0) {\n end = tr.doc.resolve(end.pos + 1);\n }\n\n // if the end is at the start of an empty node (</span></p><p>|) move it backwards so we drop empty start tags (</span></p>|)\n while (end.parentOffset === 0 && end.depth > 0) {\n end = tr.doc.resolve(end.pos - 1);\n }\n\n // if the start is at the start of a node (<p><span>|) move it backwards so we include all open tags (|<p><span>)\n while (start.parentOffset === 0 && start.depth > 0) {\n start = tr.doc.resolve(start.pos - 1);\n }\n\n // if the start is at the end of a node (|</p><p><span>|) move it forwards so we drop all closing tags (|<p><span>)\n while (start.parentOffset >= start.parent.nodeSize - 2 && start.depth > 0) {\n start = tr.doc.resolve(start.pos + 1);\n }\n\n const selectionInfo = prosemirrorSliceToSlicedBlocks(\n tr.doc.slice(start.pos, end.pos, true),\n pmSchema,\n );\n\n return {\n _meta: {\n startPos: start.pos,\n endPos: end.pos,\n },\n ...selectionInfo,\n };\n}\n","import type { Node } from \"prosemirror-model\";\nimport {\n NodeSelection,\n TextSelection,\n type Transaction,\n} from \"prosemirror-state\";\nimport type { TextCursorPosition } from \"../../../editor/cursorPositionTypes.js\";\nimport type {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { UnreachableCaseError } from \"../../../util/typescript.js\";\nimport {\n getBlockInfo,\n getBlockInfoFromTransaction,\n} from \"../../getBlockInfoFromPos.js\";\nimport { nodeToBlock } from \"../../nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../nodeUtil.js\";\nimport { getBlockNoteSchema, getPmSchema } from \"../../pmUtil.js\";\n\nexport function getTextCursorPosition<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(tr: Transaction): TextCursorPosition<BSchema, I, S> {\n const { bnBlock } = getBlockInfoFromTransaction(tr);\n const pmSchema = getPmSchema(tr.doc);\n\n const resolvedPos = tr.doc.resolve(bnBlock.beforePos);\n // Gets previous blockContainer node at the same nesting level, if the current node isn't the first child.\n const prevNode = resolvedPos.nodeBefore;\n\n // Gets next blockContainer node at the same nesting level, if the current node isn't the last child.\n const nextNode = tr.doc.resolve(bnBlock.afterPos).nodeAfter;\n\n // Gets parent blockContainer node, if the current node is nested.\n let parentNode: Node | undefined = undefined;\n if (resolvedPos.depth > 1) {\n // for nodes nested in bnBlocks\n parentNode = resolvedPos.node();\n if (!parentNode.type.isInGroup(\"bnBlock\")) {\n // for blockGroups, we need to go one level up\n parentNode = resolvedPos.node(resolvedPos.depth - 1);\n }\n }\n\n return {\n block: nodeToBlock(bnBlock.node, pmSchema),\n prevBlock: prevNode === null ? undefined : nodeToBlock(prevNode, pmSchema),\n nextBlock: nextNode === null ? undefined : nodeToBlock(nextNode, pmSchema),\n parentBlock:\n parentNode === undefined ? undefined : nodeToBlock(parentNode, pmSchema),\n };\n}\n\nexport function setTextCursorPosition(\n tr: Transaction,\n targetBlock: BlockIdentifier,\n placement: \"start\" | \"end\" = \"start\",\n) {\n const id = typeof targetBlock === \"string\" ? targetBlock : targetBlock.id;\n const pmSchema = getPmSchema(tr.doc);\n const schema = getBlockNoteSchema(pmSchema);\n\n const posInfo = getNodeById(id, tr.doc);\n if (!posInfo) {\n throw new Error(`Block with ID ${id} not found`);\n }\n\n const info = getBlockInfo(posInfo);\n\n const contentType: \"none\" | \"inline\" | \"table\" =\n schema.blockSchema[info.blockNoteType]!.content;\n\n if (info.isBlockContainer) {\n const blockContent = info.blockContent;\n if (contentType === \"none\") {\n tr.setSelection(NodeSelection.create(tr.doc, blockContent.beforePos));\n return;\n }\n\n if (contentType === \"inline\") {\n if (placement === \"start\") {\n tr.setSelection(\n TextSelection.create(tr.doc, blockContent.beforePos + 1),\n );\n } else {\n tr.setSelection(\n TextSelection.create(tr.doc, blockContent.afterPos - 1),\n );\n }\n } else if (contentType === \"table\") {\n if (placement === \"start\") {\n // Need to offset the position as we have to get through the `tableRow`\n // and `tableCell` nodes to get to the `tableParagraph` node we want to\n // set the selection in.\n tr.setSelection(\n TextSelection.create(tr.doc, blockContent.beforePos + 4),\n );\n } else {\n tr.setSelection(\n TextSelection.create(tr.doc, blockContent.afterPos - 4),\n );\n }\n } else {\n throw new UnreachableCaseError(contentType);\n }\n } else {\n const child =\n placement === \"start\"\n ? info.childContainer.node.firstChild!\n : info.childContainer.node.lastChild!;\n\n setTextCursorPosition(tr, child.attrs.id, placement);\n }\n}\n","// some dependencies only export as ESM modules. This makes them incompatible with Node CJS.\n// To work around this, we load these dependencies as dynamic imports in a function that initializes them.\n\n// (to reproduce this issue, run ts-node on a file that users server-util)\nexport let esmDependencies:\n | undefined\n | {\n rehypeParse: typeof import(\"rehype-parse\");\n rehypeStringify: typeof import(\"rehype-stringify\");\n unified: typeof import(\"unified\");\n hastUtilFromDom: typeof import(\"hast-util-from-dom\");\n rehypeRemark: typeof import(\"rehype-remark\");\n remarkGfm: typeof import(\"remark-gfm\");\n remarkStringify: typeof import(\"remark-stringify\");\n remarkParse: typeof import(\"remark-parse\");\n remarkRehype: typeof import(\"remark-rehype\");\n rehypeFormat: typeof import(\"rehype-format\");\n };\n\nexport async function initializeESMDependencies() {\n if (esmDependencies) {\n return esmDependencies;\n }\n const vals = await Promise.all([\n import(\"rehype-parse\"),\n import(\"rehype-stringify\"),\n import(\"unified\"),\n import(\"hast-util-from-dom\"),\n import(\"rehype-remark\"),\n import(\"remark-gfm\"),\n import(\"remark-stringify\"),\n import(\"remark-parse\"),\n import(\"remark-rehype\"),\n import(\"rehype-format\"),\n ]);\n\n esmDependencies = {\n rehypeParse: vals[0],\n rehypeStringify: vals[1],\n unified: vals[2],\n hastUtilFromDom: vals[3],\n rehypeRemark: vals[4],\n remarkGfm: vals[5],\n remarkStringify: vals[6],\n remarkParse: vals[7],\n remarkRehype: vals[8],\n rehypeFormat: vals[9],\n };\n\n return esmDependencies;\n}\n","import { Element as HASTElement, Parent as HASTParent } from \"hast\";\n\n/**\n * Rehype plugin which removes <u> tags. Used to remove underlines before converting HTML to markdown, as Markdown\n * doesn't support underlines.\n */\nexport function removeUnderlines() {\n const removeUnderlinesHelper = (tree: HASTParent) => {\n let numChildElements = tree.children.length;\n\n for (let i = 0; i < numChildElements; i++) {\n const node = tree.children[i];\n\n if (node.type === \"element\") {\n // Recursively removes underlines from child elements.\n removeUnderlinesHelper(node);\n\n if ((node as HASTElement).tagName === \"u\") {\n // Lifts child nodes outside underline element, deletes the underline element, and updates current index &\n // the number of child elements.\n if (node.children.length > 0) {\n tree.children.splice(i, 1, ...node.children);\n\n const numElementsAdded = node.children.length - 1;\n numChildElements += numElementsAdded;\n i += numElementsAdded;\n } else {\n tree.children.splice(i, 1);\n\n numChildElements--;\n i--;\n }\n }\n }\n }\n };\n\n return removeUnderlinesHelper;\n}\n","import { Element as HASTElement, Parent as HASTParent } from \"hast\";\nimport { esmDependencies } from \"../../../../util/esmDependencies.js\";\n\n/**\n * Rehype plugin which adds a space after each checkbox input element. This is\n * because remark doesn't add any spaces between the checkbox input and the text\n * itself, but these are needed for correct Markdown syntax.\n */\nexport function addSpacesToCheckboxes() {\n const deps = esmDependencies;\n\n if (!deps) {\n throw new Error(\n \"addSpacesToCheckboxes requires ESM dependencies to be initialized\",\n );\n }\n\n const helper = (tree: HASTParent) => {\n if (tree.children && \"length\" in tree.children && tree.children.length) {\n for (let i = tree.children.length - 1; i >= 0; i--) {\n const child = tree.children[i];\n const nextChild =\n i + 1 < tree.children.length ? tree.children[i + 1] : undefined;\n\n // Checks for paragraph element after checkbox input element.\n if (\n child.type === \"element\" &&\n child.tagName === \"input\" &&\n child.properties?.type === \"checkbox\" &&\n nextChild?.type === \"element\" &&\n nextChild.tagName === \"p\"\n ) {\n // Converts paragraph to span, otherwise remark will think it needs to\n // be on a new line.\n nextChild.tagName = \"span\";\n // Adds a space after the checkbox input element.\n nextChild.children.splice(\n 0,\n 0,\n deps.hastUtilFromDom.fromDom(\n document.createTextNode(\" \"),\n ) as HASTElement,\n );\n } else {\n helper(child as HASTParent);\n }\n }\n }\n };\n\n return helper;\n}\n","import { Schema } from \"prosemirror-model\";\nimport { PartialBlock } from \"../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport {\n esmDependencies,\n initializeESMDependencies,\n} from \"../../../util/esmDependencies.js\";\nimport { createExternalHTMLExporter } from \"../html/externalHTMLExporter.js\";\nimport { removeUnderlines } from \"./removeUnderlinesRehypePlugin.js\";\nimport { addSpacesToCheckboxes } from \"./util/addSpacesToCheckboxesRehypePlugin.js\";\n\n// Needs to be sync because it's used in drag handler event (SideMenuPlugin)\n// Ideally, call `await initializeESMDependencies()` before calling this function\nexport function cleanHTMLToMarkdown(cleanHTMLString: string) {\n const deps = esmDependencies;\n\n if (!deps) {\n throw new Error(\n \"cleanHTMLToMarkdown requires ESM dependencies to be initialized\",\n );\n }\n\n const markdownString = deps.unified\n .unified()\n .use(deps.rehypeParse.default, { fragment: true })\n .use(removeUnderlines)\n .use(addSpacesToCheckboxes)\n .use(deps.rehypeRemark.default)\n .use(deps.remarkGfm.default)\n .use(deps.remarkStringify.default, {\n handlers: { text: (node) => node.value },\n })\n .processSync(cleanHTMLString);\n\n return markdownString.value as string;\n}\n\nexport async function blocksToMarkdown<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blocks: PartialBlock<BSchema, I, S>[],\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>,\n options: { document?: Document },\n): Promise<string> {\n await initializeESMDependencies();\n const exporter = createExternalHTMLExporter(schema, editor);\n const externalHTML = exporter.exportBlocks(blocks, options);\n\n return cleanHTMLToMarkdown(externalHTML);\n}\n","function getChildIndex(node: Element) {\n return Array.prototype.indexOf.call(node.parentElement!.childNodes, node);\n}\n\nfunction isWhitespaceNode(node: Node) {\n return node.nodeType === 3 && !/\\S/.test(node.nodeValue || \"\");\n}\n\n/**\n * Step 1, Turns:\n *\n * <ul>\n * <li>item</li>\n * <li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </li>\n *\n * Into:\n * <ul>\n * <li>item</li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </ul>\n *\n */\nfunction liftNestedListsToParent(element: HTMLElement) {\n element.querySelectorAll(\"li > ul, li > ol\").forEach((list) => {\n const index = getChildIndex(list);\n const parentListItem = list.parentElement!;\n const siblingsAfter = Array.from(parentListItem.childNodes).slice(\n index + 1,\n );\n list.remove();\n siblingsAfter.forEach((sibling) => {\n sibling.remove();\n });\n\n parentListItem.insertAdjacentElement(\"afterend\", list);\n\n siblingsAfter.reverse().forEach((sibling) => {\n if (isWhitespaceNode(sibling)) {\n return;\n }\n const siblingContainer = document.createElement(\"li\");\n siblingContainer.append(sibling);\n list.insertAdjacentElement(\"afterend\", siblingContainer);\n });\n if (parentListItem.childNodes.length === 0) {\n parentListItem.remove();\n }\n });\n}\n\n/**\n * Step 2, Turns (output of liftNestedListsToParent):\n *\n * <li>item</li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n *\n * Into:\n * <div>\n * <li>item</li>\n * <div data-node-type=\"blockGroup\">\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </div>\n * </div>\n *\n * This resulting format is parsed\n */\nfunction createGroups(element: HTMLElement) {\n element.querySelectorAll(\"li + ul, li + ol\").forEach((list) => {\n const listItem = list.previousElementSibling as HTMLElement;\n const blockContainer = document.createElement(\"div\");\n\n listItem.insertAdjacentElement(\"afterend\", blockContainer);\n blockContainer.append(listItem);\n\n const blockGroup = document.createElement(\"div\");\n blockGroup.setAttribute(\"data-node-type\", \"blockGroup\");\n blockContainer.append(blockGroup);\n\n while (\n blockContainer.nextElementSibling?.nodeName === \"UL\" ||\n blockContainer.nextElementSibling?.nodeName === \"OL\"\n ) {\n blockGroup.append(blockContainer.nextElementSibling);\n }\n });\n}\n\n// prevent XSS, similar to https://github.com/ProseMirror/prosemirror-view/blob/1251b2b412656a2a06263e4187574beb43651273/src/clipboard.ts#L204\n// https://github.com/TypeCellOS/BlockNote/issues/601\nlet _detachedDoc: Document | null = null;\nfunction detachedDoc() {\n return (\n _detachedDoc ||\n (_detachedDoc = document.implementation.createHTMLDocument(\"title\"))\n );\n}\n\nexport function nestedListsToBlockNoteStructure(\n elementOrHTML: HTMLElement | string,\n) {\n if (typeof elementOrHTML === \"string\") {\n const element = detachedDoc().createElement(\"div\");\n element.innerHTML = elementOrHTML;\n elementOrHTML = element;\n }\n liftNestedListsToParent(elementOrHTML);\n createGroups(elementOrHTML);\n return elementOrHTML;\n}\n","import { DOMParser, Schema } from \"prosemirror-model\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\n\nimport { Block } from \"../../../blocks/defaultBlocks.js\";\nimport { nodeToBlock } from \"../../nodeConversions/nodeToBlock.js\";\nimport { nestedListsToBlockNoteStructure } from \"./util/nestedLists.js\";\nexport async function HTMLToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(html: string, pmSchema: Schema): Promise<Block<BSchema, I, S>[]> {\n const htmlNode = nestedListsToBlockNoteStructure(html);\n const parser = DOMParser.fromSchema(pmSchema);\n\n // Other approach might be to use\n // const doc = pmSchema.nodes[\"doc\"].createAndFill()!;\n // and context: doc.resolve(3),\n\n const parentNode = parser.parse(htmlNode, {\n topNode: pmSchema.nodes[\"blockGroup\"].create(),\n });\n\n const blocks: Block<BSchema, I, S>[] = [];\n\n for (let i = 0; i < parentNode.childCount; i++) {\n blocks.push(nodeToBlock(parentNode.child(i), pmSchema));\n }\n\n return blocks;\n}\n","import { Schema } from \"prosemirror-model\";\n\nimport { Block } from \"../../../blocks/defaultBlocks.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { initializeESMDependencies } from \"../../../util/esmDependencies.js\";\nimport { HTMLToBlocks } from \"../html/parseHTML.js\";\n\n// modified version of https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js\n// that outputs a data-language attribute instead of a CSS class (e.g.: language-typescript)\nfunction code(state: any, node: any) {\n const value = node.value ? node.value : \"\";\n /** @type {Properties} */\n const properties: any = {};\n\n if (node.lang) {\n // changed line\n properties[\"data-language\"] = node.lang;\n }\n\n // Create `<code>`.\n /** @type {Element} */\n let result: any = {\n type: \"element\",\n tagName: \"code\",\n properties,\n children: [{ type: \"text\", value }],\n };\n\n if (node.meta) {\n result.data = { meta: node.meta };\n }\n\n state.patch(node, result);\n result = state.applyData(node, result);\n\n // Create `<pre>`.\n result = {\n type: \"element\",\n tagName: \"pre\",\n properties: {},\n children: [result],\n };\n state.patch(node, result);\n return result;\n}\n\nexport async function markdownToHTML(markdown: string): Promise<string> {\n const deps = await initializeESMDependencies();\n\n const htmlString = deps.unified\n .unified()\n .use(deps.remarkParse.default)\n .use(deps.remarkGfm.default)\n .use(deps.remarkRehype.default, {\n handlers: {\n ...(deps.remarkRehype.defaultHandlers as any),\n code,\n },\n })\n .use(deps.rehypeStringify.default)\n .processSync(markdown);\n\n return htmlString.value as string;\n}\n\nexport async function markdownToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(markdown: string, pmSchema: Schema): Promise<Block<BSchema, I, S>[]> {\n const htmlString = await markdownToHTML(markdown);\n\n return HTMLToBlocks(htmlString, pmSchema);\n}\n","export const acceptedMIMETypes = [\n \"vscode-editor-data\",\n \"blocknote/html\",\n \"text/markdown\",\n \"text/html\",\n \"text/plain\",\n \"Files\",\n] as const;\n","import { Block, PartialBlock } from \"../../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor\";\nimport {\n BlockSchema,\n FileBlockConfig,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { getNearestBlockPos } from \"../../getBlockInfoFromPos.js\";\nimport { acceptedMIMETypes } from \"./acceptedMIMETypes.js\";\n\nfunction checkFileExtensionsMatch(\n fileExtension1: string,\n fileExtension2: string,\n) {\n if (!fileExtension1.startsWith(\".\") || !fileExtension2.startsWith(\".\")) {\n throw new Error(`The strings provided are not valid file extensions.`);\n }\n\n return fileExtension1 === fileExtension2;\n}\n\nfunction checkMIMETypesMatch(mimeType1: string, mimeType2: string) {\n const types1 = mimeType1.split(\"/\");\n const types2 = mimeType2.split(\"/\");\n\n if (types1.length !== 2) {\n throw new Error(`The string ${mimeType1} is not a valid MIME type.`);\n }\n if (types2.length !== 2) {\n throw new Error(`The string ${mimeType2} is not a valid MIME type.`);\n }\n\n if (types1[1] === \"*\" || types2[1] === \"*\") {\n return types1[0] === types2[0];\n }\n if (types1[0] === \"*\" || types2[0] === \"*\") {\n return types1[1] === types2[1];\n }\n\n return types1[0] === types2[0] && types1[1] === types2[1];\n}\n\nfunction insertOrUpdateBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n referenceBlock: Block<BSchema, I, S>,\n newBlock: PartialBlock<BSchema, I, S>,\n) {\n let insertedBlockId: string | undefined;\n\n if (\n Array.isArray(referenceBlock.content) &&\n referenceBlock.content.length === 0\n ) {\n insertedBlockId = editor.updateBlock(referenceBlock, newBlock).id;\n } else {\n insertedBlockId = editor.insertBlocks(\n [newBlock],\n referenceBlock,\n \"after\",\n )[0].id;\n }\n\n return insertedBlockId;\n}\n\nexport async function handleFileInsertion<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(event: DragEvent | ClipboardEvent, editor: BlockNoteEditor<BSchema, I, S>) {\n if (!editor.uploadFile) {\n // eslint-disable-next-line no-console\n console.warn(\n \"Attempted ot insert file, but uploadFile is not set in the BlockNote editor options\",\n );\n return;\n }\n\n const dataTransfer =\n \"dataTransfer\" in event ? event.dataTransfer : event.clipboardData;\n if (dataTransfer === null) {\n return;\n }\n\n let format: (typeof acceptedMIMETypes)[number] | null = null;\n for (const mimeType of acceptedMIMETypes) {\n if (dataTransfer.types.includes(mimeType)) {\n format = mimeType;\n break;\n }\n }\n if (format !== \"Files\") {\n return;\n }\n\n const items = dataTransfer.items;\n if (!items) {\n return;\n }\n\n event.preventDefault();\n\n const fileBlockConfigs = Object.values(editor.schema.blockSchema).filter(\n (blockConfig) => blockConfig.isFileBlock,\n ) as FileBlockConfig[];\n\n for (let i = 0; i < items.length; i++) {\n // Gets file block corresponding to MIME type.\n let fileBlockType = \"file\";\n for (const fileBlockConfig of fileBlockConfigs) {\n for (const mimeType of fileBlockConfig.fileBlockAccept || []) {\n const isFileExtension = mimeType.startsWith(\".\");\n const file = items[i].getAsFile();\n\n if (file) {\n if (\n (!isFileExtension &&\n file.type &&\n checkMIMETypesMatch(items[i].type, mimeType)) ||\n (isFileExtension &&\n checkFileExtensionsMatch(\n \".\" + file.name.split(\".\").pop(),\n mimeType,\n ))\n ) {\n fileBlockType = fileBlockConfig.type;\n break;\n }\n }\n }\n }\n\n const file = items[i].getAsFile();\n if (file) {\n const fileBlock = {\n type: fileBlockType,\n props: {\n name: file.name,\n },\n } as PartialBlock<BSchema, I, S>;\n\n let insertedBlockId: string | undefined = undefined;\n\n if (event.type === \"paste\") {\n const currentBlock = editor.getTextCursorPosition().block;\n insertedBlockId = insertOrUpdateBlock(editor, currentBlock, fileBlock);\n } else if (event.type === \"drop\") {\n const coords = {\n left: (event as DragEvent).clientX,\n top: (event as DragEvent).clientY,\n };\n\n const pos = editor.prosemirrorView?.posAtCoords(coords);\n if (!pos) {\n return;\n }\n\n insertedBlockId = editor.transact((tr) => {\n const posInfo = getNearestBlockPos(tr.doc, pos.pos);\n return insertOrUpdateBlock(\n editor,\n editor.getBlock(posInfo.node.attrs.id)!,\n fileBlock,\n );\n });\n } else {\n return;\n }\n\n const updateData = await editor.uploadFile(file, insertedBlockId);\n\n const updatedFileBlock =\n typeof updateData === \"string\"\n ? ({\n props: {\n url: updateData,\n },\n } as PartialBlock<BSchema, I, S>)\n : { ...updateData };\n\n editor.updateBlock(insertedBlockId, updatedFileBlock);\n }\n }\n}\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"prosemirror-state\";\n\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { acceptedMIMETypes } from \"./acceptedMIMETypes.js\";\nimport { handleFileInsertion } from \"./handleFileInsertion.js\";\n\nexport const createDropFileExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n) =>\n Extension.create<{ editor: BlockNoteEditor<BSchema, I, S> }, undefined>({\n name: \"dropFile\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n drop(_view, event) {\n if (!editor.isEditable) {\n return;\n }\n\n let format: (typeof acceptedMIMETypes)[number] | null = null;\n for (const mimeType of acceptedMIMETypes) {\n if (event.dataTransfer!.types.includes(mimeType)) {\n format = mimeType;\n break;\n }\n }\n if (format === null) {\n return true;\n }\n\n if (format === \"Files\") {\n handleFileInsertion(event, editor);\n return true;\n }\n\n return false;\n },\n },\n },\n }),\n ];\n },\n });\n","// Headings H1-H6.\nconst h1 = /(^|\\n) {0,3}#{1,6} {1,8}[^\\n]{1,64}\\r?\\n\\r?\\n\\s{0,32}\\S/;\n\n// Bold, italic, underline, strikethrough, highlight.\nconst bold = /(?:\\s|^)(_|__|\\*|\\*\\*|~~|==|\\+\\+)(?!\\s).{1,64}(?<!\\s)(?=\\1)/;\n\n// Basic inline link (also captures images).\nconst link = /\\[[^\\]]{1,128}\\]\\(https?:\\/\\/\\S{1,999}\\)/;\n\n// Inline code.\nconst code = /(?:\\s|^)`(?!\\s)[^`]{1,48}(?<!\\s)`([^\\w]|$)/;\n\n// Unordered list.\nconst ul = /(?:^|\\n)\\s{0,5}-\\s{1}[^\\n]+\\n\\s{0,15}-\\s/;\n\n// Ordered list.\nconst ol = /(?:^|\\n)\\s{0,5}\\d+\\.\\s{1}[^\\n]+\\n\\s{0,15}\\d+\\.\\s/;\n\n// Horizontal rule.\nconst hr = /\\n{2} {0,3}-{2,48}\\n{2}/;\n\n// Fenced code block.\nconst fences =\n /(?:\\n|^)(```|~~~|\\$\\$)(?!`|~)[^\\s]{0,64} {0,64}[^\\n]{0,64}\\n[\\s\\S]{0,9999}?\\s*\\1 {0,64}(?:\\n+|$)/;\n\n// Classical underlined H1 and H2 headings.\nconst title = /(?:\\n|^)(?!\\s)\\w[^\\n]{0,64}\\r?\\n(-|=)\\1{0,64}\\n\\n\\s{0,64}(\\w|$)/;\n\n// Blockquote.\nconst blockquote =\n /(?:^|(\\r?\\n\\r?\\n))( {0,3}>[^\\n]{1,333}\\n){1,999}($|(\\r?\\n))/;\n\n// Table Header\nconst tableHeader = /^\\s*\\|(.+\\|)+\\s*$/m;\n\n// Table Divider\nconst tableDivider = /^\\s*\\|(\\s*[-:]+[-:]\\s*\\|)+\\s*$/m;\n\n// Table Row\nconst tableRow = /^\\s*\\|(.+\\|)+\\s*$/m;\n\n/**\n * Returns `true` if the source text might be a markdown document.\n *\n * @param src Source text to analyze.\n */\nexport const isMarkdown = (src: string): boolean =>\n h1.test(src) ||\n bold.test(src) ||\n link.test(src) ||\n code.test(src) ||\n ul.test(src) ||\n ol.test(src) ||\n hr.test(src) ||\n fences.test(src) ||\n title.test(src) ||\n blockquote.test(src) ||\n tableHeader.test(src) ||\n tableDivider.test(src) ||\n tableRow.test(src);\n","import { EditorView } from \"prosemirror-view\";\n\nexport async function handleVSCodePaste(\n event: ClipboardEvent,\n view: EditorView,\n) {\n const { schema } = view.state;\n\n if (!event.clipboardData) {\n return false;\n }\n\n const text = event.clipboardData!.getData(\"text/plain\");\n\n if (!text) {\n return false;\n }\n\n if (!schema.nodes.codeBlock) {\n view.pasteText(text);\n return true;\n }\n\n const vscode = event.clipboardData!.getData(\"vscode-editor-data\");\n const vscodeData = vscode ? JSON.parse(vscode) : undefined;\n const language = vscodeData?.mode;\n\n if (!language) {\n return false;\n }\n\n // strip carriage return chars from text pasted as code\n // see: https://github.com/ProseMirror/prosemirror-view/commit/a50a6bcceb4ce52ac8fcc6162488d8875613aacd\n view.pasteHTML(\n `<pre><code class=\"language-${language}\">${text.replace(\n /\\r\\n?/g,\n \"\\n\",\n )}</code></pre>`,\n );\n\n return true;\n}\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"prosemirror-state\";\n\nimport type {\n BlockNoteEditor,\n BlockNoteEditorOptions,\n} from \"../../../editor/BlockNoteEditor\";\nimport { isMarkdown } from \"../../parsers/markdown/detectMarkdown.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { acceptedMIMETypes } from \"./acceptedMIMETypes.js\";\nimport { handleFileInsertion } from \"./handleFileInsertion.js\";\nimport { handleVSCodePaste } from \"./handleVSCodePaste.js\";\n\nfunction defaultPasteHandler({\n event,\n editor,\n prioritizeMarkdownOverHTML,\n plainTextAsMarkdown,\n}: {\n event: ClipboardEvent;\n editor: BlockNoteEditor<any, any, any>;\n prioritizeMarkdownOverHTML: boolean;\n plainTextAsMarkdown: boolean;\n}) {\n // Special case for code blocks, as they do not support any rich text\n // formatting, so we force pasting plain text.\n const isInCodeBlock = editor.transact(\n (tr) =>\n tr.selection.$from.parent.type.spec.code &&\n tr.selection.$to.parent.type.spec.code,\n );\n\n if (isInCodeBlock) {\n const data = event.clipboardData?.getData(\"text/plain\");\n\n if (data) {\n editor.pasteText(data);\n\n return true;\n }\n }\n\n let format: (typeof acceptedMIMETypes)[number] | undefined;\n for (const mimeType of acceptedMIMETypes) {\n if (event.clipboardData!.types.includes(mimeType)) {\n format = mimeType;\n break;\n }\n }\n\n if (!format) {\n return true;\n }\n\n if (format === \"vscode-editor-data\") {\n handleVSCodePaste(event, editor.prosemirrorView!);\n return true;\n }\n\n if (format === \"Files\") {\n handleFileInsertion(event, editor);\n return true;\n }\n\n const data = event.clipboardData!.getData(format);\n\n if (format === \"blocknote/html\") {\n // Is blocknote/html, so no need to convert it\n editor.pasteHTML(data, true);\n return true;\n }\n\n if (format === \"text/markdown\") {\n editor.pasteMarkdown(data);\n return true;\n }\n\n if (prioritizeMarkdownOverHTML) {\n // Use plain text instead of HTML if it looks like Markdown\n const plainText = event.clipboardData!.getData(\"text/plain\");\n\n if (isMarkdown(plainText)) {\n editor.pasteMarkdown(plainText);\n return true;\n }\n }\n\n if (format === \"text/html\") {\n editor.pasteHTML(data);\n return true;\n }\n\n if (plainTextAsMarkdown) {\n editor.pasteMarkdown(data);\n return true;\n }\n\n editor.pasteText(data);\n return true;\n}\n\nexport const createPasteFromClipboardExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n pasteHandler: Exclude<\n BlockNoteEditorOptions<any, any, any>[\"pasteHandler\"],\n undefined\n >,\n) =>\n Extension.create({\n name: \"pasteFromClipboard\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n paste(_view, event) {\n event.preventDefault();\n\n if (!editor.isEditable) {\n return;\n }\n\n return pasteHandler({\n event,\n editor,\n defaultPasteHandler: ({\n prioritizeMarkdownOverHTML = true,\n plainTextAsMarkdown = true,\n } = {}) => {\n return defaultPasteHandler({\n event,\n editor,\n prioritizeMarkdownOverHTML,\n plainTextAsMarkdown,\n });\n },\n });\n },\n },\n },\n }),\n ];\n },\n });\n","import { Fragment } from \"@tiptap/pm/model\";\nimport {\n BlockNoDefaults,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { getPmSchema } from \"../pmUtil.js\";\nimport { nodeToBlock } from \"./nodeToBlock.js\";\n\n/**\n * Converts all Blocks within a fragment to BlockNote blocks.\n */\nexport function fragmentToBlocks<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(fragment: Fragment) {\n // first convert selection to blocknote-style blocks, and then\n // pass these to the exporter\n const blocks: BlockNoDefaults<B, I, S>[] = [];\n fragment.descendants((node) => {\n const pmSchema = getPmSchema(node);\n if (node.type.name === \"blockContainer\") {\n if (node.firstChild?.type.name === \"blockGroup\") {\n // selection started within a block group\n // in this case the fragment starts with:\n // <blockContainer>\n // <blockGroup>\n // <blockContainer ... />\n // <blockContainer ... />\n // </blockGroup>\n // </blockContainer>\n //\n // instead of:\n // <blockContainer>\n // <blockContent ... />\n // <blockGroup>\n // <blockContainer ... />\n // <blockContainer ... />\n // </blockGroup>\n // </blockContainer>\n //\n // so we don't need to serialize this block, just descend into the children of the blockGroup\n return true;\n }\n }\n\n if (node.type.name === \"columnList\" && node.childCount === 1) {\n // column lists with a single column should be flattened (not the entire column list has been selected)\n node.firstChild?.forEach((child) => {\n blocks.push(nodeToBlock(child, pmSchema));\n });\n return false;\n }\n\n if (node.type.isInGroup(\"bnBlock\")) {\n blocks.push(nodeToBlock(node, pmSchema));\n // don't descend into children, as they're already included in the block returned by nodeToBlock\n return false;\n }\n return true;\n });\n return blocks;\n}\n","import { Extension } from \"@tiptap/core\";\nimport { Fragment, Node } from \"prosemirror-model\";\nimport { NodeSelection, Plugin } from \"prosemirror-state\";\nimport { CellSelection } from \"prosemirror-tables\";\nimport type { EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../schema/index.js\";\nimport { createExternalHTMLExporter } from \"../../exporters/html/externalHTMLExporter.js\";\nimport { cleanHTMLToMarkdown } from \"../../exporters/markdown/markdownExporter.js\";\nimport { fragmentToBlocks } from \"../../nodeConversions/fragmentToBlocks.js\";\nimport {\n contentNodeToInlineContent,\n contentNodeToTableContent,\n} from \"../../nodeConversions/nodeToBlock.js\";\n\nfunction fragmentToExternalHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n view: EditorView,\n selectedFragment: Fragment,\n editor: BlockNoteEditor<BSchema, I, S>,\n) {\n let isWithinBlockContent = false;\n const isWithinTable = view.state.selection instanceof CellSelection;\n\n if (!isWithinTable) {\n // Checks whether block ancestry should be included when creating external\n // HTML. If the selection is within a block content node, the block ancestry\n // is excluded as we only care about the inline content.\n const fragmentWithoutParents = view.state.doc.slice(\n view.state.selection.from,\n view.state.selection.to,\n false,\n ).content;\n\n const children = [];\n for (let i = 0; i < fragmentWithoutParents.childCount; i++) {\n children.push(fragmentWithoutParents.child(i));\n }\n\n isWithinBlockContent =\n children.find(\n (child) =>\n child.type.isInGroup(\"bnBlock\") ||\n child.type.name === \"blockGroup\" ||\n child.type.spec.group === \"blockContent\",\n ) === undefined;\n if (isWithinBlockContent) {\n selectedFragment = fragmentWithoutParents;\n }\n }\n\n let externalHTML: string;\n\n const externalHTMLExporter = createExternalHTMLExporter(\n view.state.schema,\n editor,\n );\n\n if (isWithinTable) {\n if (selectedFragment.firstChild?.type.name === \"table\") {\n // contentNodeToTableContent expects the fragment of the content of a table, not the table node itself\n // but cellselection.content() returns the table node itself if all cells and columns are selected\n selectedFragment = selectedFragment.firstChild.content;\n }\n\n // first convert selection to blocknote-style table content, and then\n // pass this to the exporter\n const ic = contentNodeToTableContent(\n selectedFragment as any,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n );\n\n // Wrap in table to ensure correct parsing by spreadsheet applications\n externalHTML = `<table>${externalHTMLExporter.exportInlineContent(\n ic as any,\n {},\n )}</table>`;\n } else if (isWithinBlockContent) {\n // first convert selection to blocknote-style inline content, and then\n // pass this to the exporter\n const ic = contentNodeToInlineContent(\n selectedFragment as any,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n );\n externalHTML = externalHTMLExporter.exportInlineContent(ic, {});\n } else {\n const blocks = fragmentToBlocks(selectedFragment);\n externalHTML = externalHTMLExporter.exportBlocks(blocks, {});\n }\n return externalHTML;\n}\n\nexport function selectedFragmentToHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n view: EditorView,\n editor: BlockNoteEditor<BSchema, I, S>,\n): {\n clipboardHTML: string;\n externalHTML: string;\n markdown: string;\n} {\n // Checks if a `blockContent` node is being copied and expands\n // the selection to the parent `blockContainer` node. This is\n // for the use-case in which only a block without content is\n // selected, e.g. an image block.\n if (\n \"node\" in view.state.selection &&\n (view.state.selection.node as Node).type.spec.group === \"blockContent\"\n ) {\n editor.transact((tr) =>\n tr.setSelection(\n new NodeSelection(tr.doc.resolve(view.state.selection.from - 1)),\n ),\n );\n }\n\n // Uses default ProseMirror clipboard serialization.\n const clipboardHTML: string = view.serializeForClipboard(\n view.state.selection.content(),\n ).dom.innerHTML;\n\n const selectedFragment = view.state.selection.content().content;\n\n const externalHTML = fragmentToExternalHTML<BSchema, I, S>(\n view,\n selectedFragment,\n editor,\n );\n\n const markdown = cleanHTMLToMarkdown(externalHTML);\n\n return { clipboardHTML, externalHTML, markdown };\n}\n\nconst checkIfSelectionInNonEditableBlock = () => {\n // Let browser handle event if selection is empty (nothing\n // happens).\n const selection = window.getSelection();\n if (!selection || selection.isCollapsed) {\n return true;\n }\n\n // Let browser handle event if it's within a non-editable\n // \"island\". This means it's in selectable content within a\n // non-editable block. We only need to check one node as it's\n // not possible for the browser selection to start in an\n // editable block and end in a non-editable one.\n let node = selection.focusNode;\n while (node) {\n if (\n node instanceof HTMLElement &&\n node.getAttribute(\"contenteditable\") === \"false\"\n ) {\n return true;\n }\n\n node = node.parentElement;\n }\n\n return false;\n};\n\nconst copyToClipboard = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n view: EditorView,\n event: ClipboardEvent,\n) => {\n // Stops the default browser copy behaviour.\n event.preventDefault();\n event.clipboardData!.clearData();\n\n const { clipboardHTML, externalHTML, markdown } = selectedFragmentToHTML(\n view,\n editor,\n );\n\n // TODO: Writing to other MIME types not working in Safari for\n // some reason.\n event.clipboardData!.setData(\"blocknote/html\", clipboardHTML);\n event.clipboardData!.setData(\"text/html\", externalHTML);\n event.clipboardData!.setData(\"text/plain\", markdown);\n};\n\nexport const createCopyToClipboardExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n) =>\n Extension.create<{ editor: BlockNoteEditor<BSchema, I, S> }, undefined>({\n name: \"copyToClipboard\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n copy(view, event) {\n if (checkIfSelectionInNonEditableBlock()) {\n return true;\n }\n\n copyToClipboard(editor, view, event);\n // Prevent default PM handler to be called\n return true;\n },\n cut(view, event) {\n if (checkIfSelectionInNonEditableBlock()) {\n return true;\n }\n\n copyToClipboard(editor, view, event);\n if (view.editable) {\n view.dispatch(view.state.tr.deleteSelection());\n }\n // Prevent default PM handler to be called\n return true;\n },\n // This is for the use-case in which only a block without content\n // is selected, e.g. an image block, and dragged (not using the\n // drag handle).\n dragstart(view, event) {\n // Checks if a `NodeSelection` is active.\n if (!(\"node\" in view.state.selection)) {\n return;\n }\n\n // Checks if a `blockContent` node is being dragged.\n if (\n (view.state.selection.node as Node).type.spec.group !==\n \"blockContent\"\n ) {\n return;\n }\n\n // Expands the selection to the parent `blockContainer` node.\n editor.transact((tr) =>\n tr.setSelection(\n new NodeSelection(\n tr.doc.resolve(view.state.selection.from - 1),\n ),\n ),\n );\n\n // Stops the default browser drag start behaviour.\n event.preventDefault();\n event.dataTransfer!.clearData();\n\n const { clipboardHTML, externalHTML, markdown } =\n selectedFragmentToHTML(view, editor);\n\n // TODO: Writing to other MIME types not working in Safari for\n // some reason.\n event.dataTransfer!.setData(\"blocknote/html\", clipboardHTML);\n event.dataTransfer!.setData(\"text/html\", externalHTML);\n event.dataTransfer!.setData(\"text/plain\", markdown);\n\n // Prevent default PM handler to be called\n return true;\n },\n },\n },\n }),\n ];\n },\n });\n","import { Extension } from \"@tiptap/core\";\nimport { defaultProps } from \"../../blocks/defaultProps.js\";\n\nexport const BackgroundColorExtension = Extension.create({\n name: \"blockBackgroundColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\", \"tableCell\", \"tableHeader\"],\n attributes: {\n backgroundColor: {\n default: defaultProps.backgroundColor.default,\n parseHTML: (element) =>\n element.hasAttribute(\"data-background-color\")\n ? element.getAttribute(\"data-background-color\")\n : defaultProps.backgroundColor.default,\n renderHTML: (attributes) => {\n if (\n attributes.backgroundColor ===\n defaultProps.backgroundColor.default\n ) {\n return {};\n }\n return {\n \"data-background-color\": attributes.backgroundColor,\n };\n },\n },\n },\n },\n ];\n },\n});\n","// from https://raw.githubusercontent.com/ueberdosis/tiptap/develop/packages/core/src/EventEmitter.ts (MIT)\n\ntype StringKeyOf<T> = Extract<keyof T, string>;\ntype CallbackType<\n T extends Record<string, any>,\n EventName extends StringKeyOf<T>,\n> = T[EventName] extends any[] ? T[EventName] : [T[EventName]];\ntype CallbackFunction<\n T extends Record<string, any>,\n EventName extends StringKeyOf<T>,\n> = (...props: CallbackType<T, EventName>) => any;\n\nexport class EventEmitter<T extends Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/ban-types\n private callbacks: { [key: string]: Function[] } = {};\n\n public on<EventName extends StringKeyOf<T>>(\n event: EventName,\n fn: CallbackFunction<T, EventName>,\n ) {\n if (!this.callbacks[event]) {\n this.callbacks[event] = [];\n }\n\n this.callbacks[event].push(fn);\n\n return () => this.off(event, fn);\n }\n\n protected emit<EventName extends StringKeyOf<T>>(\n event: EventName,\n ...args: CallbackType<T, EventName>\n ) {\n const callbacks = this.callbacks[event];\n\n if (callbacks) {\n callbacks.forEach((callback) => callback.apply(this, args));\n }\n }\n\n public off<EventName extends StringKeyOf<T>>(\n event: EventName,\n fn?: CallbackFunction<T, EventName>,\n ) {\n const callbacks = this.callbacks[event];\n\n if (callbacks) {\n if (fn) {\n this.callbacks[event] = callbacks.filter((callback) => callback !== fn);\n } else {\n delete this.callbacks[event];\n }\n }\n }\n\n protected removeAllListeners(): void {\n this.callbacks = {};\n }\n}\n","import { Plugin } from \"prosemirror-state\";\nimport { EventEmitter } from \"../util/EventEmitter.js\";\n\nexport abstract class BlockNoteExtension<\n TEvent extends Record<string, any> = any,\n> extends EventEmitter<TEvent> {\n public static key(): string {\n throw new Error(\"You must implement the key method in your extension\");\n }\n\n protected addProsemirrorPlugin(plugin: Plugin) {\n this.plugins.push(plugin);\n }\n\n public readonly plugins: Plugin[] = [];\n public get priority(): number | undefined {\n return undefined;\n }\n\n // eslint-disable-next-line\n constructor(..._args: any[]) {\n super();\n // Allow subclasses to have constructors with parameters\n // without this, we can't easily implement BlockNoteEditor.extension(MyExtension) pattern\n }\n}\n","import { defaultSelectionBuilder, yCursorPlugin } from \"y-prosemirror\";\nimport { Awareness } from \"y-protocols/awareness.js\";\nimport * as Y from \"yjs\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nexport type CollaborationUser = {\n name: string;\n color: string;\n [key: string]: string;\n};\n\nexport class CursorPlugin extends BlockNoteExtension {\n public static key() {\n return \"yCursorPlugin\";\n }\n\n private provider: { awareness: Awareness };\n private recentlyUpdatedCursors: Map<\n number,\n { element: HTMLElement; hideTimeout: NodeJS.Timeout | undefined }\n >;\n constructor(\n private collaboration: {\n fragment: Y.XmlFragment;\n user: CollaborationUser;\n provider: { awareness: Awareness };\n renderCursor?: (user: CollaborationUser) => HTMLElement;\n showCursorLabels?: \"always\" | \"activity\";\n },\n ) {\n super();\n this.provider = collaboration.provider;\n this.recentlyUpdatedCursors = new Map();\n\n this.provider.awareness.setLocalStateField(\"user\", collaboration.user);\n\n if (collaboration.showCursorLabels !== \"always\") {\n this.provider.awareness.on(\n \"change\",\n ({\n updated,\n }: {\n added: Array<number>;\n updated: Array<number>;\n removed: Array<number>;\n }) => {\n for (const clientID of updated) {\n const cursor = this.recentlyUpdatedCursors.get(clientID);\n\n if (cursor) {\n cursor.element.setAttribute(\"data-active\", \"\");\n\n if (cursor.hideTimeout) {\n clearTimeout(cursor.hideTimeout);\n }\n\n this.recentlyUpdatedCursors.set(clientID, {\n element: cursor.element,\n hideTimeout: setTimeout(() => {\n cursor.element.removeAttribute(\"data-active\");\n }, 2000),\n });\n }\n }\n },\n );\n }\n\n this.addProsemirrorPlugin(\n yCursorPlugin(this.provider.awareness, {\n selectionBuilder: defaultSelectionBuilder,\n cursorBuilder: this.renderCursor,\n }),\n );\n }\n\n public get priority() {\n return 999;\n }\n\n private renderCursor = (user: CollaborationUser, clientID: number) => {\n let cursorData = this.recentlyUpdatedCursors.get(clientID);\n\n if (!cursorData) {\n const cursorElement = (\n this.collaboration.renderCursor ?? CursorPlugin.defaultCursorRender\n )(user);\n\n if (this.collaboration.showCursorLabels !== \"always\") {\n cursorElement.addEventListener(\"mouseenter\", () => {\n const cursor = this.recentlyUpdatedCursors.get(clientID)!;\n cursor.element.setAttribute(\"data-active\", \"\");\n\n if (cursor.hideTimeout) {\n clearTimeout(cursor.hideTimeout);\n this.recentlyUpdatedCursors.set(clientID, {\n element: cursor.element,\n hideTimeout: undefined,\n });\n }\n });\n\n cursorElement.addEventListener(\"mouseleave\", () => {\n const cursor = this.recentlyUpdatedCursors.get(clientID)!;\n\n this.recentlyUpdatedCursors.set(clientID, {\n element: cursor.element,\n hideTimeout: setTimeout(() => {\n cursor.element.removeAttribute(\"data-active\");\n }, 2000),\n });\n });\n }\n\n cursorData = {\n element: cursorElement,\n hideTimeout: undefined,\n };\n\n this.recentlyUpdatedCursors.set(clientID, cursorData);\n }\n\n return cursorData.element;\n };\n\n public updateUser = (user: {\n name: string;\n color: string;\n [key: string]: string;\n }) => {\n this.provider.awareness.setLocalStateField(\"user\", user);\n };\n\n public static defaultCursorRender = (user: CollaborationUser) => {\n const cursorElement = document.createElement(\"span\");\n\n cursorElement.classList.add(\"bn-collaboration-cursor__base\");\n\n const caretElement = document.createElement(\"span\");\n caretElement.setAttribute(\"contentedEditable\", \"false\");\n caretElement.classList.add(\"bn-collaboration-cursor__caret\");\n caretElement.setAttribute(\"style\", `background-color: ${user.color}`);\n\n const labelElement = document.createElement(\"span\");\n\n labelElement.classList.add(\"bn-collaboration-cursor__label\");\n labelElement.setAttribute(\"style\", `background-color: ${user.color}`);\n labelElement.insertBefore(document.createTextNode(user.name), null);\n\n caretElement.insertBefore(labelElement, null);\n\n cursorElement.insertBefore(document.createTextNode(\"\\u2060\"), null); // Non-breaking space\n cursorElement.insertBefore(caretElement, null);\n cursorElement.insertBefore(document.createTextNode(\"\\u2060\"), null); // Non-breaking space\n\n return cursorElement;\n };\n}\n","import { ySyncPlugin } from \"y-prosemirror\";\nimport type * as Y from \"yjs\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nexport class SyncPlugin extends BlockNoteExtension {\n public static key() {\n return \"ySyncPlugin\";\n }\n\n constructor(fragment: Y.XmlFragment) {\n super();\n this.addProsemirrorPlugin(ySyncPlugin(fragment));\n }\n\n public get priority() {\n return 1001;\n }\n}\n","import { yUndoPlugin } from \"y-prosemirror\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nexport class UndoPlugin extends BlockNoteExtension {\n public static key() {\n return \"yUndoPlugin\";\n }\n\n constructor() {\n super();\n this.addProsemirrorPlugin(yUndoPlugin());\n }\n\n public get priority() {\n return 1000;\n }\n}\n","import { Mark, mergeAttributes } from \"@tiptap/core\";\n\nexport const CommentMark = Mark.create({\n name: \"comment\",\n excludes: \"\",\n inclusive: false,\n keepOnSplit: true,\n\n addAttributes() {\n // Return an object with attribute configuration\n return {\n // orphans are marks that currently don't have an active thread. It could be\n // that users have resolved the thread. Resolved threads by default are not shown in the document,\n // but we need to keep the mark (positioning) data so we can still \"revive\" it when the thread is unresolved\n // or we enter a \"comments\" view that includes resolved threads.\n orphan: {\n parseHTML: (element) => !!element.getAttribute(\"data-orphan\"),\n renderHTML: (attributes) => {\n return (attributes as { orphan: boolean }).orphan\n ? {\n \"data-orphan\": \"true\",\n }\n : {};\n },\n default: false,\n },\n threadId: {\n parseHTML: (element) => element.getAttribute(\"data-bn-thread-id\"),\n renderHTML: (attributes) => {\n return {\n \"data-bn-thread-id\": (attributes as { threadId: string }).threadId,\n };\n },\n default: \"\",\n },\n };\n },\n\n renderHTML({ HTMLAttributes }: { HTMLAttributes: Record<string, any> }) {\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n class: \"bn-thread-mark\",\n }),\n ];\n },\n\n parseHTML() {\n return [{ tag: \"span.bn-thread-mark\" }];\n },\n\n extendMarkSchema(extension) {\n if (extension.name === \"comment\") {\n return {\n blocknoteIgnore: true,\n };\n }\n return {};\n },\n});\n","import type { User } from \"../../../comments/index.js\";\nimport { EventEmitter } from \"../../../util/EventEmitter.js\";\n\n/**\n * The `UserStore` is used to retrieve and cache information about users.\n *\n * It does this by calling `resolveUsers` (which is user-defined in the Editor Options)\n * for users that are not yet cached.\n */\nexport class UserStore<U extends User> extends EventEmitter<any> {\n private userCache: Map<string, U> = new Map();\n\n // avoid duplicate loads\n private loadingUsers = new Set<string>();\n\n public constructor(\n private readonly resolveUsers: (userIds: string[]) => Promise<U[]>,\n ) {\n super();\n }\n\n /**\n * Load information about users based on an array of user ids.\n */\n public async loadUsers(userIds: string[]) {\n const missingUsers = userIds.filter(\n (id) => !this.userCache.has(id) && !this.loadingUsers.has(id),\n );\n\n if (missingUsers.length === 0) {\n return;\n }\n\n for (const id of missingUsers) {\n this.loadingUsers.add(id);\n }\n\n try {\n const users = await this.resolveUsers(missingUsers);\n for (const user of users) {\n this.userCache.set(user.id, user);\n }\n this.emit(\"update\", this.userCache);\n } finally {\n for (const id of missingUsers) {\n // delete the users from the loading set\n // on a next call to `loadUsers` we will either\n // return the cached user or retry loading the user if the request failed failed\n this.loadingUsers.delete(id);\n }\n }\n }\n\n /**\n * Retrieve information about a user based on their id, if cached.\n *\n * The user will have to be loaded via `loadUsers` first\n */\n public getUser(userId: string): U | undefined {\n return this.userCache.get(userId);\n }\n\n /**\n * Subscribe to changes in the user store.\n *\n * @param cb - The callback to call when the user store changes.\n * @returns A function to unsubscribe from the user store.\n */\n public subscribe(cb: (users: Map<string, U>) => void): () => void {\n return this.on(\"update\", cb);\n }\n}\n","import { Node } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { getRelativeSelection, ySyncPluginKey } from \"y-prosemirror\";\nimport type {\n CommentBody,\n ThreadData,\n ThreadStore,\n User,\n} from \"../../comments/index.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UserStore } from \"./userstore/UserStore.js\";\n\nconst PLUGIN_KEY = new PluginKey(`blocknote-comments`);\nconst SET_SELECTED_THREAD_ID = \"SET_SELECTED_THREAD_ID\";\n\ntype CommentsPluginState = {\n /**\n * Decorations to be rendered, specifically to indicate the selected thread\n */\n decorations: DecorationSet;\n};\n\n/**\n * Calculate the thread positions from the current document state\n */\nfunction getUpdatedThreadPositions(doc: Node, markType: string) {\n const threadPositions = new Map<string, { from: number; to: number }>();\n\n // find all thread marks and store their position + create decoration for selected thread\n doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === markType) {\n const thisThreadId = (mark.attrs as { threadId: string | undefined })\n .threadId;\n if (!thisThreadId) {\n return;\n }\n const from = pos;\n const to = from + node.nodeSize;\n\n // FloatingThreads component uses \"to\" as the position, so always store the largest \"to\" found\n // AnchoredThreads component uses \"from\" as the position, so always store the smallest \"from\" found\n const currentPosition = threadPositions.get(thisThreadId) ?? {\n from: Infinity,\n to: 0,\n };\n threadPositions.set(thisThreadId, {\n from: Math.min(from, currentPosition.from),\n to: Math.max(to, currentPosition.to),\n });\n }\n });\n });\n return threadPositions;\n}\n\nexport class CommentsPlugin extends BlockNoteExtension {\n public static key() {\n return \"comments\";\n }\n\n public readonly userStore: UserStore<User>;\n\n /**\n * Whether a comment is currently being composed\n */\n private pendingComment = false;\n\n /**\n * The currently selected thread id\n */\n private selectedThreadId: string | undefined;\n\n /**\n * Store the positions of all threads in the document.\n * this can be used later to implement a floating sidebar\n */\n private threadPositions: Map<string, { from: number; to: number }> =\n new Map();\n\n private emitStateUpdate() {\n this.emit(\"update\", {\n selectedThreadId: this.selectedThreadId,\n pendingComment: this.pendingComment,\n threadPositions: this.threadPositions,\n });\n }\n\n /**\n * when a thread is resolved or deleted, we need to update the marks to reflect the new state\n */\n private updateMarksFromThreads = (threads: Map<string, ThreadData>) => {\n this.editor.transact((tr) => {\n tr.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === this.markType) {\n const markType = mark.type;\n const markThreadId = mark.attrs.threadId;\n const thread = threads.get(markThreadId);\n const isOrphan = !!(!thread || thread.resolved || thread.deletedAt);\n\n if (isOrphan !== mark.attrs.orphan) {\n const trimmedFrom = Math.max(pos, 0);\n const trimmedTo = Math.min(\n pos + node.nodeSize,\n tr.doc.content.size - 1,\n tr.doc.content.size - 1,\n );\n tr.removeMark(trimmedFrom, trimmedTo, mark);\n tr.addMark(\n trimmedFrom,\n trimmedTo,\n markType.create({\n ...mark.attrs,\n orphan: isOrphan,\n }),\n );\n\n if (isOrphan && this.selectedThreadId === markThreadId) {\n // unselect\n this.selectedThreadId = undefined;\n this.emitStateUpdate();\n }\n }\n }\n });\n });\n });\n };\n\n constructor(\n private readonly editor: BlockNoteEditor<any, any, any>,\n public readonly threadStore: ThreadStore,\n private readonly markType: string,\n ) {\n super();\n\n if (!editor.resolveUsers) {\n throw new Error(\"resolveUsers is required for comments\");\n }\n this.userStore = new UserStore<User>(editor.resolveUsers);\n\n // Note: Plugins are currently not destroyed when the editor is destroyed.\n // We should unsubscribe from the threadStore when the editor is destroyed.\n this.threadStore.subscribe(this.updateMarksFromThreads);\n\n editor.onCreate(() => {\n // Need to wait for TipTap editor state to be initialized\n this.updateMarksFromThreads(this.threadStore.getThreads());\n editor.onSelectionChange(() => {\n if (this.pendingComment) {\n this.pendingComment = false;\n this.emitStateUpdate();\n }\n });\n });\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n this.addProsemirrorPlugin(\n new Plugin<CommentsPluginState>({\n key: PLUGIN_KEY,\n state: {\n init() {\n return {\n decorations: DecorationSet.empty,\n };\n },\n apply(tr, state) {\n const action = tr.getMeta(PLUGIN_KEY);\n\n if (!tr.docChanged && !action) {\n return state;\n }\n\n // only update threadPositions if the doc changed\n const threadPositions = tr.docChanged\n ? getUpdatedThreadPositions(tr.doc, self.markType)\n : self.threadPositions;\n\n if (threadPositions.size > 0 || self.threadPositions.size > 0) {\n // small optimization; don't emit event if threadPositions before / after were both empty\n self.threadPositions = threadPositions;\n self.emitStateUpdate();\n }\n\n // update decorations if doc or selected thread changed\n const decorations = [];\n\n if (self.selectedThreadId) {\n const selectedThreadPosition = threadPositions.get(\n self.selectedThreadId,\n );\n\n if (selectedThreadPosition) {\n decorations.push(\n Decoration.inline(\n selectedThreadPosition.from,\n selectedThreadPosition.to,\n {\n class: \"bn-thread-mark-selected\",\n },\n ),\n );\n }\n }\n\n return {\n decorations: DecorationSet.create(tr.doc, decorations),\n };\n },\n },\n props: {\n decorations(state) {\n return (\n PLUGIN_KEY.getState(state)?.decorations ?? DecorationSet.empty\n );\n },\n /**\n * Handle click on a thread mark and mark it as selected\n */\n handleClick: (view, pos, event) => {\n if (event.button !== 0) {\n return;\n }\n\n const node = view.state.doc.nodeAt(pos);\n\n if (!node) {\n self.selectThread(undefined);\n return;\n }\n\n const commentMark = node.marks.find(\n (mark) =>\n mark.type.name === markType && mark.attrs.orphan !== true,\n );\n\n const threadId = commentMark?.attrs.threadId as string | undefined;\n self.selectThread(threadId, false);\n },\n },\n }),\n );\n }\n\n /**\n * Subscribe to state updates\n */\n public onUpdate(\n callback: (state: {\n pendingComment: boolean;\n selectedThreadId: string | undefined;\n threadPositions: Map<string, { from: number; to: number }>;\n }) => void,\n ) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Set the selected thread\n */\n public selectThread(threadId: string | undefined, scrollToThread = true) {\n if (this.selectedThreadId === threadId) {\n return;\n }\n this.selectedThreadId = threadId;\n this.emitStateUpdate();\n this.editor.transact((tr) =>\n tr.setMeta(PLUGIN_KEY, {\n name: SET_SELECTED_THREAD_ID,\n }),\n );\n\n if (threadId && scrollToThread) {\n const selectedThreadPosition = this.threadPositions.get(threadId);\n\n if (!selectedThreadPosition) {\n return;\n }\n\n // When a new thread is selected, scrolls the page to its reference text in\n // the editor.\n (\n this.editor.prosemirrorView?.domAtPos(selectedThreadPosition.from)\n .node as Element | undefined\n )?.scrollIntoView({\n behavior: \"smooth\",\n block: \"center\",\n });\n }\n }\n\n /**\n * Start a pending comment (e.g.: when clicking the \"Add comment\" button)\n */\n public startPendingComment() {\n this.pendingComment = true;\n this.emitStateUpdate();\n }\n\n /**\n * Stop a pending comment (e.g.: user closes the comment composer)\n */\n public stopPendingComment() {\n this.pendingComment = false;\n this.emitStateUpdate();\n }\n\n /**\n * Create a thread at the current selection\n */\n public async createThread(options: {\n initialComment: {\n body: CommentBody;\n metadata?: any;\n };\n metadata?: any;\n }) {\n const thread = await this.threadStore.createThread(options);\n\n if (this.threadStore.addThreadToDocument) {\n // creating the mark is handled by the store\n // this is useful if we don't have write-access to the document.\n // We can then offload the responsibility of creating the mark to the server.\n // (e.g.: RESTYjsThreadStore)\n const view = this.editor.prosemirrorView!;\n const pmSelection = view.state.selection;\n\n const ystate = ySyncPluginKey.getState(view.state);\n\n const selection = {\n prosemirror: {\n head: pmSelection.head,\n anchor: pmSelection.anchor,\n },\n yjs: ystate\n ? getRelativeSelection(ystate.binding, view.state)\n : undefined, // if we're not using yjs\n };\n\n await this.threadStore.addThreadToDocument({\n threadId: thread.id,\n selection,\n });\n } else {\n // we create the mark directly in the document\n this.editor._tiptapEditor.commands.setMark(this.markType, {\n orphan: false,\n threadId: thread.id,\n });\n }\n }\n}\n","import { EditorState, Plugin, PluginKey, PluginView } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport { ySyncPluginKey } from \"y-prosemirror\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport type {\n BlockFromConfig,\n FileBlockConfig,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\n\nexport type FilePanelState<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = UiElementPosition & {\n // TODO: This typing is not quite right (children should be from BSchema)\n block: BlockFromConfig<FileBlockConfig, I, S>;\n};\n\nexport class FilePanelView<I extends InlineContentSchema, S extends StyleSchema>\n implements PluginView\n{\n public state?: FilePanelState<I, S>;\n public emitUpdate: () => void;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n Record<string, FileBlockConfig>,\n I,\n S\n >,\n private readonly pluginKey: PluginKey<FilePanelState<I, S>>,\n private readonly pmView: EditorView,\n emitUpdate: (state: FilePanelState<I, S>) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized file panel\");\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.mouseDownHandler);\n pmView.dom.addEventListener(\"dragstart\", this.dragstartHandler);\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n pmView.root.addEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n mouseDownHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n // For dragging the whole editor.\n dragstartHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n const blockElement = this.pmView.root.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${this.state.block.id}\"]`,\n );\n if (!blockElement) {\n return;\n }\n this.state.referencePos = blockElement.getBoundingClientRect();\n this.emitUpdate();\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const pluginState = this.pluginKey.getState(view.state);\n const prevPluginState = this.pluginKey.getState(prevState);\n\n if (!this.state?.show && pluginState?.block && this.editor.isEditable) {\n const blockElement = this.pmView.root.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${pluginState.block.id}\"]`,\n );\n if (!blockElement) {\n return;\n }\n this.state = {\n show: true,\n referencePos: blockElement.getBoundingClientRect(),\n block: pluginState.block,\n };\n\n this.emitUpdate();\n\n return;\n }\n\n const isOpening = pluginState?.block && !prevPluginState?.block;\n const isClosing = !pluginState?.block && prevPluginState?.block;\n if (isOpening && this.state && !this.state.show) {\n this.state.show = true;\n this.emitUpdate();\n }\n if (isClosing && this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n closeMenu = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.mouseDownHandler);\n\n this.pmView.dom.removeEventListener(\"dragstart\", this.dragstartHandler);\n\n this.pmView.root.removeEventListener(\"scroll\", this.scrollHandler, true);\n }\n}\n\nconst filePanelPluginKey = new PluginKey<FilePanelState<any, any>>(\n \"FilePanelPlugin\",\n);\n\nexport class FilePanelProsemirrorPlugin<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"filePanel\";\n }\n\n private view: FilePanelView<I, S> | undefined;\n\n constructor(editor: BlockNoteEditor<Record<string, FileBlockConfig>, I, S>) {\n super();\n this.addProsemirrorPlugin(\n new Plugin<{\n block: BlockFromConfig<FileBlockConfig, I, S> | undefined;\n }>({\n key: filePanelPluginKey,\n view: (editorView) => {\n this.view = new FilePanelView<I, S>(\n editor,\n filePanelPluginKey,\n editorView,\n (state) => {\n this.emit(\"update\", state);\n },\n );\n return this.view;\n },\n props: {\n handleKeyDown: (_view, event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.shown) {\n this.view?.closeMenu();\n return true;\n }\n return false;\n },\n },\n state: {\n init: () => {\n return {\n block: undefined,\n };\n },\n apply: (transaction, prev) => {\n const state: FilePanelState<I, S> | undefined =\n transaction.getMeta(filePanelPluginKey);\n\n if (state) {\n return state;\n }\n\n if (\n !transaction.getMeta(ySyncPluginKey) &&\n (transaction.selectionSet || transaction.docChanged)\n ) {\n return { block: undefined };\n }\n return prev;\n },\n },\n }),\n );\n }\n\n public get shown() {\n return this.view?.state?.show || false;\n }\n\n public onUpdate(callback: (state: FilePanelState<I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n public closeMenu = () => this.view?.closeMenu();\n}\n","import { isNodeSelection, isTextSelection, posToDOMRect } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey, PluginView } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\n\nexport type FormattingToolbarState = UiElementPosition;\n\nexport class FormattingToolbarView implements PluginView {\n public state?: FormattingToolbarState;\n public emitUpdate: () => void;\n\n public preventHide = false;\n public preventShow = false;\n\n public shouldShow: (props: {\n view: EditorView;\n state: EditorState;\n from: number;\n to: number;\n }) => boolean = ({ view, state, from, to }) => {\n const { doc, selection } = state;\n const { empty } = selection;\n\n // Sometime check for `empty` is not enough.\n // Doubleclick an empty paragraph returns a node size of 2.\n // So we check also for an empty text size.\n const isEmptyTextBlock =\n !doc.textBetween(from, to).length && isTextSelection(state.selection);\n\n // Don't show toolbar inside code blocks\n if (\n selection.$from.parent.type.spec.code ||\n (isNodeSelection(selection) && selection.node.type.spec.code)\n ) {\n return false;\n }\n\n if (empty || isEmptyTextBlock) {\n return false;\n }\n\n const focusedElement = document.activeElement;\n if (!this.isElementWithinEditorWrapper(focusedElement) && view.editable) {\n // editable editors must have focus for the toolbar to show\n return false;\n }\n return true;\n };\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchema,\n InlineContentSchema,\n StyleSchema\n >,\n private readonly pmView: EditorView,\n emitUpdate: (state: FormattingToolbarState) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\n \"Attempting to update uninitialized formatting toolbar\",\n );\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n pmView.root.addEventListener(\"mouseup\", this.mouseupHandler);\n pmView.dom.addEventListener(\"dragstart\", this.dragHandler);\n pmView.dom.addEventListener(\"dragover\", this.dragHandler);\n pmView.dom.addEventListener(\"blur\", this.blurHandler);\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n pmView.root.addEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n blurHandler = (event: FocusEvent) => {\n if (this.preventHide) {\n this.preventHide = false;\n\n return;\n }\n\n const editorWrapper = this.pmView.dom.parentElement!;\n\n // Checks if the focus is moving to an element outside the editor. If it is,\n // the toolbar is hidden.\n if (\n // An element is clicked.\n event &&\n event.relatedTarget &&\n // Element is inside the editor.\n (editorWrapper === (event.relatedTarget as Node) ||\n editorWrapper.contains(event.relatedTarget as Node) ||\n (event.relatedTarget as HTMLElement).matches(\n \".bn-ui-container, .bn-ui-container *\",\n ))\n ) {\n return;\n }\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n isElementWithinEditorWrapper = (element: Node | null) => {\n if (!element) {\n return false;\n }\n const editorWrapper = this.pmView.dom.parentElement;\n if (!editorWrapper) {\n return false;\n }\n\n return editorWrapper.contains(element);\n };\n\n viewMousedownHandler = (e: MouseEvent) => {\n if (!this.isElementWithinEditorWrapper(e.target as Node)) {\n this.preventShow = true;\n }\n };\n\n mouseupHandler = () => {\n if (this.preventShow) {\n this.preventShow = false;\n setTimeout(() => this.update(this.pmView));\n }\n };\n\n // For dragging the whole editor.\n dragHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n this.state.referencePos = this.getSelectionBoundingBox();\n this.emitUpdate();\n }\n };\n\n update(view: EditorView, oldState?: EditorState) {\n // Delays the update to handle edge case with drag and drop, where the view\n // is blurred asynchronously and happens only after the state update.\n // Wrapping in a setTimeout gives enough time to wait for the blur event to\n // occur before updating the toolbar.\n const { state, composing } = view;\n const { doc, selection } = state;\n const isSame =\n oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection);\n\n if (composing || isSame) {\n return;\n }\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n const shouldShow = this.shouldShow({\n view,\n state,\n from,\n to,\n });\n\n // in jsdom, Range.prototype.getClientRects is not implemented,\n // this would cause `getSelectionBoundingBox` to fail\n // we can just ignore jsdom for now and not show the toolbar\n const jsdom = typeof Range.prototype.getClientRects === \"undefined\";\n\n // Checks if menu should be shown/updated.\n if (!this.preventShow && (shouldShow || this.preventHide) && !jsdom) {\n // Unlike other UI elements, we don't prevent the formatting toolbar from\n // showing when the editor is not editable. This is because some buttons,\n // e.g. the download file button, should still be accessible. Therefore,\n // logic for hiding when the editor is non-editable is handled\n // individually in each button.\n const nextState = {\n show: true,\n referencePos: this.getSelectionBoundingBox(),\n };\n\n if (\n nextState.show !== this.state?.show ||\n nextState.referencePos.toJSON() !== this.state?.referencePos.toJSON()\n ) {\n this.state = nextState;\n this.emitUpdate();\n }\n\n return;\n }\n\n // Checks if menu should be hidden.\n if (\n this.state?.show &&\n !this.preventHide &&\n (!shouldShow || this.preventShow || !this.editor.isEditable)\n ) {\n this.state.show = false;\n this.emitUpdate();\n\n return;\n }\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.viewMousedownHandler);\n this.pmView.root.removeEventListener(\"mouseup\", this.mouseupHandler);\n this.pmView.dom.removeEventListener(\"dragstart\", this.dragHandler);\n this.pmView.dom.removeEventListener(\"dragover\", this.dragHandler);\n this.pmView.dom.removeEventListener(\"blur\", this.blurHandler);\n\n this.pmView.root.removeEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n closeMenu = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n getSelectionBoundingBox() {\n const { state } = this.pmView;\n const { selection } = state;\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n if (isNodeSelection(selection)) {\n const node = this.pmView.nodeDOM(from) as HTMLElement;\n if (node) {\n return node.getBoundingClientRect();\n }\n }\n\n return posToDOMRect(this.pmView, from, to);\n }\n}\n\nexport const formattingToolbarPluginKey = new PluginKey(\n \"FormattingToolbarPlugin\",\n);\n\nexport class FormattingToolbarProsemirrorPlugin extends BlockNoteExtension {\n public static key() {\n return \"formattingToolbar\";\n }\n\n private view: FormattingToolbarView | undefined;\n\n constructor(editor: BlockNoteEditor<any, any, any>) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: formattingToolbarPluginKey,\n view: (editorView) => {\n this.view = new FormattingToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n props: {\n handleKeyDown: (_view, event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.shown) {\n this.view!.closeMenu();\n return true;\n }\n return false;\n },\n },\n }),\n );\n }\n\n public get shown() {\n return this.view?.state?.show || false;\n }\n\n public onUpdate(callback: (state: FormattingToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n\n public closeMenu = () => this.view!.closeMenu();\n}\n","// Stripped down version of the TipTap HardBreak extension:\n// https://github.com/ueberdosis/tiptap/blob/f3258d9ee5fb7979102fe63434f6ea4120507311/packages/extension-hard-break/src/hard-break.ts#L80\n// Changes:\n// - Removed options\n// - Removed keyboard shortcuts & moved them to the `KeyboardShortcutsExtension`\n// - Removed `setHardBreak` command (added a simpler version in the Shift+Enter\n// handler in `KeyboardShortcutsExtension`).\n// - Added priority\nimport { mergeAttributes, Node } from \"@tiptap/core\";\n\nexport const HardBreak = Node.create({\n name: \"hardBreak\",\n\n inline: true,\n\n group: \"inline\",\n\n selectable: false,\n\n linebreakReplacement: true,\n\n priority: 10,\n\n parseHTML() {\n return [{ tag: \"br\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"br\", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];\n },\n\n renderText() {\n return \"\\n\";\n },\n});\n","import { Node } from \"prosemirror-model\";\nimport { EditorState } from \"prosemirror-state\";\n\nimport {\n BlockInfo,\n getBlockInfoFromResolvedPos,\n} from \"../../../getBlockInfoFromPos.js\";\n\n/**\n * Returns the block info from the parent block\n * or undefined if we're at the root\n */\nexport const getParentBlockInfo = (doc: Node, beforePos: number) => {\n const $pos = doc.resolve(beforePos);\n\n if ($pos.depth <= 1) {\n return undefined;\n }\n\n // get start pos of parent\n const parentBeforePos = $pos.posAtIndex(\n $pos.index($pos.depth - 1),\n $pos.depth - 1,\n );\n\n const parentBlockInfo = getBlockInfoFromResolvedPos(\n doc.resolve(parentBeforePos),\n );\n return parentBlockInfo;\n};\n\n/**\n * Returns the block info from the sibling block before (above) the given block,\n * or undefined if the given block is the first sibling.\n */\nexport const getPrevBlockInfo = (doc: Node, beforePos: number) => {\n const $pos = doc.resolve(beforePos);\n\n const indexInParent = $pos.index();\n\n if (indexInParent === 0) {\n return undefined;\n }\n\n const prevBlockBeforePos = $pos.posAtIndex(indexInParent - 1);\n\n const prevBlockInfo = getBlockInfoFromResolvedPos(\n doc.resolve(prevBlockBeforePos),\n );\n return prevBlockInfo;\n};\n\n/**\n * If a block has children like this:\n * A\n * - B\n * - C\n * -- D\n *\n * Then the bottom nested block returned is D.\n */\nexport const getBottomNestedBlockInfo = (doc: Node, blockInfo: BlockInfo) => {\n while (blockInfo.childContainer) {\n const group = blockInfo.childContainer.node;\n\n const newPos = doc\n .resolve(blockInfo.childContainer.beforePos + 1)\n .posAtIndex(group.childCount - 1);\n blockInfo = getBlockInfoFromResolvedPos(doc.resolve(newPos));\n }\n\n return blockInfo;\n};\n\nconst canMerge = (prevBlockInfo: BlockInfo, nextBlockInfo: BlockInfo) => {\n return (\n prevBlockInfo.isBlockContainer &&\n prevBlockInfo.blockContent.node.type.spec.content === \"inline*\" &&\n prevBlockInfo.blockContent.node.childCount > 0 &&\n nextBlockInfo.isBlockContainer &&\n nextBlockInfo.blockContent.node.type.spec.content === \"inline*\"\n );\n};\n\nconst mergeBlocks = (\n state: EditorState,\n dispatch: ((args?: any) => any) | undefined,\n prevBlockInfo: BlockInfo,\n nextBlockInfo: BlockInfo,\n) => {\n // Un-nests all children of the next block.\n if (!nextBlockInfo.isBlockContainer) {\n throw new Error(\n `Attempted to merge block at position ${nextBlockInfo.bnBlock.beforePos} into previous block at position ${prevBlockInfo.bnBlock.beforePos}, but next block is not a block container`,\n );\n }\n\n // Removes a level of nesting all children of the next block by 1 level, if it contains both content and block\n // group nodes.\n if (nextBlockInfo.childContainer) {\n const childBlocksStart = state.doc.resolve(\n nextBlockInfo.childContainer.beforePos + 1,\n );\n const childBlocksEnd = state.doc.resolve(\n nextBlockInfo.childContainer.afterPos - 1,\n );\n const childBlocksRange = childBlocksStart.blockRange(childBlocksEnd);\n\n if (dispatch) {\n const pos = state.doc.resolve(nextBlockInfo.bnBlock.beforePos);\n state.tr.lift(childBlocksRange!, pos.depth);\n }\n }\n\n // Deletes the boundary between the two blocks. Can be thought of as\n // removing the closing tags of the first block and the opening tags of the\n // second one to stitch them together.\n if (dispatch) {\n if (!prevBlockInfo.isBlockContainer) {\n throw new Error(\n `Attempted to merge block at position ${nextBlockInfo.bnBlock.beforePos} into previous block at position ${prevBlockInfo.bnBlock.beforePos}, but previous block is not a block container`,\n );\n }\n\n // TODO: test merging between a columnList and paragraph, between two columnLists, and v.v.\n dispatch(\n state.tr.delete(\n prevBlockInfo.blockContent.afterPos - 1,\n nextBlockInfo.blockContent.beforePos + 1,\n ),\n );\n }\n\n return true;\n};\n\nexport const mergeBlocksCommand =\n (posBetweenBlocks: number) =>\n ({\n state,\n dispatch,\n }: {\n state: EditorState;\n dispatch: ((args?: any) => any) | undefined;\n }) => {\n const $pos = state.doc.resolve(posBetweenBlocks);\n const nextBlockInfo = getBlockInfoFromResolvedPos($pos);\n\n const prevBlockInfo = getPrevBlockInfo(\n state.doc,\n nextBlockInfo.bnBlock.beforePos,\n );\n\n if (!prevBlockInfo) {\n return false;\n }\n\n const bottomNestedBlockInfo = getBottomNestedBlockInfo(\n state.doc,\n prevBlockInfo,\n );\n\n if (!canMerge(bottomNestedBlockInfo, nextBlockInfo)) {\n return false;\n }\n\n return mergeBlocks(state, dispatch, bottomNestedBlockInfo, nextBlockInfo);\n };\n","import { Extension } from \"@tiptap/core\";\n\nimport { TextSelection } from \"prosemirror-state\";\nimport { ReplaceAroundStep } from \"prosemirror-transform\";\nimport {\n getBottomNestedBlockInfo,\n getParentBlockInfo,\n getPrevBlockInfo,\n mergeBlocksCommand,\n} from \"../../api/blockManipulation/commands/mergeBlocks/mergeBlocks.js\";\nimport { nestBlock } from \"../../api/blockManipulation/commands/nestBlock/nestBlock.js\";\nimport { splitBlockCommand } from \"../../api/blockManipulation/commands/splitBlock/splitBlock.js\";\nimport { updateBlockCommand } from \"../../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport { getBlockInfoFromSelection } from \"../../api/getBlockInfoFromPos.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\n\nexport const KeyboardShortcutsExtension = Extension.create<{\n editor: BlockNoteEditor<any, any, any>;\n tabBehavior: \"prefer-navigate-ui\" | \"prefer-indent\";\n}>({\n priority: 50,\n\n // TODO: The shortcuts need a refactor. Do we want to use a command priority\n // design as there is now, or clump the logic into a single function?\n addKeyboardShortcuts() {\n // handleBackspace is partially adapted from https://github.com/ueberdosis/tiptap/blob/ed56337470efb4fd277128ab7ef792b37cfae992/packages/core/src/extensions/keymap.ts\n const handleBackspace = () =>\n this.editor.commands.first(({ chain, commands }) => [\n // Deletes the selection if it's not empty.\n () => commands.deleteSelection(),\n // Undoes an input rule if one was triggered in the last editor state change.\n () => commands.undoInputRule(),\n // Reverts block content type to a paragraph if the selection is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n\n const selectionAtBlockStart =\n state.selection.from === blockInfo.blockContent.beforePos + 1;\n const isParagraph =\n blockInfo.blockContent.node.type.name === \"paragraph\";\n\n if (selectionAtBlockStart && !isParagraph) {\n return commands.command(\n updateBlockCommand(blockInfo.bnBlock.beforePos, {\n type: \"paragraph\",\n props: {},\n }),\n );\n }\n\n return false;\n }),\n // Removes a level of nesting if the block is indented if the selection is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { blockContent } = blockInfo;\n\n const selectionAtBlockStart =\n state.selection.from === blockContent.beforePos + 1;\n\n if (selectionAtBlockStart) {\n return commands.liftListItem(\"blockContainer\");\n }\n\n return false;\n }),\n // Merges block with the previous one if it isn't indented, and the selection is at the start of the\n // block. The target block for merging must contain inline content.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { bnBlock: blockContainer, blockContent } = blockInfo;\n\n const selectionAtBlockStart =\n state.selection.from === blockContent.beforePos + 1;\n const selectionEmpty = state.selection.empty;\n\n const posBetweenBlocks = blockContainer.beforePos;\n\n if (selectionAtBlockStart && selectionEmpty) {\n return chain()\n .command(mergeBlocksCommand(posBetweenBlocks))\n .scrollIntoView()\n .run();\n }\n\n return false;\n }),\n () =>\n commands.command(({ state, dispatch }) => {\n // when at the start of a first block in a column\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n\n const selectionAtBlockStart =\n state.selection.from === blockInfo.blockContent.beforePos + 1;\n\n if (!selectionAtBlockStart) {\n return false;\n }\n\n const prevBlockInfo = getPrevBlockInfo(\n state.doc,\n blockInfo.bnBlock.beforePos,\n );\n\n if (prevBlockInfo) {\n // should be no previous block\n return false;\n }\n\n const parentBlockInfo = getParentBlockInfo(\n state.doc,\n blockInfo.bnBlock.beforePos,\n );\n\n if (parentBlockInfo?.blockNoteType !== \"column\") {\n return false;\n }\n\n const column = parentBlockInfo;\n\n const columnList = getParentBlockInfo(\n state.doc,\n column.bnBlock.beforePos,\n );\n if (columnList?.blockNoteType !== \"columnList\") {\n throw new Error(\"parent of column is not a column list\");\n }\n\n const shouldRemoveColumn =\n column.childContainer!.node.childCount === 1;\n\n const shouldRemoveColumnList =\n shouldRemoveColumn &&\n columnList.childContainer!.node.childCount === 2;\n\n const isFirstColumn =\n columnList.childContainer!.node.firstChild ===\n column.bnBlock.node;\n\n if (dispatch) {\n const blockToMove = state.doc.slice(\n blockInfo.bnBlock.beforePos,\n blockInfo.bnBlock.afterPos,\n false,\n );\n\n /*\n There are 3 different cases:\n a) remove entire column list (if no columns would be remaining)\n b) remove just a column (if no blocks inside a column would be remaining)\n c) keep columns (if there are blocks remaining inside a column)\n\n Each of these 3 cases has 2 sub-cases, depending on whether the backspace happens at the start of the first (most-left) column,\n or at the start of a non-first column.\n */\n if (shouldRemoveColumnList) {\n if (isFirstColumn) {\n state.tr.step(\n new ReplaceAroundStep(\n // replace entire column list\n columnList.bnBlock.beforePos,\n columnList.bnBlock.afterPos,\n // select content of remaining column:\n column.bnBlock.afterPos + 1,\n columnList.bnBlock.afterPos - 2,\n blockToMove,\n blockToMove.size, // append existing content to blockToMove\n false,\n ),\n );\n const pos = state.tr.doc.resolve(column.bnBlock.beforePos);\n state.tr.setSelection(TextSelection.between(pos, pos));\n } else {\n // replaces the column list with the blockToMove slice, prepended with the content of the remaining column\n state.tr.step(\n new ReplaceAroundStep(\n // replace entire column list\n columnList.bnBlock.beforePos,\n columnList.bnBlock.afterPos,\n // select content of existing column:\n columnList.bnBlock.beforePos + 2,\n column.bnBlock.beforePos - 1,\n blockToMove,\n 0, // prepend existing content to blockToMove\n false,\n ),\n );\n const pos = state.tr.doc.resolve(\n state.tr.mapping.map(column.bnBlock.beforePos - 1),\n );\n state.tr.setSelection(TextSelection.between(pos, pos));\n }\n } else if (shouldRemoveColumn) {\n if (isFirstColumn) {\n // delete column\n state.tr.delete(\n column.bnBlock.beforePos,\n column.bnBlock.afterPos,\n );\n\n // move before columnlist\n state.tr.insert(\n columnList.bnBlock.beforePos,\n blockToMove.content,\n );\n\n const pos = state.tr.doc.resolve(\n columnList.bnBlock.beforePos,\n );\n state.tr.setSelection(TextSelection.between(pos, pos));\n } else {\n // just delete the </column><column> closing and opening tags to merge the columns\n state.tr.delete(\n column.bnBlock.beforePos - 1,\n column.bnBlock.beforePos + 1,\n );\n }\n } else {\n // delete block\n state.tr.delete(\n blockInfo.bnBlock.beforePos,\n blockInfo.bnBlock.afterPos,\n );\n if (isFirstColumn) {\n // move before columnlist\n state.tr.insert(\n columnList.bnBlock.beforePos - 1,\n blockToMove.content,\n );\n } else {\n // append block to previous column\n state.tr.insert(\n column.bnBlock.beforePos - 1,\n blockToMove.content,\n );\n }\n const pos = state.tr.doc.resolve(column.bnBlock.beforePos - 1);\n state.tr.setSelection(TextSelection.between(pos, pos));\n }\n }\n\n return true;\n }),\n // Deletes the current block if it's an empty block with inline content,\n // and moves the selection to the previous block.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n\n const blockEmpty =\n blockInfo.blockContent.node.childCount === 0 &&\n blockInfo.blockContent.node.type.spec.content === \"inline*\";\n\n if (blockEmpty) {\n const prevBlockInfo = getPrevBlockInfo(\n state.doc,\n blockInfo.bnBlock.beforePos,\n );\n if (!prevBlockInfo || !prevBlockInfo.isBlockContainer) {\n return false;\n }\n\n let chainedCommands = chain();\n\n if (\n prevBlockInfo.blockContent.node.type.spec.content ===\n \"tableRow+\"\n ) {\n const tableBlockEndPos = blockInfo.bnBlock.beforePos - 1;\n const tableBlockContentEndPos = tableBlockEndPos - 1;\n const lastRowEndPos = tableBlockContentEndPos - 1;\n const lastCellEndPos = lastRowEndPos - 1;\n const lastCellParagraphEndPos = lastCellEndPos - 1;\n\n chainedCommands = chainedCommands.setTextSelection(\n lastCellParagraphEndPos,\n );\n } else if (\n prevBlockInfo.blockContent.node.type.spec.content === \"\"\n ) {\n const nonEditableBlockContentStartPos =\n prevBlockInfo.blockContent.afterPos -\n prevBlockInfo.blockContent.node.nodeSize;\n\n chainedCommands = chainedCommands.setNodeSelection(\n nonEditableBlockContentStartPos,\n );\n } else {\n const blockContentStartPos =\n prevBlockInfo.blockContent.afterPos -\n prevBlockInfo.blockContent.node.nodeSize;\n\n chainedCommands =\n chainedCommands.setTextSelection(blockContentStartPos);\n }\n\n return chainedCommands\n .deleteRange({\n from: blockInfo.bnBlock.beforePos,\n to: blockInfo.bnBlock.afterPos,\n })\n .scrollIntoView()\n .run();\n }\n\n return false;\n }),\n // Deletes previous block if it contains no content and isn't a table,\n // when the selection is empty and at the start of the block. Moves the\n // current block into the deleted block's place.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n\n if (!blockInfo.isBlockContainer) {\n // TODO\n throw new Error(`todo`);\n }\n\n const selectionAtBlockStart =\n state.selection.from === blockInfo.blockContent.beforePos + 1;\n const selectionEmpty = state.selection.empty;\n\n const prevBlockInfo = getPrevBlockInfo(\n state.doc,\n blockInfo.bnBlock.beforePos,\n );\n\n if (prevBlockInfo && selectionAtBlockStart && selectionEmpty) {\n const bottomBlock = getBottomNestedBlockInfo(\n state.doc,\n prevBlockInfo,\n );\n\n if (!bottomBlock.isBlockContainer) {\n // TODO\n throw new Error(`todo`);\n }\n\n const prevBlockNotTableAndNoContent =\n bottomBlock.blockContent.node.type.spec.content === \"\" ||\n (bottomBlock.blockContent.node.type.spec.content ===\n \"inline*\" &&\n bottomBlock.blockContent.node.childCount === 0);\n\n if (prevBlockNotTableAndNoContent) {\n return chain()\n .cut(\n {\n from: blockInfo.bnBlock.beforePos,\n to: blockInfo.bnBlock.afterPos,\n },\n bottomBlock.bnBlock.afterPos,\n )\n .deleteRange({\n from: bottomBlock.bnBlock.beforePos,\n to: bottomBlock.bnBlock.afterPos,\n })\n .run();\n }\n }\n\n return false;\n }),\n ]);\n\n const handleDelete = () =>\n this.editor.commands.first(({ commands }) => [\n // Deletes the selection if it's not empty.\n () => commands.deleteSelection(),\n // Merges block with the next one (at the same nesting level or lower),\n // if one exists, the block has no children, and the selection is at the\n // end of the block.\n () =>\n commands.command(({ state }) => {\n // TODO: Change this to not rely on offsets & schema assumptions\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const {\n bnBlock: blockContainer,\n blockContent,\n childContainer,\n } = blockInfo;\n\n const { depth } = state.doc.resolve(blockContainer.beforePos);\n const blockAtDocEnd =\n blockContainer.afterPos === state.doc.nodeSize - 3;\n const selectionAtBlockEnd =\n state.selection.from === blockContent.afterPos - 1;\n const selectionEmpty = state.selection.empty;\n const hasChildBlocks = childContainer !== undefined;\n\n if (\n !blockAtDocEnd &&\n selectionAtBlockEnd &&\n selectionEmpty &&\n !hasChildBlocks\n ) {\n let oldDepth = depth;\n let newPos = blockContainer.afterPos + 1;\n let newDepth = state.doc.resolve(newPos).depth;\n\n while (newDepth < oldDepth) {\n oldDepth = newDepth;\n newPos += 2;\n newDepth = state.doc.resolve(newPos).depth;\n }\n\n return commands.command(mergeBlocksCommand(newPos - 1));\n }\n\n return false;\n }),\n ]);\n\n const handleEnter = (withShift = false) => {\n return this.editor.commands.first(({ commands }) => [\n // Removes a level of nesting if the block is empty & indented, while the selection is also empty & at the start\n // of the block.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { bnBlock: blockContainer, blockContent } = blockInfo;\n\n const { depth } = state.doc.resolve(blockContainer.beforePos);\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\n const blockEmpty = blockContent.node.childCount === 0;\n const blockIndented = depth > 1;\n\n if (\n selectionAtBlockStart &&\n selectionEmpty &&\n blockEmpty &&\n blockIndented\n ) {\n return commands.liftListItem(\"blockContainer\");\n }\n\n return false;\n }),\n // Creates a hard break if block is configured to do so.\n () =>\n commands.command(({ state }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n\n const blockHardBreakShortcut: \"shift+enter\" | \"enter\" | \"none\" =\n this.options.editor.schema.blockSchema[blockInfo.blockNoteType]\n .hardBreakShortcut ?? \"shift+enter\";\n\n if (blockHardBreakShortcut === \"none\") {\n return false;\n }\n\n if (\n // If shortcut is not configured, or is configured as \"shift+enter\",\n // create a hard break for shift+enter, but not for enter.\n (blockHardBreakShortcut === \"shift+enter\" && withShift) ||\n // If shortcut is configured as \"enter\", create a hard break for\n // both enter and shift+enter.\n blockHardBreakShortcut === \"enter\"\n ) {\n return commands.insertContent({\n type: \"hardBreak\",\n });\n }\n\n return false;\n }),\n // Creates a new block and moves the selection to it if the current one is empty, while the selection is also\n // empty & at the start of the block.\n () =>\n commands.command(({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { bnBlock: blockContainer, blockContent } = blockInfo;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\n const blockEmpty = blockContent.node.childCount === 0;\n\n if (selectionAtBlockStart && selectionEmpty && blockEmpty) {\n const newBlockInsertionPos = blockContainer.afterPos;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n if (dispatch) {\n const newBlock =\n state.schema.nodes[\"blockContainer\"].createAndFill()!;\n\n state.tr\n .insert(newBlockInsertionPos, newBlock)\n .scrollIntoView();\n state.tr.setSelection(\n new TextSelection(state.doc.resolve(newBlockContentPos)),\n );\n }\n\n return true;\n }\n\n return false;\n }),\n // Splits the current block, moving content inside that's after the cursor to a new text block below. Also\n // deletes the selection beforehand, if it's not empty.\n () =>\n commands.command(({ state, chain }) => {\n const blockInfo = getBlockInfoFromSelection(state);\n if (!blockInfo.isBlockContainer) {\n return false;\n }\n const { blockContent } = blockInfo;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const blockEmpty = blockContent.node.childCount === 0;\n\n if (!blockEmpty) {\n chain()\n .deleteSelection()\n .command(\n splitBlockCommand(\n state.selection.from,\n selectionAtBlockStart,\n selectionAtBlockStart,\n ),\n )\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n };\n\n return {\n Backspace: handleBackspace,\n Delete: handleDelete,\n Enter: () => handleEnter(),\n \"Shift-Enter\": () => handleEnter(true),\n // Always returning true for tab key presses ensures they're not captured by the browser. Otherwise, they blur the\n // editor since the browser will try to use tab for keyboard navigation.\n Tab: () => {\n if (\n this.options.tabBehavior !== \"prefer-indent\" &&\n (this.options.editor.formattingToolbar?.shown ||\n this.options.editor.linkToolbar?.shown ||\n this.options.editor.filePanel?.shown)\n ) {\n // don't handle tabs if a toolbar is shown, so we can tab into / out of it\n return false;\n }\n return nestBlock(this.options.editor);\n // return true;\n },\n \"Shift-Tab\": () => {\n if (\n this.options.tabBehavior !== \"prefer-indent\" &&\n (this.options.editor.formattingToolbar?.shown ||\n this.options.editor.linkToolbar?.shown ||\n this.options.editor.filePanel?.shown)\n ) {\n // don't handle tabs if a toolbar is shown, so we can tab into / out of it\n return false;\n }\n this.editor.commands.liftListItem(\"blockContainer\");\n return true;\n },\n \"Shift-Mod-ArrowUp\": () => {\n this.options.editor.moveBlocksUp();\n return true;\n },\n \"Shift-Mod-ArrowDown\": () => {\n this.options.editor.moveBlocksDown();\n return true;\n },\n \"Mod-z\": () => this.options.editor.undo(),\n \"Mod-y\": () => this.options.editor.redo(),\n \"Shift-Mod-z\": () => this.options.editor.redo(),\n };\n },\n});\n","import { getMarkRange, posToDOMRect, Range } from \"@tiptap/core\";\n\nimport { EditorView } from \"@tiptap/pm/view\";\nimport { Mark } from \"prosemirror-model\";\nimport { EditorState, Plugin, PluginKey, PluginView } from \"prosemirror-state\";\n\nimport { getPmSchema } from \"../../api/pmUtil.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\n\nexport type LinkToolbarState = UiElementPosition & {\n // The hovered link's URL, and the text it's displayed with in the\n // editor.\n url: string;\n text: string;\n};\n\nclass LinkToolbarView implements PluginView {\n public state?: LinkToolbarState;\n public emitUpdate: () => void;\n\n menuUpdateTimer: ReturnType<typeof setTimeout> | undefined;\n startMenuUpdateTimer: () => void;\n stopMenuUpdateTimer: () => void;\n\n mouseHoveredLinkMark: Mark | undefined;\n mouseHoveredLinkMarkRange: Range | undefined;\n\n keyboardHoveredLinkMark: Mark | undefined;\n keyboardHoveredLinkMarkRange: Range | undefined;\n\n linkMark: Mark | undefined;\n linkMarkRange: Range | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<any, any, any>,\n private readonly pmView: EditorView,\n emitUpdate: (state: LinkToolbarState) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized link toolbar\");\n }\n\n emitUpdate(this.state);\n };\n\n this.startMenuUpdateTimer = () => {\n this.menuUpdateTimer = setTimeout(() => {\n this.update(this.pmView, undefined, true);\n }, 250);\n };\n\n this.stopMenuUpdateTimer = () => {\n if (this.menuUpdateTimer) {\n clearTimeout(this.menuUpdateTimer);\n this.menuUpdateTimer = undefined;\n }\n\n return false;\n };\n\n this.pmView.dom.addEventListener(\"mouseover\", this.mouseOverHandler);\n this.pmView.root.addEventListener(\n \"click\",\n this.clickHandler as EventListener,\n true,\n );\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n this.pmView.root.addEventListener(\"scroll\", this.scrollHandler, true);\n }\n\n mouseOverHandler = (event: MouseEvent) => {\n // Resets the link mark currently hovered by the mouse cursor.\n this.mouseHoveredLinkMark = undefined;\n this.mouseHoveredLinkMarkRange = undefined;\n\n this.stopMenuUpdateTimer();\n\n if (\n event.target instanceof HTMLAnchorElement &&\n event.target.nodeName === \"A\"\n ) {\n // Finds link mark at the hovered element's position to update mouseHoveredLinkMark and\n // mouseHoveredLinkMarkRange.\n const hoveredLinkElement = event.target;\n const posInHoveredLinkMark =\n this.pmView.posAtDOM(hoveredLinkElement, 0) + 1;\n const resolvedPosInHoveredLinkMark =\n this.pmView.state.doc.resolve(posInHoveredLinkMark);\n const marksAtPos = resolvedPosInHoveredLinkMark.marks();\n\n for (const mark of marksAtPos) {\n if (\n mark.type.name === this.pmView.state.schema.mark(\"link\").type.name\n ) {\n this.mouseHoveredLinkMark = mark;\n this.mouseHoveredLinkMarkRange =\n getMarkRange(resolvedPosInHoveredLinkMark, mark.type, mark.attrs) ||\n undefined;\n\n break;\n }\n }\n }\n\n this.startMenuUpdateTimer();\n\n return false;\n };\n\n clickHandler = (event: MouseEvent) => {\n const editorWrapper = this.pmView.dom.parentElement!;\n\n if (\n // Toolbar is open.\n this.linkMark &&\n // An element is clicked.\n event &&\n event.target &&\n // The clicked element is not the editor.\n !(\n editorWrapper === (event.target as Node) ||\n editorWrapper.contains(event.target as Node)\n )\n ) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n };\n\n scrollHandler = () => {\n if (this.linkMark !== undefined) {\n if (this.state?.show) {\n this.state.referencePos = posToDOMRect(\n this.pmView,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n );\n this.emitUpdate();\n }\n }\n };\n\n editLink(url: string, text: string) {\n this.editor.transact((tr) => {\n const pmSchema = getPmSchema(tr);\n tr.insertText(text, this.linkMarkRange!.from, this.linkMarkRange!.to);\n tr.addMark(\n this.linkMarkRange!.from,\n this.linkMarkRange!.from + text.length,\n pmSchema.mark(\"link\", { href: url }),\n );\n });\n this.pmView.focus();\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n deleteLink() {\n this.editor.transact((tr) =>\n tr\n .removeMark(\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n this.linkMark!.type,\n )\n .setMeta(\"preventAutolink\", true),\n );\n this.pmView.focus();\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n update(view: EditorView, oldState?: EditorState, fromMouseOver = false) {\n const { state } = view;\n\n const isSame =\n oldState &&\n oldState.selection.from === state.selection.from &&\n oldState.selection.to === state.selection.to;\n\n if (isSame || !this.pmView.hasFocus()) {\n return;\n }\n\n // Saves the currently hovered link mark before it's updated.\n const prevLinkMark = this.linkMark;\n\n // Resets the currently hovered link mark.\n this.linkMark = undefined;\n this.linkMarkRange = undefined;\n\n // Resets the link mark currently hovered by the keyboard cursor.\n this.keyboardHoveredLinkMark = undefined;\n this.keyboardHoveredLinkMarkRange = undefined;\n\n // Finds link mark at the editor selection's position to update keyboardHoveredLinkMark and\n // keyboardHoveredLinkMarkRange.\n if (this.pmView.state.selection.empty) {\n const marksAtPos = this.pmView.state.selection.$from.marks();\n\n for (const mark of marksAtPos) {\n if (\n mark.type.name === this.pmView.state.schema.mark(\"link\").type.name\n ) {\n this.keyboardHoveredLinkMark = mark;\n this.keyboardHoveredLinkMarkRange =\n getMarkRange(\n this.pmView.state.selection.$from,\n mark.type,\n mark.attrs,\n ) || undefined;\n\n break;\n }\n }\n }\n\n if (this.mouseHoveredLinkMark && fromMouseOver) {\n this.linkMark = this.mouseHoveredLinkMark;\n this.linkMarkRange = this.mouseHoveredLinkMarkRange;\n }\n\n // Keyboard cursor position takes precedence over mouse hovered link.\n if (this.keyboardHoveredLinkMark) {\n this.linkMark = this.keyboardHoveredLinkMark;\n this.linkMarkRange = this.keyboardHoveredLinkMarkRange;\n }\n\n if (this.linkMark && this.editor.isEditable) {\n this.state = {\n show: true,\n referencePos: posToDOMRect(\n this.pmView,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n ),\n url: this.linkMark!.attrs.href,\n text: this.pmView.state.doc.textBetween(\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n ),\n };\n this.emitUpdate();\n\n return;\n }\n\n // Hides menu.\n if (\n this.state?.show &&\n prevLinkMark &&\n (!this.linkMark || !this.editor.isEditable)\n ) {\n this.state.show = false;\n this.emitUpdate();\n\n return;\n }\n }\n\n closeMenu = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mouseover\", this.mouseOverHandler);\n this.pmView.root.removeEventListener(\"scroll\", this.scrollHandler, true);\n this.pmView.root.removeEventListener(\n \"click\",\n this.clickHandler as EventListener,\n true,\n );\n }\n}\n\nexport const linkToolbarPluginKey = new PluginKey(\"LinkToolbarPlugin\");\n\nexport class LinkToolbarProsemirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"linkToolbar\";\n }\n\n private view: LinkToolbarView | undefined;\n\n constructor(editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: linkToolbarPluginKey,\n view: (editorView) => {\n this.view = new LinkToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n props: {\n handleKeyDown: (_view, event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.shown) {\n this.view!.closeMenu();\n return true;\n }\n return false;\n },\n },\n }),\n );\n }\n\n public onUpdate(callback: (state: LinkToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Edit the currently hovered link.\n */\n public editLink = (url: string, text: string) => {\n this.view!.editLink(url, text);\n };\n\n /**\n * Delete the currently hovered link.\n */\n public deleteLink = () => {\n this.view!.deleteLink();\n };\n\n /**\n * When hovering on/off links using the mouse cursor, the link toolbar will\n * open & close with a delay.\n *\n * This function starts the delay timer, and should be used for when the mouse\n * cursor enters the link toolbar.\n */\n public startHideTimer = () => {\n this.view!.startMenuUpdateTimer();\n };\n\n /**\n * When hovering on/off links using the mouse cursor, the link toolbar will\n * open & close with a delay.\n *\n * This function stops the delay timer, and should be used for when the mouse\n * cursor exits the link toolbar.\n */\n public stopHideTimer = () => {\n this.view!.stopMenuUpdateTimer();\n };\n\n public get shown() {\n return this.view?.state?.show || false;\n }\n\n public closeMenu = () => this.view!.closeMenu();\n}\n","export const VALID_LINK_PROTOCOLS = [\n \"http\",\n \"https\",\n \"ftp\",\n \"ftps\",\n \"mailto\",\n \"tel\",\n \"callto\",\n \"sms\",\n \"cid\",\n \"xmpp\",\n];\nexport const DEFAULT_LINK_PROTOCOL = \"https\";\n","import { Plugin, PluginKey, TextSelection } from \"prosemirror-state\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nconst PLUGIN_KEY = new PluginKey(\"node-selection-keyboard\");\n// By default, typing with a node selection active will cause ProseMirror to\n// replace the node with one that contains editable content. This plugin blocks\n// this behaviour without also blocking things like keyboard shortcuts:\n//\n// - Lets through key presses that do not include alphanumeric characters. This\n// includes things like backspace/delete/home/end/etc.\n// - Lets through any key presses that include ctrl/meta keys. These will be\n// shortcuts of some kind like ctrl+C/mod+C.\n// - Special case for Enter key which creates a new paragraph block below and\n// sets the selection to it. This is just to bring the UX closer to Notion\n//\n// While a more elegant solution would probably process transactions instead of\n// keystrokes, this brings us most of the way to Notion's UX without much added\n// complexity.\nexport class NodeSelectionKeyboardPlugin extends BlockNoteExtension {\n public static key() {\n return \"nodeSelectionKeyboard\";\n }\n\n constructor() {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: PLUGIN_KEY,\n props: {\n handleKeyDown: (view, event) => {\n // Checks for node selection\n if (\"node\" in view.state.selection) {\n // Checks if key press uses ctrl/meta modifier\n if (event.ctrlKey || event.metaKey) {\n return false;\n }\n // Checks if key press is alphanumeric\n if (event.key.length === 1) {\n event.preventDefault();\n\n return true;\n }\n // Checks if key press is Enter\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey\n ) {\n const tr = view.state.tr;\n view.dispatch(\n tr\n .insert(\n view.state.tr.selection.$to.after(),\n view.state.schema.nodes[\"paragraph\"].createChecked(),\n )\n .setSelection(\n new TextSelection(\n tr.doc.resolve(view.state.tr.selection.$to.after() + 1),\n ),\n ),\n );\n\n return true;\n }\n }\n\n return false;\n },\n },\n }),\n );\n }\n}\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { v4 } from \"uuid\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nconst PLUGIN_KEY = new PluginKey(`blocknote-placeholder`);\n\nexport class PlaceholderPlugin extends BlockNoteExtension {\n public static key() {\n return \"placeholder\";\n }\n\n constructor(\n editor: BlockNoteEditor<any, any, any>,\n placeholders: Record<\n string | \"default\" | \"emptyDocument\",\n string | undefined\n >,\n ) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: PLUGIN_KEY,\n view: (view) => {\n const uniqueEditorSelector = `placeholder-selector-${v4()}`;\n view.dom.classList.add(uniqueEditorSelector);\n const styleEl = document.createElement(\"style\");\n\n const nonce = editor._tiptapEditor.options.injectNonce;\n if (nonce) {\n styleEl.setAttribute(\"nonce\", nonce);\n }\n\n if (editor.prosemirrorView?.root instanceof ShadowRoot) {\n editor.prosemirrorView.root.append(styleEl);\n } else {\n editor.prosemirrorView?.root.head.appendChild(styleEl);\n }\n\n const styleSheet = styleEl.sheet!;\n\n const getSelector = (additionalSelectors = \"\") =>\n `.${uniqueEditorSelector} .bn-block-content${additionalSelectors} .bn-inline-content:has(> .ProseMirror-trailingBreak:only-child):before`;\n\n try {\n // FIXME: the names \"default\" and \"emptyDocument\" are hardcoded\n const {\n default: defaultPlaceholder,\n emptyDocument: emptyPlaceholder,\n ...rest\n } = placeholders;\n\n // add block specific placeholders\n for (const [blockType, placeholder] of Object.entries(rest)) {\n const blockTypeSelector = `[data-content-type=\"${blockType}\"]`;\n\n styleSheet.insertRule(\n `${getSelector(blockTypeSelector)} { content: ${JSON.stringify(\n placeholder,\n )}; }`,\n );\n }\n\n const onlyBlockSelector = `[data-is-only-empty-block]`;\n const mustBeFocusedSelector = `[data-is-empty-and-focused]`;\n\n // placeholder for when there's only one empty block\n styleSheet.insertRule(\n `${getSelector(onlyBlockSelector)} { content: ${JSON.stringify(\n emptyPlaceholder,\n )}; }`,\n );\n\n // placeholder for default blocks, only when the cursor is in the block (mustBeFocused)\n styleSheet.insertRule(\n `${getSelector(mustBeFocusedSelector)} { content: ${JSON.stringify(\n defaultPlaceholder,\n )}; }`,\n );\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(\n `Failed to insert placeholder CSS rule - this is likely due to the browser not supporting certain CSS pseudo-element selectors (:has, :only-child:, or :before)`,\n e,\n );\n }\n\n return {\n destroy: () => {\n if (editor.prosemirrorView?.root instanceof ShadowRoot) {\n editor.prosemirrorView.root.removeChild(styleEl);\n } else {\n editor.prosemirrorView?.root.head.removeChild(styleEl);\n }\n },\n };\n },\n props: {\n decorations: (state) => {\n const { doc, selection } = state;\n\n if (!editor.isEditable) {\n return;\n }\n\n if (!selection.empty) {\n return;\n }\n\n // Don't show placeholder when the cursor is inside a code block\n if (selection.$from.parent.type.spec.code) {\n return;\n }\n\n const decs = [];\n\n // decoration for when there's only one empty block\n // positions are hardcoded for now\n if (state.doc.content.size === 6) {\n decs.push(\n Decoration.node(2, 4, {\n \"data-is-only-empty-block\": \"true\",\n }),\n );\n }\n\n const $pos = selection.$anchor;\n const node = $pos.parent;\n\n if (node.content.size === 0) {\n const before = $pos.before();\n\n decs.push(\n Decoration.node(before, before + node.nodeSize, {\n \"data-is-empty-and-focused\": \"true\",\n }),\n );\n }\n\n return DecorationSet.create(doc, decs);\n },\n },\n }),\n );\n }\n}\n","import { findChildren } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nconst PLUGIN_KEY = new PluginKey(`previous-blocks`);\n\nconst nodeAttributes: Record<string, string> = {\n // Numbered List Items\n index: \"index\",\n // Headings\n level: \"level\",\n // All Blocks\n type: \"type\",\n depth: \"depth\",\n \"depth-change\": \"depth-change\",\n};\n\n/**\n * This plugin tracks transformation of Block node attributes, so we can support CSS transitions.\n *\n * Problem it solves: ProseMirror recreates the DOM when transactions happen. So when a transaction changes a Node attribute,\n * it results in a completely new DOM element. This means CSS transitions don't work.\n *\n * Solution: When attributes change on a node, this plugin sets a data-* attribute with the \"previous\" value. This way we can still use CSS transitions. (See block.module.css)\n */\nexport class PreviousBlockTypePlugin extends BlockNoteExtension {\n public static key() {\n return \"previousBlockType\";\n }\n\n constructor() {\n super();\n let timeout: ReturnType<typeof setTimeout>;\n this.addProsemirrorPlugin(\n new Plugin({\n key: PLUGIN_KEY,\n view(_editorView) {\n return {\n update: async (view, _prevState) => {\n if (this.key?.getState(view.state).updatedBlocks.size > 0) {\n // use setTimeout 0 to clear the decorations so that at least\n // for one DOM-render the decorations have been applied\n timeout = setTimeout(() => {\n view.dispatch(\n view.state.tr.setMeta(PLUGIN_KEY, { clearUpdate: true }),\n );\n }, 0);\n }\n },\n destroy: () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n },\n };\n },\n state: {\n init() {\n return {\n // Block attributes, by block ID, from just before the previous transaction.\n prevTransactionOldBlockAttrs: {} as any,\n // Block attributes, by block ID, from just before the current transaction.\n currentTransactionOldBlockAttrs: {} as any,\n // Set of IDs of blocks whose attributes changed from the current transaction.\n updatedBlocks: new Set<string>(),\n };\n },\n\n apply(transaction, prev, oldState, newState) {\n prev.currentTransactionOldBlockAttrs = {};\n prev.updatedBlocks.clear();\n\n if (!transaction.docChanged || oldState.doc.eq(newState.doc)) {\n return prev;\n }\n\n // TODO: Instead of iterating through the entire document, only check nodes affected by the transactions. Will\n // also probably require checking nodes affected by the previous transaction too.\n // We didn't get this to work yet:\n // const transform = combineTransactionSteps(oldState.doc, [transaction]);\n // // const { mapping } = transform;\n // const changes = getChangedRanges(transform);\n //\n // changes.forEach(({ oldRange, newRange }) => {\n // const oldNodes = findChildrenInRange(\n // oldState.doc,\n // oldRange,\n // (node) => node.attrs.id\n // );\n //\n // const newNodes = findChildrenInRange(\n // newState.doc,\n // newRange,\n // (node) => node.attrs.id\n // );\n\n const currentTransactionOriginalOldBlockAttrs = {} as any;\n\n const oldNodes = findChildren(\n oldState.doc,\n (node) => node.attrs.id,\n );\n const oldNodesById = new Map(\n oldNodes.map((node) => [node.node.attrs.id, node]),\n );\n const newNodes = findChildren(\n newState.doc,\n (node) => node.attrs.id,\n );\n\n // Traverses all block containers in the new editor state.\n for (const node of newNodes) {\n const oldNode = oldNodesById.get(node.node.attrs.id);\n\n const oldContentNode = oldNode?.node.firstChild;\n const newContentNode = node.node.firstChild;\n\n if (oldNode && oldContentNode && newContentNode) {\n const newAttrs = {\n index: newContentNode.attrs.index,\n level: newContentNode.attrs.level,\n type: newContentNode.type.name,\n depth: newState.doc.resolve(node.pos).depth,\n };\n\n let oldAttrs = {\n index: oldContentNode.attrs.index,\n level: oldContentNode.attrs.level,\n type: oldContentNode.type.name,\n depth: oldState.doc.resolve(oldNode.pos).depth,\n };\n\n currentTransactionOriginalOldBlockAttrs[node.node.attrs.id] =\n oldAttrs;\n\n // Whenever a transaction is appended by the OrderedListItemIndexPlugin, it's given the metadata:\n // { \"orderedListIndexing\": true }\n // These appended transactions happen immediately after any transaction which causes ordered list item\n // indices to require updating, including those which trigger animations. Therefore, these animations are\n // immediately overridden when the PreviousBlockTypePlugin processes the appended transaction, despite only\n // the listItemIndex attribute changing. To solve this, oldAttrs must be edited for transactions with the\n // \"orderedListIndexing\" metadata, so the correct animation can be re-triggered.\n if (transaction.getMeta(\"numberedListIndexing\")) {\n // If the block existed before the transaction, gets the attributes from before the previous transaction\n // (i.e. the transaction that caused list item indices to need updating).\n if (node.node.attrs.id in prev.prevTransactionOldBlockAttrs) {\n oldAttrs =\n prev.prevTransactionOldBlockAttrs[node.node.attrs.id];\n }\n\n // Stops list item indices themselves being animated (looks smoother), unless the block's content type is\n // changing from a numbered list item to something else.\n if (newAttrs.type === \"numberedListItem\") {\n oldAttrs.index = newAttrs.index;\n }\n }\n\n prev.currentTransactionOldBlockAttrs[node.node.attrs.id] =\n oldAttrs;\n\n // TODO: faster deep equal?\n if (JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs)) {\n (oldAttrs as any)[\"depth-change\"] =\n oldAttrs.depth - newAttrs.depth;\n\n // for debugging:\n // console.log(\n // \"id:\",\n // node.node.attrs.id,\n // \"previousBlockTypePlugin changes detected, oldAttrs\",\n // oldAttrs,\n // \"new\",\n // newAttrs\n // );\n\n prev.updatedBlocks.add(node.node.attrs.id);\n }\n }\n }\n\n prev.prevTransactionOldBlockAttrs =\n currentTransactionOriginalOldBlockAttrs;\n\n return prev;\n },\n },\n props: {\n decorations(state) {\n const pluginState = (this as Plugin).getState(state);\n if (pluginState.updatedBlocks.size === 0) {\n return undefined;\n }\n\n const decorations: Decoration[] = [];\n\n state.doc.descendants((node, pos) => {\n if (!node.attrs.id) {\n return;\n }\n\n if (!pluginState.updatedBlocks.has(node.attrs.id)) {\n return;\n }\n\n const prevAttrs =\n pluginState.currentTransactionOldBlockAttrs[node.attrs.id];\n const decorationAttrs: any = {};\n\n for (const [nodeAttr, val] of Object.entries(prevAttrs)) {\n decorationAttrs[\"data-prev-\" + nodeAttributes[nodeAttr]] =\n val || \"none\";\n }\n\n // for debugging:\n // console.log(\n // \"previousBlockTypePlugin committing decorations\",\n // decorationAttrs\n // );\n\n const decoration = Decoration.node(pos, pos + node.nodeSize, {\n ...decorationAttrs,\n });\n\n decorations.push(decoration);\n });\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n }),\n );\n }\n}\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nconst PLUGIN_KEY = new PluginKey(`blocknote-show-selection`);\n\n/**\n * Plugin that shows adds a decoration around the current selection\n * This can be used to highlight the current selection in the UI even when the\n * text editor is not focused.\n */\nexport class ShowSelectionPlugin extends BlockNoteExtension {\n public static key() {\n return \"showSelection\";\n }\n\n private enabled = false;\n\n public constructor(private readonly editor: BlockNoteEditor<any, any, any>) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: PLUGIN_KEY,\n props: {\n decorations: (state) => {\n const { doc, selection } = state;\n\n if (!this.enabled) {\n return DecorationSet.empty;\n }\n\n const dec = Decoration.inline(selection.from, selection.to, {\n \"data-show-selection\": \"true\",\n });\n\n return DecorationSet.create(doc, [dec]);\n },\n },\n }),\n );\n }\n\n public setEnabled(enabled: boolean) {\n if (this.enabled === enabled) {\n return;\n }\n\n this.enabled = enabled;\n\n this.editor.transact((tr) => tr.setMeta(PLUGIN_KEY, {}));\n }\n\n public getEnabled() {\n return this.enabled;\n }\n}\n","import { EditorView } from \"prosemirror-view\";\n\nexport function getDraggableBlockFromElement(\n element: Element,\n view: EditorView,\n) {\n while (\n element &&\n element.parentElement &&\n element.parentElement !== view.dom &&\n element.getAttribute?.(\"data-node-type\") !== \"blockContainer\"\n ) {\n element = element.parentElement;\n }\n if (element.getAttribute?.(\"data-node-type\") !== \"blockContainer\") {\n return undefined;\n }\n return { node: element as HTMLElement, id: element.getAttribute(\"data-id\")! };\n}\n","import { Fragment, Node, ResolvedPos, Slice } from \"prosemirror-model\";\nimport { Selection } from \"prosemirror-state\";\nimport { Mappable } from \"prosemirror-transform\";\n\n/**\n * This class represents an editor selection which spans multiple nodes/blocks. It's currently only used to allow users\n * to drag multiple blocks at the same time. Expects the selection anchor and head to be between nodes, i.e. just before\n * the first target node and just after the last, and that anchor and head are at the same nesting level.\n *\n * Partially based on ProseMirror's NodeSelection implementation:\n * (https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.ts)\n * MultipleNodeSelection differs from NodeSelection in the following ways:\n * 1. Stores which nodes are included in the selection instead of just a single node.\n * 2. Already expects the selection to start just before the first target node and ends just after the last, while a\n * NodeSelection automatically sets both anchor and head to just before the single target node.\n */\nexport class MultipleNodeSelection extends Selection {\n nodes: Array<Node>;\n\n constructor($anchor: ResolvedPos, $head: ResolvedPos) {\n super($anchor, $head);\n\n // Parent is at the same nesting level as anchor/head since they are just before/ just after target nodes.\n const parentNode = $anchor.node();\n\n this.nodes = [];\n $anchor.doc.nodesBetween($anchor.pos, $head.pos, (node, _pos, parent) => {\n if (parent !== null && parent.eq(parentNode)) {\n this.nodes.push(node);\n return false;\n }\n return;\n });\n }\n\n static create(doc: Node, from: number, to = from): MultipleNodeSelection {\n return new MultipleNodeSelection(doc.resolve(from), doc.resolve(to));\n }\n\n content(): Slice {\n return new Slice(Fragment.from(this.nodes), 0, 0);\n }\n\n eq(selection: Selection): boolean {\n if (!(selection instanceof MultipleNodeSelection)) {\n return false;\n }\n\n if (this.nodes.length !== selection.nodes.length) {\n return false;\n }\n\n if (this.from !== selection.from || this.to !== selection.to) {\n return false;\n }\n\n for (let i = 0; i < this.nodes.length; i++) {\n if (!this.nodes[i].eq(selection.nodes[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n map(doc: Node, mapping: Mappable): Selection {\n const fromResult = mapping.mapResult(this.from);\n const toResult = mapping.mapResult(this.to);\n\n if (toResult.deleted) {\n return Selection.near(doc.resolve(fromResult.pos));\n }\n\n if (fromResult.deleted) {\n return Selection.near(doc.resolve(toResult.pos));\n }\n\n return new MultipleNodeSelection(\n doc.resolve(fromResult.pos),\n doc.resolve(toResult.pos),\n );\n }\n\n toJSON(): any {\n return { type: \"multiple-node\", anchor: this.anchor, head: this.head };\n }\n}\n\nSelection.jsonID(\"multiple-node\", MultipleNodeSelection);\n","import { Node } from \"prosemirror-model\";\nimport { NodeSelection, Selection } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport { createExternalHTMLExporter } from \"../../api/exporters/html/externalHTMLExporter.js\";\nimport { cleanHTMLToMarkdown } from \"../../api/exporters/markdown/markdownExporter.js\";\nimport { fragmentToBlocks } from \"../../api/nodeConversions/fragmentToBlocks.js\";\nimport { getNodeById } from \"../../api/nodeUtil.js\";\nimport { Block } from \"../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { MultipleNodeSelection } from \"./MultipleNodeSelection.js\";\n\nlet dragImageElement: Element | undefined;\n\nexport type SideMenuState<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = UiElementPosition & {\n // The block that the side menu is attached to.\n block: Block<BSchema, I, S>;\n};\n\nfunction blockPositionsFromSelection(selection: Selection, doc: Node) {\n // Absolute positions just before the first block spanned by the selection, and just after the last block. Having the\n // selection start and end just before and just after the target blocks ensures no whitespace/line breaks are left\n // behind after dragging & dropping them.\n let beforeFirstBlockPos: number;\n let afterLastBlockPos: number;\n\n // Even the user starts dragging blocks but drops them in the same place, the selection will still be moved just\n // before & just after the blocks spanned by the selection, and therefore doesn't need to change if they try to drag\n // the same blocks again. If this happens, the anchor & head move out of the block content node they were originally\n // in. If the anchor should update but the head shouldn't and vice versa, it means the user selection is outside a\n // block content node, which should never happen.\n const selectionStartInBlockContent =\n doc.resolve(selection.from).node().type.spec.group === \"blockContent\";\n const selectionEndInBlockContent =\n doc.resolve(selection.to).node().type.spec.group === \"blockContent\";\n\n // Ensures that entire outermost nodes are selected if the selection spans multiple nesting levels.\n const minDepth = Math.min(selection.$anchor.depth, selection.$head.depth);\n\n if (selectionStartInBlockContent && selectionEndInBlockContent) {\n // Absolute positions at the start of the first block in the selection and at the end of the last block. User\n // selections will always start and end in block content nodes, but we want the start and end positions of their\n // parent block nodes, which is why minDepth - 1 is used.\n const startFirstBlockPos = selection.$from.start(minDepth - 1);\n const endLastBlockPos = selection.$to.end(minDepth - 1);\n\n // Shifting start and end positions by one moves them just outside the first and last selected blocks.\n beforeFirstBlockPos = doc.resolve(startFirstBlockPos - 1).pos;\n afterLastBlockPos = doc.resolve(endLastBlockPos + 1).pos;\n } else {\n beforeFirstBlockPos = selection.from;\n afterLastBlockPos = selection.to;\n }\n\n return { from: beforeFirstBlockPos, to: afterLastBlockPos };\n}\n\nfunction setDragImage(view: EditorView, from: number, to = from) {\n if (from === to) {\n // Moves to position to be just after the first (and only) selected block.\n to += view.state.doc.resolve(from + 1).node().nodeSize;\n }\n\n // Parent element is cloned to remove all unselected children without affecting the editor content.\n const parentClone = view.domAtPos(from).node.cloneNode(true) as Element;\n const parent = view.domAtPos(from).node as Element;\n\n const getElementIndex = (parentElement: Element, targetElement: Element) =>\n Array.prototype.indexOf.call(parentElement.children, targetElement);\n\n const firstSelectedBlockIndex = getElementIndex(\n parent,\n // Expects from position to be just before the first selected block.\n view.domAtPos(from + 1).node.parentElement!,\n );\n const lastSelectedBlockIndex = getElementIndex(\n parent,\n // Expects to position to be just after the last selected block.\n view.domAtPos(to - 1).node.parentElement!,\n );\n\n for (let i = parent.childElementCount - 1; i >= 0; i--) {\n if (i > lastSelectedBlockIndex || i < firstSelectedBlockIndex) {\n parentClone.removeChild(parentClone.children[i]);\n }\n }\n\n // dataTransfer.setDragImage(element) only works if element is attached to the DOM.\n unsetDragImage(view.root);\n dragImageElement = parentClone;\n\n // Browsers may have CORS policies which prevents iframes from being\n // manipulated, so better to stay on the safe side and remove them from the\n // drag preview. The drag preview doesn't work with iframes anyway.\n const iframes = dragImageElement.getElementsByTagName(\"iframe\");\n for (let i = 0; i < iframes.length; i++) {\n const iframe = iframes[i];\n const parent = iframe.parentElement;\n\n if (parent) {\n parent.removeChild(iframe);\n }\n }\n\n // TODO: This is hacky, need a better way of assigning classes to the editor so that they can also be applied to the\n // drag preview.\n const classes = view.dom.className.split(\" \");\n const inheritedClasses = classes\n .filter(\n (className) =>\n className !== \"ProseMirror\" &&\n className !== \"bn-root\" &&\n className !== \"bn-editor\",\n )\n .join(\" \");\n\n dragImageElement.className =\n dragImageElement.className + \" bn-drag-preview \" + inheritedClasses;\n\n if (view.root instanceof ShadowRoot) {\n view.root.appendChild(dragImageElement);\n } else {\n view.root.body.appendChild(dragImageElement);\n }\n}\n\nexport function unsetDragImage(rootEl: Document | ShadowRoot) {\n if (dragImageElement !== undefined) {\n if (rootEl instanceof ShadowRoot) {\n rootEl.removeChild(dragImageElement);\n } else {\n rootEl.body.removeChild(dragImageElement);\n }\n\n dragImageElement = undefined;\n }\n}\n\nexport function dragStart<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n e: { dataTransfer: DataTransfer | null; clientY: number },\n block: Block<BSchema, I, S>,\n editor: BlockNoteEditor<BSchema, I, S>,\n) {\n if (!e.dataTransfer) {\n return;\n }\n\n const view = editor.prosemirrorView;\n if (!view) {\n return;\n }\n\n const posInfo = getNodeById(block.id, view.state.doc);\n if (!posInfo) {\n throw new Error(`Block with ID ${block.id} not found`);\n }\n const pos = posInfo.posBeforeNode;\n\n if (pos != null) {\n const selection = view.state.selection;\n const doc = view.state.doc;\n\n const { from, to } = blockPositionsFromSelection(selection, doc);\n\n const draggedBlockInSelection = from <= pos && pos < to;\n const multipleBlocksSelected =\n selection.$anchor.node() !== selection.$head.node() ||\n selection instanceof MultipleNodeSelection;\n\n if (draggedBlockInSelection && multipleBlocksSelected) {\n view.dispatch(\n view.state.tr.setSelection(MultipleNodeSelection.create(doc, from, to)),\n );\n setDragImage(view, from, to);\n } else {\n view.dispatch(\n view.state.tr.setSelection(NodeSelection.create(view.state.doc, pos)),\n );\n setDragImage(view, pos);\n }\n\n const selectedSlice = view.state.selection.content();\n const schema = editor.pmSchema;\n\n const clipboardHTML =\n view.serializeForClipboard(selectedSlice).dom.innerHTML;\n\n const externalHTMLExporter = createExternalHTMLExporter(schema, editor);\n\n const blocks = fragmentToBlocks(selectedSlice.content);\n const externalHTML = externalHTMLExporter.exportBlocks(blocks, {});\n\n const plainText = cleanHTMLToMarkdown(externalHTML);\n\n e.dataTransfer.clearData();\n e.dataTransfer.setData(\"blocknote/html\", clipboardHTML);\n e.dataTransfer.setData(\"text/html\", externalHTML);\n e.dataTransfer.setData(\"text/plain\", plainText);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setDragImage(dragImageElement!, 0, 0);\n }\n}\n","import { DOMParser, Slice } from \"@tiptap/pm/model\";\nimport {\n EditorState,\n Plugin,\n PluginKey,\n PluginView,\n TextSelection,\n} from \"@tiptap/pm/state\";\nimport { EditorView } from \"@tiptap/pm/view\";\n\nimport { Block } from \"../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { initializeESMDependencies } from \"../../util/esmDependencies.js\";\nimport { getDraggableBlockFromElement } from \"../getDraggableBlockFromElement.js\";\nimport { dragStart, unsetDragImage } from \"./dragging.js\";\n\nexport type SideMenuState<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = UiElementPosition & {\n // The block that the side menu is attached to.\n block: Block<BSchema, I, S>;\n};\n\nconst PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP = 0.1;\n\nfunction getBlockFromCoords(\n view: EditorView,\n coords: { left: number; top: number },\n sideMenuDetection: \"viewport\" | \"editor\",\n adjustForColumns = true,\n) {\n const elements = view.root.elementsFromPoint(\n // bit hacky - offset x position to right to account for the width of sidemenu itself\n coords.left + (sideMenuDetection === \"editor\" ? 50 : 0),\n coords.top,\n );\n\n for (const element of elements) {\n if (!view.dom.contains(element)) {\n // probably a ui overlay like formatting toolbar etc\n continue;\n }\n if (adjustForColumns) {\n const column = element.closest(\"[data-node-type=columnList]\");\n if (column) {\n return getBlockFromCoords(\n view,\n {\n left: coords.left + 50, // bit hacky, but if we're inside a column, offset x position to right to account for the width of sidemenu itself\n top: coords.top,\n },\n sideMenuDetection,\n false,\n );\n }\n }\n return getDraggableBlockFromElement(element, view);\n }\n return undefined;\n}\n\nfunction getBlockFromMousePos(\n mousePos: {\n x: number;\n y: number;\n },\n view: EditorView,\n sideMenuDetection: \"viewport\" | \"editor\",\n): { node: HTMLElement; id: string } | undefined {\n // Editor itself may have padding or other styling which affects\n // size/position, so we get the boundingRect of the first child (i.e. the\n // blockGroup that wraps all blocks in the editor) for more accurate side\n // menu placement.\n if (!view.dom.firstChild) {\n return;\n }\n\n const editorBoundingBox = (\n view.dom.firstChild as HTMLElement\n ).getBoundingClientRect();\n\n // this.horizontalPosAnchor = editorBoundingBox.x;\n\n // Gets block at mouse cursor's position.\n const coords = {\n left: mousePos.x,\n top: mousePos.y,\n };\n\n const mouseLeftOfEditor = coords.left < editorBoundingBox.left;\n const mouseRightOfEditor = coords.left > editorBoundingBox.right;\n\n // Clamps the x position to the editor's bounding box.\n if (sideMenuDetection === \"viewport\") {\n if (mouseLeftOfEditor) {\n coords.left = editorBoundingBox.left + 10;\n }\n\n if (mouseRightOfEditor) {\n coords.left = editorBoundingBox.right - 10;\n }\n }\n\n let block = getBlockFromCoords(view, coords, sideMenuDetection);\n\n if (!mouseRightOfEditor && block) {\n // note: this case is not necessary when we're on the right side of the editor\n\n /* Now, because blocks can be nested\n | BlockA |\n x | BlockB y|\n\n hovering over position x (the \"margin of block B\") will return block A instead of block B.\n to fix this, we get the block from the right side of block A (position y, which will fall in BlockB correctly)\n */\n\n const rect = block.node.getBoundingClientRect();\n coords.left = rect.right - 10;\n block = getBlockFromCoords(view, coords, \"viewport\", false);\n }\n\n return block;\n}\n\n/**\n * With the sidemenu plugin we can position a menu next to a hovered block.\n */\nexport class SideMenuView<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> implements PluginView\n{\n public state?: SideMenuState<BSchema, I, S>;\n public readonly emitUpdate: (state: SideMenuState<BSchema, I, S>) => void;\n\n private mousePos: { x: number; y: number } | undefined;\n\n private hoveredBlock: HTMLElement | undefined;\n\n public menuFrozen = false;\n\n public isDragOrigin = false;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n private readonly sideMenuDetection: \"viewport\" | \"editor\",\n private readonly pmView: EditorView,\n emitUpdate: (state: SideMenuState<BSchema, I, S>) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized side menu\");\n }\n\n emitUpdate(this.state);\n };\n\n this.pmView.root.addEventListener(\n \"dragstart\",\n this.onDragStart as EventListener,\n );\n this.pmView.root.addEventListener(\n \"dragover\",\n this.onDragOver as EventListener,\n );\n this.pmView.root.addEventListener(\n \"drop\",\n this.onDrop as EventListener,\n true,\n );\n this.pmView.root.addEventListener(\n \"dragend\",\n this.onDragEnd as EventListener,\n true,\n );\n initializeESMDependencies();\n\n // Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.\n this.pmView.root.addEventListener(\n \"mousemove\",\n this.onMouseMove as EventListener,\n true,\n );\n\n // Hides and unfreezes the menu whenever the user presses a key.\n this.pmView.root.addEventListener(\n \"keydown\",\n this.onKeyDown as EventListener,\n true,\n );\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n pmView.root.addEventListener(\"scroll\", this.onScroll, true);\n }\n\n updateState = (state: SideMenuState<BSchema, I, S>) => {\n this.state = state;\n this.emitUpdate(this.state);\n };\n\n updateStateFromMousePos = () => {\n if (this.menuFrozen || !this.mousePos) {\n return;\n }\n\n const block = getBlockFromMousePos(\n this.mousePos,\n this.pmView,\n this.sideMenuDetection,\n );\n\n // Closes the menu if the mouse cursor is beyond the editor vertically.\n if (!block || !this.editor.isEditable) {\n if (this.state?.show) {\n this.state.show = false;\n this.updateState(this.state);\n }\n\n return;\n }\n\n // Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.\n if (\n this.state?.show &&\n this.hoveredBlock?.hasAttribute(\"data-id\") &&\n this.hoveredBlock?.getAttribute(\"data-id\") === block.id\n ) {\n return;\n }\n\n this.hoveredBlock = block.node;\n\n // Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.\n // TODO: needed?\n const blockContent = block.node.firstChild as HTMLElement;\n\n if (!blockContent) {\n return;\n }\n\n // TODO: needed?\n\n // Shows or updates elements.\n if (this.editor.isEditable) {\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n const column = block.node.closest(\"[data-node-type=column]\");\n this.updateState({\n show: true,\n referencePos: new DOMRect(\n column\n ? // We take the first child as column elements have some default\n // padding. This is a little weird since this child element will\n // be the first block, but since it's always non-nested and we\n // only take the x coordinate, it's ok.\n column.firstElementChild!.getBoundingClientRect().x\n : (\n this.pmView.dom.firstChild as HTMLElement\n ).getBoundingClientRect().x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height,\n ),\n block: this.editor.getBlock(\n this.hoveredBlock!.getAttribute(\"data-id\")!,\n )!,\n });\n }\n };\n\n onDrop = (event: DragEvent) => {\n // Content from outside a BlockNote editor is being dropped - just let\n // ProseMirror's default behaviour handle it.\n if (this.pmView.dragging === null) {\n return;\n }\n\n this.editor._tiptapEditor.commands.blur();\n\n // Finds the BlockNote editor element that the drop event occurred in (if\n // any).\n const parentEditorElement =\n event.target instanceof Node\n ? (event.target instanceof HTMLElement\n ? event.target\n : event.target.parentElement\n )?.closest(\".bn-editor\") || null\n : null;\n\n // Drop event occurred within an editor.\n if (parentEditorElement) {\n // When ProseMirror handles a drop event on the editor while\n // `view.dragging` is set, it deletes the selected content. However, if\n // a block from a different editor is being dropped, this causes some\n // issues that the code below fixes:\n if (!this.isDragOrigin && this.pmView.dom === parentEditorElement) {\n // Because the editor selection is unrelated to the dragged content, we\n // don't want PM to delete its content. Therefore, we collapse the\n // selection.\n this.pmView.dispatch(\n this.pmView.state.tr.setSelection(\n TextSelection.create(\n this.pmView.state.tr.doc,\n this.pmView.state.tr.selection.to,\n ),\n ),\n );\n } else if (this.isDragOrigin && this.pmView.dom !== parentEditorElement) {\n // Because the editor from which the block originates doesn't get a drop\n // event on it, PM doesn't delete its selected content. Therefore, we\n // need to do so manually.\n //\n // Note: Deleting the selected content from the editor from which the\n // block originates, may change its height. This can cause the position of\n // the editor in which the block is being dropping to shift, before it\n // can handle the drop event. That in turn can cause the drop to happen\n // somewhere other than the user intended. To get around this, we delay\n // deleting the selected content until all editors have had the chance to\n // handle the event.\n setTimeout(\n () => this.pmView.dispatch(this.pmView.state.tr.deleteSelection()),\n 0,\n );\n }\n }\n\n if (\n this.sideMenuDetection === \"editor\" ||\n (event as any).synthetic ||\n !event.dataTransfer?.types.includes(\"blocknote/html\")\n ) {\n return;\n }\n\n const pos = this.pmView.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n if (!pos || pos.inside === -1) {\n /**\n * When `this.sideMenuSelection === \"viewport\"`, if the event is outside the\n * editor contents, we dispatch a fake event, so that we can still drop the\n * content when dragging / dropping to the side of the editor\n */\n const evt = this.createSyntheticEvent(event);\n // console.log(\"dispatch fake drop\");\n this.pmView.dom.dispatchEvent(evt);\n }\n };\n\n onDragEnd = () => {\n // When the user starts dragging a block, `view.dragging` is set on all\n // BlockNote editors. However, when the drag ends, only the editor that the\n // drag originated in automatically clears `view.dragging`. Therefore, we\n // have to manually clear it on all editors.\n this.pmView.dragging = null;\n };\n\n /**\n * If a block is being dragged, ProseMirror usually gets the context of what's\n * being dragged from `view.dragging`, which is automatically set when a\n * `dragstart` event fires in the editor. However, if the user tries to drag\n * and drop blocks between multiple editors, only the one in which the drag\n * began has that context, so we need to set it on the others manually. This\n * ensures that PM always drops the blocks in between other blocks, and not\n * inside them.\n *\n * After the `dragstart` event fires on the drag handle, it sets\n * `blocknote/html` data on the clipboard. This handler fires right after,\n * parsing the `blocknote/html` data into nodes and setting them on\n * `view.dragging`.\n *\n * Note: Setting `view.dragging` on `dragover` would be better as the user\n * could then drag between editors in different windows, but you can only\n * access `dataTransfer` contents on `dragstart` and `drop` events.\n */\n onDragStart = (event: DragEvent) => {\n const html = event.dataTransfer?.getData(\"blocknote/html\");\n if (!html) {\n return;\n }\n\n if (this.pmView.dragging) {\n throw new Error(\"New drag was started while an existing drag is ongoing\");\n }\n\n const element = document.createElement(\"div\");\n element.innerHTML = html;\n\n const parser = DOMParser.fromSchema(this.pmView.state.schema);\n const node = parser.parse(element, {\n topNode: this.pmView.state.schema.nodes[\"blockGroup\"].create(),\n });\n\n this.pmView.dragging = {\n slice: new Slice(node.content, 0, 0),\n move: true,\n };\n };\n\n /**\n * If the event is outside the editor contents,\n * we dispatch a fake event, so that we can still drop the content\n * when dragging / dropping to the side of the editor\n */\n onDragOver = (event: DragEvent) => {\n if (\n this.sideMenuDetection === \"editor\" ||\n (event as any).synthetic ||\n !event.dataTransfer?.types.includes(\"blocknote/html\")\n ) {\n return;\n }\n\n const pos = this.pmView.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n if (!pos || (pos.inside === -1 && this.pmView.dom.firstChild)) {\n const evt = this.createSyntheticEvent(event);\n // console.log(\"dispatch fake dragover\");\n this.pmView.dom.dispatchEvent(evt);\n }\n };\n\n onKeyDown = (_event: KeyboardEvent) => {\n if (this.state?.show && this.editor.isFocused()) {\n // Typing in editor should hide side menu\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n };\n\n onMouseMove = (event: MouseEvent) => {\n if (this.menuFrozen) {\n return;\n }\n\n this.mousePos = { x: event.clientX, y: event.clientY };\n\n // We want the full area of the editor to check if the cursor is hovering\n // above it though.\n const editorOuterBoundingBox = this.pmView.dom.getBoundingClientRect();\n const cursorWithinEditor =\n this.mousePos.x > editorOuterBoundingBox.left &&\n this.mousePos.x < editorOuterBoundingBox.right &&\n this.mousePos.y > editorOuterBoundingBox.top &&\n this.mousePos.y < editorOuterBoundingBox.bottom;\n\n // TODO: remove parentElement, but then we need to remove padding from boundingbox or find a different solution\n const editorWrapper = this.pmView.dom!.parentElement!;\n\n // Doesn't update if the mouse hovers an element that's over the editor but\n // isn't a part of it or the side menu.\n if (\n // Cursor is within the editor area\n cursorWithinEditor &&\n // An element is hovered\n event &&\n event.target &&\n // Element is outside the editor\n !(\n editorWrapper === event.target ||\n editorWrapper.contains(event.target as HTMLElement)\n )\n ) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n\n return;\n }\n\n this.updateStateFromMousePos();\n };\n\n private createSyntheticEvent(event: DragEvent) {\n const evt = new Event(event.type, event) as any;\n const editorBoundingBox = (\n this.pmView.dom.firstChild as HTMLElement\n ).getBoundingClientRect();\n evt.clientX = event.clientX;\n evt.clientY = event.clientY;\n if (\n event.clientX < editorBoundingBox.left &&\n event.clientX >\n editorBoundingBox.left -\n editorBoundingBox.width *\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP\n ) {\n // when we're slightly left of the editor, we can drop to the side of the block\n evt.clientX =\n editorBoundingBox.left +\n (editorBoundingBox.width *\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP) /\n 2;\n } else if (\n event.clientX > editorBoundingBox.right &&\n event.clientX <\n editorBoundingBox.right +\n editorBoundingBox.width *\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP\n ) {\n // when we're slightly right of the editor, we can drop to the side of the block\n evt.clientX =\n editorBoundingBox.right -\n (editorBoundingBox.width *\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP) /\n 2;\n } else if (\n event.clientX < editorBoundingBox.left ||\n event.clientX > editorBoundingBox.right\n ) {\n // when mouse is outside of the editor on x axis, drop it somewhere safe (but not to the side of a block)\n evt.clientX =\n editorBoundingBox.left +\n PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP *\n editorBoundingBox.width *\n 2; // put it somewhere in first block, but safe outside of the PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP margin\n }\n\n evt.clientY = Math.min(\n Math.max(event.clientY, editorBoundingBox.top),\n editorBoundingBox.top + editorBoundingBox.height,\n );\n\n evt.dataTransfer = event.dataTransfer;\n evt.preventDefault = () => event.preventDefault();\n evt.synthetic = true; // prevent recursion\n return evt;\n }\n\n onScroll = () => {\n if (this.state?.show) {\n this.state.referencePos = this.hoveredBlock!.getBoundingClientRect();\n this.emitUpdate(this.state);\n }\n };\n\n // Needed in cases where the editor state updates without the mouse cursor\n // moving, as some state updates can require a side menu update. For example,\n // adding a button to the side menu which removes the block can cause the\n // block below to jump up into the place of the removed block when clicked,\n // allowing the user to click the button again without moving the cursor. This\n // would otherwise not update the side menu, and so clicking the button again\n // would attempt to remove the same block again, causing an error.\n update(_view: EditorView, prevState: EditorState) {\n const docChanged = !prevState.doc.eq(this.pmView.state.doc);\n if (docChanged && this.state?.show) {\n this.updateStateFromMousePos();\n }\n }\n\n destroy() {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n this.pmView.root.removeEventListener(\n \"mousemove\",\n this.onMouseMove as EventListener,\n true,\n );\n this.pmView.root.removeEventListener(\n \"dragstart\",\n this.onDragStart as EventListener,\n );\n this.pmView.root.removeEventListener(\n \"dragover\",\n this.onDragOver as EventListener,\n );\n this.pmView.root.removeEventListener(\n \"drop\",\n this.onDrop as EventListener,\n true,\n );\n this.pmView.root.removeEventListener(\n \"dragend\",\n this.onDragEnd as EventListener,\n true,\n );\n this.pmView.root.removeEventListener(\n \"keydown\",\n this.onKeyDown as EventListener,\n true,\n );\n this.pmView.root.removeEventListener(\"scroll\", this.onScroll, true);\n }\n}\n\nexport const sideMenuPluginKey = new PluginKey(\"SideMenuPlugin\");\n\nexport class SideMenuProsemirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"sideMenu\";\n }\n\n public view: SideMenuView<BSchema, I, S> | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n sideMenuDetection: \"viewport\" | \"editor\",\n ) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: sideMenuPluginKey,\n view: (editorView) => {\n this.view = new SideMenuView(\n editor,\n sideMenuDetection,\n editorView,\n (state) => {\n this.emit(\"update\", state);\n },\n );\n return this.view;\n },\n }),\n );\n }\n\n public onUpdate(callback: (state: SideMenuState<BSchema, I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragStart = (\n event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n },\n block: Block<BSchema, I, S>,\n ) => {\n if (this.view) {\n this.view.isDragOrigin = true;\n }\n\n dragStart(event, block, this.editor);\n };\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragEnd = () => {\n if (this.editor.prosemirrorView) {\n unsetDragImage(this.editor.prosemirrorView.root);\n }\n\n if (this.view) {\n this.view.isDragOrigin = false;\n }\n };\n /**\n * Freezes the side menu. When frozen, the side menu will stay\n * attached to the same block regardless of which block is hovered by the\n * mouse cursor.\n */\n freezeMenu = () => {\n this.view!.menuFrozen = true;\n this.view!.state!.show = true;\n this.view!.emitUpdate(this.view!.state!);\n };\n /**\n * Unfreezes the side menu. When frozen, the side menu will stay\n * attached to the same block regardless of which block is hovered by the\n * mouse cursor.\n */\n unfreezeMenu = () => {\n this.view!.menuFrozen = false;\n this.view!.state!.show = false;\n this.view!.emitUpdate(this.view!.state!);\n };\n}\n","import { Mapping } from \"prosemirror-transform\";\nimport {\n absolutePositionToRelativePosition,\n relativePositionToAbsolutePosition,\n ySyncPluginKey,\n} from \"y-prosemirror\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport * as Y from \"yjs\";\nimport type { ProsemirrorBinding } from \"y-prosemirror\";\n\n/**\n * This is used to track a mapping for each editor. The mapping stores the mappings for each transaction since the first transaction that was tracked.\n */\nconst editorToMapping = new Map<BlockNoteEditor<any, any, any>, Mapping>();\n\n/**\n * This initializes a single mapping for an editor instance.\n */\nfunction getMapping(editor: BlockNoteEditor<any, any, any>) {\n if (editorToMapping.has(editor)) {\n // Mapping already initialized, so we don't need to do anything\n return editorToMapping.get(editor)!;\n }\n const mapping = new Mapping();\n editor._tiptapEditor.on(\"transaction\", ({ transaction }) => {\n mapping.appendMapping(transaction.mapping);\n });\n editor._tiptapEditor.on(\"destroy\", () => {\n // Cleanup the mapping when the editor is destroyed\n editorToMapping.delete(editor);\n });\n\n // There only is one mapping per editor, so we can just set it\n editorToMapping.set(editor, mapping);\n\n return mapping;\n}\n\n/**\n * This is used to keep track of positions of elements in the editor.\n * It is needed because y-prosemirror's sync plugin can disrupt normal prosemirror position mapping.\n *\n * It is specifically made to be able to be used whether the editor is being used in a collaboratively, or single user, providing the same API.\n *\n * @param editor The editor to track the position of.\n * @param position The position to track.\n * @param side The side of the position to track. \"left\" is the default. \"right\" would move with the change if the change is in the right direction.\n * @returns A function that returns the position of the element.\n */\nexport function trackPosition(\n /**\n * The editor to track the position of.\n */\n editor: BlockNoteEditor<any, any, any>,\n /**\n * The position to track.\n */\n position: number,\n /**\n * This is the side of the position to track. \"left\" is the default. \"right\" would move with the change if the change is in the right direction.\n */\n side: \"left\" | \"right\" = \"left\",\n): () => number {\n const ySyncPluginState = ySyncPluginKey.getState(\n editor._tiptapEditor.state,\n ) as {\n doc: Y.Doc;\n binding: ProsemirrorBinding;\n };\n\n if (!ySyncPluginState) {\n // No y-prosemirror sync plugin, so we need to track the mapping manually\n // This will initialize the mapping for this editor, if needed\n const mapping = getMapping(editor);\n\n // This is the start point of tracking the mapping\n const trackedMapLength = mapping.maps.length;\n\n return () => {\n const pos = mapping\n // Only read the history of the mapping that we care about\n .slice(trackedMapLength)\n .map(position, side === \"left\" ? -1 : 1);\n\n return pos;\n };\n }\n\n const relativePosition = absolutePositionToRelativePosition(\n // Track the position after the position if we are on the right side\n position + (side === \"right\" ? 1 : 0),\n ySyncPluginState.binding.type,\n ySyncPluginState.binding.mapping,\n );\n\n return () => {\n const curYSyncPluginState = ySyncPluginKey.getState(\n editor._tiptapEditor.state,\n ) as typeof ySyncPluginState;\n const pos = relativePositionToAbsolutePosition(\n curYSyncPluginState.doc,\n curYSyncPluginState.binding.type,\n relativePosition,\n curYSyncPluginState.binding.mapping,\n );\n\n // This can happen if the element is garbage collected\n if (pos === null) {\n throw new Error(\"Position not found, cannot track positions\");\n }\n\n return pos + (side === \"right\" ? -1 : 0);\n };\n}\n","import { findParentNode } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\n\nimport { trackPosition } from \"../../api/positionMapping.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\n\nconst findBlock = findParentNode((node) => node.type.name === \"blockContainer\");\n\nexport type SuggestionMenuState = UiElementPosition & {\n query: string;\n ignoreQueryLength?: boolean;\n};\n\nclass SuggestionMenuView<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> {\n public state?: SuggestionMenuState;\n public emitUpdate: (triggerCharacter: string) => void;\n private rootEl?: Document | ShadowRoot;\n pluginState: SuggestionPluginState;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n emitUpdate: (menuName: string, state: SuggestionMenuState) => void,\n ) {\n this.pluginState = undefined;\n\n this.emitUpdate = (menuName: string) => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized suggestions menu\");\n }\n\n emitUpdate(menuName, {\n ...this.state,\n ignoreQueryLength: this.pluginState?.ignoreQueryLength,\n });\n };\n\n this.rootEl = this.editor.prosemirrorView?.root;\n\n // Setting capture=true ensures that any parent container of the editor that\n // gets scrolled will trigger the scroll event. Scroll events do not bubble\n // and so won't propagate to the document by default.\n this.rootEl?.addEventListener(\"scroll\", this.handleScroll, true);\n }\n\n handleScroll = () => {\n if (this.state?.show) {\n const decorationNode = this.rootEl?.querySelector(\n `[data-decoration-id=\"${this.pluginState!.decorationId}\"]`,\n );\n if (!decorationNode) {\n return;\n }\n this.state.referencePos = decorationNode.getBoundingClientRect();\n this.emitUpdate(this.pluginState!.triggerCharacter!);\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const prev: SuggestionPluginState =\n suggestionMenuPluginKey.getState(prevState);\n const next: SuggestionPluginState = suggestionMenuPluginKey.getState(\n view.state,\n );\n\n // See how the state changed\n const started = prev === undefined && next !== undefined;\n const stopped = prev !== undefined && next === undefined;\n const changed = prev !== undefined && next !== undefined;\n\n // Cancel when suggestion isn't active\n if (!started && !changed && !stopped) {\n return;\n }\n\n this.pluginState = stopped ? prev : next;\n\n if (stopped || !this.editor.isEditable) {\n if (this.state) {\n this.state.show = false;\n }\n this.emitUpdate(this.pluginState!.triggerCharacter);\n\n return;\n }\n\n const decorationNode = this.rootEl?.querySelector(\n `[data-decoration-id=\"${this.pluginState!.decorationId}\"]`,\n );\n\n if (this.editor.isEditable && decorationNode) {\n this.state = {\n show: true,\n referencePos: decorationNode.getBoundingClientRect(),\n query: this.pluginState!.query,\n };\n\n this.emitUpdate(this.pluginState!.triggerCharacter!);\n }\n }\n\n destroy() {\n this.rootEl?.removeEventListener(\"scroll\", this.handleScroll, true);\n }\n\n closeMenu = () => {\n this.editor.transact((tr) => tr.setMeta(suggestionMenuPluginKey, null));\n };\n\n clearQuery = () => {\n if (this.pluginState === undefined) {\n return;\n }\n\n this.editor._tiptapEditor\n .chain()\n .focus()\n // TODO need to make an API for this\n .deleteRange({\n from:\n this.pluginState.queryStartPos() -\n (this.pluginState.deleteTriggerCharacter\n ? this.pluginState.triggerCharacter!.length\n : 0),\n to: this.editor.transact((tr) => tr.selection.from),\n })\n .run();\n };\n}\n\ntype SuggestionPluginState =\n | {\n triggerCharacter: string;\n deleteTriggerCharacter: boolean;\n queryStartPos: () => number;\n query: string;\n decorationId: string;\n ignoreQueryLength?: boolean;\n }\n | undefined;\n\nconst suggestionMenuPluginKey = new PluginKey(\"SuggestionMenuPlugin\");\n\n/**\n * A ProseMirror plugin for suggestions, designed to make '/'-commands possible as well as mentions.\n *\n * This is basically a simplified version of TipTap's [Suggestions](https://github.com/ueberdosis/tiptap/tree/db92a9b313c5993b723c85cd30256f1d4a0b65e1/packages/suggestion) plugin.\n *\n * This version is adapted from the aforementioned version in the following ways:\n * - This version supports generic items instead of only strings (to allow for more advanced filtering for example)\n * - This version hides some unnecessary complexity from the user of the plugin.\n * - This version handles key events differently\n */\nexport class SuggestionMenuProseMirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"suggestionMenu\";\n }\n\n private view: SuggestionMenuView<BSchema, I, S> | undefined;\n private triggerCharacters: string[] = [];\n\n constructor(editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n const triggerCharacters = this.triggerCharacters;\n this.addProsemirrorPlugin(\n new Plugin({\n key: suggestionMenuPluginKey,\n\n view: () => {\n this.view = new SuggestionMenuView<BSchema, I, S>(\n editor,\n (triggerCharacter, state) => {\n this.emit(`update ${triggerCharacter}`, state);\n },\n );\n return this.view;\n },\n\n state: {\n // Initialize the plugin's internal state.\n init(): SuggestionPluginState {\n return undefined;\n },\n\n // Apply changes to the plugin state from an editor transaction.\n apply: (\n transaction,\n prev,\n _oldState,\n newState,\n ): SuggestionPluginState => {\n // TODO: More clearly define which transactions should be ignored.\n if (transaction.getMeta(\"orderedListIndexing\") !== undefined) {\n return prev;\n }\n\n // Ignore transactions in code blocks.\n if (transaction.selection.$from.parent.type.spec.code) {\n return prev;\n }\n\n // Either contains the trigger character if the menu should be shown,\n // or null if it should be hidden.\n const suggestionPluginTransactionMeta: {\n triggerCharacter: string;\n deleteTriggerCharacter?: boolean;\n ignoreQueryLength?: boolean;\n } | null = transaction.getMeta(suggestionMenuPluginKey);\n\n if (\n typeof suggestionPluginTransactionMeta === \"object\" &&\n suggestionPluginTransactionMeta !== null\n ) {\n if (prev) {\n // Close the previous menu if it exists\n this.closeMenu();\n }\n const trackedPosition = trackPosition(\n editor,\n newState.selection.from -\n // Need to account for the trigger char that was inserted, so we offset the position by the length of the trigger character.\n suggestionPluginTransactionMeta.triggerCharacter.length,\n );\n return {\n triggerCharacter:\n suggestionPluginTransactionMeta.triggerCharacter,\n deleteTriggerCharacter:\n suggestionPluginTransactionMeta.deleteTriggerCharacter !==\n false,\n // When reading the queryStartPos, we offset the result by the length of the trigger character, to make it easy on the caller\n queryStartPos: () =>\n trackedPosition() +\n suggestionPluginTransactionMeta.triggerCharacter.length,\n query: \"\",\n decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,\n ignoreQueryLength:\n suggestionPluginTransactionMeta?.ignoreQueryLength,\n };\n }\n\n // Checks if the menu is hidden, in which case it doesn't need to be hidden or updated.\n if (prev === undefined) {\n return prev;\n }\n\n // Checks if the menu should be hidden.\n if (\n // Highlighting text should hide the menu.\n newState.selection.from !== newState.selection.to ||\n // Transactions with plugin metadata should hide the menu.\n suggestionPluginTransactionMeta === null ||\n // Certain mouse events should hide the menu.\n // TODO: Change to global mousedown listener.\n transaction.getMeta(\"focus\") ||\n transaction.getMeta(\"blur\") ||\n transaction.getMeta(\"pointer\") ||\n // Moving the caret before the character which triggered the menu should hide it.\n (prev.triggerCharacter !== undefined &&\n newState.selection.from < prev.queryStartPos()) ||\n // Moving the caret to a new block should hide the menu.\n !newState.selection.$from.sameParent(\n newState.doc.resolve(prev.queryStartPos()),\n )\n ) {\n return undefined;\n }\n\n const next = { ...prev };\n\n // Updates the current query.\n next.query = newState.doc.textBetween(\n prev.queryStartPos(),\n newState.selection.from,\n );\n\n return next;\n },\n },\n\n props: {\n handleTextInput(view, from, to, text) {\n // only on insert\n if (from === to) {\n const doc = view.state.doc;\n for (const str of triggerCharacters) {\n const snippet =\n str.length > 1\n ? doc.textBetween(from - str.length, from) + text\n : text;\n\n if (str === snippet) {\n view.dispatch(view.state.tr.insertText(text));\n view.dispatch(\n view.state.tr\n .setMeta(suggestionMenuPluginKey, {\n triggerCharacter: snippet,\n })\n .scrollIntoView(),\n );\n return true;\n }\n }\n }\n return false;\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const suggestionPluginState: SuggestionPluginState = (\n this as Plugin\n ).getState(state);\n\n if (suggestionPluginState === undefined) {\n return null;\n }\n\n // If the menu was opened programmatically by another extension, it may not use a trigger character. In this\n // case, the decoration is set on the whole block instead, as the decoration range would otherwise be empty.\n if (!suggestionPluginState.deleteTriggerCharacter) {\n const blockNode = findBlock(state.selection);\n if (blockNode) {\n return DecorationSet.create(state.doc, [\n Decoration.node(\n blockNode.pos,\n blockNode.pos + blockNode.node.nodeSize,\n {\n nodeName: \"span\",\n class: \"bn-suggestion-decorator\",\n \"data-decoration-id\": suggestionPluginState.decorationId,\n },\n ),\n ]);\n }\n }\n // Creates an inline decoration around the trigger character.\n return DecorationSet.create(state.doc, [\n Decoration.inline(\n suggestionPluginState.queryStartPos() -\n suggestionPluginState.triggerCharacter!.length,\n suggestionPluginState.queryStartPos(),\n {\n nodeName: \"span\",\n class: \"bn-suggestion-decorator\",\n \"data-decoration-id\": suggestionPluginState.decorationId,\n },\n ),\n ]);\n },\n },\n }),\n );\n }\n\n public onUpdate(\n triggerCharacter: string,\n callback: (state: SuggestionMenuState) => void,\n ) {\n if (!this.triggerCharacters.includes(triggerCharacter)) {\n this.addTriggerCharacter(triggerCharacter);\n }\n // TODO: be able to remove the triggerCharacter\n return this.on(`update ${triggerCharacter}`, callback);\n }\n\n addTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters.push(triggerCharacter);\n };\n\n // TODO: Should this be called automatically when listeners are removed?\n removeTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters = this.triggerCharacters.filter(\n (c) => c !== triggerCharacter,\n );\n };\n\n closeMenu = () => this.view!.closeMenu();\n\n clearQuery = () => this.view!.clearQuery();\n\n public get shown() {\n return this.view?.state?.show || false;\n }\n}\n\nexport function createSuggestionMenu<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(editor: BlockNoteEditor<BSchema, I, S>, triggerCharacter: string) {\n editor.suggestionMenus.addTriggerCharacter(triggerCharacter);\n}\n","import { Mark } from \"@tiptap/core\";\nimport { MarkSpec } from \"prosemirror-model\";\n\n// This copies the marks from @handlewithcare/prosemirror-suggest-changes,\n// but uses the Tiptap Mark API instead so we can use them in BlockNote\n\n// The ideal solution would be to not depend on tiptap nodes / marks, but be able to use prosemirror nodes / marks directly\n// this way we could directly use the exported marks from @handlewithcare/prosemirror-suggest-changes\nexport const SuggestionAddMark = Mark.create({\n name: \"insertion\",\n inclusive: false,\n excludes: \"deletion modification insertion\",\n addAttributes() {\n return {\n id: { default: null, validate: \"number\" }, // note: validate is supported in prosemirror but not in tiptap, so this doesn't actually work (considered not critical)\n };\n },\n extendMarkSchema(extension) {\n if (extension.name !== \"insertion\") {\n return {};\n }\n return {\n blocknoteIgnore: true,\n inclusive: false,\n\n toDOM(mark, inline) {\n return [\n \"ins\",\n {\n \"data-id\": String(mark.attrs[\"id\"]),\n \"data-inline\": String(inline),\n ...(!inline && { style: \"display: contents\" }), // changed to \"contents\" to make this work for table rows\n },\n 0,\n ];\n },\n parseDOM: [\n {\n tag: \"ins\",\n getAttrs(node) {\n if (!node.dataset[\"id\"]) {\n return false;\n }\n return {\n id: parseInt(node.dataset[\"id\"], 10),\n };\n },\n },\n ],\n } satisfies MarkSpec;\n },\n});\n\nexport const SuggestionDeleteMark = Mark.create({\n name: \"deletion\",\n inclusive: false,\n excludes: \"insertion modification deletion\",\n addAttributes() {\n return {\n id: { default: null, validate: \"number\" }, // note: validate is supported in prosemirror but not in tiptap\n };\n },\n extendMarkSchema(extension) {\n if (extension.name !== \"deletion\") {\n return {};\n }\n return {\n blocknoteIgnore: true,\n inclusive: false,\n\n // attrs: {\n // id: { validate: \"number\" },\n // },\n toDOM(mark, inline) {\n return [\n \"del\",\n {\n \"data-id\": String(mark.attrs[\"id\"]),\n \"data-inline\": String(inline),\n ...(!inline && { style: \"display: contents\" }), // changed to \"contents\" to make this work for table rows\n },\n 0,\n ];\n },\n parseDOM: [\n {\n tag: \"del\",\n getAttrs(node) {\n if (!node.dataset[\"id\"]) {\n return false;\n }\n return {\n id: parseInt(node.dataset[\"id\"], 10),\n };\n },\n },\n ],\n } satisfies MarkSpec;\n },\n});\n\nexport const SuggestionModificationMark = Mark.create({\n name: \"modification\",\n inclusive: false,\n excludes: \"deletion insertion\",\n addAttributes() {\n // note: validate is supported in prosemirror but not in tiptap\n return {\n id: { default: null, validate: \"number\" },\n type: { validate: \"string\" },\n attrName: { default: null, validate: \"string|null\" },\n previousValue: { default: null },\n newValue: { default: null },\n };\n },\n extendMarkSchema(extension) {\n if (extension.name !== \"modification\") {\n return {};\n }\n return {\n blocknoteIgnore: true,\n inclusive: false,\n // attrs: {\n // id: { validate: \"number\" },\n // type: { validate: \"string\" },\n // attrName: { default: null, validate: \"string|null\" },\n // previousValue: { default: null },\n // newValue: { default: null },\n // },\n toDOM(mark, inline) {\n return [\n inline ? \"span\" : \"div\",\n {\n \"data-type\": \"modification\",\n \"data-id\": String(mark.attrs[\"id\"]),\n \"data-mod-type\": mark.attrs[\"type\"] as string,\n \"data-mod-prev-val\": JSON.stringify(mark.attrs[\"previousValue\"]),\n // TODO: Try to serialize marks with toJSON?\n \"data-mod-new-val\": JSON.stringify(mark.attrs[\"newValue\"]),\n },\n 0,\n ];\n },\n parseDOM: [\n {\n tag: \"span[data-type='modification']\",\n getAttrs(node) {\n if (!node.dataset[\"id\"]) {\n return false;\n }\n return {\n id: parseInt(node.dataset[\"id\"], 10),\n type: node.dataset[\"modType\"],\n previousValue: node.dataset[\"modPrevVal\"],\n newValue: node.dataset[\"modNewVal\"],\n };\n },\n },\n {\n tag: \"div[data-type='modification']\",\n getAttrs(node) {\n if (!node.dataset[\"id\"]) {\n return false;\n }\n return {\n id: parseInt(node.dataset[\"id\"], 10),\n type: node.dataset[\"modType\"],\n previousValue: node.dataset[\"modPrevVal\"],\n };\n },\n },\n ],\n } satisfies MarkSpec;\n },\n});\n","import { EditorState, Plugin, PluginKey, PluginView } from \"prosemirror-state\";\nimport {\n CellSelection,\n addColumnAfter,\n addColumnBefore,\n addRowAfter,\n addRowBefore,\n deleteColumn,\n deleteRow,\n mergeCells,\n splitCell,\n} from \"prosemirror-tables\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\nimport {\n RelativeCellIndices,\n addRowsOrColumns,\n areInSameColumn,\n canColumnBeDraggedInto,\n canRowBeDraggedInto,\n cropEmptyRowsOrColumns,\n getCellsAtColumnHandle,\n getCellsAtRowHandle,\n getDimensionsOfTable,\n moveColumn,\n moveRow,\n} from \"../../api/blockManipulation/tables/tables.js\";\nimport { nodeToBlock } from \"../../api/nodeConversions/nodeToBlock.js\";\nimport { getNodeById } from \"../../api/nodeUtil.js\";\nimport {\n checkBlockIsDefaultType,\n isTableCellSelection,\n} from \"../../blocks/defaultBlockTypeGuards.js\";\nimport { DefaultBlockSchema } from \"../../blocks/defaultBlocks.js\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\nimport {\n BlockFromConfigNoChildren,\n BlockSchemaWithBlock,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { getDraggableBlockFromElement } from \"../getDraggableBlockFromElement.js\";\n\nlet dragImageElement: HTMLElement | undefined;\n\n// TODO consider switching this to jotai, it is a bit messy and noisy\nexport type TableHandlesState<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = {\n show: boolean;\n showAddOrRemoveRowsButton: boolean;\n showAddOrRemoveColumnsButton: boolean;\n referencePosCell: DOMRect | undefined;\n referencePosTable: DOMRect;\n\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], I, S>;\n colIndex: number | undefined;\n rowIndex: number | undefined;\n\n draggingState:\n | {\n draggedCellOrientation: \"row\" | \"col\";\n originalIndex: number;\n mousePos: number;\n }\n | undefined;\n\n widgetContainer: HTMLElement | undefined;\n};\n\nfunction setHiddenDragImage(rootEl: Document | ShadowRoot) {\n if (dragImageElement) {\n return;\n }\n\n dragImageElement = document.createElement(\"div\");\n dragImageElement.innerHTML = \"_\";\n dragImageElement.style.opacity = \"0\";\n dragImageElement.style.height = \"1px\";\n dragImageElement.style.width = \"1px\";\n if (rootEl instanceof Document) {\n rootEl.body.appendChild(dragImageElement);\n } else {\n rootEl.appendChild(dragImageElement);\n }\n}\n\nfunction unsetHiddenDragImage(rootEl: Document | ShadowRoot) {\n if (dragImageElement) {\n if (rootEl instanceof Document) {\n rootEl.body.removeChild(dragImageElement);\n } else {\n rootEl.removeChild(dragImageElement);\n }\n dragImageElement = undefined;\n }\n}\n\nfunction getChildIndex(node: Element) {\n return Array.prototype.indexOf.call(node.parentElement!.childNodes, node);\n}\n\n// Finds the DOM element corresponding to the table cell that the target element\n// is currently in. If the target element is not in a table cell, returns null.\nfunction domCellAround(target: Element) {\n let currentTarget: Element | undefined = target;\n while (\n currentTarget &&\n currentTarget.nodeName !== \"TD\" &&\n currentTarget.nodeName !== \"TH\" &&\n !currentTarget.classList.contains(\"tableWrapper\")\n ) {\n if (currentTarget.classList.contains(\"ProseMirror\")) {\n return undefined;\n }\n const parent: ParentNode | null = currentTarget.parentNode;\n\n if (!parent || !(parent instanceof Element)) {\n return undefined;\n }\n currentTarget = parent;\n }\n\n return currentTarget.nodeName === \"TD\" || currentTarget.nodeName === \"TH\"\n ? {\n type: \"cell\",\n domNode: currentTarget,\n tbodyNode: currentTarget.closest(\"tbody\"),\n }\n : {\n type: \"wrapper\",\n domNode: currentTarget,\n tbodyNode: currentTarget.querySelector(\"tbody\"),\n };\n}\n\n// Hides elements in the DOMwith the provided class names.\nfunction hideElements(selector: string, rootEl: Document | ShadowRoot) {\n const elementsToHide = rootEl.querySelectorAll(selector);\n\n for (let i = 0; i < elementsToHide.length; i++) {\n (elementsToHide[i] as HTMLElement).style.visibility = \"hidden\";\n }\n}\n\nexport class TableHandlesView<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> implements PluginView\n{\n public state?: TableHandlesState<I, S>;\n public emitUpdate: () => void;\n\n public tableId: string | undefined;\n public tablePos: number | undefined;\n public tableElement: HTMLElement | undefined;\n\n public menuFrozen = false;\n\n public mouseState: \"up\" | \"down\" | \"selecting\" = \"up\";\n\n public prevWasEditable: boolean | null = null;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >,\n private readonly pmView: EditorView,\n emitUpdate: (state: TableHandlesState<I, S>) => void,\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized image toolbar\");\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousemove\", this.mouseMoveHandler);\n pmView.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n window.addEventListener(\"mouseup\", this.mouseUpHandler);\n\n pmView.root.addEventListener(\n \"dragover\",\n this.dragOverHandler as EventListener,\n );\n pmView.root.addEventListener(\n \"drop\",\n this.dropHandler as unknown as EventListener,\n );\n }\n\n viewMousedownHandler = () => {\n this.mouseState = \"down\";\n };\n\n mouseUpHandler = (event: MouseEvent) => {\n this.mouseState = \"up\";\n this.mouseMoveHandler(event);\n };\n\n mouseMoveHandler = (event: MouseEvent) => {\n if (this.menuFrozen) {\n return;\n }\n\n if (this.mouseState === \"selecting\") {\n return;\n }\n\n if (\n !(event.target instanceof Element) ||\n !this.pmView.dom.contains(event.target)\n ) {\n return;\n }\n\n const target = domCellAround(event.target);\n\n if (\n target?.type === \"cell\" &&\n this.mouseState === \"down\" &&\n !this.state?.draggingState\n ) {\n // hide draghandles when selecting text as they could be in the way of the user\n this.mouseState = \"selecting\";\n\n if (this.state?.show) {\n this.state.show = false;\n this.state.showAddOrRemoveRowsButton = false;\n this.state.showAddOrRemoveColumnsButton = false;\n this.emitUpdate();\n }\n return;\n }\n\n if (!target || !this.editor.isEditable) {\n if (this.state?.show) {\n this.state.show = false;\n this.state.showAddOrRemoveRowsButton = false;\n this.state.showAddOrRemoveColumnsButton = false;\n this.emitUpdate();\n }\n return;\n }\n\n if (!target.tbodyNode) {\n return;\n }\n\n const tableRect = target.tbodyNode.getBoundingClientRect();\n\n const blockEl = getDraggableBlockFromElement(target.domNode, this.pmView);\n if (!blockEl) {\n return;\n }\n this.tableElement = blockEl.node;\n\n let tableBlock:\n | BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], I, S>\n | undefined;\n\n const pmNodeInfo = this.editor.transact((tr) =>\n getNodeById(blockEl.id, tr.doc),\n );\n if (!pmNodeInfo) {\n throw new Error(`Block with ID ${blockEl.id} not found`);\n }\n\n const block = nodeToBlock(\n pmNodeInfo.node,\n this.editor.pmSchema,\n this.editor.schema.blockSchema,\n this.editor.schema.inlineContentSchema,\n this.editor.schema.styleSchema,\n );\n\n if (checkBlockIsDefaultType(\"table\", block, this.editor)) {\n this.tablePos = pmNodeInfo.posBeforeNode + 1;\n tableBlock = block;\n }\n\n if (!tableBlock) {\n return;\n }\n\n this.tableId = blockEl.id;\n const widgetContainer = target.domNode\n .closest(\".tableWrapper\")\n ?.querySelector(\".table-widgets-container\") as HTMLElement;\n\n if (target?.type === \"wrapper\") {\n // if we're just to the right or below the table, show the extend buttons\n // (this is a bit hacky. It would probably be cleaner to render the extend buttons in the Table NodeView instead)\n const belowTable =\n event.clientY >= tableRect.bottom - 1 && // -1 to account for fractions of pixels in \"bottom\"\n event.clientY < tableRect.bottom + 20;\n const toRightOfTable =\n event.clientX >= tableRect.right - 1 &&\n event.clientX < tableRect.right + 20;\n\n // without this check, we'd also hide draghandles when hovering over them\n const hideHandles =\n event.clientX > tableRect.right || event.clientY > tableRect.bottom;\n\n this.state = {\n ...this.state!,\n show: true,\n showAddOrRemoveRowsButton: belowTable,\n showAddOrRemoveColumnsButton: toRightOfTable,\n referencePosTable: tableRect,\n block: tableBlock,\n widgetContainer,\n colIndex: hideHandles ? undefined : this.state?.colIndex,\n rowIndex: hideHandles ? undefined : this.state?.rowIndex,\n referencePosCell: hideHandles\n ? undefined\n : this.state?.referencePosCell,\n };\n } else {\n const colIndex = getChildIndex(target.domNode);\n const rowIndex = getChildIndex(target.domNode.parentElement!);\n const cellRect = target.domNode.getBoundingClientRect();\n\n if (\n this.state !== undefined &&\n this.state.show &&\n this.tableId === blockEl.id &&\n this.state.rowIndex === rowIndex &&\n this.state.colIndex === colIndex\n ) {\n // no update needed\n return;\n }\n\n this.state = {\n show: true,\n showAddOrRemoveColumnsButton:\n colIndex === tableBlock.content.rows[0].cells.length - 1,\n showAddOrRemoveRowsButton:\n rowIndex === tableBlock.content.rows.length - 1,\n referencePosTable: tableRect,\n\n block: tableBlock,\n draggingState: undefined,\n referencePosCell: cellRect,\n colIndex: colIndex,\n rowIndex: rowIndex,\n\n widgetContainer,\n };\n }\n this.emitUpdate();\n\n return false;\n };\n\n dragOverHandler = (event: DragEvent) => {\n if (this.state?.draggingState === undefined) {\n return;\n }\n\n event.preventDefault();\n event.dataTransfer!.dropEffect = \"move\";\n\n hideElements(\n \".prosemirror-dropcursor-block, .prosemirror-dropcursor-inline\",\n this.pmView.root,\n );\n\n // The mouse cursor coordinates, bounded to the table's bounding box. The\n // bounding box is shrunk by 1px on each side to ensure that the bounded\n // coordinates are always inside a table cell.\n const boundedMouseCoords = {\n left: Math.min(\n Math.max(event.clientX, this.state.referencePosTable.left + 1),\n this.state.referencePosTable.right - 1,\n ),\n top: Math.min(\n Math.max(event.clientY, this.state.referencePosTable.top + 1),\n this.state.referencePosTable.bottom - 1,\n ),\n };\n\n // Gets the table cell element that the bounded mouse cursor coordinates lie\n // in.\n const tableCellElements = this.pmView.root\n .elementsFromPoint(boundedMouseCoords.left, boundedMouseCoords.top)\n .filter(\n (element) => element.tagName === \"TD\" || element.tagName === \"TH\",\n );\n if (tableCellElements.length === 0) {\n return;\n }\n const tableCellElement = tableCellElements[0];\n\n let emitStateUpdate = false;\n\n // Gets current row and column index.\n const rowIndex = getChildIndex(tableCellElement.parentElement!);\n const colIndex = getChildIndex(tableCellElement);\n\n // Checks if the drop cursor needs to be updated. This affects decorations\n // only so it doesn't trigger a state update.\n const oldIndex =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? this.state.rowIndex\n : this.state.colIndex;\n const newIndex =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? rowIndex\n : colIndex;\n const dispatchDecorationsTransaction = newIndex !== oldIndex;\n\n // Checks if either the hovered cell has changed and updates the row and\n // column index. Also updates the reference DOMRect.\n if (this.state.rowIndex !== rowIndex || this.state.colIndex !== colIndex) {\n this.state.rowIndex = rowIndex;\n this.state.colIndex = colIndex;\n\n this.state.referencePosCell = tableCellElement.getBoundingClientRect();\n\n emitStateUpdate = true;\n }\n\n // Checks if the mouse cursor position along the axis that the user is\n // dragging on has changed and updates it.\n const mousePos =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? boundedMouseCoords.top\n : boundedMouseCoords.left;\n if (this.state.draggingState.mousePos !== mousePos) {\n this.state.draggingState.mousePos = mousePos;\n\n emitStateUpdate = true;\n }\n\n // Emits a state update if any of the fields have changed.\n if (emitStateUpdate) {\n this.emitUpdate();\n }\n\n // Dispatches a dummy transaction to force a decorations update if\n // necessary.\n if (dispatchDecorationsTransaction) {\n this.editor.transact((tr) => tr.setMeta(tableHandlesPluginKey, true));\n }\n };\n\n dropHandler = (event: DragEvent) => {\n this.mouseState = \"up\";\n if (this.state === undefined || this.state.draggingState === undefined) {\n return false;\n }\n\n if (\n this.state.rowIndex === undefined ||\n this.state.colIndex === undefined\n ) {\n throw new Error(\n \"Attempted to drop table row or column, but no table block was hovered prior.\",\n );\n }\n\n event.preventDefault();\n\n const { draggingState, colIndex, rowIndex } = this.state;\n\n const columnWidths = this.state.block.content.columnWidths;\n\n if (draggingState.draggedCellOrientation === \"row\") {\n if (\n !canRowBeDraggedInto(\n this.state.block,\n draggingState.originalIndex,\n rowIndex,\n )\n ) {\n // If the target row is invalid, don't move the row\n return false;\n }\n const newTable = moveRow(\n this.state.block,\n draggingState.originalIndex,\n rowIndex,\n );\n this.editor.updateBlock(this.state.block, {\n type: \"table\",\n content: {\n ...this.state.block.content,\n rows: newTable as any,\n },\n });\n } else {\n if (\n !canColumnBeDraggedInto(\n this.state.block,\n draggingState.originalIndex,\n colIndex,\n )\n ) {\n // If the target column is invalid, don't move the column\n return false;\n }\n const newTable = moveColumn(\n this.state.block,\n draggingState.originalIndex,\n colIndex,\n );\n const [columnWidth] = columnWidths.splice(draggingState.originalIndex, 1);\n columnWidths.splice(colIndex, 0, columnWidth);\n this.editor.updateBlock(this.state.block, {\n type: \"table\",\n content: {\n ...this.state.block.content,\n columnWidths,\n rows: newTable as any,\n },\n });\n }\n\n // Have to reset text cursor position to the block as `updateBlock` moves\n // the existing selection out of the block.\n this.editor.setTextCursorPosition(this.state.block.id);\n\n return true;\n };\n // Updates drag handles when the table is modified or removed.\n update() {\n if (!this.state || !this.state.show) {\n return;\n }\n\n // Hide handles if the table block has been removed.\n this.state.block = this.editor.getBlock(this.state.block.id)!;\n if (\n !this.state.block ||\n this.state.block.type !== \"table\" ||\n // when collaborating, the table element might be replaced and out of date\n // because yjs replaces the element when for example you change the color via the side menu\n !this.tableElement?.isConnected\n ) {\n this.state.show = false;\n this.state.showAddOrRemoveRowsButton = false;\n this.state.showAddOrRemoveColumnsButton = false;\n this.emitUpdate();\n\n return;\n }\n\n const { height: rowCount, width: colCount } = getDimensionsOfTable(\n this.state.block,\n );\n\n if (\n this.state.rowIndex !== undefined &&\n this.state.colIndex !== undefined\n ) {\n // If rows or columns are deleted in the update, the hovered indices for\n // those may now be out of bounds. If this is the case, they are moved to\n // the new last row or column.\n if (this.state.rowIndex >= rowCount) {\n this.state.rowIndex = rowCount - 1;\n }\n if (this.state.colIndex >= colCount) {\n this.state.colIndex = colCount - 1;\n }\n }\n\n // Update bounding boxes.\n const tableBody = this.tableElement!.querySelector(\"tbody\");\n\n if (!tableBody) {\n throw new Error(\n \"Table block does not contain a 'tbody' HTML element. This should never happen.\",\n );\n }\n\n if (\n this.state.rowIndex !== undefined &&\n this.state.colIndex !== undefined\n ) {\n const row = tableBody.children[this.state.rowIndex];\n const cell = row.children[this.state.colIndex];\n if (cell) {\n this.state.referencePosCell = cell.getBoundingClientRect();\n } else {\n this.state.rowIndex = undefined;\n this.state.colIndex = undefined;\n }\n }\n this.state.referencePosTable = tableBody.getBoundingClientRect();\n\n this.emitUpdate();\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousemove\", this.mouseMoveHandler);\n window.removeEventListener(\"mouseup\", this.mouseUpHandler);\n this.pmView.dom.removeEventListener(\"mousedown\", this.viewMousedownHandler);\n this.pmView.root.removeEventListener(\n \"dragover\",\n this.dragOverHandler as EventListener,\n );\n this.pmView.root.removeEventListener(\n \"drop\",\n this.dropHandler as unknown as EventListener,\n );\n }\n}\n\nexport const tableHandlesPluginKey = new PluginKey(\"TableHandlesPlugin\");\n\nexport class TableHandlesProsemirrorPlugin<\n I extends InlineContentSchema,\n S extends StyleSchema,\n> extends BlockNoteExtension {\n public static key() {\n return \"tableHandles\";\n }\n\n private view: TableHandlesView<I, S> | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >,\n ) {\n super();\n this.addProsemirrorPlugin(\n new Plugin({\n key: tableHandlesPluginKey,\n view: (editorView) => {\n this.view = new TableHandlesView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n // We use decorations to render the drop cursor when dragging a table row\n // or column. The decorations are updated in the `dragOverHandler` method.\n props: {\n decorations: (state) => {\n if (\n this.view === undefined ||\n this.view.state === undefined ||\n this.view.state.draggingState === undefined ||\n this.view.tablePos === undefined\n ) {\n return;\n }\n\n const newIndex =\n this.view.state.draggingState.draggedCellOrientation === \"row\"\n ? this.view.state.rowIndex\n : this.view.state.colIndex;\n\n if (newIndex === undefined) {\n return;\n }\n\n const decorations: Decoration[] = [];\n const { block, draggingState } = this.view.state;\n const { originalIndex, draggedCellOrientation } = draggingState;\n\n // Return empty decorations if:\n // - Dragging to same position\n // - No block exists\n // - Row drag not allowed\n // - Column drag not allowed\n if (\n newIndex === originalIndex ||\n !block ||\n (draggedCellOrientation === \"row\" &&\n !canRowBeDraggedInto(block, originalIndex, newIndex)) ||\n (draggedCellOrientation === \"col\" &&\n !canColumnBeDraggedInto(block, originalIndex, newIndex))\n ) {\n return DecorationSet.create(state.doc, decorations);\n }\n\n // Gets the table to show the drop cursor in.\n const tableResolvedPos = state.doc.resolve(this.view.tablePos + 1);\n\n if (\n this.view.state.draggingState.draggedCellOrientation === \"row\"\n ) {\n const cellsInRow = getCellsAtRowHandle(\n this.view.state.block,\n newIndex,\n );\n\n cellsInRow.forEach(({ row, col }) => {\n // Gets each row in the table.\n const rowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(row) + 1,\n );\n\n // Gets the cell within the row.\n const cellResolvedPos = state.doc.resolve(\n rowResolvedPos.posAtIndex(col) + 1,\n );\n const cellNode = cellResolvedPos.node();\n // Creates a decoration at the start or end of each cell,\n // depending on whether the new index is before or after the\n // original index.\n const decorationPos =\n cellResolvedPos.pos +\n (newIndex > originalIndex ? cellNode.nodeSize - 2 : 0);\n decorations.push(\n // The widget is a small bar which spans the width of the cell.\n Decoration.widget(decorationPos, () => {\n const widget = document.createElement(\"div\");\n widget.className = \"bn-table-drop-cursor\";\n widget.style.left = \"0\";\n widget.style.right = \"0\";\n // This is only necessary because the drop indicator's height\n // is an even number of pixels, whereas the border between\n // table cells is an odd number of pixels. So this makes the\n // positioning slightly more consistent regardless of where\n // the row is being dropped.\n if (newIndex > originalIndex) {\n widget.style.bottom = \"-2px\";\n } else {\n widget.style.top = \"-3px\";\n }\n widget.style.height = \"4px\";\n\n return widget;\n }),\n );\n });\n } else {\n const cellsInColumn = getCellsAtColumnHandle(\n this.view.state.block,\n newIndex,\n );\n\n cellsInColumn.forEach(({ row, col }) => {\n // Gets each row in the table.\n const rowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(row) + 1,\n );\n\n // Gets the cell within the row.\n const cellResolvedPos = state.doc.resolve(\n rowResolvedPos.posAtIndex(col) + 1,\n );\n const cellNode = cellResolvedPos.node();\n\n // Creates a decoration at the start or end of each cell,\n // depending on whether the new index is before or after the\n // original index.\n const decorationPos =\n cellResolvedPos.pos +\n (newIndex > originalIndex ? cellNode.nodeSize - 2 : 0);\n\n decorations.push(\n // The widget is a small bar which spans the height of the cell.\n Decoration.widget(decorationPos, () => {\n const widget = document.createElement(\"div\");\n widget.className = \"bn-table-drop-cursor\";\n widget.style.top = \"0\";\n widget.style.bottom = \"0\";\n // This is only necessary because the drop indicator's width\n // is an even number of pixels, whereas the border between\n // table cells is an odd number of pixels. So this makes the\n // positioning slightly more consistent regardless of where\n // the column is being dropped.\n if (newIndex > originalIndex) {\n widget.style.right = \"-2px\";\n } else {\n widget.style.left = \"-3px\";\n }\n widget.style.width = \"4px\";\n\n return widget;\n }),\n );\n });\n }\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n }),\n );\n }\n\n public onUpdate(callback: (state: TableHandlesState<I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Callback that should be set on the `dragStart` event for whichever element\n * is used as the column drag handle.\n */\n colDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientX: number;\n }) => {\n if (\n this.view!.state === undefined ||\n this.view!.state.colIndex === undefined\n ) {\n throw new Error(\n \"Attempted to drag table column, but no table block was hovered prior.\",\n );\n }\n\n this.view!.state.draggingState = {\n draggedCellOrientation: \"col\",\n originalIndex: this.view!.state.colIndex,\n mousePos: event.clientX,\n };\n this.view!.emitUpdate();\n\n this.editor.transact((tr) =>\n tr.setMeta(tableHandlesPluginKey, {\n draggedCellOrientation:\n this.view!.state!.draggingState!.draggedCellOrientation,\n originalIndex: this.view!.state!.colIndex,\n newIndex: this.view!.state!.colIndex,\n tablePos: this.view!.tablePos,\n }),\n );\n\n if (!this.editor.prosemirrorView) {\n throw new Error(\"Editor view not initialized.\");\n }\n\n setHiddenDragImage(this.editor.prosemirrorView.root);\n event.dataTransfer!.setDragImage(dragImageElement!, 0, 0);\n event.dataTransfer!.effectAllowed = \"move\";\n };\n\n /**\n * Callback that should be set on the `dragStart` event for whichever element\n * is used as the row drag handle.\n */\n rowDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n }) => {\n if (\n this.view!.state === undefined ||\n this.view!.state.rowIndex === undefined\n ) {\n throw new Error(\n \"Attempted to drag table row, but no table block was hovered prior.\",\n );\n }\n\n this.view!.state.draggingState = {\n draggedCellOrientation: \"row\",\n originalIndex: this.view!.state.rowIndex,\n mousePos: event.clientY,\n };\n this.view!.emitUpdate();\n\n this.editor.transact((tr) =>\n tr.setMeta(tableHandlesPluginKey, {\n draggedCellOrientation:\n this.view!.state!.draggingState!.draggedCellOrientation,\n originalIndex: this.view!.state!.rowIndex,\n newIndex: this.view!.state!.rowIndex,\n tablePos: this.view!.tablePos,\n }),\n );\n\n if (!this.editor.prosemirrorView) {\n throw new Error(\"Editor view not initialized.\");\n }\n\n setHiddenDragImage(this.editor.prosemirrorView.root);\n event.dataTransfer!.setDragImage(dragImageElement!, 0, 0);\n event.dataTransfer!.effectAllowed = \"copyMove\";\n };\n\n /**\n * Callback that should be set on the `dragEnd` event for both the element\n * used as the row drag handle, and the one used as the column drag handle.\n */\n dragEnd = () => {\n if (this.view!.state === undefined) {\n throw new Error(\n \"Attempted to drag table row, but no table block was hovered prior.\",\n );\n }\n\n this.view!.state.draggingState = undefined;\n this.view!.emitUpdate();\n\n this.editor.transact((tr) => tr.setMeta(tableHandlesPluginKey, null));\n\n if (!this.editor.prosemirrorView) {\n throw new Error(\"Editor view not initialized.\");\n }\n\n unsetHiddenDragImage(this.editor.prosemirrorView.root);\n };\n\n /**\n * Freezes the drag handles. When frozen, they will stay attached to the same\n * cell regardless of which cell is hovered by the mouse cursor.\n */\n freezeHandles = () => {\n this.view!.menuFrozen = true;\n };\n\n /**\n * Unfreezes the drag handles. When frozen, they will stay attached to the\n * same cell regardless of which cell is hovered by the mouse cursor.\n */\n unfreezeHandles = () => {\n this.view!.menuFrozen = false;\n };\n\n getCellsAtRowHandle = (\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeRowIndex: RelativeCellIndices[\"row\"],\n ) => {\n return getCellsAtRowHandle(block, relativeRowIndex);\n };\n\n /**\n * Get all the cells in a column of the table block.\n */\n getCellsAtColumnHandle = (\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeColumnIndex: RelativeCellIndices[\"col\"],\n ) => {\n return getCellsAtColumnHandle(block, relativeColumnIndex);\n };\n\n /**\n * Sets the selection to the given cell or a range of cells.\n * @returns The new state after the selection has been set.\n */\n private setCellSelection = (\n state: EditorState,\n relativeStartCell: RelativeCellIndices,\n relativeEndCell: RelativeCellIndices = relativeStartCell,\n ) => {\n const view = this.view;\n\n if (!view) {\n throw new Error(\"Table handles view not initialized\");\n }\n\n const tableResolvedPos = state.doc.resolve(view.tablePos! + 1);\n const startRowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(relativeStartCell.row) + 1,\n );\n const startCellResolvedPos = state.doc.resolve(\n // No need for +1, since CellSelection expects the position before the cell\n startRowResolvedPos.posAtIndex(relativeStartCell.col),\n );\n const endRowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(relativeEndCell.row) + 1,\n );\n const endCellResolvedPos = state.doc.resolve(\n // No need for +1, since CellSelection expects the position before the cell\n endRowResolvedPos.posAtIndex(relativeEndCell.col),\n );\n\n // Begin a new transaction to set the selection\n const tr = state.tr;\n\n // Set the selection to the given cell or a range of cells\n tr.setSelection(\n new CellSelection(startCellResolvedPos, endCellResolvedPos),\n );\n\n // Quickly apply the transaction to get the new state to update the selection before splitting the cell\n return state.apply(tr);\n };\n\n /**\n * Adds a row or column to the table using prosemirror-table commands\n */\n addRowOrColumn = (\n index: RelativeCellIndices[\"row\"] | RelativeCellIndices[\"col\"],\n direction:\n | { orientation: \"row\"; side: \"above\" | \"below\" }\n | { orientation: \"column\"; side: \"left\" | \"right\" },\n ) => {\n this.editor.exec((beforeState, dispatch) => {\n const state = this.setCellSelection(\n beforeState,\n direction.orientation === \"row\"\n ? { row: index, col: 0 }\n : { row: 0, col: index },\n );\n\n if (direction.orientation === \"row\") {\n if (direction.side === \"above\") {\n return addRowBefore(state, dispatch);\n } else {\n return addRowAfter(state, dispatch);\n }\n } else {\n if (direction.side === \"left\") {\n return addColumnBefore(state, dispatch);\n } else {\n return addColumnAfter(state, dispatch);\n }\n }\n });\n };\n\n /**\n * Removes a row or column from the table using prosemirror-table commands\n */\n removeRowOrColumn = (\n index: RelativeCellIndices[\"row\"] | RelativeCellIndices[\"col\"],\n direction: \"row\" | \"column\",\n ) => {\n if (direction === \"row\") {\n return this.editor.exec((beforeState, dispatch) => {\n const state = this.setCellSelection(beforeState, {\n row: index,\n col: 0,\n });\n return deleteRow(state, dispatch);\n });\n } else {\n return this.editor.exec((beforeState, dispatch) => {\n const state = this.setCellSelection(beforeState, {\n row: 0,\n col: index,\n });\n return deleteColumn(state, dispatch);\n });\n }\n };\n\n /**\n * Merges the cells in the table block.\n */\n mergeCells = (cellsToMerge?: {\n relativeStartCell: RelativeCellIndices;\n relativeEndCell: RelativeCellIndices;\n }) => {\n return this.editor.exec((beforeState, dispatch) => {\n const state = cellsToMerge\n ? this.setCellSelection(\n beforeState,\n cellsToMerge.relativeStartCell,\n cellsToMerge.relativeEndCell,\n )\n : beforeState;\n\n return mergeCells(state, dispatch);\n });\n };\n\n /**\n * Splits the cell in the table block.\n * If no cell is provided, the current cell selected will be split.\n */\n splitCell = (relativeCellToSplit?: RelativeCellIndices) => {\n return this.editor.exec((beforeState, dispatch) => {\n const state = relativeCellToSplit\n ? this.setCellSelection(beforeState, relativeCellToSplit)\n : beforeState;\n\n return splitCell(state, dispatch);\n });\n };\n\n /**\n * Gets the start and end cells of the current cell selection.\n * @returns The start and end cells of the current cell selection.\n */\n getCellSelection = ():\n | undefined\n | {\n from: RelativeCellIndices;\n to: RelativeCellIndices;\n /**\n * All of the cells that are within the selected range.\n */\n cells: RelativeCellIndices[];\n } => {\n // Based on the current selection, find the table cells that are within the selected range\n\n return this.editor.transact((tr) => {\n const selection = tr.selection;\n\n let $fromCell = selection.$from;\n let $toCell = selection.$to;\n if (isTableCellSelection(selection)) {\n // When the selection is a table cell selection, we can find the\n // from and to cells by iterating over the ranges in the selection\n const { ranges } = selection;\n ranges.forEach((range) => {\n $fromCell = range.$from.min($fromCell ?? range.$from);\n $toCell = range.$to.max($toCell ?? range.$to);\n });\n } else {\n // When the selection is a normal text selection\n // Assumes we are within a tableParagraph\n // And find the from and to cells by resolving the positions\n $fromCell = tr.doc.resolve(\n selection.$from.pos - selection.$from.parentOffset - 1,\n );\n $toCell = tr.doc.resolve(\n selection.$to.pos - selection.$to.parentOffset - 1,\n );\n\n // Opt-out when the selection is not pointing into cells\n if ($fromCell.pos === 0 || $toCell.pos === 0) {\n return undefined;\n }\n }\n\n // Find the row and table that the from and to cells are in\n const $fromRow = tr.doc.resolve(\n $fromCell.pos - $fromCell.parentOffset - 1,\n );\n const $toRow = tr.doc.resolve($toCell.pos - $toCell.parentOffset - 1);\n\n // Find the table\n const $table = tr.doc.resolve($fromRow.pos - $fromRow.parentOffset - 1);\n\n // Find the column and row indices of the from and to cells\n const fromColIndex = $fromCell.index($fromRow.depth);\n const fromRowIndex = $fromRow.index($table.depth);\n const toColIndex = $toCell.index($toRow.depth);\n const toRowIndex = $toRow.index($table.depth);\n\n const cells: RelativeCellIndices[] = [];\n for (let row = fromRowIndex; row <= toRowIndex; row++) {\n for (let col = fromColIndex; col <= toColIndex; col++) {\n cells.push({ row, col });\n }\n }\n\n return {\n from: {\n row: fromRowIndex,\n col: fromColIndex,\n },\n to: {\n row: toRowIndex,\n col: toColIndex,\n },\n cells,\n };\n });\n };\n\n /**\n * Gets the direction of the merge based on the current cell selection.\n *\n * Returns undefined when there is no cell selection, or the selection is not within a table.\n */\n getMergeDirection = (\n block:\n | BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>\n | undefined,\n ) => {\n return this.editor.transact((tr) => {\n const isSelectingTableCells = isTableCellSelection(tr.selection)\n ? tr.selection\n : undefined;\n\n if (\n !isSelectingTableCells ||\n !block ||\n // Only offer the merge button if there is more than one cell selected.\n isSelectingTableCells.ranges.length <= 1\n ) {\n return undefined;\n }\n\n const cellSelection = this.getCellSelection();\n\n if (!cellSelection) {\n return undefined;\n }\n\n if (areInSameColumn(cellSelection.from, cellSelection.to, block)) {\n return \"vertical\";\n }\n\n return \"horizontal\";\n });\n };\n\n cropEmptyRowsOrColumns = (\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n removeEmpty: \"columns\" | \"rows\",\n ) => {\n return cropEmptyRowsOrColumns(block, removeEmpty);\n };\n\n addRowsOrColumns = (\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n addType: \"columns\" | \"rows\",\n numToAdd: number,\n ) => {\n return addRowsOrColumns(block, addType, numToAdd);\n };\n}\n","import { Extension } from \"@tiptap/core\";\n\nexport const TextAlignmentExtension = Extension.create({\n name: \"textAlignment\",\n\n addGlobalAttributes() {\n return [\n {\n // Attribute is applied to block content instead of container so that child blocks don't inherit the text\n // alignment styling.\n types: [\n \"paragraph\",\n \"heading\",\n \"bulletListItem\",\n \"numberedListItem\",\n \"checkListItem\",\n \"tableCell\",\n \"tableHeader\",\n ],\n attributes: {\n textAlignment: {\n default: \"left\",\n parseHTML: (element) => {\n return element.getAttribute(\"data-text-alignment\");\n },\n renderHTML: (attributes) => {\n if (attributes.textAlignment === \"left\") {\n return {};\n }\n return {\n \"data-text-alignment\": attributes.textAlignment,\n };\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { defaultProps } from \"../../blocks/defaultProps.js\";\n\nexport const TextColorExtension = Extension.create({\n name: \"blockTextColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\", \"tableCell\", \"tableHeader\"],\n attributes: {\n textColor: {\n default: defaultProps.textColor.default,\n parseHTML: (element) =>\n element.hasAttribute(\"data-text-color\")\n ? element.getAttribute(\"data-text-color\")\n : defaultProps.textColor.default,\n renderHTML: (attributes) => {\n if (attributes.textColor === defaultProps.textColor.default) {\n return {};\n }\n return {\n \"data-text-color\": attributes.textColor,\n };\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\n\n// based on https://github.com/ueberdosis/tiptap/blob/40a9404c94c7fef7900610c195536384781ae101/demos/src/Experiments/TrailingNode/Vue/trailing-node.ts\n\n/**\n * Extension based on:\n * - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js\n * - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts\n */\n\nexport interface TrailingNodeOptions {\n node: string;\n}\n\n/**\n * Add a trailing node to the document so the user can always click at the bottom of the document and start typing\n */\nexport const TrailingNode = Extension.create<TrailingNodeOptions>({\n name: \"trailingNode\",\n\n addProseMirrorPlugins() {\n const plugin = new PluginKey(this.name);\n // const disabledNodes = Object.entries(this.editor.schema.nodes)\n // .map(([, value]) => value)\n // .filter((node) => this.options.notAfter.includes(node.name));\n\n return [\n new Plugin({\n key: plugin,\n appendTransaction: (_, __, state) => {\n const { doc, tr, schema } = state;\n const shouldInsertNodeAtEnd = plugin.getState(state);\n const endPosition = doc.content.size - 2;\n const type = schema.nodes[\"blockContainer\"];\n const contentType = schema.nodes[\"paragraph\"];\n if (!shouldInsertNodeAtEnd) {\n return;\n }\n\n return tr.insert(\n endPosition,\n type.create(undefined, contentType.create()),\n );\n },\n state: {\n init: (_, _state) => {\n // (maybe fix): use same logic as apply() here\n // so it works when initializing\n },\n apply: (tr, value) => {\n if (!tr.docChanged) {\n return value;\n }\n\n let lastNode = tr.doc.lastChild;\n\n if (!lastNode || lastNode.type.name !== \"blockGroup\") {\n throw new Error(\"Expected blockGroup\");\n }\n\n lastNode = lastNode.lastChild;\n\n if (!lastNode || lastNode.type.name !== \"blockContainer\") {\n return true; // not a blockContainer, but for example Columns. Insert trailing node\n }\n\n const lastContentNode = lastNode.firstChild;\n\n if (!lastContentNode) {\n throw new Error(\"Expected blockContent\");\n }\n\n // If last node is not empty (size > 4) or it doesn't contain\n // inline content, we need to add a trailing node.\n return (\n lastNode.nodeSize > 4 ||\n lastContentNode.type.spec.content !== \"inline*\"\n );\n },\n },\n }),\n ];\n },\n});\n","import { Node } from \"@tiptap/core\";\n\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport { BlockNoteDOMAttributes } from \"../schema/index.js\";\nimport { mergeCSSClasses } from \"../util/browser.js\";\n\n// Object containing all possible block attributes.\nconst BlockAttributes: Record<string, string> = {\n blockColor: \"data-block-color\",\n blockStyle: \"data-block-style\",\n id: \"data-id\",\n depth: \"data-depth\",\n depthChange: \"data-depth-change\",\n};\n\n/**\n * The main \"Block node\" documents consist of\n */\nexport const BlockContainer = Node.create<{\n domAttributes?: BlockNoteDOMAttributes;\n editor: BlockNoteEditor<any, any, any>;\n}>({\n name: \"blockContainer\",\n group: \"blockGroupChild bnBlock\",\n // A block always contains content, and optionally a blockGroup which contains nested blocks\n content: \"blockContent blockGroup?\",\n // Ensures content-specific keyboard handlers trigger first.\n priority: 50,\n defining: true,\n marks: \"insertion modification deletion\",\n parseHTML() {\n return [\n {\n tag: \"div[data-node-type=\" + this.name + \"]\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const attrs: Record<string, string> = {};\n for (const [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {\n if (element.getAttribute(HTMLAttr)) {\n attrs[nodeAttr] = element.getAttribute(HTMLAttr)!;\n }\n }\n\n return attrs;\n },\n },\n // Ignore `blockOuter` divs, but parse the `blockContainer` divs inside them.\n {\n tag: `div[data-node-type=\"blockOuter\"]`,\n skip: true,\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const blockOuter = document.createElement(\"div\");\n blockOuter.className = \"bn-block-outer\";\n blockOuter.setAttribute(\"data-node-type\", \"blockOuter\");\n for (const [attribute, value] of Object.entries(HTMLAttributes)) {\n if (attribute !== \"class\") {\n blockOuter.setAttribute(attribute, value);\n }\n }\n\n const blockHTMLAttributes = {\n ...(this.options.domAttributes?.block || {}),\n ...HTMLAttributes,\n };\n const block = document.createElement(\"div\");\n block.className = mergeCSSClasses(\"bn-block\", blockHTMLAttributes.class);\n block.setAttribute(\"data-node-type\", this.name);\n for (const [attribute, value] of Object.entries(blockHTMLAttributes)) {\n if (attribute !== \"class\") {\n block.setAttribute(attribute, value);\n }\n }\n\n blockOuter.appendChild(block);\n\n return {\n dom: blockOuter,\n contentDOM: block,\n };\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport { BlockNoteDOMAttributes } from \"../schema/index.js\";\nimport { mergeCSSClasses } from \"../util/browser.js\";\n\nexport const BlockGroup = Node.create<{\n domAttributes?: BlockNoteDOMAttributes;\n}>({\n name: \"blockGroup\",\n group: \"childContainer\",\n content: \"blockGroupChild+\",\n marks: \"deletion insertion modification\",\n parseHTML() {\n return [\n {\n tag: \"div\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.getAttribute(\"data-node-type\") === \"blockGroup\") {\n // Null means the element matches, but we don't want to add any attributes to the node.\n return null;\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const blockGroupHTMLAttributes = {\n ...(this.options.domAttributes?.blockGroup || {}),\n ...HTMLAttributes,\n };\n const blockGroup = document.createElement(\"div\");\n blockGroup.className = mergeCSSClasses(\n \"bn-block-group\",\n blockGroupHTMLAttributes.class,\n );\n blockGroup.setAttribute(\"data-node-type\", \"blockGroup\");\n for (const [attribute, value] of Object.entries(blockGroupHTMLAttributes)) {\n if (attribute !== \"class\") {\n blockGroup.setAttribute(attribute, value);\n }\n }\n\n return {\n dom: blockGroup,\n contentDOM: blockGroup,\n };\n },\n});\n","import { Node } from \"@tiptap/core\";\n\nexport const Doc = Node.create({\n name: \"doc\",\n topNode: true,\n content: \"blockGroup\",\n marks: \"insertion modification deletion\",\n});\n","import * as Y from \"yjs\";\n\nimport {\n yCursorPluginKey,\n ySyncPluginKey,\n yUndoPluginKey,\n} from \"y-prosemirror\";\nimport { CursorPlugin } from \"./CursorPlugin.js\";\nimport { SyncPlugin } from \"./SyncPlugin.js\";\nimport { UndoPlugin } from \"./UndoPlugin.js\";\n\nimport {\n BlockNoteEditor,\n BlockNoteEditorOptions,\n} from \"../../editor/BlockNoteEditor.js\";\nimport { BlockNoteExtension } from \"../../editor/BlockNoteExtension.js\";\n\nexport class ForkYDocPlugin extends BlockNoteExtension<{\n forked: boolean;\n}> {\n public static key() {\n return \"ForkYDocPlugin\";\n }\n\n private editor: BlockNoteEditor<any, any, any>;\n private collaboration: BlockNoteEditorOptions<any, any, any>[\"collaboration\"];\n\n constructor({\n editor,\n collaboration,\n }: {\n editor: BlockNoteEditor<any, any, any>;\n collaboration: BlockNoteEditorOptions<any, any, any>[\"collaboration\"];\n }) {\n super(editor);\n this.editor = editor;\n this.collaboration = collaboration;\n }\n\n /**\n * To find a fragment in another ydoc, we need to search for it.\n */\n private findTypeInOtherYdoc<T extends Y.AbstractType<any>>(\n ytype: T,\n otherYdoc: Y.Doc,\n ): T {\n const ydoc = ytype.doc!;\n if (ytype._item === null) {\n /**\n * If is a root type, we need to find the root key in the original ydoc\n * and use it to get the type in the other ydoc.\n */\n const rootKey = Array.from(ydoc.share.keys()).find(\n (key) => ydoc.share.get(key) === ytype,\n );\n if (rootKey == null) {\n throw new Error(\"type does not exist in other ydoc\");\n }\n return otherYdoc.get(rootKey, ytype.constructor as new () => T) as T;\n } else {\n /**\n * If it is a sub type, we use the item id to find the history type.\n */\n const ytypeItem = ytype._item;\n const otherStructs =\n otherYdoc.store.clients.get(ytypeItem.id.client) ?? [];\n const itemIndex = Y.findIndexSS(otherStructs, ytypeItem.id.clock);\n const otherItem = otherStructs[itemIndex] as Y.Item;\n const otherContent = otherItem.content as Y.ContentType;\n return otherContent.type as T;\n }\n }\n\n /**\n * Whether the editor is editing a forked document,\n * preserving a reference to the original document and the forked document.\n */\n public get isForkedFromRemote() {\n return this.forkedState !== undefined;\n }\n\n /**\n * Stores whether the editor is editing a forked document,\n * preserving a reference to the original document and the forked document.\n */\n private forkedState:\n | {\n originalFragment: Y.XmlFragment;\n forkedFragment: Y.XmlFragment;\n }\n | undefined;\n\n /**\n * Fork the Y.js document from syncing to the remote,\n * allowing modifications to the document without affecting the remote.\n * These changes can later be rolled back or applied to the remote.\n */\n public fork() {\n if (this.isForkedFromRemote) {\n return;\n }\n\n const originalFragment = this.collaboration.fragment;\n\n if (!originalFragment) {\n throw new Error(\"No fragment to fork from\");\n }\n\n const doc = new Y.Doc();\n // Copy the original document to a new Yjs document\n Y.applyUpdate(doc, Y.encodeStateAsUpdate(originalFragment.doc!));\n\n // Find the forked fragment in the new Yjs document\n const forkedFragment = this.findTypeInOtherYdoc(originalFragment, doc);\n\n this.forkedState = {\n originalFragment,\n forkedFragment,\n };\n\n // Need to reset all the yjs plugins\n this.editor._tiptapEditor.unregisterPlugin([\n yCursorPluginKey,\n yUndoPluginKey,\n ySyncPluginKey,\n ]);\n // Register them again, based on the new forked fragment\n this.editor._tiptapEditor.registerPlugin(\n new SyncPlugin(forkedFragment).plugins[0],\n );\n this.editor._tiptapEditor.registerPlugin(new UndoPlugin().plugins[0]);\n // No need to register the cursor plugin again, it's a local fork\n this.emit(\"forked\", true);\n }\n\n /**\n * Resume syncing the Y.js document to the remote\n * If `keepChanges` is true, any changes that have been made to the forked document will be applied to the original document.\n * Otherwise, the original document will be restored and the changes will be discarded.\n */\n public merge({ keepChanges }: { keepChanges: boolean }) {\n if (!this.forkedState) {\n return;\n }\n // Remove the forked fragment's plugins\n this.editor._tiptapEditor.unregisterPlugin(ySyncPluginKey);\n this.editor._tiptapEditor.unregisterPlugin(yUndoPluginKey);\n\n const { originalFragment, forkedFragment } = this.forkedState;\n if (keepChanges) {\n // Apply any changes that have been made to the fork, onto the original doc\n const update = Y.encodeStateAsUpdate(forkedFragment.doc!);\n Y.applyUpdate(originalFragment.doc!, update);\n }\n this.editor.extensions[\"ySyncPlugin\"] = new SyncPlugin(originalFragment);\n this.editor.extensions[\"yCursorPlugin\"] = new CursorPlugin(\n this.collaboration!,\n );\n this.editor.extensions[\"yUndoPlugin\"] = new UndoPlugin();\n // Register the plugins again, based on the original fragment\n this.editor._tiptapEditor.registerPlugin(\n this.editor.extensions[\"ySyncPlugin\"].plugins[0],\n );\n this.editor._tiptapEditor.registerPlugin(\n this.editor.extensions[\"yCursorPlugin\"].plugins[0],\n );\n this.editor._tiptapEditor.registerPlugin(\n this.editor.extensions[\"yUndoPlugin\"].plugins[0],\n );\n // Reset the forked state\n this.forkedState = undefined;\n this.emit(\"forked\", false);\n }\n}\n","import { AnyExtension, Extension, extensions } from \"@tiptap/core\";\nimport { Gapcursor } from \"@tiptap/extension-gapcursor\";\nimport { History } from \"@tiptap/extension-history\";\nimport { Link } from \"@tiptap/extension-link\";\nimport { Text } from \"@tiptap/extension-text\";\nimport { Plugin } from \"prosemirror-state\";\nimport * as Y from \"yjs\";\n\nimport { createDropFileExtension } from \"../api/clipboard/fromClipboard/fileDropExtension.js\";\nimport { createPasteFromClipboardExtension } from \"../api/clipboard/fromClipboard/pasteExtension.js\";\nimport { createCopyToClipboardExtension } from \"../api/clipboard/toClipboard/copyExtension.js\";\nimport type { ThreadStore } from \"../comments/index.js\";\nimport { BackgroundColorExtension } from \"../extensions/BackgroundColor/BackgroundColorExtension.js\";\nimport { CursorPlugin } from \"../extensions/Collaboration/CursorPlugin.js\";\nimport { SyncPlugin } from \"../extensions/Collaboration/SyncPlugin.js\";\nimport { UndoPlugin } from \"../extensions/Collaboration/UndoPlugin.js\";\nimport { CommentMark } from \"../extensions/Comments/CommentMark.js\";\nimport { CommentsPlugin } from \"../extensions/Comments/CommentsPlugin.js\";\nimport { FilePanelProsemirrorPlugin } from \"../extensions/FilePanel/FilePanelPlugin.js\";\nimport { FormattingToolbarProsemirrorPlugin } from \"../extensions/FormattingToolbar/FormattingToolbarPlugin.js\";\nimport { HardBreak } from \"../extensions/HardBreak/HardBreak.js\";\nimport { KeyboardShortcutsExtension } from \"../extensions/KeyboardShortcuts/KeyboardShortcutsExtension.js\";\nimport { LinkToolbarProsemirrorPlugin } from \"../extensions/LinkToolbar/LinkToolbarPlugin.js\";\nimport {\n DEFAULT_LINK_PROTOCOL,\n VALID_LINK_PROTOCOLS,\n} from \"../extensions/LinkToolbar/protocols.js\";\nimport { NodeSelectionKeyboardPlugin } from \"../extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.js\";\nimport { PlaceholderPlugin } from \"../extensions/Placeholder/PlaceholderPlugin.js\";\nimport { PreviousBlockTypePlugin } from \"../extensions/PreviousBlockType/PreviousBlockTypePlugin.js\";\nimport { ShowSelectionPlugin } from \"../extensions/ShowSelection/ShowSelectionPlugin.js\";\nimport { SideMenuProsemirrorPlugin } from \"../extensions/SideMenu/SideMenuPlugin.js\";\nimport { SuggestionMenuProseMirrorPlugin } from \"../extensions/SuggestionMenu/SuggestionPlugin.js\";\nimport {\n SuggestionAddMark,\n SuggestionDeleteMark,\n SuggestionModificationMark,\n} from \"../extensions/Suggestions/SuggestionMarks.js\";\nimport { TableHandlesProsemirrorPlugin } from \"../extensions/TableHandles/TableHandlesPlugin.js\";\nimport { TextAlignmentExtension } from \"../extensions/TextAlignment/TextAlignmentExtension.js\";\nimport { TextColorExtension } from \"../extensions/TextColor/TextColorExtension.js\";\nimport { TrailingNode } from \"../extensions/TrailingNode/TrailingNodeExtension.js\";\nimport UniqueID from \"../extensions/UniqueID/UniqueID.js\";\nimport { BlockContainer, BlockGroup, Doc } from \"../pm-nodes/index.js\";\nimport {\n BlockNoteDOMAttributes,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n StyleSchema,\n StyleSpecs,\n} from \"../schema/index.js\";\nimport type {\n BlockNoteEditor,\n BlockNoteEditorOptions,\n SupportedExtension,\n} from \"./BlockNoteEditor.js\";\nimport { ForkYDocPlugin } from \"../extensions/Collaboration/ForkYDocPlugin.js\";\n\ntype ExtensionOptions<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n> = {\n editor: BlockNoteEditor<BSchema, I, S>;\n domAttributes: Partial<BlockNoteDOMAttributes>;\n blockSpecs: BlockSpecs;\n inlineContentSpecs: InlineContentSpecs;\n styleSpecs: StyleSpecs;\n trailingBlock: boolean | undefined;\n collaboration?: {\n fragment: Y.XmlFragment;\n user: {\n name: string;\n color: string;\n [key: string]: string;\n };\n provider: any;\n renderCursor?: (user: any) => HTMLElement;\n showCursorLabels?: \"always\" | \"activity\";\n };\n disableExtensions: string[] | undefined;\n setIdAttribute?: boolean;\n animations: boolean;\n tableHandles: boolean;\n dropCursor: (opts: any) => Plugin;\n placeholders: Record<\n string | \"default\" | \"emptyDocument\",\n string | undefined\n >;\n tabBehavior?: \"prefer-navigate-ui\" | \"prefer-indent\";\n sideMenuDetection: \"viewport\" | \"editor\";\n comments?: {\n threadStore: ThreadStore;\n };\n pasteHandler: BlockNoteEditorOptions<any, any, any>[\"pasteHandler\"];\n};\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nexport const getBlockNoteExtensions = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n opts: ExtensionOptions<BSchema, I, S>,\n) => {\n const ret: Record<string, SupportedExtension> = {};\n const tiptapExtensions = getTipTapExtensions(opts);\n\n for (const ext of tiptapExtensions) {\n ret[ext.name] = ext;\n }\n\n if (opts.collaboration) {\n ret[\"ySyncPlugin\"] = new SyncPlugin(opts.collaboration.fragment);\n ret[\"yUndoPlugin\"] = new UndoPlugin();\n\n if (opts.collaboration.provider?.awareness) {\n ret[\"yCursorPlugin\"] = new CursorPlugin(opts.collaboration);\n }\n ret[\"forkYDocPlugin\"] = new ForkYDocPlugin({\n editor: opts.editor,\n collaboration: opts.collaboration,\n });\n }\n\n // Note: this is pretty hardcoded and will break when user provides plugins with same keys.\n // Define name on plugins instead and not make this a map?\n ret[\"formattingToolbar\"] = new FormattingToolbarProsemirrorPlugin(\n opts.editor,\n );\n ret[\"linkToolbar\"] = new LinkToolbarProsemirrorPlugin(opts.editor);\n ret[\"sideMenu\"] = new SideMenuProsemirrorPlugin(\n opts.editor,\n opts.sideMenuDetection,\n );\n ret[\"suggestionMenus\"] = new SuggestionMenuProseMirrorPlugin(opts.editor);\n ret[\"filePanel\"] = new FilePanelProsemirrorPlugin(opts.editor as any);\n ret[\"placeholder\"] = new PlaceholderPlugin(opts.editor, opts.placeholders);\n\n if (opts.animations ?? true) {\n ret[\"animations\"] = new PreviousBlockTypePlugin();\n }\n\n if (opts.tableHandles) {\n ret[\"tableHandles\"] = new TableHandlesProsemirrorPlugin(opts.editor as any);\n }\n\n ret[\"nodeSelectionKeyboard\"] = new NodeSelectionKeyboardPlugin();\n\n ret[\"showSelection\"] = new ShowSelectionPlugin(opts.editor);\n\n if (opts.comments) {\n ret[\"comments\"] = new CommentsPlugin(\n opts.editor,\n opts.comments.threadStore,\n CommentMark.name,\n );\n }\n\n const disableExtensions: string[] = opts.disableExtensions || [];\n for (const ext of disableExtensions) {\n delete ret[ext];\n }\n\n return ret;\n};\n\nlet LINKIFY_INITIALIZED = false;\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nconst getTipTapExtensions = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n opts: ExtensionOptions<BSchema, I, S>,\n) => {\n const tiptapExtensions: AnyExtension[] = [\n extensions.ClipboardTextSerializer,\n extensions.Commands,\n extensions.Editable,\n extensions.FocusEvents,\n extensions.Tabindex,\n\n // DevTools,\n Gapcursor,\n\n // DropCursor,\n Extension.create({\n name: \"dropCursor\",\n addProseMirrorPlugins: () => [\n opts.dropCursor({\n width: 5,\n color: \"#ddeeff\",\n editor: opts.editor,\n }),\n ],\n }),\n\n UniqueID.configure({\n // everything from bnBlock group (nodes that represent a BlockNote block should have an id)\n types: [\"blockContainer\", \"columnList\", \"column\"],\n setIdAttribute: opts.setIdAttribute,\n }),\n HardBreak,\n // Comments,\n\n // basics:\n Text,\n\n // marks:\n SuggestionAddMark,\n SuggestionDeleteMark,\n SuggestionModificationMark,\n Link.extend({\n inclusive: false,\n }).configure({\n defaultProtocol: DEFAULT_LINK_PROTOCOL,\n // only call this once if we have multiple editors installed. Or fix https://github.com/ueberdosis/tiptap/issues/5450\n protocols: LINKIFY_INITIALIZED ? [] : VALID_LINK_PROTOCOLS,\n }),\n ...Object.values(opts.styleSpecs).map((styleSpec) => {\n return styleSpec.implementation.mark.configure({\n editor: opts.editor as any,\n });\n }),\n\n TextColorExtension,\n\n BackgroundColorExtension,\n TextAlignmentExtension,\n\n // make sure escape blurs editor, so that we can tab to other elements in the host page (accessibility)\n Extension.create({\n name: \"OverrideEscape\",\n addKeyboardShortcuts() {\n return {\n Escape: () => {\n if (opts.editor.suggestionMenus.shown) {\n // escape is handled by suggestionmenu\n return false;\n }\n return this.editor.commands.blur();\n },\n };\n },\n }),\n\n // nodes\n Doc,\n BlockContainer.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n }),\n KeyboardShortcutsExtension.configure({\n editor: opts.editor,\n tabBehavior: opts.tabBehavior,\n }),\n BlockGroup.configure({\n domAttributes: opts.domAttributes,\n }),\n ...Object.values(opts.inlineContentSpecs)\n .filter((a) => a.config !== \"link\" && a.config !== \"text\")\n .map((inlineContentSpec) => {\n return inlineContentSpec.implementation!.node.configure({\n editor: opts.editor as any,\n });\n }),\n\n ...Object.values(opts.blockSpecs).flatMap((blockSpec) => {\n return [\n // dependent nodes (e.g.: tablecell / row)\n ...(blockSpec.implementation.requiredExtensions || []).map((ext) =>\n ext.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n }),\n ),\n // the actual node itself\n blockSpec.implementation.node.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n }),\n ];\n }),\n createCopyToClipboardExtension(opts.editor),\n createPasteFromClipboardExtension(\n opts.editor,\n opts.pasteHandler ||\n ((context: {\n defaultPasteHandler: (context?: {\n prioritizeMarkdownOverHTML?: boolean;\n plainTextAsMarkdown?: boolean;\n }) => boolean | undefined;\n }) => context.defaultPasteHandler()),\n ),\n createDropFileExtension(opts.editor),\n\n // This needs to be at the bottom of this list, because Key events (such as enter, when selecting a /command),\n // should be handled before Enter handlers in other components like splitListItem\n ...(opts.trailingBlock === undefined || opts.trailingBlock\n ? [TrailingNode]\n : []),\n ...(opts.comments ? [CommentMark] : []),\n ];\n\n LINKIFY_INITIALIZED = true;\n\n if (!opts.collaboration) {\n // disable history extension when collaboration is enabled as y-prosemirror takes care of undo / redo\n tiptapExtensions.push(History);\n }\n\n return tiptapExtensions;\n};\n","import { Fragment, Schema, Slice } from \"@tiptap/pm/model\";\nimport { EditorView } from \"@tiptap/pm/view\";\n\nimport { getBlockInfoFromSelection } from \"../api/getBlockInfoFromPos.js\";\n\n// helper function to remove a child from a fragment\nfunction removeChild(node: Fragment, n: number) {\n const children: any[] = [];\n node.forEach((child, _, i) => {\n if (i !== n) {\n children.push(child);\n }\n });\n return Fragment.from(children);\n}\n\n/**\n * Wrap adjacent tableRow items in a table.\n *\n * This makes sure the content that we paste is always a table (and not a tableRow)\n * A table works better for the remaing paste handling logic, as it's actually a blockContent node\n */\nexport function wrapTableRows(f: Fragment, schema: Schema) {\n const newItems: any[] = [];\n for (let i = 0; i < f.childCount; i++) {\n if (f.child(i).type.name === \"tableRow\") {\n if (\n newItems.length > 0 &&\n newItems[newItems.length - 1].type.name === \"table\"\n ) {\n // append to existing table\n const prevTable = newItems[newItems.length - 1];\n const newTable = prevTable.copy(prevTable.content.addToEnd(f.child(i)));\n newItems[newItems.length - 1] = newTable;\n } else {\n // create new table to wrap tableRow with\n const newTable = schema.nodes.table.createChecked(\n undefined,\n f.child(i),\n );\n newItems.push(newTable);\n }\n } else {\n newItems.push(f.child(i));\n }\n }\n f = Fragment.from(newItems);\n return f;\n}\n\n/**\n * fix for https://github.com/ProseMirror/prosemirror/issues/1430#issuecomment-1822570821\n *\n * This fix wraps pasted ProseMirror nodes in their own `blockContainer` nodes\n * in most cases. This is to ensure that ProseMirror inserts them as separate\n * blocks, which it sometimes doesn't do because it doesn't have enough context\n * about the hierarchy of the pasted nodes. The issue can be seen when pasting\n * e.g. an image or two consecutive paragraphs, where PM tries to nest the\n * pasted block(s) when it shouldn't.\n *\n * However, the fix is not applied in a few cases. See `shouldApplyFix` for\n * which cases are excluded.\n */\nexport function transformPasted(slice: Slice, view: EditorView) {\n let f = Fragment.from(slice.content);\n f = wrapTableRows(f, view.state.schema);\n\n if (!shouldApplyFix(f, view)) {\n // Don't apply the fix.\n return new Slice(f, slice.openStart, slice.openEnd);\n }\n\n for (let i = 0; i < f.childCount; i++) {\n if (f.child(i).type.spec.group === \"blockContent\") {\n const content = [f.child(i)];\n\n // when there is a blockGroup with lists, it should be nested in the new blockcontainer\n // (if we remove this if-block, the nesting bug will be fixed, but lists won't be nested correctly)\n if (\n i + 1 < f.childCount &&\n f.child(i + 1).type.name === \"blockGroup\" // TODO\n ) {\n const nestedChild = f\n .child(i + 1)\n .child(0)\n .child(0);\n\n if (\n nestedChild.type.name === \"bulletListItem\" ||\n nestedChild.type.name === \"numberedListItem\" ||\n nestedChild.type.name === \"checkListItem\"\n ) {\n content.push(f.child(i + 1));\n f = removeChild(f, i + 1);\n }\n }\n const container = view.state.schema.nodes.blockContainer.createChecked(\n undefined,\n content,\n );\n f = f.replaceChild(i, container);\n }\n }\n return new Slice(f, slice.openStart, slice.openEnd);\n}\n\n/**\n * Used in `transformPasted` to check if the fix there should be applied, i.e.\n * if the pasted fragment should be wrapped in a `blockContainer` node. This\n * will explicitly tell ProseMirror to treat it as a separate block.\n */\nfunction shouldApplyFix(fragment: Fragment, view: EditorView) {\n const nodeHasSingleChild = fragment.childCount === 1;\n const nodeHasInlineContent =\n fragment.firstChild?.type.spec.content === \"inline*\";\n const nodeHasTableContent =\n fragment.firstChild?.type.spec.content === \"tableRow+\";\n\n if (nodeHasSingleChild) {\n if (nodeHasInlineContent) {\n // Case when we paste a single node with inline content, e.g. a paragraph\n // or heading. We want to insert the content in-line for better UX instead\n // of a separate block, so we return false.\n return false;\n }\n\n if (nodeHasTableContent) {\n // Not ideal that we check selection here, as `transformPasted` is called\n // for both paste and drop events. Drop events can potentially cause\n // issues as they don't always happen at the current selection.\n const blockInfo = getBlockInfoFromSelection(view.state);\n if (blockInfo.isBlockContainer) {\n const selectedBlockHasTableContent =\n blockInfo.blockContent.node.type.spec.content === \"tableRow+\";\n\n // Case for when we paste a single node with table content, i.e. a\n // table. Normally, we return true as we want to ensure the table is\n // inserted as a separate block. However, if the selection is in an\n // existing table, we return false, as we want the content of the pasted\n // table to be added to the existing one for better UX.\n return !selectedBlockHasTableContent;\n }\n }\n }\n\n return true;\n}\n","import {\n Editor,\n EditorOptions,\n Editor as TiptapEditor,\n createDocument,\n} from \"@tiptap/core\";\n\nimport { Node } from \"@tiptap/pm/model\";\n\nimport { EditorView } from \"@tiptap/pm/view\";\n\nimport { EditorState, Transaction } from \"@tiptap/pm/state\";\nimport { blockToNode } from \"../api/nodeConversions/blockToNode.js\";\nimport { PartialBlock } from \"../blocks/defaultBlocks.js\";\nimport { StyleSchema } from \"../schema/index.js\";\nimport type { BlockNoteEditor } from \"./BlockNoteEditor.js\";\n\nexport type BlockNoteTipTapEditorOptions = Partial<\n Omit<EditorOptions, \"content\">\n> & {\n content: PartialBlock<any, any, any>[];\n};\n\n/**\n * Custom Editor class that extends TiptapEditor and separates\n * the creation of the view from the constructor.\n */\nexport class BlockNoteTipTapEditor extends TiptapEditor {\n private _state: EditorState;\n\n public static create = (\n options: BlockNoteTipTapEditorOptions,\n styleSchema: StyleSchema,\n ) => {\n // because we separate the constructor from the creation of the view,\n // we need to patch setTimeout to prevent this code from having any effect:\n // https://github.com/ueberdosis/tiptap/blob/45bac803283446795ad1b03f43d3746fa54a68ff/packages/core/src/Editor.ts#L117\n const oldSetTimeout = globalThis?.window?.setTimeout;\n if (typeof globalThis?.window?.setTimeout !== \"undefined\") {\n globalThis.window.setTimeout = (() => {\n return 0;\n }) as any;\n }\n try {\n return new BlockNoteTipTapEditor(options, styleSchema);\n } finally {\n if (oldSetTimeout) {\n globalThis.window.setTimeout = oldSetTimeout;\n }\n }\n };\n\n protected constructor(\n options: BlockNoteTipTapEditorOptions,\n styleSchema: StyleSchema,\n ) {\n // possible fix for next.js server side rendering\n // const d = globalThis.document;\n // const w = globalThis.window;\n // if (!globalThis.document) {\n // globalThis.document = {\n // createElement: () => {},\n // };\n // }\n\n // options.injectCSS = false\n\n super({ ...options, content: undefined });\n // try {\n // globalThis.window = w;\n // } catch(e) {}\n // try {\n // globalThis.document = d;\n // } catch(e) {}\n\n // This is a hack to make \"initial content detection\" by y-prosemirror (and also tiptap isEmpty)\n // properly detect whether or not the document has changed.\n // We change the doc.createAndFill function to make sure the initial block id is set, instead of null\n const schema = this.schema;\n let cache: any;\n const oldCreateAndFill = schema.nodes.doc.createAndFill;\n (schema.nodes.doc as any).createAndFill = (...args: any) => {\n if (cache) {\n return cache;\n }\n const ret = oldCreateAndFill.apply(schema.nodes.doc, args);\n\n // create a copy that we can mutate (otherwise, assigning attrs is not safe and corrupts the pm state)\n const jsonNode = JSON.parse(JSON.stringify(ret!.toJSON()));\n jsonNode.content[0].content[0].attrs.id = \"initialBlockId\";\n\n cache = Node.fromJSON(schema, jsonNode);\n return cache;\n };\n\n let doc: Node;\n\n try {\n const pmNodes = options?.content.map((b) =>\n blockToNode(b, this.schema, styleSchema).toJSON(),\n );\n doc = createDocument(\n {\n type: \"doc\",\n content: [\n {\n type: \"blockGroup\",\n content: pmNodes,\n },\n ],\n },\n this.schema,\n this.options.parseOptions,\n );\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\n \"Error creating document from blocks passed as `initialContent`. Caused by exception: \",\n e,\n );\n throw new Error(\n \"Error creating document from blocks passed as `initialContent`:\\n\" +\n +JSON.stringify(options.content),\n );\n }\n\n // Create state immediately, so that it's available independently from the View,\n // the way Prosemirror \"intends it to be\". This also makes sure that we can access\n // the state before the view is created / mounted.\n this._state = EditorState.create({\n doc,\n schema: this.schema,\n // selection: selection || undefined,\n });\n }\n\n get state() {\n if (this.view) {\n this._state = this.view.state;\n }\n return this._state;\n }\n\n dispatch(transaction: Transaction) {\n if (!this.view) {\n // before view has been initialized\n this._state = this.state.apply(transaction);\n this.emit(\"transaction\", {\n editor: this,\n transaction,\n });\n return;\n }\n // This is a verbatim copy of the default dispatch method, but with the following changes:\n // - We provide the appendedTransactions to a new `v3-update` event\n // In the future, we can remove this dispatch method entirely and rely on the new `update` event signature which does what we want by providing the appendedTransactions\n ////////////////////////////////////////////////////////////////////////////////\n // if the editor / the view of the editor was destroyed\n // the transaction should not be dispatched as there is no view anymore.\n if (this.view.isDestroyed) {\n return;\n }\n\n if (this.isCapturingTransaction) {\n // Do the default capture behavior\n (this as any).dispatchTransaction(transaction);\n\n return;\n }\n\n const { state, transactions: appendedTransactions } =\n this.state.applyTransaction(transaction);\n const selectionHasChanged = !this.state.selection.eq(state.selection);\n\n this.emit(\"beforeTransaction\", {\n editor: this,\n transaction,\n nextState: state,\n });\n this.view.updateState(state);\n this.emit(\"transaction\", {\n editor: this,\n transaction,\n });\n\n if (selectionHasChanged) {\n this.emit(\"selectionUpdate\", {\n editor: this,\n transaction,\n });\n }\n\n const focus = transaction.getMeta(\"focus\");\n const blur = transaction.getMeta(\"blur\");\n\n if (focus) {\n this.emit(\"focus\", {\n editor: this,\n event: focus.event,\n transaction,\n });\n }\n\n if (blur) {\n this.emit(\"blur\", {\n editor: this,\n event: blur.event,\n transaction,\n });\n }\n\n if (!transaction.docChanged || transaction.getMeta(\"preventUpdate\")) {\n return;\n }\n\n this.emit(\"update\", {\n editor: this,\n transaction,\n });\n this.emit(\"v3-update\", {\n editor: this,\n transaction,\n appendedTransactions: appendedTransactions.slice(1),\n });\n }\n\n // a helper method that can enable plugins before the view has been initialized\n // currently only used for testing\n forceEnablePlugins() {\n if (this.view) {\n throw new Error(\n \"forcePluginsEnabled called after view has been initialized\",\n );\n }\n this._state = this.state.reconfigure({\n plugins: this.extensionManager.plugins,\n });\n }\n\n /**\n * Replace the default `createView` method with a custom one - which we call on mount\n */\n private createViewAlternative(\n blockNoteEditor: BlockNoteEditor<any, any, any>,\n contentComponent?: any,\n ) {\n (this as any).contentComponent = contentComponent;\n\n const markViews: any = {};\n this.extensionManager.extensions.forEach((extension) => {\n if (extension.type === \"mark\" && extension.config.addMarkView) {\n // Note: migrate to using `addMarkView` from tiptap as soon as this lands\n // (currently tiptap doesn't support markviews)\n markViews[extension.name] =\n extension.config.addMarkView(blockNoteEditor);\n }\n });\n\n this.view = new EditorView(\n { mount: this.options.element as any }, // use mount option so that we reuse the existing element instead of creating a new one\n {\n ...this.options.editorProps,\n // @ts-ignore\n dispatchTransaction: this.dispatch.bind(this),\n state: this.state,\n markViews,\n nodeViews: this.extensionManager.nodeViews,\n },\n );\n\n // `editor.view` is not yet available at this time.\n // Therefore we will add all plugins directly afterwards.\n //\n // To research: this is the default tiptap behavior, but might actually not be necessary\n // it feels like it's a workaround for plugins that don't account for the view not being available yet\n const newState = this.state.reconfigure({\n plugins: this.extensionManager.plugins,\n });\n\n this.view.updateState(newState);\n\n // emit the created event, call here manually because we blocked the default call in the constructor\n // (https://github.com/ueberdosis/tiptap/blob/45bac803283446795ad1b03f43d3746fa54a68ff/packages/core/src/Editor.ts#L117)\n this.commands.focus(\n this.options.autofocus ||\n this.options.element.getAttribute(\"data-bn-autofocus\") === \"true\",\n { scrollIntoView: false },\n );\n this.emit(\"create\", { editor: this });\n this.isInitialized = true;\n }\n\n /**\n * Mounts / unmounts the editor to a dom element\n *\n * @param element DOM element to mount to, ur null / undefined to destroy\n */\n public mount = (\n blockNoteEditor: BlockNoteEditor<any, any, any>,\n element?: HTMLElement | null,\n contentComponent?: any,\n ) => {\n if (!element) {\n this.destroy();\n } else {\n this.options.element = element;\n this.createViewAlternative(blockNoteEditor, contentComponent);\n }\n };\n}\n\n(BlockNoteTipTapEditor.prototype as any).createView = function () {\n // no-op\n // Disable default call to `createView` in the Editor constructor.\n // We should call `createView` manually only when a DOM element is available\n\n // additional fix because onPaste and onDrop depend on installing plugins in constructor which we don't support\n // (note: can probably be removed after tiptap upgrade fixed in 2.8.0)\n this.options.onPaste = this.options.onDrop = undefined;\n};\n\ndeclare module \"@tiptap/core\" {\n interface EditorEvents {\n /**\n * This is a custom event that will be emitted in Tiptap V3.\n * We use it to provide the appendedTransactions, until Tiptap V3 is released.\n */\n \"v3-update\": {\n editor: Editor;\n transaction: Transaction;\n appendedTransactions: Transaction[];\n };\n }\n}\n","import {\n AnyExtension,\n EditorOptions,\n Extension,\n getSchema,\n isNodeSelection,\n Mark,\n posToDOMRect,\n Node as TipTapNode,\n} from \"@tiptap/core\";\nimport { Node, Schema } from \"prosemirror-model\";\n// import \"./blocknote.css\";\nimport * as Y from \"yjs\";\nimport { insertBlocks } from \"../api/blockManipulation/commands/insertBlocks/insertBlocks.js\";\nimport {\n moveBlocksDown,\n moveBlocksUp,\n} from \"../api/blockManipulation/commands/moveBlocks/moveBlocks.js\";\nimport {\n canNestBlock,\n canUnnestBlock,\n nestBlock,\n unnestBlock,\n} from \"../api/blockManipulation/commands/nestBlock/nestBlock.js\";\nimport { removeAndInsertBlocks } from \"../api/blockManipulation/commands/replaceBlocks/replaceBlocks.js\";\nimport { updateBlock } from \"../api/blockManipulation/commands/updateBlock/updateBlock.js\";\nimport {\n getBlock,\n getNextBlock,\n getParentBlock,\n getPrevBlock,\n} from \"../api/blockManipulation/getBlock/getBlock.js\";\nimport { insertContentAt } from \"../api/blockManipulation/insertContentAt.js\";\nimport {\n getSelection,\n getSelectionCutBlocks,\n setSelection,\n} from \"../api/blockManipulation/selections/selection.js\";\nimport {\n getTextCursorPosition,\n setTextCursorPosition,\n} from \"../api/blockManipulation/selections/textCursorPosition.js\";\nimport { createExternalHTMLExporter } from \"../api/exporters/html/externalHTMLExporter.js\";\nimport { blocksToMarkdown } from \"../api/exporters/markdown/markdownExporter.js\";\nimport { HTMLToBlocks } from \"../api/parsers/html/parseHTML.js\";\nimport {\n markdownToBlocks,\n markdownToHTML,\n} from \"../api/parsers/markdown/parseMarkdown.js\";\nimport {\n Block,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n DefaultStyleSchema,\n PartialBlock,\n} from \"../blocks/defaultBlocks.js\";\nimport type { CommentsPlugin } from \"../extensions/Comments/CommentsPlugin.js\";\nimport { FilePanelProsemirrorPlugin } from \"../extensions/FilePanel/FilePanelPlugin.js\";\nimport { FormattingToolbarProsemirrorPlugin } from \"../extensions/FormattingToolbar/FormattingToolbarPlugin.js\";\nimport { LinkToolbarProsemirrorPlugin } from \"../extensions/LinkToolbar/LinkToolbarPlugin.js\";\nimport { ShowSelectionPlugin } from \"../extensions/ShowSelection/ShowSelectionPlugin.js\";\nimport { SideMenuProsemirrorPlugin } from \"../extensions/SideMenu/SideMenuPlugin.js\";\nimport { SuggestionMenuProseMirrorPlugin } from \"../extensions/SuggestionMenu/SuggestionPlugin.js\";\nimport { TableHandlesProsemirrorPlugin } from \"../extensions/TableHandles/TableHandlesPlugin.js\";\nimport { UniqueID } from \"../extensions/UniqueID/UniqueID.js\";\nimport {\n BlockIdentifier,\n BlockNoteDOMAttributes,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n PartialInlineContent,\n Styles,\n StyleSchema,\n StyleSpecs,\n} from \"../schema/index.js\";\nimport { mergeCSSClasses } from \"../util/browser.js\";\nimport { NoInfer, UnreachableCaseError } from \"../util/typescript.js\";\n\nimport { getBlockNoteExtensions } from \"./BlockNoteExtensions.js\";\nimport { TextCursorPosition } from \"./cursorPositionTypes.js\";\n\nimport { Selection } from \"./selectionTypes.js\";\nimport { transformPasted } from \"./transformPasted.js\";\n\nimport { checkDefaultBlockTypeInSchema } from \"../blocks/defaultBlockTypeGuards.js\";\nimport { BlockNoteSchema } from \"./BlockNoteSchema.js\";\nimport {\n BlockNoteTipTapEditor,\n BlockNoteTipTapEditorOptions,\n} from \"./BlockNoteTipTapEditor.js\";\n\nimport { Dictionary } from \"../i18n/dictionary.js\";\nimport { en } from \"../i18n/locales/index.js\";\n\nimport { redo, undo } from \"@tiptap/pm/history\";\nimport {\n TextSelection,\n type Command,\n type Plugin,\n type Transaction,\n} from \"@tiptap/pm/state\";\nimport { dropCursor } from \"prosemirror-dropcursor\";\nimport { EditorView } from \"prosemirror-view\";\nimport { redoCommand, undoCommand, ySyncPluginKey } from \"y-prosemirror\";\nimport { createInternalHTMLSerializer } from \"../api/exporters/html/internalHTMLSerializer.js\";\nimport { inlineContentToNodes } from \"../api/nodeConversions/blockToNode.js\";\nimport { docToBlocks } from \"../api/nodeConversions/nodeToBlock.js\";\nimport {\n BlocksChanged,\n getBlocksChangedByTransaction,\n} from \"../api/nodeUtil.js\";\nimport { nestedListsToBlockNoteStructure } from \"../api/parsers/html/util/nestedLists.js\";\nimport { CodeBlockOptions } from \"../blocks/CodeBlockContent/CodeBlockContent.js\";\nimport type { ThreadStore, User } from \"../comments/index.js\";\nimport type { CursorPlugin } from \"../extensions/Collaboration/CursorPlugin.js\";\nimport type { ForkYDocPlugin } from \"../extensions/Collaboration/ForkYDocPlugin.js\";\nimport { EventEmitter } from \"../util/EventEmitter.js\";\nimport { BlockNoteExtension } from \"./BlockNoteExtension.js\";\n\nimport \"../style.css\";\n\n/**\n * A factory function that returns a BlockNoteExtension\n * This is useful so we can create extensions that require an editor instance\n * in the constructor\n */\nexport type BlockNoteExtensionFactory = (\n editor: BlockNoteEditor<any, any, any>,\n) => BlockNoteExtension;\n\n/**\n * We support Tiptap extensions and BlockNoteExtension based extensions\n */\nexport type SupportedExtension = AnyExtension | BlockNoteExtension;\n\nexport type BlockCache<\n BSchema extends BlockSchema = any,\n ISchema extends InlineContentSchema = any,\n SSchema extends StyleSchema = any,\n> = WeakMap<Node, Block<BSchema, ISchema, SSchema>>;\n\nexport type BlockNoteEditorOptions<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema,\n> = {\n /**\n * Whether changes to blocks (like indentation, creating lists, changing headings) should be animated or not. Defaults to `true`.\n *\n * @default true\n */\n animations?: boolean;\n\n /**\n * When enabled, allows for collaboration between multiple users.\n */\n collaboration: {\n /**\n * The Yjs XML fragment that's used for collaboration.\n */\n fragment: Y.XmlFragment;\n /**\n * The user info for the current user that's shown to other collaborators.\n */\n user: {\n name: string;\n color: string;\n };\n /**\n * A Yjs provider (used for awareness / cursor information)\n */\n provider: any;\n /**\n * Optional function to customize how cursors of users are rendered\n */\n renderCursor?: (user: any) => HTMLElement;\n /**\n * Optional flag to set when the user label should be shown with the default\n * collaboration cursor. Setting to \"always\" will always show the label,\n * while \"activity\" will only show the label when the user moves the cursor\n * or types. Defaults to \"activity\".\n */\n showCursorLabels?: \"always\" | \"activity\";\n };\n\n /**\n * Options for code blocks.\n */\n codeBlock?: CodeBlockOptions;\n\n comments: {\n threadStore: ThreadStore;\n };\n\n /**\n * Use default BlockNote font and reset the styles of <p> <li> <h1> elements etc., that are used in BlockNote.\n *\n * @default true\n */\n defaultStyles: boolean;\n\n /**\n * A dictionary object containing translations for the editor.\n */\n dictionary?: Dictionary & Record<string, any>;\n\n /**\n * Disable internal extensions (based on keys / extension name)\n */\n disableExtensions: string[];\n\n /**\n * An object containing attributes that should be added to HTML elements of the editor.\n *\n * @example { editor: { class: \"my-editor-class\" } }\n */\n domAttributes: Partial<BlockNoteDOMAttributes>;\n\n dropCursor?: (opts: {\n editor: BlockNoteEditor<\n NoInfer<BSchema>,\n NoInfer<ISchema>,\n NoInfer<SSchema>\n >;\n color?: string | false;\n width?: number;\n class?: string;\n }) => Plugin;\n\n /**\n * The content that should be in the editor when it's created, represented as an array of partial block objects.\n */\n initialContent: PartialBlock<\n NoInfer<BSchema>,\n NoInfer<ISchema>,\n NoInfer<SSchema>\n >[];\n\n /**\n * @deprecated, provide placeholders via dictionary instead\n */\n placeholders: Record<\n string | \"default\" | \"emptyDocument\",\n string | undefined\n >;\n\n /**\n * Custom paste handler that can be used to override the default paste behavior.\n * @returns The function should return `true` if the paste event was handled, otherwise it should return `false` if it should be canceled or `undefined` if it should be handled by another handler.\n *\n * @example\n * ```ts\n * pasteHandler: ({ defaultPasteHandler }) => {\n * return defaultPasteHandler({ pasteBehavior: \"prefer-html\" });\n * }\n * ```\n */\n pasteHandler?: (context: {\n event: ClipboardEvent;\n editor: BlockNoteEditor<BSchema, ISchema, SSchema>;\n /**\n * The default paste handler\n * @param context The context object\n * @returns Whether the paste event was handled or not\n */\n defaultPasteHandler: (context?: {\n /**\n * Whether to prioritize Markdown content in `text/plain` over `text/html` when pasting from the clipboard.\n * @default true\n */\n prioritizeMarkdownOverHTML?: boolean;\n /**\n * Whether to parse `text/plain` content from the clipboard as Markdown content.\n * @default true\n */\n plainTextAsMarkdown?: boolean;\n }) => boolean | undefined;\n }) => boolean | undefined;\n\n /**\n * Resolve a URL of a file block to one that can be displayed or downloaded. This can be used for creating authenticated URL or\n * implementing custom protocols / schemes\n * @returns The URL that's\n */\n resolveFileUrl: (url: string) => Promise<string>;\n\n resolveUsers: (userIds: string[]) => Promise<User[]>;\n\n schema: BlockNoteSchema<BSchema, ISchema, SSchema>;\n\n /**\n * A flag indicating whether to set an HTML ID for every block\n *\n * When set to `true`, on each block an id attribute will be set with the block id\n * Otherwise, the HTML ID attribute will not be set.\n *\n * (note that the id is always set on the `data-id` attribute)\n */\n setIdAttribute?: boolean;\n\n /**\n * The detection mode for showing the side menu - \"viewport\" always shows the\n * side menu for the block next to the mouse cursor, while \"editor\" only shows\n * it when hovering the editor or the side menu itself.\n *\n * @default \"viewport\"\n */\n sideMenuDetection: \"viewport\" | \"editor\";\n\n /**\n Select desired behavior when pressing `Tab` (or `Shift-Tab`). Specifically,\n what should happen when a user has selected multiple blocks while a toolbar\n is open:\n - `\"prefer-navigate-ui\"`: Change focus to the toolbar. The user needs to\n first press `Escape` to close the toolbar, and can then indent multiple\n blocks. Better for keyboard accessibility.\n - `\"prefer-indent\"`: Regardless of whether toolbars are open, indent the\n selection of blocks. In this case, it's not possible to navigate toolbars\n with the keyboard.\n\n @default \"prefer-navigate-ui\"\n */\n tabBehavior: \"prefer-navigate-ui\" | \"prefer-indent\";\n\n /**\n * Allows enabling / disabling features of tables.\n */\n tables?: {\n /**\n * Whether to allow splitting and merging cells within a table.\n *\n * @default false\n */\n splitCells?: boolean;\n /**\n * Whether to allow changing the background color of cells.\n *\n * @default false\n */\n cellBackgroundColor?: boolean;\n /**\n * Whether to allow changing the text color of cells.\n *\n * @default false\n */\n cellTextColor?: boolean;\n /**\n * Whether to allow changing cells into headers.\n *\n * @default false\n */\n headers?: boolean;\n };\n\n trailingBlock?: boolean;\n\n /**\n * The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).\n * This method should set when creating the editor as this is application-specific.\n *\n * `undefined` means the application doesn't support file uploads.\n *\n * @param file The file that should be uploaded.\n * @returns The URL of the uploaded file OR an object containing props that should be set on the file block (such as an id)\n */\n uploadFile: (\n file: File,\n blockId?: string,\n ) => Promise<string | Record<string, any>>;\n\n /**\n * additional tiptap options, undocumented\n */\n _tiptapOptions: Partial<EditorOptions>;\n\n /**\n * (experimental) add extra extensions to the editor\n *\n * @deprecated, should use `extensions` instead\n */\n _extensions: Record<\n string,\n | { plugin: Plugin; priority?: number }\n | ((editor: BlockNoteEditor<any, any, any>) => {\n plugin: Plugin;\n priority?: number;\n })\n >;\n\n /**\n * Register\n */\n extensions: Array<BlockNoteExtension | BlockNoteExtensionFactory>;\n\n /**\n * Boolean indicating whether the editor is in headless mode.\n * Headless mode means we can use features like importing / exporting blocks,\n * but there's no underlying editor (UI) instantiated.\n *\n * You probably don't need to set this manually, but use the `server-util` package instead that uses this option internally\n */\n _headless: boolean;\n};\n\nconst blockNoteTipTapOptions = {\n enableInputRules: true,\n enablePasteRules: true,\n enableCoreExtensions: false,\n};\n\nexport class BlockNoteEditor<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema,\n> extends EventEmitter<{\n create: void;\n}> {\n /**\n * The underlying prosemirror schema\n */\n public readonly pmSchema: Schema;\n\n /**\n * extensions that are added to the editor, can be tiptap extensions or prosemirror plugins\n */\n public extensions: Record<string, SupportedExtension> = {};\n\n /**\n * Boolean indicating whether the editor is in headless mode.\n * Headless mode means we can use features like importing / exporting blocks,\n * but there's no underlying editor (UI) instantiated.\n *\n * You probably don't need to set this manually, but use the `server-util` package instead that uses this option internally\n */\n public readonly headless: boolean = false;\n\n public readonly _tiptapEditor: Omit<BlockNoteTipTapEditor, \"view\"> & {\n view: EditorView | undefined;\n contentComponent: any;\n } = undefined as any; // TODO: Type should actually reflect that it can be `undefined` in headless mode\n\n /**\n * Used by React to store a reference to an `ElementRenderer` helper utility to make sure we can render React elements\n * in the correct context (used by `ReactRenderUtil`)\n */\n public elementRenderer: ((node: any, container: HTMLElement) => void) | null =\n null;\n\n /**\n * Cache of all blocks. This makes sure we don't have to \"recompute\" blocks if underlying Prosemirror Nodes haven't changed.\n * This is especially useful when we want to keep track of the same block across multiple operations,\n * with this cache, blocks stay the same object reference (referential equality with ===).\n */\n public blockCache: BlockCache = new WeakMap();\n\n /**\n * The dictionary contains translations for the editor.\n */\n public readonly dictionary: Dictionary & Record<string, any>;\n\n /**\n * The schema of the editor. The schema defines which Blocks, InlineContent, and Styles are available in the editor.\n */\n public readonly schema: BlockNoteSchema<BSchema, ISchema, SSchema>;\n\n public readonly blockImplementations: BlockSpecs;\n public readonly inlineContentImplementations: InlineContentSpecs;\n public readonly styleImplementations: StyleSpecs;\n\n public readonly formattingToolbar: FormattingToolbarProsemirrorPlugin;\n public readonly linkToolbar: LinkToolbarProsemirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly sideMenu: SideMenuProsemirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly suggestionMenus: SuggestionMenuProseMirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly filePanel?: FilePanelProsemirrorPlugin<ISchema, SSchema>;\n public readonly tableHandles?: TableHandlesProsemirrorPlugin<\n ISchema,\n SSchema\n >;\n public readonly comments?: CommentsPlugin;\n\n private readonly showSelectionPlugin: ShowSelectionPlugin;\n\n /**\n * The plugin for forking a document, only defined if in collaboration mode\n */\n public readonly forkYDocPlugin?: ForkYDocPlugin;\n /**\n * The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).\n * This method should set when creating the editor as this is application-specific.\n *\n * `undefined` means the application doesn't support file uploads.\n *\n * @param file The file that should be uploaded.\n * @returns The URL of the uploaded file OR an object containing props that should be set on the file block (such as an id)\n */\n public readonly uploadFile:\n | ((file: File, blockId?: string) => Promise<string | Record<string, any>>)\n | undefined;\n\n private onUploadStartCallbacks: ((blockId?: string) => void)[] = [];\n private onUploadEndCallbacks: ((blockId?: string) => void)[] = [];\n\n public readonly resolveFileUrl?: (url: string) => Promise<string>;\n public readonly resolveUsers?: (userIds: string[]) => Promise<User[]>;\n /**\n * Editor settings\n */\n public readonly settings: {\n tables: {\n splitCells: boolean;\n cellBackgroundColor: boolean;\n cellTextColor: boolean;\n headers: boolean;\n };\n codeBlock: CodeBlockOptions;\n };\n\n public static create<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema,\n >(options: Partial<BlockNoteEditorOptions<BSchema, ISchema, SSchema>> = {}) {\n return new BlockNoteEditor<BSchema, ISchema, SSchema>(options);\n }\n\n protected constructor(\n protected readonly options: Partial<BlockNoteEditorOptions<any, any, any>>,\n ) {\n super();\n const anyOpts = options as any;\n if (anyOpts.onEditorContentChange) {\n throw new Error(\n \"onEditorContentChange initialization option is deprecated, use <BlockNoteView onChange={...} />, the useEditorChange(...) hook, or editor.onChange(...)\",\n );\n }\n\n if (anyOpts.onTextCursorPositionChange) {\n throw new Error(\n \"onTextCursorPositionChange initialization option is deprecated, use <BlockNoteView onSelectionChange={...} />, the useEditorSelectionChange(...) hook, or editor.onSelectionChange(...)\",\n );\n }\n\n if (anyOpts.onEditorReady) {\n throw new Error(\n \"onEditorReady is deprecated. Editor is immediately ready for use after creation.\",\n );\n }\n\n if (anyOpts.editable) {\n throw new Error(\n \"editable initialization option is deprecated, use <BlockNoteView editable={true/false} />, or alternatively editor.isEditable = true/false\",\n );\n }\n\n this.dictionary = options.dictionary || en;\n this.settings = {\n tables: {\n splitCells: options?.tables?.splitCells ?? false,\n cellBackgroundColor: options?.tables?.cellBackgroundColor ?? false,\n cellTextColor: options?.tables?.cellTextColor ?? false,\n headers: options?.tables?.headers ?? false,\n },\n codeBlock: {\n indentLineWithTab: options?.codeBlock?.indentLineWithTab ?? true,\n defaultLanguage: options?.codeBlock?.defaultLanguage ?? \"text\",\n supportedLanguages: options?.codeBlock?.supportedLanguages ?? {},\n createHighlighter: options?.codeBlock?.createHighlighter ?? undefined,\n },\n };\n\n // apply defaults\n const newOptions = {\n defaultStyles: true,\n schema: options.schema || BlockNoteSchema.create(),\n _headless: false,\n ...options,\n placeholders: {\n ...this.dictionary.placeholders,\n ...options.placeholders,\n },\n };\n\n if (newOptions.comments && !newOptions.resolveUsers) {\n throw new Error(\"resolveUsers is required when using comments\");\n }\n\n this.resolveUsers = newOptions.resolveUsers;\n\n // @ts-ignore\n this.schema = newOptions.schema;\n this.blockImplementations = newOptions.schema.blockSpecs;\n this.inlineContentImplementations = newOptions.schema.inlineContentSpecs;\n this.styleImplementations = newOptions.schema.styleSpecs;\n\n this.extensions = getBlockNoteExtensions({\n editor: this,\n domAttributes: newOptions.domAttributes || {},\n blockSpecs: this.schema.blockSpecs,\n styleSpecs: this.schema.styleSpecs,\n inlineContentSpecs: this.schema.inlineContentSpecs,\n collaboration: newOptions.collaboration,\n trailingBlock: newOptions.trailingBlock,\n disableExtensions: newOptions.disableExtensions,\n setIdAttribute: newOptions.setIdAttribute,\n animations: newOptions.animations ?? true,\n tableHandles: checkDefaultBlockTypeInSchema(\"table\", this),\n dropCursor: this.options.dropCursor ?? dropCursor,\n placeholders: newOptions.placeholders,\n tabBehavior: newOptions.tabBehavior,\n sideMenuDetection: newOptions.sideMenuDetection || \"viewport\",\n comments: newOptions.comments,\n pasteHandler: newOptions.pasteHandler,\n });\n\n // add extensions from _tiptapOptions\n (newOptions._tiptapOptions?.extensions || []).forEach((ext) => {\n this.extensions[ext.name] = ext;\n });\n\n // add extensions from options\n for (let ext of newOptions.extensions || []) {\n if (typeof ext === \"function\") {\n // factory\n ext = ext(this);\n }\n const key = (ext.constructor as any).key();\n if (!key) {\n throw new Error(\n `Extension ${ext.constructor.name} does not have a key method`,\n );\n }\n if (this.extensions[key]) {\n throw new Error(\n `Extension ${ext.constructor.name} already exists with key ${key}`,\n );\n }\n this.extensions[key] = ext;\n }\n\n // (when passed in via the deprecated `_extensions` option)\n Object.entries(newOptions._extensions || {}).forEach(([key, ext]) => {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const editor = this;\n\n const instance = typeof ext === \"function\" ? ext(editor) : ext;\n if (!(\"plugin\" in instance)) {\n // Assume it is an Extension/Mark/Node\n this.extensions[key] = instance;\n return;\n }\n\n this.extensions[key] = new (class extends BlockNoteExtension {\n public static key() {\n return key;\n }\n constructor() {\n super();\n this.addProsemirrorPlugin(instance.plugin);\n }\n public get priority() {\n return instance.priority;\n }\n })();\n });\n\n this.formattingToolbar = this.extensions[\"formattingToolbar\"] as any;\n this.linkToolbar = this.extensions[\"linkToolbar\"] as any;\n this.sideMenu = this.extensions[\"sideMenu\"] as any;\n this.suggestionMenus = this.extensions[\"suggestionMenus\"] as any;\n this.filePanel = this.extensions[\"filePanel\"] as any;\n this.tableHandles = this.extensions[\"tableHandles\"] as any;\n this.comments = this.extensions[\"comments\"] as any;\n this.showSelectionPlugin = this.extensions[\"showSelection\"] as any;\n this.forkYDocPlugin = this.extensions[\"forkYDocPlugin\"] as any;\n\n if (newOptions.uploadFile) {\n const uploadFile = newOptions.uploadFile;\n this.uploadFile = async (file, blockId) => {\n this.onUploadStartCallbacks.forEach((callback) =>\n callback.apply(this, [blockId]),\n );\n try {\n return await uploadFile(file, blockId);\n } finally {\n this.onUploadEndCallbacks.forEach((callback) =>\n callback.apply(this, [blockId]),\n );\n }\n };\n }\n\n this.resolveFileUrl = newOptions.resolveFileUrl;\n this.headless = newOptions._headless;\n\n const collaborationEnabled =\n \"ySyncPlugin\" in this.extensions ||\n \"liveblocksExtension\" in this.extensions;\n\n if (collaborationEnabled && newOptions.initialContent) {\n // eslint-disable-next-line no-console\n console.warn(\n \"When using Collaboration, initialContent might cause conflicts, because changes should come from the collaboration provider\",\n );\n }\n\n const initialContent =\n newOptions.initialContent ||\n (collaborationEnabled\n ? [\n {\n type: \"paragraph\",\n id: \"initialBlockId\",\n },\n ]\n : [\n {\n type: \"paragraph\",\n id: UniqueID.options.generateID(),\n },\n ]);\n\n if (!Array.isArray(initialContent) || initialContent.length === 0) {\n throw new Error(\n \"initialContent must be a non-empty array of blocks, received: \" +\n initialContent,\n );\n }\n\n const tiptapExtensions = [\n ...Object.entries(this.extensions).map(([key, ext]) => {\n if (\n ext instanceof Extension ||\n ext instanceof TipTapNode ||\n ext instanceof Mark\n ) {\n // tiptap extension\n return ext;\n }\n\n if (ext instanceof BlockNoteExtension && !ext.plugins.length) {\n return undefined;\n }\n\n // \"blocknote\" extensions (prosemirror plugins)\n return Extension.create({\n name: key,\n priority: ext.priority,\n addProseMirrorPlugins: () => ext.plugins,\n });\n }),\n ].filter((ext): ext is Extension => ext !== undefined);\n\n const tiptapOptions: BlockNoteTipTapEditorOptions = {\n ...blockNoteTipTapOptions,\n ...newOptions._tiptapOptions,\n content: initialContent,\n extensions: tiptapExtensions,\n editorProps: {\n ...newOptions._tiptapOptions?.editorProps,\n attributes: {\n // As of TipTap v2.5.0 the tabIndex is removed when the editor is not\n // editable, so you can't focus it. We want to revert this as we have\n // UI behaviour that relies on it.\n tabIndex: \"0\",\n ...newOptions._tiptapOptions?.editorProps?.attributes,\n ...newOptions.domAttributes?.editor,\n class: mergeCSSClasses(\n \"bn-editor\",\n newOptions.defaultStyles ? \"bn-default-styles\" : \"\",\n newOptions.domAttributes?.editor?.class || \"\",\n ),\n },\n transformPasted,\n },\n };\n\n if (!this.headless) {\n this._tiptapEditor = BlockNoteTipTapEditor.create(\n tiptapOptions,\n this.schema.styleSchema,\n ) as BlockNoteTipTapEditor & {\n view: any;\n contentComponent: any;\n };\n this.pmSchema = this._tiptapEditor.schema;\n } else {\n // In headless mode, we don't instantiate an underlying TipTap editor,\n // but we still need the schema\n this.pmSchema = getSchema(tiptapOptions.extensions!);\n }\n this.pmSchema.cached.blockNoteEditor = this;\n this.emit(\"create\");\n }\n\n /**\n * Stores the currently active transaction, which is the accumulated transaction from all {@link dispatch} calls during a {@link transact} calls\n */\n private activeTransaction: Transaction | null = null;\n\n /**\n * Execute a prosemirror command. This is mostly for backwards compatibility with older code.\n *\n * @note You should prefer the {@link transact} method when possible, as it will automatically handle the dispatching of the transaction and work across blocknote transactions.\n *\n * @example\n * ```ts\n * editor.exec((state, dispatch, view) => {\n * dispatch(state.tr.insertText(\"Hello, world!\"));\n * });\n * ```\n */\n public exec(command: Command) {\n if (this.activeTransaction) {\n throw new Error(\n \"`exec` should not be called within a `transact` call, move the `exec` call outside of the `transact` call\",\n );\n }\n const state = this._tiptapEditor.state;\n const view = this._tiptapEditor.view;\n const dispatch = (tr: Transaction) => this._tiptapEditor.dispatch(tr);\n\n return command(state, dispatch, view);\n }\n\n /**\n * Check if a command can be executed. A command should return `false` if it is not valid in the current state.\n *\n * @example\n * ```ts\n * if (editor.canExec(command)) {\n * // show button\n * } else {\n * // hide button\n * }\n * ```\n */\n public canExec(command: Command): boolean {\n if (this.activeTransaction) {\n throw new Error(\n \"`canExec` should not be called within a `transact` call, move the `canExec` call outside of the `transact` call\",\n );\n }\n const state = this._tiptapEditor.state;\n const view = this._tiptapEditor.view;\n\n return command(state, undefined, view);\n }\n\n /**\n * Execute a function within a \"blocknote transaction\".\n * All changes to the editor within the transaction will be grouped together, so that\n * we can dispatch them as a single operation (thus creating only a single undo step)\n *\n * @note There is no need to dispatch the transaction, as it will be automatically dispatched when the callback is complete.\n *\n * @example\n * ```ts\n * // All changes to the editor will be grouped together\n * editor.transact((tr) => {\n * tr.insertText(\"Hello, world!\");\n * // These two operations will be grouped together in a single undo step\n * editor.transact((tr) => {\n * tr.insertText(\"Hello, world!\");\n * });\n * });\n * ```\n */\n public transact<T>(\n callback: (\n /**\n * The current active transaction, this will automatically be dispatched to the editor when the callback is complete\n * If another `transact` call is made within the callback, it will be passed the same transaction as the parent call.\n */\n tr: Transaction,\n ) => T,\n ): T {\n if (this.activeTransaction) {\n // Already in a transaction, so we can just callback immediately\n return callback(this.activeTransaction);\n }\n\n try {\n // Enter transaction mode, by setting a starting transaction\n this.activeTransaction = this._tiptapEditor.state.tr;\n\n // Capture all dispatch'd transactions\n const result = callback(this.activeTransaction);\n\n // Any transactions captured by the `dispatch` call will be stored in `this.activeTransaction`\n const activeTr = this.activeTransaction;\n\n this.activeTransaction = null;\n if (\n activeTr &&\n // Only dispatch if the transaction was actually modified in some way\n (activeTr.docChanged ||\n activeTr.selectionSet ||\n activeTr.scrolledIntoView ||\n activeTr.storedMarksSet ||\n !activeTr.isGeneric)\n ) {\n // Dispatch the transaction if it was modified\n this._tiptapEditor.dispatch(activeTr);\n }\n\n return result;\n } finally {\n // We wrap this in a finally block to ensure we don't disable future transactions just because of an error in the callback\n this.activeTransaction = null;\n }\n }\n\n // TO DISCUSS\n /**\n * Shorthand to get a typed extension from the editor, by\n * just passing in the extension class.\n *\n * @param ext - The extension class to get\n * @param key - optional, the key of the extension in the extensions object (defaults to the extension name)\n * @returns The extension instance\n */\n public extension<T extends BlockNoteExtension>(\n ext: { new (...args: any[]): T } & typeof BlockNoteExtension,\n key = ext.key(),\n ): T {\n const extension = this.extensions[key] as T;\n if (!extension) {\n throw new Error(`Extension ${key} not found`);\n }\n return extension;\n }\n\n /**\n * Mount the editor to a parent DOM element. Call mount(undefined) to clean up\n *\n * @warning Not needed to call manually when using React, use BlockNoteView to take care of mounting\n */\n public mount = (\n parentElement?: HTMLElement | null,\n contentComponent?: any,\n ) => {\n this._tiptapEditor.mount(this, parentElement, contentComponent);\n };\n\n /**\n * Get the underlying prosemirror state\n * @note Prefer using `editor.transact` to read the current editor state, as that will ensure the state is up to date\n * @see https://prosemirror.net/docs/ref/#state.EditorState\n */\n public get prosemirrorState() {\n if (this.activeTransaction) {\n throw new Error(\n \"`prosemirrorState` should not be called within a `transact` call, move the `prosemirrorState` call outside of the `transact` call or use `editor.transact` to read the current editor state\",\n );\n }\n return this._tiptapEditor.state;\n }\n\n /**\n * Get the underlying prosemirror view\n * @see https://prosemirror.net/docs/ref/#view.EditorView\n */\n public get prosemirrorView() {\n return this._tiptapEditor.view;\n }\n\n public get domElement() {\n return this.prosemirrorView?.dom as HTMLDivElement | undefined;\n }\n\n public isFocused() {\n return this.prosemirrorView?.hasFocus() || false;\n }\n\n public focus() {\n this.prosemirrorView?.focus();\n }\n\n public onUploadStart(callback: (blockId?: string) => void) {\n this.onUploadStartCallbacks.push(callback);\n\n return () => {\n const index = this.onUploadStartCallbacks.indexOf(callback);\n if (index > -1) {\n this.onUploadStartCallbacks.splice(index, 1);\n }\n };\n }\n\n public onUploadEnd(callback: (blockId?: string) => void) {\n this.onUploadEndCallbacks.push(callback);\n\n return () => {\n const index = this.onUploadEndCallbacks.indexOf(callback);\n if (index > -1) {\n this.onUploadEndCallbacks.splice(index, 1);\n }\n };\n }\n\n /**\n * @deprecated, use `editor.document` instead\n */\n public get topLevelBlocks(): Block<BSchema, ISchema, SSchema>[] {\n return this.document;\n }\n\n /**\n * Gets a snapshot of all top-level (non-nested) blocks in the editor.\n * @returns A snapshot of all top-level (non-nested) blocks in the editor.\n */\n public get document(): Block<BSchema, ISchema, SSchema>[] {\n return this.transact((tr) => {\n return docToBlocks(tr.doc, this.pmSchema);\n });\n }\n\n /**\n * Gets a snapshot of an existing block from the editor.\n * @param blockIdentifier The identifier of an existing block that should be\n * retrieved.\n * @returns The block that matches the identifier, or `undefined` if no\n * matching block was found.\n */\n public getBlock(\n blockIdentifier: BlockIdentifier,\n ): Block<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getBlock(tr.doc, blockIdentifier));\n }\n\n /**\n * Gets a snapshot of the previous sibling of an existing block from the\n * editor.\n * @param blockIdentifier The identifier of an existing block for which the\n * previous sibling should be retrieved.\n * @returns The previous sibling of the block that matches the identifier.\n * `undefined` if no matching block was found, or it's the first child/block\n * in the document.\n */\n public getPrevBlock(\n blockIdentifier: BlockIdentifier,\n ): Block<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getPrevBlock(tr.doc, blockIdentifier));\n }\n\n /**\n * Gets a snapshot of the next sibling of an existing block from the editor.\n * @param blockIdentifier The identifier of an existing block for which the\n * next sibling should be retrieved.\n * @returns The next sibling of the block that matches the identifier.\n * `undefined` if no matching block was found, or it's the last child/block in\n * the document.\n */\n public getNextBlock(\n blockIdentifier: BlockIdentifier,\n ): Block<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getNextBlock(tr.doc, blockIdentifier));\n }\n\n /**\n * Gets a snapshot of the parent of an existing block from the editor.\n * @param blockIdentifier The identifier of an existing block for which the\n * parent should be retrieved.\n * @returns The parent of the block that matches the identifier. `undefined`\n * if no matching block was found, or the block isn't nested.\n */\n public getParentBlock(\n blockIdentifier: BlockIdentifier,\n ): Block<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getParentBlock(tr.doc, blockIdentifier));\n }\n\n /**\n * Traverses all blocks in the editor depth-first, and executes a callback for each.\n * @param callback The callback to execute for each block. Returning `false` stops the traversal.\n * @param reverse Whether the blocks should be traversed in reverse order.\n */\n public forEachBlock(\n callback: (block: Block<BSchema, ISchema, SSchema>) => boolean,\n reverse = false,\n ): void {\n const blocks = this.document.slice();\n\n if (reverse) {\n blocks.reverse();\n }\n\n function traverseBlockArray(\n blockArray: Block<BSchema, ISchema, SSchema>[],\n ): boolean {\n for (const block of blockArray) {\n if (callback(block) === false) {\n return false;\n }\n\n const children = reverse\n ? block.children.slice().reverse()\n : block.children;\n\n if (!traverseBlockArray(children)) {\n return false;\n }\n }\n\n return true;\n }\n\n traverseBlockArray(blocks);\n }\n\n /**\n * Executes a callback whenever the editor's contents change.\n * @param callback The callback to execute.\n *\n * @deprecated use {@link BlockNoteEditor.onChange} instead\n */\n public onEditorContentChange(callback: () => void) {\n this._tiptapEditor.on(\"update\", callback);\n }\n\n /**\n * Executes a callback whenever the editor's selection changes.\n * @param callback The callback to execute.\n *\n * @deprecated use `onSelectionChange` instead\n */\n public onEditorSelectionChange(callback: () => void) {\n this._tiptapEditor.on(\"selectionUpdate\", callback);\n }\n\n /**\n * Gets a snapshot of the current text cursor position.\n * @returns A snapshot of the current text cursor position.\n */\n public getTextCursorPosition(): TextCursorPosition<\n BSchema,\n ISchema,\n SSchema\n > {\n return this.transact((tr) => getTextCursorPosition(tr));\n }\n\n /**\n * Sets the text cursor position to the start or end of an existing block. Throws an error if the target block could\n * not be found.\n * @param targetBlock The identifier of an existing block that the text cursor should be moved to.\n * @param placement Whether the text cursor should be placed at the start or end of the block.\n */\n public setTextCursorPosition(\n targetBlock: BlockIdentifier,\n placement: \"start\" | \"end\" = \"start\",\n ) {\n return this.transact((tr) =>\n setTextCursorPosition(tr, targetBlock, placement),\n );\n }\n\n /**\n * Gets a snapshot of the current selection. This contains all blocks (included nested blocks)\n * that the selection spans across.\n *\n * If the selection starts / ends halfway through a block, the returned data will contain the entire block.\n */\n public getSelection(): Selection<BSchema, ISchema, SSchema> | undefined {\n return this.transact((tr) => getSelection(tr));\n }\n\n /**\n * Gets a snapshot of the current selection. This contains all blocks (included nested blocks)\n * that the selection spans across.\n *\n * If the selection starts / ends halfway through a block, the returned block will be\n * only the part of the block that is included in the selection.\n */\n public getSelectionCutBlocks() {\n return this.transact((tr) => getSelectionCutBlocks(tr));\n }\n\n /**\n * Sets the selection to a range of blocks.\n * @param startBlock The identifier of the block that should be the start of the selection.\n * @param endBlock The identifier of the block that should be the end of the selection.\n */\n public setSelection(startBlock: BlockIdentifier, endBlock: BlockIdentifier) {\n return this.transact((tr) => setSelection(tr, startBlock, endBlock));\n }\n\n /**\n * Checks if the editor is currently editable, or if it's locked.\n * @returns True if the editor is editable, false otherwise.\n */\n public get isEditable(): boolean {\n if (!this._tiptapEditor) {\n if (!this.headless) {\n throw new Error(\"no editor, but also not headless?\");\n }\n return false;\n }\n return this._tiptapEditor.isEditable === undefined\n ? true\n : this._tiptapEditor.isEditable;\n }\n\n /**\n * Makes the editor editable or locks it, depending on the argument passed.\n * @param editable True to make the editor editable, or false to lock it.\n */\n public set isEditable(editable: boolean) {\n if (!this._tiptapEditor) {\n if (!this.headless) {\n throw new Error(\"no editor, but also not headless?\");\n }\n // not relevant on headless\n return;\n }\n if (this._tiptapEditor.options.editable !== editable) {\n this._tiptapEditor.setEditable(editable);\n }\n }\n\n /**\n * Inserts new blocks into the editor. If a block's `id` is undefined, BlockNote generates one automatically. Throws an\n * error if the reference block could not be found.\n * @param blocksToInsert An array of partial blocks that should be inserted.\n * @param referenceBlock An identifier for an existing block, at which the new blocks should be inserted.\n * @param placement Whether the blocks should be inserted just before, just after, or nested inside the\n * `referenceBlock`.\n */\n public insertBlocks(\n blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" = \"before\",\n ) {\n return this.transact((tr) =>\n insertBlocks(tr, blocksToInsert, referenceBlock, placement),\n );\n }\n\n /**\n * Updates an existing block in the editor. Since updatedBlock is a PartialBlock object, some fields might not be\n * defined. These undefined fields are kept as-is from the existing block. Throws an error if the block to update could\n * not be found.\n * @param blockToUpdate The block that should be updated.\n * @param update A partial block which defines how the existing block should be changed.\n */\n public updateBlock(\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema, ISchema, SSchema>,\n ) {\n return this.transact((tr) => updateBlock(tr, blockToUpdate, update));\n }\n\n /**\n * Removes existing blocks from the editor. Throws an error if any of the blocks could not be found.\n * @param blocksToRemove An array of identifiers for existing blocks that should be removed.\n */\n public removeBlocks(blocksToRemove: BlockIdentifier[]) {\n return this.transact(\n (tr) => removeAndInsertBlocks(tr, blocksToRemove, []).removedBlocks,\n );\n }\n\n /**\n * Replaces existing blocks in the editor with new blocks. If the blocks that should be removed are not adjacent or\n * are at different nesting levels, `blocksToInsert` will be inserted at the position of the first block in\n * `blocksToRemove`. Throws an error if any of the blocks to remove could not be found.\n * @param blocksToRemove An array of blocks that should be replaced.\n * @param blocksToInsert An array of partial blocks to replace the old ones with.\n */\n public replaceBlocks(\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[],\n ) {\n return this.transact((tr) =>\n removeAndInsertBlocks(tr, blocksToRemove, blocksToInsert),\n );\n }\n\n /**\n * Undo the last action.\n */\n public undo() {\n if (this.options.collaboration) {\n return this.exec(undoCommand);\n }\n\n return this.exec(undo);\n }\n\n /**\n * Redo the last action.\n */\n public redo() {\n if (this.options.collaboration) {\n return this.exec(redoCommand);\n }\n return this.exec(redo);\n }\n\n /**\n * Insert a piece of content at the current cursor position.\n *\n * @param content can be a string, or array of partial inline content elements\n */\n public insertInlineContent(\n content: PartialInlineContent<ISchema, SSchema>,\n { updateSelection = false }: { updateSelection?: boolean } = {},\n ) {\n const nodes = inlineContentToNodes(content, this.pmSchema);\n\n this.transact((tr) => {\n insertContentAt(\n tr,\n {\n from: tr.selection.from,\n to: tr.selection.to,\n },\n nodes,\n {\n updateSelection,\n },\n );\n });\n }\n\n /**\n * Gets the active text styles at the text cursor position or at the end of the current selection if it's active.\n */\n public getActiveStyles() {\n return this.transact((tr) => {\n const styles: Styles<SSchema> = {};\n const marks = tr.selection.$to.marks();\n\n for (const mark of marks) {\n const config = this.schema.styleSchema[mark.type.name];\n if (!config) {\n if (\n // Links are not considered styles in blocknote\n mark.type.name !== \"link\" &&\n // \"blocknoteIgnore\" tagged marks (such as comments) are also not considered BlockNote \"styles\"\n !mark.type.spec.blocknoteIgnore\n ) {\n // eslint-disable-next-line no-console\n console.warn(\"mark not found in styleschema\", mark.type.name);\n }\n\n continue;\n }\n if (config.propSchema === \"boolean\") {\n (styles as any)[config.type] = true;\n } else {\n (styles as any)[config.type] = mark.attrs.stringValue;\n }\n }\n\n return styles;\n });\n }\n\n /**\n * Adds styles to the currently selected content.\n * @param styles The styles to add.\n */\n public addStyles(styles: Styles<SSchema>) {\n for (const [style, value] of Object.entries(styles)) {\n const config = this.schema.styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n this._tiptapEditor.commands.setMark(style);\n } else if (config.propSchema === \"string\") {\n this._tiptapEditor.commands.setMark(style, { stringValue: value });\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n /**\n * Removes styles from the currently selected content.\n * @param styles The styles to remove.\n */\n public removeStyles(styles: Styles<SSchema>) {\n for (const style of Object.keys(styles)) {\n this._tiptapEditor.commands.unsetMark(style);\n }\n }\n\n /**\n * Toggles styles on the currently selected content.\n * @param styles The styles to toggle.\n */\n public toggleStyles(styles: Styles<SSchema>) {\n for (const [style, value] of Object.entries(styles)) {\n const config = this.schema.styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n this._tiptapEditor.commands.toggleMark(style);\n } else if (config.propSchema === \"string\") {\n this._tiptapEditor.commands.toggleMark(style, { stringValue: value });\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n /**\n * Gets the currently selected text.\n */\n public getSelectedText() {\n return this.transact((tr) => {\n return tr.doc.textBetween(tr.selection.from, tr.selection.to);\n });\n }\n\n /**\n * Gets the URL of the last link in the current selection, or `undefined` if there are no links in the selection.\n */\n public getSelectedLinkUrl() {\n return this._tiptapEditor.getAttributes(\"link\").href as string | undefined;\n }\n\n /**\n * Creates a new link to replace the selected content.\n * @param url The link URL.\n * @param text The text to display the link with.\n */\n public createLink(url: string, text?: string) {\n if (url === \"\") {\n return;\n }\n const mark = this.pmSchema.mark(\"link\", { href: url });\n this.transact((tr) => {\n const { from, to } = tr.selection;\n\n if (text) {\n tr.insertText(text, from, to).addMark(from, from + text.length, mark);\n } else {\n tr.setSelection(TextSelection.create(tr.doc, to)).addMark(\n from,\n to,\n mark,\n );\n }\n });\n }\n\n /**\n * Checks if the block containing the text cursor can be nested.\n */\n public canNestBlock() {\n return canNestBlock(this);\n }\n\n /**\n * Nests the block containing the text cursor into the block above it.\n */\n public nestBlock() {\n nestBlock(this);\n }\n\n /**\n * Checks if the block containing the text cursor is nested.\n */\n public canUnnestBlock() {\n return canUnnestBlock(this);\n }\n\n /**\n * Lifts the block containing the text cursor out of its parent.\n */\n public unnestBlock() {\n unnestBlock(this);\n }\n\n /**\n * Moves the selected blocks up. If the previous block has children, moves\n * them to the end of its children. If there is no previous block, but the\n * current blocks share a common parent, moves them out of & before it.\n */\n public moveBlocksUp() {\n return moveBlocksUp(this);\n }\n\n /**\n * Moves the selected blocks down. If the next block has children, moves\n * them to the start of its children. If there is no next block, but the\n * current blocks share a common parent, moves them out of & after it.\n */\n public moveBlocksDown() {\n return moveBlocksDown(this);\n }\n\n /**\n * Exports blocks into a simplified HTML string. To better conform to HTML standards, children of blocks which aren't list\n * items are un-nested in the output HTML.\n *\n * @param blocks An array of blocks that should be serialized into HTML.\n * @returns The blocks, serialized as an HTML string.\n */\n public async blocksToHTMLLossy(\n blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document,\n ): Promise<string> {\n const exporter = createExternalHTMLExporter(this.pmSchema, this);\n return exporter.exportBlocks(blocks, {});\n }\n\n /**\n * Serializes blocks into an HTML string in the format that would normally be rendered by the editor.\n *\n * Use this method if you want to server-side render HTML (for example, a blog post that has been edited in BlockNote)\n * and serve it to users without loading the editor on the client (i.e.: displaying the blog post)\n *\n * @param blocks An array of blocks that should be serialized into HTML.\n * @returns The blocks, serialized as an HTML string.\n */\n public async blocksToFullHTML(\n blocks: PartialBlock<BSchema, ISchema, SSchema>[],\n ): Promise<string> {\n const exporter = createInternalHTMLSerializer(this.pmSchema, this);\n return exporter.serializeBlocks(blocks, {});\n }\n /**\n * Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and\n * `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote\n * doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.\n * @param html The HTML string to parse blocks from.\n * @returns The blocks parsed from the HTML string.\n */\n public async tryParseHTMLToBlocks(\n html: string,\n ): Promise<Block<BSchema, ISchema, SSchema>[]> {\n return HTMLToBlocks(html, this.pmSchema);\n }\n\n /**\n * Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of\n * BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.\n * @param blocks An array of blocks that should be serialized into Markdown.\n * @returns The blocks, serialized as a Markdown string.\n */\n public async blocksToMarkdownLossy(\n blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document,\n ): Promise<string> {\n return blocksToMarkdown(blocks, this.pmSchema, this, {});\n }\n\n /**\n * Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on\n * Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it\n * as text.\n * @param markdown The Markdown string to parse blocks from.\n * @returns The blocks parsed from the Markdown string.\n */\n public async tryParseMarkdownToBlocks(\n markdown: string,\n ): Promise<Block<BSchema, ISchema, SSchema>[]> {\n return markdownToBlocks(markdown, this.pmSchema);\n }\n\n /**\n * Updates the user info for the current user that's shown to other collaborators.\n */\n public updateCollaborationUserInfo(user: { name: string; color: string }) {\n if (!this.options.collaboration) {\n throw new Error(\n \"Cannot update collaboration user info when collaboration is disabled.\",\n );\n }\n\n (this.extensions[\"yCursorPlugin\"] as CursorPlugin).updateUser(user);\n }\n\n /**\n * A callback function that runs whenever the editor's contents change.\n *\n * @param callback The callback to execute.\n * @returns A function to remove the callback.\n */\n public onChange(\n callback: (\n editor: BlockNoteEditor<BSchema, ISchema, SSchema>,\n context: {\n /**\n * Returns the blocks that were inserted, updated, or deleted by the change that occurred.\n */\n getChanges(): BlocksChanged<BSchema, ISchema, SSchema>;\n },\n ) => void,\n ) {\n if (this.headless) {\n // Note: would be nice if this is possible in headless mode as well\n return;\n }\n\n const cb = ({\n transaction,\n appendedTransactions,\n }: {\n transaction: Transaction;\n appendedTransactions: Transaction[];\n }) => {\n callback(this, {\n getChanges: () =>\n getBlocksChangedByTransaction(transaction, appendedTransactions),\n });\n };\n\n this._tiptapEditor.on(\"v3-update\", cb);\n\n return () => {\n this._tiptapEditor.off(\"v3-update\", cb);\n };\n }\n\n /**\n * A callback function that runs whenever the text cursor position or selection changes.\n *\n * @param callback The callback to execute.\n * @returns A function to remove the callback.\n */\n public onSelectionChange(\n callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void,\n includeSelectionChangedByRemote?: boolean,\n ) {\n if (this.headless) {\n return;\n }\n\n const cb = (e: { transaction: Transaction }) => {\n if (\n e.transaction.getMeta(ySyncPluginKey) &&\n !includeSelectionChangedByRemote\n ) {\n // selection changed because of a yjs sync (i.e.: other user was typing)\n // we don't want to trigger the callback in this case\n return;\n }\n callback(this);\n };\n\n this._tiptapEditor.on(\"selectionUpdate\", cb);\n\n return () => {\n this._tiptapEditor.off(\"selectionUpdate\", cb);\n };\n }\n\n /**\n * A callback function that runs when the editor has been initialized.\n *\n * This can be useful for plugins to initialize themselves after the editor has been initialized.\n */\n public onCreate(callback: () => void) {\n this.on(\"create\", callback);\n\n return () => {\n this.off(\"create\", callback);\n };\n }\n\n public getSelectionBoundingBox() {\n if (!this.prosemirrorView) {\n return undefined;\n }\n\n const { selection } = this.prosemirrorState;\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n if (isNodeSelection(selection)) {\n const node = this.prosemirrorView.nodeDOM(from) as HTMLElement;\n if (node) {\n return node.getBoundingClientRect();\n }\n }\n\n return posToDOMRect(this.prosemirrorView, from, to);\n }\n\n public get isEmpty() {\n const doc = this.document;\n // Note: only works for paragraphs as default blocks (but for now this is default in blocknote)\n // checking prosemirror directly might be faster\n return (\n doc.length === 0 ||\n (doc.length === 1 &&\n doc[0].type === \"paragraph\" &&\n (doc[0].content as any).length === 0)\n );\n }\n\n public openSuggestionMenu(\n triggerCharacter: string,\n pluginState?: {\n deleteTriggerCharacter?: boolean;\n ignoreQueryLength?: boolean;\n },\n ) {\n if (!this.prosemirrorView) {\n return;\n }\n\n this.focus();\n this.transact((tr) => {\n if (pluginState?.deleteTriggerCharacter) {\n tr.insertText(triggerCharacter);\n }\n tr.scrollIntoView().setMeta(this.suggestionMenus.plugins[0], {\n triggerCharacter: triggerCharacter,\n deleteTriggerCharacter: pluginState?.deleteTriggerCharacter || false,\n ignoreQueryLength: pluginState?.ignoreQueryLength || false,\n });\n });\n }\n\n // `forceSelectionVisible` determines whether the editor selection is shows\n // even when the editor is not focused. This is useful for e.g. creating new\n // links, so the user still sees the affected content when an input field is\n // focused.\n // TODO: Reconsider naming?\n public getForceSelectionVisible() {\n return this.showSelectionPlugin.getEnabled();\n }\n\n public setForceSelectionVisible(forceSelectionVisible: boolean) {\n this.showSelectionPlugin.setEnabled(forceSelectionVisible);\n }\n\n /**\n * This will convert HTML into a format that is compatible with BlockNote.\n */\n private convertHtmlToBlockNoteHtml(html: string) {\n const htmlNode = nestedListsToBlockNoteStructure(html.trim());\n return htmlNode.innerHTML;\n }\n\n /**\n * Paste HTML into the editor. Defaults to converting HTML to BlockNote HTML.\n * @param html The HTML to paste.\n * @param raw Whether to paste the HTML as is, or to convert it to BlockNote HTML.\n */\n public pasteHTML(html: string, raw = false) {\n let htmlToPaste = html;\n if (!raw) {\n htmlToPaste = this.convertHtmlToBlockNoteHtml(html);\n }\n if (!htmlToPaste) {\n return;\n }\n this.prosemirrorView?.pasteHTML(htmlToPaste);\n }\n\n /**\n * Paste text into the editor. Defaults to interpreting text as markdown.\n * @param text The text to paste.\n */\n public pasteText(text: string) {\n return this.prosemirrorView?.pasteText(text);\n }\n\n /**\n * Paste markdown into the editor.\n * @param markdown The markdown to paste.\n */\n public async pasteMarkdown(markdown: string) {\n return this.pasteHTML(await markdownToHTML(markdown));\n }\n}\n","export const COLORS_DEFAULT = {\n gray: {\n text: \"#9b9a97\",\n background: \"#ebeced\",\n },\n brown: {\n text: \"#64473a\",\n background: \"#e9e5e3\",\n },\n red: {\n text: \"#e03e3e\",\n background: \"#fbe4e4\",\n },\n orange: {\n text: \"#d9730d\",\n background: \"#f6e9d9\",\n },\n yellow: {\n text: \"#dfab01\",\n background: \"#fbf3db\",\n },\n green: {\n text: \"#4d6461\",\n background: \"#ddedea\",\n },\n blue: {\n text: \"#0b6e99\",\n background: \"#ddebf1\",\n },\n purple: {\n text: \"#6940a5\",\n background: \"#eae4f2\",\n },\n pink: {\n text: \"#ad1a72\",\n background: \"#f4dfeb\",\n },\n};\n\nexport const COLORS_DARK_MODE_DEFAULT = {\n gray: {\n text: \"#bebdb8\",\n background: \"#9b9a97\",\n },\n brown: {\n text: \"#8e6552\",\n background: \"#64473a\",\n },\n red: {\n text: \"#ec4040\",\n background: \"#be3434\",\n },\n orange: {\n text: \"#e3790d\",\n background: \"#b7600a\",\n },\n yellow: {\n text: \"#dfab01\",\n background: \"#b58b00\",\n },\n green: {\n text: \"#6b8b87\",\n background: \"#4d6461\",\n },\n blue: {\n text: \"#0e87bc\",\n background: \"#0b6e99\",\n },\n purple: {\n text: \"#8552d7\",\n background: \"#6940a5\",\n },\n pink: {\n text: \"#da208f\",\n background: \"#ad1a72\",\n },\n};\n","import { BlockNoteSchema } from \"../editor/BlockNoteSchema.js\";\nimport { COLORS_DEFAULT } from \"../editor/defaultColors.js\";\nimport {\n BlockFromConfig,\n BlockSchema,\n InlineContent,\n InlineContentSchema,\n StyleSchema,\n StyledText,\n Styles,\n} from \"../schema/index.js\";\n\nimport type {\n BlockMapping,\n InlineContentMapping,\n StyleMapping,\n} from \"./mapping.js\";\n\nexport type ExporterOptions = {\n /**\n * A function that can be used to resolve files, images, etc.\n * Exporters might need the binary contents of files like images,\n * which might not always be available from the same origin as the main page.\n * You can use this option to proxy requests through a server you control\n * to avoid cross-origin (CORS) issues.\n *\n * @default uses a BlockNote hosted proxy (https://corsproxy.api.blocknotejs.org/)\n * @param url - The URL of the file to resolve\n * @returns A Promise that resolves to a string (the URL to use instead of the original)\n * or a Blob (you can return the Blob directly if you have already fetched it)\n */\n resolveFileUrl?: (url: string) => Promise<string | Blob>;\n /**\n * Colors to use for background of blocks, font colors, and highlight colors\n */\n colors: typeof COLORS_DEFAULT;\n};\nexport abstract class Exporter<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n RB,\n RI,\n RS,\n TS,\n> {\n public constructor(\n _schema: BlockNoteSchema<B, I, S>, // only used for type inference\n protected readonly mappings: {\n blockMapping: BlockMapping<B, I, S, RB, RI>;\n inlineContentMapping: InlineContentMapping<I, S, RI, TS>;\n styleMapping: StyleMapping<S, RS>;\n },\n public readonly options: ExporterOptions,\n ) {}\n\n public async resolveFile(url: string) {\n if (!this.options?.resolveFileUrl) {\n return (await fetch(url)).blob();\n }\n const ret = await this.options.resolveFileUrl(url);\n if (ret instanceof Blob) {\n return ret;\n }\n return (await fetch(ret)).blob();\n }\n\n public mapStyles(styles: Styles<S>) {\n const stylesArray = Object.entries(styles).map(([key, value]) => {\n const mappedStyle = this.mappings.styleMapping[key](value, this);\n return mappedStyle;\n });\n return stylesArray;\n }\n\n public mapInlineContent(inlineContent: InlineContent<I, S>) {\n return this.mappings.inlineContentMapping[inlineContent.type](\n inlineContent,\n this,\n );\n }\n\n public transformInlineContent(inlineContentArray: InlineContent<I, S>[]) {\n return inlineContentArray.map((ic) => this.mapInlineContent(ic));\n }\n\n public abstract transformStyledText(styledText: StyledText<S>): TS;\n\n public async mapBlock(\n block: BlockFromConfig<B[keyof B], I, S>,\n nestingLevel: number,\n numberedListIndex: number,\n ) {\n return this.mappings.blockMapping[block.type](\n block,\n this,\n nestingLevel,\n numberedListIndex,\n );\n }\n}\n","import { BlockNoteSchema } from \"../editor/BlockNoteSchema.js\";\nimport {\n BlockFromConfigNoChildren,\n BlockSchema,\n InlineContentFromConfig,\n InlineContentSchema,\n StyleSchema,\n Styles,\n} from \"../schema/index.js\";\nimport type { Exporter } from \"./Exporter.js\";\n\n/**\n * Defines a mapping from all block types with a schema to a result type `R`.\n */\nexport type BlockMapping<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n RB,\n RI,\n> = {\n [K in keyof B]: (\n block: BlockFromConfigNoChildren<B[K], I, S>,\n // we don't know the exact types that are supported by the exporter at this point,\n // because the mapping only knows about converting certain types (which might be a subset of the supported types)\n // this is why there are many `any` types here (same for types below)\n exporter: Exporter<any, any, any, RB, RI, any, any>,\n nestingLevel: number,\n numberedListIndex?: number,\n ) => RB | Promise<RB>;\n};\n\n/**\n * Defines a mapping from all inline content types with a schema to a result type R.\n */\nexport type InlineContentMapping<\n I extends InlineContentSchema,\n S extends StyleSchema,\n RI,\n TS,\n> = {\n [K in keyof I]: (\n inlineContent: InlineContentFromConfig<I[K], S>,\n exporter: Exporter<any, I, S, any, RI, any, TS>,\n ) => RI;\n};\n\n/**\n * Defines a mapping from all style types with a schema to a result type R.\n */\nexport type StyleMapping<S extends StyleSchema, RS> = {\n [K in keyof S]: (\n style: Styles<S>[K],\n exporter: Exporter<any, any, any, any, any, RS, any>,\n ) => RS;\n};\n\n/**\n * The mapping factory is a utility function to easily create mappings for\n * a BlockNoteSchema. Using the factory makes it easier to get typescript code completion etc.\n */\nexport function mappingFactory<\n B extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(_schema: BlockNoteSchema<B, I, S>) {\n return {\n createBlockMapping: <R, RI>(mapping: BlockMapping<B, I, S, R, RI>) =>\n mapping,\n createInlineContentMapping: <R, RS>(\n mapping: InlineContentMapping<I, S, R, RS>,\n ) => mapping,\n createStyleMapping: <R>(mapping: StyleMapping<S, R>) => mapping,\n };\n}\n","import type { Emoji, EmojiMartData } from \"@emoji-mart/data\";\n\nimport { checkDefaultInlineContentTypeInSchema } from \"../../blocks/defaultBlockTypeGuards.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema/index.js\";\nimport { DefaultGridSuggestionItem } from \"./DefaultGridSuggestionItem.js\";\n\n// Temporary fix for https://github.com/missive/emoji-mart/pull/929\nlet emojiLoadingPromise:\n | Promise<{\n emojiMart: typeof import(\"emoji-mart\");\n emojiData: EmojiMartData;\n }>\n | undefined;\n\nasync function loadEmojiMart() {\n if (emojiLoadingPromise) {\n return emojiLoadingPromise;\n }\n\n emojiLoadingPromise = (async () => {\n // load dynamically because emoji-mart doesn't specify type: module and breaks in nodejs\n const [emojiMartModule, emojiDataModule] = await Promise.all([\n import(\"emoji-mart\"),\n // use a dynamic import to encourage bundle-splitting\n // and a smaller initial client bundle size\n import(\"@emoji-mart/data\"),\n ]);\n\n const emojiMart =\n \"default\" in emojiMartModule ? emojiMartModule.default : emojiMartModule;\n const emojiData =\n \"default\" in emojiDataModule\n ? (emojiDataModule.default as EmojiMartData)\n : (emojiDataModule as EmojiMartData);\n\n await emojiMart.init({ data: emojiData });\n\n return { emojiMart, emojiData };\n })();\n\n return emojiLoadingPromise;\n}\n\nexport async function getDefaultEmojiPickerItems<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n query: string,\n): Promise<DefaultGridSuggestionItem[]> {\n if (!checkDefaultInlineContentTypeInSchema(\"text\", editor)) {\n return [];\n }\n\n const { emojiData, emojiMart } = await loadEmojiMart();\n\n const emojisToShow =\n query.trim() === \"\"\n ? Object.values(emojiData.emojis)\n : ((await emojiMart!.SearchIndex.search(query)) as Emoji[]);\n\n return emojisToShow.map((emoji) => ({\n id: emoji.skins[0].native,\n onItemClick: () => editor.insertInlineContent(emoji.skins[0].native + \" \"),\n }));\n}\n","/**\n * Combines items by group. This can be used to combine multiple slash menu item arrays,\n * while making sure that items from the same group are adjacent to each other.\n */\nexport function combineByGroup<T extends { group?: string }>(\n items: T[],\n ...additionalItemsArray: {\n group?: string;\n }[][]\n) {\n const combinedItems = [...items];\n for (const additionalItems of additionalItemsArray) {\n for (const additionalItem of additionalItems) {\n const lastItemWithSameGroup = combinedItems.findLastIndex(\n (item) => item.group === additionalItem.group,\n );\n if (lastItemWithSameGroup === -1) {\n combinedItems.push(additionalItem as T);\n } else {\n combinedItems.splice(lastItemWithSameGroup + 1, 0, additionalItem as T);\n }\n }\n }\n return combinedItems;\n}\n"],"names":["removeDuplicates","array","by","seen","item","key","findDuplicates","items","filtered","el","index","UniqueID","Extension","testOptions","v4","element","attributes","defaultIdAttributes","dragSourceElement","transformPasted","Plugin","PluginKey","transactions","oldState","newState","docChanges","transaction","filterTransactions","tr","_a","_b","types","attributeName","generateID","transform","combineTransactionSteps","mapping","getChangedRanges","newRange","newNodes","findChildrenInRange","node","newIds","id","duplicatedNewIds","pos","initialDoc","jsonNode","deleted","view","handleDragstart","event","slice","removeId","fragment","list","nodeWithoutId","Fragment","Slice","isLinkInlineContent","content","isPartialLinkInlineContent","isStyledTextInlineContent","mapTableCell","isTableCell","isPartialTableCell","_c","_d","_e","getColspan","cell","getRowspan","UnreachableCaseError","val","assertEmpty","obj","throwError","dataTest","rest","isAppleOS","formatKeyboardShortcut","shortcut","ctrlText","mergeCSSClasses","classes","c","isSafari","createDefaultBlockDOMOutputSpec","blockName","htmlTag","blockContentHTMLAttributes","inlineContentHTMLAttributes","blockContent","attribute","value","inlineContent","defaultBlockToHTML","block","editor","blockToNode","toDOM","renderSpec","mergeParagraphs","paragraphs","firstParagraph","i","paragraph","defaultProps","inheritedProps","camelToDataKebab","str","filenameFromURL","url","parts","propsToAttributes","propSchema","tiptapAttributes","name","_spec","spec","asNumber","getBlockFromPos","getPos","tipTapEditor","type","blockIdentifier","wrapInBlockStructure","blockType","blockProps","isFileBlock","domAttributes","attr","prop","defaultValue","createStronglyTypedTiptapNode","config","Node","createInternalBlockSpec","implementation","createBlockSpecFromStronglyTypedTiptapNode","requiredExtensions","getBlockSchemaFromSpecs","specs","applyNonSelectableBlockFix","nodeView","getParseRules","customParseFunction","rules","props","createBlockSpec","blockConfig","blockImplementation","HTMLAttributes","div","blockContentDOMAttributes","output","getNearestBlockPos","doc","$pos","depth","allBlockContainerPositions","resolvedPos","position","getBlockInfoWithManualOffset","bnBlockBeforePosOffset","bnBlockNode","bnBlockBeforePos","bnBlockAfterPos","bnBlock","blockGroup","offset","blockContentNode","blockContentBeforePos","blockContentAfterPos","blockGroupNode","blockGroupBeforePos","blockGroupAfterPos","getBlockInfo","posInfo","getBlockInfoFromResolvedPos","getBlockInfoFromSelection","state","getBlockInfoFromTransaction","getPmSchema","trOrNode","getBlockNoteEditor","schema","getBlockNoteSchema","getBlockSchema","getInlineContentSchema","getStyleSchema","getBlockCache","contentNodeToTableContent","contentNode","inlineContentSchema","styleSchema","ret","headerMatrix","rowNode","_offset","rowIndex","row","cellNode","colWidth","cellIndex","child","contentNodeToInlineContent","acc","contentPartial","last","first","isHeader","currentContent","nodeToCustomInlineContent","styles","linkMark","mark","icConfig","nodeToBlock","blockSchema","blockCache","cachedBlock","blockInfo","blockSpec","children","docToBlocks","blocks","prosemirrorSliceToSlicedBlocks","processNode","openStart","openEnd","blockCutAtStart","blockCutAtEnd","blockContainer","isFirstBlock","isLastBlock","childGroup","childBlocks","addInlineContentAttributes","inlineContentType","inlineContentProps","addInlineContentKeyboardShortcuts","createInternalInlineContentSpec","createInlineContentSpecFromTipTapNode","getInlineContentSchemaFromSpecs","getInlineContentParseRules","htmlElement","createInlineContentSpec","inlineContentConfig","inlineContentImplementation","update","inlineContentToNodes","stylePropsToAttributes","addStyleAttributes","styleType","styleValue","createInternalStyleSpec","createStyleSpecFromTipTapMark","getStyleSchemaFromSpecs","getStyleParseRules","createStyleSpec","styleConfig","styleImplementation","Mark","renderResult","getTableCellOccupancyGrid","height","width","getDimensionsOfTable","grid","findNextAvailable","col","j","rowspan","colspan","startRow","startCol","getTableRowsFromOccupancyGrid","occupancyGrid","getAbsoluteTableCells","relativeCellIndices","r","rowWidth","getRelativeTableCells","absoluteCellIndices","occupancyCell","getCellsAtRowHandle","relativeRowIndex","absoluteRow","cells","_v","a","getCellsAtColumnHandle","relativeColumnIndex","absoluteCol","moveColumn","fromColIndex","toColIndex","absoluteSourceCol","absoluteTargetCol","sourceCell","moveRow","fromRowIndex","toRowIndex","absoluteSourceRow","absoluteTargetRow","sourceRow","isCellEmpty","s","cropEmptyRowsOrColumns","removeEmpty","emptyColsOnRight","cellsToRemove","emptyRowsOnBottom","rowsToRemove","addRowsOrColumns","addType","numToAdd","newRow","_","colIndex","canRowBeDraggedInto","draggingIndex","targetRowIndex","targetCells","endRowIndex","startRowIndex","canColumnBeDraggedInto","targetColumnIndex","endColumnIndex","startColumnIndex","areInSameColumn","from","to","anchorAbsoluteCellIndices","headAbsoluteCellIndices","styledTextToNodes","styledText","marks","style","text","linkToNodes","link","styledTextArrayToNodes","nodes","blockOrInlineContentToContentNode","tableContentToNodes","tableContent","rowNodes","headerRows","headerCols","columnWidths","columnNodes","isHeaderRow","isHeaderCol","attrs","absoluteCellIndex","colwidth","groupNode","getNodeById","targetNode","posBeforeNode","isNodeBlock","areBlocksDifferentExcludingChildren","block1","block2","getBlocksChangedByTransaction","appendedTransactions","source","pmSchema","combinedTransaction","changedRanges","prevAffectedBlocks","range","nextAffectedBlocks","nextBlocks","prevBlocks","changes","prevBlock","insertBlocks","blocksToInsert","referenceBlock","placement","nodesToInsert","ReplaceStep","removeAndInsertBlocks","blocksToRemove","idsOfBlocksToRemove","removedBlocks","idOfFirstBlock","removedSize","oldDocSize","newDocSize","notFoundIds","updateBlockCommand","posBeforeBlock","dispatch","updateBlockTr","replaceFromPos","replaceToPos","oldNodeType","newNodeType","newBnBlockNodeType","replaceFromOffset","replaceToOffset","updateChildren","updateBlockContentNode","existingBlock","start","end","contentDepth","startDepth","endDepth","childNodes","updateBlock","blockToUpdate","blockContainerNode","addAttributesAndRemoveClasses","className","serializeInlineContentExternalHTML","serializer","options","dom","serializeBlock","orderedListItemBlockTypes","unorderedListItemBlockTypes","BC_NODE","bc","elementFragment","blockContentDataAttributes","ic","listType","li","childFragment","serializeBlocksToFragment","_f","_g","_h","serializeBlocksExternalHTML","createExternalHTMLExporter","DOMSerializer","html","domFragment","parent","serializeInlineContentInternalHTML","listIndex","serializeBlocks","serializeBlocksInternalHTML","blockDOM","BG_NODE","bg","createInternalHTMLSerializer","parseFigureElement","figureElement","targetTag","targetElement","captionElement","caption","createAddFileButton","buttonText","buttonIcon","addFileButton","addFileButtonIcon","addFileButtonText","addFileButtonMouseDownHandler","addFileButtonClickHandler","FILE_ICON_SVG","createFileNameWithIcon","file","icon","fileName","createFileBlockWrapper","wrapper","destroyUploadStartHandler","blockId","loading","fileNameWithIcon","createFigureWithCaption","figure","createLinkWithCaption","fileCaption","parseAudioElement","audioElement","FILE_AUDIO_ICON_SVG","audioPropSchema","audioBlockConfig","audioRender","audio","downloadUrl","audioParse","parsedFigure","audioToExternalHTML","AudioBlock","shikiParserSymbol","shikiHighlighterPromiseSymbol","defaultCodeBlockPropSchema","CodeBlockContent","inputElement","language","dataLanguage","languages","getLanguageId","pre","contentDOM","select","selectWrapper","handleLanguageChange","option","newNode","globalThisForShiki","highlighter","parser","hasWarned","createHighlightPlugin","parserOptions","createdHighlighter","createParser","InputRule","match","$start","languageName","TextSelection","selection","$from","isTextSelection","isAtEnd","endsWithDoubleNewline","CodeBlock","aliases","BackgroundColorMark","BackgroundColor","TextColorMark","TextColor","parseEmbedElement","embedElement","filePropSchema","fileBlockConfig","fileRender","fileParse","fileToExternalHTML","fileSrcLink","FileBlock","headingPropSchema","HeadingBlockContent","level","chain","Heading","createResizableFileBlockWrapper","resizeHandlesContainerElement","destroy","leftResizeHandle","rightResizeHandle","resizeParams","windowMouseMoveHandler","newWidth","windowMouseUpHandler","wrapperMouseEnterHandler","wrapperMouseLeaveHandler","leftResizeHandleMouseDownHandler","rightResizeHandleMouseDownHandler","parseImageElement","imageElement","previewWidth","FILE_IMAGE_ICON_SVG","imagePropSchema","imageBlockConfig","imageRender","imageWrapper","image","imageParse","imageToExternalHTML","ImageBlock","getListItemContent","_node","DOMParser","clonedNodeDiv","listItemsFirstChild","listItemNode","remainingListItemChildren","listItemsChildren","splitBlockCommand","posInBlock","keepType","keepProps","nearestBlockContainerPos","info","handleEnter","selectionEmpty","commands","bulletListItemPropSchema","BulletListItemBlockContent","BulletListItem","checkListItemPropSchema","checkListItemBlockContent","checkbox","checkboxWrapper","changeHandler","beforeBlockContainerPos","label","CheckListItem","PLUGIN_KEY","NumberedListIndexingPlugin","_transactions","_oldState","modified","newIndex","prevBlockInfo","prevBlockIndex","isFirst","numberedListItemPropSchema","NumberedListItemBlockContent","startIndex","NumberedListItem","paragraphPropSchema","ParagraphBlockContent","Paragraph","quotePropSchema","QuoteBlockContent","Quote","RESIZE_MIN_WIDTH","EMPTY_CELL_WIDTH","EMPTY_CELL_HEIGHT","TableExtension","columnResizing","tableEditing","selectionIsEmpty","selectionIsAtStartOfNode","selectionIsInTableParagraphNode","goToNextCell","extension","context","callOrReturn","getExtensionField","tablePropSchema","TableBlockContent","BlockNoteTableView","TableView","cellMinWidth","tableWrapper","tableWrapperInner","floatingContainer","record","TableParagraph","TableRow","mergeAttributes","parseTableContent","parsedContent","extractedContent","Table","TableHeader","TableCell","parseVideoElement","videoElement","FILE_VIDEO_ICON_SVG","videoPropSchema","videoBlockConfig","videoRender","videoWrapper","video","videoParse","videoToExternalHTML","VideoBlock","defaultBlockSpecs","defaultBlockSchema","defaultStyleSpecs","Bold","Italic","Underline","Strike","Code","defaultStyleSchema","defaultInlineContentSpecs","defaultInlineContentSchema","checkDefaultBlockTypeInSchema","checkDefaultInlineContentTypeInSchema","checkBlockIsDefaultType","checkBlockIsFileBlock","checkBlockIsFileBlockWithPreview","checkBlockIsFileBlockWithPlaceholder","checkBlockTypeHasDefaultProp","checkBlockHasDefaultProp","isTableCellSelection","CellSelection","uploadToTmpFilesDotOrg_DEV_ONLY","body","setSelectionToNextContentEditableBlock","contentType","insertOrUpdateBlock","currentBlock","newBlock","getDefaultSlashMenuItems","insertedBlock","filterSuggestionItems","query","title","alias","removeUndefined","BlockNoteSchema","opts","__publicField","pageBreakConfig","pageBreakRender","pageBreak","pageBreakParse","pageBreakToExternalHTML","PageBreak","pageBreakSchema","withPageBreak","checkPageBreakBlocksInSchema","getPageBreakSlashMenuItems","getBlockSelectionData","anchorBlockPosInfo","NodeSelection","headBlockPosInfo","updateBlockSelectionFromData","data","anchorBlockPos","headBlockPos","flattenColumns","column","moveSelectedBlocksAndSelection","selectionData","checkPlacementIsValid","parentBlock","getMoveUpPlacement","referenceBlockParent","getMoveDownPlacement","nextBlock","moveBlocksUp","moveUpPlacement","moveBlocksDown","moveDownPlacement","sinkListItem","itemType","groupType","$to","nodeBefore","nestedBefore","inner","before","after","ReplaceAroundStep","nestBlock","unnestBlock","canNestBlock","canUnnestBlock","getBlock","getPrevBlock","nodeToConvert","getNextBlock","getParentBlock","$posBeforeNode","parentNode","grandparentNode","insertContentAt","isOnlyTextContent","isOnlyBlockContent","selectionToInsertionEnd","getSelection","$startBlockBeforePos","$endBlockBeforePos","indexToBlock","sharedDepth","endIndex","startIndexAtDepth","childCountAtDepth","setSelection","startBlock","endBlock","startBlockId","endBlockId","anchorPosInfo","headPosInfo","anchorBlockInfo","headBlockInfo","anchorBlockConfig","headBlockConfig","startPos","endPos","tableMap","TableMap","lastCellPos","lastCellNodeSize","getSelectionCutBlocks","selectionInfo","getTextCursorPosition","prevNode","nextNode","setTextCursorPosition","targetBlock","esmDependencies","initializeESMDependencies","vals","removeUnderlines","removeUnderlinesHelper","tree","numChildElements","numElementsAdded","addSpacesToCheckboxes","deps","helper","nextChild","cleanHTMLToMarkdown","cleanHTMLString","blocksToMarkdown","externalHTML","getChildIndex","isWhitespaceNode","liftNestedListsToParent","parentListItem","siblingsAfter","sibling","siblingContainer","createGroups","listItem","_detachedDoc","detachedDoc","nestedListsToBlockNoteStructure","elementOrHTML","HTMLToBlocks","htmlNode","code","properties","result","markdownToHTML","markdown","markdownToBlocks","htmlString","acceptedMIMETypes","checkFileExtensionsMatch","fileExtension1","fileExtension2","checkMIMETypesMatch","mimeType1","mimeType2","types1","types2","insertedBlockId","handleFileInsertion","dataTransfer","format","mimeType","fileBlockConfigs","fileBlockType","isFileExtension","fileBlock","coords","updateData","updatedFileBlock","createDropFileExtension","_view","h1","bold","ul","ol","hr","fences","blockquote","tableHeader","tableDivider","tableRow","isMarkdown","src","handleVSCodePaste","vscode","vscodeData","defaultPasteHandler","prioritizeMarkdownOverHTML","plainTextAsMarkdown","plainText","createPasteFromClipboardExtension","pasteHandler","fragmentToBlocks","fragmentToExternalHTML","selectedFragment","isWithinBlockContent","isWithinTable","fragmentWithoutParents","externalHTMLExporter","selectedFragmentToHTML","clipboardHTML","checkIfSelectionInNonEditableBlock","copyToClipboard","createCopyToClipboardExtension","BackgroundColorExtension","EventEmitter","fn","args","callbacks","callback","BlockNoteExtension","_args","plugin","_CursorPlugin","collaboration","user","clientID","cursorData","cursorElement","cursor","updated","yCursorPlugin","defaultSelectionBuilder","caretElement","labelElement","CursorPlugin","SyncPlugin","ySyncPlugin","UndoPlugin","yUndoPlugin","CommentMark","UserStore","resolveUsers","userIds","missingUsers","users","userId","cb","SET_SELECTED_THREAD_ID","getUpdatedThreadPositions","markType","threadPositions","thisThreadId","currentPosition","CommentsPlugin","threadStore","threads","markThreadId","thread","isOrphan","trimmedFrom","trimmedTo","self","DecorationSet","action","decorations","selectedThreadPosition","Decoration","commentMark","threadId","scrollToThread","pmSelection","ystate","ySyncPluginKey","getRelativeSelection","FilePanelView","pluginKey","pmView","emitUpdate","blockElement","prevState","pluginState","prevPluginState","isOpening","isClosing","filePanelPluginKey","FilePanelProsemirrorPlugin","editorView","prev","FormattingToolbarView","empty","isEmptyTextBlock","isNodeSelection","focusedElement","editorWrapper","e","composing","isSame","ranges","shouldShow","jsdom","nextState","posToDOMRect","formattingToolbarPluginKey","FormattingToolbarProsemirrorPlugin","HardBreak","getParentBlockInfo","beforePos","parentBeforePos","getPrevBlockInfo","indexInParent","prevBlockBeforePos","getBottomNestedBlockInfo","group","newPos","canMerge","nextBlockInfo","mergeBlocks","childBlocksStart","childBlocksEnd","childBlocksRange","mergeBlocksCommand","posBetweenBlocks","bottomNestedBlockInfo","KeyboardShortcutsExtension","handleBackspace","selectionAtBlockStart","isParagraph","parentBlockInfo","columnList","shouldRemoveColumn","shouldRemoveColumnList","isFirstColumn","blockToMove","chainedCommands","lastCellParagraphEndPos","nonEditableBlockContentStartPos","blockContentStartPos","bottomBlock","handleDelete","childContainer","blockAtDocEnd","selectionAtBlockEnd","oldDepth","newDepth","withShift","blockEmpty","blockIndented","blockHardBreakShortcut","newBlockInsertionPos","newBlockContentPos","LinkToolbarView","hoveredLinkElement","posInHoveredLinkMark","resolvedPosInHoveredLinkMark","marksAtPos","getMarkRange","fromMouseOver","prevLinkMark","linkToolbarPluginKey","LinkToolbarProsemirrorPlugin","VALID_LINK_PROTOCOLS","DEFAULT_LINK_PROTOCOL","NodeSelectionKeyboardPlugin","PlaceholderPlugin","placeholders","uniqueEditorSelector","styleEl","nonce","styleSheet","getSelector","additionalSelectors","defaultPlaceholder","emptyPlaceholder","placeholder","blockTypeSelector","onlyBlockSelector","mustBeFocusedSelector","decs","nodeAttributes","PreviousBlockTypePlugin","timeout","_editorView","_prevState","currentTransactionOriginalOldBlockAttrs","oldNodes","findChildren","oldNodesById","oldNode","oldContentNode","newContentNode","newAttrs","oldAttrs","prevAttrs","decorationAttrs","nodeAttr","decoration","ShowSelectionPlugin","dec","enabled","getDraggableBlockFromElement","MultipleNodeSelection","Selection","$anchor","$head","_pos","fromResult","toResult","dragImageElement","blockPositionsFromSelection","beforeFirstBlockPos","afterLastBlockPos","selectionStartInBlockContent","selectionEndInBlockContent","minDepth","startFirstBlockPos","endLastBlockPos","setDragImage","parentClone","getElementIndex","parentElement","firstSelectedBlockIndex","lastSelectedBlockIndex","unsetDragImage","iframes","iframe","inheritedClasses","rootEl","dragStart","draggedBlockInSelection","multipleBlocksSelected","selectedSlice","PERCENTAGE_OF_BLOCK_WIDTH_CONSIDERED_SIDE_DROP","getBlockFromCoords","sideMenuDetection","adjustForColumns","elements","getBlockFromMousePos","mousePos","editorBoundingBox","mouseLeftOfEditor","mouseRightOfEditor","rect","SideMenuView","blockContentBoundingBox","parentEditorElement","evt","_event","editorOuterBoundingBox","cursorWithinEditor","sideMenuPluginKey","SideMenuProsemirrorPlugin","editorToMapping","getMapping","Mapping","trackPosition","side","ySyncPluginState","trackedMapLength","relativePosition","absolutePositionToRelativePosition","curYSyncPluginState","relativePositionToAbsolutePosition","findBlock","findParentNode","SuggestionMenuView","decorationNode","suggestionMenuPluginKey","menuName","next","started","stopped","SuggestionMenuProseMirrorPlugin","triggerCharacter","triggerCharacters","suggestionPluginTransactionMeta","trackedPosition","snippet","suggestionPluginState","blockNode","createSuggestionMenu","SuggestionAddMark","inline","SuggestionDeleteMark","SuggestionModificationMark","setHiddenDragImage","unsetHiddenDragImage","domCellAround","target","currentTarget","hideElements","selector","elementsToHide","TableHandlesView","tableRect","blockEl","tableBlock","pmNodeInfo","widgetContainer","belowTable","toRightOfTable","hideHandles","cellRect","boundedMouseCoords","tableCellElements","tableCellElement","emitStateUpdate","oldIndex","dispatchDecorationsTransaction","tableHandlesPluginKey","draggingState","newTable","columnWidth","rowCount","colCount","tableBody","TableHandlesProsemirrorPlugin","relativeStartCell","relativeEndCell","tableResolvedPos","startRowResolvedPos","startCellResolvedPos","endRowResolvedPos","endCellResolvedPos","direction","beforeState","addRowBefore","addRowAfter","addColumnBefore","addColumnAfter","deleteRow","deleteColumn","cellsToMerge","mergeCells","relativeCellToSplit","splitCell","$fromCell","$toCell","$fromRow","$toRow","$table","isSelectingTableCells","cellSelection","originalIndex","draggedCellOrientation","rowResolvedPos","cellResolvedPos","decorationPos","widget","TextAlignmentExtension","TextColorExtension","TrailingNode","__","shouldInsertNodeAtEnd","endPosition","_state","lastNode","lastContentNode","BlockAttributes","BlockContainer","HTMLAttr","blockOuter","blockHTMLAttributes","BlockGroup","blockGroupHTMLAttributes","Doc","ForkYDocPlugin","ytype","otherYdoc","ydoc","rootKey","ytypeItem","otherStructs","itemIndex","Y","originalFragment","forkedFragment","yCursorPluginKey","yUndoPluginKey","keepChanges","getBlockNoteExtensions","tiptapExtensions","getTipTapExtensions","ext","disableExtensions","LINKIFY_INITIALIZED","extensions","Gapcursor","Text","Link","styleSpec","inlineContentSpec","History","removeChild","wrapTableRows","f","newItems","prevTable","shouldApplyFix","nestedChild","container","nodeHasSingleChild","nodeHasInlineContent","nodeHasTableContent","_BlockNoteTipTapEditor","TiptapEditor","blockNoteEditor","contentComponent","cache","oldCreateAndFill","pmNodes","b","createDocument","EditorState","selectionHasChanged","focus","blur","markViews","EditorView","oldSetTimeout","BlockNoteTipTapEditor","blockNoteTipTapOptions","BlockNoteEditor","anyOpts","en","newOptions","dropCursor","_i","instance","uploadFile","collaborationEnabled","initialContent","TipTapNode","tiptapOptions","_j","_l","_k","_m","_o","_n","getSchema","command","activeTr","reverse","traverseBlockArray","blockArray","editable","undoCommand","undo","redoCommand","redo","updateSelection","includeSelectionChangedByRemote","forceSelectionVisible","raw","htmlToPaste","COLORS_DEFAULT","COLORS_DARK_MODE_DEFAULT","Exporter","_schema","mappings","inlineContentArray","nestingLevel","numberedListIndex","mappingFactory","emojiLoadingPromise","loadEmojiMart","emojiMartModule","emojiDataModule","emojiMart","emojiData","getDefaultEmojiPickerItems","emoji","combineByGroup","additionalItemsArray","combinedItems","additionalItems","additionalItem","lastItemWithSameGroup"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,SAASA,GAAiBC,GAAYC,IAAK,KAAK,WAAW;AACzD,QAAMC,IAAY,CAAC;AACZ,SAAAF,EAAM,OAAO,CAACG,MAAc;AAC3B,UAAAC,IAAMH,EAAGE,CAAI;AACZ,WAAA,OAAO,UAAU,eAAe,KAAKD,GAAME,CAAG,IACjD,KACCF,EAAKE,CAAG,IAAI;AAAA,EAAA,CAClB;AACH;AAKA,SAASC,GAAeC,GAAY;AAClC,QAAMC,IAAWD,EAAM;AAAA,IACrB,CAACE,GAASC,MAAkBH,EAAM,QAAQE,CAAE,MAAMC;AAAA,EACpD;AAEO,SADYV,GAAiBQ,CAAQ;AAE9C;AAEM,MAAAG,KAAWC,EAAU,OAAO;AAAA,EAChC,MAAM;AAAA;AAAA;AAAA,EAGN,UAAU;AAAA,EACV,aAAa;AACJ,WAAA;AAAA,MACL,eAAe;AAAA,MACf,OAAO,CAAC;AAAA,MACR,gBAAgB;AAAA,MAChB,YAAY,MAAM;AAEhB,YAAI,OAAO,SAAW,OAAgB,OAAe,gBAAgB;AACnE,gBAAMC,IAAe,OAAe;AAChC,iBAAAA,EAAY,WAAW,SACzBA,EAAY,SAAS,IAETA,EAAA,UAGPA,EAAY,OAAO,SAAS;AAAA,QAAA;AAGrC,eAAOC,GAAG;AAAA,MACZ;AAAA,MACA,mBAAmB;AAAA,IACrB;AAAA,EACF;AAAA,EACA,sBAAsB;AACb,WAAA;AAAA,MACL;AAAA,QACE,OAAO,KAAK,QAAQ;AAAA,QACpB,YAAY;AAAA,UACV,CAAC,KAAK,QAAQ,aAAa,GAAG;AAAA,YAC5B,SAAS;AAAA,YACT,WAAW,CAACC,MACVA,EAAQ,aAAa,QAAQ,KAAK,QAAQ,aAAa,EAAE;AAAA,YAC3D,YAAY,CAACC,MAAe;AAC1B,oBAAMC,IAAsB;AAAA,gBAC1B,CAAC,QAAQ,KAAK,QAAQ,aAAa,EAAE,GACnCD,EAAW,KAAK,QAAQ,aAAa;AAAA,cACzC;AACI,qBAAA,KAAK,QAAQ,iBACR;AAAA,gBACL,GAAGC;AAAA,gBACH,IAAID,EAAW,KAAK,QAAQ,aAAa;AAAA,cAC3C,IAEOC;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,wBAAwB;AACtB,QAAIC,IAAyB,MACzBC,IAAkB;AACf,WAAA;AAAA,MACL,IAAIC,EAAO;AAAA,QACT,KAAK,IAAIC,EAAU,UAAU;AAAA,QAC7B,mBAAmB,CAACC,GAAcC,GAAUC,MAAa;AAEvD,gBAAMC,IACJH,EAAa,KAAK,CAACI,MAAgBA,EAAY,UAAU,KACzD,CAACH,EAAS,IAAI,GAAGC,EAAS,GAAG,GACzBG,IACJ,KAAK,QAAQ,qBACbL,EAAa,KAAK,CAACM,MAAO;AACxB,gBAAIC,GAAIC;AACR,mBAAO,EAAG,GAAAA,KAAMD,IAAK,KAAK,SAAS,uBAAuB,QAC1DC,MAAO,WAEHA,EAAG,KAAKD,GAAID,CAAE;AAAA,UAAA,CACnB;AACC,cAAA,CAACH,KAAcE;AACjB;AAEI,gBAAA,EAAE,IAAAC,MAAOJ,GACT,EAAE,OAAAO,GAAO,eAAAC,GAAe,YAAAC,MAAe,KAAK,SAC5CC,IAAYC;AAAA,YAChBZ,EAAS;AAAA,YACTD;AAAA,UACF,GACM,EAAE,SAAAc,MAAYF;AAuEhB,cArEYG,GAAiBH,CAAS,EAElC,QAAQ,CAAC,EAAE,UAAAI,QAAe;AAChC,kBAAMC,IAAWC;AAAA,cACfhB,EAAS;AAAA,cACTc;AAAA,cACA,CAACG,MACQV,EAAM,SAASU,EAAK,KAAK,IAAI;AAAA,YAExC,GACMC,IAASH,EACZ,IAAI,CAAC,EAAE,MAAAE,EAAW,MAAAA,EAAK,MAAMT,CAAa,CAAC,EAC3C,OAAO,CAACW,MAAOA,MAAO,IAAI,GACvBC,IAAmBtC,GAAeoC,CAAM;AAC9C,YAAAH,EAAS,QAAQ,CAAC,EAAE,MAAAE,GAAM,KAAAI,QAAU;AAC9B,kBAAAhB;AAKJ,oBAAMc,KACHd,IAAKD,EAAG,IAAI,OAAOiB,CAAG,OAAO,QAAQhB,MAAO,SACzC,SACAA,EAAG,MAAMG,CAAa;AAC5B,kBAAIW,MAAO,MAAM;AAIf,sBAAMG,IAAavB,EAAS,IAAI,KAAK,cAAiB,EAAA;AAItD,oBAFEA,EAAS,IAAI,QAAQ,cAAcuB,CAAU,MAAM,MAErC;AAEd,wBAAMC,KAAW,KAAK;AAAA,oBACpB,KAAK,UAAUvB,EAAS,IAAI,OAAQ,CAAA;AAAA,kBACtC;AAIE,sBAHFuB,GAAS,QAAQ,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,kBAGxC,KAAK,UAAUA,GAAS,OAAO,MAC/B,KAAK,UAAUD,EAAW,OAAO,CAAC,GAClC;AAEG,oBAAAlB,EAAA,cAAciB,GAAK,QAAW;AAAA,sBAC/B,GAAGJ,EAAK;AAAA,sBACR,CAACT,CAAa,GAAG;AAAA,oBAAA,CAClB;AACD;AAAA,kBAAA;AAAA,gBACF;AAGC,gBAAAJ,EAAA,cAAciB,GAAK,QAAW;AAAA,kBAC/B,GAAGJ,EAAK;AAAA,kBACR,CAACT,CAAa,GAAGC,EAAW;AAAA,gBAAA,CAC7B;AACD;AAAA,cAAA;AAGF,oBAAM,EAAE,SAAAe,EAAQ,IAAIZ,EAAQ,OAAO,EAAE,UAAUS,CAAG;AAElD,cADgBG,KAAWJ,EAAiB,SAASD,CAAE,KAElDf,EAAA,cAAciB,GAAK,QAAW;AAAA,gBAC/B,GAAGJ,EAAK;AAAA,gBACR,CAACT,CAAa,GAAGC,EAAW;AAAA,cAAA,CAC7B;AAAA,YACH,CACD;AAAA,UAAA,CACF,GACG,EAACL,EAAG,MAAM;AAGP,mBAAAA;AAAA,QACT;AAAA;AAAA,QAEA,KAAKqB,GAAM;AACH,gBAAAC,IAAkB,CAACC,MAAe;AAClC,gBAAAtB;AACJ,YAAAX,IACG,GAAAW,IAAKoB,EAAK,IAAI,mBAAmB,QAAQpB,MAAO,WAE7CA,EAAG,SAASsB,EAAM,MAAM,IAE1BF,EAAK,IAAI,gBACT;AAAA,UACN;AACO,wBAAA,iBAAiB,aAAaC,CAAe,GAC7C;AAAA,YACL,UAAU;AACD,qBAAA,oBAAoB,aAAaA,CAAe;AAAA,YAAA;AAAA,UAE3D;AAAA,QACF;AAAA,QACA,OAAO;AAAA;AAAA;AAAA;AAAA,UAIL,iBAAiB;AAAA;AAAA;AAAA,YAGf,MAAM,CAACD,GAAME,MAAe;AACtB,kBAAAtB;AACJ,qBACEX,MAAsB+B,EAAK,IAAI,mBAC7BpB,IAAKsB,EAAM,kBAAkB,QAAQtB,MAAO,SAC1C,SACAA,EAAG,mBAAmB,SAERV,IAAA,KAEAA,IAAA,IAGAD,IAAA,MAEb;AAAA,YACT;AAAA;AAAA,YAEA,OAAO,OACaC,IAAA,IACX;AAAA,UAEX;AAAA;AAAA;AAAA,UAGA,iBAAiB,CAACiC,MAAU;AAC1B,gBAAI,CAACjC;AACI,qBAAAiC;AAET,kBAAM,EAAE,OAAArB,GAAO,eAAAC,EAAc,IAAI,KAAK,SAChCqB,IAAW,CAACC,MAAkB;AAClC,oBAAMC,IAAc,CAAC;AACZ,qBAAAD,EAAA,QAAQ,CAACb,MAAc;AAE9B,oBAAIA,EAAK,QAAQ;AACf,kBAAAc,EAAK,KAAKd,CAAI;AACd;AAAA,gBAAA;AAGF,oBAAI,CAACV,EAAM,SAASU,EAAK,KAAK,IAAI,GAAG;AACnC,kBAAAc,EAAK,KAAKd,EAAK,KAAKY,EAASZ,EAAK,OAAO,CAAC,CAAC;AAC3C;AAAA,gBAAA;AAGI,sBAAAe,IAAgBf,EAAK,KAAK;AAAA,kBAC9B;AAAA,oBACE,GAAGA,EAAK;AAAA,oBACR,CAACT,CAAa,GAAG;AAAA,kBACnB;AAAA,kBACAqB,EAASZ,EAAK,OAAO;AAAA,kBACrBA,EAAK;AAAA,gBACP;AACA,gBAAAc,EAAK,KAAKC,CAAa;AAAA,cAAA,CACxB,GACMC,EAAS,KAAKF,CAAI;AAAA,YAC3B;AAEkB,mBAAApC,IAAA,IACX,IAAIuC;AAAA,cACTL,EAASD,EAAM,OAAO;AAAA,cACtBA,EAAM;AAAA,cACNA,EAAM;AAAA,YACR;AAAA,UAAA;AAAA,QACF;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC;ACzMM,SAASO,GACdC,GACoB;AACpB,SAAOA,EAAQ,SAAS;AAC1B;AAEO,SAASC,GACdD,GAC2B;AAC3B,SAAO,OAAOA,KAAY,YAAYA,EAAQ,SAAS;AACzD;AAEO,SAASE,GACdF,GAC0B;AAC1B,SAAO,OAAOA,KAAY,YAAYA,EAAQ,SAAS;AACzD;AClIO,SAASG,GAIdH,GAIiB;;AACV,SAAAI,GAAYJ,CAAO,IACtB,EAAE,GAAGA,MACLK,GAAmBL,CAAO,IACxB;AAAA,IACE,MAAM;AAAA,IACN,SAAU,CAA6B,EAAA,OAAOA,EAAQ,OAAc;AAAA,IACpE,OAAO;AAAA,MACL,mBAAiB/B,IAAA+B,EAAQ,UAAR,gBAAA/B,EAAe,oBAAmB;AAAA,MACnD,aAAWC,IAAA8B,EAAQ,UAAR,gBAAA9B,EAAe,cAAa;AAAA,MACvC,iBAAeoC,IAAAN,EAAQ,UAAR,gBAAAM,EAAe,kBAAiB;AAAA,MAC/C,WAASC,IAAAP,EAAQ,UAAR,gBAAAO,EAAe,YAAW;AAAA,MACnC,WAASC,IAAAR,EAAQ,UAAR,gBAAAQ,EAAe,YAAW;AAAA,IAAA;AAAA,EACrC,IAEF;AAAA,IACE,MAAM;AAAA,IACN,SAAU,CAAA,EAA6B,OAAOR,CAAc;AAAA,IAC5D,OAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,WAAW;AAAA,MACX,eAAe;AAAA,MACf,SAAS;AAAA,MACT,SAAS;AAAA,IAAA;AAAA,EAEb;AACR;AAEO,SAASK,GAIdL,GAMmC;AACnC,SAEEA,KAAY,QACZ,OAAOA,KAAY,YACnB,CAAC,MAAM,QAAQA,CAAO,KACtBA,EAAQ,SAAS;AAErB;AAEO,SAASI,GAIdJ,GAM4B;AAC5B,SACEK,GAAmBL,CAAO,KAC1BA,EAAQ,UAAU,UAClBA,EAAQ,YAAY;AAExB;AAEO,SAASS,GACdC,GAIQ;AACJ,SAAAN,GAAYM,CAAI,IACXA,EAAK,MAAM,WAAW,IAExB;AACT;AAEO,SAASC,GACdD,GAIQ;AACJ,SAAAN,GAAYM,CAAI,IACXA,EAAK,MAAM,WAAW,IAExB;AACT;AC7GO,MAAME,UAA6B,MAAM;AAAA,EAC9C,YAAYC,GAAY;AAChB,UAAA,qBAAqBA,CAAG,EAAE;AAAA,EAAA;AAEpC;AAEgB,SAAAC,GAAYC,GAA4BC,IAAa,IAAM;AACzE,QAAM,EAAE,aAAaC,GAAU,GAAGC,EAAS,IAAAH;AAE3C,MAAI,OAAO,KAAKG,CAAI,EAAE,SAAS,KAAKF;AAClC,UAAM,IAAI,MAAM,0BAA0B,KAAK,UAAUD,CAAG,CAAC;AAEjE;ACZO,MAAMI,KAAY,MACvB,OAAO,YAAc,QACpB,MAAM,KAAK,UAAU,QAAQ,KAC3B,cAAc,KAAK,UAAU,SAAS,KACrC,cAAc,KAAK,UAAU,SAAS;AAE5B,SAAAC,EAAuBC,GAAkBC,IAAW,QAAQ;AAC1E,SAAIH,OACKE,EAAS,QAAQ,OAAO,GAAG,IAE3BA,EAAS,QAAQ,OAAOC,CAAQ;AAE3C;AAEO,SAASC,KAAmBC,GAAyC;AAC1E,SAAOA,EAAQ,OAAO,CAACC,MAAMA,CAAC,EAAE,KAAK,GAAG;AAC1C;AAEO,MAAMC,KAAW,MACtB,iCAAiC,KAAK,UAAU,SAAS;ACHpD,SAASC,EACdC,GACAC,GACAC,GACAC,GACA;AACM,QAAAC,IAAe,SAAS,cAAc,KAAK;AACjD,EAAAA,EAAa,YAAYT;AAAA,IACvB;AAAA,IACAO,EAA2B;AAAA,EAC7B,GACaE,EAAA,aAAa,qBAAqBJ,CAAS;AACxD,aAAW,CAACK,GAAWC,CAAK,KAAK,OAAO,QAAQJ,CAA0B;AACxE,IAAIG,MAAc,WACHD,EAAA,aAAaC,GAAWC,CAAK;AAIxC,QAAAC,IAAgB,SAAS,cAAcN,CAAO;AACpD,EAAAM,EAAc,YAAYZ;AAAA,IACxB;AAAA,IACAQ,EAA4B;AAAA,EAC9B;AACA,aAAW,CAACE,GAAWC,CAAK,KAAK,OAAO;AAAA,IACtCH;AAAA,EAAA;AAEA,IAAIE,MAAc,WACFE,EAAA,aAAaF,GAAWC,CAAK;AAI/C,SAAAF,EAAa,YAAYG,CAAa,GAE/B;AAAA,IACL,KAAKH;AAAA,IACL,YAAYG;AAAA,EACd;AACF;AAKa,MAAAC,KAAqB,CAKhCC,GACAC,MAIG;AACH,MAAIzD,IAAO0D,GAAYF,GAAOC,EAAO,QAAQ;AAEzC,EAAAzD,EAAK,KAAK,SAAS,qBAErBA,IAAOA,EAAK;AAGR,QAAA2D,IAAQF,EAAO,SAAS,MAAMzD,EAAK,KAAK,IAAI,EAAE,KAAK;AAEzD,MAAI2D,MAAU;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGI,QAAAC,IAAaD,EAAM3D,CAAI;AAE7B,MAAI,OAAO4D,KAAe,YAAY,EAAE,SAASA;AAC/C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGK,SAAAA;AAIT;AAMO,SAASC,GAAgBvF,GAAsB;AAC9C,QAAAwF,IAAaxF,EAAQ,iBAAiB,GAAG;AAC3C,MAAAwF,EAAW,SAAS,GAAG;AACnB,UAAAC,IAAiBD,EAAW,CAAC;AACnC,aAASE,IAAI,GAAGA,IAAIF,EAAW,QAAQE,KAAK;AACpC,YAAAC,IAAYH,EAAWE,CAAC;AACf,MAAAD,EAAA,aAAa,SAASE,EAAU,WAC/CA,EAAU,OAAO;AAAA,IAAA;AAAA,EACnB;AAEJ;AC3GO,MAAMC,IAAe;AAAA,EAC1B,iBAAiB;AAAA,IACf,SAAS;AAAA,EACX;AAAA,EACA,WAAW;AAAA,IACT,SAAS;AAAA,EACX;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,QAAQ,CAAC,QAAQ,UAAU,SAAS,SAAS;AAAA,EAAA;AAEjD,GAOaC,KAAiB,CAAC,mBAAmB,WAAW;ACvBtD,SAASC,GAAiBC,GAAqB;AACpD,SAAO,UAAUA,EAAI,QAAQ,mBAAmB,OAAO,EAAE,YAAY;AACvE;AAEO,SAASC,GAAgBC,GAAqB;AAC7C,QAAAC,IAAQD,EAAI,MAAM,GAAG;AAC3B,SACE,CAACC,EAAM;AAAA,EACPA,EAAMA,EAAM,SAAS,CAAC,MAAM,KAGrBD,IAEFC,EAAMA,EAAM,SAAS,CAAC;AAC/B;ACeO,SAASC,GAAkBC,GAAoC;AACpE,QAAMC,IAA8C,CAAC;AAE9C,gBAAA,QAAQD,CAAU,EACtB,OAAO,CAAC,CAACE,GAAMC,CAAK,MAAM,CAACV,GAAe,SAASS,CAAI,CAAC,EACxD,QAAQ,CAAC,CAACA,GAAME,CAAI,MAAM;AACzB,IAAAH,EAAiBC,CAAI,IAAI;AAAA,MACvB,SAASE,EAAK;AAAA,MACd,aAAa;AAAA;AAAA;AAAA;AAAA,MAIb,WAAW,CAACxG,MAAY;AACtB,cAAM+E,IAAQ/E,EAAQ,aAAa8F,GAAiBQ,CAAI,CAAC;AAEzD,YAAIvB,MAAU;AACL,iBAAA;AAGT,YACGyB,EAAK,YAAY,UAAaA,EAAK,SAAS,aAC5CA,EAAK,YAAY,UAAa,OAAOA,EAAK,WAAY;AAEvD,iBAAIzB,MAAU,SACL,KAGLA,MAAU,UACL,KAGF;AAGT,YACGyB,EAAK,YAAY,UAAaA,EAAK,SAAS,YAC5CA,EAAK,YAAY,UAAa,OAAOA,EAAK,WAAY,UACvD;AACM,gBAAAC,IAAW,WAAW1B,CAAK;AAIjC,iBAFE,CAAC,OAAO,MAAM0B,CAAQ,KAAK,OAAO,SAASA,CAAQ,IAG5CA,IAGF;AAAA,QAAA;AAGF,eAAA1B;AAAA,MACT;AAAA,MACA,YAAY,CAAC9E,MAEJA,EAAWqG,CAAI,MAAME,EAAK,UAC7B;AAAA,QACE,CAACV,GAAiBQ,CAAI,CAAC,GAAGrG,EAAWqG,CAAI;AAAA,MAAA,IAE3C,CAAC;AAAA,IAET;AAAA,EAAA,CACD,GAEID;AACT;AAIO,SAASK,GAOdC,GACAxB,GACAyB,GACAC,GACA;AAEI,MAAA,OAAOF,KAAW;AACpB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAEF,QAAM7E,IAAM6E,EAAO,GAIbG,IAFiBF,EAAa,MAAM,IAAI,QAAQ9E,CAAI,EAAE,KAAK,EAE1B,MAAM;AAE7C,MAAI,CAACgF;AACG,UAAA,IAAI,MAAM,uBAAuB;AAInC,QAAA5B,IAAQC,EAAO,SAAS2B,CAAe;AAMzC,MAAA5B,EAAM,SAAS2B;AACX,UAAA,IAAI,MAAM,2BAA2B;AAGtC,SAAA3B;AACT;AAMO,SAAS6B,GAId/G,GAKAgH,GACAC,GACAb,GACAc,IAAc,IACdC,GAKA;AAEM,QAAAtC,IAAe,SAAS,cAAc,KAAK;AAGjD,MAAIsC,MAAkB;AACpB,eAAW,CAACC,GAAMrC,CAAK,KAAK,OAAO,QAAQoC,CAAa;AACtD,MAAIC,MAAS,WACEvC,EAAA,aAAauC,GAAMrC,CAAK;AAK3C,EAAAF,EAAa,YAAYT;AAAA,IACvB;AAAA,KACA+C,KAAA,gBAAAA,EAAe,UAAS;AAAA,EAC1B,GAEatC,EAAA,aAAa,qBAAqBmC,CAAS;AAIxD,aAAW,CAACK,GAAMtC,CAAK,KAAK,OAAO,QAAQkC,CAAU,GAAG;AAEtD,UAAMK,IADOlB,EAAWiB,CAAI,EACF;AAC1B,IAAI,CAACxB,GAAe,SAASwB,CAAI,KAAKtC,MAAUuC,KAC9CzC,EAAa,aAAaiB,GAAiBuB,CAAI,GAAGtC,CAAK;AAAA,EACzD;AAGF,SAAImC,KACWrC,EAAA,aAAa,mBAAmB,EAAE,GAGpCA,EAAA,YAAY7E,EAAQ,GAAG,GAEhCA,EAAQ,eAAe,WACzBA,EAAQ,WAAW,YAAYoE;AAAA,IAC7B;AAAA,IACApE,EAAQ,WAAW;AAAA,EACrB,IAGK;AAAA,IACL,GAAGA;AAAA,IACH,KAAK6E;AAAA,EACP;AACF;AAaO,SAAS0C,EAQdC,GAAuD;AAChD,SAAAC,GAAK,OAAOD,CAAM;AAC3B;AAIgB,SAAAE,GACdF,GACAG,GAMA;AACO,SAAA;AAAA,IACL,QAAAH;AAAA,IACA,gBAAAG;AAAA,EACF;AACF;AAEgB,SAAAC,GAGdlG,GAAS0E,GAAeyB,GAA8C;AAC/D,SAAAH;AAAA,IACL;AAAA,MACE,MAAMhG,EAAK;AAAA,MACX,SAAUA,EAAK,OAAO,YAAY,YAC9B,WACAA,EAAK,OAAO,YAAY,cACtB,UACA;AAAA,MAKN,YAAA0E;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAA1E;AAAA,MACA,oBAAAmG;AAAA,MACA,gBAAgB5C;AAAA,MAChB,gBAAgBA;AAAA;AAAA,IAAA;AAAA,EAGpB;AACF;AAEO,SAAS6C,GAA8CC,GAAU;AACtE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAK,EAAE,IAAI,CAAC,CAACzI,GAAKyF,CAAK,MAAM,CAACzF,GAAKyF,EAAM,MAAM,CAAC;AAAA,EACjE;AACF;ACtNgB,SAAAiD,GAA2BC,GAAoB9C,GAAgB;AACpE,EAAA8C,EAAA,YAAY,CAAC7F,OAIhBA,EAAM,SAAS,eACjB,WAAW,MAAM;AACR,IAAA+C,EAAA,KAAK,IAAI,KAAK;AAAA,KACpB,EAAE,GAGA;AAEX;AAKgB,SAAA+C,GACdV,GACAW,GACA;AACA,QAAMC,IAAwB;AAAA,IAC5B;AAAA,MACE,KAAK,wBAAwBZ,EAAO,OAAO;AAAA,MAC3C,gBAAgB;AAAA,IAAA;AAAA,EAEpB;AAEA,SAAIW,KACFC,EAAM,KAAK;AAAA,IACT,KAAK;AAAA,IACL,SAAS1G,GAA4B;AAC/B,UAAA,OAAOA,KAAS;AACX,eAAA;AAGH,YAAA2G,IAAQF,KAAA,gBAAAA,EAAsBzG;AAEpC,aAAI2G,MAAU,SACL,KAGFA;AAAA,IAAA;AAAA,EACT,CACD,GAkBID;AACT;AAIgB,SAAAE,GAKdC,GACAC,GACA;AACA,QAAM9G,IAAO6F,EAA8B;AAAA,IACzC,MAAMgB,EAAY;AAAA,IAClB,SAAUA,EAAY,YAAY,WAC9B,YACA;AAAA,IACJ,OAAO;AAAA,IACP,YAAYA,EAAY,gBAAgB;AAAA,IACxC,WAAW;AAAA,IACX,gBAAgB;AACP,aAAApC,GAAkBoC,EAAY,UAAU;AAAA,IACjD;AAAA,IAEA,YAAY;AACH,aAAAL,GAAcK,GAAaC,EAAoB,KAAK;AAAA,IAC7D;AAAA,IAEA,WAAW,EAAE,gBAAAC,KAAkB;AAMvB,YAAAC,IAAM,SAAS,cAAc,KAAK;AACjC,aAAA3B;AAAA,QACL;AAAA,UACE,KAAK2B;AAAA,UACL,YAAYH,EAAY,YAAY,WAAWG,IAAM;AAAA,QACvD;AAAA,QACAH,EAAY;AAAA,QACZ,CAAC;AAAA,QACDA,EAAY;AAAA,QACZA,EAAY;AAAA,QACZE;AAAA,MACF;AAAA,IACF;AAAA,IAEA,cAAc;AACL,aAAA,CAAC,EAAE,QAAA9B,QAAa;;AAEf,cAAAxB,IAAS,KAAK,QAAQ,QAEtBD,IAAQwB;AAAA,UACZC;AAAA,UACAxB;AAAA,UACA,KAAK;AAAA,UACLoD,EAAY;AAAA,QACd,GAEMI,MACJ7H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC,GAEzC8H,IAASJ,EAAoB,OAAOtD,GAAcC,CAAM,GAExD8C,IAAqBlB;AAAA,UACzB6B;AAAA,UACA1D,EAAM;AAAA,UACNA,EAAM;AAAA,UACNqD,EAAY;AAAA,UACZI;AAAA,QACF;AAEI,eAAAJ,EAAY,iBAAiB,MACJP,GAAAC,GAAU,KAAK,MAAM,GAG3CA;AAAA,MACT;AAAA,IAAA;AAAA,EACF,CACD;AAEG,MAAAvG,EAAK,SAAS6G,EAAY;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGF,SAAOb,GAAwBa,GAAa;AAAA,IAC1C,MAAA7G;AAAA,IACA,gBAAgB,CAACwD,GAAOC,MAAW;;AACjC,YAAMwD,MACJ7H,IAAAY,EAAK,QAAQ,kBAAb,gBAAAZ,EAA4B,iBAAgB,CAAC,GAEzC8H,IAASJ,EAAoB,OAAOtD,GAAcC,CAAa;AAE9D,aAAA4B;AAAA,QACL6B;AAAA,QACA1D,EAAM;AAAA,QACNA,EAAM;AAAA,QACNqD,EAAY;AAAA,QACZA,EAAY;AAAA,QACZI;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA,IAGA,gBAAgB,CAACzD,GAAOC,MAAW;;AACjC,YAAMwD,MACJ7H,IAAAY,EAAK,QAAQ,kBAAb,gBAAAZ,EAA4B,iBAAgB,CAAC;AAE/C,UAAI8H,KAAS7H,IAAAyH,EAAoB,mBAApB,gBAAAzH,EAAA;AAAA,QAAAyH;AAAA,QACXtD;AAAA,QACAC;AAAA;AAEF,aAAIyD,MAAW,WACJA,IAAAJ,EAAoB,OAAOtD,GAAcC,CAAa,IAE1D4B;AAAA,QACL6B;AAAA,QACA1D,EAAM;AAAA,QACNA,EAAM;AAAA,QACNqD,EAAY;AAAA,QACZI;AAAA,MACF;AAAA,IAAA;AAAA,EACF,CACD;AACH;ACzMgB,SAAAE,EAAmBC,GAAWhH,GAAa;AACnD,QAAAiH,IAAOD,EAAI,QAAQhH,CAAG;AAI5B,MAAIiH,EAAK,aAAaA,EAAK,UAAU,KAAK,UAAU,SAAS;AACpD,WAAA;AAAA,MACL,eAAeA,EAAK;AAAA,MACpB,MAAMA,EAAK;AAAA,IACb;AAKF,MAAIC,IAAQD,EAAK,OACbrH,IAAOqH,EAAK,KAAKC,CAAK;AAC1B,SAAOA,IAAQ,KAAG;AAChB,QAAItH,EAAK,KAAK,UAAU,SAAS;AACxB,aAAA;AAAA,QACL,eAAeqH,EAAK,OAAOC,CAAK;AAAA,QAChC,MAAAtH;AAAA,MACF;AAGF,IAAAsH,KACOtH,IAAAqH,EAAK,KAAKC,CAAK;AAAA,EAAA;AASxB,QAAMC,IAAuC,CAAC;AAC1C,EAAAH,EAAA,YAAY,CAACpH,GAAMI,MAAQ;AAC7B,IAAIJ,EAAK,KAAK,UAAU,SAAS,KAC/BuH,EAA2B,KAAKnH,CAAG;AAAA,EACrC,CACD,GAGO,QAAA,KAAK,YAAYA,CAAG,uCAAuC;AAEnE,QAAMoH,IAAcJ,EAAI;AAAA,IACtBG,EAA2B,KAAK,CAACE,MAAaA,KAAYrH,CAAG,KAC3DmH,EAA2BA,EAA2B,SAAS,CAAC;AAAA,EACpE;AACO,SAAA;AAAA,IACL,eAAeC,EAAY;AAAA,IAC3B,MAAMA,EAAY;AAAA,EACpB;AACF;AAagB,SAAAE,GACd1H,GACA2H,GACW;AACX,MAAI,CAAC3H,EAAK,KAAK,UAAU,SAAS;AAChC,UAAM,IAAI;AAAA,MACR,8EAA8EA,EAAK,KAAK,IAAI;AAAA,IAC9F;AAGF,QAAM4H,IAAc5H,GACd6H,IAAmBF,GACnBG,IAAkBD,IAAmBD,EAAY,UAEjDG,IAA2B;AAAA,IAC/B,MAAMH;AAAA,IACN,WAAWC;AAAA,IACX,UAAUC;AAAA,EACZ;AAEI,MAAAF,EAAY,KAAK,SAAS,kBAAkB;AAC1C,QAAAzE,GACA6E;AA2BJ,QAzBYJ,EAAA,QAAQ,CAAC5H,GAAMiI,MAAW;AACpC,UAAIjI,EAAK,KAAK,KAAK,UAAU,gBAAgB;AAE3C,cAAMkI,IAAmBlI,GACnBmI,IAAwBN,IAAmBI,IAAS,GACpDG,IAAuBD,IAAwBnI,EAAK;AAE3C,QAAAmD,IAAA;AAAA,UACb,MAAM+E;AAAA,UACN,WAAWC;AAAA,UACX,UAAUC;AAAA,QACZ;AAAA,MACSpI,WAAAA,EAAK,KAAK,SAAS,cAAc;AAC1C,cAAMqI,IAAiBrI,GACjBsI,IAAsBT,IAAmBI,IAAS,GAClDM,IAAqBD,IAAsBtI,EAAK;AAEzC,QAAAgI,IAAA;AAAA,UACX,MAAMK;AAAA,UACN,WAAWC;AAAA,UACX,UAAUC;AAAA,QACZ;AAAA,MAAA;AAAA,IACF,CACD,GAEG,CAACpF;AACH,YAAM,IAAI;AAAA,QACR,6EAA6EyE,CAAW;AAAA,MAC1F;AAGK,WAAA;AAAA,MACL,kBAAkB;AAAA,MAClB,SAAAG;AAAA,MACA,cAAA5E;AAAA,MACA,gBAAgB6E;AAAA,MAChB,eAAe7E,EAAa,KAAK,KAAK;AAAA,IACxC;AAAA,EAAA,OACK;AACL,QAAI,CAAC4E,EAAQ,KAAK,KAAK,UAAU,gBAAgB;AAC/C,YAAM,IAAI;AAAA,QACR,oDAAoDA,EAAQ,IAAI;AAAA,MAClE;AAGK,WAAA;AAAA,MACL,kBAAkB;AAAA,MAClB,SAAAA;AAAA,MACA,gBAAgBA;AAAA,MAChB,eAAeA,EAAQ,KAAK,KAAK;AAAA,IACnC;AAAA,EAAA;AAEJ;AAYO,SAASS,GAAaC,GAAgD;AAC3E,SAAOf,GAA6Be,EAAQ,MAAMA,EAAQ,aAAa;AACzE;AASO,SAASC,GAA4BlB,GAA0B;AAChE,MAAA,CAACA,EAAY;AACf,UAAM,IAAI;AAAA,MACR,oDAAoDA,EAAY,GAAG;AAAA,IACrE;AAEF,SAAOE,GAA6BF,EAAY,WAAWA,EAAY,GAAG;AAC5E;AAQO,SAASmB,EAA0BC,GAAoB;AAC5D,QAAMH,IAAUtB,EAAmByB,EAAM,KAAKA,EAAM,UAAU,MAAM;AAEpE,SAAOJ,GAAaC,CAAO;AAC7B;AAQO,SAASI,GAA4B1J,GAAiB;AAC3D,QAAMsJ,IAAUtB,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,MAAM;AAE9D,SAAOqJ,GAAaC,CAAO;AAC7B;ACpPO,SAASK,EAAYC,GAA4B;AACtD,SAAI,SAASA,IACJA,EAAS,IAAI,KAAK,SAEpBA,EAAS,KAAK;AACvB;AAEA,SAASC,GAIPC,GAAgD;AAChD,SAAOA,EAAO,OAAO;AACvB;AAEO,SAASC,GAIdD,GAAgD;AACzC,SAAAD,GAAmBC,CAAM,EAAE;AAKpC;AAEO,SAASE,GACdF,GACS;AACF,SAAAC,GAAmBD,CAAM,EAAE;AACpC;AAEO,SAASG,GACdH,GACG;AACI,SAAAC,GAAmBD,CAAM,EAAE;AACpC;AAEO,SAASI,GAAsCJ,GAAmB;AAChE,SAAAC,GAAmBD,CAAM,EAAE;AACpC;AAEO,SAASK,GAAcL,GAAgB;AACrC,SAAAD,GAAmBC,CAAM,EAAE;AACpC;ACtBgB,SAAAM,GAGdC,GAAmBC,GAAwBC,GAAgB;;AAC3D,QAAMC,IAA0B;AAAA,IAC9B,MAAM;AAAA,IACN,cAAc,CAAC;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,MAAM,CAAA;AAAA,EACR,GAMMC,IAA4B,CAAC;AAEnC,EAAAJ,EAAY,QAAQ,QAAQ,CAACK,GAASC,GAASC,MAAa;AAC1D,UAAMC,IAAqC;AAAA,MACzC,OAAO,CAAA;AAAA,IACT;AAEA,IAAID,MAAa,KACPF,EAAA,QAAQ,QAAQ,CAACI,MAAa;AAChC,UAAAC,IAAWD,EAAS,MAAM;AAC1B,MAA0BC,KAAa,SAC9BA,IAAA,IAAI,MAAMD,EAAS,MAAM,WAAW,CAAC,EAAE,KAAK,MAAS,IAE9DN,EAAA,aAAa,KAAK,GAAGO,CAAQ;AAAA,IAAA,CAClC,GAGHF,EAAI,QAAQH,EAAQ,QAAQ,QAAQ,IAAI,CAACI,GAAUE,OAC5CP,EAAaG,CAAQ,MACXH,EAAAG,CAAQ,IAAI,CAAC,IAG5BH,EAAaG,CAAQ,EAAEI,CAAS,IAAIF,EAAS,KAAK,SAAS,eAoCpD;AAAA,MACL,MAAM;AAAA,MACN,SApCcA,EAAS,QAAQ,QAC9B;AAAA,QAAI,CAACG,MACJC,GAA2BD,GAAOX,GAAqBC,CAAW;AAAA,MAAA,EAKnE;AAAA,QACC,CAACY,GAAKC,MAAmB;AACnB,cAAA,CAACD,EAAI;AACA,mBAAAC;AAGT,gBAAMC,IAAOF,EAAIA,EAAI,SAAS,CAAC,GACzBG,IAAQF,EAAe,CAAC;AAG9B,iBACEE,KACApJ,GAA0BmJ,CAAI,KAC9BnJ,GAA0BoJ,CAAK,KAC/B,KAAK,UAAUD,EAAK,MAAM,MAAM,KAAK,UAAUC,EAAM,MAAM,KAGtDD,EAAA,QAAQ;AAAA,IAAOC,EAAM,MAC1BH,EAAI,KAAK,GAAGC,EAAe,MAAM,CAAC,CAAC,GAC5BD,MAELA,EAAA,KAAK,GAAGC,CAAc,GACnBD;AAAA,QACT;AAAA,QACA,CAAA;AAAA,MACF;AAAA,MAKA,OAAO;AAAA,QACL,SAASL,EAAS,MAAM;AAAA,QACxB,SAASA,EAAS,MAAM;AAAA,QACxB,iBAAiBA,EAAS,MAAM;AAAA,QAChC,WAAWA,EAAS,MAAM;AAAA,QAC1B,eAAeA,EAAS,MAAM;AAAA,MAAA;AAAA,IAElC,EACD,GAEGN,EAAA,KAAK,KAAKK,CAAG;AAAA,EAAA,CAClB;AAED,WAAShG,IAAI,GAAGA,IAAI4F,EAAa,QAAQ5F;AACvC,KAAI5E,IAAAwK,EAAa5F,CAAC,MAAd,QAAA5E,EAAiB,MAAM,CAACsL,MAAaA,OACnCf,EAAA,cAAcA,EAAI,cAAc,KAAK;AAI7C,WAAS3F,IAAI,GAAGA,MAAI3E,IAAAuK,EAAa,CAAC,MAAd,gBAAAvK,EAAiB,SAAQ2E;AAC3C,IAAI4F,KAAA,QAAAA,EAAc,MAAM,CAACI,MAAQA,EAAIhG,CAAC,OAChC2F,EAAA,cAAcA,EAAI,cAAc,KAAK;AAItC,SAAAA;AACT;AAKgB,SAAAU,GAGdb,GAAmBC,GAAwBC,GAAgB;AAC3D,QAAMvI,IAAmC,CAAC;AAC1C,MAAIwJ;AAIQ,SAAAnB,EAAA,QAAQ,QAAQ,CAACxJ,MAAS;AAGhC,QAAAA,EAAK,KAAK,SAAS,aAAa;AAClC,UAAI2K;AAEE,YAAAtJ,GAA0BsJ,CAAc;AAE1C,UAAAA,EAAe,QAAQ;AAAA;AAAA,iBACdzJ,GAAoByJ,CAAc;AAE3C,UAAAA,EAAe,QAAQA,EAAe,QAAQ,SAAS,CAAC,EAAE,QACxD;AAAA;AAAA;AAEI,gBAAA,IAAI,MAAM,YAAY;AAAA;AAIb,QAAAA,IAAA;AAAA,UACf,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,UACN,QAAQ,CAAA;AAAA,QACV;AAGF;AAAA,IAAA;AAGF,QAAI3K,EAAK,KAAK,SAAS,UAAUA,EAAK,KAAK,SAAS,QAAQ;AAC1D,UAAI,CAACyJ,EAAoBzJ,EAAK,KAAK,IAAI,GAAG;AAExC,gBAAQ,KAAK,oCAAoCA,EAAK,KAAK,IAAI;AAC/D;AAAA,MAAA;AAEF,MAAI2K,MACFxJ,EAAQ,KAAKwJ,CAAc,GACVA,IAAA,SAGXxJ,EAAA;AAAA,QACNyJ,GAA0B5K,GAAMyJ,GAAqBC,CAAW;AAAA,MAClE;AAEA;AAAA,IAAA;AAGF,UAAMmB,IAAoB,CAAC;AACvB,QAAAC;AAEO,eAAAC,KAAQ/K,EAAK;AAClB,UAAA+K,EAAK,KAAK,SAAS;AACV,QAAAD,IAAAC;AAAA,WACN;AACL,cAAMjF,IAAS4D,EAAYqB,EAAK,KAAK,IAAI;AACzC,YAAI,CAACjF,GAAQ;AACP,cAAAiF,EAAK,KAAK,KAAK;AAGjB;AAEF,gBAAM,IAAI,MAAM,SAASA,EAAK,KAAK,IAAI,2BAA2B;AAAA,QAAA;AAEhE,YAAAjF,EAAO,eAAe;AACvB,UAAA+E,EAAe/E,EAAO,IAAI,IAAI;AAAA,iBACtBA,EAAO,eAAe;AAC9B,UAAA+E,EAAe/E,EAAO,IAAI,IAAIiF,EAAK,MAAM;AAAA;AAEpC,gBAAA,IAAIhJ,EAAqB+D,EAAO,UAAU;AAAA,MAClD;AAMJ,IAAI6E,IAEEtJ,GAA0BsJ,CAAc,IACrCG,KAkBH3J,EAAQ,KAAKwJ,CAAc,GACVA,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAMG,EAAS,MAAM;AAAA,MACrB,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM9K,EAAK;AAAA,UACX,QAAA6K;AAAA,QAAA;AAAA,MACF;AAAA,IAEJ,KA1BE,KAAK,UAAUF,EAAe,MAAM,MAAM,KAAK,UAAUE,CAAM,IAG/DF,EAAe,QAAQ3K,EAAK,eAG5BmB,EAAQ,KAAKwJ,CAAc,GACVA,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAM3K,EAAK;AAAA,MACX,QAAA6K;AAAA,IACF,KAiBK3J,GAAoByJ,CAAc,MAEvCG,IAGEH,EAAe,SAASG,EAAS,MAAM,OAGvC,KAAK;AAAA,MACHH,EAAe,QAAQA,EAAe,QAAQ,SAAS,CAAC,EACrD;AAAA,IAAA,MACC,KAAK,UAAUE,CAAM,IAE3BF,EAAe,QAAQA,EAAe,QAAQ,SAAS,CAAC,EAAE,QACxD3K,EAAK,cAGP2K,EAAe,QAAQ,KAAK;AAAA,MAC1B,MAAM;AAAA,MACN,MAAM3K,EAAK;AAAA,MACX,QAAA6K;AAAA,IAAA,CACD,KAIH1J,EAAQ,KAAKwJ,CAAc,GACVA,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAMG,EAAS,MAAM;AAAA,MACrB,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM9K,EAAK;AAAA,UACX,QAAA6K;AAAA,QAAA;AAAA,MACF;AAAA,IAEJ,MAIF1J,EAAQ,KAAKwJ,CAAc,GACVA,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAM3K,EAAK;AAAA,MACX,QAAA6K;AAAA,IACF,MASCC,IAScH,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAMG,EAAS,MAAM;AAAA,MACrB,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM9K,EAAK;AAAA,UACX,QAAA6K;AAAA,QAAA;AAAA,MACF;AAAA,IAEJ,IAlBiBF,IAAA;AAAA,MACf,MAAM;AAAA,MACN,MAAM3K,EAAK;AAAA,MACX,QAAA6K;AAAA,IACF;AAAA,EAgBJ,CACD,GAEGF,KACFxJ,EAAQ,KAAKwJ,CAAc,GAGtBxJ;AACT;AAEgB,SAAAyJ,GAGd5K,GAAYyJ,GAAwBC,GAAqC;AACzE,MAAI1J,EAAK,KAAK,SAAS,UAAUA,EAAK,KAAK,SAAS;AAC5C,UAAA,IAAI,MAAM,YAAY;AAE9B,QAAM2G,IAAa,CAAC,GACdqE,IAAWvB,EACfzJ,EAAK,KAAK,IACZ;AACW,aAAA,CAAC0F,GAAMrC,CAAK,KAAK,OAAO,QAAQrD,EAAK,KAAK,GAAG;AACtD,QAAI,CAACgL;AACH,YAAM,MAAM,yCAAyChL,EAAK,KAAK,IAAI;AAGrE,UAAM0E,IAAasG,EAAS;AAE5B,IAAItF,KAAQhB,MACViC,EAAMjB,CAAI,IAAIrC;AAAA,EAChB;AAGE,MAAAlC;AAEA,SAAA6J,EAAS,YAAY,WACb7J,IAAAkJ;AAAA,IACRrK;AAAA,IACAyJ;AAAA,IACAC;AAAA,EACF,IAEUvI,IAAA,QAGD;AAAA,IACT,MAAMnB,EAAK,KAAK;AAAA,IAChB,OAAA2G;AAAA,IACA,SAAAxF;AAAA,EACF;AAEF;AAOO,SAAS8J,EAKdjL,GACAiJ,GACAiC,IAAuB/B,GAAeF,CAAM,GAC5CQ,IAAyBL,GAAuBH,CAAM,GACtDS,IAAiBL,GAAeJ,CAAM,GACtCkC,IAAa7B,GAAcL,CAAM,GACX;;AACtB,MAAI,CAACjJ,EAAK,KAAK,UAAU,SAAS;AAChC,UAAM,MAAM,+CAA+CA,EAAK,KAAK,IAAI;AAGrE,QAAAoL,IAAcD,KAAA,gBAAAA,EAAY,IAAInL;AAEpC,MAAIoL;AACK,WAAAA;AAGH,QAAAC,IAAY3D,GAA6B1H,GAAM,CAAC;AAEtD,MAAIE,IAAKmL,EAAU,QAAQ,KAAK,MAAM;AAGtC,EAAInL,MAAO,SACJA,IAAAhC,GAAS,QAAQ,WAAW;AAG7B,QAAAoN,IAAYJ,EAAYG,EAAU,aAAa;AAErD,MAAI,CAACC;AACG,UAAA,MAAM,uCAAuCD,EAAU,aAAa;AAG5E,QAAM1E,IAAa,CAAC;AACpB,aAAW,CAACjB,GAAMrC,CAAK,KAAK,OAAO,QAAQ;AAAA,IACzC,GAAGrD,EAAK;AAAA,IACR,GAAIqL,EAAU,mBAAmBA,EAAU,aAAa,KAAK,QAAQ,CAAA;AAAA,EAAC,CACvE,GAAG;AACF,UAAM3G,IAAa4G,EAAU;AAG3B,IAAA5F,KAAQhB,KACR,EAAEA,EAAWgB,CAAI,EAAE,YAAY,UAAarC,MAAU,YAEtDsD,EAAMjB,CAAI,IAAIrC;AAAA,EAChB;AAGI,QAAAwD,IAAcqE,EAAYG,EAAU,aAAa,GAEjDE,IAAmC,CAAC;AAC1C,GAAAnM,IAAAiM,EAAU,mBAAV,QAAAjM,EAA0B,KAAK,QAAQ,CAACgL,MAAU;AACvC,IAAAmB,EAAA;AAAA,MACPN;AAAA,QACEb;AAAA,QACAnB;AAAA,QACAiC;AAAA,QACAzB;AAAA,QACAC;AAAA,QACAyB;AAAA,MAAA;AAAA,IAEJ;AAAA,EAAA;AAGE,MAAAhK;AAEA,MAAA0F,EAAY,YAAY,UAAU;AAChC,QAAA,CAACwE,EAAU;AACP,YAAA,IAAI,MAAM,YAAY;AAEpB,IAAAlK,IAAAkJ;AAAA,MACRgB,EAAU,aAAa;AAAA,MACvB5B;AAAA,MACAC;AAAA,IACF;AAAA,EAAA,WACS7C,EAAY,YAAY,SAAS;AACtC,QAAA,CAACwE,EAAU;AACP,YAAA,IAAI,MAAM,YAAY;AAEpB,IAAAlK,IAAAoI;AAAA,MACR8B,EAAU,aAAa;AAAA,MACvB5B;AAAA,MACAC;AAAA,IACF;AAAA,EAAA,WACS7C,EAAY,YAAY;AACvB,IAAA1F,IAAA;AAAA;AAEJ,UAAA,IAAIY,EAAqB8E,EAAY,OAAO;AAGpD,QAAMrD,IAAQ;AAAA,IACZ,IAAAtD;AAAA,IACA,MAAM2G,EAAY;AAAA,IAClB,OAAAF;AAAA,IACA,SAAAxF;AAAA,IACA,UAAAoK;AAAA,EACF;AAEY,SAAAJ,KAAA,QAAAA,EAAA,IAAInL,GAAMwD,IAEfA;AACT;AAKO,SAASgI,GAKdpE,GACA6B,GACAiC,IAAuB/B,GAAeF,CAAM,GAC5CQ,IAAyBL,GAAuBH,CAAM,GACtDS,IAAiBL,GAAeJ,CAAM,GACtCkC,IAAa7B,GAAcL,CAAM,GACjC;AACA,QAAMwC,IAAiC,CAAC;AACpC,SAAArE,EAAA,WAAY,YAAY,CAACpH,OACpByL,EAAA;AAAA,IACLR;AAAA,MACEjL;AAAA,MACAiJ;AAAA,MACAiC;AAAA,MACAzB;AAAA,MACAC;AAAA,MACAyB;AAAA,IAAA;AAAA,EAEJ,GACO,GACR,GACMM;AACT;AAqBO,SAASC,GAKd/K,GACAsI,GACAiC,IAAuB/B,GAAeF,CAAM,GAC5CQ,IAAyBL,GAAuBH,CAAM,GACtDS,IAAiBL,GAAeJ,CAAM,GACtCkC,IAAkD7B,GAAcL,CAAM,GActE;AAES,WAAA0C,EACP3L,GACA4L,GACAC,GAKA;AACI,QAAA7L,EAAK,KAAK,SAAS;AACf,YAAA,IAAI,MAAM,YAAY;AAE9B,UAAMyL,IAAiC,CAAC;AACpC,QAAAK,GACAC;AAEJ,WAAA/L,EAAK,QAAQ,CAACgM,GAAgBlC,GAAS7L,MAAU;AAC3C,UAAA+N,EAAe,KAAK,SAAS;AACzB,cAAA,IAAI,MAAM,YAAY;AAE1B,UAAAA,EAAe,eAAe;AAChC;AAEF,UAAIA,EAAe,eAAe,KAAKA,EAAe,aAAa;AACjE,cAAM,IAAI;AAAA,UACR,4CAA4CA,EAAe;AAAA,QAC7D;AAGF,YAAMC,IAAehO,MAAU,GACzBiO,IAAcjO,MAAU+B,EAAK,aAAa;AAEhD,UAAIgM,EAAe,WAAY,KAAK,SAAS,cAAc;AAOzD,YAAI,CAACC;AACG,gBAAA,IAAI,MAAM,YAAY;AAE9B,cAAMtC,IAAMgC;AAAA,UACVK,EAAe;AAAA,UACf,KAAK,IAAI,GAAGJ,IAAY,CAAC;AAAA,UACzBM,IAAc,KAAK,IAAI,GAAGL,IAAU,CAAC,IAAI;AAAA,QAC3C;AACA,QAAAC,IAAkBnC,EAAI,iBAClBuC,MACFH,IAAgBpC,EAAI,gBAEf8B,EAAA,KAAK,GAAG9B,EAAI,MAAM;AACzB;AAAA,MAAA;AAGF,YAAMnG,IAAQyH;AAAA,QACZe;AAAA,QACA/C;AAAA,QACAiC;AAAA,QACAzB;AAAA,QACAC;AAAA,QACAyB;AAAA,MACF,GACMgB,IACJH,EAAe,aAAa,IAAIA,EAAe,MAAM,CAAC,IAAI;AAE5D,UAAII,IAAsC,CAAC;AAC3C,UAAID,GAAY;AACd,cAAMxC,IAAMgC;AAAA,UACVQ;AAAA,UACA;AAAA;AAAA,UACAD,IAAc,KAAK,IAAI,GAAGL,IAAU,CAAC,IAAI;AAAA,QAC3C;AACA,QAAAO,IAAczC,EAAI,QACduC,MACFH,IAAgBpC,EAAI;AAAA,MACtB;AAGF,MAAIuC,KAAe,CAACC,KAAcN,IAAU,MAC1CE,IAAgBvI,EAAM,KAGpByI,KAAgBL,IAAY,MAC9BE,IAAkBtI,EAAM,KAG1BiI,EAAO,KAAK;AAAA,QACV,GAAIjI;AAAA,QACJ,UAAU4I;AAAA,MAAA,CACX;AAAA,IAAA,CACF,GAEM,EAAE,QAAAX,GAAQ,iBAAAK,GAAiB,eAAAC,EAAc;AAAA,EAAA;AAG9C,MAAApL,EAAM,QAAQ,eAAe;AACxB,WAAA;AAAA,MACL,QAAQ,CAAC;AAAA,MACT,iBAAiB;AAAA,MACjB,eAAe;AAAA,IACjB;AAGE,MAAAA,EAAM,QAAQ,eAAe;AAC/B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGK,SAAAgL;AAAA,IACLhL,EAAM,QAAQ;AAAA,IACd,KAAK,IAAIA,EAAM,YAAY,GAAG,CAAC;AAAA,IAC/B,KAAK,IAAIA,EAAM,UAAU,GAAG,CAAC;AAAA,EAC/B;AACF;AChqBO,SAAS0L,GAId/N,GAIAgO,GACAC,GACA7H,GAIA;AAEQ,SAAApG,EAAA,IAAI,aAAa,4BAA4BgO,CAAiB,GAG/D,OAAA,QAAQC,CAAkB,EAC9B,OAAO,CAAC,CAAC5G,GAAMtC,CAAK,MAAM;AACnB,UAAAyB,IAAOJ,EAAWiB,CAAI;AAC5B,WAAOtC,MAAUyB,EAAK;AAAA,EACvB,CAAA,EACA,IAAI,CAAC,CAACa,GAAMtC,CAAK,MACT,CAACe,GAAiBuB,CAAI,GAAGtC,CAAK,CACtC,EACA,QAAQ,CAAC,CAACsC,GAAMtC,CAAK,MAAM/E,EAAQ,IAAI,aAAaqH,GAAMtC,CAAK,CAAC,GAE/D/E,EAAQ,eAAe,UACjBA,EAAA,WAAW,aAAa,iBAAiB,EAAE,GAG9CA;AACT;AAGO,SAASkO,GAGd1G,GAGA;AACO,SAAA;AAAA,IACL,WAAW,CAAC,EAAE,QAAArC,QAAa;AACnB,YAAA+D,IAAc/D,EAAO,MAAM,UAAU;AAE3C,aACEA,EAAO,MAAM,UAAU,SACvB+D,EAAY,KAAA,EAAO,KAAK,SAAS1B,EAAO,QACxC0B,EAAY,iBAAiB;AAAA,IAAA;AAAA,EAGnC;AACF;AAIgB,SAAAiF,GACd3G,GACAG,GACA;AACO,SAAA;AAAA,IACL,QAAAH;AAAA,IACA,gBAAAG;AAAA,EACF;AACF;AAEgB,SAAAyG,GAGd1M,GAAS0E,GAAe;AACjB,SAAA+H;AAAA,IACL;AAAA,MACE,MAAMzM,EAAK;AAAA,MACX,YAAA0E;AAAA,MACA,SAAS1E,EAAK,OAAO,YAAY,YAAY,WAAW;AAAA,IAC1D;AAAA,IACA;AAAA,MACE,MAAAA;AAAA,IAAA;AAAA,EAEJ;AACF;AAEO,SAAS2M,GACdtG,GACA;AACA,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAK,EAAE,IAAI,CAAC,CAACzI,GAAKyF,CAAK,MAAM,CAACzF,GAAKyF,EAAM,MAAM,CAAC;AAAA,EACjE;AACF;ACvDO,SAASuJ,GACd9G,GACgB;AACT,SAAA;AAAA,IACL;AAAA,MACE,KAAK,8BAA8BA,EAAO,IAAI;AAAA,MAC9C,gBAAgB,CAACxH,MAAY;AAC3B,cAAMuO,IAAcvO;AAEhB,eAAAuO,EAAY,QAAQ,iBAAiB,IAChCA,IAGFA,EAAY,cAAc,iBAAiB,KAAKA;AAAA,MAAA;AAAA,IACzD;AAAA,EAEJ;AACF;AAEgB,SAAAC,GAIdC,GACAC,GACsB;AAChB,QAAAhN,IAAO+F,GAAK,OAAO;AAAA,IACvB,MAAMgH,EAAoB;AAAA,IAC1B,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,YAAYA,EAAoB,YAAY;AAAA,IAC5C,MAAMA,EAAoB,YAAY;AAAA,IACtC,SAAUA,EAAoB,YAAY,WACtC,YACA;AAAA,IAEJ,gBAAgB;AACP,aAAAtI,GAAkBsI,EAAoB,UAAU;AAAA,IACzD;AAAA,IAEA,uBAAuB;AACrB,aAAOP,GAAkCO,CAAmB;AAAA,IAC9D;AAAA,IAEA,YAAY;AACV,aAAOH,GAA2BG,CAAmB;AAAA,IACvD;AAAA,IAEA,WAAW,EAAE,MAAA/M,KAAQ;AACb,YAAAyD,IAAS,KAAK,QAAQ,QAEtByD,IAAS8F,EAA4B;AAAA,QACzCpC;AAAA,UACE5K;AAAAA,UACAyD,EAAO,OAAO;AAAA,UACdA,EAAO,OAAO;AAAA,QAChB;AAAA;AAAA,QACA,MAAM;AAAA,QAEN;AAAA,QACAA;AAAA,MACF;AAEO,aAAA4I;AAAA,QACLnF;AAAA,QACA6F,EAAoB;AAAA,QACpB/M,EAAK;AAAA,QACL+M,EAAoB;AAAA,MACtB;AAAA,IACF;AAAA,IAEA,cAAc;AACZ,aAAO,CAAC,EAAE,MAAA/M,GAAM,QAAAiF,QAAa;AACrB,cAAAxB,IAAS,KAAK,QAAQ,QAEtByD,IAAS8F,EAA4B;AAAA,UACzCpC;AAAA,YACE5K;AAAAA,YACAyD,EAAO,OAAO;AAAA,YACdA,EAAO,OAAO;AAAA,UAChB;AAAA;AAAA,UACA,CAACwJ,MAAW;AACN,gBAAA,OAAOhI,KAAW;AACpB;AAGF,kBAAM9D,IAAU+L,EAAqB,CAACD,CAAM,GAAGxJ,EAAO,QAAQ;AAEvD,YAAAA,EAAA;AAAA,cAAS,CAACtE,MACfA,EAAG,YAAY8F,KAAUA,EAAO,IAAIjF,EAAK,UAAUmB,CAAO;AAAA,YAC5D;AAAA,UACF;AAAA,UACAsC;AAAA,QACF;AAEO,eAAA4I;AAAA,UACLnF;AAAA,UACA6F,EAAoB;AAAA,UACpB/M,EAAK;AAAA,UACL+M,EAAoB;AAAA,QACtB;AAAA,MACF;AAAA,IAAA;AAAA,EACF,CACD;AAEM,SAAAL;AAAA,IACL1M;AAAA,IACA+M,EAAoB;AAAA,EACtB;AACF;ACvJO,SAASI,GACdzI,GACY;AACZ,SAAIA,MAAe,YACV,CAAC,IAEH;AAAA,IACL,aAAa;AAAA,MACX,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW,CAACpG,MAAYA,EAAQ,aAAa,YAAY;AAAA,MACzD,YAAY,CAACC,MACXA,EAAW,gBAAgB,SACvB;AAAA,QACE,cAAcA,EAAW;AAAA,MAAA,IAE3B,CAAA;AAAA,IAAC;AAAA,EAEX;AACF;AAKO,SAAS6O,GAId9O,GAIA+O,GACAC,GACA5I,GAIA;AAEQ,SAAApG,EAAA,IAAI,aAAa,mBAAmB+O,CAAS,GAGjD3I,MAAe,YACTpG,EAAA,IAAI,aAAa,cAAcgP,CAAoB,GAGzDhP,EAAQ,eAAe,UACjBA,EAAA,WAAW,aAAa,iBAAiB,EAAE,GAG9CA;AACT;AAIgB,SAAAiP,GACdzH,GACAG,GACA;AACO,SAAA;AAAA,IACL,QAAAH;AAAA,IACA,gBAAAG;AAAA,EACF;AACF;AAEgB,SAAAuH,GAGdzC,GAASrG,GAAe;AACjB,SAAA6I;AAAA,IACL;AAAA,MACE,MAAMxC,EAAK;AAAA,MACX,YAAArG;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAAqG;AAAA,IAAA;AAAA,EAEJ;AACF;AAEO,SAAS0C,GAA8CpH,GAAU;AACtE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAK,EAAE,IAAI,CAAC,CAACzI,GAAKyF,CAAK,MAAM,CAACzF,GAAKyF,EAAM,MAAM,CAAC;AAAA,EACjE;AACF;ACtEO,SAASqK,GAAmB5H,GAAkC;AAC5D,SAAA;AAAA,IACL;AAAA,MACE,KAAK,qBAAqBA,EAAO,IAAI;AAAA,MACrC,gBAAgB,CAACxH,MAAY;AAC3B,cAAMuO,IAAcvO;AAEhB,eAAAuO,EAAY,QAAQ,iBAAiB,IAChCA,IAGFA,EAAY,cAAc,iBAAiB,KAAKA;AAAA,MAAA;AAAA,IACzD;AAAA,EAEJ;AACF;AAEgB,SAAAc,GACdC,GACAC,GACc;AACR,QAAA9C,IAAO+C,GAAK,OAAO;AAAA,IACvB,MAAMF,EAAY;AAAA,IAElB,gBAAgB;AACP,aAAAT,GAAuBS,EAAY,UAAU;AAAA,IACtD;AAAA,IAEA,YAAY;AACV,aAAOF,GAAmBE,CAAW;AAAA,IACvC;AAAA,IAEA,WAAW,EAAE,MAAA7C,KAAQ;AACf,UAAAgD;AAKA,UAAAH,EAAY,eAAe;AAE7B,QAAAG,IAAeF,EAAoB,OAAO;AAAA,eACjCD,EAAY,eAAe;AACpC,QAAAG,IAAeF,EAAoB,OAAO9C,EAAK,MAAM,WAAW;AAAA;AAE1D,cAAA,IAAIhJ,EAAqB6L,EAAY,UAAU;AAIhD,aAAAR;AAAA,QACLW;AAAA,QACAH,EAAY;AAAA,QACZ7C,EAAK,MAAM;AAAA,QACX6C,EAAY;AAAA,MACd;AAAA,IAAA;AAAA,EACF,CACD;AAED,SAAOL,GAAwBK,GAAa;AAAA,IAC1C,MAAA7C;AAAA,EAAA,CACD;AACH;ACqGO,SAASiD,GACdxK,GACe;AACf,QAAM,EAAE,QAAAyK,GAAQ,OAAAC,MAAUC,GAAqB3K,CAAK,GAO9C4K,IAAsB,IAAI,MAAMH,CAAM,EACzC,KAAK,EAAK,EACV,IAAI,MAAM,IAAI,MAAMC,CAAK,EAAE,KAAK,IAAI,CAAC,GAGlCG,IAAoB,CAACrE,GAAasE,MAAgB;AACtD,aAAStK,IAAIgG,GAAKhG,IAAIiK,GAAQjK;AAC5B,eAASuK,IAAID,GAAKC,IAAIL,GAAOK;AAC3B,YAAI,CAACH,EAAKpK,CAAC,EAAEuK,CAAC;AACZ,iBAAO,EAAE,KAAKvK,GAAG,KAAKuK,EAAE;AAK9B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,WAASvE,IAAM,GAAGA,IAAMxG,EAAM,QAAQ,KAAK,QAAQwG;AACxC,aAAAsE,IAAM,GAAGA,IAAM9K,EAAM,QAAQ,KAAKwG,CAAG,EAAE,MAAM,QAAQsE,KAAO;AAC7D,YAAAzM,IAAOP,GAAakC,EAAM,QAAQ,KAAKwG,CAAG,EAAE,MAAMsE,CAAG,CAAC,GACtDE,IAAU1M,GAAWD,CAAI,GACzB4M,IAAU7M,GAAWC,CAAI,GAKzB,EAAE,KAAK6M,GAAU,KAAKC,MAAaN,EAAkBrE,GAAKsE,CAAG;AAGnE,eAAStK,IAAI0K,GAAU1K,IAAI0K,IAAWF,GAASxK;AAC7C,iBAASuK,IAAII,GAAUJ,IAAII,IAAWF,GAASF,KAAK;AAClD,cAAIH,EAAKpK,CAAC,EAAEuK,CAAC;AAEX,kBAAM,IAAI;AAAA,cACR,sDAAsDvK,CAAC,IAAIuK,CAAC;AAAA,YAC9D;AAGG,UAAAH,EAAApK,CAAC,EAAEuK,CAAC,IAAI;AAAA,YACX,KAAAvE;AAAA,YACA,KAAAsE;AAAA,YACA,SAAAE;AAAA,YACA,SAAAC;AAAA,YACA,MAAA5M;AAAA,UACF;AAAA,QAAA;AAAA,IAEJ;AAMG,SAAAuM;AACT;AAOO,SAASQ,GACdC,GACgC;AAG1B,QAAAnR,wBAAW,IAAY;AAEtB,SAAAmR,EAAc,IAAI,CAAC7E,OAEjB;AAAA,IACL,OAAOA,EACJ,IAAI,CAACnI,MACAnE,EAAK,IAAImE,EAAK,MAAM,MAAMA,EAAK,GAAG,IAC7B,MAETnE,EAAK,IAAImE,EAAK,MAAM,MAAMA,EAAK,GAAG,GAC3BA,EAAK,KACb,EACA,OAAO,CAACA,MAAsCA,MAAS,EAAK;AAAA,EACjE,EACD;AACH;AASO,SAASiN,GAIdC,GAIAvL,GAIAqL,IAA+Bb,GAA0BxK,CAAK,GAG9D;AACA,WAASwL,IAAI,GAAGA,IAAIH,EAAc,QAAQG;AACxC,aAASpM,IAAI,GAAGA,IAAIiM,EAAcG,CAAC,EAAE,QAAQpM,KAAK;AAEhD,YAAMf,IAAOgN,EAAcG,CAAC,EAAEpM,CAAC;AAC/B,UACEf,EAAK,QAAQkN,EAAoB,OACjClN,EAAK,QAAQkN,EAAoB;AAEjC,eAAO,EAAE,KAAKC,GAAG,KAAKpM,GAAG,MAAMf,EAAK,KAAK;AAAA,IAC3C;AAIJ,QAAM,IAAI;AAAA,IACR,oEAAoEkN,EAAoB,GAAG,IAAIA,EAAoB,GAAG;AAAA,EACxH;AACF;AAOO,SAASZ,GACd3K,GAUA;AAEM,QAAAyK,IAASzK,EAAM,QAAQ,KAAK;AAGlC,MAAI0K,IAAQ;AACZ,SAAA1K,EAAM,QAAQ,KAAK,QAAQ,CAACwG,MAAQ;AAElC,QAAIiF,IAAW;AACX,IAAAjF,EAAA,MAAM,QAAQ,CAACnI,MAAS;AAC1B,MAAAoN,KAAYrN,GAAWC,CAAI;AAAA,IAAA,CAC5B,GAGOqM,IAAA,KAAK,IAAIA,GAAOe,CAAQ;AAAA,EAAA,CACjC,GAEM,EAAE,QAAAhB,GAAQ,OAAAC,EAAM;AACzB;AAOO,SAASgB,GAIdC,GAIA3L,GAIAqL,IAA+Bb,GAA0BxK,CAAK,GAKlD;;AACZ,QAAM4L,KACJhQ,IAAAyP,EAAcM,EAAoB,GAAG,MAArC,gBAAA/P,EAAyC+P,EAAoB;AAG/D,MAAKC;AAKE,WAAA;AAAA,MACL,KAAKA,EAAc;AAAA,MACnB,KAAKA,EAAc;AAAA,MACnB,MAAMA,EAAc;AAAA,IACtB;AACF;AAiCgB,SAAAC,GACd7L,GACA8L,GACA;;AACM,QAAAT,IAAgBb,GAA0BxK,CAAK;AAErD,MAAI8L,IAAmB,KAAKA,KAAoBT,EAAc;AAC5D,WAAO,CAAC;AAIV,MAAIU,IAAc;AAGlB,WAAS,IAAI,GAAG,IAAID,GAAkB,KAAK;AACzC,UAAMzN,KAAOzC,IAAAyP,EAAcU,CAAW,MAAzB,gBAAAnQ,EAA6B;AAE1C,QAAI,CAACyC;AACH,aAAO,CAAC;AAIV,IAAA0N,KAAe1N,EAAK;AAAA,EAAA;AAItB,QAAM2N,IAAQ,IAAI,MAAMX,EAAc,CAAC,EAAE,MAAM,EAC5C,KAAK,EAAK,EACV,IAAI,CAACY,GAAInB,MACDY;AAAA,IACL,EAAE,KAAKK,GAAa,KAAAjB,EAAI;AAAA,IACxB9K;AAAA,IACAqL;AAAA,EACF,CACD,EACA;AAAA,IACC,CAACa,MACCA,MAAM;AAAA,EACV;AAGF,SAAOF,EAAM,OAAO,CAAC3N,GAAM5D,MAEvBuR,EAAM,UAAU,CAAC,MAAM,EAAE,QAAQ3N,EAAK,OAAO,EAAE,QAAQA,EAAK,GAAG,MAAM5D,CAExE;AACH;AAiCgB,SAAA0R,GACdnM,GACAoM,GACA;;AACM,QAAAf,IAAgBb,GAA0BxK,CAAK;AAErD,MACEoM,IAAsB,KACtBA,KAAuBf,EAAc,CAAC,EAAE;AAExC,WAAO,CAAC;AAIV,MAAIgB,IAAc;AAGlB,WAAS,IAAI,GAAG,IAAID,GAAqB,KAAK;AAC5C,UAAM/N,KAAOzC,IAAAyP,EAAc,CAAC,MAAf,gBAAAzP,EAAmByQ;AAEhC,QAAI,CAAChO;AACH,aAAO,CAAC;AAIV,IAAAgO,KAAehO,EAAK;AAAA,EAAA;AAItB,QAAM2N,IAAQ,IAAI,MAAMX,EAAc,MAAM,EACzC,KAAK,EAAK,EACV,IAAI,CAACY,GAAIzF,MACDkF;AAAA,IACL,EAAE,KAAAlF,GAAK,KAAK6F,EAAY;AAAA,IACxBrM;AAAA,IACAqL;AAAA,EACF,CACD,EACA;AAAA,IACC,CAACa,MACCA,MAAM;AAAA,EACV;AAGF,SAAOF,EAAM,OAAO,CAAC3N,GAAM5D,MAEvBuR,EAAM,UAAU,CAAC,MAAM,EAAE,QAAQ3N,EAAK,OAAO,EAAE,QAAQA,EAAK,GAAG,MAAM5D,CAExE;AACH;AAOO,SAAS6R,GACdtM,GACAuM,GACAC,GACAnB,IAA+Bb,GAA0BxK,CAAK,GAC9B;AAG1B,QAAA,EAAE,KAAKyM,EAAA,IAAsBnB;AAAA,IACjC;AAAA,MACE,KAAK;AAAA,MACL,KAAKiB;AAAA,IACP;AAAA,IACAvM;AAAA,IACAqL;AAAA,EACF,GACM,EAAE,KAAKqB,EAAA,IAAsBpB;AAAA,IACjC;AAAA,MACE,KAAK;AAAA,MACL,KAAKkB;AAAA,IACP;AAAA,IACAxM;AAAA,IACAqL;AAAA,EACF;AAOc,SAAAA,EAAA,QAAQ,CAAC7E,MAAQ;AAE7B,UAAM,CAACmG,CAAU,IAAInG,EAAI,OAAOiG,GAAmB,CAAC;AAChD,IAAAjG,EAAA,OAAOkG,GAAmB,GAAGC,CAAU;AAAA,EAAA,CAC5C,GAEMvB,GAA8BC,CAAa;AACpD;AAOO,SAASuB,GACd5M,GACA6M,GACAC,GACAzB,IAA+Bb,GAA0BxK,CAAK,GAC9B;AAG1B,QAAA,EAAE,KAAK+M,EAAA,IAAsBzB;AAAA,IACjC;AAAA,MACE,KAAKuB;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA7M;AAAA,IACAqL;AAAA,EACF,GACM,EAAE,KAAK2B,EAAA,IAAsB1B;AAAA,IACjC;AAAA,MACE,KAAKwB;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA9M;AAAA,IACAqL;AAAA,EACF,GAOM,CAAC4B,CAAS,IAAI5B,EAAc,OAAO0B,GAAmB,CAAC;AAC/C,SAAA1B,EAAA,OAAO2B,GAAmB,GAAGC,CAAS,GAE7C7B,GAA8BC,CAAa;AACpD;AAOA,SAAS6B,GACP7O,GAGS;AACT,SAAKA,IAGDL,GAAmBK,CAAI,IAClB6O,GAAY7O,EAAK,OAAO,IACtB,OAAOA,KAAS,WAClBA,EAAK,WAAW,IACd,MAAM,QAAQA,CAAI,IACpBA,EAAK;AAAA,IAAM,CAACe,MACjB,OAAOA,KAAM,WACTA,EAAE,WAAW,IACbvB,GAA0BuB,CAAC,IACzBA,EAAE,KAAK,WAAW,IAClBxB,GAA2BwB,CAAC,IAC1B,OAAOA,EAAE,WAAY,WACnBA,EAAE,QAAQ,WAAW,IACrBA,EAAE,QAAQ,MAAM,CAAC+N,MAAMA,EAAE,KAAK,WAAW,CAAC,IAC5C;AAAA,EACV,IAEO,KAnBA;AAqBX;AAOO,SAASC,GACdpN,GACAqN,GACAhC,IAA+Bb,GAA0BxK,CAAK,GAC9B;AAChC,MAAIqN,MAAgB,WAAW;AAE7B,QAAIC,IAAmB;AAEjB,aAAA3G,IAAY0E,EAAc,CAAC,EAAE,SAAS,GAC1C1E,KAAa,KAGG0E,EAAc;AAAA,MAC5B,CAAC7E,MACC0G,GAAY1G,EAAIG,CAAS,EAAE,IAAI,KAAKH,EAAIG,CAAS,EAAE,YAAY;AAAA,IACnE,GALAA;AAUA,MAAA2G;AAGF,aAAS,IAAIjC,EAAc,SAAS,GAAG,KAAK,GAAG,KAAK;AAElD,YAAMkC,IAAgB,KAAK;AAAA,QACzBlC,EAAc,CAAC,EAAE,SAASiC;AAAA,QAC1B;AAAA,MACF;AACA,MAAAjC,EAAc,CAAC,IAAIA,EAAc,CAAC,EAAE,MAAM,GAAGkC,CAAa;AAAA,IAAA;AAG5D,WAAOnC,GAA8BC,CAAa;AAAA,EAAA;AAIpD,MAAImC,IAAoB;AACxB,WAASjH,IAAW8E,EAAc,SAAS,GAAG9E,KAAY,KACxC8E,EAAc9E,CAAQ,EAAE;AAAA,IACtC,CAAClI,MAAS6O,GAAY7O,EAAK,IAAI,KAAKA,EAAK,YAAY;AAAA,EACvD,GAH2DkI;AAQ3D,IAAAiH;AAIF,QAAMC,IAAe,KAAK,IAAID,GAAmBnC,EAAc,SAAS,CAAC;AAEzE,SAAAA,EAAc,OAAOA,EAAc,SAASoC,GAAcA,CAAY,GAE/DrC,GAA8BC,CAAa;AACpD;AAOO,SAASqC,GACd1N,GACA2N,GAMAC,GACAvC,IAA+Bb,GAA0BxK,CAAK,GAC9B;AAChC,QAAM,EAAE,OAAA0K,GAAO,QAAAD,MAAWE,GAAqB3K,CAAK;AAEpD,MAAI2N,MAAY;AAEA,IAAAtC,EAAA,QAAQ,CAAC7E,GAAKD,MAAa;AACvC,UAAIqH,KAAY;AACd,iBAASpN,IAAI,GAAGA,IAAIoN,GAAUpN;AAC5B,UAAAgG,EAAI,KAAK;AAAA,YACP,KAAKD;AAAA,YACL,KAAK,KAAK,IAAI,GAAGC,EAAI,IAAI,CAACgF,MAAMA,EAAE,GAAG,CAAC,IAAI;AAAA,YAC1C,SAAS;AAAA,YACT,SAAS;AAAA,YACT,MAAM1N,GAAa,EAAE;AAAA,UAAA,CACtB;AAAA;AAIH,QAAA0I,EAAI,OAAOkE,IAAQkD,GAAU,KAAKA,CAAQ;AAAA,IAC5C,CACD;AAAA,WAEGA,IAAW;AAEb,aAAS,IAAI,GAAG,IAAIA,GAAU,KAAK;AAC3B,YAAAC,IAAS,IAAI,MAAMnD,CAAK,EAAE,KAAK,IAAI,EAAE,IAAI,CAACoD,GAAGC,OAAc;AAAA,QAC/D,KAAKtD,IAAS;AAAA,QACd,KAAKsD;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,QACT,MAAMjQ,GAAa,EAAE;AAAA,MAAA,EACrB;AACF,MAAAuN,EAAc,KAAKwC,CAAM;AAAA,IAAA;AAAA,MAE7B,CAAWD,IAAW,KAEpBvC,EAAc,OAAOZ,IAASmD,GAAU,KAAKA,CAAQ;AAIzD,SAAOxC,GAA8BC,CAAa;AACpD;AAKgB,SAAA2C,GACdhO,GACAiO,GACAC,GACA;AAEM,QAAAC,IAActC,GAAoB7L,GAAOkO,CAAc;AAI7D,MAAI,CADmBC,EAAY,KAAK,CAAC9P,MAASC,GAAWD,EAAK,IAAI,IAAI,CAAC;AAElE,WAAA;AAGT,MAAI+P,IAAcF,GACdG,IAAgBH;AACR,SAAAC,EAAA,QAAQ,CAAC9P,MAAS;AACtB,UAAA2M,IAAU1M,GAAWD,EAAK,IAAI;AACpC,IAAA+P,IAAc,KAAK,IAAIA,GAAa/P,EAAK,MAAM2M,IAAU,CAAC,GAC1DqD,IAAgB,KAAK,IAAIA,GAAehQ,EAAK,GAAG;AAAA,EAAA,CACjD,GAGsB4P,IAAgBC,IAKnCA,MAAmBE,IACnBF,MAAmBG;AACzB;AAKgB,SAAAC,GACdtO,GACAiO,GACAM,GACA;AAEM,QAAAJ,IAAchC,GAAuBnM,GAAOuO,CAAiB;AAInE,MAAI,CADmBJ,EAAY,KAAK,CAAC9P,MAASD,GAAWC,EAAK,IAAI,IAAI,CAAC;AAElE,WAAA;AAGT,MAAImQ,IAAiBD,GACjBE,IAAmBF;AACX,SAAAJ,EAAA,QAAQ,CAAC9P,MAAS;AACtB,UAAA4M,IAAU7M,GAAWC,EAAK,IAAI;AACpC,IAAAmQ,IAAiB,KAAK,IAAIA,GAAgBnQ,EAAK,MAAM4M,IAAU,CAAC,GAChEwD,IAAmB,KAAK,IAAIA,GAAkBpQ,EAAK,GAAG;AAAA,EAAA,CACvD,GAGuB4P,IAAgBM,IAKpCA,MAAsBC,IACtBD,MAAsBE;AAC5B;AAOgB,SAAAC,GACdC,GACAC,GACA5O,GACA;AAEM,QAAA6O,IAA4BvD,GAAsBqD,GAAM3O,CAAK,GAG7D8O,IAA0BxD,GAAsBsD,GAAI5O,CAAK;AAGxD,SAAA6O,EAA0B,QAAQC,EAAwB;AACnE;AC31BA,SAASC,GACPC,GACAvJ,GACAS,GACApE,GACQ;AACR,QAAMmN,IAAgB,CAAC;AAEZ,aAAA,CAACC,GAAOrP,CAAK,KAAK,OAAO,QAAQmP,EAAW,UAAU,CAAA,CAAE,GAAG;AAC9D,UAAA1M,IAAS4D,EAAYgJ,CAAK;AAChC,QAAI,CAAC5M;AACH,YAAM,IAAI,MAAM,SAAS4M,CAAK,2BAA2B;AAGvD,QAAA5M,EAAO,eAAe;AACxB,MAAIzC,KACFoP,EAAM,KAAKxJ,EAAO,KAAKyJ,CAAK,CAAC;AAAA,aAEtB5M,EAAO,eAAe;AAC/B,MAAIzC,KACIoP,EAAA,KAAKxJ,EAAO,KAAKyJ,GAAO,EAAE,aAAarP,EAAA,CAAO,CAAC;AAAA;AAGjD,YAAA,IAAItB,EAAqB+D,EAAO,UAAU;AAAA,EAClD;AAKF,SAFwB,CAACR,KAAa,CAAC2D,EAAO,MAAM3D,CAAS,EAAE,KAAK,OASlEkN,EAAW,KAER,MAAM,OAAO,EAGb,OAAO,CAACG,MAASA,EAAK,SAAS,CAAC,EAEhC,IAAI,CAACA,MACAA,MAAS;AAAA,IACJ1J,EAAO,MAAM,UAAa,cAAc,IAExCA,EAAO,KAAK0J,GAAMF,CAAK,CAEjC,IAnBID,EAAW,KAAK,SAAS,IAC5B,CAACvJ,EAAO,KAAKuJ,EAAW,MAAMC,CAAK,CAAC,IACpC,CAAC;AAmBT;AAMA,SAASG,GACPC,GACA5J,GACAS,GACQ;AACR,QAAMoB,IAAW7B,EAAO,MAAM,KAAK,OAAO;AAAA,IACxC,MAAM4J,EAAK;AAAA,EAAA,CACZ;AAED,SAAOC,GAAuBD,EAAK,SAAS5J,GAAQS,CAAW,EAAE;AAAA,IAC/D,CAAC1J,MAAS;AACJ,UAAAA,EAAK,KAAK,SAAS;AACrB,eAAOA,EAAK,KAAK,CAAC,GAAGA,EAAK,OAAO8K,CAAQ,CAAC;AAGxC,UAAA9K,EAAK,KAAK,SAAS;AACd,eAAAA;AAEH,YAAA,IAAI,MAAM,sBAAsB;AAAA,IAAA;AAAA,EAE1C;AACF;AAMA,SAAS8S,GACP3R,GACA8H,GACAS,GACApE,GACQ;AACR,QAAMyN,IAAgB,CAAC;AAEnB,MAAA,OAAO5R,KAAY;AACf,WAAA4R,EAAA;AAAA,MACJ,GAAGR;AAAA,QACD,EAAgB,MAAMpR,GAAS,QAAQ,GAAG;AAAA,QAC1C8H;AAAA,QACAS;AAAA,QACApE;AAAA,MAAA;AAAA,IAEJ,GACOyN;AAGT,aAAWP,KAAcrR;AACjB,IAAA4R,EAAA;AAAA,MACJ,GAAGR,GAAkBC,GAAYvJ,GAAQS,GAAapE,CAAS;AAAA,IACjE;AAEK,SAAAyN;AACT;AAKO,SAAS7F,EAId/J,GACA8F,GACA3D,GACAoE,IAAiBL,GAAeJ,CAAM,GAC9B;AACR,QAAM8J,IAAgB,CAAC;AAEvB,aAAW5R,KAAWgC;AAChB,IAAA,OAAOhC,KAAY,WACf4R,EAAA;AAAA,MACJ,GAAGD,GAAuB3R,GAAS8H,GAAQS,GAAapE,CAAS;AAAA,IACnE,IACSlE,GAA2BD,CAAO,IAC3C4R,EAAM,KAAK,GAAGH,GAAYzR,GAAS8H,GAAQS,CAAW,CAAC,IAC9CrI,GAA0BF,CAAO,IACpC4R,EAAA;AAAA,MACJ,GAAGD,GAAuB,CAAC3R,CAAO,GAAG8H,GAAQS,GAAapE,CAAS;AAAA,IACrE,IAEMyN,EAAA;AAAA,MACJC,GAAkC7R,GAAS8H,GAAQS,CAAW;AAAA,IAChE;AAGG,SAAAqJ;AACT;AAKO,SAASE,GAIdC,GACAjK,GACAS,IAA2BL,GAAeJ,CAAM,GACxC;AACR,QAAMkK,IAAmB,CAAC,GAGpBC,IAAa,IAAI,MAAMF,EAAa,cAAc,CAAC,EAAE,KAAK,EAAI,GAE9DG,IAAa,IAAI,MAAMH,EAAa,cAAc,CAAC,EAAE,KAAK,EAAI,GAE9DI,IAAuCJ,EAAa,gBAAgB,CAAC;AAE3E,WAASnJ,IAAW,GAAGA,IAAWmJ,EAAa,KAAK,QAAQnJ,KAAY;AAChE,UAAAC,IAAMkJ,EAAa,KAAKnJ,CAAQ,GAChCwJ,IAAsB,CAAC,GACvBC,IAAcJ,EAAWrJ,CAAQ;AACvC,aAASI,IAAY,GAAGA,IAAYH,EAAI,MAAM,QAAQG,KAAa;AAC3D,YAAAtI,IAAOmI,EAAI,MAAMG,CAAS,GAC1BsJ,IAAcJ,EAAWlJ,CAAS,GAIlCuJ,IAA2B;AAIjC,UAAIvS,IAAoD;AAGxD,YAAMwS,IAAoB7E;AAAA,QACxB;AAAA,UACE,KAAK/E;AAAA,UACL,KAAKI;AAAA,QACP;AAAA,QACA,EAAiB,SAAS+I,EAAa;AAAA,MACzC;AAGI,UAAAU,IAA0CN,EAC5CK,EAAkB,GACpB,IACI,CAACL,EAAaK,EAAkB,GAAG,CAAC,IACpC;AAEJ,UAAK9R,EAEL,KAAW,OAAOA,KAAS;AACf,QAAAV,IAAA8H,EAAO,KAAKpH,CAAI;AAAA,eACjBL,GAAmBK,CAAI,GAAG;AACnC,QAAIA,EAAK,YACGV,IAAA+L;AAAA,UACRrL,EAAK;AAAA,UACLoH;AAAA,UACA;AAAA,UACAS;AAAA,QACF;AAEI,cAAA+E,IAAU7M,GAAWC,CAAI;AAE/B,QAAI4M,IAAU,MAEDmF,IAAA,IAAI,MAAMnF,CAAO,EAAE,KAAK,EAAK,EAAE,IAAI,CAAC6C,GAAGtN,MAEzCsP,EAAaK,EAAkB,MAAM3P,CAAC,KAAK,MACnD;AAAA,MACH;AAEU,QAAA7C,IAAA+L;AAAA,UACRrL;AAAA,UACAoH;AAAA,UACA;AAAA,UACAS;AAAA,QACF;AAGF,YAAMO,IAAWhB,EAAO,MACtBwK,KAAeD,IAAc,gBAAgB,WAC/C,EAAE;AAAA,QACA;AAAA,UACE,GAAIhS,GAAmBK,CAAI,IAAIA,EAAK,QAAQ,CAAC;AAAA,UAC7C,UAAA+R;AAAA,QACF;AAAA,QACA3K,EAAO,MAAM,eAAkB,cAAcyK,GAAOvS,CAAO;AAAA,MAC7D;AACA,MAAAoS,EAAY,KAAKtJ,CAAQ;AAAA,IAAA;AAGrB,UAAAJ,IAAUZ,EAAO,MAAM,SAAY,cAAc,IAAIsK,CAAW;AACtE,IAAAJ,EAAS,KAAKtJ,CAAO;AAAA,EAAA;AAEhB,SAAAsJ;AACT;AAEA,SAASH,GACPxP,GAGAyF,GACAS,GACA;AACI,MAAAF,GACArE,IAAO3B,EAAM;AAOjB,MAJI2B,MAAS,WACJA,IAAA,cAGL,CAAC8D,EAAO,MAAM9D,CAAI;AACpB,UAAM,IAAI,MAAM,aAAaA,CAAI,sBAAsB;AAGrD,MAAA,CAAC3B,EAAM;AACT,IAAAgG,IAAcP,EAAO,MAAM9D,CAAI,EAAE,cAAc3B,EAAM,KAAK;AAAA,WACjD,OAAOA,EAAM,WAAY,UAAU;AAC5C,UAAMuP,IAAQ7F;AAAA,MACZ,CAAC1J,EAAM,OAAO;AAAA,MACdyF;AAAA,MACA9D;AAAA,MACAuE;AAAA,IACF;AACA,IAAAF,IAAcP,EAAO,MAAM9D,CAAI,EAAE,cAAc3B,EAAM,OAAOuP,CAAK;AAAA,EACxD,WAAA,MAAM,QAAQvP,EAAM,OAAO,GAAG;AACvC,UAAMuP,IAAQ7F;AAAA,MACZ1J,EAAM;AAAA,MACNyF;AAAA,MACA9D;AAAA,MACAuE;AAAA,IACF;AACA,IAAAF,IAAcP,EAAO,MAAM9D,CAAI,EAAE,cAAc3B,EAAM,OAAOuP,CAAK;AAAA,EACxD,WAAAvP,EAAM,QAAQ,SAAS,gBAAgB;AAChD,UAAMuP,IAAQE,GAAoBzP,EAAM,SAASyF,GAAQS,CAAW;AACpE,IAAAF,IAAcP,EAAO,MAAM9D,CAAI,EAAE,cAAc3B,EAAM,OAAOuP,CAAK;AAAA,EAAA;AAEjE,UAAM,IAAIhR,EAAqByB,EAAM,QAAQ,IAAI;AAE5C,SAAAgG;AACT;AAKO,SAAS9F,GACdF,GACAyF,GACAS,IAA2BL,GAAeJ,CAAM,GAChD;AACA,MAAI/I,IAAKsD,EAAM;AAEf,EAAItD,MAAO,WACJA,IAAAhC,GAAS,QAAQ,WAAW;AAGnC,QAAMqN,IAAmB,CAAC;AAE1B,MAAI/H,EAAM;AACG,eAAA4G,KAAS5G,EAAM;AACxB,MAAA+H,EAAS,KAAK7H,GAAY0G,GAAOnB,GAAQS,CAAW,CAAC;AAQzD,MAHE,CAAClG,EAAM;AAAA,EACPyF,EAAO,MAAMzF,EAAM,IAAI,EAAE,UAAU,cAAc,GAE/B;AAGlB,UAAMgG,IAAcwJ;AAAA,MAClBxP;AAAA,MACAyF;AAAA,MACAS;AAAA,IACF,GAEMmK,IACJtI,EAAS,SAAS,IACdtC,EAAO,MAAM,WAAc,cAAc,IAAIsC,CAAQ,IACrD;AAEC,WAAAtC,EAAO,MAAM,eAAkB;AAAA,MACpC;AAAA,QACE,IAAA/I;AAAA,QACA,GAAGsD,EAAM;AAAA,MACX;AAAA,MACAqQ,IAAY,CAACrK,GAAaqK,CAAS,IAAIrK;AAAA,IACzC;AAAA,EAAA,OACF;AAAA,QAAWP,EAAO,MAAMzF,EAAM,IAAI,EAAE,UAAU,SAAS;AAErD,aAAOyF,EAAO,MAAMzF,EAAM,IAAI,EAAE;AAAA,QAC9B;AAAA,UACE,IAAAtD;AAAA,UACA,GAAGsD,EAAM;AAAA,QACX;AAAA,QACA+H;AAAA,MACF;AAEA,UAAM,IAAI;AAAA,MACR,cAAc/H,EAAM,IAAI;AAAA,IAC1B;AAAA;AAEJ;ACvWgB,SAAAsQ,EACd5T,GACAkH,GACmD;AACnD,MAAI2M,GACAC;AAmBA,MAjBJ5M,EAAI,WAAY,YAAY,CAACpH,GAAMI,MAE7B2T,IACK,KAIL,CAACE,GAAYjU,CAAI,KAAKA,EAAK,MAAM,OAAOE,IACnC,MAGI6T,IAAA/T,GACbgU,IAAgB5T,IAAM,GAEf,GACR,GAEG,EAAA2T,MAAe,UAAaC,MAAkB;AAI3C,WAAA;AAAA,MACL,MAAMD;AAAA,MACN,eAAAC;AAAA,IACF;AACF;AAEO,SAASC,GAAYjU,GAAqB;AACxC,SAAAA,EAAK,KAAK,UAAU,SAAS;AACtC;AA2EA,SAASkU,GAKPC,GACAC,GACS;AAIP,SAAAD,EAAO,OAAOC,EAAO,MACrBD,EAAO,SAASC,EAAO,QACvB,KAAK,UAAUD,EAAO,KAAK,MAAM,KAAK,UAAUC,EAAO,KAAK,KAC5D,KAAK,UAAUD,EAAO,OAAO,MAAM,KAAK,UAAUC,EAAO,OAAO;AAEpE;AAQO,SAASC,GAKdpV,GACAqV,IAAsC,IACI;AACtC,MAAAC,IAA4B,EAAE,MAAM,QAAQ;AAE5C,EAAAtV,EAAY,QAAQ,OAAO,IACpBsV,IAAA,EAAE,MAAM,QAAQ,IAChBtV,EAAY,QAAQ,SAAS,MAAM,SACnCsV,IAAA,EAAE,MAAM,OAAO,IACftV,EAAY,QAAQ,UAAU,IAC9BsV,IAAA;AAAA,IACP,MAAMtV,EAAY,QAAQ,UAAU,EAAE,OAAO,SAAS;AAAA,EACxD,IACSA,EAAY,QAAQ,SAAS,MAClCA,EAAY,QAAQ,SAAS,EAAE,sBACxBsV,IAAA;AAAA,IACP,MAAM;AAAA,EACR,IAESA,IAAA;AAAA,IACP,MAAM;AAAA,EACR;AAKE,QAAAC,IAAW1L,EAAY7J,CAAW,GAClCwV,IAAsB/U,GAAwBT,EAAY,QAAQ;AAAA,IACtEA;AAAA,IACA,GAAGqV;AAAA,EAAA,CACJ,GAEKI,IAAgB9U,GAAiB6U,CAAmB,GACpDE,IAAqBD,EACxB,QAAQ,CAACE,MACD7U;AAAA,IACL0U,EAAoB;AAAA,IACpBG,EAAM;AAAA,IACNX;AAAA,EACF,CACD,EACA,IAAI,CAAC,EAAE,MAAAjU,EAAW,MAAAiL,EAAYjL,GAAMwU,CAAQ,CAAC,GAE1CK,IAAqBH,EACxB,QAAQ,CAACE,MACD7U;AAAA,IACL0U,EAAoB;AAAA,IACpBG,EAAM;AAAA,IACNX;AAAA,EACF,CACD,EACA,IAAI,CAAC,EAAE,MAAAjU,EAAW,MAAAiL,EAAYjL,GAAMwU,CAAQ,CAAC,GAE1CM,IAAa,IAAI;AAAA,IACrBD,EAAmB,IAAI,CAACrR,MACf,CAACA,EAAM,IAAIA,CAAK,CACxB;AAAA,EACH,GACMuR,IAAa,IAAI;AAAA,IACrBJ,EAAmB,IAAI,CAACnR,MACf,CAACA,EAAM,IAAIA,CAAK,CACxB;AAAA,EACH,GAEMwR,IAAoD,CAAC;AAG3D,aAAW,CAAC9U,GAAIsD,CAAK,KAAKsR;AACxB,IAAKC,EAAW,IAAI7U,CAAE,KACpB8U,EAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAAxR;AAAA,MACA,QAAA+Q;AAAA,MACA,WAAW;AAAA,IAAA,CACZ;AAKL,aAAW,CAACrU,GAAIsD,CAAK,KAAKuR;AACxB,IAAKD,EAAW,IAAI5U,CAAE,KACpB8U,EAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAAxR;AAAA,MACA,QAAA+Q;AAAA,MACA,WAAW;AAAA,IAAA,CACZ;AAKL,aAAW,CAACrU,GAAIsD,CAAK,KAAKsR;AACpB,QAAAC,EAAW,IAAI7U,CAAE,GAAG;AAChB,YAAA+U,IAAYF,EAAW,IAAI7U,CAAE;AAG/B,MAAAgU,GAAoCe,GAAWzR,CAAK,KACtDwR,EAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,OAAAxR;AAAA,QACA,WAAAyR;AAAA,QACA,QAAAV;AAAA,MAAA,CACD;AAAA,IACH;AAIG,SAAAS;AACT;AC/PO,SAASE,GAKd/V,GACAgW,GACAC,GACAC,IAAgC,UACR;AACxB,QAAMnV,IACJ,OAAOkV,KAAmB,WAAWA,IAAiBA,EAAe,IACjEZ,IAAW1L,EAAY3J,CAAE,GACzBmW,IAAgBH,EAAe;AAAA,IAAI,CAAC3R,MACxCE,GAAYF,GAAOgR,CAAQ;AAAA,EAC7B,GAEM/L,IAAUqL,EAAY5T,GAAIf,EAAG,GAAG;AACtC,MAAI,CAACsJ;AACH,UAAM,IAAI,MAAM,iBAAiBvI,CAAE,YAAY;AAGjD,MAAIE,IAAMqI,EAAQ;AAClB,SAAI4M,MAAc,YAChBjV,KAAOqI,EAAQ,KAAK,WAGnBtJ,EAAA;AAAA,IACD,IAAIoW,GAAYnV,GAAKA,GAAK,IAAIa,EAAMD,EAAS,KAAKsU,CAAa,GAAG,GAAG,CAAC,CAAC;AAAA,EACzE,GAIuBA,EAAc;AAAA,IAAI,CAACtV,MACxCiL,EAAYjL,GAAMwU,CAAQ;AAAA,EAC5B;AAGF;ACxCgB,SAAAgB,GAKdrW,GACAsW,GACAN,GAIA;AACM,QAAAX,IAAW1L,EAAY3J,CAAE,GAGzBmW,IAAwBH,EAAe;AAAA,IAAI,CAAC3R,MAChDE,GAAYF,GAAOgR,CAAQ;AAAA,EAC7B,GAEMkB,IAAsB,IAAI;AAAA,IAC9BD,EAAe;AAAA,MAAI,CAACjS,MAClB,OAAOA,KAAU,WAAWA,IAAQA,EAAM;AAAA,IAAA;AAAA,EAE9C,GACMmS,IAAwC,CAAC,GAEzCC,IACJ,OAAOH,EAAe,CAAC,KAAM,WACzBA,EAAe,CAAC,IAChBA,EAAe,CAAC,EAAE;AACxB,MAAII,IAAc;AAiDd,MA/CJ1W,EAAG,IAAI,YAAY,CAACa,GAAMI,MAAQ;AAE5B,QAAAsV,EAAoB,SAAS;AACxB,aAAA;AAIT,QACE,CAAC1V,EAAK,KAAK,UAAU,SAAS,KAC9B,CAAC0V,EAAoB,IAAI1V,EAAK,MAAM,EAAE;AAE/B,aAAA;AAOT,QAHA2V,EAAc,KAAK1K,EAAYjL,GAAMwU,CAAQ,CAAC,GAC1BkB,EAAA,OAAO1V,EAAK,MAAM,EAAE,GAEpCmV,EAAe,SAAS,KAAKnV,EAAK,MAAM,OAAO4V,GAAgB;AAC3DE,YAAAA,IAAa3W,EAAG,IAAI;AACvB,MAAAA,EAAA,OAAOiB,GAAKkV,CAAa;AACtBS,YAAAA,IAAa5W,EAAG,IAAI;AAE1B,MAAA0W,KAAeC,IAAaC;AAAAA,IAAA;AAGxB,UAAAD,IAAa3W,EAAG,IAAI,UAIpBkI,IAAOlI,EAAG,IAAI,QAAQiB,IAAMyV,CAAW;AAC7C,IACExO,EAAK,KAAK,EAAE,KAAK,SAAS,gBAC1BA,EAAK,KAAKA,EAAK,QAAQ,CAAC,EAAE,KAAK,SAAS,SACxCA,EAAK,KAAK,EAAE,eAAe,IAE3BlI,EAAG,OAAOkI,EAAK,OAAA,GAAUA,EAAK,OAAO,IAErClI,EAAG,OAAOiB,IAAMyV,GAAazV,IAAMyV,IAAc7V,EAAK,QAAQ;AAE1D,UAAA+V,IAAa5W,EAAG,IAAI;AAC1B,WAAA0W,KAAeC,IAAaC,GAErB;AAAA,EAAA,CACR,GAGGL,EAAoB,OAAO,GAAG;AAChC,UAAMM,IAAc,CAAC,GAAGN,CAAmB,EAAE,KAAK;AAAA,CAAI;AAEhD,UAAA;AAAA,MACJ,qEACEM;AAAA,IACJ;AAAA,EAAA;AAQK,SAAA,EAAE,gBAJcV,EAAc;AAAA,IAAI,CAACtV,MACxCiL,EAAYjL,GAAMwU,CAAQ;AAAA,EAC5B,GAEyB,eAAAmB,EAAc;AACzC;AC5Ea,MAAAM,IAAqB,CAKhCC,GACA1S,MAEO,CAAC;AAAA,EACN,IAAArE;AAAA,EACA,UAAAgX;AAAA,OAKIA,KACYC,GAAAjX,GAAI+W,GAAgB1S,CAAK,GAElC;AAIJ,SAAS4S,GAKdjX,GACA+W,GACA1S,GACA6S,GACAC,GACA;AACA,QAAMjL,IAAY3C,GAA4BvJ,EAAG,IAAI,QAAQ+W,CAAc,CAAC,GAEtE1B,IAAW1L,EAAY3J,CAAE;AAE/B,MACEkX,MAAmB,UACnBC,MAAiB,UACjBD,IAAiBC;AAEX,UAAA,IAAI,MAAM,wCAAwC;AAK1D,QAAMC,IAAc/B,EAAS,MAAMnJ,EAAU,aAAa,GACpDmL,IAAchC,EAAS,MAAMhR,EAAM,QAAQ6H,EAAU,aAAa,GAClEoL,IAAqBD,EAAY,UAAU,SAAS,IACtDA,IACAhC,EAAS,MAAM;AAEnB,MAAInJ,EAAU,oBAAoBmL,EAAY,UAAU,cAAc,GAAG;AACvE,UAAME,IACJL,MAAmB,UACnBA,IAAiBhL,EAAU,aAAa,aACxCgL,IAAiBhL,EAAU,aAAa,WACpCgL,IAAiBhL,EAAU,aAAa,YAAY,IACpD,QAEAsL,IACJL,MAAiB,UACjBA,IAAejL,EAAU,aAAa,aACtCiL,IAAejL,EAAU,aAAa,WAClCiL,IAAejL,EAAU,aAAa,YAAY,IAClD;AAES,IAAAuL,GAAApT,GAAOrE,GAAIkM,CAAS,GAGnCwL;AAAA,MACErT;AAAA,MACArE;AAAA,MACAoX;AAAA,MACAC;AAAA,MACAnL;AAAA,MACAqL;AAAA,MACAC;AAAA,IACF;AAAA,EAAA,WACS,CAACtL,EAAU,oBAAoBmL,EAAY,UAAU,SAAS;AACxD,IAAAI,GAAApT,GAAOrE,GAAIkM,CAAS;AAAA,OAG9B;AAQL,UAAMyL,IAAgB7L,EAAYI,EAAU,QAAQ,MAAMmJ,CAAQ;AAC/D,IAAArV,EAAA;AAAA,MACDkM,EAAU,QAAQ;AAAA,MAClBA,EAAU,QAAQ;AAAA,MAClB3H;AAAA,QACE;AAAA,UACE,UAAUoT,EAAc;AAAA;AAAA,UACxB,GAAGtT;AAAA,QACL;AAAA,QACAgR;AAAA,MAAA;AAAA,IAEJ;AAEA;AAAA,EAAA;AAKF,EAAArV,EAAG,cAAckM,EAAU,QAAQ,WAAWoL,GAAoB;AAAA,IAChE,GAAGpL,EAAU,QAAQ,KAAK;AAAA,IAC1B,GAAG7H,EAAM;AAAA,EAAA,CACV;AACH;AAEA,SAASqT,GAKPrT,GACArE,GACAoX,GACAC,GACAnL,GAMAqL,GACAC,GACA;AACM,QAAAnC,IAAW1L,EAAY3J,CAAE;AAC/B,MAAIgC,IAA6B;AAGjC,MAAIqC,EAAM;AACJ,QAAA,OAAOA,EAAM,WAAY;AAEjB,MAAArC,IAAA+L;AAAA,QACR,CAAC1J,EAAM,OAAO;AAAA,QACdgR;AAAA,QACAgC,EAAY;AAAA,MACd;AAAA,aACS,MAAM,QAAQhT,EAAM,OAAO;AAGpC,MAAArC,IAAU+L,EAAqB1J,EAAM,SAASgR,GAAUgC,EAAY,IAAI;AAAA,aAC/DhT,EAAM,QAAQ,SAAS;AACtB,MAAArC,IAAA8R,GAAoBzP,EAAM,SAASgR,CAAQ;AAAA;AAErD,YAAM,IAAIzS,EAAqByB,EAAM,QAAQ,IAAI;AAAA;AAO/C,IAAA+S,EAAY,KAAK,YAAY,MAGtBC,EAAY,KAAK,YAAYD,EAAY,KAAK,YAEvDpV,IAAU,CAAC;AAYf,MAAIA,MAAY;AAEd,IAAAhC,EAAG,cAAckM,EAAU,aAAa,WAAWmL,GAAa;AAAA,MAC9D,GAAGnL,EAAU,aAAa,KAAK;AAAA,MAC/B,GAAG7H,EAAM;AAAA,IAAA,CACV;AAAA,WACQkT,MAAsB,UAAaC,MAAoB,QAAW;AAE3E,IAAAxX,EAAG,cAAckM,EAAU,aAAa,WAAWmL,GAAa;AAAA,MAC9D,GAAGnL,EAAU,aAAa,KAAK;AAAA,MAC/B,GAAG7H,EAAM;AAAA,IAAA,CACV;AAED,UAAMuT,IACJ1L,EAAU,aAAa,YAAY,KAAKqL,KAAqB,IACzDM,IACJ3L,EAAU,aAAa,YACvB,KACCsL,KAAmBtL,EAAU,aAAa,KAAK,QAAQ,OAKpD4L,IAAe9X,EAAG,IAAI,QAAQkM,EAAU,aAAa,SAAS,EAAE,OAChE6L,IAAa/X,EAAG,IAAI,QAAQ4X,CAAK,EAAE,OACnCI,IAAWhY,EAAG,IAAI,QAAQ6X,CAAG,EAAE;AAElC,IAAA7X,EAAA;AAAA,MACD4X;AAAA,MACAC;AAAA,MACA,IAAI/V;AAAA,QACFD,EAAS,KAAKG,CAAO;AAAA,QACrB+V,IAAaD,IAAe;AAAA,QAC5BE,IAAWF,IAAe;AAAA,MAAA;AAAA,IAE9B;AAAA,EAAA;AAKG,IAAA9X,EAAA;AAAA,MACDkM,EAAU,aAAa;AAAA,MACvBA,EAAU,aAAa;AAAA,MACvBmL,EAAY;AAAA,QACV;AAAA,UACE,GAAGnL,EAAU,aAAa,KAAK;AAAA,UAC/B,GAAG7H,EAAM;AAAA,QACX;AAAA,QACArC;AAAA,MAAA;AAAA,IAEJ;AAEJ;AAEA,SAASyV,GAIPpT,GAAoCrE,GAAekM,GAAsB;AACnE,QAAAmJ,IAAW1L,EAAY3J,CAAE;AAC/B,MAAIqE,EAAM,aAAa,UAAaA,EAAM,SAAS,SAAS,GAAG;AAC7D,UAAM4T,IAAa5T,EAAM,SAAS,IAAI,CAAC4G,MAC9B1G,GAAY0G,GAAOoK,CAAQ,CACnC;AAGD,QAAInJ,EAAU;AAIT,MAAAlM,EAAA;AAAA,QACD,IAAIoW;AAAA,UACFlK,EAAU,eAAe,YAAY;AAAA,UACrCA,EAAU,eAAe,WAAW;AAAA,UACpC,IAAIpK,EAAMD,EAAS,KAAKoW,CAAU,GAAG,GAAG,CAAC;AAAA,QAAA;AAAA,MAE7C;AAAA,SACK;AACD,UAAA,CAAC/L,EAAU;AACP,cAAA,IAAI,MAAM,YAAY;AAG3B,MAAAlM,EAAA;AAAA,QACDkM,EAAU,aAAa;AAAA,QACvBmJ,EAAS,MAAM,WAAc,cAAc,IAAI4C,CAAU;AAAA,MAC3D;AAAA,IAAA;AAAA,EACF;AAEJ;AAEO,SAASC,GAKdlY,GACAmY,GACArK,GACAoJ,GACAC,GACsB;AACtB,QAAMpW,IACJ,OAAOoX,KAAkB,WAAWA,IAAgBA,EAAc,IAC9D7O,IAAUqL,EAAY5T,GAAIf,EAAG,GAAG;AACtC,MAAI,CAACsJ;AACH,UAAM,IAAI,MAAM,iBAAiBvI,CAAE,YAAY;AAGjD,EAAAkW;AAAA,IACEjX;AAAA,IACAsJ,EAAQ;AAAA,IACRwE;AAAA,IACAoJ;AAAA,IACAC;AAAA,EACF;AAEM,QAAAiB,IAAqBpY,EAAG,IAC3B,QAAQsJ,EAAQ,gBAAgB,CAAC,EACjC,KAAK,GAEF+L,IAAW1L,EAAY3J,CAAE;AACxB,SAAA8L,EAAYsM,GAAoB/C,CAAQ;AACjD;AC3TA,SAASgD,GAA8BlZ,GAAsB;AAE3D,QAAMmZ,IACJ,MAAM,KAAKnZ,EAAQ,SAAS,EAAE;AAAA,IAC5B,CAACmZ,MAAc,CAACA,EAAU,WAAW,KAAK;AAAA,EAAA,KACvC,CAAC;AAEJ,EAAAA,EAAU,SAAS,IACbnZ,EAAA,YAAYmZ,EAAU,KAAK,GAAG,IAEtCnZ,EAAQ,gBAAgB,OAAO;AAEnC;AAEO,SAASoZ,GAKdjU,GACAN,GACAwU,GACAC,GACA;AACI,MAAA7E;AAGJ,MAAK5P;AAEL,QAAW,OAAOA,KAAiB;AACjC,MAAA4P,IAAQ7F,EAAqB,CAAC/J,CAAY,GAAGM,EAAO,QAAQ;AAAA,aACnD,MAAM,QAAQN,CAAY;AAC3B,MAAA4P,IAAA7F,EAAqB/J,GAAcM,EAAO,QAAQ;AAAA,aACjDN,EAAa,SAAS;AACvB,MAAA4P,IAAAE,GAAoB9P,GAAcM,EAAO,QAAQ;AAAA;AAEnD,YAAA,IAAI1B,EAAqBoB,EAAa,IAAI;AAAA,MAR1C,OAAA,IAAI,MAAM,0BAA0B;AAc5C,QAAM0U,IAAMF,EAAW,kBAAkB3W,EAAS,KAAK+R,CAAK,GAAG6E,CAAO;AAElE,SAAAC,EAAI,aAAa,KACnBL,GAA8BK,CAAkB,GAG3CA;AACT;AAOA,SAASC,GAKPjX,GACA4C,GACAD,GACAmU,GACAI,GACAC,GACAJ,GACA;;AACM,QAAAxQ,KAAMwQ,KAAA,gBAAAA,EAAS,aAAY,UAC3BK,IAAUxU,EAAO,SAAS,MAAM;AAEtC,MAAIkD,IAAQnD,EAAM;AAEd,MAAA,CAACA,EAAM,OAAO;AAChB,IAAAmD,IAAQ,CAAC;AACT,eAAW,CAAC/B,GAAME,CAAI,KAAK,OAAO;AAAA,MAChCrB,EAAO,OAAO,YAAYD,EAAM,IAAW,EAAE;AAAA,IAAA;AAEzC,MAAAsB,EAAK,YAAY,WAClB6B,EAAc/B,CAAI,IAAIE,EAAK;AAAA,EAEhC;AAGI,QAAAoT,KAAK7Y,KAAAD,IAAA6Y,EAAQ,SAAR,gBAAA7Y,EAAc,UAAd,gBAAAC,EAAA;AAAA,IAAAD;AAAA,IACT6Y,EAAQ,OAAO;AAAA,MACb,IAAIzU,EAAM;AAAA,MACV,GAAGmD;AAAA,IACJ,CAAA;AAAA,KAQG+M,IAAQ,MAAM,KAAKwE,EAAG,IAAI,UAAU,GAEpCvO,IAAMlG,EAAO,qBACjBD,EAAM,IACR,EAAE,eAAe,eAAe,EAAE,GAAGA,GAAO,OAAAmD,EAAA,GAAgBlD,CAAa,GAEnE0U,IAAkB/Q,EAAI,uBAAuB;AACnD,MAAIuC,EAAI,IAAI,UAAU,SAAS,kBAAkB,GAAG;AAClD,UAAMyO,IAA6B;AAAA,MACjC,GAAG1E;AAAA,MACH,GAAG,MAAM,KAAK/J,EAAI,IAAI,UAAU;AAAA,IAAA,EAChC;AAAA,MACA,CAACjE,MACCA,EAAK,KAAK,WAAW,MAAM,KAC3BA,EAAK,SAAS,uBACdA,EAAK,SAAS,qBACdA,EAAK,SAAS,4BACdA,EAAK,SAAS,oBACdA,EAAK,SAAS,aACdA,EAAK,SAAS,gBACdA,EAAK,SAAS;AAAA,IAClB;AAGA,eAAWA,KAAQ0S;AAChB,MAAAzO,EAAI,IAAI,WAA4B,aAAajE,EAAK,MAAMA,EAAK,KAAK;AAG3C,IAAA8R,GAAA7N,EAAI,IAAI,UAA0B,GAChEwO,EAAgB,OAAO,GAAG,MAAM,KAAKxO,EAAI,IAAI,UAAU,CAAC;AAAA,EAAA;AAExC,IAAAwO,EAAA,OAAOxO,EAAI,GAAG;AAG5B,MAAAA,EAAI,cAAcnG,EAAM,SAAS;AACnC,UAAM6U,IAAKX;AAAA,MACTjU;AAAA,MACAD,EAAM;AAAA;AAAA,MACNmU;AAAA,MACAC;AAAA,IACF;AAEI,IAAAjO,EAAA,WAAW,YAAY0O,CAAE;AAAA,EAAA;AAG/B,MAAIC;AAOJ,MANIP,EAA0B,IAAIvU,EAAM,IAAK,IAChC8U,IAAA,OACFN,EAA4B,IAAIxU,EAAM,IAAK,MACzC8U,IAAA,OAGTA,GAAU;AACR,UAAA7W,IAAAZ,EAAS,cAAT,gBAAAY,EAAoB,cAAa6W,GAAU;AACvC,YAAAxX,IAAOsG,EAAI,cAAckR,CAAQ;AAEvC,MAAIA,MAAa,SAAQ3R,KAAA,QAAAA,EAAO,WAASA,KAAA,gBAAAA,EAAO,WAAU,KACxD7F,EAAK,aAAa,SAAS6F,EAAM,QAAQ,EAAE,GAE7C9F,EAAS,OAAOC,CAAI;AAAA,IAAA;AAEhB,UAAAyX,IAAKnR,EAAI,cAAc,IAAI;AACjC,IAAAmR,EAAG,OAAOJ,CAAe,GAChBtX,EAAA,UAAW,YAAY0X,CAAE;AAAA,EAAA;AAElC,IAAA1X,EAAS,OAAOsX,CAAe;AAGjC,MAAI3U,EAAM,YAAYA,EAAM,SAAS,SAAS,GAAG;AACzC,UAAAgV,IAAgBpR,EAAI,uBAAuB;AAUjD,QATAqR;AAAA,MACED;AAAA,MACA/U;AAAA,MACAD,EAAM;AAAA,MACNmU;AAAA,MACAI;AAAA,MACAC;AAAA,MACAJ;AAAA,IACF,KAEElW,IAAAb,EAAS,cAAT,gBAAAa,EAAoB,cAAa,UACjCC,IAAAd,EAAS,cAAT,gBAAAc,EAAoB,cAAa;AAGjC,eACE+W,IAAAF,EAAc,eAAd,gBAAAE,EAA0B,cAAa,UACvCC,IAAAH,EAAc,eAAd,gBAAAG,EAA0B,cAAa;AAEvC,QAAA9X,EAAS,UAAW,UAAW,YAAY2X,EAAc,UAAW;AAIpE,IAAA/U,EAAO,SAAS,MAAMD,EAAM,IAAW,EAAE,UAAU,cAAc,IAEnE3C,EAAS,OAAO2X,CAAa,KAGzBI,IAAAjP,EAAA,eAAA,QAAAiP,EAAY,OAAOJ;AAAA,EACzB;AAEJ;AAEA,MAAMC,KAA4B,CAKhC5X,GACA4C,GACAgI,GACAkM,GACAI,GACAC,GACAJ,MACG;AACH,aAAWpU,KAASiI;AAClBqM,IAAAA;AAAAA,MACEjX;AAAA,MACA4C;AAAA,MACAD;AAAA,MACAmU;AAAA,MACAI;AAAA,MACAC;AAAA,MACAJ;AAAA,IACF;AAEJ,GAEaiB,KAA8B,CAKzCpV,GACAgI,GACAkM,GACAI,GACAC,GACAJ,MACG;AAEG,QAAA/W,MADM+W,KAAA,gBAAAA,EAAS,aAAY,UACZ,uBAAuB;AAE5C,SAAAa;AAAA,IACE5X;AAAA,IACA4C;AAAA,IACAgI;AAAA,IACAkM;AAAA,IACAI;AAAA,IACAC;AAAA,IACAJ;AAAA,EACF,GACO/W;AACT,GC1OaiY,KAA6B,CAKxC7P,GACAxF,MACG;AACG,QAAAkU,IAAaoB,GAAc,WAAW9P,CAAM;AAE3C,SAAA;AAAA,IACL,cAAc,CACZwC,GACAmM,MACG;AACH,YAAMoB,IAAOH;AAAA,QACXpV;AAAA,QACAgI;AAAA,QACAkM;AAAA,QACI,oBAAA,IAAY,CAAC,kBAAkB,CAAC;AAAA,QAChC,oBAAA,IAAY,CAAC,kBAAkB,eAAe,CAAC;AAAA,QACnDC;AAAA,MACF,GACM5Q,IAAM,SAAS,cAAc,KAAK;AACxC,aAAAA,EAAI,OAAOgS,CAAI,GACRhS,EAAI;AAAA,IACb;AAAA,IAEA,qBAAqB,CACnB1D,GACAsU,MACG;AACH,YAAMqB,IAAcvB;AAAA,QAClBjU;AAAA,QACAH;AAAA,QACAqU;AAAA,QACAC;AAAA,MACF,GAEMsB,IAAS,SAAS,cAAc,KAAK;AAC3C,aAAAA,EAAO,OAAOD,EAAY,UAAU,EAAI,CAAC,GAElCC,EAAO;AAAA,IAAA;AAAA,EAElB;AACF;AC7DO,SAASC,GAKd1V,GACAN,GACAwU,GACArS,GACAsS,GACA;AACI,MAAA7E;AAGJ,MAAK5P;AAEL,QAAW,OAAOA,KAAiB;AACjC,MAAA4P,IAAQ7F,EAAqB,CAAC/J,CAAY,GAAGM,EAAO,UAAU6B,CAAS;AAAA,aAC9D,MAAM,QAAQnC,CAAY;AACnC,MAAA4P,IAAQ7F,EAAqB/J,GAAcM,EAAO,UAAU6B,CAAS;AAAA,aAC5DnC,EAAa,SAAS;AACvB,MAAA4P,IAAAE,GAAoB9P,GAAcM,EAAO,QAAQ;AAAA;AAEnD,YAAA,IAAI1B,EAAqBoB,EAAa,IAAI;AAAA,MAR1C,OAAA,IAAI,MAAM,0BAA0B;AAgBrC,SAFKwU,EAAW,kBAAkB3W,EAAS,KAAK+R,CAAK,GAAG6E,CAAO;AAGxE;AAEA,SAASE,GAKPrU,GACAD,GACAmU,GACAyB,GACAxB,GACA;;AACA,QAAMK,IAAUxU,EAAO,SAAS,MAAM;AAEtC,MAAIkD,IAAQnD,EAAM;AAEd,MAAA,CAACA,EAAM,OAAO;AAChB,IAAAmD,IAAQ,CAAC;AACT,eAAW,CAAC/B,GAAME,CAAI,KAAK,OAAO;AAAA,MAChCrB,EAAO,OAAO,YAAYD,EAAM,IAAW,EAAE;AAAA,IAAA;AAEzC,MAAAsB,EAAK,YAAY,WAClB6B,EAAc/B,CAAI,IAAIE,EAAK;AAAA,EAEhC;AAII,QAAA6E,IADOlG,EAAO,qBAAqBD,EAAM,IAAW,EAAE,eAC3C,eAAe,EAAE,GAAGA,GAAO,OAAAmD,KAAgBlD,CAAa;AAYrE,MAVAD,EAAM,SAAS,sBAOjBmG,EAAI,IAAI,aAAa,cAAcyP,EAAU,UAAU,GAGrDzP,EAAI,cAAcnG,EAAM,SAAS;AACnC,UAAM6U,IAAKc;AAAA,MACT1V;AAAA,MACAD,EAAM;AAAA;AAAA,MACNmU;AAAA,MACAnU,EAAM;AAAA,MACNoU;AAAA,IACF;AACI,IAAAjO,EAAA,WAAW,YAAY0O,CAAE;AAAA,EAAA;AAK3B,MAFW5U,EAAO,SAAS,MAAMD,EAAM,IAAW,EAE3C,UAAU,SAAS,GAAG;AAC/B,QAAIA,EAAM,YAAYA,EAAM,SAAS,SAAS,GAAG;AAC/C,YAAM3C,IAAWwY;AAAA,QACf5V;AAAA,QACAD,EAAM;AAAA,QACNmU;AAAA,QACAC;AAAA,MACF;AAEI,OAAAxY,IAAAuK,EAAA,eAAA,QAAAvK,EAAY,OAAOyB;AAAA,IAAQ;AAEjC,WAAO8I,EAAI;AAAA,EAAA;AAIP,QAAAuO,KAAKzW,KAAApC,IAAA4Y,EAAQ,SAAR,gBAAA5Y,EAAc,UAAd,gBAAAoC,EAAA;AAAA,IAAApC;AAAA,IACT4Y,EAAQ,OAAO;AAAA,MACb,IAAIzU,EAAM;AAAA,MACV,GAAGmD;AAAA,IACJ,CAAA;AAAA;AAMA,UAAAjF,IAAAwW,EAAA,eAAA,QAAAxW,EAAY,YAAYiI,EAAI,MAE3BnG,EAAM,YAAYA,EAAM,SAAS,SAAS,OAC5C7B,IAAAuW,EAAG,eAAH,QAAAvW,EAAe;AAAA,IACb2X,GAA4B7V,GAAQD,EAAM,UAAUmU,GAAYC,CAAO;AAAA,MAGpEM,EAAG;AACZ;AAEA,SAASmB,GAKP5V,GACAgI,GACAkM,GACAC,GACA;AAEM,QAAA/W,MADM+W,KAAA,gBAAAA,EAAS,aAAY,UACZ,uBAAuB;AAE5C,MAAIwB,IAAY;AAChB,aAAW5V,KAASiI,GAAQ;AACtB,IAAAjI,EAAM,SAAS,qBACjB4V,MAEYA,IAAA;AAEd,UAAMG,IAAWzB;AAAA,MACfrU;AAAA,MACAD;AAAA,MACAmU;AAAA,MACAyB;AAAA,MACAxB;AAAA,IACF;AACA,IAAA/W,EAAS,YAAY0Y,CAAQ;AAAA,EAAA;AAGxB,SAAA1Y;AACT;AAEO,MAAMyY,KAA8B,CAKzC7V,GACAgI,GACAkM,GACAC,MACG;;AACH,QAAM4B,IAAU/V,EAAO,SAAS,MAAM,YAEhCgW,IAAKD,EAAQ,KAAM,MAAOA,EAAQ,OAAO,CAAA,CAAE,CAAC,GAK5C3Y,IAAWwY,GAAgB5V,GAAQgI,GAAQkM,GAAYC,CAAO;AAEjE,UAAAxY,IAAAqa,EAAA,eAAA,QAAAra,EAAY,YAAYyB,IAEpB4Y,EAAG;AACZ,GC7KaC,KAA+B,CAK1CzQ,GACAxF,MACG;AACG,QAAAkU,IAAaoB,GAAc,WAAW9P,CAAM;AAE3C,SAAA;AAAA,IACL,iBAAiB,CACfwC,GACAmM,MAEO0B,GAA4B7V,GAAQgI,GAAQkM,GAAYC,CAAO,EACnE;AAAA,EAEP;AACF,GCrCa+B,KAAqB,CAChCC,GACAC,MACG;AACH,QAAMC,IAAgBF,EAAc;AAAA,IAClCC;AAAA,EACF;AACA,MAAI,CAACC;AACI;AAGH,QAAAC,IAAiBH,EAAc,cAAc,YAAY,GACzDI,KAAUD,KAAA,gBAAAA,EAAgB,gBAAe;AAExC,SAAA,EAAE,eAAAD,GAAe,SAAAE,EAAQ;AAClC,GCZaC,KAAsB,CACjCzW,GACAC,GACAyW,GACAC,MACG;AACG,QAAAC,IAAgB,SAAS,cAAc,KAAK;AAClD,EAAAA,EAAc,YAAY;AAEpB,QAAAC,IAAoB,SAAS,cAAc,KAAK;AACtD,EAAAA,EAAkB,YAAY,2BAC1BF,IACFE,EAAkB,YAAYF,CAAU,IAExCE,EAAkB,YAChB,uQAEJD,EAAc,YAAYC,CAAiB;AAErC,QAAAC,IAAoB,SAAS,cAAc,GAAG;AACpD,EAAAA,EAAkB,YAAY,2BAC9BA,EAAkB,YAChBJ,KAAczW,EAAO,WAAW,YAAY,KAAK,iBACnD2W,EAAc,YAAYE,CAAiB;AAGrC,QAAAC,IAAgC,CAAC7Z,MAAsB;AAC3D,IAAAA,EAAM,eAAe;AAAA,EACvB,GAEM8Z,IAA4B,MAAM;AAC/B,IAAA/W,EAAA;AAAA,MAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,QACvC,OAAAD;AAAA,MACD,CAAA;AAAA,IACH;AAAA,EACF;AACc,SAAA4W,EAAA;AAAA,IACZ;AAAA,IACAG;AAAA,IACA;AAAA,EACF,GACcH,EAAA,iBAAiB,SAASI,GAA2B,EAAI,GAEhE;AAAA,IACL,KAAKJ;AAAA,IACL,SAAS,MAAM;AACC,MAAAA,EAAA;AAAA,QACZ;AAAA,QACAG;AAAA,QACA;AAAA,MACF,GACcH,EAAA;AAAA,QACZ;AAAA,QACAI;AAAA,QACA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF,GC5DaC,KAAgB,uQAEhBC,KAAyB,CACpClX,MAC+C;AACzC,QAAAmX,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY;AAEX,QAAAC,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,gBACjBA,EAAK,YAAYH,IACjBE,EAAK,YAAYC,CAAI;AAEf,QAAAC,IAAW,SAAS,cAAc,GAAG;AAC3C,SAAAA,EAAS,YAAY,gBACZA,EAAA,cAAcrX,EAAM,MAAM,MACnCmX,EAAK,YAAYE,CAAQ,GAElB;AAAA,IACL,KAAKF;AAAA,EACP;AACF,GCdaG,KAAyB,CACpCtX,GACAC,GAKAnF,GACA4b,GACAC,MACG;AACG,QAAAY,IAAU,SAAS,cAAc,KAAK;AAKxC,MAJJA,EAAQ,YAAY,iCAIhBvX,EAAM,MAAM,QAAQ,IAAI;AAC1B,UAAM4W,IAAgBH;AAAA,MACpBzW;AAAA,MACAC;AAAA,MACAyW;AAAA,MACAC;AAAA,IACF;AACQ,IAAAY,EAAA,YAAYX,EAAc,GAAG;AAErC,UAAMY,IAA4BvX,EAAO,cAAc,CAACwX,MAAY;AAC9D,UAAAA,MAAYzX,EAAM,IAAI;AAChB,QAAAuX,EAAA,YAAYX,EAAc,GAAG;AAE/B,cAAAc,IAAU,SAAS,cAAc,KAAK;AAC5C,QAAAA,EAAQ,YAAY,2BACpBA,EAAQ,cAAc,cACtBH,EAAQ,YAAYG,CAAO;AAAA,MAAA;AAAA,IAC7B,CACD;AAEM,WAAA;AAAA,MACL,KAAKH;AAAA,MACL,SAAS,MAAM;AACa,QAAAC,EAAA,GAC1BZ,EAAc,QAAQ;AAAA,MAAA;AAAA,IAE1B;AAAA,EAAA;AAGI,QAAAzQ,IAAkD,EAAE,KAAKoR,EAAQ;AAGvE,MAAIvX,EAAM,MAAM,gBAAgB,MAAS,CAAClF,GAAS;AAE3C,UAAA6c,IAAmBT,GAAuBlX,CAAK;AAC7C,IAAAuX,EAAA,YAAYI,EAAiB,GAAG,GAExCxR,EAAI,UAAU,MAAM;;AAClB,OAAAvK,IAAA+b,EAAiB,YAAjB,QAAA/b,EAAA,KAAA+b;AAAA,IACF;AAAA,EAAA;AAGQ,IAAAJ,EAAA,YAAYzc,EAAQ,GAAG;AAI7B,MAAAkF,EAAM,MAAM,SAAS;AACjB,UAAAwW,IAAU,SAAS,cAAc,GAAG;AAC1C,IAAAA,EAAQ,YAAY,mBACZA,EAAA,cAAcxW,EAAM,MAAM,SAClCuX,EAAQ,YAAYf,CAAO;AAAA,EAAA;AAGtB,SAAArQ;AACT,GC/EayR,KAA0B,CACrC9c,GACA0b,MACG;AACG,QAAAqB,IAAS,SAAS,cAAc,QAAQ,GACxCtB,IAAiB,SAAS,cAAc,YAAY;AAC1D,SAAAA,EAAe,cAAcC,GAE7BqB,EAAO,YAAY/c,CAAO,GAC1B+c,EAAO,YAAYtB,CAAc,GAE1B,EAAE,KAAKsB,EAAO;AACvB,GCZaC,KAAwB,CACnChd,GACA0b,MACG;AACG,QAAAe,IAAU,SAAS,cAAc,KAAK,GACtCQ,IAAc,SAAS,cAAc,GAAG;AAC9C,SAAAA,EAAY,cAAcvB,GAE1Be,EAAQ,YAAYzc,CAAO,GAC3Byc,EAAQ,YAAYQ,CAAW,GAExB;AAAA,IACL,KAAKR;AAAA,EACP;AACF,GCdaS,KAAoB,CAACC,OAGzB,EAAE,KAFGA,EAAa,OAAO,OAEnB,ICaFC,KACX,2xBAEWC,KAAkB;AAAA,EAC7B,iBAAiBzX,EAAa;AAAA;AAAA,EAE9B,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EAEA,aAAa;AAAA,IACX,SAAS;AAAA,EAAA;AAEb,GAEa0X,KAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,YAAYD;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AAAA,EACb,iBAAiB,CAAC,SAAS;AAC7B,GAEaE,KAAc,CACzBrY,GACAC,MACG;AACG,QAAAmX,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAYc;AAEX,QAAAI,IAAQ,SAAS,cAAc,OAAO;AAC5C,SAAAA,EAAM,YAAY,YACdrY,EAAO,iBACTA,EAAO,eAAeD,EAAM,MAAM,GAAG,EAAE,KAAK,CAACuY,MAAgB;AAC3D,IAAAD,EAAM,MAAMC;AAAA,EAAA,CACb,IAEKD,EAAA,MAAMtY,EAAM,MAAM,KAE1BsY,EAAM,WAAW,IACjBA,EAAM,kBAAkB,SACxBA,EAAM,YAAY,IAEXhB;AAAA,IACLtX;AAAA,IACAC;AAAA,IACA,EAAE,KAAKqY,EAAM;AAAA,IACbrY,EAAO,WAAW,YAAY,MAAM;AAAA,IACpCmX,EAAK;AAAA,EACP;AACF,GAEaoB,KAAa,CACxB1d,MACmE;AAC/D,MAAAA,EAAQ,YAAY;AAElB,WAAAA,EAAQ,QAAQ,QAAQ,IACnB,SAGFkd,GAAkBld,CAA2B;AAGlD,MAAAA,EAAQ,YAAY,UAAU;AAC1B,UAAA2d,IAAetC,GAAmBrb,GAAS,OAAO;AACxD,QAAI,CAAC2d;AACI;AAGH,UAAA,EAAE,eAAAnC,GAAe,SAAAE,EAAA,IAAYiC;AAE5B,WAAA;AAAA,MACL,GAAGT,GAAkB1B,CAAiC;AAAA,MACtD,SAAAE;AAAA,IACF;AAAA,EAAA;AAIJ,GAEakC,KAAsB,CACjC1Y,MACG;AACC,MAAA,CAACA,EAAM,MAAM,KAAK;AACd,UAAAwD,IAAM,SAAS,cAAc,GAAG;AACtC,WAAAA,EAAI,cAAc,aAEX;AAAA,MACL,KAAKA;AAAA,IACP;AAAA,EAAA;AAGE,MAAA8U;AAUA,SATAtY,EAAM,MAAM,eACNsY,IAAA,SAAS,cAAc,OAAO,GAChCA,EAAA,MAAMtY,EAAM,MAAM,QAEhBsY,IAAA,SAAS,cAAc,GAAG,GAC5BA,EAAA,OAAOtY,EAAM,MAAM,KACzBsY,EAAM,cAActY,EAAM,MAAM,QAAQA,EAAM,MAAM,MAGlDA,EAAM,MAAM,UACVA,EAAM,MAAM,cACP4X,GAAwBU,GAAOtY,EAAM,MAAM,OAAO,IAElD8X,GAAsBQ,GAAOtY,EAAM,MAAM,OAAO,IAIpD;AAAA,IACL,KAAKsY;AAAA,EACP;AACF,GAEaK,KAAavV,GAAgBgV,IAAkB;AAAA,EAC1D,QAAQC;AAAA,EACR,OAAOG;AAAA,EACP,gBAAgBE;AAClB,CAAC,GChFYE,KAAoB,OAAO,IAAI,uBAAuB,GACtDC,KAAgC,OAAO;AAAA,EAClD;AACF,GACaC,KAA6B;AAAA,EACxC,UAAU;AAAA,IACR,SAAS;AAAA,EAAA;AAEb,GAEMC,KAAmB1W,EAA8B;AAAA,EACrD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa;AACJ,WAAA;AAAA,MACL,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,MACnB,oBAAoB,CAAA;AAAA,IACtB;AAAA,EACF;AAAA,EACA,gBAAgB;AACd,UAAM+R,IAAU,KAAK;AAEd,WAAA;AAAA,MACL,UAAU;AAAA,QACR,SAASA,EAAQ,OAAO,SAAS,UAAU;AAAA,QAC3C,WAAW,CAAC4E,MAAiB;AAC3B,cAAIle,IAAUke,GACVC,IAA0B;AAE9B,WACEne,KAAA,gBAAAA,EAAS,aAAY,UACrBA,KAAA,gBAAAA,EAAS,QAAQ,iBAAgB,gBAEvBA,IAAAA,EAAQ,SAAS,CAAC,KAG1BA,KAAA,gBAAAA,EAAS,aAAY,UACbA,IAAAA,KAAA,gBAAAA,EAAS,SAAS;AAGxB,gBAAAoe,IAAepe,KAAA,gBAAAA,EAAS,aAAa;AAE3C,cAAIoe;AACF,YAAAD,IAAWC,EAAa,YAAY;AAAA,eAC/B;AAEL,kBAAMC,IADa,CAAC,IAAIre,KAAA,gBAAAA,EAAS,UAAU,MAAM,SAAQ,EAAG,EAEzD,OAAO,CAACmZ,MAAcA,EAAU,WAAW,WAAW,CAAC,EACvD,IAAI,CAACA,MAAcA,EAAU,QAAQ,aAAa,EAAE,CAAC;AAEpD,YAAAkF,EAAU,SAAS,MACVF,IAAAE,EAAU,CAAC,EAAE,YAAY;AAAA,UACtC;AAGF,iBAAKF,IAKHG,GAAchF,EAAQ,OAAO,SAAS,WAAW6E,CAAQ,KACzDA,IALO;AAAA,QAOX;AAAA,QACA,YAAY,CAACle,MACJA,EAAW,WACd;AAAA,UACE,OAAO,YAAYA,EAAW,QAAQ;AAAA,UACtC,iBAAiBA,EAAW;AAAA,QAAA,IAE9B,CAAC;AAAA,MACP;AAAA,IAEJ;AAAA,EACF;AAAA,EACA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA;AAAA,QAEL,oBAAoB;AAAA,MAAA;AAAA,IAExB;AAAA,EACF;AAAA,EACA,WAAW,EAAE,gBAAAwI,KAAkB;;AACvB,UAAA8V,IAAM,SAAS,cAAc,KAAK,GAClC,EAAE,KAAAhF,GAAK,YAAAiF,EAAA,IAAeha;AAAA,MAC1B,KAAK;AAAA,MACL;AAAA,QACA1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,MAC7C;AAAA,QACE,KAAIC,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAC;AAAA,QAClD,GAAG0H;AAAA,MAAA;AAAA,IAEP;AAEA,WAAA8Q,EAAI,YAAYiF,CAAU,GAC1BjF,EAAI,YAAYgF,CAAG,GACnBA,EAAI,YAAYC,CAAU,GAEnB;AAAA,MACL,KAAAjF;AAAA,MACA,YAAAiF;AAAA,IACF;AAAA,EACF;AAAA,EACA,cAAc;AACZ,UAAMlF,IAAU,KAAK;AAErB,WAAO,CAAC,EAAE,QAAAnU,GAAQ,MAAAzD,GAAM,QAAAiF,GAAQ,gBAAA8B,QAAqB;;AAC7C,YAAA8V,IAAM,SAAS,cAAc,KAAK,GAClCE,IAAS,SAAS,cAAc,QAAQ,GACxCC,IAAgB,SAAS,cAAc,KAAK,GAC5C,EAAE,KAAAnF,GAAK,YAAAiF,EAAA,IAAeha;AAAA,QAC1B,KAAK;AAAA,QACL;AAAA,QACA;AAAA,UACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,UACjD,GAAG2H;AAAA,QACL;AAAA,UACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,MAC/C,GACM4d,IAAuB,CAACvc,MAAiB;AACvC,cAAA+b,IAAY/b,EAAM,OAA6B;AAErD,QAAA+C,EAAO,SAAS,QAAQ,CAAC,EAAE,IAAAtE,SACzBA,EAAG,iBAAiB8F,KAAU,YAAYwX,CAAQ,GAE3C,GACR;AAAA,MACH;AAEO,oBAAA;AAAA,QACL7E,EAAQ,OAAO,SAAS,UAAU;AAAA,MACpC,EAAE,QAAQ,CAAC,CAAC1X,GAAI,EAAE,MAAA0E,EAAM,CAAA,MAAM;AACtB,cAAAsY,IAAS,SAAS,cAAc,QAAQ;AAE9C,QAAAA,EAAO,QAAQhd,GACfgd,EAAO,OAAOtY,GACdmY,EAAO,YAAYG,CAAM;AAAA,MAAA,CAC1B,GAEDF,EAAc,kBAAkB,SAChCD,EAAO,QACL/c,EAAK,MAAM,YACX4X,EAAQ,OAAO,SAAS,UAAU,iBACpCC,EAAI,YAAYiF,CAAU,GAC1BjF,EAAI,YAAYmF,CAAa,GAC7BnF,EAAI,YAAYgF,CAAG,GACnBA,EAAI,YAAYC,CAAU,GAC1BE,EAAc,YAAYD,CAAM,GACzBA,EAAA,iBAAiB,UAAUE,CAAoB,GAE/C;AAAA,QACL,KAAApF;AAAA,QACA,YAAAiF;AAAA,QACA,QAAQ,CAACK,MACHA,EAAQ,SAAS,KAAK;AAAA,QAM5B,SAAS,MAAM;AACN,UAAAJ,EAAA,oBAAoB,UAAUE,CAAoB;AAAA,QAAA;AAAA,MAE7D;AAAA,IACF;AAAA,EACF;AAAA,EACA,wBAAwB;AACtB,UAAMrF,IAAU,KAAK,SACfwF,IAAqB;AAKvB,QAAAC,GACAC,GACAC,IAAY;AA0DhB,WAAO,CANiBC,GAAsB;AAAA,MAC5C,QApDyB,CAACC,MAAkB;AAC5C,YAAI,CAAC7F,EAAQ,OAAO,SAAS,UAAU;AACrC,iBAAI,QAAQ,IAAI,aAAa,iBAAiB,CAAC2F,MAErC,QAAA;AAAA,YACN;AAAA,UACF,GACYA,IAAA,KAEP,CAAC;AAEV,YAAI,CAACF;AACgB,iBAAAD,EAAAf,EAA6B,IAC9Ce,EAAmBf,EAA6B,KAChDzE,EAAQ,OAAO,SAAS,UAAU,kBAAkB,GAE/CwF,EAAmBf,EAA6B,EAAE;AAAA,YACvD,CAACqB,MAAuB;AACR,cAAAL,IAAAK;AAAA,YAAA;AAAA,UAElB;AAEF,cAAMjB,IAAWG;AAAA,UACfhF,EAAQ,OAAO,SAAS;AAAA,UACxB6F,EAAc;AAAA,QAChB;AAGE,eAAA,CAAChB,KACDA,MAAa,UACbA,MAAa,UACbA,MAAa,eACbA,MAAa,QAEN,CAAC,IAGLY,EAAY,mBAAqB,EAAA,SAASZ,CAAQ,KAIlDa,MACHA,IACEF,EAAmBhB,EAAiB,KACpCuB,GAAaN,CAAkB,GACjCD,EAAmBhB,EAAiB,IAAIkB,IAGnCA,EAAOG,CAAa,KAVlBJ,EAAY,aAAaZ,CAAQ;AAAA,MAW5C;AAAA,MAIE,mBAAmB,CAACzc,MAASA,EAAK,MAAM;AAAA,MACxC,WAAW,CAAC,KAAK,IAAI;AAAA,IAAA,CACtB,CAEsB;AAAA,EACzB;AAAA,EACA,gBAAgB;AACd,UAAM4X,IAAU,KAAK;AAEd,WAAA;AAAA,MACL,IAAIgG,GAAU;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAAgM,GAAO,OAAAiJ,QAAY;AACpC,gBAAMC,IAASlV,EAAM,IAAI,QAAQgM,EAAM,IAAI,GACrCmJ,IAAeF,EAAM,CAAC,EAAE,KAAK,GAC7Btf,IAAa;AAAA,YACjB,UACEqe,GAAchF,EAAQ,OAAO,SAAS,WAAWmG,CAAY,KAC7DA;AAAA,UACJ;AAEA,cACE,CAACD,EACE,KAAK,EAAE,EACP;AAAA,YACCA,EAAO,MAAM,EAAE;AAAA,YACfA,EAAO,WAAW,EAAE;AAAA,YACpB,KAAK;AAAA,UAAA;AAGF,mBAAA;AAGH,UAAAlV,EAAA,GACH,OAAOgM,EAAM,MAAMA,EAAM,EAAE,EAC3B,aAAaA,EAAM,MAAMA,EAAM,MAAM,KAAK,MAAMrW,CAAU,EAC1D,aAAayf,EAAc,OAAOpV,EAAM,GAAG,KAAKgM,EAAM,IAAI,CAAC;AAAA,QAE9D;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EACA,uBAAuB;AACd,WAAA;AAAA,MACL,QAAQ,CAAC,EAAE,QAAAnR,QAAa;AAChB,cAAA,EAAE,WAAAwa,MAAcxa,EAAO,OACvB,EAAE,OAAAya,MAAUD;AAIhB,YAAAxa,EAAO,SAAS,KAAK,IAAI,KACzB,CAACya,EAAM,OAAO,eACdC,GAAgBF,CAAS,GACzB;AAEA,gBAAM9L,IAAO+L,EAAM,MAAMA,EAAM,eAAe;AAE9C,iBAAAza,EAAO,QAAQ,iBAAiB0O,CAAI,EAAE,kBAAkB,IAAI,GAErD;AAAA,QAAA;AAGF,eAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAC,EAAE,QAAA1O,QACD,KAAK,QAAQ,qBAGdA,EAAO,SAAS,KAAK,IAAI,KACpBA,EAAA,SAAS,cAAc,IAAI,GAC3B,MAJA;AAAA,MASX,OAAO,CAAC,EAAE,QAAAA,QAAa;AACrB,cAAM,EAAE,OAAAya,EAAA,IAAUza,EAAO,MAAM;AAE/B,YAAI,CAACA,EAAO,SAAS,KAAK,IAAI;AACrB,iBAAA;AAGT,cAAM2a,IAAUF,EAAM,iBAAiBA,EAAM,OAAO,WAAW,GACzDG,IAAwBH,EAAM,OAAO,YAAY,SAAS;AAAA;AAAA,CAAM;AAElE,eAAA,CAACE,KAAW,CAACC,KACR5a,EAAA,SAAS,cAAc;AAAA,CAAI,GAC3B,MAGFA,EACJ,MAAM,EACN,QAAQ,CAAC,EAAE,IAAAtE,SACVA,EAAG,OAAO+e,EAAM,MAAM,GAAGA,EAAM,GAAG,GAE3B,GACR,EACA,SAAS,EACT,IAAI;AAAA,MACT;AAAA,MACA,eAAe,CAAC,EAAE,QAAAza,QAAa;AAC7B,cAAM,EAAE,OAAAya,EAAA,IAAUza,EAAO,MAAM;AAE/B,eAAKA,EAAO,SAAS,KAAK,IAAI,KAI9BA,EACG,QACA;AAAA,UACCya,EAAM,MAAMA,EAAM,eAAeA,EAAM,OAAO;AAAA,UAC9C;AAAA,YACE,MAAM;AAAA,UAAA;AAAA,UAGT,IAAI,GAEA,MAbE;AAAA,MAaF;AAAA,IAEX;AAAA,EAAA;AAEJ,CAAC,GAEYI,KAAYpY;AAAA,EACvBqW;AAAA,EACAD;AACF;AAEA,SAASM,GACPhF,GACAmG,GACoB;;AACpB,UAAO3e,IAAA,OAAO,QAAQwY,EAAQ,kBAAkB,EAAE;AAAA,IAChD,CAAC,CAAC1X,GAAI,EAAE,SAAAqe,EAAA,CAAS,OACRA,KAAA,gBAAAA,EAAS,SAASR,OAAiB7d,MAAO6d;AAAA,QAF9C,gBAAA3e,EAIH;AACN;ACzbA,MAAMof,KAAsB1Q,GAAK,OAAO;AAAA,EACtC,MAAM;AAAA,EAEN,gBAAgB;AACP,WAAA;AAAA,MACL,aAAa;AAAA,QACX,SAAS;AAAA,QACT,WAAW,CAACxP,MAAYA,EAAQ,aAAa,uBAAuB;AAAA,QACpE,YAAY,CAACC,OAAgB;AAAA,UAC3B,yBAAyBA,EAAW;AAAA,QACtC;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACD,MACL,OAAOA,KAAY,WACd,KAGLA,EAAQ,aAAa,uBAAuB,IACvC;AAAA,UACL,aAAaA,EAAQ,aAAa,uBAAuB;AAAA,QAC3D,IAGK;AAAA,MACT;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAyI,KAAkB;AACtB,WAAA,CAAC,QAAQA,GAAgB,CAAC;AAAA,EAAA;AAErC,CAAC,GAEY0X,KAAkBjR;AAAA,EAC7BgR;AAAA,EACA;AACF,GC5CME,KAAgB5Q,GAAK,OAAO;AAAA,EAChC,MAAM;AAAA,EAEN,gBAAgB;AACP,WAAA;AAAA,MACL,aAAa;AAAA,QACX,SAAS;AAAA,QACT,WAAW,CAACxP,MAAYA,EAAQ,aAAa,iBAAiB;AAAA,QAC9D,YAAY,CAACC,OAAgB;AAAA,UAC3B,mBAAmBA,EAAW;AAAA,QAChC;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACD,MACL,OAAOA,KAAY,WACd,KAGLA,EAAQ,aAAa,iBAAiB,IACjC,EAAE,aAAaA,EAAQ,aAAa,iBAAiB,EAAE,IAGzD;AAAA,MACT;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAyI,KAAkB;AACtB,WAAA,CAAC,QAAQA,GAAgB,CAAC;AAAA,EAAA;AAErC,CAAC,GAEY4X,KAAYnR,GAA8BkR,IAAe,QAAQ,GC1CjEE,KAAoB,CAACC,OAGzB,EAAE,KAFGA,EAAa,OAAO,OAEnB,ICUFC,KAAiB;AAAA,EAC5B,iBAAiB5a,EAAa;AAAA;AAAA,EAE9B,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,SAAS;AAAA,EAAA;AAEb,GAEa6a,KAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,YAAYD;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AACf,GAEaE,KAAa,CACxBxb,GACAC,MAEOqX,GAAuBtX,GAAOC,CAAM,GAGhCwb,KAAY,CAAC3gB,MAAyB;AAC7C,MAAAA,EAAQ,YAAY;AAElB,WAAAA,EAAQ,QAAQ,QAAQ,IACnB,SAGFsgB,GAAkBtgB,CAA2B;AAGlD,MAAAA,EAAQ,YAAY,UAAU;AAC1B,UAAA2d,IAAetC,GAAmBrb,GAAS,OAAO;AACxD,QAAI,CAAC2d;AACI;AAGH,UAAA,EAAE,eAAAnC,GAAe,SAAAE,EAAA,IAAYiC;AAE5B,WAAA;AAAA,MACL,GAAG2C,GAAkB9E,CAAiC;AAAA,MACtD,SAAAE;AAAA,IACF;AAAA,EAAA;AAIJ,GAEakF,KAAqB,CAChC1b,MACG;AACC,MAAA,CAACA,EAAM,MAAM,KAAK;AACd,UAAAwD,IAAM,SAAS,cAAc,GAAG;AACtC,WAAAA,EAAI,cAAc,YAEX;AAAA,MACL,KAAKA;AAAA,IACP;AAAA,EAAA;AAGI,QAAAmY,IAAc,SAAS,cAAc,GAAG;AAI1C,SAHQA,EAAA,OAAO3b,EAAM,MAAM,KAC/B2b,EAAY,cAAc3b,EAAM,MAAM,QAAQA,EAAM,MAAM,KAEtDA,EAAM,MAAM,UACP8X,GAAsB6D,GAAa3b,EAAM,MAAM,OAAO,IAGxD;AAAA,IACL,KAAK2b;AAAA,EACP;AACF,GAEaC,KAAYxY,GAAgBmY,IAAiB;AAAA,EACxD,QAAQC;AAAA,EACR,OAAOC;AAAA,EACP,gBAAgBC;AAClB,CAAC,GCvFYG,KAAoB;AAAA,EAC/B,GAAGnb;AAAA,EACH,OAAO,EAAE,SAAS,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC,EAAW;AAClD,GAEMob,KAAsBzZ,EAA8B;AAAA,EACxD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,gBAAgB;AACd,WAAOpB,GAAkB4a,EAAiB;AAAA,EAC5C;AAAA,EAEA,gBAAgB;AACP,WAAA;AAAA,MACL,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAACE,MAET,IAAI3B,GAAU;AAAA,QACnB,MAAM,IAAI,OAAO,OAAO2B,CAAK,QAAQ;AAAA,QACrC,SAAS,CAAC,EAAE,OAAA3W,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAE/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,OAAAkU;AAAA,cAAA;AAAA,YAEH,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAM3K,EAAM,MAAM,IAAIA,EAAM,IAAI,EAC9C,IAAI;AAAA,QAAA;AAAA,MACT,CACD,CACF;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,aAAa,MAAM;AACjB,cAAMvJ,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAIF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO;AAAA,cACL,OAAO;AAAA,YAAA;AAAA,UAEV,CAAA;AAAA,QACH;AAAA,MACF;AAAA,MACA,aAAa,MAAM;AACjB,cAAMA,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO;AAAA,cACL,OAAO;AAAA,YAAA;AAAA,UAEV,CAAA;AAAA,QACH;AAAA,MACF;AAAA,MACA,aAAa,MAAM;AACjB,cAAMA,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO;AAAA,cACL,OAAO;AAAA,YAAA;AAAA,UAEV,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EACA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,OAAO,EAAE,OAAO,EAAE;AAAA,QAClB,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,OAAO,EAAE,OAAO,EAAE;AAAA,QAClB,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,OAAO,EAAE,OAAO,EAAE;AAAA,QAClB,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,MAAArL,GAAM,gBAAA+G,KAAkB;;AAC5B,WAAAjE;AAAA,MACL,KAAK;AAAA,MACL,IAAI9C,EAAK,MAAM,KAAK;AAAA,MACpB;AAAA,QACE,KAAIZ,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEYogB,KAAUvZ;AAAA,EACrBoZ;AAAA,EACAD;AACF,GC5JaK,KAAkC,CAC7Clc,GACAC,GACAnF,GACAqhB,GACAzF,GACAC,MAC8C;AACxC,QAAA,EAAE,KAAAtC,GAAK,SAAA+H,EAAA,IAAY9E;AAAA,IACvBtX;AAAA,IACAC;AAAA,IACAnF;AAAA,IACA4b;AAAA,IACAC;AAAA,EACF,GACMY,IAAUlD;AAChB,EAAIrU,EAAM,MAAM,OAAOA,EAAM,MAAM,gBAC7BA,EAAM,MAAM,eACduX,EAAQ,MAAM,QAAQ,GAAGvX,EAAM,MAAM,YAAY,OAEjDuX,EAAQ,MAAM,QAAQ;AAIpB,QAAA8E,IAAmB,SAAS,cAAc,KAAK;AACrD,EAAAA,EAAiB,YAAY,oBAC7BA,EAAiB,MAAM,OAAO;AACxB,QAAAC,IAAoB,SAAS,cAAc,KAAK;AACtD,EAAAA,EAAkB,YAAY,oBAC9BA,EAAkB,MAAM,QAAQ;AAI5B,MAAAC,GAOA7R,IAAQ1K,EAAM,MAAM;AAIlB,QAAAwc,IAAyB,CAACtf,MAAsB;;AACpD,QAAI,CAACqf,GAAc;AAEf,MAAA,CAACtc,EAAO,cACRkc,EAA8B,SAASE,CAAgB,KACvDF,EAA8B,SAASG,CAAiB,MAExDH,EAA8B,YAAYE,CAAgB,GAC1DF,EAA8B,YAAYG,CAAiB;AAG7D;AAAA,IAAA;AAGE,QAAAG;AAEA,IAAAzc,EAAM,MAAM,kBAAkB,WAC5Buc,EAAa,eAAe,SAC9BE,IACEF,EAAa,gBACZA,EAAa,iBAAiBrf,EAAM,WAAW,IAElDuf,IACEF,EAAa,gBACZrf,EAAM,UAAUqf,EAAa,kBAAkB,IAGhDA,EAAa,eAAe,SAC9BE,IACEF,EAAa,eACbA,EAAa,iBACbrf,EAAM,UAERuf,IACEF,EAAa,eACbrf,EAAM,UACNqf,EAAa,gBASnB7R,IAAQ,KAAK;AAAA,MACX,KAAK,IAAI+R,GALM,EAKY;AAAA,QAC3B5gB,KAAAD,IAAAqE,EAAO,eAAP,gBAAArE,EAAmB,sBAAnB,gBAAAC,EAAsC,gBAAe,OAAO;AAAA,IAC9D,GACQ0b,EAAA,MAAM,QAAQ,GAAG7M,CAAK;AAAA,EAChC,GAGMgS,IAAuB,CAACxf,MAAsB;AAalD,KAVG,CAACA,EAAM,UACN,CAACqa,EAAQ,SAASra,EAAM,MAAc,KACtC,CAAC+C,EAAO,eACVkc,EAA8B,SAASE,CAAgB,KACvDF,EAA8B,SAASG,CAAiB,MAExDH,EAA8B,YAAYE,CAAgB,GAC1DF,EAA8B,YAAYG,CAAiB,IAGxDC,MAIUA,IAAA,QAEftc,EAAO,YAAYD,GAAO;AAAA,MACxB,OAAO;AAAA,QACL,cAAc0K;AAAA,MAAA;AAAA,IAChB,CACD;AAAA,EACH,GAGMiS,IAA2B,MAAM;AACrC,IAAI1c,EAAO,eACTkc,EAA8B,YAAYE,CAAgB,GAC1DF,EAA8B,YAAYG,CAAiB;AAAA,EAE/D,GAGMM,IAA2B,CAAC1f,MAAsB;AACtD,IACEA,EAAM,kBAAkBmf,KACxBnf,EAAM,kBAAkBof,KAKtBC,KAKFtc,EAAO,cACPkc,EAA8B,SAASE,CAAgB,KACvDF,EAA8B,SAASG,CAAiB,MAExDH,EAA8B,YAAYE,CAAgB,GAC1DF,EAA8B,YAAYG,CAAiB;AAAA,EAE/D,GAIMO,IAAmC,CAAC3f,MAAsB;AAC9D,IAAAA,EAAM,eAAe,GAENqf,IAAA;AAAA,MACb,YAAY;AAAA,MACZ,cAAchF,EAAQ;AAAA,MACtB,gBAAgBra,EAAM;AAAA,IACxB;AAAA,EACF,GACM4f,IAAoC,CAAC5f,MAAsB;AAC/D,IAAAA,EAAM,eAAe,GAENqf,IAAA;AAAA,MACb,YAAY;AAAA,MACZ,cAAchF,EAAQ;AAAA,MACtB,gBAAgBra,EAAM;AAAA,IACxB;AAAA,EACF;AAEO,gBAAA,iBAAiB,aAAasf,CAAsB,GACpD,OAAA,iBAAiB,WAAWE,CAAoB,GAC/CnF,EAAA,iBAAiB,cAAcoF,CAAwB,GACvDpF,EAAA,iBAAiB,cAAcqF,CAAwB,GAC9CP,EAAA;AAAA,IACf;AAAA,IACAQ;AAAA,EACF,GACkBP,EAAA;AAAA,IAChB;AAAA,IACAQ;AAAA,EACF,GAEO;AAAA,IACL,KAAKvF;AAAA,IACL,SAAS,MAAM;AACH,MAAA6E,KAAA,QAAAA,KACH,OAAA,oBAAoB,aAAaI,CAAsB,GACvD,OAAA,oBAAoB,WAAWE,CAAoB,GAClDnF,EAAA,oBAAoB,cAAcoF,CAAwB,GAC1DpF,EAAA,oBAAoB,cAAcqF,CAAwB,GACjDP,EAAA;AAAA,QACf;AAAA,QACAQ;AAAA,MACF,GACkBP,EAAA;AAAA,QAChB;AAAA,QACAQ;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AACF,GClNaC,KAAoB,CAACC,MAAmC;AAC7D,QAAAjc,IAAMic,EAAa,OAAO,QAC1BC,IAAeD,EAAa,SAAS;AAEpC,SAAA,EAAE,KAAAjc,GAAK,cAAAkc,EAAa;AAC7B,GCUaC,KACX,kaAEWC,KAAkB;AAAA,EAC7B,eAAezc,EAAa;AAAA,EAC5B,iBAAiBA,EAAa;AAAA;AAAA,EAE9B,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EAEA,aAAa;AAAA,IACX,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,EAAA;AAEV,GAEa0c,KAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,YAAYD;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AAAA,EACb,iBAAiB,CAAC,SAAS;AAC7B,GAEaE,KAAc,CACzBrd,GACAC,MACG;AACG,QAAAmX,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY8F;AAEX,QAAAI,IAAe,SAAS,cAAc,KAAK;AACjD,EAAAA,EAAa,YAAY;AAEnB,QAAAC,IAAQ,SAAS,cAAc,KAAK;AAC1C,SAAAA,EAAM,YAAY,mBACdtd,EAAO,iBACTA,EAAO,eAAeD,EAAM,MAAM,GAAG,EAAE,KAAK,CAACuY,MAAgB;AAC3D,IAAAgF,EAAM,MAAMhF;AAAA,EAAA,CACb,IAEKgF,EAAA,MAAMvd,EAAM,MAAM,KAG1Bud,EAAM,MAAMvd,EAAM,MAAM,QAAQA,EAAM,MAAM,WAAW,mBACvDud,EAAM,kBAAkB,SACxBA,EAAM,YAAY,IAClBD,EAAa,YAAYC,CAAK,GAEvBrB;AAAA,IACLlc;AAAA,IACAC;AAAA,IACA,EAAE,KAAKqd,EAAa;AAAA,IACpBA;AAAA,IACArd,EAAO,WAAW,YAAY,MAAM;AAAA,IACpCmX,EAAK;AAAA,EACP;AACF,GAEaoG,KAAa,CACxB1iB,MACmE;AAC/D,MAAAA,EAAQ,YAAY;AAElB,WAAAA,EAAQ,QAAQ,QAAQ,IACnB,SAGFiiB,GAAkBjiB,CAA2B;AAGlD,MAAAA,EAAQ,YAAY,UAAU;AAC1B,UAAA2d,IAAetC,GAAmBrb,GAAS,KAAK;AACtD,QAAI,CAAC2d;AACI;AAGH,UAAA,EAAE,eAAAnC,GAAe,SAAAE,EAAA,IAAYiC;AAE5B,WAAA;AAAA,MACL,GAAGsE,GAAkBzG,CAAiC;AAAA,MACtD,SAAAE;AAAA,IACF;AAAA,EAAA;AAIJ,GAEaiH,KAAsB,CACjCzd,MACG;AACC,MAAA,CAACA,EAAM,MAAM,KAAK;AACd,UAAAwD,IAAM,SAAS,cAAc,GAAG;AACtC,WAAAA,EAAI,cAAc,aAEX;AAAA,MACL,KAAKA;AAAA,IACP;AAAA,EAAA;AAGE,MAAA+Z;AAcA,SAbAvd,EAAM,MAAM,eACNud,IAAA,SAAS,cAAc,KAAK,GAC9BA,EAAA,MAAMvd,EAAM,MAAM,KACxBud,EAAM,MAAMvd,EAAM,MAAM,QAAQA,EAAM,MAAM,WAAW,mBACnDA,EAAM,MAAM,iBACRud,EAAA,QAAQvd,EAAM,MAAM,kBAGpBud,IAAA,SAAS,cAAc,GAAG,GAC5BA,EAAA,OAAOvd,EAAM,MAAM,KACzBud,EAAM,cAAcvd,EAAM,MAAM,QAAQA,EAAM,MAAM,MAGlDA,EAAM,MAAM,UACVA,EAAM,MAAM,cACP4X,GAAwB2F,GAAOvd,EAAM,MAAM,OAAO,IAElD8X,GAAsByF,GAAOvd,EAAM,MAAM,OAAO,IAIpD;AAAA,IACL,KAAKud;AAAA,EACP;AACF,GAEaG,KAAata,GAAgBga,IAAkB;AAAA,EAC1D,QAAQC;AAAA,EACR,OAAOG;AAAA,EACP,gBAAgBC;AAClB,CAAC;AC/Ie,SAAAE,GAIdC,GAIAnY,GAIArE,GACU;;AAYJ,QAAA0Y,IAAS+D,GAAU,WAAWpY,CAAM,GAGpCjJ,IAAOohB,GAKPE,IAAgB,SAAS,cAAc,KAAK;AAEpC,EAAAA,EAAA,aAAa,kBAAkB,YAAY;AAEzD,aAAWlX,KAAS,MAAM,KAAKpK,EAAK,UAAU;AAC5C,IAAAshB,EAAc,YAAYlX,EAAM,UAAU,EAAI,CAAC;AAM7C,MAAA/B,IAAiBiV,EAAO,MAAMgE,GAAe;AAAA,IAC/C,SAASrY,EAAO,MAAM,WAAW,OAAO;AAAA,EAAA,CACzC;AAKD,IAAI5J,KAAAD,IAAAiJ,EAAe,eAAf,gBAAAjJ,EAA2B,eAA3B,gBAAAC,EAAuC,KAAK,UAAS,oBAGvDgJ,IAAiBA,EAAe;AAAA,IAC9BA,EAAe,QAAQ;AAAA,MACrBA,EAAe,WAAW,WAAW,WAAW;AAAA,IAAA;AAAA,EAEpD;AAKI,QAAAkZ,KAAsB9f,IAAA4G,EAAe,eAAf,gBAAA5G,EAA2B;AAGnD,MAAA,EAAC8f,KAAA,QAAAA,EAAqB;AAEjB,WAAAvgB,EAAS,KAAKqH,CAAc;AAMrC,QAAMmZ,IAAevY,EAAO,MAAMrE,CAAI,EAAE;AAAA,IACtC,CAAC;AAAA,IACD2c,EAAoB;AAAA,EACtB,GAIME,IAA4BpZ,EAAe,QAAQ;AAAA;AAAA,IAEvDkZ,EAAoB,WAAW;AAAA,EACjC;AAGA,MAFqCE,EAA0B,OAAO,GAEpC;AAG1B,UAAAC,IAAoBrZ,EAAe,KAAKoZ,CAAyB;AAGhE,WAAAD,EAAa,QAAQ,SAASE,CAAiB;AAAA,EAAA;AAIxD,SAAOF,EAAa;AACtB;AC3GO,MAAMG,KAAoB,CAC/BC,GACAC,GACAC,MAEO,CAAC;AAAA,EACN,OAAAlZ;AAAA,EACA,UAAAuN;AAAA,MAII;AACJ,QAAM4L,IAA2B5a,EAAmByB,EAAM,KAAKgZ,CAAU,GAEnEI,IAAOxZ,GAAauZ,CAAwB;AAE9C,MAAA,CAACC,EAAK;AACR,UAAM,IAAI;AAAA,MACR,6DAA6DJ,CAAU;AAAA,IACzE;AAGF,QAAMtiB,IAAQ;AAAA,IACZ;AAAA,MACE,MAAM0iB,EAAK,QAAQ,KAAK;AAAA;AAAA,MACxB,OAAOF,IAAY,EAAE,GAAGE,EAAK,QAAQ,KAAK,OAAO,IAAI,WAAc,CAAA;AAAA,IACrE;AAAA,IACA;AAAA,MACE,MAAMH,IACFG,EAAK,aAAa,KAAK,OACvBpZ,EAAM,OAAO,MAAM;AAAA,MACvB,OAAOkZ,IAAY,EAAE,GAAGE,EAAK,aAAa,KAAK,UAAU,CAAA;AAAA,IAAC;AAAA,EAE9D;AAEA,SAAI7L,KACFvN,EAAM,GAAG,MAAMgZ,GAAY,GAAGtiB,CAAK,GAG9B;AACT,GC1CW2iB,KAAc,CAACxe,MAA2C;AACrE,QAAM,EAAE,WAAA4H,GAAW,gBAAA6W,EAAA,IAAmBze,EAAO,SAAS,CAACtE,OAC9C;AAAA,IACL,WAAW0J,GAA4B1J,CAAE;AAAA,IACzC,gBAAgBA,EAAG,UAAU,WAAWA,EAAG,UAAU;AAAA,EACvD,EACD;AAEG,MAAA,CAACkM,EAAU;AACN,WAAA;AAET,QAAM,EAAE,SAASW,GAAgB,cAAA7I,EAAiB,IAAAkI;AAElD,SACE,EACElI,EAAa,KAAK,KAAK,SAAS,oBAChCA,EAAa,KAAK,KAAK,SAAS,sBAChCA,EAAa,KAAK,KAAK,SAAS,oBAElC,CAAC+e,IAEM,KAGFze,EAAO,cAAc,SAAS,MAAM,CAAC,EAAE,OAAAmF,GAAO,OAAA4W,GAAO,UAAA2C,QAAe;AAAA,IACzE;AAAA;AAAA,MAEEA,EAAS,QAAQ,MACXhf,EAAa,KAAK,eAAe,IAC5Bgf,EAAS;AAAA,QACdlM,EAAmBjK,EAAe,WAAW;AAAA,UAC3C,MAAM;AAAA,UACN,OAAO,CAAA;AAAA,QACR,CAAA;AAAA,MACH,IAGK,EACR;AAAA;AAAA,IAEH;AAAA;AAAA;AAAA,MAGEmW,EAAS,QAAQ,MACXhf,EAAa,KAAK,aAAa,KAC3Bqc,IACH,kBACA,QAAQmC,GAAkB/Y,EAAM,UAAU,MAAM,EAAI,CAAC,EACrD,IAAI,GAEA,MAGF,EACR;AAAA;AAAA,EAAA,CACJ;AACH,GChDawZ,KAA2B;AAAA,EACtC,GAAGle;AACL,GAEMme,KAA6Bxc,EAA8B;AAAA,EAC/D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA;AAAA;AAAA,EAGP,UAAU;AAAA,EACV,gBAAgB;AACP,WAAA;AAAA;AAAA,MAEL,IAAI+X,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,YAAY;AAAA,QAC7B,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAE/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO,CAAA;AAAA,YACR,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAMuJ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MAEpD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,OAAO,MAAMqN,GAAY,KAAK,QAAQ,MAAM;AAAA,MAC5C,eAAe,MAAM;AACnB,cAAM5W,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAAC/M,MAAY;;AACjB,cAAA,OAAOA,KAAY;AACd,mBAAA;AAGT,gBAAM4a,IAAS5a,EAAQ;AAEvB,iBAAI4a,MAAW,OACN,KAIPA,EAAO,YAAY,QAClBA,EAAO,YAAY,WAAS9Z,IAAA8Z,EAAO,kBAAP,gBAAA9Z,EAAsB,aAAY,OAExD,CAAC,IAGH;AAAA,QACT;AAAA;AAAA;AAAA,QAGA,YAAY,CAACY,GAAMiJ,MACjBkY,GAAmBnhB,GAAMiJ,GAAQ,KAAK,IAAI;AAAA,QAC5C,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAlC,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA;AAAA;AAAA;AAAA,MAIL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEYijB,KAAiBpc;AAAA,EAC5Bmc;AAAA,EACAD;AACF,GCnHaG,KAA0B;AAAA,EACrC,GAAGre;AAAA,EACH,SAAS;AAAA,IACP,SAAS;AAAA,EAAA;AAEb,GAEMse,KAA4B3c,EAA8B;AAAA,EAC9D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,gBAAgB;AACd,WAAOpB,GAAkB8d,EAAuB;AAAA,EAClD;AAAA,EAEA,gBAAgB;AACP,WAAA;AAAA;AAAA,MAEL,IAAI3E,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,gBAAgB;AAAA,QACjC,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAE/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAAS;AAAA,cAAA;AAAA,YAEZ,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAMuJ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MACnD,CACD;AAAA,MACD,IAAIgJ,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,gBAAgB;AAAA,QACjC,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAG/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAAS;AAAA,cAAA;AAAA,YAEZ,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAMuJ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MAEpD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,OAAO,MAAMqN,GAAY,KAAK,QAAQ,MAAM;AAAA,MAC5C,eAAe,MAAM;AACnB,cAAM5W,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAAC/M,MACL,OAAOA,KAAY,YAKnBA,EAAQ,QAAQ,qBAAqB,KAAKA,EAAQ,QAAQ,IAAI,IACzD,KAGJA,EAA6B,SAAS,aAClC,EAAE,SAAUA,EAA6B,QAAQ,IAGnD;AAAA,QAET,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACA,MAAY;;AACjB,cAAA,OAAOA,KAAY;AACd,mBAAA;AAGT,gBAAM4a,IAAS5a,EAAQ;AAEvB,cAAI4a,MAAW;AACN,mBAAA;AAIP,cAAAA,EAAO,YAAY,QAClBA,EAAO,YAAY,WAAS9Z,IAAA8Z,EAAO,kBAAP,gBAAA9Z,EAAsB,aAAY,MAC/D;AACA,kBAAMqjB,IACHnkB,EAAQ;AAAA,cACP;AAAA,YAAA,KACwB;AAE5B,mBAAImkB,MAAa,OACR,KAGF,EAAE,SAASA,EAAS,QAAQ;AAAA,UAAA;AAG9B,iBAAA;AAAA,QACT;AAAA;AAAA;AAAA,QAGA,YAAY,CAACziB,GAAMiJ,MACjBkY,GAAmBnhB,GAAMiJ,GAAQ,KAAK,IAAI;AAAA,QAC5C,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,EAAE,MAAAjJ,GAAM,gBAAA+G,KAAkB;;AAC7B,UAAA0b,IAAW,SAAS,cAAc,OAAO;AAC/C,IAAAA,EAAS,OAAO,YACPA,EAAA,UAAUziB,EAAK,MAAM,SAC1BA,EAAK,MAAM,WACJyiB,EAAA,aAAa,WAAW,EAAE;AAG/B,UAAA,EAAE,KAAA5K,GAAK,YAAAiF,EAAA,IAAeha;AAAA,MAC1B,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAEI,WAAAwY,EAAA,aAAa4K,GAAU3F,CAAU,GAE9B,EAAE,KAAAjF,GAAK,YAAAiF,EAAW;AAAA,EAC3B;AAAA;AAAA;AAAA,EAIA,cAAc;AACZ,WAAO,CAAC,EAAE,MAAA9c,GAAM,QAAAiF,GAAQ,QAAAxB,GAAQ,gBAAAsD,QAAqB;;AAG7C,YAAAgU,IAAU,SAAS,cAAc,KAAK,GACtC2H,IAAkB,SAAS,cAAc,KAAK;AACpD,MAAAA,EAAgB,kBAAkB;AAE5B,YAAAD,IAAW,SAAS,cAAc,OAAO;AAC/C,MAAAA,EAAS,OAAO,YACPA,EAAA,UAAUziB,EAAK,MAAM,SAC1BA,EAAK,MAAM,WACJyiB,EAAA,aAAa,WAAW,EAAE;AAGrC,YAAME,IAAgB,MAAM;AACtB,YAAA,CAAClf,EAAO,YAAY;AAIb,UAAAgf,EAAA,UAAU,CAACA,EAAS;AAC7B;AAAA,QAAA;AAIE,YAAA,OAAOxd,KAAW,WAAW;AAC/B,gBAAM2d,IAA0Bzb;AAAA,YAC9B1D,EAAO,MAAM;AAAA,YACbwB,EAAO;AAAA,UACT;AAEA,cAAI2d,EAAwB,KAAK,KAAK,SAAS;AAC7C,kBAAM,IAAI;AAAA,cACR,qCAAqCA,EAAwB,KAAK,KAAK,IAAI;AAAA,YAC7E;AAGF,eAAK,OAAO,SAAS;AAAA,YACnB3M,EAAmB2M,EAAwB,eAAe;AAAA,cACxD,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAASH,EAAS;AAAA,cAAA;AAAA,YAErB,CAAA;AAAA,UACH;AAAA,QAAA;AAAA,MAEJ;AACS,MAAAA,EAAA,iBAAiB,UAAUE,CAAa;AAE3C,YAAA,EAAE,KAAA9K,GAAK,YAAAiF,EAAA,IAAeha;AAAA,QAC1B,KAAK;AAAA,QACL;AAAA,QACA;AAAA,UACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,UACjD,GAAG2H;AAAA,QACL;AAAA,UACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,MAC/C;AAEI,UAAA,OAAO4F,KAAW,WAAW;AAM/B,cAAM4d,IAAQ,WADE,KAAK,OAAO,MAAM,IAAI,QAAQ5d,GAAQ,EAAE,KAAK,EAAE,MAAM;AAE5D,QAAAwd,EAAA,aAAa,mBAAmBI,CAAK,GAC9C/F,EAAW,KAAK+F;AAAA,MAAA;AAGlB,aAAAhL,EAAI,YAAYiF,CAAU,GAC1BjF,EAAI,YAAYkD,CAAO,GACvBA,EAAQ,YAAY2H,CAAe,GACnC3H,EAAQ,YAAY+B,CAAU,GAC9B4F,EAAgB,YAAYD,CAAQ,GAE7B;AAAA,QACL,KAAA5K;AAAA,QACA,YAAAiF;AAAA,QACA,SAAS,MAAM;AACJ,UAAA2F,EAAA,oBAAoB,UAAUE,CAAa;AAAA,QAAA;AAAA,MAExD;AAAA,IACF;AAAA,EAAA;AAEJ,CAAC,GAEYG,KAAgB5c;AAAA,EAC3Bsc;AAAA,EACAD;AACF,GCtSMQ,KAAa,IAAInkB,EAAU,wBAAwB,GAC5CokB,KAA6B,MACjC,IAAIrkB,EAAO;AAAA,EAChB,KAAKokB;AAAAA,EACL,mBAAmB,CAACE,GAAeC,GAAWnkB,MAAa;AACzD,UAAMI,IAAKJ,EAAS;AACjB,IAAAI,EAAA,QAAQ,wBAAwB,EAAI;AAEvC,QAAIgkB,IAAW;AAKf,WAAApkB,EAAS,IAAI,YAAY,CAACiB,GAAMI,MAAQ;;AAEpC,UAAAJ,EAAK,KAAK,SAAS,oBACnBA,EAAK,WAAY,KAAK,SAAS,oBAC/B;AACA,YAAIojB,IAAW,GAAGpjB,EAAK,WAAY,MAAM,SAAY,CAAC;AAEtD,cAAMqL,IAAY7C,GAAa;AAAA,UAC7B,eAAepI;AAAA,UACf,MAAAJ;AAAA,QAAA,CACD;AAEG,YAAA,CAACqL,EAAU;AACP,gBAAA,IAAI,MAAM,YAAY;AAMxB,cAAA4J,IAAY9V,EAAG,IAAI;AAAA,UACvBkM,EAAU,QAAQ;AAAA,QAAA,EAClB;AAEF,YAAI4J,GAAW;AACb,gBAAMoO,IAAgB7a,GAAa;AAAA,YACjC,eAAe6C,EAAU,QAAQ,YAAY4J,EAAU;AAAA,YACvD,MAAMA;AAAA,UAAA,CACP;AAKD,cAFEoO,EAAc,kBAAkB,oBAEF;AAC1B,gBAAA,CAACA,EAAc;AACX,oBAAA,IAAI,MAAM,YAAY;AAE9B,kBAAMC,IACJD,EAAc,aAAa,KAAK,MAAM;AAExC,YAAAD,KAAY,SAASE,CAAc,IAAI,GAAG,SAAS;AAAA,UAAA;AAAA,QACrD;AAGI,cAAA9Z,IAAc6B,EAAU,aAAa,MACrCpN,IAAQuL,EAAY,MAAM,OAC1B+Z,MACJnkB,IAAA6V,KAAA,gBAAAA,EAAW,eAAX,gBAAA7V,EAAuB,KAAK,UAAS;AAEvC,YAAInB,MAAUmlB,KAAa5Z,EAAY,MAAM,SAAS,CAAC+Z,GAAU;AACpD,UAAAJ,IAAA;AAEX,gBAAM,EAAE,OAAApM,GAAO,GAAGrD,MAAUlK,EAAY;AAExC,UAAArK,EAAG,cAAckM,EAAU,aAAa,WAAW,QAAW;AAAA,YAC5D,GAAGqI;AAAA,YACH,OAAO0P;AAAA,YACP,GAAI,OAAOrM,KAAU,YACnBwM,KAAW;AAAA,cACT,OAAAxM;AAAA,YAAA;AAAA,UACF,CACH;AAAA,QAAA;AAAA,MACH;AAAA,IACF,CACD,GAEMoM,IAAWhkB,IAAK;AAAA,EAAA;AACzB,CACD,GCrEUqkB,KAA6B;AAAA,EACxC,GAAGtf;AAAA,EACH,OAAO,EAAE,SAAS,QAAW,MAAM,SAAS;AAC9C,GAEMuf,KAA+B5d,EAA8B;AAAA,EACjE,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,UAAU;AAAA,EACV,gBAAgB;AACP,WAAA;AAAA,MACL,GAAGpB,GAAkB+e,EAA0B;AAAA;AAAA;AAAA,MAG/C,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,CAACllB,MAAYA,EAAQ,aAAa,YAAY;AAAA,QACzD,YAAY,CAACC,OACJ;AAAA,UACL,cAAcA,EAAW;AAAA,QAC3B;AAAA,MACF;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,gBAAgB;AACP,WAAA;AAAA;AAAA,MAEL,IAAIqf,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,gBAAgB;AAAA,QACjC,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,GAAO,OAAAiJ,QAAY;AACrC,gBAAAxS,IAAY1C,EAA0BC,CAAK;AACjD,cACE,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAClDA,EAAU,kBAAkB;AAE5B;AAEF,gBAAMqY,IAAa,SAAS7F,EAAM,CAAC,CAAC;AAEpC,UAAA2B,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OACGqY,MAAe,KAAK,MACpB;AAAA,gBACC,OAAOA;AAAA,cAAA;AAAA,YAEZ,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAM9O,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MAEpD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,OAAO,MAAMqN,GAAY,KAAK,QAAQ,MAAM;AAAA,MAC5C,eAAe,MAAM;AACnB,cAAM5W,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,wBAAwB;AACf,WAAA,CAAC2X,IAA4B;AAAA,EACtC;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAAC1kB,MAAY;;AACjB,cAAA,OAAOA,KAAY;AACd,mBAAA;AAGT,gBAAM4a,IAAS5a,EAAQ;AAEvB,cAAI4a,MAAW;AACN,mBAAA;AAIP,cAAAA,EAAO,YAAY,QAClBA,EAAO,YAAY,WAAS9Z,IAAA8Z,EAAO,kBAAP,gBAAA9Z,EAAsB,aAAY,MAC/D;AACA,kBAAMskB,IACJ,SAASxK,EAAO,aAAa,OAAO,KAAK,GAAG,KAAK;AAE/C,mBAAA5a,EAAQ,mBAAmBolB,MAAe,IACrC,CAAC,IAGH;AAAA,cACL,OAAOA;AAAA,YACT;AAAA,UAAA;AAGK,iBAAA;AAAA,QACT;AAAA;AAAA;AAAA,QAGA,YAAY,CAAC1jB,GAAMiJ,MACjBkY,GAAmBnhB,GAAMiJ,GAAQ,KAAK,IAAI;AAAA,QAC5C,UAAU;AAAA,QACV,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAlC,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA;AAAA;AAAA;AAAA,MAIL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEYskB,KAAmBzd;AAAA,EAC9Bud;AAAA,EACAD;AACF,GCjKaI,KAAsB;AAAA,EACjC,GAAG1f;AACL,GAEa2f,KAAwBhe,EAA8B;AAAA,EACjE,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,uBAAuB;AACd,WAAA;AAAA,MACL,aAAa,MAAM;AACjB,cAAMwF,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAAC/M,MAAY;;AACrB,iBAAI,OAAOA,KAAY,YAAY,GAACc,IAAAd,EAAQ,gBAAR,QAAAc,EAAqB,UAChD,KAGF,CAAC;AAAA,QACV;AAAA,QACA,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAA2H,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEYykB,KAAY5d;AAAA,EACvB2d;AAAA,EACAD;AACF,GCnEaG,KAAkB;AAAA,EAC7B,GAAG7f;AACL,GAEa8f,KAAoBne,EAA8B;AAAA,EAC7D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,gBAAgB;AACP,WAAA;AAAA;AAAA,MAEL,IAAI+X,GAAU;AAAA,QACZ,MAAM,IAAI,OAAO,QAAQ;AAAA,QACzB,SAAS,CAAC,EAAE,OAAAhV,GAAO,OAAA4W,GAAO,OAAA5K,QAAY;AAC9B,gBAAAvJ,IAAY1C,EAA0BC,CAAK;AAE/C,UAAA,CAACyC,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,aAKpDmU,EACG,EAAA;AAAA,YACCvJ,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,cAC9C,MAAM;AAAA,cACN,OAAO,CAAA;AAAA,YACR,CAAA;AAAA,UAAA,EAGF,YAAY,EAAE,MAAMuJ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAAA,QAAA;AAAA,MAEpD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,uBAAuB;AACd,WAAA;AAAA,MACL,aAAa,MAAM;AACjB,cAAMvJ,IAAY1C,EAA0B,KAAK,OAAO,KAAK;AAE3D,eAAA,CAAC0C,EAAU,oBACXA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,YAE3C,KAGF,KAAK,OAAO,SAAS;AAAA,UAC1B4K,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,UACP,CAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,YAAY;AACH,WAAA;AAAA;AAAA,MAEL;AAAA,QACE,KAAK,2BAA2B,KAAK,OAAO;AAAA,QAC5C,gBAAgB;AAAA,MAClB;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAtE,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EAAA;AAEJ,CAAC,GAEY4kB,KAAQ/d;AAAA,EACnB8d;AAAA,EACAD;AACF,GC/FaG,KAAmB,IACnBC,KAAmB,KACnBC,KAAoB,IAEpBC,KAAiBlmB,EAAU,OAAO;AAAA,EAC7C,MAAM;AAAA,EAEN,uBAAuB,MACd;AAAA,IACLmmB,GAAe;AAAA,MACb,cAAcJ;AAAA,MACd,qBAAqBC;AAAA;AAAA;AAAA;AAAA,MAIrB,MAAM;AAAA,IAAA,CACP;AAAA,IACDI,GAAa;AAAA,EACf;AAAA,EAGF,uBAAuB;AACd,WAAA;AAAA;AAAA,MAEL,OAAO,MAEH,KAAK,OAAO,MAAM,UAAU,SAC5B,KAAK,OAAO,MAAM,UAAU,MAAM,OAAO,KAAK,SAC5C,oBAEF,KAAK,OAAO,SAAS,cAAc,EAAE,MAAM,aAAa,GAEjD,MAGF;AAAA;AAAA;AAAA,MAIT,WAAW,MAAM;AACT,cAAAtG,IAAY,KAAK,OAAO,MAAM,WAC9BuG,IAAmBvG,EAAU,OAC7BwG,IAA2BxG,EAAU,MAAM,iBAAiB,GAC5DyG,IACJzG,EAAU,MAAM,KAAK,EAAE,KAAK,SAAS;AAEvC,eACEuG,KACAC,KACAC;AAAA,MAEJ;AAAA;AAAA,MAEA,KAAK,MACI,KAAK,OAAO,SAAS;AAAA,QAAQ,CAAC,EAAE,OAAA9b,GAAO,UAAAuN,GAAU,MAAA3V,EACtD,MAAAmkB,GAAa,CAAC,EAAE/b,GAAOuN,GAAU3V,CAAI;AAAA,MACvC;AAAA,MAEF,aAAa,MACJ,KAAK,OAAO,SAAS;AAAA,QAAQ,CAAC,EAAE,OAAAoI,GAAO,UAAAuN,GAAU,MAAA3V,EACtD,MAAAmkB,GAAa,EAAE,EAAE/b,GAAOuN,GAAU3V,CAAI;AAAA,MACxC;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,iBAAiBokB,GAAW;AAC1B,UAAMC,IAAU;AAAA,MACd,MAAMD,EAAU;AAAA,MAChB,SAASA,EAAU;AAAA,MACnB,SAASA,EAAU;AAAA,IACrB;AAEO,WAAA;AAAA,MACL,WAAWE;AAAA,QACTC,GAAkBH,GAAW,aAAaC,CAAO;AAAA,MAAA;AAAA,IAErD;AAAA,EAAA;AAEJ,CAAC,GCnEYG,KAAkB;AAAA,EAC7B,WAAW9gB,EAAa;AAC1B,GAEa+gB,KAAoBpf,EAA8B;AAAA,EAC7D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,WAAW;AAAA,EAEX,OAAO;AAAA,EACP,WAAW;AAAA,EAEX,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,MAAA;AAAA,IAET;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAkB,KAAkB;;AACtB,WAAAjE;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAI1D,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MACL;AAAA,QACA1H,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,kBAAiB,CAAA;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAc;AACZ,WAAO,CAAC,EAAE,MAAAW,GAAM,gBAAA+G,QAAqB;;MACnC,MAAMme,UAA2BC,GAAU;AAAA,QACzC,YACSnlB,GACAolB,GACAniB,GACP;AACA,gBAAMjD,GAAMolB,CAAY,GAJjBplB,KAAAA,OAAAA,GACA,KAAA,eAAAolB,GACA,KAAA,6BAAAniB;AAID,gBAAAE,IAAe,SAAS,cAAc,KAAK;AACjD,UAAAA,EAAa,YAAYT;AAAA,YACvB;AAAA,YACAO,EAA2B;AAAA,UAC7B,GACaE,EAAA,aAAa,qBAAqB,OAAO;AACtD,qBAAW,CAACC,GAAWC,CAAK,KAAK,OAAO;AAAA,YACtCJ;AAAA,UAAA;AAEA,YAAIG,MAAc,WACHD,EAAA,aAAaC,GAAWC,CAAK;AAI9C,gBAAMgiB,IAAe,KAAK,KAEpBC,IAAoB,SAAS,cAAc,KAAK;AACtD,UAAAA,EAAkB,YAAY,sBACZA,EAAA,YAAYD,EAAa,UAAW,GAEtDA,EAAa,YAAYC,CAAiB,GAE1CniB,EAAa,YAAYkiB,CAAY;AAC/B,gBAAAE,IAAoB,SAAS,cAAc,KAAK;AACtD,UAAAA,EAAkB,YAAY,2BAC9BA,EAAkB,MAAM,WAAW,YACnCF,EAAa,YAAYE,CAAiB,GAE1C,KAAK,MAAMpiB;AAAA,QAAA;AAAA,QAGb,eAAeqiB,GAAiC;AAE5C,iBAAA,CAAEA,EAAO,OAAuB,QAAQ,qBAAqB,KAC7D,MAAM,eAAeA,CAAM;AAAA,QAAA;AAAA,MAE/B;AAGK,aAAA,IAAIN,EAAmBllB,GAAMmkB,IAAkB;AAAA,QACpD,KAAI/kB,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,iBAAgB,CAAC;AAAA,QACjD,GAAG2H;AAAA,MAAA,CACJ;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC,GAEK0e,KAAiB5f,EAA8B;AAAA,EACnD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EAET,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACvH,MAAY;AAMrB,cALI,OAAOA,KAAY,YAAY,CAACA,EAAQ,eAKxC,CAACA,EAAQ,QAAQ,qBAAqB;AACjC,mBAAA;AAGT,gBAAM4a,IAAS5a,EAAQ;AAEvB,iBAAI4a,MAAW,OACN,KAGLA,EAAO,YAAY,QAAQA,EAAO,YAAY,OACzC,CAAC,IAGH;AAAA,QACT;AAAA,QACA,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAnS,KAAkB;AACtB,WAAA,CAAC,KAAKA,GAAgB,CAAC;AAAA,EAAA;AAElC,CAAC,GAMY2e,KAAW3f,GAAK,OAAgD;AAAA,EAC3E,MAAM;AAAA,EAEN,aAAa;AACJ,WAAA;AAAA,MACL,gBAAgB,CAAA;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,SAAS;AAAA,EAET,WAAW;AAAA,EACX,OAAO;AAAA,EACP,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,MAAM;AAAA,EACvB;AAAA,EAEA,WAAW,EAAE,gBAAAgB,KAAkB;AACtB,WAAA;AAAA,MACL;AAAA,MACA4e,GAAgB,KAAK,QAAQ,gBAAgB5e,CAAc;AAAA,MAC3D;AAAA,IACF;AAAA,EAAA;AAEJ,CAAC;AAKD,SAAS6e,GAAkB5lB,GAAmBiJ,GAAgB;AAatD,QAAA4c,IAZSxE,GAAU,WAAWpY,CAAM,EAYb,MAAMjJ,GAAM;AAAA,IACvC,SAASiJ,EAAO,MAAM,WAAW,OAAO;AAAA,EAAA,CACzC,GACK6c,IAA6B,CAAC;AAGtB,SAAAD,EAAA,QAAQ,YAAY,CAACzb,MAAU;AAE3C,QAAIA,EAAM;AAER,aAAA0b,EAAiB,KAAK1b,CAAK,GACpB;AAAA,EAGF,CACR,GAEMpJ,EAAS,UAAU8kB,CAAgB;AAC5C;AAEO,MAAMC,KAAQ7f;AAAA,EACnB+e;AAAA,EACAD;AAAA,EACA;AAAA,IACEX;AAAA,IACAoB;AAAA,IACAO,GAAY,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQjB,SAAS;AAAA,MACT,YAAY;AACH,eAAA;AAAA,UACL;AAAA,YACE,KAAK;AAAA;AAAA;AAAA,YAGL,YAAY,CAAChmB,GAAMiJ,MACjB2c,GAAkB5lB,GAAqBiJ,CAAM;AAAA,UAAA;AAAA,QAEnD;AAAA,MAAA;AAAA,IACF,CACD;AAAA,IACDgd,GAAU,OAAO;AAAA,MACf,SAAS;AAAA,MACT,YAAY;AACH,eAAA;AAAA,UACL;AAAA,YACE,KAAK;AAAA;AAAA;AAAA,YAGL,YAAY,CAACjmB,GAAMiJ,MACjB2c,GAAkB5lB,GAAqBiJ,CAAM;AAAA,UAAA;AAAA,QAEnD;AAAA,MAAA;AAAA,IACF,CACD;AAAA,IACDyc;AAAA,EAAA;AAEJ,GCtQaQ,KAAoB,CAACC,MAAmC;AAC7D,QAAA5hB,IAAM4hB,EAAa,OAAO,QAC1B1F,IAAe0F,EAAa,SAAS;AAEpC,SAAA,EAAE,KAAA5hB,GAAK,cAAAkc,EAAa;AAC7B,GCUa2F,KACX,gaAEWC,KAAkB;AAAA,EAC7B,eAAeniB,EAAa;AAAA,EAC5B,iBAAiBA,EAAa;AAAA;AAAA,EAE9B,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EAEA,aAAa;AAAA,IACX,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,EAAA;AAEV,GAEaoiB,KAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,YAAYD;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AAAA,EACb,iBAAiB,CAAC,SAAS;AAC7B,GAEaE,KAAc,CACzB/iB,GACAC,MACG;AACG,QAAAmX,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAYwL;AAEX,QAAAI,IAAe,SAAS,cAAc,KAAK;AACjD,EAAAA,EAAa,YAAY;AAEnB,QAAAC,IAAQ,SAAS,cAAc,OAAO;AAC5C,SAAAA,EAAM,YAAY,mBACdhjB,EAAO,iBACTA,EAAO,eAAeD,EAAM,MAAM,GAAG,EAAE,KAAK,CAACuY,MAAgB;AAC3D,IAAA0K,EAAM,MAAM1K;AAAA,EAAA,CACb,IAEK0K,EAAA,MAAMjjB,EAAM,MAAM,KAE1BijB,EAAM,WAAW,IACjBA,EAAM,kBAAkB,SACxBA,EAAM,YAAY,IACZA,EAAA,QAAQjjB,EAAM,MAAM,cAC1BgjB,EAAa,YAAYC,CAAK,GAEvB/G;AAAA,IACLlc;AAAA,IACAC;AAAA,IACA,EAAE,KAAK+iB,EAAa;AAAA,IACpBA;AAAA,IACA/iB,EAAO,WAAW,YAAY,MAAM;AAAA,IACpCmX,EAAK;AAAA,EACP;AACF,GAEa8L,KAAa,CACxBpoB,MACmE;AAC/D,MAAAA,EAAQ,YAAY;AAElB,WAAAA,EAAQ,QAAQ,QAAQ,IACnB,SAGF4nB,GAAkB5nB,CAA2B;AAGlD,MAAAA,EAAQ,YAAY,UAAU;AAC1B,UAAA2d,IAAetC,GAAmBrb,GAAS,OAAO;AACxD,QAAI,CAAC2d;AACI;AAGH,UAAA,EAAE,eAAAnC,GAAe,SAAAE,EAAA,IAAYiC;AAE5B,WAAA;AAAA,MACL,GAAGiK,GAAkBpM,CAAiC;AAAA,MACtD,SAAAE;AAAA,IACF;AAAA,EAAA;AAIJ,GAEa2M,KAAsB,CACjCnjB,MACG;AACC,MAAA,CAACA,EAAM,MAAM,KAAK;AACd,UAAAwD,IAAM,SAAS,cAAc,GAAG;AACtC,WAAAA,EAAI,cAAc,aAEX;AAAA,MACL,KAAKA;AAAA,IACP;AAAA,EAAA;AAGE,MAAAyf;AAaA,SAZAjjB,EAAM,MAAM,eACNijB,IAAA,SAAS,cAAc,OAAO,GAChCA,EAAA,MAAMjjB,EAAM,MAAM,KACpBA,EAAM,MAAM,iBACRijB,EAAA,QAAQjjB,EAAM,MAAM,kBAGpBijB,IAAA,SAAS,cAAc,GAAG,GAC5BA,EAAA,OAAOjjB,EAAM,MAAM,KACzBijB,EAAM,cAAcjjB,EAAM,MAAM,QAAQA,EAAM,MAAM,MAGlDA,EAAM,MAAM,UACVA,EAAM,MAAM,cACP4X,GAAwBqL,GAAOjjB,EAAM,MAAM,OAAO,IAElD8X,GAAsBmL,GAAOjjB,EAAM,MAAM,OAAO,IAIpD;AAAA,IACL,KAAKijB;AAAA,EACP;AACF,GAEaG,KAAahgB,GAAgB0f,IAAkB;AAAA,EAC1D,QAAQC;AAAA,EACR,OAAOG;AAAA,EACP,gBAAgBC;AAClB,CAAC,GC3HYE,KAAoB;AAAA,EAC/B,WAAW/C;AAAA,EACX,SAASrE;AAAA,EACT,OAAOwE;AAAA,EACP,WAAW3F;AAAA,EACX,gBAAgBgE;AAAA,EAChB,kBAAkBqB;AAAA,EAClB,eAAeb;AAAA,EACf,OAAOiD;AAAA,EACP,MAAM3G;AAAA,EACN,OAAO8B;AAAA,EACP,OAAO0F;AAAA,EACP,OAAOzK;AACT,GAEa2K,KAAqB1gB,GAAwBygB,EAAiB,GAO9DE,KAAoB;AAAA,EAC/B,MAAMvZ,GAA8BwZ,IAAM,SAAS;AAAA,EACnD,QAAQxZ,GAA8ByZ,IAAQ,SAAS;AAAA,EACvD,WAAWzZ,GAA8B0Z,IAAW,SAAS;AAAA,EAC7D,QAAQ1Z,GAA8B2Z,IAAQ,SAAS;AAAA,EACvD,MAAM3Z,GAA8B4Z,IAAM,SAAS;AAAA,EACnD,WAAWzI;AAAA,EACX,iBAAiBF;AACnB,GAEa4I,KAAqB5Z,GAAwBsZ,EAAiB,GAO9DO,KAA4B;AAAA,EACvC,MAAM,EAAE,QAAQ,QAAQ,gBAAgB,CAAA,EAAU;AAAA,EAClD,MAAM,EAAE,QAAQ,QAAQ,gBAAgB,CAAU,EAAA;AACpD,GAEaC,KAA6B5a;AAAA,EACxC2a;AACF;AC9DgB,SAAAE,EAKdliB,GACA7B,GAC0E;AAExE,SAAA6B,KAAa7B,EAAO,OAAO,eAC3BA,EAAO,OAAO,YAAY6B,CAAS,MAAMwhB,GAAmBxhB,CAAS;AAEzE;AAEgB,SAAAmiB,GAKdnb,GACA7I,GAKA;AAEE,SAAA6I,KAAqB7I,EAAO,OAAO,uBACnCA,EAAO,OAAO,oBAAoB6I,CAAiB,MACjDib,GAA2Bjb,CAAiB;AAElD;AAEgB,SAAAob,GAKdpiB,GACA9B,GACAC,GAC+D;AAE7D,SAAAD,EAAM,SAAS8B,KACf9B,EAAM,QAAQC,EAAO,OAAO,eAC5B+jB,EAA8BhkB,EAAM,MAAMC,CAAM;AAEpD;AAEgB,SAAAkkB,GAKdnkB,GACAC,GACiD;AAE9C,SAAAD,EAAM,QAAQC,EAAO,OAAO,eAC3BA,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE,eACxC;AAEJ;AAEgB,SAAAokB,GAKdpkB,GACAC,GAOA;AACA,SACGD,EAAM,QAAQC,EAAO,OAAO,eAC3BA,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE,eACtC,iBAAiBC,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE,cACzD;AAEJ;AAEgB,SAAAqkB,GAIdrkB,GAAuBC,GAAkC;AAEzD,SADeA,EAAO,OAAO,YAAYD,EAAM,IAAI,EACrC,eAAe,CAACA,EAAM,MAAM;AAC5C;AAEgB,SAAAskB,GAKdniB,GACAL,GACA7B,GAaA;AAEE,SAAA6B,KAAa7B,EAAO,OAAO,eAC3BkC,KAAQlC,EAAO,OAAO,YAAY6B,CAAS,EAAE,cAC7C7B,EAAO,OAAO,YAAY6B,CAAS,EAAE,WAAWK,CAAI,MAAMzB,EAAayB,CAAI;AAE/E;AAEgB,SAAAoiB,GAKdpiB,GACAnC,GACAC,GAWA;AACA,SAAOqkB,GAA6BniB,GAAMnC,EAAM,MAAMC,CAAM;AAC9D;AAEO,SAASukB,GACd/J,GAC4B;AAC5B,SAAOA,aAAqBgK;AAC9B;ACnKa,MAAAC,KAAkC,OAC7CvN,MACoB;AACd,QAAAwN,IAAO,IAAI,SAAS;AACrB,SAAAA,EAAA,OAAO,QAAQxN,CAAI,IAMhB,OAJI,MAAM,MAAM,sCAAsC;AAAA,IAC5D,QAAQ;AAAA,IACR,MAAAwN;AAAA,EAAA,CACD,GACiB,KAAK,GAAG,KAAK,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,EACF;AACF;ACFA,SAASC,GAIP3kB,GAAwC;AACpC,MAAAD,IACFC,EAAO,sBAAA,EAAwB,OAC7B4kB,IAAc5kB,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE;AAExD,SAAO6kB,MAAgB,UAAQ;AAE7B,QADQ7kB,IAAAC,EAAO,wBAAwB,WACnCD,MAAU;AACZ;AAEF,IAAA6kB,IAAc5kB,EAAO,OAAO,YAAYD,EAAM,IAAI,EAAE,SAI7CC,EAAA,sBAAsBD,GAAO,KAAK;AAAA,EAAA;AAE7C;AAMgB,SAAA8kB,EAKd7kB,GACAD,GACsB;AAChB,QAAA+kB,IAAe9kB,EAAO,sBAAA,EAAwB;AAEhD,MAAA8kB,EAAa,YAAY;AACrB,UAAA,IAAI,MAAM,0DAA0D;AAGxE,MAAAC;AAEJ,SACE,MAAM,QAAQD,EAAa,OAAO,MAChCA,EAAa,QAAQ,WAAW,KAChClnB,GAA0BknB,EAAa,QAAQ,CAAC,CAAC,KACjDA,EAAa,QAAQ,CAAC,EAAE,SAAS,UACjCA,EAAa,QAAQ,CAAC,EAAE,SAAS,OACjCA,EAAa,QAAQ,WAAW,MAEvBC,IAAA/kB,EAAO,YAAY8kB,GAAc/kB,CAAK,GAIjDC,EAAO,sBAAsB+kB,CAAQ,MAE1BA,IAAA/kB,EAAO,aAAa,CAACD,CAAK,GAAG+kB,GAAc,OAAO,EAAE,CAAC,GAChE9kB,EAAO,sBAAsBA,EAAO,sBAAsB,EAAE,SAAU,IAGxE2kB,GAAuC3kB,CAAM,GAEtC+kB;AACT;AAEO,SAASC,GAIdhlB,GAAwC;AACxC,QAAM3F,IAAiC,CAAC;AAEpC,SAAA0pB,EAA8B,WAAW/jB,CAAM,KAC3C3F,EAAA;AAAA,IACJ;AAAA,MACE,aAAa,MAAM;AACjBwqB,QAAAA,EAAoB7kB,GAAQ;AAAA,UAC1B,MAAM;AAAA,UACN,OAAO,EAAE,OAAO,EAAE;AAAA,QAAA,CACnB;AAAA,MACH;AAAA,MACA,OAAOlB,EAAuB,WAAW;AAAA,MACzC,KAAK;AAAA,MACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,IAClC;AAAA,IACA;AAAA,MACE,aAAa,MAAM;AACjB6kB,QAAAA,EAAoB7kB,GAAQ;AAAA,UAC1B,MAAM;AAAA,UACN,OAAO,EAAE,OAAO,EAAE;AAAA,QAAA,CACnB;AAAA,MACH;AAAA,MACA,OAAOlB,EAAuB,WAAW;AAAA,MACzC,KAAK;AAAA,MACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,IAClC;AAAA,IACA;AAAA,MACE,aAAa,MAAM;AACjB6kB,QAAAA,EAAoB7kB,GAAQ;AAAA,UAC1B,MAAM;AAAA,UACN,OAAO,EAAE,OAAO,EAAE;AAAA,QAAA,CACnB;AAAA,MACH;AAAA,MACA,OAAOlB,EAAuB,WAAW;AAAA,MACzC,KAAK;AAAA,MACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,IAAA;AAAA,EAEpC,GAGE+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,KAAK;AAAA,IACL,GAAGA,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,oBAAoB/jB,CAAM,KAC1D3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,aAAa;AAAA,IAC3C,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,kBAAkB/jB,CAAM,KACxD3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,aAAa;AAAA,IAC3C,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,iBAAiB/jB,CAAM,KACvD3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,aAAa;AAAA,IAC3C,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,aAAa/jB,CAAM,KACnD3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,WAAW;AAAA,IACzC,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,aAAa/jB,CAAM,KACnD3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,OAAOlB,EAAuB,WAAW;AAAA,IACzC,KAAK;AAAA,IACL,GAAGkB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjBwqB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,YACJ;AAAA,cACE,OAAO,CAAC,IAAI,IAAI,EAAE;AAAA,YACpB;AAAA,YACA;AAAA,cACE,OAAO,CAAC,IAAI,IAAI,EAAE;AAAA,YAAA;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CACD;AAAA,IACH;AAAA,IACA,OAAO;AAAA,IACP,KAAK;AAAA,IACL,GAAGA,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACX,YAAA4qB,IAAgBJ,EAAoB7kB,GAAQ;AAAA,QAChD,MAAM;AAAA,MAAA,CACP;AAGM,MAAAA,EAAA;AAAA,QAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,UACvC,OAAOilB;AAAA,QACR,CAAA;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,GAAGjlB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACX,YAAA4qB,IAAgBJ,EAAoB7kB,GAAQ;AAAA,QAChD,MAAM;AAAA,MAAA,CACP;AAGM,MAAAA,EAAA;AAAA,QAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,UACvC,OAAOilB;AAAA,QACR,CAAA;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,GAAGjlB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,SAAS/jB,CAAM,KAC/C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACX,YAAA4qB,IAAgBJ,EAAoB7kB,GAAQ;AAAA,QAChD,MAAM;AAAA,MAAA,CACP;AAGM,MAAAA,EAAA;AAAA,QAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,UACvC,OAAOilB;AAAA,QACR,CAAA;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,GAAGjlB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGC+jB,EAA8B,QAAQ/jB,CAAM,KAC9C3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACX,YAAA4qB,IAAgBJ,EAAoB7kB,GAAQ;AAAA,QAChD,MAAM;AAAA,MAAA,CACP;AAGM,MAAAA,EAAA;AAAA,QAAS,CAACtE,MACfA,EAAG,QAAQsE,EAAO,UAAW,QAAQ,CAAC,GAAG;AAAA,UACvC,OAAOilB;AAAA,QACR,CAAA;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,GAAGjlB,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAGH3F,EAAM,KAAK;AAAA,IACT,aAAa,MAAM;AACjB,MAAA2F,EAAO,mBAAmB,KAAK;AAAA,QAC7B,wBAAwB;AAAA,QACxB,mBAAmB;AAAA,MAAA,CACpB;AAAA,IACH;AAAA,IACA,KAAK;AAAA,IACL,GAAGA,EAAO,WAAW,WAAW;AAAA,EAAA,CACjC,GAEM3F;AACT;AAEgB,SAAA6qB,GAEd7qB,GAAY8qB,GAAe;AAC3B,SAAO9qB,EAAM;AAAA,IACX,CAAC,EAAE,OAAA+qB,GAAO,SAAAtK,QACRsK,EAAM,YAAc,EAAA,SAASD,EAAM,YAAa,CAAA,KAC/CrK,KACCA,EAAQ;AAAA,MAAO,CAACuK,MACdA,EAAM,cAAc,SAASF,EAAM,YAAa,CAAA;AAAA,MAChD,WAAW;AAAA,EACnB;AACF;AChTA,SAASG,GAA2D7mB,GAAW;AAC7E,SAAKA,KAGE,OAAO;AAAA,IACZ,OAAO,QAAQA,CAAG,EAAE,OAAO,CAAC,GAAGmB,CAAK,MAAMA,MAAU,MAAS;AAAA,EAC/D;AACF;AAEO,MAAM2lB,GAIX;AAAA,EAoDA,YAAYC,GAIT;AAvDa,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAGA;AAAA,IAAAA,EAAA,yBACd;AAEc,IAAAA,EAAA,eACd;AAEc,IAAAA,EAAA,sBAIZ;AAqCF,SAAK,aAAaH,GAAgBE,KAAA,gBAAAA,EAAM,UAAU,KAAKpC,IACvD,KAAK,qBACHkC,GAAgBE,KAAA,gBAAAA,EAAM,kBAAkB,KAAK3B,IAC/C,KAAK,aAAayB,GAAgBE,KAAA,gBAAAA,EAAM,UAAU,KAAKlC,IAElD,KAAA,cAAc3gB,GAAwB,KAAK,UAAU,GAC1D,KAAK,sBAAsBuG;AAAA,MACzB,KAAK;AAAA,IACP,GACK,KAAA,cAAcc,GAAwB,KAAK,UAAU;AAAA,EAAA;AAAA,EA5C5D,OAAc,OAIZmK,GAaC;AACM,WAAA,IAAIoR,GAITpR,CAAO;AAAA,EAAA;AAwBb;ACpGO,MAAMuR,KAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,YAAY,CAAC;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,cAAc;AAChB,GACaC,KAAkB,MAAM;AAC7B,QAAAC,IAAY,SAAS,cAAc,KAAK;AAE9C,SAAAA,EAAU,YAAY,iBACZA,EAAA,aAAa,mBAAmB,EAAE,GAErC;AAAA,IACL,KAAKA;AAAA,EACP;AACF,GACaC,KAAiB,CAC5BhrB,MACkE;AAClE,MAAIA,EAAQ,YAAY,SAASA,EAAQ,aAAa,iBAAiB;AAC9D,WAAA;AAAA,MACL,MAAM;AAAA,IACR;AAIJ,GACairB,KAA0B,MAAM;AACrC,QAAAF,IAAY,SAAS,cAAc,KAAK;AAEpC,SAAAA,EAAA,aAAa,mBAAmB,EAAE,GAErC;AAAA,IACL,KAAKA;AAAA,EACP;AACF,GAEaG,KAAY5iB,GAAgBuiB,IAAiB;AAAA,EACxD,QAAQC;AAAA,EACR,OAAOE;AAAA,EACP,gBAAgBC;AAClB,CAAC,GCxCYE,KAAkBT,GAAgB,OAAO;AAAA,EACpD,YAAY;AAAA,IACV,WAAWQ;AAAA,EAAA;AAEf,CAAC,GAKYE,KAAgB,CAK3BzgB,MAEO+f,GAAgB,OAAO;AAAA,EAC5B,YAAY;AAAA,IACV,GAAG/f,EAAO;AAAA,IACV,GAAGwgB,GAAgB;AAAA,EACrB;AAAA,EACA,oBAAoBxgB,EAAO;AAAA,EAC3B,YAAYA,EAAO;AAAA,CACpB;ACrBI,SAAS0gB,GAIdlmB,GACqE;AAEnE,SAAA,eAAeA,EAAO,OAAO,eAC7BA,EAAO,OAAO,YAAY,cACxBgmB,GAAgB,YAAY;AAElC;AAEO,SAASG,GAIdnmB,GAAwC;AACxC,QAAM3F,IACJ,CAAC;AAEC,SAAA6rB,GAA6BlmB,CAAM,KACrC3F,EAAM,KAAK;AAAA,IACT,GAAG2F,EAAO,WAAW,WAAW;AAAA,IAChC,aAAa,MAAM;AACjB6kB,MAAAA,EAAoB7kB,GAAQ;AAAA,QAC1B,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAAA,IACA,KAAK;AAAA,EAAA,CACN,GAGI3F;AACT;ACFA,SAAS+rB,GACPpmB,GACoB;AACb,SAAAA,EAAO,SAAS,CAACtE,MAAO;AAC7B,UAAM2qB,IAAqB3iB,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,MAAM;AAErE,QAAAA,EAAG,qBAAqB8oB;AACnB,aAAA;AAAA,QACL,MAAM;AAAA,QACN,eAAe6B,EAAmB,KAAK,MAAM;AAAA,QAC7C,kBACE3qB,EAAG,UAAU,YAAY,MAAM2qB,EAAmB;AAAA,QACpD,gBACE3qB,EAAG,UAAU,UAAU,MAAM2qB,EAAmB;AAAA,MACpD;AACF,QAAW3qB,EAAG,qBAAqB4qB;AAC1B,aAAA;AAAA,QACL,MAAM;AAAA,QACN,eAAeD,EAAmB,KAAK,MAAM;AAAA,MAC/C;AACK;AACL,YAAME,IAAmB7iB,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,IAAI;AAE9D,aAAA;AAAA,QACL,MAAM;AAAA,QACN,eAAe2qB,EAAmB,KAAK,MAAM;AAAA,QAC7C,aAAaE,EAAiB,KAAK,MAAM;AAAA,QACzC,cAAc7qB,EAAG,UAAU,SAAS2qB,EAAmB;AAAA,QACvD,YAAY3qB,EAAG,UAAU,OAAO6qB,EAAiB;AAAA,MACnD;AAAA,IAAA;AAAA,EACF,CACD;AACH;AAaA,SAASC,GACP9qB,GACA+qB,GACA;;AACA,QAAMC,KAAiB/qB,IAAA0U,EAAYoW,EAAK,eAAe/qB,EAAG,GAAG,MAAtC,gBAAAC,EAAyC;AAChE,MAAI+qB,MAAmB;AACrB,UAAM,IAAI;AAAA,MACR,gCAAgCD,EAAK,aAAa;AAAA,IACpD;AAGE,MAAAjM;AACA,MAAAiM,EAAK,SAAS;AAChB,IAAAjM,IAAYgK,GAAc;AAAA,MACxB9oB,EAAG;AAAA,MACHgrB,IAAiBD,EAAK;AAAA,MACtBC,IAAiBD,EAAK;AAAA,IACxB;AAAA,WACSA,EAAK,SAAS;AACvB,IAAAjM,IAAY8L,GAAc,OAAO5qB,EAAG,KAAKgrB,IAAiB,CAAC;AAAA,OACtD;AACL,UAAMC,KAAe/qB,IAAAyU,EAAYoW,EAAK,aAAa/qB,EAAG,GAAG,MAApC,gBAAAE,EAAuC;AAC5D,QAAI+qB,MAAiB;AACnB,YAAM,IAAI;AAAA,QACR,gCAAgCF,EAAK,WAAW;AAAA,MAClD;AAGF,IAAAjM,IAAYD,EAAc;AAAA,MACxB7e,EAAG;AAAA,MACHgrB,IAAiBD,EAAK;AAAA,MACtBE,IAAeF,EAAK;AAAA,IACtB;AAAA,EAAA;AAGF,EAAA/qB,EAAG,aAAa8e,CAAS;AAC3B;AAQA,SAASoM,GACP5e,GACwB;AACjB,SAAAA,EACJ,IAAI,CAACjI,MACAA,EAAM,SAAS,eACVA,EAAM,SACV,IAAI,CAAC8mB,MAAWD,GAAeC,EAAO,QAAQ,CAAC,EAC/C,KAAK,IAGH;AAAA,IACL,GAAG9mB;AAAA,IACH,UAAU6mB,GAAe7mB,EAAM,QAAQ;AAAA,EACzC,CACD,EACA,KAAK;AACV;AAYgB,SAAA+mB,GACd9mB,GACA2R,GACAC,GACA;AAEO,EAAA5R,EAAA,SAAS,CAACtE,MAAO;;AACtB,UAAMsM,MAASrM,IAAAqE,EAAO,aAAa,MAApB,gBAAArE,EAAuB,WAAU;AAAA,MAC9CqE,EAAO,wBAAwB;AAAA,IACjC,GACM+mB,IAAgBX,GAAsBpmB,CAAM;AAElD,IAAAA,EAAO,aAAagI,CAAM,GAC1BhI,EAAO,aAAa4mB,GAAe5e,CAAM,GAAG2J,GAAgBC,CAAS,GAErE4U,GAA6B9qB,GAAIqrB,CAAa;AAAA,EAAA,CAC/C;AACH;AAMA,SAASC,GAAsBC,GAA6C;AACnE,SAAA,CAACA,KAAeA,EAAY,SAAS;AAC9C;AAYA,SAASC,GACPlnB,GACAwR,GACAyV,GAGY;AACR,MAAAtV,GACAC;AAgBA,MAdCJ,IAKMA,EAAU,SAAS,SAAS,KACrCG,IAAiBH,EAAU,SAASA,EAAU,SAAS,SAAS,CAAC,GACrDI,IAAA,YAEKD,IAAAH,GACLI,IAAA,YATRqV,MACetV,IAAAsV,GACLrV,IAAA,WAWZ,CAACD,KAAkB,CAACC;AACf;AAGH,QAAAuV,IAAuBnnB,EAAO,eAAe2R,CAAc;AAC7D,SAACqV,GAAsBG,CAAoB,IAUxC,EAAE,gBAAAxV,GAAgB,WAAAC,EAAU,IAT1BsV;AAAA,IACLlnB;AAAA,IACA4R,MAAc,UACVD,IACA3R,EAAO,aAAa2R,CAAc;AAAA,IACtCwV;AAAA,EACF;AAIJ;AAYA,SAASC,GACPpnB,GACAqnB,GACAJ,GAGY;AACR,MAAAtV,GACAC;AAgBA,MAdCyV,IAKMA,EAAU,SAAS,SAAS,KACpB1V,IAAA0V,EAAU,SAAS,CAAC,GACzBzV,IAAA,aAEKD,IAAA0V,GACLzV,IAAA,WATRqV,MACetV,IAAAsV,GACLrV,IAAA,UAWZ,CAACD,KAAkB,CAACC;AACf;AAGH,QAAAuV,IAAuBnnB,EAAO,eAAe2R,CAAc;AAC7D,SAACqV,GAAsBG,CAAoB,IAUxC,EAAE,gBAAAxV,GAAgB,WAAAC,EAAU,IAT1BwV;AAAA,IACLpnB;AAAA,IACA4R,MAAc,WACVD,IACA3R,EAAO,aAAa2R,CAAc;AAAA,IACtCwV;AAAA,EACF;AAIJ;AAEO,SAASG,GAAatnB,GAAwC;AACnE,EAAAA,EAAO,SAAS,MAAM;AACd,UAAAwa,IAAYxa,EAAO,aAAa,GAChCD,KAAQya,KAAA,gBAAAA,EAAW,OAAO,OAAMxa,EAAO,wBAAwB,OAE/DunB,IAAkBL;AAAA,MACtBlnB;AAAA,MACAA,EAAO,aAAaD,CAAK;AAAA,MACzBC,EAAO,eAAeD,CAAK;AAAA,IAC7B;AAEA,IAAKwnB,KAILT;AAAA,MACE9mB;AAAA,MACAunB,EAAgB;AAAA,MAChBA,EAAgB;AAAA,IAClB;AAAA,EAAA,CACD;AACH;AAEO,SAASC,GAAexnB,GAAwC;AACrE,EAAAA,EAAO,SAAS,MAAM;AACd,UAAAwa,IAAYxa,EAAO,aAAa,GAChCD,KACJya,KAAA,gBAAAA,EAAW,QAAOA,KAAA,gBAAAA,EAAW,OAAO,UAAS,OAC7Cxa,EAAO,sBAAwB,EAAA,OAE3BynB,IAAoBL;AAAA,MACxBpnB;AAAA,MACAA,EAAO,aAAaD,CAAK;AAAA,MACzBC,EAAO,eAAeD,CAAK;AAAA,IAC7B;AAEA,IAAK0nB,KAILX;AAAA,MACE9mB;AAAA,MACAynB,EAAkB;AAAA,MAClBA,EAAkB;AAAA,IACpB;AAAA,EAAA,CACD;AACH;ACpUA,SAASC,GAAaC,GAAoBC,GAAqB;AACtD,SAAA,SAAUziB,GAAoBuN,GAAsC;AACzE,UAAM,EAAE,OAAA+H,GAAO,KAAAoN,EAAI,IAAI1iB,EAAM,WACvBgM,IAAQsJ,EAAM;AAAA,MAClBoN;AAAA,MACA,CAACtrB,MACCA,EAAK,aAAa,MACjBA,EAAK,KAAK,SAAS,gBAAgBA,EAAK,KAAK,SAAS;AAAA;AAAA,IAC3D;AACA,QAAI,CAAC4U;AACI,aAAA;AAET,UAAM8O,IAAa9O,EAAM;AACzB,QAAI8O,MAAe;AACV,aAAA;AAGT,UAAM6H,IADS3W,EAAM,OACK,MAAM8O,IAAa,CAAC;AAC1C,QAAA6H,EAAW,SAASH;AACf,aAAA;AAET,QAAIjV,GAAU;AACZ,YAAMqV,IACJD,EAAW,aAAaA,EAAW,UAAU,SAASF,GAClDI,IAAQzqB,EAAS,KAAKwqB,IAAeJ,EAAS,WAAW,IAAI,GAC7DzqB,IAAQ,IAAIM;AAAA,QAChBD,EAAS;AAAA,UACPoqB,EAAS,OAAO,MAAMpqB,EAAS,KAAKqqB,EAAU,OAAO,MAAMI,CAAK,CAAC,CAAC;AAAA;AAAA,QACpE;AAAA,QACAD,IAAe,IAAI;AAAA,QACnB;AAAA,MACF,GAEME,IAAS9W,EAAM,OACf+W,IAAQ/W,EAAM;AACpB,MAAAuB;AAAA,QACEvN,EAAM,GACH;AAAA,UACC,IAAIgjB;AAAA,YACFF,KAAUF,IAAe,IAAI;AAAA,YAC7BG;AAAA,YACAD;AAAA,YACAC;AAAA,YACAhrB;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,QACF,EAED,eAAe;AAAA,MACpB;AAAA,IAAA;AAEK,WAAA;AAAA,EACT;AACF;AAEO,SAASkrB,GAAUpoB,GAAwC;AAChE,SAAOA,EAAO;AAAA,IAAK,CAACmF,GAAOuN,MACzBgV;AAAA,MACEviB,EAAM,OAAO,MAAM;AAAA,MACnBA,EAAM,OAAO,MAAM;AAAA,IACrB,EAAEA,GAAOuN,CAAQ;AAAA,EACnB;AACF;AAEO,SAAS2V,GAAYroB,GAAwC;AAC3D,EAAAA,EAAA,cAAc,SAAS,aAAa,gBAAgB;AAC7D;AAEO,SAASsoB,GAAatoB,GAAwC;AAC5D,SAAAA,EAAO,SAAS,CAACtE,MAAO;AAC7B,UAAM,EAAE,SAAS6M,MAAmBnD,GAA4B1J,CAAE;AAElE,WAAOA,EAAG,IAAI,QAAQ6M,EAAe,SAAS,EAAE,eAAe;AAAA,EAAA,CAChE;AACH;AAEO,SAASggB,GAAevoB,GAAwC;AAC9D,SAAAA,EAAO,SAAS,CAACtE,MAAO;AAC7B,UAAM,EAAE,SAAS6M,MAAmBnD,GAA4B1J,CAAE;AAElE,WAAOA,EAAG,IAAI,QAAQ6M,EAAe,SAAS,EAAE,QAAQ;AAAA,EAAA,CACzD;AACH;ACnFgB,SAAAigB,GAKd7kB,GACAhC,GACkC;AAClC,QAAMlF,IACJ,OAAOkF,KAAoB,WAAWA,IAAkBA,EAAgB,IACpEoP,IAAW1L,EAAY1B,CAAG,GAE1BqB,IAAUqL,EAAY5T,GAAIkH,CAAG;AACnC,MAAKqB;AAIE,WAAAwC,EAAYxC,EAAQ,MAAM+L,CAAQ;AAC3C;AAEgB,SAAA0X,GAKd9kB,GACAhC,GACkC;AAClC,QAAMlF,IACJ,OAAOkF,KAAoB,WAAWA,IAAkBA,EAAgB,IAEpEqD,IAAUqL,EAAY5T,GAAIkH,CAAG,GAC7BoN,IAAW1L,EAAY1B,CAAG;AAChC,MAAI,CAACqB;AACI;AAIT,QAAM0jB,IADiB/kB,EAAI,QAAQqB,EAAQ,aAAa,EACnB;AACrC,MAAK0jB;AAIE,WAAAlhB,EAAYkhB,GAAe3X,CAAQ;AAC5C;AAEgB,SAAA4X,GAKdhlB,GACAhC,GACkC;AAClC,QAAMlF,IACJ,OAAOkF,KAAoB,WAAWA,IAAkBA,EAAgB,IACpEqD,IAAUqL,EAAY5T,GAAIkH,CAAG,GAC7BoN,IAAW1L,EAAY1B,CAAG;AAChC,MAAI,CAACqB;AACI;AAMT,QAAM0jB,IAHgB/kB,EAAI;AAAA,IACxBqB,EAAQ,gBAAgBA,EAAQ,KAAK;AAAA,EACvC,EACoC;AACpC,MAAK0jB;AAIE,WAAAlhB,EAAYkhB,GAAe3X,CAAQ;AAC5C;AAEgB,SAAA6X,GAKdjlB,GACAhC,GACkC;AAClC,QAAMlF,IACJ,OAAOkF,KAAoB,WAAWA,IAAkBA,EAAgB,IACpEoP,IAAW1L,EAAY1B,CAAG,GAC1BqB,IAAUqL,EAAY5T,GAAIkH,CAAG;AACnC,MAAI,CAACqB;AACI;AAGT,QAAM6jB,IAAiBllB,EAAI,QAAQqB,EAAQ,aAAa,GAClD8jB,IAAaD,EAAe,KAAK,GACjCE,IAAkBF,EAAe,KAAK,EAAE,GACxCH,IACJK,EAAgB,KAAK,SAAS,QAC1BD,EAAW,KAAK,SAAS,eACvBC,IACAD,IACF;AACN,MAAKJ;AAIE,WAAAlhB,EAAYkhB,GAAe3X,CAAQ;AAC5C;AC7GgB,SAAAiY,GACdttB,GACAsI,GACAsL,GACA6E,IAEI,EAAE,iBAAiB,MACvB;AAMA,MAAI,EAAE,MAAAzF,GAAM,IAAAC,MACV,OAAO3K,KAAa,WAChB,EAAE,MAAMA,GAAU,IAAIA,EAAA,IACtB,EAAE,MAAMA,EAAS,MAAM,IAAIA,EAAS,GAAG,GAEzCilB,IAAoB,IACpBC,IAAqB,IAGrBha,IAAO;AAoBP,MAlBEI,EAAA,QAAQ,CAAC/S,MAAS;AAEtB,IAAAA,EAAK,MAAM,GAEP0sB,KAAqB1sB,EAAK,UAAUA,EAAK,MAAM,WAAW,IAC5D2S,KAAQ3S,EAAK,OAEO0sB,IAAA,IAGDC,IAAAA,IAAqB3sB,EAAK,UAAU;AAAA,EAAA,CAC1D,GAOGmS,MAASC,KAAMua,GAAoB;AACrC,UAAM,EAAE,QAAAzT,EAAO,IAAI/Z,EAAG,IAAI,QAAQgT,CAAI;AAItC,IAFE+G,EAAO,eAAe,CAACA,EAAO,KAAK,KAAK,QAAQ,CAACA,EAAO,eAGhD/G,KAAA,GACFC,KAAA;AAAA,EACR;AAKF,SAAIsa,IAUCvtB,EAAA,WAAWwT,GAAMR,GAAMC,CAAE,IAEzBjT,EAAA,YAAYgT,GAAMC,GAAIW,CAAK,GAI5B6E,EAAQ,mBACVgV,GAAwBztB,GAAIA,EAAG,MAAM,SAAS,GAAG,EAAE,GAG9C;AACT;AC/DO,SAAS0tB,GAId1tB,GAAuD;AACjD,QAAAqV,IAAW1L,EAAY3J,CAAE;AAE/B,MAAIA,EAAG,UAAU,SAAS,UAAUA,EAAG;AAC9B;AAGH,QAAA2tB,IAAuB3tB,EAAG,IAAI;AAAA,IAClCgI,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,IAAI,EAAE;AAAA,EAChD,GACM4tB,IAAqB5tB,EAAG,IAAI;AAAA,IAChCgI,EAAmBhI,EAAG,KAAKA,EAAG,UAAU,EAAE,EAAE;AAAA,EAC9C,GAKM6tB,IAAe,CACnB/uB,GACAqJ,MACyB;AACzB,UAAMlH,IAAM0sB,EAAqB,WAAW7uB,GAAOqJ,CAAK,GAClDtH,IAAOb,EAAG,IAAI,QAAQiB,CAAG,EAAE;AAEjC,QAAI,CAACJ;AACH,YAAM,IAAI;AAAA,QACR,wDAAwDI,CAAG;AAAA,MAC7D;AAGK,WAAA6K,EAAYjL,GAAMwU,CAAQ;AAAA,EACnC,GAEM/I,IAAiC,CAAC,GAElCwhB,IAAcH,EAAqB,YAAYC,EAAmB,GAAG,GACrErJ,IAAaoJ,EAAqB,MAAMG,CAAW,GACnDC,IAAWH,EAAmB,MAAME,CAAW;AAgCjD,MAAAH,EAAqB,QAAQG,GAAa;AAE5C,IAAAxhB,EAAO,KAAKR,EAAY6hB,EAAqB,WAAYtY,CAAQ,CAAC;AAIlE,aAASlN,IAAQwlB,EAAqB,OAAOxlB,IAAQ2lB,GAAa3lB;AAGhE,UAFmBwlB,EAAqB,KAAKxlB,CAAK,EAEnC,KAAK,UAAU,gBAAgB,GAAG;AAC/C,cAAM6lB,IAAoBL,EAAqB,MAAMxlB,CAAK,IAAI,GACxD8lB,IAAoBN,EAAqB,KAAKxlB,CAAK,EAAE;AAI3D,iBAAStD,IAAImpB,GAAmBnpB,IAAIopB,GAAmBppB;AACrD,UAAAyH,EAAO,KAAKuhB,EAAahpB,GAAGsD,CAAK,CAAC;AAAA,MACpC;AAAA,EAEJ;AAGA,IAAAmE,EAAO,KAAKuhB,EAAatJ,GAAYuJ,CAAW,CAAC;AAKnD,WAASjpB,IAAI0f,IAAa,GAAG1f,KAAKkpB,GAAUlpB;AAC1C,IAAAyH,EAAO,KAAKuhB,EAAahpB,GAAGipB,CAAW,CAAC;AAGtC,MAAAxhB,EAAO,WAAW;AACpB,UAAM,IAAI;AAAA,MACR,gEAAgEtM,EAAG,SAAS;AAAA,IAC9E;AAGK,SAAA;AAAA,IACL,QAAAsM;AAAA,EACF;AACF;AAEgB,SAAA4hB,GACdluB,GACAmuB,GACAC,GACA;AACA,QAAMC,IACJ,OAAOF,KAAe,WAAWA,IAAaA,EAAW,IACrDG,IAAa,OAAOF,KAAa,WAAWA,IAAWA,EAAS,IAChE/Y,IAAW1L,EAAY3J,CAAE,GACzB8J,IAASC,GAAmBsL,CAAQ;AAE1C,MAAIgZ,MAAiBC;AACnB,UAAM,IAAI;AAAA,MACR,wEAAwED,CAAY;AAAA,IACtF;AAEF,QAAME,IAAgB5Z,EAAY0Z,GAAcruB,EAAG,GAAG;AACtD,MAAI,CAACuuB;AACH,UAAM,IAAI,MAAM,iBAAiBF,CAAY,YAAY;AAE3D,QAAMG,IAAc7Z,EAAY2Z,GAAYtuB,EAAG,GAAG;AAClD,MAAI,CAACwuB;AACH,UAAM,IAAI,MAAM,iBAAiBF,CAAU,YAAY;AAGnD,QAAAG,IAAkBplB,GAAaklB,CAAa,GAC5CG,IAAgBrlB,GAAamlB,CAAW,GAExCG,IACJ7kB,EAAO,YACL2kB,EAAgB,aAClB,GACIG,IACJ9kB,EAAO,YACL4kB,EAAc,aAChB;AAEF,MACE,CAACD,EAAgB,oBACjBE,EAAkB,YAAY;AAE9B,UAAM,IAAI;AAAA,MACR,mEAAmEN,CAAY;AAAA,IACjF;AAEF,MAAI,CAACK,EAAc,oBAAoBE,EAAgB,YAAY;AACjE,UAAM,IAAI;AAAA,MACR,mEAAmEN,CAAU;AAAA,IAC/E;AAGE,MAAAO,GACAC;AAEA,MAAAH,EAAkB,YAAY,SAAS;AACzC,UAAMI,IAAWC,GAAS,IAAIP,EAAgB,aAAa,IAAI;AAK/D,IAAAI,IAHEJ,EAAgB,aAAa,YAC7BM,EAAS,WAAW,GAAG,GAAGN,EAAgB,aAAa,IAAI,IAC3D,IACwB;AAAA,EAAA;AAEf,IAAAI,IAAAJ,EAAgB,aAAa,YAAY;AAGlD,MAAAG,EAAgB,YAAY,SAAS;AACvC,UAAMG,IAAWC,GAAS,IAAIN,EAAc,aAAa,IAAI,GACvDO,IACJP,EAAc,aAAa,YAC3BK,EAAS;AAAA,MACPA,EAAS,SAAS;AAAA,MAClBA,EAAS,QAAQ;AAAA,MACjBL,EAAc,aAAa;AAAA,IAAA,IAE7B,GACIQ,IAAmBlvB,EAAG,IAAI,QAAQivB,CAAW,EAAE,UAAW;AAChE,IAAAH,IAASG,IAAcC,IAAmB;AAAA,EAAA;AAEjC,IAAAJ,IAAAJ,EAAc,aAAa,WAAW;AAOjD,EAAA1uB,EAAG,aAAa6e,EAAc,OAAO7e,EAAG,KAAK6uB,GAAUC,CAAM,CAAC;AAChE;AAEO,SAASK,GAAsBnvB,GAAiB;AAG/C,QAAAqV,IAAW1L,EAAY3J,CAAE;AAC3B,MAAA4X,IAAQ5X,EAAG,UAAU,OACrB6X,IAAM7X,EAAG,UAAU;AAMhB,SAAA6X,EAAI,gBAAgBA,EAAI,OAAO,WAAW,KAAKA,EAAI,QAAQ;AAChE,IAAAA,IAAM7X,EAAG,IAAI,QAAQ6X,EAAI,MAAM,CAAC;AAIlC,SAAOA,EAAI,iBAAiB,KAAKA,EAAI,QAAQ;AAC3C,IAAAA,IAAM7X,EAAG,IAAI,QAAQ6X,EAAI,MAAM,CAAC;AAIlC,SAAOD,EAAM,iBAAiB,KAAKA,EAAM,QAAQ;AAC/C,IAAAA,IAAQ5X,EAAG,IAAI,QAAQ4X,EAAM,MAAM,CAAC;AAI/B,SAAAA,EAAM,gBAAgBA,EAAM,OAAO,WAAW,KAAKA,EAAM,QAAQ;AACtE,IAAAA,IAAQ5X,EAAG,IAAI,QAAQ4X,EAAM,MAAM,CAAC;AAGtC,QAAMwX,IAAgB7iB;AAAA,IACpBvM,EAAG,IAAI,MAAM4X,EAAM,KAAKC,EAAI,KAAK,EAAI;AAAA,IACrCxC;AAAA,EACF;AAEO,SAAA;AAAA,IACL,OAAO;AAAA,MACL,UAAUuC,EAAM;AAAA,MAChB,QAAQC,EAAI;AAAA,IACd;AAAA,IACA,GAAGuX;AAAA,EACL;AACF;AClPO,SAASC,GAIdrvB,GAAoD;AACpD,QAAM,EAAE,SAAA4I,EAAA,IAAYc,GAA4B1J,CAAE,GAC5CqV,IAAW1L,EAAY3J,EAAG,GAAG,GAE7BqI,IAAcrI,EAAG,IAAI,QAAQ4I,EAAQ,SAAS,GAE9C0mB,IAAWjnB,EAAY,YAGvBknB,IAAWvvB,EAAG,IAAI,QAAQ4I,EAAQ,QAAQ,EAAE;AAGlD,MAAIwkB;AACA,SAAA/kB,EAAY,QAAQ,MAEtB+kB,IAAa/kB,EAAY,KAAK,GACzB+kB,EAAW,KAAK,UAAU,SAAS,MAEtCA,IAAa/kB,EAAY,KAAKA,EAAY,QAAQ,CAAC,KAIhD;AAAA,IACL,OAAOyD,EAAYlD,EAAQ,MAAMyM,CAAQ;AAAA,IACzC,WAAWia,MAAa,OAAO,SAAYxjB,EAAYwjB,GAAUja,CAAQ;AAAA,IACzE,WAAWka,MAAa,OAAO,SAAYzjB,EAAYyjB,GAAUla,CAAQ;AAAA,IACzE,aACE+X,MAAe,SAAY,SAAYthB,EAAYshB,GAAY/X,CAAQ;AAAA,EAC3E;AACF;AAEO,SAASma,GACdxvB,GACAyvB,GACAvZ,IAA6B,SAC7B;AACA,QAAMnV,IAAK,OAAO0uB,KAAgB,WAAWA,IAAcA,EAAY,IACjEpa,IAAW1L,EAAY3J,EAAG,GAAG,GAC7B8J,IAASC,GAAmBsL,CAAQ,GAEpC/L,IAAUqL,EAAY5T,GAAIf,EAAG,GAAG;AACtC,MAAI,CAACsJ;AACH,UAAM,IAAI,MAAM,iBAAiBvI,CAAE,YAAY;AAG3C,QAAA8hB,IAAOxZ,GAAaC,CAAO,GAE3B4f,IACJpf,EAAO,YAAY+Y,EAAK,aAAa,EAAG;AAE1C,MAAIA,EAAK,kBAAkB;AACzB,UAAM7e,IAAe6e,EAAK;AAC1B,QAAIqG,MAAgB,QAAQ;AAC1B,MAAAlpB,EAAG,aAAa4qB,GAAc,OAAO5qB,EAAG,KAAKgE,EAAa,SAAS,CAAC;AACpE;AAAA,IAAA;AAGF,QAAIklB,MAAgB;AAClB,MAAIhT,MAAc,UACblW,EAAA;AAAA,QACD6e,EAAc,OAAO7e,EAAG,KAAKgE,EAAa,YAAY,CAAC;AAAA,MACzD,IAEGhE,EAAA;AAAA,QACD6e,EAAc,OAAO7e,EAAG,KAAKgE,EAAa,WAAW,CAAC;AAAA,MACxD;AAAA,aAEOklB,MAAgB;AACzB,MAAIhT,MAAc,UAIblW,EAAA;AAAA,QACD6e,EAAc,OAAO7e,EAAG,KAAKgE,EAAa,YAAY,CAAC;AAAA,MACzD,IAEGhE,EAAA;AAAA,QACD6e,EAAc,OAAO7e,EAAG,KAAKgE,EAAa,WAAW,CAAC;AAAA,MACxD;AAAA;AAGI,YAAA,IAAIpB,EAAqBsmB,CAAW;AAAA,EAC5C,OACK;AACC,UAAAje,IACJiL,MAAc,UACV2M,EAAK,eAAe,KAAK,aACzBA,EAAK,eAAe,KAAK;AAE/B,IAAA2M,GAAsBxvB,GAAIiL,EAAM,MAAM,IAAIiL,CAAS;AAAA,EAAA;AAEvD;ACjHW,IAAAwZ;AAeX,eAAsBC,KAA4B;AAChD,MAAID;AACK,WAAAA;AAEH,QAAAE,IAAO,MAAM,QAAQ,IAAI;AAAA,IAC7B,OAAO,cAAc;AAAA,IACrB,OAAO,kBAAkB;AAAA,IACzB,OAAO,SAAS;AAAA,IAChB,OAAO,oBAAoB;AAAA,IAC3B,OAAO,eAAe;AAAA,IACtB,OAAO,YAAY;AAAA,IACnB,OAAO,kBAAkB;AAAA,IACzB,OAAO,cAAc;AAAA,IACrB,OAAO,eAAe;AAAA,IACtB,OAAO,eAAe;AAAA,EAAA,CACvB;AAEiB,SAAAF,KAAA;AAAA,IAChB,aAAaE,EAAK,CAAC;AAAA,IACnB,iBAAiBA,EAAK,CAAC;AAAA,IACvB,SAASA,EAAK,CAAC;AAAA,IACf,iBAAiBA,EAAK,CAAC;AAAA,IACvB,cAAcA,EAAK,CAAC;AAAA,IACpB,WAAWA,EAAK,CAAC;AAAA,IACjB,iBAAiBA,EAAK,CAAC;AAAA,IACvB,aAAaA,EAAK,CAAC;AAAA,IACnB,cAAcA,EAAK,CAAC;AAAA,IACpB,cAAcA,EAAK,CAAC;AAAA,EACtB,GAEOF;AACT;AC5CO,SAASG,KAAmB;AAC3B,QAAAC,IAAyB,CAACC,MAAqB;AAC/C,QAAAC,IAAmBD,EAAK,SAAS;AAErC,aAASlrB,IAAI,GAAGA,IAAImrB,GAAkBnrB,KAAK;AACnC,YAAAhE,IAAOkvB,EAAK,SAASlrB,CAAC;AAExB,UAAAhE,EAAK,SAAS,cAEhBivB,EAAuBjvB,CAAI,GAEtBA,EAAqB,YAAY;AAGhC,YAAAA,EAAK,SAAS,SAAS,GAAG;AAC5B,UAAAkvB,EAAK,SAAS,OAAOlrB,GAAG,GAAG,GAAGhE,EAAK,QAAQ;AAErC,gBAAAovB,IAAmBpvB,EAAK,SAAS,SAAS;AAC5B,UAAAmvB,KAAAC,GACfprB,KAAAorB;AAAA,QAAA;AAEA,UAAAF,EAAA,SAAS,OAAOlrB,GAAG,CAAC,GAEzBmrB,KACAnrB;AAAA,IAGN;AAAA,EAEJ;AAEO,SAAAirB;AACT;AC9BO,SAASI,KAAwB;AACtC,QAAMC,IAAOT;AAEb,MAAI,CAACS;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAGI,QAAAC,IAAS,CAACL,MAAqB;;AACnC,QAAIA,EAAK,YAAY,YAAYA,EAAK,YAAYA,EAAK,SAAS;AAC9D,eAASlrB,IAAIkrB,EAAK,SAAS,SAAS,GAAGlrB,KAAK,GAAGA,KAAK;AAC5C,cAAAoG,IAAQ8kB,EAAK,SAASlrB,CAAC,GACvBwrB,IACJxrB,IAAI,IAAIkrB,EAAK,SAAS,SAASA,EAAK,SAASlrB,IAAI,CAAC,IAAI;AAGxD,QACEoG,EAAM,SAAS,aACfA,EAAM,YAAY,aAClBhL,IAAAgL,EAAM,eAAN,gBAAAhL,EAAkB,UAAS,eAC3BowB,KAAA,gBAAAA,EAAW,UAAS,aACpBA,EAAU,YAAY,OAItBA,EAAU,UAAU,QAEpBA,EAAU,SAAS;AAAA,UACjB;AAAA,UACA;AAAA,UACAF,EAAK,gBAAgB;AAAA,YACnB,SAAS,eAAe,GAAG;AAAA,UAAA;AAAA,QAE/B,KAEAC,EAAOnlB,CAAmB;AAAA,MAC5B;AAAA,EAGN;AAEO,SAAAmlB;AACT;ACjCO,SAASE,GAAoBC,GAAyB;AAC3D,QAAMJ,IAAOT;AAEb,MAAI,CAACS;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAeF,SAZuBA,EAAK,QACzB,UACA,IAAIA,EAAK,YAAY,SAAS,EAAE,UAAU,GAAM,CAAA,EAChD,IAAIN,EAAgB,EACpB,IAAIK,EAAqB,EACzB,IAAIC,EAAK,aAAa,OAAO,EAC7B,IAAIA,EAAK,UAAU,OAAO,EAC1B,IAAIA,EAAK,gBAAgB,SAAS;AAAA,IACjC,UAAU,EAAE,MAAM,CAACtvB,MAASA,EAAK,MAAM;AAAA,EAAA,CACxC,EACA,YAAY0vB,CAAe,EAER;AACxB;AAEA,eAAsBC,GAKpBlkB,GACAxC,GACAxF,GACAmU,GACiB;AACjB,QAAMkX,GAA0B;AAEhC,QAAMc,IADW9W,GAA2B7P,GAAQxF,CAAM,EAC5B,aAAagI,GAAQmM,CAAO;AAE1D,SAAO6X,GAAoBG,CAAY;AACzC;ACzDA,SAASC,GAAc7vB,GAAe;AACpC,SAAO,MAAM,UAAU,QAAQ,KAAKA,EAAK,cAAe,YAAYA,CAAI;AAC1E;AAEA,SAAS8vB,GAAiB9vB,GAAY;AAC7B,SAAAA,EAAK,aAAa,KAAK,CAAC,KAAK,KAAKA,EAAK,aAAa,EAAE;AAC/D;AAwBA,SAAS+vB,GAAwBzxB,GAAsB;AACrD,EAAAA,EAAQ,iBAAiB,kBAAkB,EAAE,QAAQ,CAACwC,MAAS;AACvD,UAAA7C,IAAQ4xB,GAAc/uB,CAAI,GAC1BkvB,IAAiBlvB,EAAK,eACtBmvB,IAAgB,MAAM,KAAKD,EAAe,UAAU,EAAE;AAAA,MAC1D/xB,IAAQ;AAAA,IACV;AACA,IAAA6C,EAAK,OAAO,GACEmvB,EAAA,QAAQ,CAACC,MAAY;AACjC,MAAAA,EAAQ,OAAO;AAAA,IAAA,CAChB,GAEcF,EAAA,sBAAsB,YAAYlvB,CAAI,GAErDmvB,EAAc,QAAQ,EAAE,QAAQ,CAACC,MAAY;AACvC,UAAAJ,GAAiBI,CAAO;AAC1B;AAEI,YAAAC,IAAmB,SAAS,cAAc,IAAI;AACpD,MAAAA,EAAiB,OAAOD,CAAO,GAC1BpvB,EAAA,sBAAsB,YAAYqvB,CAAgB;AAAA,IAAA,CACxD,GACGH,EAAe,WAAW,WAAW,KACvCA,EAAe,OAAO;AAAA,EACxB,CACD;AACH;AAwBA,SAASI,GAAa9xB,GAAsB;AAC1C,EAAAA,EAAQ,iBAAiB,kBAAkB,EAAE,QAAQ,CAACwC,MAAS;;AAC7D,UAAMuvB,IAAWvvB,EAAK,wBAChBkL,IAAiB,SAAS,cAAc,KAAK;AAE1C,IAAAqkB,EAAA,sBAAsB,YAAYrkB,CAAc,GACzDA,EAAe,OAAOqkB,CAAQ;AAExB,UAAAroB,IAAa,SAAS,cAAc,KAAK;AAI/C,SAHWA,EAAA,aAAa,kBAAkB,YAAY,GACtDgE,EAAe,OAAOhE,CAAU,KAG9B5I,IAAA4M,EAAe,uBAAf,gBAAA5M,EAAmC,cAAa,UAChDC,IAAA2M,EAAe,uBAAf,gBAAA3M,EAAmC,cAAa;AAErC,MAAA2I,EAAA,OAAOgE,EAAe,kBAAkB;AAAA,EACrD,CACD;AACH;AAIA,IAAIskB,KAAgC;AACpC,SAASC,KAAc;AACrB,SACED,OACCA,KAAe,SAAS,eAAe,mBAAmB,OAAO;AAEtE;AAEO,SAASE,GACdC,GACA;AACI,MAAA,OAAOA,KAAkB,UAAU;AACrC,UAAMnyB,IAAUiyB,KAAc,cAAc,KAAK;AACjD,IAAAjyB,EAAQ,YAAYmyB,GACJA,IAAAnyB;AAAA,EAAA;AAElB,SAAAyxB,GAAwBU,CAAa,GACrCL,GAAaK,CAAa,GACnBA;AACT;AChHsB,eAAAC,GAIpB1X,GAAcxE,GAAmD;AAC3D,QAAAmc,IAAWH,GAAgCxX,CAAI,GAO/CuT,IANSlL,GAAU,WAAW7M,CAAQ,EAMlB,MAAMmc,GAAU;AAAA,IACxC,SAASnc,EAAS,MAAM,WAAc,OAAO;AAAA,EAAA,CAC9C,GAEK/I,IAAiC,CAAC;AAExC,WAAS,IAAI,GAAG,IAAI8gB,EAAW,YAAY;AACzC,IAAA9gB,EAAO,KAAKR,EAAYshB,EAAW,MAAM,CAAC,GAAG/X,CAAQ,CAAC;AAGjD,SAAA/I;AACT;ACpBA,SAASmlB,GAAKhoB,GAAY5I,GAAW;AACnC,QAAMqD,IAAQrD,EAAK,QAAQA,EAAK,QAAQ,IAElC6wB,IAAkB,CAAC;AAEzB,EAAI7wB,EAAK,SAEI6wB,EAAA,eAAe,IAAI7wB,EAAK;AAKrC,MAAI8wB,IAAc;AAAA,IAChB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAAD;AAAA,IACA,UAAU,CAAC,EAAE,MAAM,QAAQ,OAAAxtB,EAAO,CAAA;AAAA,EACpC;AAEA,SAAIrD,EAAK,SACP8wB,EAAO,OAAO,EAAE,MAAM9wB,EAAK,KAAK,IAG5B4I,EAAA,MAAM5I,GAAM8wB,CAAM,GACfA,IAAAloB,EAAM,UAAU5I,GAAM8wB,CAAM,GAG5BA,IAAA;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY,CAAC;AAAA,IACb,UAAU,CAACA,CAAM;AAAA,EACnB,GACMloB,EAAA,MAAM5I,GAAM8wB,CAAM,GACjBA;AACT;AAEA,eAAsBC,GAAeC,GAAmC;AAChE,QAAA1B,IAAO,MAAMR,GAA0B;AAe7C,SAbmBQ,EAAK,QACrB,UACA,IAAIA,EAAK,YAAY,OAAO,EAC5B,IAAIA,EAAK,UAAU,OAAO,EAC1B,IAAIA,EAAK,aAAa,SAAS;AAAA,IAC9B,UAAU;AAAA,MACR,GAAIA,EAAK,aAAa;AAAA,MACtBsB,MAAAA;AAAAA,IAAA;AAAA,EACF,CACD,EACA,IAAItB,EAAK,gBAAgB,OAAO,EAChC,YAAY0B,CAAQ,EAEL;AACpB;AAEsB,eAAAC,GAIpBD,GAAkBxc,GAAmD;AAC/D,QAAA0c,IAAa,MAAMH,GAAeC,CAAQ;AAEzC,SAAAN,GAAaQ,GAAY1c,CAAQ;AAC1C;AC7EO,MAAM2c,KAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;ACIA,SAASC,GACPC,GACAC,GACA;AACI,MAAA,CAACD,EAAe,WAAW,GAAG,KAAK,CAACC,EAAe,WAAW,GAAG;AAC7D,UAAA,IAAI,MAAM,qDAAqD;AAGvE,SAAOD,MAAmBC;AAC5B;AAEA,SAASC,GAAoBC,GAAmBC,GAAmB;AAC3D,QAAAC,IAASF,EAAU,MAAM,GAAG,GAC5BG,IAASF,EAAU,MAAM,GAAG;AAE9B,MAAAC,EAAO,WAAW;AACpB,UAAM,IAAI,MAAM,cAAcF,CAAS,4BAA4B;AAEjE,MAAAG,EAAO,WAAW;AACpB,UAAM,IAAI,MAAM,cAAcF,CAAS,4BAA4B;AAGrE,SAAIC,EAAO,CAAC,MAAM,OAAOC,EAAO,CAAC,MAAM,MAC9BD,EAAO,CAAC,MAAMC,EAAO,CAAC,KAE3BD,EAAO,CAAC,MAAM,OAAOC,EAAO,CAAC,MAAM,OAIhCD,EAAO,CAAC,MAAMC,EAAO,CAAC,MAAKD,EAAO,CAAC,MAAMC,EAAO,CAAC;AAC1D;AAEA,SAASrJ,GAKP7kB,GACA2R,GACAoT,GACA;AACI,MAAAoJ;AAGF,SAAA,MAAM,QAAQxc,EAAe,OAAO,KACpCA,EAAe,QAAQ,WAAW,IAElCwc,IAAkBnuB,EAAO,YAAY2R,GAAgBoT,CAAQ,EAAE,KAE/DoJ,IAAkBnuB,EAAO;AAAA,IACvB,CAAC+kB,CAAQ;AAAA,IACTpT;AAAA,IACA;AAAA,EAAA,EACA,CAAC,EAAE,IAGAwc;AACT;AAEsB,eAAAC,GAIpBnxB,GAAmC+C,GAAwC;;AACvE,MAAA,CAACA,EAAO,YAAY;AAEd,YAAA;AAAA,MACN;AAAA,IACF;AACA;AAAA,EAAA;AAGF,QAAMquB,IACJ,kBAAkBpxB,IAAQA,EAAM,eAAeA,EAAM;AACvD,MAAIoxB,MAAiB;AACnB;AAGF,MAAIC,IAAoD;AACxD,aAAWC,KAAYb;AACrB,QAAIW,EAAa,MAAM,SAASE,CAAQ,GAAG;AAChC,MAAAD,IAAAC;AACT;AAAA,IAAA;AAGJ,MAAID,MAAW;AACb;AAGF,QAAMj0B,IAAQg0B,EAAa;AAC3B,MAAI,CAACh0B;AACH;AAGF,EAAA4C,EAAM,eAAe;AAErB,QAAMuxB,IAAmB,OAAO,OAAOxuB,EAAO,OAAO,WAAW,EAAE;AAAA,IAChE,CAACoD,MAAgBA,EAAY;AAAA,EAC/B;AAEA,WAAS7C,IAAI,GAAGA,IAAIlG,EAAM,QAAQkG,KAAK;AAErC,QAAIkuB,IAAgB;AACpB,eAAWnT,KAAmBkT;AAC5B,iBAAWD,KAAYjT,EAAgB,mBAAmB,CAAA,GAAI;AACtD,cAAAoT,IAAkBH,EAAS,WAAW,GAAG,GACzCrX,IAAO7c,EAAMkG,CAAC,EAAE,UAAU;AAEhC,YAAI2W,MAEC,CAACwX,KACAxX,EAAK,QACL4W,GAAoBzzB,EAAMkG,CAAC,EAAE,MAAMguB,CAAQ,KAC5CG,KACCf;AAAA,UACE,MAAMzW,EAAK,KAAK,MAAM,GAAG,EAAE,IAAI;AAAA,UAC/BqX;AAAA,QAAA,IAEJ;AACA,UAAAE,IAAgBnT,EAAgB;AAChC;AAAA,QAAA;AAAA,MAEJ;AAIJ,UAAMpE,IAAO7c,EAAMkG,CAAC,EAAE,UAAU;AAChC,QAAI2W,GAAM;AACR,YAAMyX,IAAY;AAAA,QAChB,MAAMF;AAAA,QACN,OAAO;AAAA,UACL,MAAMvX,EAAK;AAAA,QAAA;AAAA,MAEf;AAEA,UAAIiX;AAEA,UAAAlxB,EAAM,SAAS,SAAS;AACpB,cAAA6nB,IAAe9kB,EAAO,sBAAA,EAAwB;AAClC,QAAAmuB,IAAAtJ,GAAoB7kB,GAAQ8kB,GAAc6J,CAAS;AAAA,MAAA,WAC5D1xB,EAAM,SAAS,QAAQ;AAChC,cAAM2xB,IAAS;AAAA,UACb,MAAO3xB,EAAoB;AAAA,UAC3B,KAAMA,EAAoB;AAAA,QAC5B,GAEMN,KAAMhB,IAAAqE,EAAO,oBAAP,gBAAArE,EAAwB,YAAYizB;AAChD,YAAI,CAACjyB;AACH;AAGgB,QAAAwxB,IAAAnuB,EAAO,SAAS,CAACtE,MAAO;AACxC,gBAAMsJ,IAAUtB,EAAmBhI,EAAG,KAAKiB,EAAI,GAAG;AAC3C,iBAAAkoB;AAAA,YACL7kB;AAAA,YACAA,EAAO,SAASgF,EAAQ,KAAK,MAAM,EAAE;AAAA,YACrC2pB;AAAA,UACF;AAAA,QAAA,CACD;AAAA,MAAA;AAED;AAGF,YAAME,IAAa,MAAM7uB,EAAO,WAAWkX,GAAMiX,CAAe,GAE1DW,IACJ,OAAOD,KAAe,WACjB;AAAA,QACC,OAAO;AAAA,UACL,KAAKA;AAAA,QAAA;AAAA,MACP,IAEF,EAAE,GAAGA,EAAW;AAEf,MAAA7uB,EAAA,YAAYmuB,GAAiBW,CAAgB;AAAA,IAAA;AAAA,EACtD;AAEJ;AChLO,MAAMC,KAA0B,CAKrC/uB,MAEAtF,EAAU,OAA8D;AAAA,EACtE,MAAM;AAAA,EACN,wBAAwB;AACf,WAAA;AAAA,MACL,IAAIQ,EAAO;AAAA,QACT,OAAO;AAAA,UACL,iBAAiB;AAAA,YACf,KAAK8zB,GAAO/xB,GAAO;AACb,kBAAA,CAAC+C,EAAO;AACV;AAGF,kBAAIsuB,IAAoD;AACxD,yBAAWC,KAAYb;AACrB,oBAAIzwB,EAAM,aAAc,MAAM,SAASsxB,CAAQ,GAAG;AACvC,kBAAAD,IAAAC;AACT;AAAA,gBAAA;AAGJ,qBAAID,MAAW,OACN,KAGLA,MAAW,WACbF,GAAoBnxB,GAAO+C,CAAM,GAC1B,MAGF;AAAA,YAAA;AAAA,UACT;AAAA,QACF;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC,GCrDGivB,KAAK,2DAGLC,KAAO,WAAA,sEAAA,GAGP9f,KAAO,4CAGP+d,KAAO,WAAA,gDAAA,GAGPgC,KAAK,4CAGLC,KAAK,oDAGLC,KAAK,2BAGLC,KACJ,oGAGIlK,KAAQ,mEAGRmK,KACJ,+DAGIC,KAAc,sBAGdC,KAAe,mCAGfC,KAAW,sBAOJC,KAAa,CAACC,MACzBX,GAAG,KAAKW,CAAG,KACXV,GAAK,KAAKU,CAAG,KACbxgB,GAAK,KAAKwgB,CAAG,KACbzC,GAAK,KAAKyC,CAAG,KACbT,GAAG,KAAKS,CAAG,KACXR,GAAG,KAAKQ,CAAG,KACXP,GAAG,KAAKO,CAAG,KACXN,GAAO,KAAKM,CAAG,KACfxK,GAAM,KAAKwK,CAAG,KACdL,GAAW,KAAKK,CAAG,KACnBJ,GAAY,KAAKI,CAAG,KACpBH,GAAa,KAAKG,CAAG,KACrBF,GAAS,KAAKE,CAAG;ACzDG,eAAAC,GACpB5yB,GACAF,GACA;AACM,QAAA,EAAE,QAAAyI,MAAWzI,EAAK;AAEpB,MAAA,CAACE,EAAM;AACF,WAAA;AAGT,QAAMiS,IAAOjS,EAAM,cAAe,QAAQ,YAAY;AAEtD,MAAI,CAACiS;AACI,WAAA;AAGL,MAAA,CAAC1J,EAAO,MAAM;AAChB,WAAAzI,EAAK,UAAUmS,CAAI,GACZ;AAGT,QAAM4gB,IAAS7yB,EAAM,cAAe,QAAQ,oBAAoB,GAC1D8yB,IAAaD,IAAS,KAAK,MAAMA,CAAM,IAAI,QAC3C9W,IAAW+W,KAAA,gBAAAA,EAAY;AAE7B,SAAK/W,KAMAjc,EAAA;AAAA,IACH,8BAA8Bic,CAAQ,KAAK9J,EAAK;AAAA,MAC9C;AAAA,MACA;AAAA;AAAA,IAAA,CACD;AAAA,EACH,GAEO,MAZE;AAaX;ACxBA,SAAS8gB,GAAoB;AAAA,EAC3B,OAAA/yB;AAAA,EACA,QAAA+C;AAAA,EACA,4BAAAiwB;AAAA,EACA,qBAAAC;AACF,GAKG;;AASD,MANsBlwB,EAAO;AAAA,IAC3B,CAACtE,MACCA,EAAG,UAAU,MAAM,OAAO,KAAK,KAAK,QACpCA,EAAG,UAAU,IAAI,OAAO,KAAK,KAAK;AAAA,EACtC,GAEmB;AACjB,UAAM+qB,KAAO9qB,IAAAsB,EAAM,kBAAN,gBAAAtB,EAAqB,QAAQ;AAE1C,QAAI8qB;AACF,aAAAzmB,EAAO,UAAUymB,CAAI,GAEd;AAAA,EACT;AAGE,MAAA6H;AACJ,aAAWC,KAAYb;AACrB,QAAIzwB,EAAM,cAAe,MAAM,SAASsxB,CAAQ,GAAG;AACxC,MAAAD,IAAAC;AACT;AAAA,IAAA;AAIJ,MAAI,CAACD;AACI,WAAA;AAGT,MAAIA,MAAW;AACK,WAAAuB,GAAA5yB,GAAO+C,EAAO,eAAgB,GACzC;AAGT,MAAIsuB,MAAW;AACb,WAAAF,GAAoBnxB,GAAO+C,CAAM,GAC1B;AAGT,QAAMymB,IAAOxpB,EAAM,cAAe,QAAQqxB,CAAM;AAEhD,MAAIA,MAAW;AAEN,WAAAtuB,EAAA,UAAUymB,GAAM,EAAI,GACpB;AAGT,MAAI6H,MAAW;AACb,WAAAtuB,EAAO,cAAcymB,CAAI,GAClB;AAGT,MAAIwJ,GAA4B;AAE9B,UAAME,IAAYlzB,EAAM,cAAe,QAAQ,YAAY;AAEvD,QAAA0yB,GAAWQ,CAAS;AACtB,aAAAnwB,EAAO,cAAcmwB,CAAS,GACvB;AAAA,EACT;AAGF,SAAI7B,MAAW,eACbtuB,EAAO,UAAUymB,CAAI,GACd,MAGLyJ,KACFlwB,EAAO,cAAcymB,CAAI,GAClB,OAGTzmB,EAAO,UAAUymB,CAAI,GACd;AACT;AAEO,MAAM2J,KAAoC,CAK/CpwB,GACAqwB,MAKA31B,EAAU,OAAO;AAAA,EACf,MAAM;AAAA,EACN,wBAAwB;AACf,WAAA;AAAA,MACL,IAAIQ,EAAO;AAAA,QACT,OAAO;AAAA,UACL,iBAAiB;AAAA,YACf,MAAM8zB,GAAO/xB,GAAO;AAGd,kBAFJA,EAAM,eAAe,GAEjB,EAAC+C,EAAO;AAIZ,uBAAOqwB,EAAa;AAAA,kBAClB,OAAApzB;AAAA,kBACA,QAAA+C;AAAA,kBACA,qBAAqB,CAAC;AAAA,oBACpB,4BAAAiwB,IAA6B;AAAA,oBAC7B,qBAAAC,IAAsB;AAAA,kBACxB,IAAI,OACKF,GAAoB;AAAA,oBACzB,OAAA/yB;AAAA,oBACA,QAAA+C;AAAA,oBACA,4BAAAiwB;AAAA,oBACA,qBAAAC;AAAA,kBAAA,CACD;AAAA,gBACH,CACD;AAAA,YAAA;AAAA,UACH;AAAA,QACF;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC;AC1II,SAASI,GAIdlzB,GAAoB;AAGpB,QAAM4K,IAAqC,CAAC;AACnC,SAAA5K,EAAA,YAAY,CAACb,MAAS;;AACvB,UAAAwU,IAAW1L,EAAY9I,CAAI;AAC7B,WAAAA,EAAK,KAAK,SAAS,sBACjBZ,IAAAY,EAAK,eAAL,gBAAAZ,EAAiB,KAAK,UAAS,eAoB1B,KAIPY,EAAK,KAAK,SAAS,gBAAgBA,EAAK,eAAe,MAEpDX,IAAAW,EAAA,eAAA,QAAAX,EAAY,QAAQ,CAAC+K,MAAU;AAClC,MAAAqB,EAAO,KAAKR,EAAYb,GAAOoK,CAAQ,CAAC;AAAA,IAAA,IAEnC,MAGLxU,EAAK,KAAK,UAAU,SAAS,KAC/ByL,EAAO,KAAKR,EAAYjL,GAAMwU,CAAQ,CAAC,GAEhC,MAEF;AAAA,EAAA,CACR,GACM/I;AACT;AC5CA,SAASuoB,GAKPxzB,GACAyzB,GACAxwB,GACA;;AACA,MAAIywB,IAAuB;AACrB,QAAAC,IAAgB3zB,EAAK,MAAM,qBAAqBynB;AAEtD,MAAI,CAACkM,GAAe;AAIZ,UAAAC,IAAyB5zB,EAAK,MAAM,IAAI;AAAA,MAC5CA,EAAK,MAAM,UAAU;AAAA,MACrBA,EAAK,MAAM,UAAU;AAAA,MACrB;AAAA,IAAA,EACA,SAEI+K,IAAW,CAAC;AAClB,aAASvH,IAAI,GAAGA,IAAIowB,EAAuB,YAAYpwB;AACrD,MAAAuH,EAAS,KAAK6oB,EAAuB,MAAMpwB,CAAC,CAAC;AAG/C,IAAAkwB,IACE3oB,EAAS;AAAA,MACP,CAACnB,MACCA,EAAM,KAAK,UAAU,SAAS,KAC9BA,EAAM,KAAK,SAAS,gBACpBA,EAAM,KAAK,KAAK,UAAU;AAAA,IAAA,MACxB,QACJ8pB,MACiBD,IAAAG;AAAA,EACrB;AAGE,MAAAxE;AAEJ,QAAMyE,IAAuBvb;AAAA,IAC3BtY,EAAK,MAAM;AAAA,IACXiD;AAAA,EACF;AAEA,MAAI0wB,GAAe;AACjB,MAAI/0B,IAAA60B,EAAiB,eAAjB,gBAAA70B,EAA6B,KAAK,UAAS,YAG7C60B,IAAmBA,EAAiB,WAAW;AAKjD,UAAM5b,IAAK9O;AAAA,MACT0qB;AAAA,MACAxwB,EAAO,OAAO;AAAA,MACdA,EAAO,OAAO;AAAA,IAChB;AAGA,IAAAmsB,IAAe,UAAUyE,EAAqB;AAAA,MAC5Chc;AAAA,MACA,CAAA;AAAA,IACD,CAAA;AAAA,aACQ6b,GAAsB;AAG/B,UAAM7b,IAAKhO;AAAA,MACT4pB;AAAA,MACAxwB,EAAO,OAAO;AAAA,MACdA,EAAO,OAAO;AAAA,IAChB;AACA,IAAAmsB,IAAeyE,EAAqB,oBAAoBhc,GAAI,CAAA,CAAE;AAAA,EAAA,OACzD;AACC,UAAA5M,IAASsoB,GAAiBE,CAAgB;AAChD,IAAArE,IAAeyE,EAAqB,aAAa5oB,GAAQ,CAAA,CAAE;AAAA,EAAA;AAEtD,SAAAmkB;AACT;AAEgB,SAAA0E,GAKd9zB,GACAiD,GAKA;AAME,EAAA,UAAUjD,EAAK,MAAM,aACpBA,EAAK,MAAM,UAAU,KAAc,KAAK,KAAK,UAAU,kBAEjDiD,EAAA;AAAA,IAAS,CAACtE,MACfA,EAAG;AAAA,MACD,IAAI4qB,GAAc5qB,EAAG,IAAI,QAAQqB,EAAK,MAAM,UAAU,OAAO,CAAC,CAAC;AAAA,IAAA;AAAA,EAEnE;AAIF,QAAM+zB,IAAwB/zB,EAAK;AAAA,IACjCA,EAAK,MAAM,UAAU,QAAQ;AAAA,IAC7B,IAAI,WAEAyzB,IAAmBzzB,EAAK,MAAM,UAAU,QAAU,EAAA,SAElDovB,IAAeoE;AAAA,IACnBxzB;AAAA,IACAyzB;AAAA,IACAxwB;AAAA,EACF,GAEMutB,IAAWvB,GAAoBG,CAAY;AAE1C,SAAA,EAAE,eAAA2E,GAAe,cAAA3E,GAAc,UAAAoB,EAAS;AACjD;AAEA,MAAMwD,KAAqC,MAAM;AAGzC,QAAAvW,IAAY,OAAO,aAAa;AAClC,MAAA,CAACA,KAAaA,EAAU;AACnB,WAAA;AAQT,MAAIje,IAAOie,EAAU;AACrB,SAAOje,KAAM;AACX,QACEA,aAAgB,eAChBA,EAAK,aAAa,iBAAiB,MAAM;AAElC,aAAA;AAGT,IAAAA,IAAOA,EAAK;AAAA,EAAA;AAGP,SAAA;AACT,GAEMy0B,KAAkB,CAKtBhxB,GACAjD,GACAE,MACG;AAEH,EAAAA,EAAM,eAAe,GACrBA,EAAM,cAAe,UAAU;AAE/B,QAAM,EAAE,eAAA6zB,GAAe,cAAA3E,GAAc,UAAAoB,EAAa,IAAAsD;AAAA,IAChD9zB;AAAA,IACAiD;AAAA,EACF;AAIM,EAAA/C,EAAA,cAAe,QAAQ,kBAAkB6zB,CAAa,GACtD7zB,EAAA,cAAe,QAAQ,aAAakvB,CAAY,GAChDlvB,EAAA,cAAe,QAAQ,cAAcswB,CAAQ;AACrD,GAEa0D,KAAiC,CAK5CjxB,MAEAtF,EAAU,OAA8D;AAAA,EACtE,MAAM;AAAA,EACN,wBAAwB;AACf,WAAA;AAAA,MACL,IAAIQ,EAAO;AAAA,QACT,OAAO;AAAA,UACL,iBAAiB;AAAA,YACf,KAAK6B,GAAME,GAAO;AAChB,qBAAI8zB,QAIYC,GAAAhxB,GAAQjD,GAAME,CAAK,GAE5B;AAAA,YACT;AAAA,YACA,IAAIF,GAAME,GAAO;AACf,qBAAI8zB,SAIYC,GAAAhxB,GAAQjD,GAAME,CAAK,GAC/BF,EAAK,YACPA,EAAK,SAASA,EAAK,MAAM,GAAG,iBAAiB,IAGxC;AAAA,YACT;AAAA;AAAA;AAAA;AAAA,YAIA,UAAUA,GAAME,GAAO;AAOrB,kBALI,EAAE,UAAUF,EAAK,MAAM,cAMxBA,EAAK,MAAM,UAAU,KAAc,KAAK,KAAK,UAC9C;AAEA;AAIK,cAAAiD,EAAA;AAAA,gBAAS,CAACtE,MACfA,EAAG;AAAA,kBACD,IAAI4qB;AAAA,oBACF5qB,EAAG,IAAI,QAAQqB,EAAK,MAAM,UAAU,OAAO,CAAC;AAAA,kBAAA;AAAA,gBAC9C;AAAA,cAEJ,GAGAE,EAAM,eAAe,GACrBA,EAAM,aAAc,UAAU;AAE9B,oBAAM,EAAE,eAAA6zB,GAAe,cAAA3E,GAAc,UAAAoB,EACnC,IAAAsD,GAAuB9zB,GAAMiD,CAAM;AAI/B,qBAAA/C,EAAA,aAAc,QAAQ,kBAAkB6zB,CAAa,GACrD7zB,EAAA,aAAc,QAAQ,aAAakvB,CAAY,GAC/ClvB,EAAA,aAAc,QAAQ,cAAcswB,CAAQ,GAG3C;AAAA,YAAA;AAAA,UACT;AAAA,QACF;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC,GCvRU2D,KAA2Bx2B,EAAU,OAAO;AAAA,EACvD,MAAM;AAAA,EAEN,sBAAsB;AACb,WAAA;AAAA,MACL;AAAA,QACE,OAAO,CAAC,kBAAkB,aAAa,aAAa;AAAA,QACpD,YAAY;AAAA,UACV,iBAAiB;AAAA,YACf,SAAS+F,EAAa,gBAAgB;AAAA,YACtC,WAAW,CAAC5F,MACVA,EAAQ,aAAa,uBAAuB,IACxCA,EAAQ,aAAa,uBAAuB,IAC5C4F,EAAa,gBAAgB;AAAA,YACnC,YAAY,CAAC3F,MAETA,EAAW,oBACX2F,EAAa,gBAAgB,UAEtB,CAAC,IAEH;AAAA,cACL,yBAAyB3F,EAAW;AAAA,YACtC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC;ACrBM,MAAMq2B,GAA4C;AAAA,EAAlD;AAEG;AAAA,IAAA1L,EAAA,mBAA2C,CAAC;AAAA;AAAA,EAE7C,GACLxoB,GACAm0B,GACA;AACA,WAAK,KAAK,UAAUn0B,CAAK,MAClB,KAAA,UAAUA,CAAK,IAAI,CAAC,IAG3B,KAAK,UAAUA,CAAK,EAAE,KAAKm0B,CAAE,GAEtB,MAAM,KAAK,IAAIn0B,GAAOm0B,CAAE;AAAA,EAAA;AAAA,EAGvB,KACRn0B,MACGo0B,GACH;AACM,UAAAC,IAAY,KAAK,UAAUr0B,CAAK;AAEtC,IAAIq0B,KACFA,EAAU,QAAQ,CAACC,MAAaA,EAAS,MAAM,MAAMF,CAAI,CAAC;AAAA,EAC5D;AAAA,EAGK,IACLp0B,GACAm0B,GACA;AACM,UAAAE,IAAY,KAAK,UAAUr0B,CAAK;AAEtC,IAAIq0B,MACEF,IACG,KAAA,UAAUn0B,CAAK,IAAIq0B,EAAU,OAAO,CAACC,MAAaA,MAAaH,CAAE,IAE/D,OAAA,KAAK,UAAUn0B,CAAK;AAAA,EAE/B;AAAA,EAGQ,qBAA2B;AACnC,SAAK,YAAY,CAAC;AAAA,EAAA;AAEtB;ACvDO,MAAeu0B,UAEZL,GAAqB;AAAA;AAAA,EAe7B,eAAeM,GAAc;AACrB,UAAA;AAPQ,IAAAhM,EAAA,iBAAoB,CAAC;AAAA,EAO7B;AAAA,EAfR,OAAc,MAAc;AACpB,UAAA,IAAI,MAAM,qDAAqD;AAAA,EAAA;AAAA,EAG7D,qBAAqBiM,GAAgB;AACxC,SAAA,QAAQ,KAAKA,CAAM;AAAA,EAAA;AAAA,EAI1B,IAAW,WAA+B;AAAA,EACjC;AASX;ACdO,MAAMC,KAAN,MAAMA,WAAqBH,EAAmB;AAAA,EAUnD,YACUI,GAOR;AACM,UAAA;AAdA,IAAAnM,EAAA;AACA,IAAAA,EAAA;AA+DA,IAAAA,EAAA,sBAAe,CAACoM,GAAyBC,MAAqB;AACpE,UAAIC,IAAa,KAAK,uBAAuB,IAAID,CAAQ;AAEzD,UAAI,CAACC,GAAY;AACf,cAAMC,KACJ,KAAK,cAAc,gBAAgBL,GAAa,qBAChDE,CAAI;AAEF,QAAA,KAAK,cAAc,qBAAqB,aAC5BG,EAAA,iBAAiB,cAAc,MAAM;AACjD,gBAAMC,IAAS,KAAK,uBAAuB,IAAIH,CAAQ;AAChD,UAAAG,EAAA,QAAQ,aAAa,eAAe,EAAE,GAEzCA,EAAO,gBACT,aAAaA,EAAO,WAAW,GAC1B,KAAA,uBAAuB,IAAIH,GAAU;AAAA,YACxC,SAASG,EAAO;AAAA,YAChB,aAAa;AAAA,UAAA,CACd;AAAA,QACH,CACD,GAEaD,EAAA,iBAAiB,cAAc,MAAM;AACjD,gBAAMC,IAAS,KAAK,uBAAuB,IAAIH,CAAQ;AAElD,eAAA,uBAAuB,IAAIA,GAAU;AAAA,YACxC,SAASG,EAAO;AAAA,YAChB,aAAa,WAAW,MAAM;AACrB,cAAAA,EAAA,QAAQ,gBAAgB,aAAa;AAAA,YAAA,GAC3C,GAAI;AAAA,UAAA,CACR;AAAA,QAAA,CACF,IAGUF,IAAA;AAAA,UACX,SAASC;AAAA,UACT,aAAa;AAAA,QACf,GAEK,KAAA,uBAAuB,IAAIF,GAAUC,CAAU;AAAA,MAAA;AAGtD,aAAOA,EAAW;AAAA,IACpB;AAEO,IAAAtM,EAAA,oBAAa,CAACoM,MAIf;AACJ,WAAK,SAAS,UAAU,mBAAmB,QAAQA,CAAI;AAAA,IACzD;AA7GU,SAAA,gBAAAD,GASR,KAAK,WAAWA,EAAc,UACzB,KAAA,6CAA6B,IAAI,GAEtC,KAAK,SAAS,UAAU,mBAAmB,QAAQA,EAAc,IAAI,GAEjEA,EAAc,qBAAqB,YACrC,KAAK,SAAS,UAAU;AAAA,MACtB;AAAA,MACA,CAAC;AAAA,QACC,SAAAM;AAAA,MAAA,MAKI;AACJ,mBAAWJ,KAAYI,GAAS;AAC9B,gBAAMD,IAAS,KAAK,uBAAuB,IAAIH,CAAQ;AAEvD,UAAIG,MACKA,EAAA,QAAQ,aAAa,eAAe,EAAE,GAEzCA,EAAO,eACT,aAAaA,EAAO,WAAW,GAG5B,KAAA,uBAAuB,IAAIH,GAAU;AAAA,YACxC,SAASG,EAAO;AAAA,YAChB,aAAa,WAAW,MAAM;AACrB,cAAAA,EAAA,QAAQ,gBAAgB,aAAa;AAAA,YAAA,GAC3C,GAAI;AAAA,UAAA,CACR;AAAA,QACH;AAAA,MACF;AAAA,IAEJ,GAGG,KAAA;AAAA,MACHE,GAAc,KAAK,SAAS,WAAW;AAAA,QACrC,kBAAkBC;AAAA,QAClB,eAAe,KAAK;AAAA,MACrB,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA7DF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA+DT,IAAW,WAAW;AACb,WAAA;AAAA,EAAA;AAgFX;AAxBE3M,EA1HWkM,IA0HG,uBAAsB,CAACE,MAA4B;AACzD,QAAAG,IAAgB,SAAS,cAAc,MAAM;AAErC,EAAAA,EAAA,UAAU,IAAI,+BAA+B;AAErD,QAAAK,IAAe,SAAS,cAAc,MAAM;AACrC,EAAAA,EAAA,aAAa,qBAAqB,OAAO,GACzCA,EAAA,UAAU,IAAI,gCAAgC,GAC3DA,EAAa,aAAa,SAAS,qBAAqBR,EAAK,KAAK,EAAE;AAE9D,QAAAS,IAAe,SAAS,cAAc,MAAM;AAErC,SAAAA,EAAA,UAAU,IAAI,gCAAgC,GAC3DA,EAAa,aAAa,SAAS,qBAAqBT,EAAK,KAAK,EAAE,GACpES,EAAa,aAAa,SAAS,eAAeT,EAAK,IAAI,GAAG,IAAI,GAErDQ,EAAA,aAAaC,GAAc,IAAI,GAE5CN,EAAc,aAAa,SAAS,eAAe,GAAQ,GAAG,IAAI,GACpDA,EAAA,aAAaK,GAAc,IAAI,GAC7CL,EAAc,aAAa,SAAS,eAAe,GAAQ,GAAG,IAAI,GAE3DA;AACT;AAjJK,IAAMO,KAANZ;ACPA,MAAMa,WAAmBhB,EAAmB;AAAA,EACjD,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,YAAYp0B,GAAyB;AAC7B,UAAA,GACD,KAAA,qBAAqBq1B,GAAYr1B,CAAQ,CAAC;AAAA,EAAA;AAAA,EAGjD,IAAW,WAAW;AACb,WAAA;AAAA,EAAA;AAEX;ACdO,MAAMs1B,WAAmBlB,EAAmB;AAAA,EACjD,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,cAAc;AACN,UAAA,GACD,KAAA,qBAAqBmB,IAAa;AAAA,EAAA;AAAA,EAGzC,IAAW,WAAW;AACb,WAAA;AAAA,EAAA;AAEX;ACda,MAAAC,KAAcvoB,GAAK,OAAO;AAAA,EACrC,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa;AAAA,EAEb,gBAAgB;AAEP,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAKL,QAAQ;AAAA,QACN,WAAW,CAACxP,MAAY,CAAC,CAACA,EAAQ,aAAa,aAAa;AAAA,QAC5D,YAAY,CAACC,MACHA,EAAmC,SACvC;AAAA,UACE,eAAe;AAAA,QAAA,IAEjB,CAAC;AAAA,QAEP,SAAS;AAAA,MACX;AAAA,MACA,UAAU;AAAA,QACR,WAAW,CAACD,MAAYA,EAAQ,aAAa,mBAAmB;AAAA,QAChE,YAAY,CAACC,OACJ;AAAA,UACL,qBAAsBA,EAAoC;AAAA,QAC5D;AAAA,QAEF,SAAS;AAAA,MAAA;AAAA,IAEb;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAwI,KAA2D;AAC/D,WAAA;AAAA,MACL;AAAA,MACA4e,GAAgB5e,GAAgB;AAAA,QAC9B,OAAO;AAAA,MACR,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,uBAAuB;AAAA,EACxC;AAAA,EAEA,iBAAiB6d,GAAW;AACtB,WAAAA,EAAU,SAAS,YACd;AAAA,MACL,iBAAiB;AAAA,IACnB,IAEK,CAAC;AAAA,EAAA;AAEZ,CAAC;AClDM,MAAM0R,WAAkC1B,GAAkB;AAAA,EAMxD,YACY2B,GACjB;AACM,UAAA;AARA,IAAArN,EAAA,uCAAgC,IAAI;AAGpC;AAAA,IAAAA,EAAA,0CAAmB,IAAY;AAGpB,SAAA,eAAAqN;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAQnB,MAAa,UAAUC,GAAmB;AACxC,UAAMC,IAAeD,EAAQ;AAAA,MAC3B,CAACt2B,MAAO,CAAC,KAAK,UAAU,IAAIA,CAAE,KAAK,CAAC,KAAK,aAAa,IAAIA,CAAE;AAAA,IAC9D;AAEI,QAAAu2B,EAAa,WAAW,GAI5B;AAAA,iBAAWv2B,KAAMu2B;AACV,aAAA,aAAa,IAAIv2B,CAAE;AAGtB,UAAA;AACF,cAAMw2B,IAAQ,MAAM,KAAK,aAAaD,CAAY;AAClD,mBAAWnB,KAAQoB;AACjB,eAAK,UAAU,IAAIpB,EAAK,IAAIA,CAAI;AAE7B,aAAA,KAAK,UAAU,KAAK,SAAS;AAAA,MAAA,UAClC;AACA,mBAAWp1B,KAAMu2B;AAIV,eAAA,aAAa,OAAOv2B,CAAE;AAAA,MAC7B;AAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQK,QAAQy2B,GAA+B;AACrC,WAAA,KAAK,UAAU,IAAIA,CAAM;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS3B,UAAUC,GAAiD;AACzD,WAAA,KAAK,GAAG,UAAUA,CAAE;AAAA,EAAA;AAE/B;ACzDA,MAAM7T,KAAa,IAAInkB,EAAU,oBAAoB,GAC/Ci4B,KAAyB;AAY/B,SAASC,GAA0B1vB,GAAW2vB,GAAkB;AACxD,QAAAC,wBAAsB,IAA0C;AAGlE,SAAA5vB,EAAA,YAAY,CAACpH,GAAMI,MAAQ;AACxB,IAAAJ,EAAA,MAAM,QAAQ,CAAC+K,MAAS;AACvB,UAAAA,EAAK,KAAK,SAASgsB,GAAU;AACzB,cAAAE,IAAgBlsB,EAAK,MACxB;AACH,YAAI,CAACksB;AACH;AAEF,cAAM9kB,IAAO/R,GACPgS,IAAKD,IAAOnS,EAAK,UAIjBk3B,IAAkBF,EAAgB,IAAIC,CAAY,KAAK;AAAA,UAC3D,MAAM;AAAA,UACN,IAAI;AAAA,QACN;AACA,QAAAD,EAAgB,IAAIC,GAAc;AAAA,UAChC,MAAM,KAAK,IAAI9kB,GAAM+kB,EAAgB,IAAI;AAAA,UACzC,IAAI,KAAK,IAAI9kB,GAAI8kB,EAAgB,EAAE;AAAA,QAAA,CACpC;AAAA,MAAA;AAAA,IACH,CACD;AAAA,EAAA,CACF,GACMF;AACT;AAEO,MAAMG,WAAuBlC,EAAmB;AAAA,EA0ErD,YACmBxxB,GACD2zB,GACCL,GACjB;AACM,UAAA;AA1EQ,IAAA7N,EAAA;AAKR;AAAA;AAAA;AAAA,IAAAA,EAAA,wBAAiB;AAKjB;AAAA;AAAA;AAAA,IAAAA,EAAA;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,6CACF,IAAI;AAaF;AAAA;AAAA;AAAA,IAAAA,EAAA,gCAAyB,CAACmO,MAAqC;AAChE,WAAA,OAAO,SAAS,CAACl4B,MAAO;AAC3B,QAAAA,EAAG,IAAI,YAAY,CAACa,GAAMI,MAAQ;AAC3B,UAAAJ,EAAA,MAAM,QAAQ,CAAC+K,MAAS;AAC3B,gBAAIA,EAAK,KAAK,SAAS,KAAK,UAAU;AACpC,oBAAMgsB,IAAWhsB,EAAK,MAChBusB,IAAevsB,EAAK,MAAM,UAC1BwsB,IAASF,EAAQ,IAAIC,CAAY,GACjCE,IAAW,CAAC,EAAE,CAACD,KAAUA,EAAO,YAAYA,EAAO;AAErD,kBAAAC,MAAazsB,EAAK,MAAM,QAAQ;AAClC,sBAAM0sB,IAAc,KAAK,IAAIr3B,GAAK,CAAC,GAC7Bs3B,IAAY,KAAK;AAAA,kBACrBt3B,IAAMJ,EAAK;AAAA,kBACXb,EAAG,IAAI,QAAQ,OAAO;AAAA,kBACtBA,EAAG,IAAI,QAAQ,OAAO;AAAA,gBACxB;AACG,gBAAAA,EAAA,WAAWs4B,GAAaC,GAAW3sB,CAAI,GACvC5L,EAAA;AAAA,kBACDs4B;AAAA,kBACAC;AAAA,kBACAX,EAAS,OAAO;AAAA,oBACd,GAAGhsB,EAAK;AAAA,oBACR,QAAQysB;AAAA,kBACT,CAAA;AAAA,gBACH,GAEIA,KAAY,KAAK,qBAAqBF,MAExC,KAAK,mBAAmB,QACxB,KAAK,gBAAgB;AAAA,cACvB;AAAA,YACF;AAAA,UACF,CACD;AAAA,QAAA,CACF;AAAA,MAAA,CACF;AAAA,IACH;AAGmB,aAAA,SAAA7zB,GACD,KAAA,cAAA2zB,GACC,KAAA,WAAAL,GAIb,CAACtzB,EAAO;AACJ,YAAA,IAAI,MAAM,uCAAuC;AAEzD,SAAK,YAAY,IAAI6yB,GAAgB7yB,EAAO,YAAY,GAInD,KAAA,YAAY,UAAU,KAAK,sBAAsB,GAEtDA,EAAO,SAAS,MAAM;AAEpB,WAAK,uBAAuB,KAAK,YAAY,WAAA,CAAY,GACzDA,EAAO,kBAAkB,MAAM;AAC7B,QAAI,KAAK,mBACP,KAAK,iBAAiB,IACtB,KAAK,gBAAgB;AAAA,MACvB,CACD;AAAA,IAAA,CACF;AAGD,UAAMk0B,IAAO;AAER,SAAA;AAAA,MACH,IAAIh5B,EAA4B;AAAA,QAC9B,KAAKokB;AAAAA,QACL,OAAO;AAAA,UACL,OAAO;AACE,mBAAA;AAAA,cACL,aAAa6U,EAAc;AAAA,YAC7B;AAAA,UACF;AAAA,UACA,MAAMz4B,GAAIyJ,GAAO;AACT,kBAAAivB,IAAS14B,EAAG,QAAQ4jB,EAAU;AAEpC,gBAAI,CAAC5jB,EAAG,cAAc,CAAC04B;AACd,qBAAAjvB;AAIH,kBAAAouB,IAAkB73B,EAAG,aACvB23B,GAA0B33B,EAAG,KAAKw4B,EAAK,QAAQ,IAC/CA,EAAK;AAET,aAAIX,EAAgB,OAAO,KAAKW,EAAK,gBAAgB,OAAO,OAE1DA,EAAK,kBAAkBX,GACvBW,EAAK,gBAAgB;AAIvB,kBAAMG,IAAc,CAAC;AAErB,gBAAIH,EAAK,kBAAkB;AACzB,oBAAMI,IAAyBf,EAAgB;AAAA,gBAC7CW,EAAK;AAAA,cACP;AAEA,cAAII,KACUD,EAAA;AAAA,gBACVE,EAAW;AAAA,kBACTD,EAAuB;AAAA,kBACvBA,EAAuB;AAAA,kBACvB;AAAA,oBACE,OAAO;AAAA,kBAAA;AAAA,gBACT;AAAA,cAEJ;AAAA,YACF;AAGK,mBAAA;AAAA,cACL,aAAaH,EAAc,OAAOz4B,EAAG,KAAK24B,CAAW;AAAA,YACvD;AAAA,UAAA;AAAA,QAEJ;AAAA,QACA,OAAO;AAAA,UACL,YAAYlvB,GAAO;;AACjB,qBACEma,IAAAA,GAAW,SAASna,CAAK,MAAzBma,gBAAAA,EAA4B,gBAAe6U,EAAc;AAAA,UAE7D;AAAA;AAAA;AAAA;AAAA,UAIA,aAAa,CAACp3B,GAAMJ,GAAKM,MAAU;AAC7B,gBAAAA,EAAM,WAAW;AACnB;AAGF,kBAAMV,IAAOQ,EAAK,MAAM,IAAI,OAAOJ,CAAG;AAEtC,gBAAI,CAACJ,GAAM;AACT,cAAA23B,EAAK,aAAa,MAAS;AAC3B;AAAA,YAAA;AAGI,kBAAAM,IAAcj4B,EAAK,MAAM;AAAA,cAC7B,CAAC+K,MACCA,EAAK,KAAK,SAASgsB,KAAYhsB,EAAK,MAAM,WAAW;AAAA,YACzD,GAEMmtB,IAAWD,KAAA,gBAAAA,EAAa,MAAM;AAC/B,YAAAN,EAAA,aAAaO,GAAU,EAAK;AAAA,UAAA;AAAA,QACnC;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA3LF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAsBD,kBAAkB;AACxB,SAAK,KAAK,UAAU;AAAA,MAClB,kBAAkB,KAAK;AAAA,MACvB,gBAAgB,KAAK;AAAA,MACrB,iBAAiB,KAAK;AAAA,IAAA,CACvB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAqKI,SACLlD,GAKA;AACO,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAM5B,aAAakD,GAA8BC,IAAiB,IAAM;;AACnE,QAAA,KAAK,qBAAqBD,MAG9B,KAAK,mBAAmBA,GACxB,KAAK,gBAAgB,GACrB,KAAK,OAAO;AAAA,MAAS,CAAC/4B,MACpBA,EAAG,QAAQ4jB,IAAY;AAAA,QACrB,MAAM8T;AAAA,MACP,CAAA;AAAA,IACH,GAEIqB,KAAYC,IAAgB;AAC9B,YAAMJ,IAAyB,KAAK,gBAAgB,IAAIG,CAAQ;AAEhE,UAAI,CAACH;AACH;AAMA,OAAA14B,KAAAD,IAAA,KAAK,OAAO,oBAAZ,gBAAAA,EAA6B,SAAS24B,EAAuB,MAC1D,SADH,QAAA14B,EAEC,eAAe;AAAA,QAChB,UAAU;AAAA,QACV,OAAO;AAAA,MAAA;AAAA,IACR;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAMK,sBAAsB;AAC3B,SAAK,iBAAiB,IACtB,KAAK,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,qBAAqB;AAC1B,SAAK,iBAAiB,IACtB,KAAK,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,MAAa,aAAauY,GAMvB;AACD,UAAM2f,IAAS,MAAM,KAAK,YAAY,aAAa3f,CAAO;AAEtD,QAAA,KAAK,YAAY,qBAAqB;AAKlC,YAAApX,IAAO,KAAK,OAAO,iBACnB43B,IAAc53B,EAAK,MAAM,WAEzB63B,IAASC,GAAe,SAAS93B,EAAK,KAAK,GAE3Cyd,IAAY;AAAA,QAChB,aAAa;AAAA,UACX,MAAMma,EAAY;AAAA,UAClB,QAAQA,EAAY;AAAA,QACtB;AAAA,QACA,KAAKC,IACDE,GAAqBF,EAAO,SAAS73B,EAAK,KAAK,IAC/C;AAAA;AAAA,MACN;AAEM,YAAA,KAAK,YAAY,oBAAoB;AAAA,QACzC,UAAU+2B,EAAO;AAAA,QACjB,WAAAtZ;AAAA,MAAA,CACD;AAAA,IAAA;AAGD,WAAK,OAAO,cAAc,SAAS,QAAQ,KAAK,UAAU;AAAA,QACxD,QAAQ;AAAA,QACR,UAAUsZ,EAAO;AAAA,MAAA,CAClB;AAAA,EACH;AAEJ;AC9UO,MAAMiB,GAEb;AAAA,EAIE,YACmB/0B,GAKAg1B,GACAC,GACjBC,GACA;AAZK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AA6BP,IAAAA,EAAA,0BAAmB,MAAM;;AACnB,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAGA;AAAA,IAAA8pB,EAAA,0BAAmB,MAAM;;AACnB,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAEA,IAAA8pB,EAAA,uBAAgB,MAAM;;AAChB,WAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,MAAM;AACd,cAAAw5B,IAAe,KAAK,OAAO,KAAK;AAAA,UACpC,8CAA8C,KAAK,MAAM,MAAM,EAAE;AAAA,QACnE;AACA,YAAI,CAACA;AACH;AAEG,aAAA,MAAM,eAAeA,EAAa,sBAAsB,GAC7D,KAAK,WAAW;AAAA,MAAA;AAAA,IAEpB;AAoCA,IAAA1P,EAAA,mBAAY,MAAM;;AACZ,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AA7FmB,SAAA,SAAAqE,GAKA,KAAA,YAAAg1B,GACA,KAAA,SAAAC,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,+CAA+C;AAGjE,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEAD,EAAO,IAAI,iBAAiB,aAAa,KAAK,gBAAgB,GAC9DA,EAAO,IAAI,iBAAiB,aAAa,KAAK,gBAAgB,GAK9DA,EAAO,KAAK,iBAAiB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAAA,EA+BjE,OAAOl4B,GAAkBq4B,GAAwB;;AAC/C,UAAMC,IAAc,KAAK,UAAU,SAASt4B,EAAK,KAAK,GAChDu4B,IAAkB,KAAK,UAAU,SAASF,CAAS;AAErD,QAAA,GAACz5B,IAAA,KAAK,UAAL,QAAAA,EAAY,UAAQ05B,KAAA,QAAAA,EAAa,UAAS,KAAK,OAAO,YAAY;AAC/D,YAAAF,IAAe,KAAK,OAAO,KAAK;AAAA,QACpC,8CAA8CE,EAAY,MAAM,EAAE;AAAA,MACpE;AACA,UAAI,CAACF;AACH;AAEF,WAAK,QAAQ;AAAA,QACX,MAAM;AAAA,QACN,cAAcA,EAAa,sBAAsB;AAAA,QACjD,OAAOE,EAAY;AAAA,MACrB,GAEA,KAAK,WAAW;AAEhB;AAAA,IAAA;AAGF,UAAME,KAAYF,KAAA,gBAAAA,EAAa,UAAS,EAACC,KAAA,QAAAA,EAAiB,QACpDE,IAAY,EAACH,KAAA,QAAAA,EAAa,WAASC,KAAA,gBAAAA,EAAiB;AAC1D,IAAIC,KAAa,KAAK,SAAS,CAAC,KAAK,MAAM,SACzC,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW,IAEdC,OAAa55B,IAAA,KAAK,UAAL,QAAAA,EAAY,UAC3B,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,EAClB;AAAA,EAUF,UAAU;AACR,SAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,gBAAgB,GAEtE,KAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,gBAAgB,GAEtE,KAAK,OAAO,KAAK,oBAAoB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAE3E;AAEA,MAAM65B,KAAqB,IAAIt6B;AAAA,EAC7B;AACF;AAEO,MAAMu6B,WAGHlE,EAAmB;AAAA,EAO3B,YAAYxxB,GAAgE;AACpE,UAAA;AAHA,IAAAylB,EAAA;AAgED,IAAAA,EAAA,mBAAY,MAAM;;AAAA,cAAA9pB,IAAA,KAAK,SAAL,gBAAAA,EAAW;AAAA;AA5D7B,SAAA;AAAA,MACH,IAAIT,EAED;AAAA,QACD,KAAKu6B;AAAA,QACL,MAAM,CAACE,OACL,KAAK,OAAO,IAAIZ;AAAA,UACd/0B;AAAA,UACAy1B;AAAA,UACAE;AAAA,UACA,CAACxwB,MAAU;AACJ,iBAAA,KAAK,UAAUA,CAAK;AAAA,UAAA;AAAA,QAE7B,GACO,KAAK;AAAA,QAEd,OAAO;AAAA,UACL,eAAe,CAAC6pB,GAAO/xB,MAAyB;;AAC9C,mBAAIA,EAAM,QAAQ,YAAY,KAAK,UACjCtB,IAAA,KAAK,SAAL,QAAAA,EAAW,aACJ,MAEF;AAAA,UAAA;AAAA,QAEX;AAAA,QACA,OAAO;AAAA,UACL,MAAM,OACG;AAAA,YACL,OAAO;AAAA,UACT;AAAA,UAEF,OAAO,CAACH,GAAao6B,MAAS;AACtB,kBAAAzwB,IACJ3J,EAAY,QAAQi6B,EAAkB;AAExC,mBAAItwB,MAKF,CAAC3J,EAAY,QAAQq5B,EAAc,MAClCr5B,EAAY,gBAAgBA,EAAY,cAElC,EAAE,OAAO,OAAU,IAErBo6B;AAAA,UAAA;AAAA,QACT;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EAzDF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA2DT,IAAW,QAAQ;;AACV,aAAAh6B,KAAAD,IAAA,KAAK,SAAL,gBAAAA,EAAW,UAAX,gBAAAC,EAAkB,SAAQ;AAAA,EAAA;AAAA,EAG5B,SAAS21B,GAAiD;AACxD,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAIrC;ACnMO,MAAMsE,GAA4C;AAAA,EA0CvD,YACmB71B,GAKAi1B,GACjBC,GACA;AAjDK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,qBAAc;AAEd,IAAAA,EAAA,oBAKS,CAAC,EAAE,MAAA1oB,GAAM,OAAAoI,GAAO,MAAAuJ,GAAM,IAAAC,QAAS;AACvC,YAAA,EAAE,KAAAhL,GAAK,WAAA6W,EAAA,IAAcrV,GACrB,EAAE,OAAA2wB,MAAUtb,GAKZub,IACJ,CAACpyB,EAAI,YAAY+K,GAAMC,CAAE,EAAE,UAAU+L,GAAgBvV,EAAM,SAAS;AAUtE,UANEqV,EAAU,MAAM,OAAO,KAAK,KAAK,QAChCwb,GAAgBxb,CAAS,KAAKA,EAAU,KAAK,KAAK,KAAK,QAKtDsb,KAASC;AACJ,eAAA;AAGT,YAAME,IAAiB,SAAS;AAChC,aAAI,GAAC,KAAK,6BAA6BA,CAAc,KAAKl5B,EAAK;AAAA,IAKjE;AAiCA,IAAA0oB,EAAA,qBAAc,CAACxoB,MAAsB;;AACnC,UAAI,KAAK,aAAa;AACpB,aAAK,cAAc;AAEnB;AAAA,MAAA;AAGI,YAAAi5B,IAAgB,KAAK,OAAO,IAAI;AAItC;AAAA,MAEEj5B,KACAA,EAAM;AAAA,OAELi5B,MAAmBj5B,EAAM,iBACxBi5B,EAAc,SAASj5B,EAAM,aAAqB,KACjDA,EAAM,cAA8B;AAAA,QACnC;AAAA,MACF,OAKAtB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAEA,IAAA8pB,EAAA,sCAA+B,CAAC5qB,MAAyB;AACvD,UAAI,CAACA;AACI,eAAA;AAEH,YAAAq7B,IAAgB,KAAK,OAAO,IAAI;AACtC,aAAKA,IAIEA,EAAc,SAASr7B,CAAO,IAH5B;AAAA,IAIX;AAEA,IAAA4qB,EAAA,8BAAuB,CAAC0Q,MAAkB;AACxC,MAAK,KAAK,6BAA6BA,EAAE,MAAc,MACrD,KAAK,cAAc;AAAA,IAEvB;AAEA,IAAA1Q,EAAA,wBAAiB,MAAM;AACrB,MAAI,KAAK,gBACP,KAAK,cAAc,IACnB,WAAW,MAAM,KAAK,OAAO,KAAK,MAAM,CAAC;AAAA,IAE7C;AAGA;AAAA,IAAAA,EAAA,qBAAc,MAAM;;AACd,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAEA,IAAA8pB,EAAA,uBAAgB,MAAM;;AAChB,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACT,KAAA,MAAM,eAAe,KAAK,wBAAwB,GACvD,KAAK,WAAW;AAAA,IAEpB;AA+EA,IAAA8pB,EAAA,mBAAY,MAAM;;AACZ,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAvLmB,SAAA,SAAAqE,GAKA,KAAA,SAAAi1B,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACR,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAGF,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEAD,EAAO,IAAI,iBAAiB,aAAa,KAAK,oBAAoB,GAClEA,EAAO,KAAK,iBAAiB,WAAW,KAAK,cAAc,GAC3DA,EAAO,IAAI,iBAAiB,aAAa,KAAK,WAAW,GACzDA,EAAO,IAAI,iBAAiB,YAAY,KAAK,WAAW,GACxDA,EAAO,IAAI,iBAAiB,QAAQ,KAAK,WAAW,GAKpDA,EAAO,KAAK,iBAAiB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAAA,EA0EjE,OAAOl4B,GAAkB1B,GAAwB;;AAKzC,UAAA,EAAE,OAAA8J,GAAO,WAAAixB,EAAA,IAAcr5B,GACvB,EAAE,KAAA4G,GAAK,WAAA6W,EAAA,IAAcrV,GACrBkxB,IACJh7B,KAAYA,EAAS,IAAI,GAAGsI,CAAG,KAAKtI,EAAS,UAAU,GAAGmf,CAAS;AAErE,QAAI4b,KAAaC;AACf;AAII,UAAA,EAAE,QAAAC,MAAW9b,GACb9L,IAAO,KAAK,IAAI,GAAG4nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,MAAM,GAAG,CAAC,GACzDxC,IAAK,KAAK,IAAI,GAAG2nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,IAAI,GAAG,CAAC,GAErDolB,IAAa,KAAK,WAAW;AAAA,MACjC,MAAAx5B;AAAA,MACA,OAAAoI;AAAA,MACA,MAAAuJ;AAAA,MACA,IAAAC;AAAA,IAAA,CACD,GAKK6nB,IAAQ,OAAO,MAAM,UAAU,iBAAmB;AAGxD,QAAI,CAAC,KAAK,gBAAgBD,KAAc,KAAK,gBAAgB,CAACC,GAAO;AAMnE,YAAMC,IAAY;AAAA,QAChB,MAAM;AAAA,QACN,cAAc,KAAK,wBAAwB;AAAA,MAC7C;AAEA,OACEA,EAAU,WAAS96B,IAAA,KAAK,UAAL,gBAAAA,EAAY,SAC/B86B,EAAU,aAAa,OAAa,QAAA76B,IAAA,KAAK,UAAL,gBAAAA,EAAY,aAAa,eAE7D,KAAK,QAAQ66B,GACb,KAAK,WAAW;AAGlB;AAAA,IAAA;AAIF,SACEz4B,IAAA,KAAK,UAAL,QAAAA,EAAY,QACZ,CAAC,KAAK,gBACL,CAACu4B,KAAc,KAAK,eAAe,CAAC,KAAK,OAAO,aACjD;AACA,WAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAEhB;AAAA,IAAA;AAAA,EACF;AAAA,EAGF,UAAU;AACR,SAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,oBAAoB,GAC1E,KAAK,OAAO,KAAK,oBAAoB,WAAW,KAAK,cAAc,GACnE,KAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,WAAW,GACjE,KAAK,OAAO,IAAI,oBAAoB,YAAY,KAAK,WAAW,GAChE,KAAK,OAAO,IAAI,oBAAoB,QAAQ,KAAK,WAAW,GAE5D,KAAK,OAAO,KAAK,oBAAoB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAAA,EAUzE,0BAA0B;AAClB,UAAA,EAAE,OAAApxB,MAAU,KAAK,QACjB,EAAE,WAAAqV,MAAcrV,GAGhB,EAAE,QAAAmxB,MAAW9b,GACb9L,IAAO,KAAK,IAAI,GAAG4nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,MAAM,GAAG,CAAC,GACzDxC,IAAK,KAAK,IAAI,GAAG2nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,IAAI,GAAG,CAAC;AAEvD,QAAA6kB,GAAgBxb,CAAS,GAAG;AAC9B,YAAMje,IAAO,KAAK,OAAO,QAAQmS,CAAI;AACrC,UAAInS;AACF,eAAOA,EAAK,sBAAsB;AAAA,IACpC;AAGF,WAAOm6B,GAAa,KAAK,QAAQhoB,GAAMC,CAAE;AAAA,EAAA;AAE7C;AAEO,MAAMgoB,KAA6B,IAAIx7B;AAAA,EAC5C;AACF;AAEO,MAAMy7B,WAA2CpF,EAAmB;AAAA,EAOzE,YAAYxxB,GAAwC;AAC5C,UAAA;AAHA,IAAAylB,EAAA;AAkCD,IAAAA,EAAA,mBAAY,MAAM,KAAK,KAAM,UAAU;AA9BvC,SAAA;AAAA,MACH,IAAIvqB,EAAO;AAAA,QACT,KAAKy7B;AAAA,QACL,MAAM,CAAChB,OACL,KAAK,OAAO,IAAIE,GAAsB71B,GAAQ21B,GAAY,CAACxwB,MAAU;AAC9D,eAAA,KAAK,UAAUA,CAAK;AAAA,QAAA,CAC1B,GACM,KAAK;AAAA,QAEd,OAAO;AAAA,UACL,eAAe,CAAC6pB,GAAO/xB,MACjBA,EAAM,QAAQ,YAAY,KAAK,SACjC,KAAK,KAAM,UAAU,GACd,MAEF;AAAA,QACT;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA3BF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA6BT,IAAW,QAAQ;;AACV,aAAArB,KAAAD,IAAA,KAAK,SAAL,gBAAAA,EAAW,UAAX,gBAAAC,EAAkB,SAAQ;AAAA,EAAA;AAAA,EAG5B,SAAS21B,GAAmD;AAC1D,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAIrC;ACzSa,MAAAsF,KAAYv0B,GAAK,OAAO;AAAA,EACnC,MAAM;AAAA,EAEN,QAAQ;AAAA,EAER,OAAO;AAAA,EAEP,YAAY;AAAA,EAEZ,sBAAsB;AAAA,EAEtB,UAAU;AAAA,EAEV,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,MAAM;AAAA,EACvB;AAAA,EAEA,WAAW,EAAE,gBAAAgB,KAAkB;AAC7B,WAAO,CAAC,MAAM4e,GAAgB,KAAK,QAAQ,gBAAgB5e,CAAc,CAAC;AAAA,EAC5E;AAAA,EAEA,aAAa;AACJ,WAAA;AAAA;AAAA,EAAA;AAEX,CAAC,GCtBYwzB,KAAqB,CAACnzB,GAAWozB,MAAsB;AAC5D,QAAAnzB,IAAOD,EAAI,QAAQozB,CAAS;AAE9B,MAAAnzB,EAAK,SAAS;AACT;AAIT,QAAMozB,IAAkBpzB,EAAK;AAAA,IAC3BA,EAAK,MAAMA,EAAK,QAAQ,CAAC;AAAA,IACzBA,EAAK,QAAQ;AAAA,EACf;AAKO,SAHiBqB;AAAA,IACtBtB,EAAI,QAAQqzB,CAAe;AAAA,EAC7B;AAEF,GAMaC,KAAmB,CAACtzB,GAAWozB,MAAsB;AAC1D,QAAAnzB,IAAOD,EAAI,QAAQozB,CAAS,GAE5BG,IAAgBtzB,EAAK,MAAM;AAEjC,MAAIszB,MAAkB;AACb;AAGT,QAAMC,IAAqBvzB,EAAK,WAAWszB,IAAgB,CAAC;AAKrD,SAHejyB;AAAA,IACpBtB,EAAI,QAAQwzB,CAAkB;AAAA,EAChC;AAEF,GAWaC,KAA2B,CAACzzB,GAAWiE,MAAyB;AAC3E,SAAOA,EAAU,kBAAgB;AACzB,UAAAyvB,IAAQzvB,EAAU,eAAe,MAEjC0vB,IAAS3zB,EACZ,QAAQiE,EAAU,eAAe,YAAY,CAAC,EAC9C,WAAWyvB,EAAM,aAAa,CAAC;AAClC,IAAAzvB,IAAY3C,GAA4BtB,EAAI,QAAQ2zB,CAAM,CAAC;AAAA,EAAA;AAGtD,SAAA1vB;AACT,GAEM2vB,KAAW,CAAC3X,GAA0B4X,MAExC5X,EAAc,oBACdA,EAAc,aAAa,KAAK,KAAK,KAAK,YAAY,aACtDA,EAAc,aAAa,KAAK,aAAa,KAC7C4X,EAAc,oBACdA,EAAc,aAAa,KAAK,KAAK,KAAK,YAAY,WAIpDC,KAAc,CAClBtyB,GACAuN,GACAkN,GACA4X,MACG;AAEC,MAAA,CAACA,EAAc;AACjB,UAAM,IAAI;AAAA,MACR,wCAAwCA,EAAc,QAAQ,SAAS,oCAAoC5X,EAAc,QAAQ,SAAS;AAAA,IAC5I;AAKF,MAAI4X,EAAc,gBAAgB;AAC1B,UAAAE,IAAmBvyB,EAAM,IAAI;AAAA,MACjCqyB,EAAc,eAAe,YAAY;AAAA,IAC3C,GACMG,IAAiBxyB,EAAM,IAAI;AAAA,MAC/BqyB,EAAc,eAAe,WAAW;AAAA,IAC1C,GACMI,IAAmBF,EAAiB,WAAWC,CAAc;AAEnE,QAAIjlB,GAAU;AACZ,YAAM/V,IAAMwI,EAAM,IAAI,QAAQqyB,EAAc,QAAQ,SAAS;AAC7D,MAAAryB,EAAM,GAAG,KAAKyyB,GAAmBj7B,EAAI,KAAK;AAAA,IAAA;AAAA,EAC5C;AAMF,MAAI+V,GAAU;AACR,QAAA,CAACkN,EAAc;AACjB,YAAM,IAAI;AAAA,QACR,wCAAwC4X,EAAc,QAAQ,SAAS,oCAAoC5X,EAAc,QAAQ,SAAS;AAAA,MAC5I;AAIF,IAAAlN;AAAA,MACEvN,EAAM,GAAG;AAAA,QACPya,EAAc,aAAa,WAAW;AAAA,QACtC4X,EAAc,aAAa,YAAY;AAAA,MAAA;AAAA,IAE3C;AAAA,EAAA;AAGK,SAAA;AACT,GAEaK,KACX,CAACC,MACD,CAAC;AAAA,EACC,OAAA3yB;AAAA,EACA,UAAAuN;AACF,MAGM;AACJ,QAAM9O,IAAOuB,EAAM,IAAI,QAAQ2yB,CAAgB,GACzCN,IAAgBvyB,GAA4BrB,CAAI,GAEhDgc,IAAgBqX;AAAA,IACpB9xB,EAAM;AAAA,IACNqyB,EAAc,QAAQ;AAAA,EACxB;AAEA,MAAI,CAAC5X;AACI,WAAA;AAGT,QAAMmY,IAAwBX;AAAA,IAC5BjyB,EAAM;AAAA,IACNya;AAAA,EACF;AAEA,SAAK2X,GAASQ,GAAuBP,CAAa,IAI3CC,GAAYtyB,GAAOuN,GAAUqlB,GAAuBP,CAAa,IAH/D;AAIX,GCvJWQ,KAA6Bt9B,EAAU,OAGjD;AAAA,EACD,UAAU;AAAA;AAAA;AAAA,EAIV,uBAAuB;AAEf,UAAAu9B,IAAkB,MACtB,KAAK,OAAO,SAAS,MAAM,CAAC,EAAE,OAAAlc,GAAO,UAAA2C,QAAe;AAAA;AAAA,MAElD,MAAMA,EAAS,gBAAgB;AAAA;AAAA,MAE/B,MAAMA,EAAS,cAAc;AAAA;AAAA,MAE7B,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAGT,cAAMswB,IACJ/yB,EAAM,UAAU,SAASyC,EAAU,aAAa,YAAY,GACxDuwB,IACJvwB,EAAU,aAAa,KAAK,KAAK,SAAS;AAExC,eAAAswB,KAAyB,CAACC,IACrBzZ,EAAS;AAAA,UACdlM,EAAmB5K,EAAU,QAAQ,WAAW;AAAA,YAC9C,MAAM;AAAA,YACN,OAAO,CAAA;AAAA,UACR,CAAA;AAAA,QACH,IAGK;AAAA,MAAA,CACR;AAAA;AAAA,MAEH,MACE8W,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAEH,cAAA,EAAE,cAAAlI,MAAiBkI;AAKzB,eAFEzC,EAAM,UAAU,SAASzF,EAAa,YAAY,IAG3Cgf,EAAS,aAAa,gBAAgB,IAGxC;AAAA,MAAA,CACR;AAAA;AAAA;AAAA,MAGH,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAET,cAAM,EAAE,SAASW,GAAgB,cAAA7I,EAAiB,IAAAkI,GAE5CswB,IACJ/yB,EAAM,UAAU,SAASzF,EAAa,YAAY,GAC9C+e,IAAiBtZ,EAAM,UAAU,OAEjC2yB,IAAmBvvB,EAAe;AAExC,eAAI2vB,KAAyBzZ,IACpB1C,EAAA,EACJ,QAAQ8b,GAAmBC,CAAgB,CAAC,EAC5C,eAAe,EACf,IAAI,IAGF;AAAA,MAAA,CACR;AAAA,MACH,MACEpZ,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,GAAO,UAAAuN,QAAe;AAElC,cAAA9K,IAAY1C,EAA0BC,CAAK;AAiBjD,YAhBI,CAACyC,EAAU,oBAOX,EAFFzC,EAAM,UAAU,SAASyC,EAAU,aAAa,YAAY,MAMxCqvB;AAAA,UACpB9xB,EAAM;AAAA,UACNyC,EAAU,QAAQ;AAAA,QACpB;AAIS,iBAAA;AAGT,cAAMwwB,IAAkBtB;AAAA,UACtB3xB,EAAM;AAAA,UACNyC,EAAU,QAAQ;AAAA,QACpB;AAEI,aAAAwwB,KAAA,gBAAAA,EAAiB,mBAAkB;AAC9B,iBAAA;AAGT,cAAMvR,IAASuR,GAETC,IAAavB;AAAA,UACjB3xB,EAAM;AAAA,UACN0hB,EAAO,QAAQ;AAAA,QACjB;AACI,aAAAwR,KAAA,gBAAAA,EAAY,mBAAkB;AAC1B,gBAAA,IAAI,MAAM,uCAAuC;AAGzD,cAAMC,IACJzR,EAAO,eAAgB,KAAK,eAAe,GAEvC0R,IACJD,KACAD,EAAW,eAAgB,KAAK,eAAe,GAE3CG,IACJH,EAAW,eAAgB,KAAK,eAChCxR,EAAO,QAAQ;AAEjB,YAAInU,GAAU;AACN,gBAAA+lB,IAActzB,EAAM,IAAI;AAAA,YAC5ByC,EAAU,QAAQ;AAAA,YAClBA,EAAU,QAAQ;AAAA,YAClB;AAAA,UACF;AAWA,cAAI2wB;AACF,gBAAIC,GAAe;AACjB,cAAArzB,EAAM,GAAG;AAAA,gBACP,IAAIgjB;AAAA;AAAA,kBAEFkQ,EAAW,QAAQ;AAAA,kBACnBA,EAAW,QAAQ;AAAA;AAAA,kBAEnBxR,EAAO,QAAQ,WAAW;AAAA,kBAC1BwR,EAAW,QAAQ,WAAW;AAAA,kBAC9BI;AAAA,kBACAA,EAAY;AAAA;AAAA,kBACZ;AAAA,gBAAA;AAAA,cAEJ;AACA,oBAAM97B,IAAMwI,EAAM,GAAG,IAAI,QAAQ0hB,EAAO,QAAQ,SAAS;AACzD,cAAA1hB,EAAM,GAAG,aAAaoV,EAAc,QAAQ5d,GAAKA,CAAG,CAAC;AAAA,YAAA,OAChD;AAEL,cAAAwI,EAAM,GAAG;AAAA,gBACP,IAAIgjB;AAAA;AAAA,kBAEFkQ,EAAW,QAAQ;AAAA,kBACnBA,EAAW,QAAQ;AAAA;AAAA,kBAEnBA,EAAW,QAAQ,YAAY;AAAA,kBAC/BxR,EAAO,QAAQ,YAAY;AAAA,kBAC3B4R;AAAA,kBACA;AAAA;AAAA,kBACA;AAAA,gBAAA;AAAA,cAEJ;AACM,oBAAA97B,IAAMwI,EAAM,GAAG,IAAI;AAAA,gBACvBA,EAAM,GAAG,QAAQ,IAAI0hB,EAAO,QAAQ,YAAY,CAAC;AAAA,cACnD;AACA,cAAA1hB,EAAM,GAAG,aAAaoV,EAAc,QAAQ5d,GAAKA,CAAG,CAAC;AAAA,YAAA;AAAA,mBAE9C27B;AACT,gBAAIE,GAAe;AAEjB,cAAArzB,EAAM,GAAG;AAAA,gBACP0hB,EAAO,QAAQ;AAAA,gBACfA,EAAO,QAAQ;AAAA,cACjB,GAGA1hB,EAAM,GAAG;AAAA,gBACPkzB,EAAW,QAAQ;AAAA,gBACnBI,EAAY;AAAA,cACd;AAEM,oBAAA97B,IAAMwI,EAAM,GAAG,IAAI;AAAA,gBACvBkzB,EAAW,QAAQ;AAAA,cACrB;AACA,cAAAlzB,EAAM,GAAG,aAAaoV,EAAc,QAAQ5d,GAAKA,CAAG,CAAC;AAAA,YAAA;AAGrD,cAAAwI,EAAM,GAAG;AAAA,gBACP0hB,EAAO,QAAQ,YAAY;AAAA,gBAC3BA,EAAO,QAAQ,YAAY;AAAA,cAC7B;AAAA,eAEG;AAEL,YAAA1hB,EAAM,GAAG;AAAA,cACPyC,EAAU,QAAQ;AAAA,cAClBA,EAAU,QAAQ;AAAA,YACpB,GACI4wB,IAEFrzB,EAAM,GAAG;AAAA,cACPkzB,EAAW,QAAQ,YAAY;AAAA,cAC/BI,EAAY;AAAA,YACd,IAGAtzB,EAAM,GAAG;AAAA,cACP0hB,EAAO,QAAQ,YAAY;AAAA,cAC3B4R,EAAY;AAAA,YACd;AAEI,kBAAA97B,IAAMwI,EAAM,GAAG,IAAI,QAAQ0hB,EAAO,QAAQ,YAAY,CAAC;AAC7D,YAAA1hB,EAAM,GAAG,aAAaoV,EAAc,QAAQ5d,GAAKA,CAAG,CAAC;AAAA,UAAA;AAAA,QACvD;AAGK,eAAA;AAAA,MAAA,CACR;AAAA;AAAA;AAAA,MAGH,MACE+hB,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAOT,YAHEA,EAAU,aAAa,KAAK,eAAe,KAC3CA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY,WAEpC;AACd,gBAAMgY,IAAgBqX;AAAA,YACpB9xB,EAAM;AAAA,YACNyC,EAAU,QAAQ;AAAA,UACpB;AACA,cAAI,CAACgY,KAAiB,CAACA,EAAc;AAC5B,mBAAA;AAGT,cAAI8Y,IAAkB3c,EAAM;AAE5B,cACE6D,EAAc,aAAa,KAAK,KAAK,KAAK,YAC1C,aACA;AAKA,kBAAM+Y,IAJmB/wB,EAAU,QAAQ,YAAY,IACJ,IACH,IACT,IACU;AAEjD,YAAA8wB,IAAkBA,EAAgB;AAAA,cAChCC;AAAA,YACF;AAAA,UAAA,WAEA/Y,EAAc,aAAa,KAAK,KAAK,KAAK,YAAY,IACtD;AACA,kBAAMgZ,IACJhZ,EAAc,aAAa,WAC3BA,EAAc,aAAa,KAAK;AAElC,YAAA8Y,IAAkBA,EAAgB;AAAA,cAChCE;AAAA,YACF;AAAA,UAAA,OACK;AACL,kBAAMC,IACJjZ,EAAc,aAAa,WAC3BA,EAAc,aAAa,KAAK;AAGhC,YAAA8Y,IAAAA,EAAgB,iBAAiBG,CAAoB;AAAA,UAAA;AAGzD,iBAAOH,EACJ,YAAY;AAAA,YACX,MAAM9wB,EAAU,QAAQ;AAAA,YACxB,IAAIA,EAAU,QAAQ;AAAA,UAAA,CACvB,EACA,eAAe,EACf,IAAI;AAAA,QAAA;AAGF,eAAA;AAAA,MAAA,CACR;AAAA;AAAA;AAAA;AAAA,MAIH,MACE8W,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAE7C,YAAA,CAACyC,EAAU;AAEP,gBAAA,IAAI,MAAM,MAAM;AAGxB,cAAMswB,IACJ/yB,EAAM,UAAU,SAASyC,EAAU,aAAa,YAAY,GACxD6W,IAAiBtZ,EAAM,UAAU,OAEjCya,IAAgBqX;AAAA,UACpB9xB,EAAM;AAAA,UACNyC,EAAU,QAAQ;AAAA,QACpB;AAEI,YAAAgY,KAAiBsY,KAAyBzZ,GAAgB;AAC5D,gBAAMqa,IAAc1B;AAAA,YAClBjyB,EAAM;AAAA,YACNya;AAAA,UACF;AAEI,cAAA,CAACkZ,EAAY;AAET,kBAAA,IAAI,MAAM,MAAM;AASxB,cALEA,EAAY,aAAa,KAAK,KAAK,KAAK,YAAY,MACnDA,EAAY,aAAa,KAAK,KAAK,KAAK,YACvC,aACAA,EAAY,aAAa,KAAK,eAAe;AAG/C,mBAAO/c,EACJ,EAAA;AAAA,cACC;AAAA,gBACE,MAAMnU,EAAU,QAAQ;AAAA,gBACxB,IAAIA,EAAU,QAAQ;AAAA,cACxB;AAAA,cACAkxB,EAAY,QAAQ;AAAA,cAErB,YAAY;AAAA,cACX,MAAMA,EAAY,QAAQ;AAAA,cAC1B,IAAIA,EAAY,QAAQ;AAAA,YACzB,CAAA,EACA,IAAI;AAAA,QACT;AAGK,eAAA;AAAA,MACR,CAAA;AAAA,IAAA,CACJ,GAEGC,IAAe,MACnB,KAAK,OAAO,SAAS,MAAM,CAAC,EAAE,UAAAra,QAAe;AAAA;AAAA,MAE3C,MAAMA,EAAS,gBAAgB;AAAA;AAAA;AAAA;AAAA,MAI/B,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AAExB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAEH,cAAA;AAAA,UACJ,SAASW;AAAA,UACT,cAAA7I;AAAA,UACA,gBAAAs5B;AAAA,QAAA,IACEpxB,GAEE,EAAE,OAAA/D,EAAM,IAAIsB,EAAM,IAAI,QAAQoD,EAAe,SAAS,GACtD0wB,IACJ1wB,EAAe,aAAapD,EAAM,IAAI,WAAW,GAC7C+zB,IACJ/zB,EAAM,UAAU,SAASzF,EAAa,WAAW,GAC7C+e,IAAiBtZ,EAAM,UAAU;AAGvC,YACE,CAAC8zB,KACDC,KACAza,KACA,EANqBua,MAAmB,SAOxC;AACA,cAAIG,IAAWt1B,GACXyzB,IAAS/uB,EAAe,WAAW,GACnC6wB,IAAWj0B,EAAM,IAAI,QAAQmyB,CAAM,EAAE;AAEzC,iBAAO8B,IAAWD;AACL,YAAAA,IAAAC,GACD9B,KAAA,GACV8B,IAAWj0B,EAAM,IAAI,QAAQmyB,CAAM,EAAE;AAGvC,iBAAO5Y,EAAS,QAAQmZ,GAAmBP,IAAS,CAAC,CAAC;AAAA,QAAA;AAGjD,eAAA;AAAA,MACR,CAAA;AAAA,IAAA,CACJ,GAEG9Y,IAAc,CAAC6a,IAAY,OACxB,KAAK,OAAO,SAAS,MAAM,CAAC,EAAE,UAAA3a,QAAe;AAAA;AAAA;AAAA,MAGlD,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAET,cAAM,EAAE,SAASW,GAAgB,cAAA7I,EAAiB,IAAAkI,GAE5C,EAAE,OAAA/D,EAAM,IAAIsB,EAAM,IAAI,QAAQoD,EAAe,SAAS,GAEtD2vB,IACJ/yB,EAAM,UAAU,QAAQ,iBAAiB,GACrCsZ,IACJtZ,EAAM,UAAU,WAAWA,EAAM,UAAU,MACvCm0B,IAAa55B,EAAa,KAAK,eAAe,GAC9C65B,IAAgB11B,IAAQ;AAG5B,eAAAq0B,KACAzZ,KACA6a,KACAC,IAEO7a,EAAS,aAAa,gBAAgB,IAGxC;AAAA,MAAA,CACR;AAAA;AAAA,MAEH,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,QAAY;AACxB,cAAAyC,IAAY1C,EAA0BC,CAAK,GAE3Cq0B,IACJ,KAAK,QAAQ,OAAO,OAAO,YAAY5xB,EAAU,aAAa,EAC3D,qBAAqB;AAE1B,eAAI4xB,MAA2B,SACtB;AAAA;AAAA;AAAA,UAMNA,MAA2B,iBAAiBH;AAAA;AAAA,UAG7CG,MAA2B,UAEpB9a,EAAS,cAAc;AAAA,YAC5B,MAAM;AAAA,UAAA,CACP,IAGI;AAAA;AAAA,MAAA,CACR;AAAA;AAAA;AAAA,MAGH,MACEA,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,GAAO,UAAAuN,QAAe;AAClC,cAAA9K,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAET,cAAM,EAAE,SAASW,GAAgB,cAAA7I,EAAiB,IAAAkI,GAE5CswB,IACJ/yB,EAAM,UAAU,QAAQ,iBAAiB,GACrCsZ,IACJtZ,EAAM,UAAU,WAAWA,EAAM,UAAU,MACvCm0B,IAAa55B,EAAa,KAAK,eAAe;AAEhD,YAAAw4B,KAAyBzZ,KAAkB6a,GAAY;AACzD,gBAAMG,IAAuBlxB,EAAe,UACtCmxB,IAAqBD,IAAuB;AAElD,cAAI/mB,GAAU;AACZ,kBAAMqS,IACJ5f,EAAM,OAAO,MAAM,eAAkB,cAAc;AAErD,YAAAA,EAAM,GACH,OAAOs0B,GAAsB1U,CAAQ,EACrC,eAAe,GAClB5f,EAAM,GAAG;AAAA,cACP,IAAIoV,EAAcpV,EAAM,IAAI,QAAQu0B,CAAkB,CAAC;AAAA,YACzD;AAAA,UAAA;AAGK,iBAAA;AAAA,QAAA;AAGF,eAAA;AAAA,MAAA,CACR;AAAA;AAAA;AAAA,MAGH,MACEhb,EAAS,QAAQ,CAAC,EAAE,OAAAvZ,GAAO,OAAA4W,QAAY;AAC/B,cAAAnU,IAAY1C,EAA0BC,CAAK;AAC7C,YAAA,CAACyC,EAAU;AACN,iBAAA;AAEH,cAAA,EAAE,cAAAlI,MAAiBkI,GAEnBswB,IACJ/yB,EAAM,UAAU,QAAQ,iBAAiB;AAG3C,eAFmBzF,EAAa,KAAK,eAAe,IAiB7C,MAdCqc,EAAA,EACH,kBACA;AAAA,UACCmC;AAAA,YACE/Y,EAAM,UAAU;AAAA,YAChB+yB;AAAA,YACAA;AAAA,UAAA;AAAA,UAGH,IAAI,GAEA;AAAA,MAIV,CAAA;AAAA,IAAA,CACJ;AAGI,WAAA;AAAA,MACL,WAAWD;AAAA,MACX,QAAQc;AAAA,MACR,OAAO,MAAMva,EAAY;AAAA,MACzB,eAAe,MAAMA,EAAY,EAAI;AAAA;AAAA;AAAA,MAGrC,KAAK,MAAM;;AACT,eACE,KAAK,QAAQ,gBAAgB,qBAC5B7iB,IAAA,KAAK,QAAQ,OAAO,sBAApB,QAAAA,EAAuC,UACtCC,IAAA,KAAK,QAAQ,OAAO,gBAApB,QAAAA,EAAiC,UACjCoC,IAAA,KAAK,QAAQ,OAAO,cAApB,QAAAA,EAA+B,SAG1B,KAEFoqB,GAAU,KAAK,QAAQ,MAAM;AAAA,MAEtC;AAAA,MACA,aAAa,MAAM;;AACjB,eACE,KAAK,QAAQ,gBAAgB,qBAC5BzsB,IAAA,KAAK,QAAQ,OAAO,sBAApB,QAAAA,EAAuC,UACtCC,IAAA,KAAK,QAAQ,OAAO,gBAApB,QAAAA,EAAiC,UACjCoC,IAAA,KAAK,QAAQ,OAAO,cAApB,QAAAA,EAA+B,SAG1B,MAEJ,KAAA,OAAO,SAAS,aAAa,gBAAgB,GAC3C;AAAA,MACT;AAAA,MACA,qBAAqB,OACd,KAAA,QAAQ,OAAO,aAAa,GAC1B;AAAA,MAET,uBAAuB,OAChB,KAAA,QAAQ,OAAO,eAAe,GAC5B;AAAA,MAET,SAAS,MAAM,KAAK,QAAQ,OAAO,KAAK;AAAA,MACxC,SAAS,MAAM,KAAK,QAAQ,OAAO,KAAK;AAAA,MACxC,eAAe,MAAM,KAAK,QAAQ,OAAO,KAAK;AAAA,IAChD;AAAA,EAAA;AAEJ,CAAC;AC7kBD,MAAM27B,GAAsC;AAAA,EAiB1C,YACmB35B,GACAi1B,GACjBC,GACA;AApBK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AAEP,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AA2CA,IAAAA,EAAA,0BAAmB,CAACxoB,MAAsB;AAOxC,UALA,KAAK,uBAAuB,QAC5B,KAAK,4BAA4B,QAEjC,KAAK,oBAAoB,GAGvBA,EAAM,kBAAkB,qBACxBA,EAAM,OAAO,aAAa,KAC1B;AAGA,cAAM28B,IAAqB38B,EAAM,QAC3B48B,IACJ,KAAK,OAAO,SAASD,GAAoB,CAAC,IAAI,GAC1CE,IACJ,KAAK,OAAO,MAAM,IAAI,QAAQD,CAAoB,GAC9CE,IAAaD,EAA6B,MAAM;AAEtD,mBAAWxyB,KAAQyyB;AAEf,cAAAzyB,EAAK,KAAK,SAAS,KAAK,OAAO,MAAM,OAAO,KAAK,MAAM,EAAE,KAAK,MAC9D;AACA,iBAAK,uBAAuBA,GAC5B,KAAK,4BACH0yB,GAAaF,GAA8BxyB,EAAK,MAAMA,EAAK,KAAK,KAChE;AAEF;AAAA,UAAA;AAAA,MAEJ;AAGF,kBAAK,qBAAqB,GAEnB;AAAA,IACT;AAEA,IAAAme,EAAA,sBAAe,CAACxoB,MAAsB;;AAC9B,YAAAi5B,IAAgB,KAAK,OAAO,IAAI;AAEtC;AAAA,MAEE,KAAK;AAAA,MAELj5B,KACAA,EAAM;AAAA,MAEN,EACEi5B,MAAmBj5B,EAAM,UACzBi5B,EAAc,SAASj5B,EAAM,MAAc,OAGzCtB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAGtB;AAEA,IAAA8pB,EAAA,uBAAgB,MAAM;;AAChB,MAAA,KAAK,aAAa,WAChB9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,eAAe+6B;AAAA,QACxB,KAAK;AAAA,QACL,KAAK,cAAe;AAAA,QACpB,KAAK,cAAe;AAAA,MACtB,GACA,KAAK,WAAW;AAAA,IAGtB;AA8HA,IAAAjR,EAAA,mBAAY,MAAM;;AACZ,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,IAEpB;AAnPmB,SAAA,SAAAqE,GACA,KAAA,SAAAi1B,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,iDAAiD;AAGnE,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEA,KAAK,uBAAuB,MAAM;AAC3B,WAAA,kBAAkB,WAAW,MAAM;AACtC,aAAK,OAAO,KAAK,QAAQ,QAAW,EAAI;AAAA,SACvC,GAAG;AAAA,IACR,GAEA,KAAK,sBAAsB,OACrB,KAAK,oBACP,aAAa,KAAK,eAAe,GACjC,KAAK,kBAAkB,SAGlB,KAGT,KAAK,OAAO,IAAI,iBAAiB,aAAa,KAAK,gBAAgB,GACnE,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GAKA,KAAK,OAAO,KAAK,iBAAiB,UAAU,KAAK,eAAe,EAAI;AAAA,EAAA;AAAA,EA6EtE,SAASp0B,GAAaoO,GAAc;;AAC7B,SAAA,OAAO,SAAS,CAACxT,MAAO;AACrB,YAAAqV,IAAW1L,EAAY3J,CAAE;AAC/B,MAAAA,EAAG,WAAWwT,GAAM,KAAK,cAAe,MAAM,KAAK,cAAe,EAAE,GACjExT,EAAA;AAAA,QACD,KAAK,cAAe;AAAA,QACpB,KAAK,cAAe,OAAOwT,EAAK;AAAA,QAChC6B,EAAS,KAAK,QAAQ,EAAE,MAAMjQ,EAAK,CAAA;AAAA,MACrC;AAAA,IAAA,CACD,GACD,KAAK,OAAO,MAAM,IAEdnF,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,EAClB;AAAA,EAGF,aAAa;;AACX,SAAK,OAAO;AAAA,MAAS,CAACD,MACpBA,EACG;AAAA,QACC,KAAK,cAAe;AAAA,QACpB,KAAK,cAAe;AAAA,QACpB,KAAK,SAAU;AAAA,MAAA,EAEhB,QAAQ,mBAAmB,EAAI;AAAA,IACpC,GACA,KAAK,OAAO,MAAM,IAEdC,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAAA,EAClB;AAAA,EAGF,OAAOoB,GAAkB1B,GAAwB4+B,IAAgB,IAAO;;AAChE,UAAA,EAAE,OAAA90B,MAAUpI;AAOlB,QAJE1B,KACAA,EAAS,UAAU,SAAS8J,EAAM,UAAU,QAC5C9J,EAAS,UAAU,OAAO8J,EAAM,UAAU,MAE9B,CAAC,KAAK,OAAO;AACzB;AAIF,UAAM+0B,IAAe,KAAK;AAY1B,QATA,KAAK,WAAW,QAChB,KAAK,gBAAgB,QAGrB,KAAK,0BAA0B,QAC/B,KAAK,+BAA+B,QAIhC,KAAK,OAAO,MAAM,UAAU,OAAO;AACrC,YAAMH,IAAa,KAAK,OAAO,MAAM,UAAU,MAAM,MAAM;AAE3D,iBAAWzyB,KAAQyyB;AAEf,YAAAzyB,EAAK,KAAK,SAAS,KAAK,OAAO,MAAM,OAAO,KAAK,MAAM,EAAE,KAAK,MAC9D;AACA,eAAK,0BAA0BA,GAC/B,KAAK,+BACH0yB;AAAA,YACE,KAAK,OAAO,MAAM,UAAU;AAAA,YAC5B1yB,EAAK;AAAA,YACLA,EAAK;AAAA,UAAA,KACF;AAEP;AAAA,QAAA;AAAA,IAEJ;AAcF,QAXI,KAAK,wBAAwB2yB,MAC/B,KAAK,WAAW,KAAK,sBACrB,KAAK,gBAAgB,KAAK,4BAIxB,KAAK,4BACP,KAAK,WAAW,KAAK,yBACrB,KAAK,gBAAgB,KAAK,+BAGxB,KAAK,YAAY,KAAK,OAAO,YAAY;AAC3C,WAAK,QAAQ;AAAA,QACX,MAAM;AAAA,QACN,cAAcvD;AAAA,UACZ,KAAK;AAAA,UACL,KAAK,cAAe;AAAA,UACpB,KAAK,cAAe;AAAA,QACtB;AAAA,QACA,KAAK,KAAK,SAAU,MAAM;AAAA,QAC1B,MAAM,KAAK,OAAO,MAAM,IAAI;AAAA,UAC1B,KAAK,cAAe;AAAA,UACpB,KAAK,cAAe;AAAA,QAAA;AAAA,MAExB,GACA,KAAK,WAAW;AAEhB;AAAA,IAAA;AAKA,SAAA/6B,IAAA,KAAK,UAAL,QAAAA,EAAY,QACZu+B,MACC,CAAC,KAAK,YAAY,CAAC,KAAK,OAAO,aAChC;AACA,WAAK,MAAM,OAAO,IAClB,KAAK,WAAW;AAEhB;AAAA,IAAA;AAAA,EACF;AAAA,EAUF,UAAU;AACR,SAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,gBAAgB,GACtE,KAAK,OAAO,KAAK,oBAAoB,UAAU,KAAK,eAAe,EAAI,GACvE,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EAAA;AAEJ;AAEa,MAAAC,KAAuB,IAAIh/B,EAAU,mBAAmB;AAE9D,MAAMi/B,WAIH5I,EAAmB;AAAA,EAO3B,YAAYxxB,GAAwC;AAC5C,UAAA;AAHA,IAAAylB,EAAA;AAiCD;AAAA;AAAA;AAAA,IAAAA,EAAA,kBAAW,CAAC3kB,GAAaoO,MAAiB;AAC1C,WAAA,KAAM,SAASpO,GAAKoO,CAAI;AAAA,IAC/B;AAKO;AAAA;AAAA;AAAA,IAAAuW,EAAA,oBAAa,MAAM;AACxB,WAAK,KAAM,WAAW;AAAA,IACxB;AASO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,wBAAiB,MAAM;AAC5B,WAAK,KAAM,qBAAqB;AAAA,IAClC;AASO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,uBAAgB,MAAM;AAC3B,WAAK,KAAM,oBAAoB;AAAA,IACjC;AAMO,IAAAA,EAAA,mBAAY,MAAM,KAAK,KAAM,UAAU;AAlEvC,SAAA;AAAA,MACH,IAAIvqB,EAAO;AAAA,QACT,KAAKi/B;AAAA,QACL,MAAM,CAACxE,OACL,KAAK,OAAO,IAAIgE,GAAgB35B,GAAQ21B,GAAY,CAACxwB,MAAU;AACxD,eAAA,KAAK,UAAUA,CAAK;AAAA,QAAA,CAC1B,GACM,KAAK;AAAA,QAEd,OAAO;AAAA,UACL,eAAe,CAAC6pB,GAAO/xB,MACjBA,EAAM,QAAQ,YAAY,KAAK,SACjC,KAAK,KAAM,UAAU,GACd,MAEF;AAAA,QACT;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA3BF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA6BF,SAASs0B,GAA6C;AACpD,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAAA,EAuCnC,IAAW,QAAQ;;AACV,aAAA31B,KAAAD,IAAA,KAAK,SAAL,gBAAAA,EAAW,UAAX,gBAAAC,EAAkB,SAAQ;AAAA,EAAA;AAIrC;AC3XO,MAAMy+B,KAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACaC,KAAwB,SCT/Bhb,KAAa,IAAInkB,EAAU,yBAAyB;AAenD,MAAMo/B,WAAoC/I,EAAmB;AAAA,EAClE,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,cAAc;AACN,UAAA,GACD,KAAA;AAAA,MACH,IAAIt2B,EAAO;AAAA,QACT,KAAKokB;AAAAA,QACL,OAAO;AAAA,UACL,eAAe,CAACviB,GAAME,MAAU;AAE1B,gBAAA,UAAUF,EAAK,MAAM,WAAW;AAE9B,kBAAAE,EAAM,WAAWA,EAAM;AAClB,uBAAA;AAGL,kBAAAA,EAAM,IAAI,WAAW;AACvB,uBAAAA,EAAM,eAAe,GAEd;AAGT,kBACEA,EAAM,QAAQ,WACd,CAACA,EAAM,YACP,CAACA,EAAM,UACP,CAACA,EAAM,WACP,CAACA,EAAM,SACP;AACM,sBAAAvB,IAAKqB,EAAK,MAAM;AACjB,uBAAAA,EAAA;AAAA,kBACHrB,EACG;AAAA,oBACCqB,EAAK,MAAM,GAAG,UAAU,IAAI,MAAM;AAAA,oBAClCA,EAAK,MAAM,OAAO,MAAM,UAAa,cAAc;AAAA,kBAAA,EAEpD;AAAA,oBACC,IAAIwd;AAAA,sBACF7e,EAAG,IAAI,QAAQqB,EAAK,MAAM,GAAG,UAAU,IAAI,MAAM,IAAI,CAAC;AAAA,oBAAA;AAAA,kBACxD;AAAA,gBAEN,GAEO;AAAA,cAAA;AAAA,YACT;AAGK,mBAAA;AAAA,UAAA;AAAA,QACT;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ;ACpEA,MAAMuiB,KAAa,IAAInkB,EAAU,uBAAuB;AAEjD,MAAMq/B,WAA0BhJ,EAAmB;AAAA,EACxD,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,YACExxB,GACAy6B,GAIA;AACM,UAAA,GACD,KAAA;AAAA,MACH,IAAIv/B,EAAO;AAAA,QACT,KAAKokB;AAAAA,QACL,MAAM,CAACviB,MAAS;;AACR,gBAAA29B,IAAuB,wBAAwB9/B,GAAI,CAAA;AACpD,UAAAmC,EAAA,IAAI,UAAU,IAAI29B,CAAoB;AACrC,gBAAAC,IAAU,SAAS,cAAc,OAAO,GAExCC,IAAQ56B,EAAO,cAAc,QAAQ;AAC3C,UAAI46B,KACMD,EAAA,aAAa,SAASC,CAAK,KAGjCj/B,IAAAqE,EAAO,oBAAP,gBAAArE,EAAwB,iBAAgB,aACnCqE,EAAA,gBAAgB,KAAK,OAAO26B,CAAO,KAE1C/+B,IAAAoE,EAAO,oBAAP,QAAApE,EAAwB,KAAK,KAAK,YAAY++B;AAGhD,gBAAME,IAAaF,EAAQ,OAErBG,IAAc,CAACC,IAAsB,OACzC,IAAIL,CAAoB,qBAAqBK,CAAmB;AAE9D,cAAA;AAEI,kBAAA;AAAA,cACJ,SAASC;AAAA,cACT,eAAeC;AAAA,cACf,GAAGr8B;AAAA,YAAA,IACD67B;AAGJ,uBAAW,CAAC54B,GAAWq5B,CAAW,KAAK,OAAO,QAAQt8B,CAAI,GAAG;AACrD,oBAAAu8B,IAAoB,uBAAuBt5B,CAAS;AAE/C,cAAAg5B,EAAA;AAAA,gBACT,GAAGC,EAAYK,CAAiB,CAAC,eAAe,KAAK;AAAA,kBACnDD;AAAA,gBAAA,CACD;AAAA,cACH;AAAA,YAAA;AAGF,kBAAME,IAAoB,8BACpBC,IAAwB;AAGnB,YAAAR,EAAA;AAAA,cACT,GAAGC,EAAYM,CAAiB,CAAC,eAAe,KAAK;AAAA,gBACnDH;AAAA,cAAA,CACD;AAAA,YACH,GAGWJ,EAAA;AAAA,cACT,GAAGC,EAAYO,CAAqB,CAAC,eAAe,KAAK;AAAA,gBACvDL;AAAA,cAAA,CACD;AAAA,YACH;AAAA,mBACO7E,GAAG;AAEF,oBAAA;AAAA,cACN;AAAA,cACAA;AAAA,YACF;AAAA,UAAA;AAGK,iBAAA;AAAA,YACL,SAAS,MAAM;;AACT,gBAAAx6B,IAAAqE,EAAO,oBAAP,gBAAArE,EAAwB,iBAAgB,aACnCqE,EAAA,gBAAgB,KAAK,YAAY26B,CAAO,KAE/C/+B,IAAAoE,EAAO,oBAAP,QAAApE,EAAwB,KAAK,KAAK,YAAY++B;AAAA,YAChD;AAAA,UAEJ;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,aAAa,CAACx1B,MAAU;AAChB,kBAAA,EAAE,KAAAxB,GAAK,WAAA6W,EAAA,IAAcrV;AAW3B,gBATI,CAACnF,EAAO,cAIR,CAACwa,EAAU,SAKXA,EAAU,MAAM,OAAO,KAAK,KAAK;AACnC;AAGF,kBAAM8gB,IAAO,CAAC;AAId,YAAIn2B,EAAM,IAAI,QAAQ,SAAS,KACxBm2B,EAAA;AAAA,cACH/G,EAAW,KAAK,GAAG,GAAG;AAAA,gBACpB,4BAA4B;AAAA,cAC7B,CAAA;AAAA,YACH;AAGF,kBAAM3wB,IAAO4W,EAAU,SACjBje,IAAOqH,EAAK;AAEd,gBAAArH,EAAK,QAAQ,SAAS,GAAG;AACrB,oBAAA0rB,IAASrkB,EAAK,OAAO;AAEtB,cAAA03B,EAAA;AAAA,gBACH/G,EAAW,KAAKtM,GAAQA,IAAS1rB,EAAK,UAAU;AAAA,kBAC9C,6BAA6B;AAAA,gBAC9B,CAAA;AAAA,cACH;AAAA,YAAA;AAGK,mBAAA43B,EAAc,OAAOxwB,GAAK23B,CAAI;AAAA,UAAA;AAAA,QACvC;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ;AC7IA,MAAMhc,KAAa,IAAInkB,EAAU,iBAAiB,GAE5CogC,KAAyC;AAAA;AAAA,EAE7C,OAAO;AAAA;AAAA,EAEP,OAAO;AAAA;AAAA,EAEP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,gBAAgB;AAClB;AAUO,MAAMC,WAAgChK,EAAmB;AAAA,EAC9D,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAGT,cAAc;AACN,UAAA;AACF,QAAAiK;AACC,SAAA;AAAA,MACH,IAAIvgC,EAAO;AAAA,QACT,KAAKokB;AAAAA,QACL,KAAKoc,GAAa;AACT,iBAAA;AAAA,YACL,QAAQ,OAAO3+B,GAAM4+B,MAAe;;AAC9B,gBAAAhgC,IAAA,KAAK,QAAL,gBAAAA,EAAU,SAASoB,EAAK,OAAO,cAAc,QAAO,MAGtD0+B,IAAU,WAAW,MAAM;AACpB,gBAAA1+B,EAAA;AAAA,kBACHA,EAAK,MAAM,GAAG,QAAQuiB,IAAY,EAAE,aAAa,GAAM,CAAA;AAAA,gBACzD;AAAA,iBACC,CAAC;AAAA,YAER;AAAA,YACA,SAAS,MAAM;AACb,cAAImc,KACF,aAAaA,CAAO;AAAA,YACtB;AAAA,UAEJ;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,OAAO;AACE,mBAAA;AAAA;AAAA,cAEL,8BAA8B,CAAC;AAAA;AAAA,cAE/B,iCAAiC,CAAC;AAAA;AAAA,cAElC,mCAAmB,IAAY;AAAA,YACjC;AAAA,UACF;AAAA,UAEA,MAAMjgC,GAAao6B,GAAMv6B,GAAUC,GAAU;AAIvC,gBAHJs6B,EAAK,kCAAkC,CAAC,GACxCA,EAAK,cAAc,MAAM,GAErB,CAACp6B,EAAY,cAAcH,EAAS,IAAI,GAAGC,EAAS,GAAG;AAClD,qBAAAs6B;AAuBT,kBAAMgG,IAA0C,CAAC,GAE3CC,IAAWC;AAAA,cACfzgC,EAAS;AAAA,cACT,CAACkB,MAASA,EAAK,MAAM;AAAA,YACvB,GACMw/B,IAAe,IAAI;AAAA,cACvBF,EAAS,IAAI,CAACt/B,MAAS,CAACA,EAAK,KAAK,MAAM,IAAIA,CAAI,CAAC;AAAA,YACnD,GACMF,IAAWy/B;AAAA,cACfxgC,EAAS;AAAA,cACT,CAACiB,MAASA,EAAK,MAAM;AAAA,YACvB;AAGA,uBAAWA,KAAQF,GAAU;AAC3B,oBAAM2/B,IAAUD,EAAa,IAAIx/B,EAAK,KAAK,MAAM,EAAE,GAE7C0/B,IAAiBD,KAAA,gBAAAA,EAAS,KAAK,YAC/BE,IAAiB3/B,EAAK,KAAK;AAE7B,kBAAAy/B,KAAWC,KAAkBC,GAAgB;AAC/C,sBAAMC,IAAW;AAAA,kBACf,OAAOD,EAAe,MAAM;AAAA,kBAC5B,OAAOA,EAAe,MAAM;AAAA,kBAC5B,MAAMA,EAAe,KAAK;AAAA,kBAC1B,OAAO5gC,EAAS,IAAI,QAAQiB,EAAK,GAAG,EAAE;AAAA,gBACxC;AAEA,oBAAI6/B,IAAW;AAAA,kBACb,OAAOH,EAAe,MAAM;AAAA,kBAC5B,OAAOA,EAAe,MAAM;AAAA,kBAC5B,MAAMA,EAAe,KAAK;AAAA,kBAC1B,OAAO5gC,EAAS,IAAI,QAAQ2gC,EAAQ,GAAG,EAAE;AAAA,gBAC3C;AAEA,gBAAAJ,EAAwCr/B,EAAK,KAAK,MAAM,EAAE,IACxD6/B,GASE5gC,EAAY,QAAQ,sBAAsB,MAGxCe,EAAK,KAAK,MAAM,MAAMq5B,EAAK,iCAC7BwG,IACExG,EAAK,6BAA6Br5B,EAAK,KAAK,MAAM,EAAE,IAKpD4/B,EAAS,SAAS,uBACpBC,EAAS,QAAQD,EAAS,SAI9BvG,EAAK,gCAAgCr5B,EAAK,KAAK,MAAM,EAAE,IACrD6/B,GAGE,KAAK,UAAUA,CAAQ,MAAM,KAAK,UAAUD,CAAQ,MACrDC,EAAiB,cAAc,IAC9BA,EAAS,QAAQD,EAAS,OAY5BvG,EAAK,cAAc,IAAIr5B,EAAK,KAAK,MAAM,EAAE;AAAA,cAC3C;AAAA,YACF;AAGF,mBAAAq5B,EAAK,+BACHgG,GAEKhG;AAAA,UAAA;AAAA,QAEX;AAAA,QACA,OAAO;AAAA,UACL,YAAYzwB,GAAO;AACX,kBAAAkwB,IAAe,KAAgB,SAASlwB,CAAK;AAC/C,gBAAAkwB,EAAY,cAAc,SAAS;AAC9B;AAGT,kBAAMhB,IAA4B,CAAC;AAEnC,mBAAAlvB,EAAM,IAAI,YAAY,CAAC5I,GAAMI,MAAQ;AAKnC,kBAJI,CAACJ,EAAK,MAAM,MAIZ,CAAC84B,EAAY,cAAc,IAAI94B,EAAK,MAAM,EAAE;AAC9C;AAGF,oBAAM8/B,IACJhH,EAAY,gCAAgC94B,EAAK,MAAM,EAAE,GACrD+/B,IAAuB,CAAC;AAE9B,yBAAW,CAACC,GAAUh+B,CAAG,KAAK,OAAO,QAAQ89B,CAAS;AACpD,gBAAAC,EAAgB,eAAef,GAAegB,CAAQ,CAAC,IACrDh+B,KAAO;AASX,oBAAMi+B,IAAajI,EAAW,KAAK53B,GAAKA,IAAMJ,EAAK,UAAU;AAAA,gBAC3D,GAAG+/B;AAAA,cAAA,CACJ;AAED,cAAAjI,EAAY,KAAKmI,CAAU;AAAA,YAAA,CAC5B,GAEMrI,EAAc,OAAOhvB,EAAM,KAAKkvB,CAAW;AAAA,UAAA;AAAA,QACpD;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ;ACpOA,MAAM/U,KAAa,IAAInkB,EAAU,0BAA0B;AAOpD,MAAMshC,WAA4BjL,EAAmB;AAAA,EAOnD,YAA6BxxB,GAAwC;AACpE,UAAA;AAHA,IAAAylB,EAAA,iBAAU;AAEkB,SAAA,SAAAzlB,GAE7B,KAAA;AAAA,MACH,IAAI9E,EAAO;AAAA,QACT,KAAKokB;AAAA,QACL,OAAO;AAAA,UACL,aAAa,CAACna,MAAU;AAChB,kBAAA,EAAE,KAAAxB,GAAK,WAAA6W,EAAA,IAAcrV;AAEvB,gBAAA,CAAC,KAAK;AACR,qBAAOgvB,EAAc;AAGvB,kBAAMuI,IAAMnI,EAAW,OAAO/Z,EAAU,MAAMA,EAAU,IAAI;AAAA,cAC1D,uBAAuB;AAAA,YAAA,CACxB;AAED,mBAAO2Z,EAAc,OAAOxwB,GAAK,CAAC+4B,CAAG,CAAC;AAAA,UAAA;AAAA,QACxC;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA3BF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA6BF,WAAWC,GAAkB;AAC9B,IAAA,KAAK,YAAYA,MAIrB,KAAK,UAAUA,GAEV,KAAA,OAAO,SAAS,CAACjhC,MAAOA,EAAG,QAAQ4jB,IAAY,CAAA,CAAE,CAAC;AAAA,EAAA;AAAA,EAGlD,aAAa;AAClB,WAAO,KAAK;AAAA,EAAA;AAEhB;ACtDgB,SAAAsd,GACd/hC,GACAkC,GACA;;AAEE,SAAAlC,KACAA,EAAQ,iBACRA,EAAQ,kBAAkBkC,EAAK,SAC/BpB,IAAAd,EAAQ,iBAAR,gBAAAc,EAAA,KAAAd,GAAuB,uBAAsB;AAE7C,IAAAA,IAAUA,EAAQ;AAEpB,QAAIe,IAAAf,EAAQ,iBAAR,gBAAAe,EAAA,KAAAf,GAAuB,uBAAsB;AAGjD,WAAO,EAAE,MAAMA,GAAwB,IAAIA,EAAQ,aAAa,SAAS,EAAG;AAC9E;ACFO,MAAMgiC,WAA8BC,GAAU;AAAA,EAGnD,YAAYC,GAAsBC,GAAoB;AACpD,UAAMD,GAASC,CAAK;AAHtB,IAAAvX,EAAA;AAMQ,UAAAqD,IAAaiU,EAAQ,KAAK;AAEhC,SAAK,QAAQ,CAAC,GACNA,EAAA,IAAI,aAAaA,EAAQ,KAAKC,EAAM,KAAK,CAACzgC,GAAM0gC,GAAMxnB,MAAW;AACvE,UAAIA,MAAW,QAAQA,EAAO,GAAGqT,CAAU;AACpC,oBAAA,MAAM,KAAKvsB,CAAI,GACb;AAAA,IAET,CACD;AAAA,EAAA;AAAA,EAGH,OAAO,OAAOoH,GAAW+K,GAAcC,IAAKD,GAA6B;AAChE,WAAA,IAAImuB,GAAsBl5B,EAAI,QAAQ+K,CAAI,GAAG/K,EAAI,QAAQgL,CAAE,CAAC;AAAA,EAAA;AAAA,EAGrE,UAAiB;AACR,WAAA,IAAInR,EAAMD,EAAS,KAAK,KAAK,KAAK,GAAG,GAAG,CAAC;AAAA,EAAA;AAAA,EAGlD,GAAGid,GAA+B;AAShC,QARI,EAAEA,aAAqBqiB,OAIvB,KAAK,MAAM,WAAWriB,EAAU,MAAM,UAItC,KAAK,SAASA,EAAU,QAAQ,KAAK,OAAOA,EAAU;AACjD,aAAA;AAGT,aAASja,IAAI,GAAGA,IAAI,KAAK,MAAM,QAAQA;AACjC,UAAA,CAAC,KAAK,MAAMA,CAAC,EAAE,GAAGia,EAAU,MAAMja,CAAC,CAAC;AAC/B,eAAA;AAIJ,WAAA;AAAA,EAAA;AAAA,EAGT,IAAIoD,GAAWzH,GAA8B;AAC3C,UAAMghC,IAAahhC,EAAQ,UAAU,KAAK,IAAI,GACxCihC,IAAWjhC,EAAQ,UAAU,KAAK,EAAE;AAE1C,WAAIihC,EAAS,UACJL,GAAU,KAAKn5B,EAAI,QAAQu5B,EAAW,GAAG,CAAC,IAG/CA,EAAW,UACNJ,GAAU,KAAKn5B,EAAI,QAAQw5B,EAAS,GAAG,CAAC,IAG1C,IAAIN;AAAA,MACTl5B,EAAI,QAAQu5B,EAAW,GAAG;AAAA,MAC1Bv5B,EAAI,QAAQw5B,EAAS,GAAG;AAAA,IAC1B;AAAA,EAAA;AAAA,EAGF,SAAc;AACL,WAAA,EAAE,MAAM,iBAAiB,QAAQ,KAAK,QAAQ,MAAM,KAAK,KAAK;AAAA,EAAA;AAEzE;AAEAL,GAAU,OAAO,iBAAiBD,EAAqB;ACtEvD,IAAIO;AAWJ,SAASC,GAA4B7iB,GAAsB7W,GAAW;AAIhE,MAAA25B,GACAC;AAOE,QAAAC,IACJ75B,EAAI,QAAQ6W,EAAU,IAAI,EAAE,OAAO,KAAK,KAAK,UAAU,gBACnDijB,IACJ95B,EAAI,QAAQ6W,EAAU,EAAE,EAAE,OAAO,KAAK,KAAK,UAAU,gBAGjDkjB,IAAW,KAAK,IAAIljB,EAAU,QAAQ,OAAOA,EAAU,MAAM,KAAK;AAExE,MAAIgjB,KAAgCC,GAA4B;AAI9D,UAAME,IAAqBnjB,EAAU,MAAM,MAAMkjB,IAAW,CAAC,GACvDE,IAAkBpjB,EAAU,IAAI,IAAIkjB,IAAW,CAAC;AAGtD,IAAAJ,IAAsB35B,EAAI,QAAQg6B,IAAqB,CAAC,EAAE,KAC1DJ,IAAoB55B,EAAI,QAAQi6B,IAAkB,CAAC,EAAE;AAAA,EAAA;AAErD,IAAAN,IAAsB9iB,EAAU,MAChC+iB,IAAoB/iB,EAAU;AAGhC,SAAO,EAAE,MAAM8iB,GAAqB,IAAIC,EAAkB;AAC5D;AAEA,SAASM,GAAa9gC,GAAkB2R,GAAcC,IAAKD,GAAM;AAC/D,EAAIA,MAASC,MAELA,KAAA5R,EAAK,MAAM,IAAI,QAAQ2R,IAAO,CAAC,EAAE,OAAO;AAIhD,QAAMovB,IAAc/gC,EAAK,SAAS2R,CAAI,EAAE,KAAK,UAAU,EAAI,GACrD+G,IAAS1Y,EAAK,SAAS2R,CAAI,EAAE,MAE7BqvB,IAAkB,CAACC,GAAwB3nB,MAC/C,MAAM,UAAU,QAAQ,KAAK2nB,EAAc,UAAU3nB,CAAa,GAE9D4nB,IAA0BF;AAAA,IAC9BtoB;AAAA;AAAA,IAEA1Y,EAAK,SAAS2R,IAAO,CAAC,EAAE,KAAK;AAAA,EAC/B,GACMwvB,IAAyBH;AAAA,IAC7BtoB;AAAA;AAAA,IAEA1Y,EAAK,SAAS4R,IAAK,CAAC,EAAE,KAAK;AAAA,EAC7B;AAEA,WAASpO,IAAIkV,EAAO,oBAAoB,GAAGlV,KAAK,GAAGA;AAC7C,KAAAA,IAAI29B,KAA0B39B,IAAI09B,MACpCH,EAAY,YAAYA,EAAY,SAASv9B,CAAC,CAAC;AAKnD,EAAA49B,GAAephC,EAAK,IAAI,GACLqgC,IAAAU;AAKb,QAAAM,IAAUhB,EAAiB,qBAAqB,QAAQ;AAC9D,WAAS78B,IAAI,GAAGA,IAAI69B,EAAQ,QAAQ79B,KAAK;AACjC,UAAA89B,IAASD,EAAQ79B,CAAC,GAClBkV,IAAS4oB,EAAO;AAEtB,IAAI5oB,KACFA,EAAO,YAAY4oB,CAAM;AAAA,EAC3B;AAMF,QAAMC,IADUvhC,EAAK,IAAI,UAAU,MAAM,GAAG,EAEzC;AAAA,IACC,CAACiX,MACCA,MAAc,iBACdA,MAAc,aACdA,MAAc;AAAA,EAAA,EAEjB,KAAK,GAAG;AAEMopB,EAAAA,EAAA,YACfA,EAAiB,YAAY,sBAAsBkB,GAEjDvhC,EAAK,gBAAgB,aAClBA,EAAA,KAAK,YAAYqgC,CAAgB,IAEjCrgC,EAAA,KAAK,KAAK,YAAYqgC,CAAgB;AAE/C;AAEO,SAASe,GAAeI,GAA+B;AAC5D,EAAInB,MAAqB,WACnBmB,aAAkB,aACpBA,EAAO,YAAYnB,CAAgB,IAE5BmB,EAAA,KAAK,YAAYnB,CAAgB,GAGvBA,IAAA;AAEvB;AAEgB,SAAAoB,GAKd,GACAz+B,GACAC,GACA;AACI,MAAA,CAAC,EAAE;AACL;AAGF,QAAMjD,IAAOiD,EAAO;AACpB,MAAI,CAACjD;AACH;AAGF,QAAMiI,IAAUqL,EAAYtQ,EAAM,IAAIhD,EAAK,MAAM,GAAG;AACpD,MAAI,CAACiI;AACH,UAAM,IAAI,MAAM,iBAAiBjF,EAAM,EAAE,YAAY;AAEvD,QAAMpD,IAAMqI,EAAQ;AAEpB,MAAIrI,KAAO,MAAM;AACT,UAAA6d,IAAYzd,EAAK,MAAM,WACvB4G,IAAM5G,EAAK,MAAM,KAEjB,EAAE,MAAA2R,GAAM,IAAAC,EAAA,IAAO0uB,GAA4B7iB,GAAW7W,CAAG,GAEzD86B,IAA0B/vB,KAAQ/R,KAAOA,IAAMgS,GAC/C+vB,IACJlkB,EAAU,QAAQ,KAAA,MAAWA,EAAU,MAAM,UAC7CA,aAAqBqiB;AAEvB,IAAI4B,KAA2BC,KACxB3hC,EAAA;AAAA,MACHA,EAAK,MAAM,GAAG,aAAa8/B,GAAsB,OAAOl5B,GAAK+K,GAAMC,CAAE,CAAC;AAAA,IACxE,GACakvB,GAAA9gC,GAAM2R,GAAMC,CAAE,MAEtB5R,EAAA;AAAA,MACHA,EAAK,MAAM,GAAG,aAAaupB,GAAc,OAAOvpB,EAAK,MAAM,KAAKJ,CAAG,CAAC;AAAA,IACtE,GACAkhC,GAAa9gC,GAAMJ,CAAG;AAGxB,UAAMgiC,IAAgB5hC,EAAK,MAAM,UAAU,QAAQ,GAC7CyI,IAASxF,EAAO,UAEhB8wB,IACJ/zB,EAAK,sBAAsB4hC,CAAa,EAAE,IAAI,WAE1C/N,IAAuBvb,GAA2B7P,GAAQxF,CAAM,GAEhEgI,IAASsoB,GAAiBqO,EAAc,OAAO,GAC/CxS,IAAeyE,EAAqB,aAAa5oB,GAAQ,CAAA,CAAE,GAE3DmoB,IAAYnE,GAAoBG,CAAY;AAElD,MAAE,aAAa,UAAU,GACvB,EAAA,aAAa,QAAQ,kBAAkB2E,CAAa,GACpD,EAAA,aAAa,QAAQ,aAAa3E,CAAY,GAC9C,EAAA,aAAa,QAAQ,cAAcgE,CAAS,GAC9C,EAAE,aAAa,gBAAgB,QAC/B,EAAE,aAAa,aAAaiN,GAAmB,GAAG,CAAC;AAAA,EAAA;AAEvD;ACvLA,MAAMwB,KAAiD;AAEvD,SAASC,GACP9hC,GACA6xB,GACAkQ,GACAC,IAAmB,IACnB;AACM,QAAAC,IAAWjiC,EAAK,KAAK;AAAA;AAAA,IAEzB6xB,EAAO,QAAQkQ,MAAsB,WAAW,KAAK;AAAA,IACrDlQ,EAAO;AAAA,EACT;AAEA,aAAW/zB,KAAWmkC;AACpB,QAAKjiC,EAAK,IAAI,SAASlC,CAAO;AAI9B,aAAIkkC,KACalkC,EAAQ,QAAQ,6BAA6B,IAEnDgkC;AAAA,QACL9hC;AAAA,QACA;AAAA,UACE,MAAM6xB,EAAO,OAAO;AAAA;AAAA,UACpB,KAAKA,EAAO;AAAA,QACd;AAAA,QACAkQ;AAAA,QACA;AAAA,MACF,IAGGlC,GAA6B/hC,GAASkC,CAAI;AAGrD;AAEA,SAASkiC,GACPC,GAIAniC,GACA+hC,GAC+C;AAK3C,MAAA,CAAC/hC,EAAK,IAAI;AACZ;AAGF,QAAMoiC,IACJpiC,EAAK,IAAI,WACT,sBAAsB,GAKlB6xB,IAAS;AAAA,IACb,MAAMsQ,EAAS;AAAA,IACf,KAAKA,EAAS;AAAA,EAChB,GAEME,IAAoBxQ,EAAO,OAAOuQ,EAAkB,MACpDE,IAAqBzQ,EAAO,OAAOuQ,EAAkB;AAG3D,EAAIL,MAAsB,eACpBM,MACKxQ,EAAA,OAAOuQ,EAAkB,OAAO,KAGrCE,MACKzQ,EAAA,OAAOuQ,EAAkB,QAAQ;AAI5C,MAAIp/B,IAAQ8+B,GAAmB9hC,GAAM6xB,GAAQkQ,CAAiB;AAE1D,MAAA,CAACO,KAAsBt/B,GAAO;AAW1B,UAAAu/B,IAAOv/B,EAAM,KAAK,sBAAsB;AACvC,IAAA6uB,EAAA,OAAO0Q,EAAK,QAAQ,IAC3Bv/B,IAAQ8+B,GAAmB9hC,GAAM6xB,GAAQ,YAAY,EAAK;AAAA,EAAA;AAGrD,SAAA7uB;AACT;AAKO,MAAMw/B,GAKb;AAAA,EAYE,YACmBv/B,GACA8+B,GACA7J,GACjBC,GACA;AAhBK,IAAAzP,EAAA;AACS,IAAAA,EAAA;AAER,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAED,IAAAA,EAAA,oBAAa;AAEb,IAAAA,EAAA,sBAAe;AAwDtB,IAAAA,EAAA,qBAAc,CAACtgB,MAAwC;AACrD,WAAK,QAAQA,GACR,KAAA,WAAW,KAAK,KAAK;AAAA,IAC5B;AAEA,IAAAsgB,EAAA,iCAA0B,MAAM;;AAC9B,UAAI,KAAK,cAAc,CAAC,KAAK;AAC3B;AAGF,YAAM1lB,IAAQk/B;AAAA,QACZ,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAGA,UAAI,CAACl/B,KAAS,CAAC,KAAK,OAAO,YAAY;AACjC,SAAApE,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IACb,KAAA,YAAY,KAAK,KAAK;AAG7B;AAAA,MAAA;AAIF,WACEC,IAAA,KAAK,UAAL,QAAAA,EAAY,UACZoC,IAAA,KAAK,iBAAL,QAAAA,EAAmB,aAAa,iBAChCC,IAAA,KAAK,iBAAL,gBAAAA,EAAmB,aAAa,gBAAe8B,EAAM;AAErD;AAGF,WAAK,eAAeA,EAAM;AAIpB,YAAAL,IAAeK,EAAM,KAAK;AAEhC,UAAKL,KAOD,KAAK,OAAO,YAAY;AACpB,cAAA8/B,IAA0B9/B,EAAa,sBAAsB,GAC7DmnB,IAAS9mB,EAAM,KAAK,QAAQ,yBAAyB;AAC3D,aAAK,YAAY;AAAA,UACf,MAAM;AAAA,UACN,cAAc,IAAI;AAAA,YAChB8mB;AAAA;AAAA;AAAA;AAAA;AAAA,cAKIA,EAAO,kBAAmB,wBAAwB;AAAA,gBAEhD,KAAK,OAAO,IAAI,WAChB,sBAAwB,EAAA;AAAA,YAC9B2Y,EAAwB;AAAA,YACxBA,EAAwB;AAAA,YACxBA,EAAwB;AAAA,UAC1B;AAAA,UACA,OAAO,KAAK,OAAO;AAAA,YACjB,KAAK,aAAc,aAAa,SAAS;AAAA,UAAA;AAAA,QAC3C,CACD;AAAA,MAAA;AAAA,IAEL;AAEA,IAAA/Z,EAAA,gBAAS,CAACxoB,MAAqB;;AAGzB,UAAA,KAAK,OAAO,aAAa;AAC3B;AAGG,WAAA,OAAO,cAAc,SAAS,KAAK;AAIxC,YAAMwiC,IACJxiC,EAAM,kBAAkB,UACnBtB,IAAAsB,EAAM,kBAAkB,cACrBA,EAAM,SACNA,EAAM,OAAO,kBAFhB,gBAAAtB,EAGE,QAAQ,kBAAiB;AAyChC,UArCE8jC,MAKE,CAAC,KAAK,gBAAgB,KAAK,OAAO,QAAQA,IAI5C,KAAK,OAAO;AAAA,QACV,KAAK,OAAO,MAAM,GAAG;AAAA,UACnBllB,EAAc;AAAA,YACZ,KAAK,OAAO,MAAM,GAAG;AAAA,YACrB,KAAK,OAAO,MAAM,GAAG,UAAU;AAAA,UAAA;AAAA,QACjC;AAAA,MAEJ,IACS,KAAK,gBAAgB,KAAK,OAAO,QAAQklB,KAYlD;AAAA,QACE,MAAM,KAAK,OAAO,SAAS,KAAK,OAAO,MAAM,GAAG,iBAAiB;AAAA,QACjE;AAAA,MACF,IAKF,KAAK,sBAAsB,YAC1BxiC,EAAc,aACf,GAACrB,IAAAqB,EAAM,iBAAN,QAAArB,EAAoB,MAAM,SAAS;AAEpC;AAGI,YAAAe,IAAM,KAAK,OAAO,YAAY;AAAA,QAClC,MAAMM,EAAM;AAAA,QACZ,KAAKA,EAAM;AAAA,MAAA,CACZ;AAED,UAAI,CAACN,KAAOA,EAAI,WAAW,IAAI;AAMvB,cAAA+iC,IAAM,KAAK,qBAAqBziC,CAAK;AAEtC,aAAA,OAAO,IAAI,cAAcyiC,CAAG;AAAA,MAAA;AAAA,IAErC;AAEA,IAAAja,EAAA,mBAAY,MAAM;AAKhB,WAAK,OAAO,WAAW;AAAA,IACzB;AAoBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,qBAAc,CAACxoB,MAAqB;;AAClC,YAAMsY,KAAO5Z,IAAAsB,EAAM,iBAAN,gBAAAtB,EAAoB,QAAQ;AACzC,UAAI,CAAC4Z;AACH;AAGE,UAAA,KAAK,OAAO;AACR,cAAA,IAAI,MAAM,wDAAwD;AAGpE,YAAA1a,IAAU,SAAS,cAAc,KAAK;AAC5C,MAAAA,EAAQ,YAAY0a;AAGd,YAAAhZ,IADSqhB,GAAU,WAAW,KAAK,OAAO,MAAM,MAAM,EACxC,MAAM/iB,GAAS;AAAA,QACjC,SAAS,KAAK,OAAO,MAAM,OAAO,MAAM,WAAc,OAAO;AAAA,MAAA,CAC9D;AAED,WAAK,OAAO,WAAW;AAAA,QACrB,OAAO,IAAI2C,EAAMjB,EAAK,SAAS,GAAG,CAAC;AAAA,QACnC,MAAM;AAAA,MACR;AAAA,IACF;AAOA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAkpB,EAAA,oBAAa,CAACxoB,MAAqB;;AAE/B,UAAA,KAAK,sBAAsB,YAC1BA,EAAc,aACf,GAACtB,IAAAsB,EAAM,iBAAN,QAAAtB,EAAoB,MAAM,SAAS;AAEpC;AAGI,YAAAgB,IAAM,KAAK,OAAO,YAAY;AAAA,QAClC,MAAMM,EAAM;AAAA,QACZ,KAAKA,EAAM;AAAA,MAAA,CACZ;AAEG,UAAA,CAACN,KAAQA,EAAI,WAAW,MAAM,KAAK,OAAO,IAAI,YAAa;AACvD,cAAA+iC,IAAM,KAAK,qBAAqBziC,CAAK;AAEtC,aAAA,OAAO,IAAI,cAAcyiC,CAAG;AAAA,MAAA;AAAA,IAErC;AAEA,IAAAja,EAAA,mBAAY,CAACka,MAA0B;;AACrC,OAAIhkC,IAAA,KAAK,UAAL,QAAAA,EAAY,QAAQ,KAAK,OAAO,gBAElC,KAAK,MAAM,OAAO,IACb,KAAA,WAAW,KAAK,KAAK;AAAA,IAE9B;AAEA,IAAA8pB,EAAA,qBAAc,CAACxoB,MAAsB;;AACnC,UAAI,KAAK;AACP;AAGF,WAAK,WAAW,EAAE,GAAGA,EAAM,SAAS,GAAGA,EAAM,QAAQ;AAIrD,YAAM2iC,IAAyB,KAAK,OAAO,IAAI,sBAAsB,GAC/DC,IACJ,KAAK,SAAS,IAAID,EAAuB,QACzC,KAAK,SAAS,IAAIA,EAAuB,SACzC,KAAK,SAAS,IAAIA,EAAuB,OACzC,KAAK,SAAS,IAAIA,EAAuB,QAGrC1J,IAAgB,KAAK,OAAO,IAAK;AAIvC;AAAA;AAAA,QAEE2J;AAAA,QAEA5iC,KACAA,EAAM;AAAA,QAEN,EACEi5B,MAAkBj5B,EAAM,UACxBi5B,EAAc,SAASj5B,EAAM,MAAqB;AAAA,QAEpD;AACI,SAAAtB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IACb,KAAA,WAAW,KAAK,KAAK;AAG5B;AAAA,MAAA;AAGF,WAAK,wBAAwB;AAAA,IAC/B;AA0DA,IAAA8pB,EAAA,kBAAW,MAAM;;AACX,OAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,eAAe,KAAK,aAAc,sBAAsB,GAC9D,KAAA,WAAW,KAAK,KAAK;AAAA,IAE9B;AA7YmB,SAAA,SAAAqE,GACA,KAAA,oBAAA8+B,GACA,KAAA,SAAA7J,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,8CAA8C;AAGhE,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GAC0B7J,GAAA,GAG1B,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GAGA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GAKA4J,EAAO,KAAK,iBAAiB,UAAU,KAAK,UAAU,EAAI;AAAA,EAAA;AAAA,EA8RpD,qBAAqBh4B,GAAkB;AAC7C,UAAMyiC,IAAM,IAAI,MAAMziC,EAAM,MAAMA,CAAK,GACjCkiC,IACJ,KAAK,OAAO,IAAI,WAChB,sBAAsB;AACxB,WAAAO,EAAI,UAAUziC,EAAM,SACpByiC,EAAI,UAAUziC,EAAM,SAElBA,EAAM,UAAUkiC,EAAkB,QAClCliC,EAAM,UACJkiC,EAAkB,OAChBA,EAAkB,QAChBP,KAGNc,EAAI,UACFP,EAAkB,OACjBA,EAAkB,QACjBP,KACA,IAEJ3hC,EAAM,UAAUkiC,EAAkB,SAClCliC,EAAM,UACJkiC,EAAkB,QAChBA,EAAkB,QAChBP,KAGNc,EAAI,UACFP,EAAkB,QACjBA,EAAkB,QACjBP,KACA,KAEJ3hC,EAAM,UAAUkiC,EAAkB,QAClCliC,EAAM,UAAUkiC,EAAkB,WAGlCO,EAAI,UACFP,EAAkB,OAClBP,KACEO,EAAkB,QAClB,IAGNO,EAAI,UAAU,KAAK;AAAA,MACjB,KAAK,IAAIziC,EAAM,SAASkiC,EAAkB,GAAG;AAAA,MAC7CA,EAAkB,MAAMA,EAAkB;AAAA,IAC5C,GAEAO,EAAI,eAAeziC,EAAM,cACrByiC,EAAA,iBAAiB,MAAMziC,EAAM,eAAe,GAChDyiC,EAAI,YAAY,IACTA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBT,OAAO1Q,GAAmBoG,GAAwB;;AAE5C,IADe,CAACA,EAAU,IAAI,GAAG,KAAK,OAAO,MAAM,GAAG,OACxCz5B,IAAA,KAAK,UAAL,QAAAA,EAAY,SAC5B,KAAK,wBAAwB;AAAA,EAC/B;AAAA,EAGF,UAAU;;AACJ,KAAAA,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IACb,KAAA,WAAW,KAAK,KAAK,IAE5B,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF,GACA,KAAK,OAAO,KAAK,oBAAoB,UAAU,KAAK,UAAU,EAAI;AAAA,EAAA;AAEtE;AAEa,MAAAmkC,KAAoB,IAAI3kC,EAAU,gBAAgB;AAExD,MAAM4kC,WAIHvO,EAAmB;AAAA,EAO3B,YACmBxxB,GACjB8+B,GACA;AACM,UAAA;AAND,IAAArZ,EAAA;AAgCP;AAAA;AAAA;AAAA,IAAAA,EAAA,wBAAiB,CACfxoB,GAIA8C,MACG;AACH,MAAI,KAAK,SACP,KAAK,KAAK,eAAe,KAGjBy+B,GAAAvhC,GAAO8C,GAAO,KAAK,MAAM;AAAA,IACrC;AAKA;AAAA;AAAA;AAAA,IAAA0lB,EAAA,sBAAe,MAAM;AACf,MAAA,KAAK,OAAO,mBACC0Y,GAAA,KAAK,OAAO,gBAAgB,IAAI,GAG7C,KAAK,SACP,KAAK,KAAK,eAAe;AAAA,IAE7B;AAMA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA1Y,EAAA,oBAAa,MAAM;AACjB,WAAK,KAAM,aAAa,IACnB,KAAA,KAAM,MAAO,OAAO,IACzB,KAAK,KAAM,WAAW,KAAK,KAAM,KAAM;AAAA,IACzC;AAMA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,sBAAe,MAAM;AACnB,WAAK,KAAM,aAAa,IACnB,KAAA,KAAM,MAAO,OAAO,IACzB,KAAK,KAAM,WAAW,KAAK,KAAM,KAAM;AAAA,IACzC;AA1EmB,SAAA,SAAAzlB,GAIZ,KAAA;AAAA,MACH,IAAI9E,EAAO;AAAA,QACT,KAAK4kC;AAAA,QACL,MAAM,CAACnK,OACL,KAAK,OAAO,IAAI4J;AAAA,UACdv/B;AAAA,UACA8+B;AAAA,UACAnJ;AAAA,UACA,CAACxwB,MAAU;AACJ,iBAAA,KAAK,UAAUA,CAAK;AAAA,UAAA;AAAA,QAE7B,GACO,KAAK;AAAA,MAEf,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA1BF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA4BF,SAASosB,GAAyD;AAChE,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAoDrC;ACxqBA,MAAMyO,yBAAsB,IAA6C;AAKzE,SAASC,GAAWjgC,GAAwC;AACtD,MAAAggC,GAAgB,IAAIhgC,CAAM;AAErB,WAAAggC,GAAgB,IAAIhgC,CAAM;AAE7B,QAAA9D,IAAU,IAAIgkC,GAAQ;AAC5B,SAAAlgC,EAAO,cAAc,GAAG,eAAe,CAAC,EAAE,aAAAxE,QAAkB;AAClD,IAAAU,EAAA,cAAcV,EAAY,OAAO;AAAA,EAAA,CAC1C,GACMwE,EAAA,cAAc,GAAG,WAAW,MAAM;AAEvC,IAAAggC,GAAgB,OAAOhgC,CAAM;AAAA,EAAA,CAC9B,GAGeggC,GAAA,IAAIhgC,GAAQ9D,CAAO,GAE5BA;AACT;AAaO,SAASikC,GAIdngC,GAIAgE,GAIAo8B,IAAyB,QACX;AACd,QAAMC,IAAmBxL,GAAe;AAAA,IACtC70B,EAAO,cAAc;AAAA,EACvB;AAKA,MAAI,CAACqgC,GAAkB;AAGf,UAAAnkC,IAAU+jC,GAAWjgC,CAAM,GAG3BsgC,IAAmBpkC,EAAQ,KAAK;AAEtC,WAAO,MACOA,EAET,MAAMokC,CAAgB,EACtB,IAAIt8B,GAAUo8B,MAAS,SAAS,KAAK,CAAC;AAAA,EAG3C;AAGF,QAAMG,IAAmBC;AAAA;AAAA,IAEvBx8B,KAAYo8B,MAAS,UAAU,IAAI;AAAA,IACnCC,EAAiB,QAAQ;AAAA,IACzBA,EAAiB,QAAQ;AAAA,EAC3B;AAEA,SAAO,MAAM;AACX,UAAMI,IAAsB5L,GAAe;AAAA,MACzC70B,EAAO,cAAc;AAAA,IACvB,GACMrD,IAAM+jC;AAAA,MACVD,EAAoB;AAAA,MACpBA,EAAoB,QAAQ;AAAA,MAC5BF;AAAA,MACAE,EAAoB,QAAQ;AAAA,IAC9B;AAGA,QAAI9jC,MAAQ;AACJ,YAAA,IAAI,MAAM,4CAA4C;AAGvD,WAAAA,KAAOyjC,MAAS,UAAU,KAAK;AAAA,EACxC;AACF;ACnGA,MAAMO,KAAYC,GAAe,CAACrkC,MAASA,EAAK,KAAK,SAAS,gBAAgB;AAO9E,MAAMskC,GAIJ;AAAA,EAMA,YACmB7gC,GACjBk1B,GACA;AARK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AACC,IAAAA,EAAA;AACR,IAAAA,EAAA;AA2BA,IAAAA,EAAA,sBAAe,MAAM;;AACf,WAAA9pB,IAAA,KAAK,UAAL,QAAAA,EAAY,MAAM;AACd,cAAAmlC,KAAiBllC,IAAA,KAAK,WAAL,gBAAAA,EAAa;AAAA,UAClC,wBAAwB,KAAK,YAAa,YAAY;AAAA;AAExD,YAAI,CAACklC;AACH;AAEG,aAAA,MAAM,eAAeA,EAAe,sBAAsB,GAC1D,KAAA,WAAW,KAAK,YAAa,gBAAiB;AAAA,MAAA;AAAA,IAEvD;AAiDA,IAAArb,EAAA,mBAAY,MAAM;AACX,WAAA,OAAO,SAAS,CAAC/pB,MAAOA,EAAG,QAAQqlC,IAAyB,IAAI,CAAC;AAAA,IACxE;AAEA,IAAAtb,EAAA,oBAAa,MAAM;AACb,MAAA,KAAK,gBAAgB,UAIzB,KAAK,OAAO,cACT,MAAA,EACA,QAEA,YAAY;AAAA,QACX,MACE,KAAK,YAAY,cAAc,KAC9B,KAAK,YAAY,yBACd,KAAK,YAAY,iBAAkB,SACnC;AAAA,QACN,IAAI,KAAK,OAAO,SAAS,CAAC/pB,MAAOA,EAAG,UAAU,IAAI;AAAA,MACnD,CAAA,EACA,IAAI;AAAA,IACT;;AA1GmB,SAAA,SAAAsE,GAGjB,KAAK,cAAc,QAEd,KAAA,aAAa,CAACghC,MAAqB;;AAClC,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,qDAAqD;AAGvE,MAAA9L,EAAW8L,GAAU;AAAA,QACnB,GAAG,KAAK;AAAA,QACR,oBAAmBrlC,IAAA,KAAK,gBAAL,gBAAAA,EAAkB;AAAA,MAAA,CACtC;AAAA,IACH,GAEK,KAAA,UAASA,IAAA,KAAK,OAAO,oBAAZ,gBAAAA,EAA6B,OAK3CC,IAAA,KAAK,WAAL,QAAAA,EAAa,iBAAiB,UAAU,KAAK,cAAc;AAAA,EAAI;AAAA,EAgBjE,OAAOmB,GAAkBq4B,GAAwB;;AACzC,UAAAQ,IACJmL,GAAwB,SAAS3L,CAAS,GACtC6L,IAA8BF,GAAwB;AAAA,MAC1DhkC,EAAK;AAAA,IACP,GAGMmkC,IAAUtL,MAAS,UAAaqL,MAAS,QACzCE,IAAUvL,MAAS,UAAaqL,MAAS;AAI/C,QAAI,CAACC,KAAW,EAHAtL,MAAS,UAAaqL,MAAS,WAGnB,CAACE;AAC3B;AAKF,QAFK,KAAA,cAAcA,IAAUvL,IAAOqL,GAEhCE,KAAW,CAAC,KAAK,OAAO,YAAY;AACtC,MAAI,KAAK,UACP,KAAK,MAAM,OAAO,KAEf,KAAA,WAAW,KAAK,YAAa,gBAAgB;AAElD;AAAA,IAAA;AAGI,UAAAL,KAAiBnlC,IAAA,KAAK,WAAL,gBAAAA,EAAa;AAAA,MAClC,wBAAwB,KAAK,YAAa,YAAY;AAAA;AAGpD,IAAA,KAAK,OAAO,cAAcmlC,MAC5B,KAAK,QAAQ;AAAA,MACX,MAAM;AAAA,MACN,cAAcA,EAAe,sBAAsB;AAAA,MACnD,OAAO,KAAK,YAAa;AAAA,IAC3B,GAEK,KAAA,WAAW,KAAK,YAAa,gBAAiB;AAAA,EACrD;AAAA,EAGF,UAAU;;AACR,KAAAnlC,IAAA,KAAK,WAAL,QAAAA,EAAa,oBAAoB,UAAU,KAAK,cAAc;AAAA,EAAI;AA0BtE;AAaA,MAAMolC,KAA0B,IAAI5lC,EAAU,sBAAsB;AAY7D,MAAMimC,WAIH5P,EAAmB;AAAA,EAQ3B,YAAYxxB,GAAwC;AAC5C,UAAA;AAJA,IAAAylB,EAAA;AACA,IAAAA,EAAA,2BAA8B,CAAC;AA6MvC,IAAAA,EAAA,6BAAsB,CAAC4b,MAA6B;AAC7C,WAAA,kBAAkB,KAAKA,CAAgB;AAAA,IAC9C;AAGA;AAAA,IAAA5b,EAAA,gCAAyB,CAAC4b,MAA6B;AAChD,WAAA,oBAAoB,KAAK,kBAAkB;AAAA,QAC9C,CAACliC,MAAMA,MAAMkiC;AAAA,MACf;AAAA,IACF;AAEA,IAAA5b,EAAA,mBAAY,MAAM,KAAK,KAAM,UAAU;AAEvC,IAAAA,EAAA,oBAAa,MAAM,KAAK,KAAM,WAAW;AAtNvC,UAAM6b,IAAoB,KAAK;AAC1B,SAAA;AAAA,MACH,IAAIpmC,EAAO;AAAA,QACT,KAAK6lC;AAAA,QAEL,MAAM,OACJ,KAAK,OAAO,IAAIF;AAAA,UACd7gC;AAAA,UACA,CAACqhC,GAAkBl8B,MAAU;AAC3B,iBAAK,KAAK,UAAUk8B,CAAgB,IAAIl8B,CAAK;AAAA,UAAA;AAAA,QAEjD,GACO,KAAK;AAAA,QAGd,OAAO;AAAA;AAAA,UAEL,OAA8B;AAAA,UAE9B;AAAA;AAAA,UAGA,OAAO,CACL3J,GACAo6B,GACAnW,GACAnkB,MAC0B;AAO1B,gBALIE,EAAY,QAAQ,qBAAqB,MAAM,UAK/CA,EAAY,UAAU,MAAM,OAAO,KAAK,KAAK;AACxC,qBAAAo6B;AAKH,kBAAA2L,IAIK/lC,EAAY,QAAQulC,EAAuB;AAEtD,gBACE,OAAOQ,KAAoC,YAC3CA,MAAoC,MACpC;AACA,cAAI3L,KAEF,KAAK,UAAU;AAEjB,oBAAM4L,IAAkBrB;AAAA,gBACtBngC;AAAA,gBACA1E,EAAS,UAAU;AAAA,gBAEjBimC,EAAgC,iBAAiB;AAAA,cACrD;AACO,qBAAA;AAAA,gBACL,kBACEA,EAAgC;AAAA,gBAClC,wBACEA,EAAgC,2BAChC;AAAA;AAAA,gBAEF,eAAe,MACbC,EAAgB,IAChBD,EAAgC,iBAAiB;AAAA,gBACnD,OAAO;AAAA,gBACP,cAAc,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,UAAU,CAAC;AAAA,gBAC1D,mBACEA,KAAA,gBAAAA,EAAiC;AAAA,cACrC;AAAA,YAAA;AAIF,gBAAI3L,MAAS;AACJ,qBAAAA;AAIT;AAAA;AAAA,cAEEt6B,EAAS,UAAU,SAASA,EAAS,UAAU;AAAA,cAE/CimC,MAAoC;AAAA;AAAA,cAGpC/lC,EAAY,QAAQ,OAAO,KAC3BA,EAAY,QAAQ,MAAM,KAC1BA,EAAY,QAAQ,SAAS;AAAA,cAE5Bo6B,EAAK,qBAAqB,UACzBt6B,EAAS,UAAU,OAAOs6B,EAAK,cAAc;AAAA,cAE/C,CAACt6B,EAAS,UAAU,MAAM;AAAA,gBACxBA,EAAS,IAAI,QAAQs6B,EAAK,cAAe,CAAA;AAAA,cAAA;AAAA;AAGpC;AAGH,kBAAAqL,IAAO,EAAE,GAAGrL,EAAK;AAGlB,mBAAAqL,EAAA,QAAQ3lC,EAAS,IAAI;AAAA,cACxBs6B,EAAK,cAAc;AAAA,cACnBt6B,EAAS,UAAU;AAAA,YACrB,GAEO2lC;AAAA,UAAA;AAAA,QAEX;AAAA,QAEA,OAAO;AAAA,UACL,gBAAgBlkC,GAAM2R,GAAMC,GAAIO,GAAM;AAEpC,gBAAIR,MAASC,GAAI;AACT,oBAAAhL,IAAM5G,EAAK,MAAM;AACvB,yBAAW6D,KAAO0gC,GAAmB;AAC7B,sBAAAG,IACJ7gC,EAAI,SAAS,IACT+C,EAAI,YAAY+K,IAAO9N,EAAI,QAAQ8N,CAAI,IAAIQ,IAC3CA;AAEN,oBAAItO,MAAQ6gC;AACV,yBAAA1kC,EAAK,SAASA,EAAK,MAAM,GAAG,WAAWmS,CAAI,CAAC,GACvCnS,EAAA;AAAA,oBACHA,EAAK,MAAM,GACR,QAAQgkC,IAAyB;AAAA,sBAChC,kBAAkBU;AAAA,oBACnB,CAAA,EACA,eAAe;AAAA,kBACpB,GACO;AAAA,cACT;AAAA,YACF;AAEK,mBAAA;AAAA,UACT;AAAA;AAAA,UAGA,YAAYt8B,GAAO;AACX,kBAAAu8B,IACJ,KACA,SAASv8B,CAAK;AAEhB,gBAAIu8B,MAA0B;AACrB,qBAAA;AAKL,gBAAA,CAACA,EAAsB,wBAAwB;AAC3C,oBAAAC,IAAYhB,GAAUx7B,EAAM,SAAS;AAC3C,kBAAIw8B;AACK,uBAAAxN,EAAc,OAAOhvB,EAAM,KAAK;AAAA,kBACrCovB,EAAW;AAAA,oBACToN,EAAU;AAAA,oBACVA,EAAU,MAAMA,EAAU,KAAK;AAAA,oBAC/B;AAAA,sBACE,UAAU;AAAA,sBACV,OAAO;AAAA,sBACP,sBAAsBD,EAAsB;AAAA,oBAAA;AAAA,kBAC9C;AAAA,gBACF,CACD;AAAA,YACH;AAGK,mBAAAvN,EAAc,OAAOhvB,EAAM,KAAK;AAAA,cACrCovB,EAAW;AAAA,gBACTmN,EAAsB,cAAA,IACpBA,EAAsB,iBAAkB;AAAA,gBAC1CA,EAAsB,cAAc;AAAA,gBACpC;AAAA,kBACE,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,sBAAsBA,EAAsB;AAAA,gBAAA;AAAA,cAC9C;AAAA,YACF,CACD;AAAA,UAAA;AAAA,QACH;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EApMF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EAsMF,SACLL,GACA9P,GACA;AACA,WAAK,KAAK,kBAAkB,SAAS8P,CAAgB,KACnD,KAAK,oBAAoBA,CAAgB,GAGpC,KAAK,GAAG,UAAUA,CAAgB,IAAI9P,CAAQ;AAAA,EAAA;AAAA,EAkBvD,IAAW,QAAQ;;AACV,aAAA31B,KAAAD,IAAA,KAAK,SAAL,gBAAAA,EAAW,UAAX,gBAAAC,EAAkB,SAAQ;AAAA,EAAA;AAErC;AAEgB,SAAAgmC,GAId5hC,GAAwCqhC,GAA0B;AAC3D,EAAArhC,EAAA,gBAAgB,oBAAoBqhC,CAAgB;AAC7D;AC7Ya,MAAAQ,KAAoBx3B,GAAK,OAAO;AAAA,EAC3C,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AAAA,EACV,gBAAgB;AACP,WAAA;AAAA,MACL,IAAI,EAAE,SAAS,MAAM,UAAU,SAAS;AAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EACA,iBAAiB8W,GAAW;AACtB,WAAAA,EAAU,SAAS,cACd,CAAC,IAEH;AAAA,MACL,iBAAiB;AAAA,MACjB,WAAW;AAAA,MAEX,MAAM7Z,GAAMw6B,GAAQ;AACX,eAAA;AAAA,UACL;AAAA,UACA;AAAA,YACE,WAAW,OAAOx6B,EAAK,MAAM,EAAK;AAAA,YAClC,eAAe,OAAOw6B,CAAM;AAAA,YAC5B,GAAI,CAACA,KAAU,EAAE,OAAO,oBAAoB;AAAA;AAAA,UAC9C;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR;AAAA,UACE,KAAK;AAAA,UACL,SAASvlC,GAAM;AACb,mBAAKA,EAAK,QAAQ,KAGX;AAAA,cACL,IAAI,SAASA,EAAK,QAAQ,IAAO,EAAE;AAAA,YACrC,IAJS;AAAA,UAIT;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC,GAEYwlC,KAAuB13B,GAAK,OAAO;AAAA,EAC9C,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AAAA,EACV,gBAAgB;AACP,WAAA;AAAA,MACL,IAAI,EAAE,SAAS,MAAM,UAAU,SAAS;AAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EACA,iBAAiB8W,GAAW;AACtB,WAAAA,EAAU,SAAS,aACd,CAAC,IAEH;AAAA,MACL,iBAAiB;AAAA,MACjB,WAAW;AAAA;AAAA;AAAA;AAAA,MAKX,MAAM7Z,GAAMw6B,GAAQ;AACX,eAAA;AAAA,UACL;AAAA,UACA;AAAA,YACE,WAAW,OAAOx6B,EAAK,MAAM,EAAK;AAAA,YAClC,eAAe,OAAOw6B,CAAM;AAAA,YAC5B,GAAI,CAACA,KAAU,EAAE,OAAO,oBAAoB;AAAA;AAAA,UAC9C;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR;AAAA,UACE,KAAK;AAAA,UACL,SAASvlC,GAAM;AACb,mBAAKA,EAAK,QAAQ,KAGX;AAAA,cACL,IAAI,SAASA,EAAK,QAAQ,IAAO,EAAE;AAAA,YACrC,IAJS;AAAA,UAIT;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC,GAEYylC,KAA6B33B,GAAK,OAAO;AAAA,EACpD,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AAAA,EACV,gBAAgB;AAEP,WAAA;AAAA,MACL,IAAI,EAAE,SAAS,MAAM,UAAU,SAAS;AAAA,MACxC,MAAM,EAAE,UAAU,SAAS;AAAA,MAC3B,UAAU,EAAE,SAAS,MAAM,UAAU,cAAc;AAAA,MACnD,eAAe,EAAE,SAAS,KAAK;AAAA,MAC/B,UAAU,EAAE,SAAS,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,iBAAiB8W,GAAW;AACtB,WAAAA,EAAU,SAAS,iBACd,CAAC,IAEH;AAAA,MACL,iBAAiB;AAAA,MACjB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQX,MAAM7Z,GAAMw6B,GAAQ;AACX,eAAA;AAAA,UACLA,IAAS,SAAS;AAAA,UAClB;AAAA,YACE,aAAa;AAAA,YACb,WAAW,OAAOx6B,EAAK,MAAM,EAAK;AAAA,YAClC,iBAAiBA,EAAK,MAAM;AAAA,YAC5B,qBAAqB,KAAK,UAAUA,EAAK,MAAM,aAAgB;AAAA;AAAA,YAE/D,oBAAoB,KAAK,UAAUA,EAAK,MAAM,QAAW;AAAA,UAC3D;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR;AAAA,UACE,KAAK;AAAA,UACL,SAAS/K,GAAM;AACb,mBAAKA,EAAK,QAAQ,KAGX;AAAA,cACL,IAAI,SAASA,EAAK,QAAQ,IAAO,EAAE;AAAA,cACnC,MAAMA,EAAK,QAAQ;AAAA,cACnB,eAAeA,EAAK,QAAQ;AAAA,cAC5B,UAAUA,EAAK,QAAQ;AAAA,YACzB,IAPS;AAAA,UAOT;AAAA,QAEJ;AAAA,QACA;AAAA,UACE,KAAK;AAAA,UACL,SAASA,GAAM;AACb,mBAAKA,EAAK,QAAQ,KAGX;AAAA,cACL,IAAI,SAASA,EAAK,QAAQ,IAAO,EAAE;AAAA,cACnC,MAAMA,EAAK,QAAQ;AAAA,cACnB,eAAeA,EAAK,QAAQ;AAAA,YAC9B,IANS;AAAA,UAMT;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC;ACnID,IAAI6gC;AA4BJ,SAAS6E,GAAmB1D,GAA+B;AACzD,EAAInB,MAIeA,IAAA,SAAS,cAAc,KAAK,GAC/CA,EAAiB,YAAY,KAC7BA,EAAiB,MAAM,UAAU,KACjCA,EAAiB,MAAM,SAAS,OAChCA,EAAiB,MAAM,QAAQ,OAC3BmB,aAAkB,WACbA,EAAA,KAAK,YAAYnB,CAAgB,IAExCmB,EAAO,YAAYnB,CAAgB;AAEvC;AAEA,SAAS8E,GAAqB3D,GAA+B;AAC3D,EAAInB,MACEmB,aAAkB,WACbA,EAAA,KAAK,YAAYnB,CAAgB,IAExCmB,EAAO,YAAYnB,CAAgB,GAElBA,IAAA;AAEvB;AAEA,SAAShR,GAAc7vB,GAAe;AACpC,SAAO,MAAM,UAAU,QAAQ,KAAKA,EAAK,cAAe,YAAYA,CAAI;AAC1E;AAIA,SAAS4lC,GAAcC,GAAiB;AACtC,MAAIC,IAAqCD;AACzC,SACEC,KACAA,EAAc,aAAa,QAC3BA,EAAc,aAAa,QAC3B,CAACA,EAAc,UAAU,SAAS,cAAc,KAChD;AACA,QAAIA,EAAc,UAAU,SAAS,aAAa;AACzC;AAET,UAAM5sB,IAA4B4sB,EAAc;AAEhD,QAAI,CAAC5sB,KAAU,EAAEA,aAAkB;AAC1B;AAEO,IAAA4sB,IAAA5sB;AAAA,EAAA;AAGlB,SAAO4sB,EAAc,aAAa,QAAQA,EAAc,aAAa,OACjE;AAAA,IACE,MAAM;AAAA,IACN,SAASA;AAAA,IACT,WAAWA,EAAc,QAAQ,OAAO;AAAA,EAAA,IAE1C;AAAA,IACE,MAAM;AAAA,IACN,SAASA;AAAA,IACT,WAAWA,EAAc,cAAc,OAAO;AAAA,EAChD;AACN;AAGA,SAASC,GAAaC,GAAkBhE,GAA+B;AAC/D,QAAAiE,IAAiBjE,EAAO,iBAAiBgE,CAAQ;AAEvD,WAAShiC,IAAI,GAAGA,IAAIiiC,EAAe,QAAQjiC;AACxC,IAAAiiC,EAAejiC,CAAC,EAAkB,MAAM,aAAa;AAE1D;AAEO,MAAMkiC,GAIb;AAAA,EAcE,YACmBziC,GAKAi1B,GACjBC,GACA;AArBK,IAAAzP,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA,oBAAa;AAEb,IAAAA,EAAA,oBAA0C;AAE1C,IAAAA,EAAA,yBAAkC;AAiCzC,IAAAA,EAAA,8BAAuB,MAAM;AAC3B,WAAK,aAAa;AAAA,IACpB;AAEA,IAAAA,EAAA,wBAAiB,CAACxoB,MAAsB;AACtC,WAAK,aAAa,MAClB,KAAK,iBAAiBA,CAAK;AAAA,IAC7B;AAEA,IAAAwoB,EAAA,0BAAmB,CAACxoB,MAAsB;;AAUtC,UATE,KAAK,cAIL,KAAK,eAAe,eAKtB,EAAEA,EAAM,kBAAkB,YAC1B,CAAC,KAAK,OAAO,IAAI,SAASA,EAAM,MAAM;AAEtC;AAGI,YAAAmlC,IAASD,GAAcllC,EAAM,MAAM;AAGvC,WAAAmlC,KAAA,gBAAAA,EAAQ,UAAS,UACjB,KAAK,eAAe,UACpB,GAACzmC,IAAA,KAAK,UAAL,QAAAA,EAAY,gBACb;AAEA,aAAK,aAAa,cAEdC,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,MAAM,4BAA4B,IACvC,KAAK,MAAM,+BAA+B,IAC1C,KAAK,WAAW;AAElB;AAAA,MAAA;AAGF,UAAI,CAACwmC,KAAU,CAAC,KAAK,OAAO,YAAY;AAClC,SAAApkC,IAAA,KAAK,UAAL,QAAAA,EAAY,SACd,KAAK,MAAM,OAAO,IAClB,KAAK,MAAM,4BAA4B,IACvC,KAAK,MAAM,+BAA+B,IAC1C,KAAK,WAAW;AAElB;AAAA,MAAA;AAGE,UAAA,CAACokC,EAAO;AACV;AAGI,YAAAM,IAAYN,EAAO,UAAU,sBAAsB,GAEnDO,IAAU/F,GAA6BwF,EAAO,SAAS,KAAK,MAAM;AACxE,UAAI,CAACO;AACH;AAEF,WAAK,eAAeA,EAAQ;AAExB,UAAAC;AAIE,YAAAC,IAAa,KAAK,OAAO;AAAA,QAAS,CAACnnC,MACvC2U,EAAYsyB,EAAQ,IAAIjnC,EAAG,GAAG;AAAA,MAChC;AACA,UAAI,CAACmnC;AACH,cAAM,IAAI,MAAM,iBAAiBF,EAAQ,EAAE,YAAY;AAGzD,YAAM5iC,IAAQyH;AAAA,QACZq7B,EAAW;AAAA,QACX,KAAK,OAAO;AAAA,QACZ,KAAK,OAAO,OAAO;AAAA,QACnB,KAAK,OAAO,OAAO;AAAA,QACnB,KAAK,OAAO,OAAO;AAAA,MACrB;AAOA,UALI5e,GAAwB,SAASlkB,GAAO,KAAK,MAAM,MAChD,KAAA,WAAW8iC,EAAW,gBAAgB,GAC9BD,IAAA7iC,IAGX,CAAC6iC;AACH;AAGF,WAAK,UAAUD,EAAQ;AACvB,YAAMG,KAAkB7kC,IAAAmkC,EAAO,QAC5B,QAAQ,eAAe,MADF,gBAAAnkC,EAEpB,cAAc;AAEd,WAAAmkC,KAAA,gBAAAA,EAAQ,UAAS,WAAW;AAG9B,cAAMW,IACJ9lC,EAAM,WAAWylC,EAAU,SAAS;AAAA,QACpCzlC,EAAM,UAAUylC,EAAU,SAAS,IAC/BM,IACJ/lC,EAAM,WAAWylC,EAAU,QAAQ,KACnCzlC,EAAM,UAAUylC,EAAU,QAAQ,IAG9BO,IACJhmC,EAAM,UAAUylC,EAAU,SAASzlC,EAAM,UAAUylC,EAAU;AAE/D,aAAK,QAAQ;AAAA,UACX,GAAG,KAAK;AAAA,UACR,MAAM;AAAA,UACN,2BAA2BK;AAAA,UAC3B,8BAA8BC;AAAA,UAC9B,mBAAmBN;AAAA,UACnB,OAAOE;AAAA,UACP,iBAAAE;AAAA,UACA,UAAUG,MAA0B/kC,IAAA,KAAK,UAAL,OAAZ,SAAYA,EAAY;AAAA,UAChD,UAAU+kC,MAA0BhuB,IAAA,KAAK,UAAL,OAAZ,SAAYA,EAAY;AAAA,UAChD,kBAAkBguB,MAEd/tB,IAAA,KAAK,UAAL,OADA,SACAA,EAAY;AAAA,QAClB;AAAA,MAAA,OACK;AACC,cAAApH,IAAWse,GAAcgW,EAAO,OAAO,GACvC97B,IAAW8lB,GAAcgW,EAAO,QAAQ,aAAc,GACtDc,IAAWd,EAAO,QAAQ,sBAAsB;AAEtD,YACE,KAAK,UAAU,UACf,KAAK,MAAM,QACX,KAAK,YAAYO,EAAQ,MACzB,KAAK,MAAM,aAAar8B,KACxB,KAAK,MAAM,aAAawH;AAGxB;AAGF,aAAK,QAAQ;AAAA,UACX,MAAM;AAAA,UACN,8BACEA,MAAa80B,EAAW,QAAQ,KAAK,CAAC,EAAE,MAAM,SAAS;AAAA,UACzD,2BACEt8B,MAAas8B,EAAW,QAAQ,KAAK,SAAS;AAAA,UAChD,mBAAmBF;AAAA,UAEnB,OAAOE;AAAA,UACP,eAAe;AAAA,UACf,kBAAkBM;AAAA,UAClB,UAAAp1B;AAAA,UACA,UAAAxH;AAAA,UAEA,iBAAAw8B;AAAA,QACF;AAAA,MAAA;AAEF,kBAAK,WAAW,GAET;AAAA,IACT;AAEA,IAAArd,EAAA,yBAAkB,CAACxoB,MAAqB;;AAClC,YAAAtB,IAAA,KAAK,UAAL,gBAAAA,EAAY,mBAAkB;AAChC;AAGF,MAAAsB,EAAM,eAAe,GACrBA,EAAM,aAAc,aAAa,QAEjCqlC;AAAA,QACE;AAAA,QACA,KAAK,OAAO;AAAA,MACd;AAKA,YAAMa,IAAqB;AAAA,QACzB,MAAM,KAAK;AAAA,UACT,KAAK,IAAIlmC,EAAM,SAAS,KAAK,MAAM,kBAAkB,OAAO,CAAC;AAAA,UAC7D,KAAK,MAAM,kBAAkB,QAAQ;AAAA,QACvC;AAAA,QACA,KAAK,KAAK;AAAA,UACR,KAAK,IAAIA,EAAM,SAAS,KAAK,MAAM,kBAAkB,MAAM,CAAC;AAAA,UAC5D,KAAK,MAAM,kBAAkB,SAAS;AAAA,QAAA;AAAA,MAE1C,GAIMmmC,IAAoB,KAAK,OAAO,KACnC,kBAAkBD,EAAmB,MAAMA,EAAmB,GAAG,EACjE;AAAA,QACC,CAACtoC,MAAYA,EAAQ,YAAY,QAAQA,EAAQ,YAAY;AAAA,MAC/D;AACE,UAAAuoC,EAAkB,WAAW;AAC/B;AAEI,YAAAC,IAAmBD,EAAkB,CAAC;AAE5C,UAAIE,IAAkB;AAGhB,YAAAh9B,IAAW8lB,GAAciX,EAAiB,aAAc,GACxDv1B,IAAWse,GAAciX,CAAgB,GAIzCE,IACJ,KAAK,MAAM,cAAc,2BAA2B,QAChD,KAAK,MAAM,WACX,KAAK,MAAM,UAKXC,KAHJ,KAAK,MAAM,cAAc,2BAA2B,QAChDl9B,IACAwH,OAC8Cy1B;AAIpD,OAAI,KAAK,MAAM,aAAaj9B,KAAY,KAAK,MAAM,aAAawH,OAC9D,KAAK,MAAM,WAAWxH,GACtB,KAAK,MAAM,WAAWwH,GAEjB,KAAA,MAAM,mBAAmBu1B,EAAiB,sBAAsB,GAEnDC,IAAA;AAKd,YAAApE,IACJ,KAAK,MAAM,cAAc,2BAA2B,QAChDiE,EAAmB,MACnBA,EAAmB;AACzB,MAAI,KAAK,MAAM,cAAc,aAAajE,MACnC,KAAA,MAAM,cAAc,WAAWA,GAElBoE,IAAA,KAIhBA,KACF,KAAK,WAAW,GAKdE,KACG,KAAA,OAAO,SAAS,CAAC9nC,MAAOA,EAAG,QAAQ+nC,IAAuB,EAAI,CAAC;AAAA,IAExE;AAEA,IAAAhe,EAAA,qBAAc,CAACxoB,MAAqB;AAElC,UADA,KAAK,aAAa,MACd,KAAK,UAAU,UAAa,KAAK,MAAM,kBAAkB;AACpD,eAAA;AAGT,UACE,KAAK,MAAM,aAAa,UACxB,KAAK,MAAM,aAAa;AAExB,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAGF,MAAAA,EAAM,eAAe;AAErB,YAAM,EAAE,eAAAymC,GAAe,UAAA51B,GAAU,UAAAxH,MAAa,KAAK,OAE7CuJ,IAAe,KAAK,MAAM,MAAM,QAAQ;AAE1C,UAAA6zB,EAAc,2BAA2B,OAAO;AAClD,YACE,CAAC31B;AAAA,UACC,KAAK,MAAM;AAAA,UACX21B,EAAc;AAAA,UACdp9B;AAAA,QAAA;AAIK,iBAAA;AAET,cAAMq9B,IAAWh3B;AAAA,UACf,KAAK,MAAM;AAAA,UACX+2B,EAAc;AAAA,UACdp9B;AAAA,QACF;AACA,aAAK,OAAO,YAAY,KAAK,MAAM,OAAO;AAAA,UACxC,MAAM;AAAA,UACN,SAAS;AAAA,YACP,GAAG,KAAK,MAAM,MAAM;AAAA,YACpB,MAAMq9B;AAAA,UAAA;AAAA,QACR,CACD;AAAA,MAAA,OACI;AACL,YACE,CAACt1B;AAAA,UACC,KAAK,MAAM;AAAA,UACXq1B,EAAc;AAAA,UACd51B;AAAA,QAAA;AAIK,iBAAA;AAET,cAAM61B,IAAWt3B;AAAA,UACf,KAAK,MAAM;AAAA,UACXq3B,EAAc;AAAA,UACd51B;AAAA,QACF,GACM,CAAC81B,CAAW,IAAI/zB,EAAa,OAAO6zB,EAAc,eAAe,CAAC;AAC3D,QAAA7zB,EAAA,OAAO/B,GAAU,GAAG81B,CAAW,GAC5C,KAAK,OAAO,YAAY,KAAK,MAAM,OAAO;AAAA,UACxC,MAAM;AAAA,UACN,SAAS;AAAA,YACP,GAAG,KAAK,MAAM,MAAM;AAAA,YACpB,cAAA/zB;AAAA,YACA,MAAM8zB;AAAA,UAAA;AAAA,QACR,CACD;AAAA,MAAA;AAKH,kBAAK,OAAO,sBAAsB,KAAK,MAAM,MAAM,EAAE,GAE9C;AAAA,IACT;AA5WmB,SAAA,SAAA3jC,GAKA,KAAA,SAAAi1B,GAGjB,KAAK,aAAa,MAAM;AAClB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,kDAAkD;AAGpE,MAAAC,EAAW,KAAK,KAAK;AAAA,IACvB,GAEAD,EAAO,IAAI,iBAAiB,aAAa,KAAK,gBAAgB,GAC9DA,EAAO,IAAI,iBAAiB,aAAa,KAAK,oBAAoB,GAC3D,OAAA,iBAAiB,WAAW,KAAK,cAAc,GAEtDA,EAAO,KAAK;AAAA,MACV;AAAA,MACA,KAAK;AAAA,IACP,GACAA,EAAO,KAAK;AAAA,MACV;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EAAA;AAAA;AAAA,EAmVF,SAAS;;AACP,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,MAAM;AAC7B;AAKF,QADK,KAAA,MAAM,QAAQ,KAAK,OAAO,SAAS,KAAK,MAAM,MAAM,EAAE,GAEzD,CAAC,KAAK,MAAM,SACZ,KAAK,MAAM,MAAM,SAAS;AAAA;AAAA,IAG1B,GAACt5B,IAAA,KAAK,iBAAL,QAAAA,EAAmB,cACpB;AACA,WAAK,MAAM,OAAO,IAClB,KAAK,MAAM,4BAA4B,IACvC,KAAK,MAAM,+BAA+B,IAC1C,KAAK,WAAW;AAEhB;AAAA,IAAA;AAGF,UAAM,EAAE,QAAQkoC,GAAU,OAAOC,EAAa,IAAAp5B;AAAA,MAC5C,KAAK,MAAM;AAAA,IACb;AAEA,IACE,KAAK,MAAM,aAAa,UACxB,KAAK,MAAM,aAAa,WAKpB,KAAK,MAAM,YAAYm5B,MACpB,KAAA,MAAM,WAAWA,IAAW,IAE/B,KAAK,MAAM,YAAYC,MACpB,KAAA,MAAM,WAAWA,IAAW;AAKrC,UAAMC,IAAY,KAAK,aAAc,cAAc,OAAO;AAE1D,QAAI,CAACA;AACH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QACE,KAAK,MAAM,aAAa,UACxB,KAAK,MAAM,aAAa,QACxB;AAEA,YAAM3lC,IADM2lC,EAAU,SAAS,KAAK,MAAM,QAAQ,EACjC,SAAS,KAAK,MAAM,QAAQ;AAC7C,MAAI3lC,IACG,KAAA,MAAM,mBAAmBA,EAAK,sBAAsB,KAEzD,KAAK,MAAM,WAAW,QACtB,KAAK,MAAM,WAAW;AAAA,IACxB;AAEG,SAAA,MAAM,oBAAoB2lC,EAAU,sBAAsB,GAE/D,KAAK,WAAW;AAAA,EAAA;AAAA,EAGlB,UAAU;AACR,SAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,gBAAgB,GAC/D,OAAA,oBAAoB,WAAW,KAAK,cAAc,GACzD,KAAK,OAAO,IAAI,oBAAoB,aAAa,KAAK,oBAAoB,GAC1E,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP,GACA,KAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EAAA;AAEJ;AAEa,MAAAN,KAAwB,IAAItoC,EAAU,oBAAoB;AAEhE,MAAM6oC,WAGHxS,EAAmB;AAAA,EAO3B,YACmBxxB,GAKjB;AACM,UAAA;AATA,IAAAylB,EAAA;AAiLR;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,sBAAe,CAACxoB,MAGV;AAEF,UAAA,KAAK,KAAM,UAAU,UACrB,KAAK,KAAM,MAAM,aAAa;AAE9B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAoBE,UAjBC,KAAA,KAAM,MAAM,gBAAgB;AAAA,QAC/B,wBAAwB;AAAA,QACxB,eAAe,KAAK,KAAM,MAAM;AAAA,QAChC,UAAUA,EAAM;AAAA,MAClB,GACA,KAAK,KAAM,WAAW,GAEtB,KAAK,OAAO;AAAA,QAAS,CAACvB,MACpBA,EAAG,QAAQ+nC,IAAuB;AAAA,UAChC,wBACE,KAAK,KAAM,MAAO,cAAe;AAAA,UACnC,eAAe,KAAK,KAAM,MAAO;AAAA,UACjC,UAAU,KAAK,KAAM,MAAO;AAAA,UAC5B,UAAU,KAAK,KAAM;AAAA,QACtB,CAAA;AAAA,MACH,GAEI,CAAC,KAAK,OAAO;AACT,cAAA,IAAI,MAAM,8BAA8B;AAG7B,MAAAxB,GAAA,KAAK,OAAO,gBAAgB,IAAI,GACnDhlC,EAAM,aAAc,aAAamgC,GAAmB,GAAG,CAAC,GACxDngC,EAAM,aAAc,gBAAgB;AAAA,IACtC;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAwoB,EAAA,sBAAe,CAACxoB,MAGV;AAEF,UAAA,KAAK,KAAM,UAAU,UACrB,KAAK,KAAM,MAAM,aAAa;AAE9B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAoBE,UAjBC,KAAA,KAAM,MAAM,gBAAgB;AAAA,QAC/B,wBAAwB;AAAA,QACxB,eAAe,KAAK,KAAM,MAAM;AAAA,QAChC,UAAUA,EAAM;AAAA,MAClB,GACA,KAAK,KAAM,WAAW,GAEtB,KAAK,OAAO;AAAA,QAAS,CAACvB,MACpBA,EAAG,QAAQ+nC,IAAuB;AAAA,UAChC,wBACE,KAAK,KAAM,MAAO,cAAe;AAAA,UACnC,eAAe,KAAK,KAAM,MAAO;AAAA,UACjC,UAAU,KAAK,KAAM,MAAO;AAAA,UAC5B,UAAU,KAAK,KAAM;AAAA,QACtB,CAAA;AAAA,MACH,GAEI,CAAC,KAAK,OAAO;AACT,cAAA,IAAI,MAAM,8BAA8B;AAG7B,MAAAxB,GAAA,KAAK,OAAO,gBAAgB,IAAI,GACnDhlC,EAAM,aAAc,aAAamgC,GAAmB,GAAG,CAAC,GACxDngC,EAAM,aAAc,gBAAgB;AAAA,IACtC;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAwoB,EAAA,iBAAU,MAAM;AACV,UAAA,KAAK,KAAM,UAAU;AACvB,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAQE,UALC,KAAA,KAAM,MAAM,gBAAgB,QACjC,KAAK,KAAM,WAAW,GAEjB,KAAA,OAAO,SAAS,CAAC/pB,MAAOA,EAAG,QAAQ+nC,IAAuB,IAAI,CAAC,GAEhE,CAAC,KAAK,OAAO;AACT,cAAA,IAAI,MAAM,8BAA8B;AAG3B,MAAAvB,GAAA,KAAK,OAAO,gBAAgB,IAAI;AAAA,IACvD;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAzc,EAAA,uBAAgB,MAAM;AACpB,WAAK,KAAM,aAAa;AAAA,IAC1B;AAMA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,yBAAkB,MAAM;AACtB,WAAK,KAAM,aAAa;AAAA,IAC1B;AAEA,IAAAA,EAAA,6BAAsB,CACpB1lB,GACA8L,MAEOD,GAAoB7L,GAAO8L,CAAgB;AAMpD;AAAA;AAAA;AAAA,IAAA4Z,EAAA,gCAAyB,CACvB1lB,GACAoM,MAEOD,GAAuBnM,GAAOoM,CAAmB;AAOlD;AAAA;AAAA;AAAA;AAAA,IAAAsZ,EAAA,0BAAmB,CACzBtgB,GACA8+B,GACAC,IAAuCD,MACpC;AACH,YAAMlnC,IAAO,KAAK;AAElB,UAAI,CAACA;AACG,cAAA,IAAI,MAAM,oCAAoC;AAGtD,YAAMonC,IAAmBh/B,EAAM,IAAI,QAAQpI,EAAK,WAAY,CAAC,GACvDqnC,IAAsBj/B,EAAM,IAAI;AAAA,QACpCg/B,EAAiB,WAAWF,EAAkB,GAAG,IAAI;AAAA,MACvD,GACMI,IAAuBl/B,EAAM,IAAI;AAAA;AAAA,QAErCi/B,EAAoB,WAAWH,EAAkB,GAAG;AAAA,MACtD,GACMK,IAAoBn/B,EAAM,IAAI;AAAA,QAClCg/B,EAAiB,WAAWD,EAAgB,GAAG,IAAI;AAAA,MACrD,GACMK,IAAqBp/B,EAAM,IAAI;AAAA;AAAA,QAEnCm/B,EAAkB,WAAWJ,EAAgB,GAAG;AAAA,MAClD,GAGMxoC,IAAKyJ,EAAM;AAGd,aAAAzJ,EAAA;AAAA,QACD,IAAI8oB,GAAc6f,GAAsBE,CAAkB;AAAA,MAC5D,GAGOp/B,EAAM,MAAMzJ,CAAE;AAAA,IACvB;AAKA;AAAA;AAAA;AAAA,IAAA+pB,EAAA,wBAAiB,CACfjrB,GACAgqC,MAGG;AACH,WAAK,OAAO,KAAK,CAACC,GAAa/xB,MAAa;AAC1C,cAAMvN,IAAQ,KAAK;AAAA,UACjBs/B;AAAA,UACAD,EAAU,gBAAgB,QACtB,EAAE,KAAKhqC,GAAO,KAAK,EACnB,IAAA,EAAE,KAAK,GAAG,KAAKA,EAAM;AAAA,QAC3B;AAEI,eAAAgqC,EAAU,gBAAgB,QACxBA,EAAU,SAAS,UACdE,GAAav/B,GAAOuN,CAAQ,IAE5BiyB,GAAYx/B,GAAOuN,CAAQ,IAGhC8xB,EAAU,SAAS,SACdI,GAAgBz/B,GAAOuN,CAAQ,IAE/BmyB,GAAe1/B,GAAOuN,CAAQ;AAAA,MAEzC,CACD;AAAA,IACH;AAKA;AAAA;AAAA;AAAA,IAAA+S,EAAA,2BAAoB,CAClBjrB,GACAgqC,MAEIA,MAAc,QACT,KAAK,OAAO,KAAK,CAACC,GAAa/xB,MAAa;AAC3C,YAAAvN,IAAQ,KAAK,iBAAiBs/B,GAAa;AAAA,QAC/C,KAAKjqC;AAAA,QACL,KAAK;AAAA,MAAA,CACN;AACM,aAAAsqC,GAAU3/B,GAAOuN,CAAQ;AAAA,IAAA,CACjC,IAEM,KAAK,OAAO,KAAK,CAAC+xB,GAAa/xB,MAAa;AAC3C,YAAAvN,IAAQ,KAAK,iBAAiBs/B,GAAa;AAAA,QAC/C,KAAK;AAAA,QACL,KAAKjqC;AAAA,MAAA,CACN;AACM,aAAAuqC,GAAa5/B,GAAOuN,CAAQ;AAAA,IAAA,CACpC;AAOL;AAAA;AAAA;AAAA,IAAA+S,EAAA,oBAAa,CAACuf,MAIL,KAAK,OAAO,KAAK,CAACP,GAAa/xB,MAAa;AAC3C,YAAAvN,IAAQ6/B,IACV,KAAK;AAAA,QACHP;AAAA,QACAO,EAAa;AAAA,QACbA,EAAa;AAAA,MAAA,IAEfP;AAEG,aAAAQ,GAAW9/B,GAAOuN,CAAQ;AAAA,IAAA,CAClC;AAOH;AAAA;AAAA;AAAA;AAAA,IAAA+S,EAAA,mBAAY,CAACyf,MACJ,KAAK,OAAO,KAAK,CAACT,GAAa/xB,MAAa;AACjD,YAAMvN,IAAQ+/B,IACV,KAAK,iBAAiBT,GAAaS,CAAmB,IACtDT;AAEG,aAAAU,GAAUhgC,GAAOuN,CAAQ;AAAA,IAAA,CACjC;AAOH;AAAA;AAAA;AAAA;AAAA,IAAA+S,EAAA,0BAAmB,MAYV,KAAK,OAAO,SAAS,CAAC/pB,MAAO;AAClC,YAAM8e,IAAY9e,EAAG;AAErB,UAAI0pC,IAAY5qB,EAAU,OACtB6qB,IAAU7qB,EAAU;AACpB,UAAA+J,GAAqB/J,CAAS,GAAG;AAG7B,cAAA,EAAE,QAAA8b,MAAW9b;AACZ,QAAA8b,EAAA,QAAQ,CAACnlB,MAAU;AACxB,UAAAi0B,IAAYj0B,EAAM,MAAM,IAAIi0B,KAAaj0B,EAAM,KAAK,GACpDk0B,IAAUl0B,EAAM,IAAI,IAAIk0B,KAAWl0B,EAAM,GAAG;AAAA,QAAA,CAC7C;AAAA,MAAA,WAKDi0B,IAAY1pC,EAAG,IAAI;AAAA,QACjB8e,EAAU,MAAM,MAAMA,EAAU,MAAM,eAAe;AAAA,MACvD,GACA6qB,IAAU3pC,EAAG,IAAI;AAAA,QACf8e,EAAU,IAAI,MAAMA,EAAU,IAAI,eAAe;AAAA,MACnD,GAGI4qB,EAAU,QAAQ,KAAKC,EAAQ,QAAQ;AAClC;AAKL,YAAAC,IAAW5pC,EAAG,IAAI;AAAA,QACtB0pC,EAAU,MAAMA,EAAU,eAAe;AAAA,MAC3C,GACMG,IAAS7pC,EAAG,IAAI,QAAQ2pC,EAAQ,MAAMA,EAAQ,eAAe,CAAC,GAG9DG,IAAS9pC,EAAG,IAAI,QAAQ4pC,EAAS,MAAMA,EAAS,eAAe,CAAC,GAGhEh5B,IAAe84B,EAAU,MAAME,EAAS,KAAK,GAC7C14B,IAAe04B,EAAS,MAAME,EAAO,KAAK,GAC1Cj5B,IAAa84B,EAAQ,MAAME,EAAO,KAAK,GACvC14B,IAAa04B,EAAO,MAAMC,EAAO,KAAK,GAEtCz5B,IAA+B,CAAC;AACtC,eAASxF,IAAMqG,GAAcrG,KAAOsG,GAAYtG;AAC9C,iBAASsE,IAAMyB,GAAczB,KAAO0B,GAAY1B;AAC9C,UAAAkB,EAAM,KAAK,EAAE,KAAAxF,GAAK,KAAAsE,EAAA,CAAK;AAIpB,aAAA;AAAA,QACL,MAAM;AAAA,UACJ,KAAK+B;AAAA,UACL,KAAKN;AAAA,QACP;AAAA,QACA,IAAI;AAAA,UACF,KAAKO;AAAA,UACL,KAAKN;AAAA,QACP;AAAA,QACA,OAAAR;AAAA,MACF;AAAA,IAAA,CACD;AAQH;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA0Z,EAAA,2BAAoB,CAClB1lB,MAIO,KAAK,OAAO,SAAS,CAACrE,MAAO;AAClC,YAAM+pC,IAAwBlhB,GAAqB7oB,EAAG,SAAS,IAC3DA,EAAG,YACH;AAGF,UAAA,CAAC+pC,KACD,CAAC1lC;AAAA,MAED0lC,EAAsB,OAAO,UAAU;AAEhC;AAGH,YAAAC,IAAgB,KAAK,iBAAiB;AAE5C,UAAKA;AAIL,eAAIj3B,GAAgBi3B,EAAc,MAAMA,EAAc,IAAI3lC,CAAK,IACtD,aAGF;AAAA,IAAA,CACR;AAGH,IAAA0lB,EAAA,gCAAyB,CACvB1lB,GACAqN,MAEOD,GAAuBpN,GAAOqN,CAAW;AAGlD,IAAAqY,EAAA,0BAAmB,CACjB1lB,GACA2N,GACAC,MAEOF,GAAiB1N,GAAO2N,GAASC,CAAQ;AApkB/B,SAAA,SAAA3N,GAOZ,KAAA;AAAA,MACH,IAAI9E,EAAO;AAAA,QACT,KAAKuoC;AAAA,QACL,MAAM,CAAC9N,OACL,KAAK,OAAO,IAAI8M,GAAiBziC,GAAQ21B,GAAY,CAACxwB,MAAU;AACzD,eAAA,KAAK,UAAUA,CAAK;AAAA,QAAA,CAC1B,GACM,KAAK;AAAA;AAAA;AAAA,QAId,OAAO;AAAA,UACL,aAAa,CAACA,MAAU;AACtB,gBACE,KAAK,SAAS,UACd,KAAK,KAAK,UAAU,UACpB,KAAK,KAAK,MAAM,kBAAkB,UAClC,KAAK,KAAK,aAAa;AAEvB;AAGF,kBAAMwa,IACJ,KAAK,KAAK,MAAM,cAAc,2BAA2B,QACrD,KAAK,KAAK,MAAM,WAChB,KAAK,KAAK,MAAM;AAEtB,gBAAIA,MAAa;AACf;AAGF,kBAAM0U,IAA4B,CAAC,GAC7B,EAAE,OAAAt0B,GAAO,eAAA2jC,EAAc,IAAI,KAAK,KAAK,OACrC,EAAE,eAAAiC,GAAe,wBAAAC,EAAA,IAA2BlC;AAOlD,gBACE/jB,MAAagmB,KACb,CAAC5lC,KACA6lC,MAA2B,SAC1B,CAAC73B,GAAoBhO,GAAO4lC,GAAehmB,CAAQ,KACpDimB,MAA2B,SAC1B,CAACv3B,GAAuBtO,GAAO4lC,GAAehmB,CAAQ;AAExD,qBAAOwU,EAAc,OAAOhvB,EAAM,KAAKkvB,CAAW;AAIpD,kBAAM8P,IAAmBh/B,EAAM,IAAI,QAAQ,KAAK,KAAK,WAAW,CAAC;AAEjE,mBACE,KAAK,KAAK,MAAM,cAAc,2BAA2B,QAEtCyG;AAAA,cACjB,KAAK,KAAK,MAAM;AAAA,cAChB+T;AAAA,YACF,EAEW,QAAQ,CAAC,EAAE,KAAApZ,GAAK,KAAAsE,QAAU;AAE7B,oBAAAg7B,IAAiB1gC,EAAM,IAAI;AAAA,gBAC/Bg/B,EAAiB,WAAW59B,CAAG,IAAI;AAAA,cACrC,GAGMu/B,IAAkB3gC,EAAM,IAAI;AAAA,gBAChC0gC,EAAe,WAAWh7B,CAAG,IAAI;AAAA,cACnC,GACMrE,IAAWs/B,EAAgB,KAAK,GAIhCC,IACJD,EAAgB,OACfnmB,IAAWgmB,IAAgBn/B,EAAS,WAAW,IAAI;AAC1C,cAAA6tB,EAAA;AAAA;AAAA,gBAEVE,EAAW,OAAOwR,GAAe,MAAM;AAC/B,wBAAAC,IAAS,SAAS,cAAc,KAAK;AAC3C,yBAAAA,EAAO,YAAY,wBACnBA,EAAO,MAAM,OAAO,KACpBA,EAAO,MAAM,QAAQ,KAMjBrmB,IAAWgmB,IACbK,EAAO,MAAM,SAAS,SAEtBA,EAAO,MAAM,MAAM,QAErBA,EAAO,MAAM,SAAS,OAEfA;AAAA,gBACR,CAAA;AAAA,cACH;AAAA,YAAA,CACD,IAEqB95B;AAAA,cACpB,KAAK,KAAK,MAAM;AAAA,cAChByT;AAAA,YACF,EAEc,QAAQ,CAAC,EAAE,KAAApZ,GAAK,KAAAsE,QAAU;AAEhC,oBAAAg7B,IAAiB1gC,EAAM,IAAI;AAAA,gBAC/Bg/B,EAAiB,WAAW59B,CAAG,IAAI;AAAA,cACrC,GAGMu/B,IAAkB3gC,EAAM,IAAI;AAAA,gBAChC0gC,EAAe,WAAWh7B,CAAG,IAAI;AAAA,cACnC,GACMrE,IAAWs/B,EAAgB,KAAK,GAKhCC,IACJD,EAAgB,OACfnmB,IAAWgmB,IAAgBn/B,EAAS,WAAW,IAAI;AAE1C,cAAA6tB,EAAA;AAAA;AAAA,gBAEVE,EAAW,OAAOwR,GAAe,MAAM;AAC/B,wBAAAC,IAAS,SAAS,cAAc,KAAK;AAC3C,yBAAAA,EAAO,YAAY,wBACnBA,EAAO,MAAM,MAAM,KACnBA,EAAO,MAAM,SAAS,KAMlBrmB,IAAWgmB,IACbK,EAAO,MAAM,QAAQ,SAErBA,EAAO,MAAM,OAAO,QAEtBA,EAAO,MAAM,QAAQ,OAEdA;AAAA,gBACR,CAAA;AAAA,cACH;AAAA,YAAA,CACD,GAGI7R,EAAc,OAAOhvB,EAAM,KAAKkvB,CAAW;AAAA,UAAA;AAAA,QACpD;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EA1KF,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA,EA4KF,SAAS9C,GAAoD;AAC3D,WAAA,KAAK,GAAG,UAAUA,CAAQ;AAAA,EAAA;AA+ZrC;ACvrCa,MAAA0U,KAAyBvrC,EAAU,OAAO;AAAA,EACrD,MAAM;AAAA,EAEN,sBAAsB;AACb,WAAA;AAAA,MACL;AAAA;AAAA;AAAA,QAGE,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,YAAY;AAAA,UACV,eAAe;AAAA,YACb,SAAS;AAAA,YACT,WAAW,CAACG,MACHA,EAAQ,aAAa,qBAAqB;AAAA,YAEnD,YAAY,CAACC,MACPA,EAAW,kBAAkB,SACxB,CAAC,IAEH;AAAA,cACL,uBAAuBA,EAAW;AAAA,YACpC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC,GCnCYorC,KAAqBxrC,EAAU,OAAO;AAAA,EACjD,MAAM;AAAA,EAEN,sBAAsB;AACb,WAAA;AAAA,MACL;AAAA,QACE,OAAO,CAAC,kBAAkB,aAAa,aAAa;AAAA,QACpD,YAAY;AAAA,UACV,WAAW;AAAA,YACT,SAAS+F,EAAa,UAAU;AAAA,YAChC,WAAW,CAAC5F,MACVA,EAAQ,aAAa,iBAAiB,IAClCA,EAAQ,aAAa,iBAAiB,IACtC4F,EAAa,UAAU;AAAA,YAC7B,YAAY,CAAC3F,MACPA,EAAW,cAAc2F,EAAa,UAAU,UAC3C,CAAC,IAEH;AAAA,cACL,mBAAmB3F,EAAW;AAAA,YAChC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,EAAA;AAEJ,CAAC,GCZYqrC,KAAezrC,EAAU,OAA4B;AAAA,EAChE,MAAM;AAAA,EAEN,wBAAwB;AACtB,UAAMg3B,IAAS,IAAIv2B,EAAU,KAAK,IAAI;AAK/B,WAAA;AAAA,MACL,IAAID,EAAO;AAAA,QACT,KAAKw2B;AAAA,QACL,mBAAmB,CAAC7jB,GAAGu4B,GAAIjhC,MAAU;AACnC,gBAAM,EAAE,KAAAxB,GAAK,IAAAjI,GAAI,QAAA8J,EAAW,IAAAL,GACtBkhC,IAAwB3U,EAAO,SAASvsB,CAAK,GAC7CmhC,IAAc3iC,EAAI,QAAQ,OAAO,GACjCjC,IAAO8D,EAAO,MAAM,gBACpBof,IAAcpf,EAAO,MAAM;AACjC,cAAK6gC;AAIL,mBAAO3qC,EAAG;AAAA,cACR4qC;AAAA,cACA5kC,EAAK,OAAO,QAAWkjB,EAAY,OAAQ,CAAA;AAAA,YAC7C;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,MAAM,CAAC/W,GAAG04B,MAAW;AAAA,UAGrB;AAAA,UACA,OAAO,CAAC7qC,GAAIkE,MAAU;AAChB,gBAAA,CAAClE,EAAG;AACC,qBAAAkE;AAGL,gBAAA4mC,IAAW9qC,EAAG,IAAI;AAEtB,gBAAI,CAAC8qC,KAAYA,EAAS,KAAK,SAAS;AAChC,oBAAA,IAAI,MAAM,qBAAqB;AAKvC,gBAFAA,IAAWA,EAAS,WAEhB,CAACA,KAAYA,EAAS,KAAK,SAAS;AAC/B,qBAAA;AAGT,kBAAMC,IAAkBD,EAAS;AAEjC,gBAAI,CAACC;AACG,oBAAA,IAAI,MAAM,uBAAuB;AAKzC,mBACED,EAAS,WAAW,KACpBC,EAAgB,KAAK,KAAK,YAAY;AAAA,UAAA;AAAA,QAE1C;AAAA,MAEH,CAAA;AAAA,IACH;AAAA,EAAA;AAEJ,CAAC,GC7EKC,KAA0C;AAAA,EAC9C,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,aAAa;AACf,GAKaC,KAAiBrkC,GAAK,OAGhC;AAAA,EACD,MAAM;AAAA,EACN,OAAO;AAAA;AAAA,EAEP,SAAS;AAAA;AAAA,EAET,UAAU;AAAA,EACV,UAAU;AAAA,EACV,OAAO;AAAA,EACP,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK,wBAAwB,KAAK,OAAO;AAAA,QACzC,UAAU,CAACzH,MAAY;AACjB,cAAA,OAAOA,KAAY;AACd,mBAAA;AAGT,gBAAMoV,IAAgC,CAAC;AACvC,qBAAW,CAACssB,GAAUqK,CAAQ,KAAK,OAAO,QAAQF,EAAe;AAC3D,YAAA7rC,EAAQ,aAAa+rC,CAAQ,MAC/B32B,EAAMssB,CAAQ,IAAI1hC,EAAQ,aAAa+rC,CAAQ;AAI5C,iBAAA32B;AAAA,QAAA;AAAA,MAEX;AAAA;AAAA,MAEA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,IAEV;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAA3M,KAAkB;;AACvB,UAAAujC,IAAa,SAAS,cAAc,KAAK;AAC/C,IAAAA,EAAW,YAAY,kBACZA,EAAA,aAAa,kBAAkB,YAAY;AACtD,eAAW,CAAClnC,GAAWC,CAAK,KAAK,OAAO,QAAQ0D,CAAc;AAC5D,MAAI3D,MAAc,WACLknC,EAAA,aAAalnC,GAAWC,CAAK;AAI5C,UAAMknC,IAAsB;AAAA,MAC1B,KAAInrC,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,UAAS,CAAC;AAAA,MAC1C,GAAG2H;AAAA,IACL,GACMvD,IAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,EAAM,YAAYd,EAAgB,YAAY6nC,EAAoB,KAAK,GACjE/mC,EAAA,aAAa,kBAAkB,KAAK,IAAI;AAC9C,eAAW,CAACJ,GAAWC,CAAK,KAAK,OAAO,QAAQknC,CAAmB;AACjE,MAAInnC,MAAc,WACVI,EAAA,aAAaJ,GAAWC,CAAK;AAIvC,WAAAinC,EAAW,YAAY9mC,CAAK,GAErB;AAAA,MACL,KAAK8mC;AAAA,MACL,YAAY9mC;AAAA,IACd;AAAA,EAAA;AAEJ,CAAC,GCnFYgnC,KAAazkC,GAAK,OAE5B;AAAA,EACD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AACH,WAAA;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,UAAU,CAACzH,MACL,OAAOA,KAAY,WACd,KAGLA,EAAQ,aAAa,gBAAgB,MAAM,eAEtC,OAGF;AAAA,MACT;AAAA,IAEJ;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAAyI,KAAkB;;AAC7B,UAAM0jC,IAA2B;AAAA,MAC/B,KAAIrrC,IAAA,KAAK,QAAQ,kBAAb,gBAAAA,EAA4B,eAAc,CAAC;AAAA,MAC/C,GAAG2H;AAAA,IACL,GACMiB,IAAa,SAAS,cAAc,KAAK;AAC/C,IAAAA,EAAW,YAAYtF;AAAA,MACrB;AAAA,MACA+nC,EAAyB;AAAA,IAC3B,GACWziC,EAAA,aAAa,kBAAkB,YAAY;AACtD,eAAW,CAAC5E,GAAWC,CAAK,KAAK,OAAO,QAAQonC,CAAwB;AACtE,MAAIrnC,MAAc,WACL4E,EAAA,aAAa5E,GAAWC,CAAK;AAIrC,WAAA;AAAA,MACL,KAAK2E;AAAA,MACL,YAAYA;AAAA,IACd;AAAA,EAAA;AAEJ,CAAC,GCnDY0iC,KAAM3kC,GAAK,OAAO;AAAA,EAC7B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AACT,CAAC;ACUM,MAAM4kC,WAAuB1V,EAEjC;AAAA,EAQD,YAAY;AAAA,IACV,QAAAxxB;AAAA,IACA,eAAA4xB;AAAA,EAAA,GAIC;AACD,UAAM5xB,CAAM;AAVN,IAAAylB,EAAA;AACA,IAAAA,EAAA;AA4DA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA;AAlDN,SAAK,SAASzlB,GACd,KAAK,gBAAgB4xB;AAAA,EAAA;AAAA,EAhBvB,OAAc,MAAM;AACX,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAqBD,oBACNuV,GACAC,GACG;AACH,UAAMC,IAAOF,EAAM;AACf,QAAAA,EAAM,UAAU,MAAM;AAKxB,YAAMG,IAAU,MAAM,KAAKD,EAAK,MAAM,KAAM,CAAA,EAAE;AAAA,QAC5C,CAACltC,MAAQktC,EAAK,MAAM,IAAIltC,CAAG,MAAMgtC;AAAA,MACnC;AACA,UAAIG,KAAW;AACP,cAAA,IAAI,MAAM,mCAAmC;AAErD,aAAOF,EAAU,IAAIE,GAASH,EAAM,WAA0B;AAAA,IAAA,OACzD;AAIL,YAAMI,IAAYJ,EAAM,OAClBK,IACJJ,EAAU,MAAM,QAAQ,IAAIG,EAAU,GAAG,MAAM,KAAK,CAAC,GACjDE,IAAYC,GAAE,YAAYF,GAAcD,EAAU,GAAG,KAAK;AAGhE,aAFkBC,EAAaC,CAAS,EACT,QACX;AAAA,IAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOF,IAAW,qBAAqB;AAC9B,WAAO,KAAK,gBAAgB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBvB,OAAO;AACZ,QAAI,KAAK;AACP;AAGI,UAAAE,IAAmB,KAAK,cAAc;AAE5C,QAAI,CAACA;AACG,YAAA,IAAI,MAAM,0BAA0B;AAGtC,UAAAhkC,IAAM,IAAI+jC,GAAE,IAAI;AAEtB,IAAAA,GAAE,YAAY/jC,GAAK+jC,GAAE,oBAAoBC,EAAiB,GAAI,CAAC;AAG/D,UAAMC,IAAiB,KAAK,oBAAoBD,GAAkBhkC,CAAG;AAErE,SAAK,cAAc;AAAA,MACjB,kBAAAgkC;AAAA,MACA,gBAAAC;AAAA,IACF,GAGK,KAAA,OAAO,cAAc,iBAAiB;AAAA,MACzCC;AAAA,MACAC;AAAA,MACAjT;AAAA,IAAA,CACD,GAED,KAAK,OAAO,cAAc;AAAA,MACxB,IAAIrC,GAAWoV,CAAc,EAAE,QAAQ,CAAC;AAAA,IAC1C,GACK,KAAA,OAAO,cAAc,eAAe,IAAIlV,KAAa,QAAQ,CAAC,CAAC,GAE/D,KAAA,KAAK,UAAU,EAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQnB,MAAM,EAAE,aAAAqV,KAAyC;AAClD,QAAA,CAAC,KAAK;AACR;AAGG,SAAA,OAAO,cAAc,iBAAiBlT,EAAc,GACpD,KAAA,OAAO,cAAc,iBAAiBiT,EAAc;AAEzD,UAAM,EAAE,kBAAAH,GAAkB,gBAAAC,EAAe,IAAI,KAAK;AAClD,QAAIG,GAAa;AAEf,YAAMv+B,IAASk+B,GAAE,oBAAoBE,EAAe,GAAI;AACtD,MAAAF,GAAA,YAAYC,EAAiB,KAAMn+B,CAAM;AAAA,IAAA;AAE7C,SAAK,OAAO,WAAW,cAAiB,IAAIgpB,GAAWmV,CAAgB,GACvE,KAAK,OAAO,WAAW,gBAAmB,IAAIpV;AAAA,MAC5C,KAAK;AAAA,IACP,GACA,KAAK,OAAO,WAAW,cAAiB,IAAIG,GAAW,GAEvD,KAAK,OAAO,cAAc;AAAA,MACxB,KAAK,OAAO,WAAW,YAAe,QAAQ,CAAC;AAAA,IACjD,GACA,KAAK,OAAO,cAAc;AAAA,MACxB,KAAK,OAAO,WAAW,cAAiB,QAAQ,CAAC;AAAA,IACnD,GACA,KAAK,OAAO,cAAc;AAAA,MACxB,KAAK,OAAO,WAAW,YAAe,QAAQ,CAAC;AAAA,IACjD,GAEA,KAAK,cAAc,QACd,KAAA,KAAK,UAAU,EAAK;AAAA,EAAA;AAE7B;ACvEa,MAAAsV,KAAyB,CAKpCxiB,MACG;;AACH,QAAMtf,IAA0C,CAAC,GAC3C+hC,IAAmBC,GAAoB1iB,CAAI;AAEjD,aAAW2iB,KAAOF;AACZ,IAAA/hC,EAAAiiC,EAAI,IAAI,IAAIA;AAGlB,EAAI3iB,EAAK,kBACPtf,EAAI,cAAiB,IAAIssB,GAAWhN,EAAK,cAAc,QAAQ,GAC3Dtf,EAAA,cAAiB,IAAIwsB,GAAW,IAEhC/2B,IAAA6pB,EAAK,cAAc,aAAnB,QAAA7pB,EAA6B,cAC/BuK,EAAI,gBAAmB,IAAIqsB,GAAa/M,EAAK,aAAa,IAExDtf,EAAA,iBAAoB,IAAIghC,GAAe;AAAA,IACzC,QAAQ1hB,EAAK;AAAA,IACb,eAAeA,EAAK;AAAA,EAAA,CACrB,IAKCtf,EAAA,oBAAuB,IAAI0wB;AAAA,IAC7BpR,EAAK;AAAA,EACP,GACAtf,EAAI,cAAiB,IAAIk0B,GAA6B5U,EAAK,MAAM,GAC7Dtf,EAAA,WAAc,IAAI65B;AAAA,IACpBva,EAAK;AAAA,IACLA,EAAK;AAAA,EACP,GACAtf,EAAI,kBAAqB,IAAIk7B,GAAgC5b,EAAK,MAAM,GACxEtf,EAAI,YAAe,IAAIwvB,GAA2BlQ,EAAK,MAAa,GACpEtf,EAAI,cAAiB,IAAIs0B,GAAkBhV,EAAK,QAAQA,EAAK,YAAY,IAErEA,EAAK,cAAc,QACjBtf,EAAA,aAAgB,IAAIs1B,GAAwB,IAG9ChW,EAAK,iBACPtf,EAAI,eAAkB,IAAI89B,GAA8Bxe,EAAK,MAAa,IAGxEtf,EAAA,wBAA2B,IAAIq0B,GAA4B,GAE/Dr0B,EAAI,gBAAmB,IAAIu2B,GAAoBjX,EAAK,MAAM,GAEtDA,EAAK,aACHtf,EAAA,WAAc,IAAIwtB;AAAA,IACpBlO,EAAK;AAAA,IACLA,EAAK,SAAS;AAAA,IACdoN,GAAY;AAAA,EACd;AAGI,QAAAwV,IAA8B5iB,EAAK,qBAAqB,CAAC;AAC/D,aAAW2iB,KAAOC;AAChB,WAAOliC,EAAIiiC,CAAG;AAGT,SAAAjiC;AACT;AAEA,IAAImiC,KAAsB;AAK1B,MAAMH,KAAsB,CAK1B1iB,MACG;AACH,QAAMyiB,IAAmC;AAAA,IACvCK,GAAW;AAAA,IACXA,GAAW;AAAA,IACXA,GAAW;AAAA,IACXA,GAAW;AAAA,IACXA,GAAW;AAAA;AAAA,IAGXC;AAAA;AAAA,IAGA7tC,EAAU,OAAO;AAAA,MACf,MAAM;AAAA,MACN,uBAAuB,MAAM;AAAA,QAC3B8qB,EAAK,WAAW;AAAA,UACd,OAAO;AAAA,UACP,OAAO;AAAA,UACP,QAAQA,EAAK;AAAA,QACd,CAAA;AAAA,MAAA;AAAA,IACH,CACD;AAAA,IAED/qB,GAAS,UAAU;AAAA;AAAA,MAEjB,OAAO,CAAC,kBAAkB,cAAc,QAAQ;AAAA,MAChD,gBAAgB+qB,EAAK;AAAA,IAAA,CACtB;AAAA,IACDqR;AAAA;AAAA;AAAA,IAIA2R;AAAA;AAAA,IAGA3G;AAAA,IACAE;AAAA,IACAC;AAAA,IACAyG,GAAK,OAAO;AAAA,MACV,WAAW;AAAA,IACZ,CAAA,EAAE,UAAU;AAAA,MACX,iBAAiBnO;AAAA;AAAA,MAEjB,WAAW+N,KAAsB,KAAKhO;AAAA,IAAA,CACvC;AAAA,IACD,GAAG,OAAO,OAAO7U,EAAK,UAAU,EAAE,IAAI,CAACkjB,MAC9BA,EAAU,eAAe,KAAK,UAAU;AAAA,MAC7C,QAAQljB,EAAK;AAAA,IAAA,CACd,CACF;AAAA,IAED0gB;AAAA,IAEAhV;AAAA,IACA+U;AAAA;AAAA,IAGAvrC,EAAU,OAAO;AAAA,MACf,MAAM;AAAA,MACN,uBAAuB;AACd,eAAA;AAAA,UACL,QAAQ,MACF8qB,EAAK,OAAO,gBAAgB,QAEvB,KAEF,KAAK,OAAO,SAAS,KAAK;AAAA,QAErC;AAAA,MAAA;AAAA,IACF,CACD;AAAA;AAAA,IAGDyhB;AAAA,IACAN,GAAe,UAAU;AAAA,MACvB,QAAQnhB,EAAK;AAAA,MACb,eAAeA,EAAK;AAAA,IAAA,CACrB;AAAA,IACDwS,GAA2B,UAAU;AAAA,MACnC,QAAQxS,EAAK;AAAA,MACb,aAAaA,EAAK;AAAA,IAAA,CACnB;AAAA,IACDuhB,GAAW,UAAU;AAAA,MACnB,eAAevhB,EAAK;AAAA,IAAA,CACrB;AAAA,IACD,GAAG,OAAO,OAAOA,EAAK,kBAAkB,EACrC,OAAO,CAACvZ,MAAMA,EAAE,WAAW,UAAUA,EAAE,WAAW,MAAM,EACxD,IAAI,CAAC08B,MACGA,EAAkB,eAAgB,KAAK,UAAU;AAAA,MACtD,QAAQnjB,EAAK;AAAA,IAAA,CACd,CACF;AAAA,IAEH,GAAG,OAAO,OAAOA,EAAK,UAAU,EAAE,QAAQ,CAAC3d,MAClC;AAAA;AAAA,MAEL,IAAIA,EAAU,eAAe,sBAAsB,CAAI,GAAA;AAAA,QAAI,CAACsgC,MAC1DA,EAAI,UAAU;AAAA,UACZ,QAAQ3iB,EAAK;AAAA,UACb,eAAeA,EAAK;AAAA,QACrB,CAAA;AAAA,MACH;AAAA;AAAA,MAEA3d,EAAU,eAAe,KAAK,UAAU;AAAA,QACtC,QAAQ2d,EAAK;AAAA,QACb,eAAeA,EAAK;AAAA,MACrB,CAAA;AAAA,IACH,CACD;AAAA,IACDyL,GAA+BzL,EAAK,MAAM;AAAA,IAC1C4K;AAAA,MACE5K,EAAK;AAAA,MACLA,EAAK,iBACF,CAACpE,MAKIA,EAAQ,oBAAoB;AAAA,IACtC;AAAA,IACA2N,GAAwBvJ,EAAK,MAAM;AAAA;AAAA;AAAA,IAInC,GAAIA,EAAK,kBAAkB,UAAaA,EAAK,gBACzC,CAAC2gB,EAAY,IACb,CAAC;AAAA,IACL,GAAI3gB,EAAK,WAAW,CAACoN,EAAW,IAAI,CAAA;AAAA,EACtC;AAEsB,SAAAyV,KAAA,IAEjB7iB,EAAK,iBAERyiB,EAAiB,KAAKW,EAAO,GAGxBX;AACT;AC1TA,SAASY,GAAYtsC,GAAgB,GAAW;AAC9C,QAAMuL,IAAkB,CAAC;AACzB,SAAAvL,EAAK,QAAQ,CAACoK,GAAOkH,GAAGtN,MAAM;AAC5B,IAAIA,MAAM,KACRuH,EAAS,KAAKnB,CAAK;AAAA,EACrB,CACD,GACMpJ,EAAS,KAAKuK,CAAQ;AAC/B;AAQgB,SAAAghC,GAAcC,GAAavjC,GAAgB;AACzD,QAAMwjC,IAAkB,CAAC;AACzB,WAASzoC,IAAI,GAAGA,IAAIwoC,EAAE,YAAYxoC;AAChC,QAAIwoC,EAAE,MAAMxoC,CAAC,EAAE,KAAK,SAAS;AAEzB,UAAAyoC,EAAS,SAAS,KAClBA,EAASA,EAAS,SAAS,CAAC,EAAE,KAAK,SAAS,SAC5C;AAEA,cAAMC,IAAYD,EAASA,EAAS,SAAS,CAAC,GACxCrF,IAAWsF,EAAU,KAAKA,EAAU,QAAQ,SAASF,EAAE,MAAMxoC,CAAC,CAAC,CAAC;AAC7D,QAAAyoC,EAAAA,EAAS,SAAS,CAAC,IAAIrF;AAAA,MAAA,OAC3B;AAEC,cAAAA,IAAWn+B,EAAO,MAAM,MAAM;AAAA,UAClC;AAAA,UACAujC,EAAE,MAAMxoC,CAAC;AAAA,QACX;AACA,QAAAyoC,EAAS,KAAKrF,CAAQ;AAAA,MAAA;AAAA;AAGxB,MAAAqF,EAAS,KAAKD,EAAE,MAAMxoC,CAAC,CAAC;AAGxB,SAAAwoC,IAAAxrC,EAAS,KAAKyrC,CAAQ,GACnBD;AACT;AAegB,SAAA9tC,GAAgBiC,GAAcH,GAAkB;AAC9D,MAAIgsC,IAAIxrC,EAAS,KAAKL,EAAM,OAAO;AAGnC,MAFA6rC,IAAID,GAAcC,GAAGhsC,EAAK,MAAM,MAAM,GAElC,CAACmsC,GAAeH,GAAGhsC,CAAI;AAEzB,WAAO,IAAIS,EAAMurC,GAAG7rC,EAAM,WAAWA,EAAM,OAAO;AAGpD,WAASqD,IAAI,GAAGA,IAAIwoC,EAAE,YAAYxoC;AAChC,QAAIwoC,EAAE,MAAMxoC,CAAC,EAAE,KAAK,KAAK,UAAU,gBAAgB;AACjD,YAAM7C,IAAU,CAACqrC,EAAE,MAAMxoC,CAAC,CAAC;AAKzB,UAAAA,IAAI,IAAIwoC,EAAE,cACVA,EAAE,MAAMxoC,IAAI,CAAC,EAAE,KAAK,SAAS,cAC7B;AACM,cAAA4oC,IAAcJ,EACjB,MAAMxoC,IAAI,CAAC,EACX,MAAM,CAAC,EACP,MAAM,CAAC;AAGR,SAAA4oC,EAAY,KAAK,SAAS,oBAC1BA,EAAY,KAAK,SAAS,sBAC1BA,EAAY,KAAK,SAAS,qBAE1BzrC,EAAQ,KAAKqrC,EAAE,MAAMxoC,IAAI,CAAC,CAAC,GACvBwoC,IAAAF,GAAYE,GAAGxoC,IAAI,CAAC;AAAA,MAC1B;AAEF,YAAM6oC,IAAYrsC,EAAK,MAAM,OAAO,MAAM,eAAe;AAAA,QACvD;AAAA,QACAW;AAAA,MACF;AACI,MAAAqrC,IAAAA,EAAE,aAAaxoC,GAAG6oC,CAAS;AAAA,IAAA;AAGnC,SAAO,IAAI5rC,EAAMurC,GAAG7rC,EAAM,WAAWA,EAAM,OAAO;AACpD;AAOA,SAASgsC,GAAe9rC,GAAoBL,GAAkB;;AACtD,QAAAssC,IAAqBjsC,EAAS,eAAe,GAC7CksC,MACJ3tC,IAAAyB,EAAS,eAAT,gBAAAzB,EAAqB,KAAK,KAAK,aAAY,WACvC4tC,MACJ3tC,IAAAwB,EAAS,eAAT,gBAAAxB,EAAqB,KAAK,KAAK,aAAY;AAE7C,MAAIytC,GAAoB;AACtB,QAAIC;AAIK,aAAA;AAGT,QAAIC,GAAqB;AAIjB,YAAA3hC,IAAY1C,EAA0BnI,EAAK,KAAK;AACtD,UAAI6K,EAAU;AASZ,eAAO,EAPLA,EAAU,aAAa,KAAK,KAAK,KAAK,YAAY;AAAA,IAQtD;AAAA,EACF;AAGK,SAAA;AACT;ACvHO,MAAM4hC,KAAN,MAAMA,WAA8BC,GAAa;AAAA,EAyB5C,YACRt1B,GACAlO,GACA;AAYA,UAAM,EAAE,GAAGkO,GAAS,SAAS,QAAW;AAvClC,IAAAsR,EAAA;AA6QD;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,eAAQ,CACbikB,GACA7uC,GACA8uC,MACG;AACH,MAAK9uC,KAGH,KAAK,QAAQ,UAAUA,GAClB,KAAA,sBAAsB6uC,GAAiBC,CAAgB,KAH5D,KAAK,QAAQ;AAAA,IAKjB;AAtOE,UAAMnkC,IAAS,KAAK;AAChB,QAAAokC;AACE,UAAAC,IAAmBrkC,EAAO,MAAM,IAAI;AACzC,IAAAA,EAAO,MAAM,IAAY,gBAAgB,IAAI6rB,MAAc;AAC1D,UAAIuY;AACK,eAAAA;AAET,YAAM1jC,IAAM2jC,EAAiB,MAAMrkC,EAAO,MAAM,KAAK6rB,CAAI,GAGnDx0B,IAAW,KAAK,MAAM,KAAK,UAAUqJ,EAAK,OAAA,CAAQ,CAAC;AACzD,aAAArJ,EAAS,QAAQ,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,kBAElC+sC,IAAAtnC,GAAK,SAASkD,GAAQ3I,CAAQ,GAC/B+sC;AAAA,IACT;AAEI,QAAAjmC;AAEA,QAAA;AACI,YAAAmmC,IAAU31B,KAAA,gBAAAA,EAAS,QAAQ;AAAA,QAAI,CAAC41B,MACpC9pC,GAAY8pC,GAAG,KAAK,QAAQ9jC,CAAW,EAAE,OAAO;AAAA;AAE5C,MAAAtC,IAAAqmC;AAAA,QACJ;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,SAASF;AAAA,YAAA;AAAA,UACX;AAAA,QAEJ;AAAA,QACA,KAAK;AAAA,QACL,KAAK,QAAQ;AAAA,MACf;AAAA,aACO3T,GAAG;AAEF,oBAAA;AAAA,QACN;AAAA,QACAA;AAAA,MACF,GACM,IAAI;AAAA,QACR,sEACE,CAAC,KAAK,UAAUhiB,EAAQ,OAAO;AAAA,MACnC;AAAA,IAAA;AAMG,SAAA,SAAS81B,GAAY,OAAO;AAAA,MAC/B,KAAAtmC;AAAA,MACA,QAAQ,KAAK;AAAA;AAAA,IAAA,CAEd;AAAA,EAAA;AAAA,EAGH,IAAI,QAAQ;AACV,WAAI,KAAK,SACF,KAAA,SAAS,KAAK,KAAK,QAEnB,KAAK;AAAA,EAAA;AAAA,EAGd,SAASnI,GAA0B;AAC7B,QAAA,CAAC,KAAK,MAAM;AAEd,WAAK,SAAS,KAAK,MAAM,MAAMA,CAAW,GAC1C,KAAK,KAAK,eAAe;AAAA,QACvB,QAAQ;AAAA,QACR,aAAAA;AAAA,MAAA,CACD;AACD;AAAA,IAAA;AAQE,QAAA,KAAK,KAAK;AACZ;AAGF,QAAI,KAAK,wBAAwB;AAE9B,WAAa,oBAAoBA,CAAW;AAE7C;AAAA,IAAA;AAGI,UAAA,EAAE,OAAA2J,GAAO,cAAc0L,EAAA,IAC3B,KAAK,MAAM,iBAAiBrV,CAAW,GACnC0uC,IAAsB,CAAC,KAAK,MAAM,UAAU,GAAG/kC,EAAM,SAAS;AAEpE,SAAK,KAAK,qBAAqB;AAAA,MAC7B,QAAQ;AAAA,MACR,aAAA3J;AAAA,MACA,WAAW2J;AAAA,IAAA,CACZ,GACI,KAAA,KAAK,YAAYA,CAAK,GAC3B,KAAK,KAAK,eAAe;AAAA,MACvB,QAAQ;AAAA,MACR,aAAA3J;AAAA,IAAA,CACD,GAEG0uC,KACF,KAAK,KAAK,mBAAmB;AAAA,MAC3B,QAAQ;AAAA,MACR,aAAA1uC;AAAA,IAAA,CACD;AAGG,UAAA2uC,IAAQ3uC,EAAY,QAAQ,OAAO,GACnC4uC,IAAO5uC,EAAY,QAAQ,MAAM;AAkBvC,IAhBI2uC,KACF,KAAK,KAAK,SAAS;AAAA,MACjB,QAAQ;AAAA,MACR,OAAOA,EAAM;AAAA,MACb,aAAA3uC;AAAA,IAAA,CACD,GAGC4uC,KACF,KAAK,KAAK,QAAQ;AAAA,MAChB,QAAQ;AAAA,MACR,OAAOA,EAAK;AAAA,MACZ,aAAA5uC;AAAA,IAAA,CACD,GAGC,GAACA,EAAY,cAAcA,EAAY,QAAQ,eAAe,OAIlE,KAAK,KAAK,UAAU;AAAA,MAClB,QAAQ;AAAA,MACR,aAAAA;AAAA,IAAA,CACD,GACD,KAAK,KAAK,aAAa;AAAA,MACrB,QAAQ;AAAA,MACR,aAAAA;AAAA,MACA,sBAAsBqV,EAAqB,MAAM,CAAC;AAAA,IAAA,CACnD;AAAA,EAAA;AAAA;AAAA;AAAA,EAKH,qBAAqB;AACnB,QAAI,KAAK;AACP,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEG,SAAA,SAAS,KAAK,MAAM,YAAY;AAAA,MACnC,SAAS,KAAK,iBAAiB;AAAA,IAAA,CAChC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMK,sBACN64B,GACAC,GACA;AACC,SAAa,mBAAmBA;AAEjC,UAAMU,IAAiB,CAAC;AACxB,SAAK,iBAAiB,WAAW,QAAQ,CAAClpB,MAAc;AACtD,MAAIA,EAAU,SAAS,UAAUA,EAAU,OAAO,gBAGhDkpB,EAAUlpB,EAAU,IAAI,IACtBA,EAAU,OAAO,YAAYuoB,CAAe;AAAA,IAChD,CACD,GAED,KAAK,OAAO,IAAIY;AAAA,MACd,EAAE,OAAO,KAAK,QAAQ,QAAe;AAAA;AAAA,MACrC;AAAA,QACE,GAAG,KAAK,QAAQ;AAAA;AAAA,QAEhB,qBAAqB,KAAK,SAAS,KAAK,IAAI;AAAA,QAC5C,OAAO,KAAK;AAAA,QACZ,WAAAD;AAAA,QACA,WAAW,KAAK,iBAAiB;AAAA,MAAA;AAAA,IAErC;AAOM,UAAA/uC,IAAW,KAAK,MAAM,YAAY;AAAA,MACtC,SAAS,KAAK,iBAAiB;AAAA,IAAA,CAChC;AAEI,SAAA,KAAK,YAAYA,CAAQ,GAI9B,KAAK,SAAS;AAAA,MACZ,KAAK,QAAQ,aACX,KAAK,QAAQ,QAAQ,aAAa,mBAAmB,MAAM;AAAA,MAC7D,EAAE,gBAAgB,GAAM;AAAA,IAC1B,GACA,KAAK,KAAK,UAAU,EAAE,QAAQ,MAAM,GACpC,KAAK,gBAAgB;AAAA,EAAA;AAoBzB;AAvREmqB,EAHW+jB,IAGG,UAAS,CACrBr1B,GACAlO,MACG;;AAIG,QAAAskC,KAAgB5uC,IAAA,yCAAY,WAAZ,gBAAAA,EAAoB;AAC1C,EAAI,SAAOC,IAAA,yCAAY,WAAZ,gBAAAA,EAAoB,cAAe,QACjC,WAAA,OAAO,aAAc,MACvB;AAGP,MAAA;AACK,WAAA,IAAI4tC,GAAsBr1B,GAASlO,CAAW;AAAA,EAAA,UACrD;AACA,IAAIskC,MACF,WAAW,OAAO,aAAaA;AAAA,EACjC;AAEJ;AAvBK,IAAMC,KAANhB;AA4RNgB,GAAsB,UAAkB,aAAa,WAAY;AAOhE,OAAK,QAAQ,UAAU,KAAK,QAAQ,SAAS;AAC/C;ACuFA,MAAMC,KAAyB;AAAA,EAC7B,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,sBAAsB;AACxB;AAEO,MAAMC,WAIHvZ,GAEP;AAAA,EAyHS,YACWhd,GACnB;;AACM,UAAA;AAxHQ;AAAA;AAAA;AAAA,IAAAsR,EAAA;AAKT;AAAA;AAAA;AAAA,IAAAA,EAAA,oBAAiD,CAAC;AASzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,kBAAoB;AAEpB,IAAAA,EAAA;AAST;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,yBACL;AAOK;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,wCAA6B,QAAQ;AAK5B;AAAA;AAAA;AAAA,IAAAA,EAAA;AAKA;AAAA;AAAA;AAAA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAKA,IAAAA,EAAA;AAKA,IAAAA,EAAA;AAKA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAIA,IAAAA,EAAA;AAEC,IAAAA,EAAA;AAKD;AAAA;AAAA;AAAA,IAAAA,EAAA;AAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA;AAIR,IAAAA,EAAA,gCAAyD,CAAC;AAC1D,IAAAA,EAAA,8BAAuD,CAAC;AAEhD,IAAAA,EAAA;AACA,IAAAA,EAAA;AAIA;AAAA;AAAA;AAAA,IAAAA,EAAA;AAkSR;AAAA;AAAA;AAAA,IAAAA,EAAA,2BAAwC;AA4IzC;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,EAAA,eAAQ,CACbuY,GACA2L,MACG;AACH,WAAK,cAAc,MAAM,MAAM3L,GAAe2L,CAAgB;AAAA,IAChE;AAhaqB,SAAA,UAAAx1B;AAGnB,UAAMw2B,IAAUx2B;AAChB,QAAIw2B,EAAQ;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QAAIA,EAAQ;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QAAIA,EAAQ;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QAAIA,EAAQ;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGG,SAAA,aAAax2B,EAAQ,cAAcy2B,IACxC,KAAK,WAAW;AAAA,MACd,QAAQ;AAAA,QACN,cAAYjvC,IAAAwY,KAAA,gBAAAA,EAAS,WAAT,gBAAAxY,EAAiB,eAAc;AAAA,QAC3C,uBAAqBC,IAAAuY,KAAA,gBAAAA,EAAS,WAAT,gBAAAvY,EAAiB,wBAAuB;AAAA,QAC7D,iBAAeoC,IAAAmW,KAAA,gBAAAA,EAAS,WAAT,gBAAAnW,EAAiB,kBAAiB;AAAA,QACjD,WAASC,IAAAkW,KAAA,gBAAAA,EAAS,WAAT,gBAAAlW,EAAiB,YAAW;AAAA,MACvC;AAAA,MACA,WAAW;AAAA,QACT,qBAAmBC,IAAAiW,KAAA,gBAAAA,EAAS,cAAT,gBAAAjW,EAAoB,sBAAqB;AAAA,QAC5D,mBAAiB+W,IAAAd,KAAA,gBAAAA,EAAS,cAAT,gBAAAc,EAAoB,oBAAmB;AAAA,QACxD,sBAAoBC,IAAAf,KAAA,gBAAAA,EAAS,cAAT,gBAAAe,EAAoB,uBAAsB,CAAC;AAAA,QAC/D,qBAAmBC,IAAAhB,KAAA,gBAAAA,EAAS,cAAT,gBAAAgB,EAAoB,sBAAqB;AAAA,MAAA;AAAA,IAEhE;AAGA,UAAM01B,IAAa;AAAA,MACjB,eAAe;AAAA,MACf,QAAQ12B,EAAQ,UAAUoR,GAAgB,OAAO;AAAA,MACjD,WAAW;AAAA,MACX,GAAGpR;AAAA,MACH,cAAc;AAAA,QACZ,GAAG,KAAK,WAAW;AAAA,QACnB,GAAGA,EAAQ;AAAA,MAAA;AAAA,IAEf;AAEA,QAAI02B,EAAW,YAAY,CAACA,EAAW;AAC/B,YAAA,IAAI,MAAM,8CAA8C;AAGhE,SAAK,eAAeA,EAAW,cAG/B,KAAK,SAASA,EAAW,QACpB,KAAA,uBAAuBA,EAAW,OAAO,YACzC,KAAA,+BAA+BA,EAAW,OAAO,oBACjD,KAAA,uBAAuBA,EAAW,OAAO,YAE9C,KAAK,aAAa7C,GAAuB;AAAA,MACvC,QAAQ;AAAA,MACR,eAAe6C,EAAW,iBAAiB,CAAC;AAAA,MAC5C,YAAY,KAAK,OAAO;AAAA,MACxB,YAAY,KAAK,OAAO;AAAA,MACxB,oBAAoB,KAAK,OAAO;AAAA,MAChC,eAAeA,EAAW;AAAA,MAC1B,eAAeA,EAAW;AAAA,MAC1B,mBAAmBA,EAAW;AAAA,MAC9B,gBAAgBA,EAAW;AAAA,MAC3B,YAAYA,EAAW,cAAc;AAAA,MACrC,cAAc9mB,EAA8B,SAAS,IAAI;AAAA,MACzD,YAAY,KAAK,QAAQ,cAAc+mB;AAAA,MACvC,cAAcD,EAAW;AAAA,MACzB,aAAaA,EAAW;AAAA,MACxB,mBAAmBA,EAAW,qBAAqB;AAAA,MACnD,UAAUA,EAAW;AAAA,MACrB,cAAcA,EAAW;AAAA,IAAA,CAC1B,MAGAE,IAAAF,EAAW,mBAAX,gBAAAE,EAA2B,eAAc,CAAA,GAAI,QAAQ,CAAC5C,MAAQ;AACxD,WAAA,WAAWA,EAAI,IAAI,IAAIA;AAAA,IAAA,CAC7B;AAGD,aAASA,KAAO0C,EAAW,cAAc,CAAA,GAAI;AACvC,MAAA,OAAO1C,KAAQ,eAEjBA,IAAMA,EAAI,IAAI;AAEV,YAAAhuC,IAAOguC,EAAI,YAAoB,IAAI;AACzC,UAAI,CAAChuC;AACH,cAAM,IAAI;AAAA,UACR,aAAaguC,EAAI,YAAY,IAAI;AAAA,QACnC;AAEE,UAAA,KAAK,WAAWhuC,CAAG;AACrB,cAAM,IAAI;AAAA,UACR,aAAaguC,EAAI,YAAY,IAAI,4BAA4BhuC,CAAG;AAAA,QAClE;AAEG,WAAA,WAAWA,CAAG,IAAIguC;AAAA,IAAA;AAuCzB,QAnCO,OAAA,QAAQ0C,EAAW,eAAe,CAAA,CAAE,EAAE,QAAQ,CAAC,CAAC1wC,GAAKguC,CAAG,MAAM;AAInE,YAAM6C,IAAW,OAAO7C,KAAQ,aAAaA,EAF9B,IAEwC,IAAIA;AACvD,UAAA,EAAE,YAAY6C,IAAW;AAEtB,aAAA,WAAW7wC,CAAG,IAAI6wC;AACvB;AAAA,MAAA;AAGF,WAAK,WAAW7wC,CAAG,IAAI,IAAK,cAAcq3B,EAAmB;AAAA,QAC3D,OAAc,MAAM;AACX,iBAAAr3B;AAAA,QAAA;AAAA,QAET,cAAc;AACN,gBAAA,GACD,KAAA,qBAAqB6wC,EAAS,MAAM;AAAA,QAAA;AAAA,QAE3C,IAAW,WAAW;AACpB,iBAAOA,EAAS;AAAA,QAAA;AAAA,MAClB,EACC;AAAA,IAAA,CACJ,GAEI,KAAA,oBAAoB,KAAK,WAAW,mBACpC,KAAA,cAAc,KAAK,WAAW,aAC9B,KAAA,WAAW,KAAK,WAAW,UAC3B,KAAA,kBAAkB,KAAK,WAAW,iBAClC,KAAA,YAAY,KAAK,WAAW,WAC5B,KAAA,eAAe,KAAK,WAAW,cAC/B,KAAA,WAAW,KAAK,WAAW,UAC3B,KAAA,sBAAsB,KAAK,WAAW,eACtC,KAAA,iBAAiB,KAAK,WAAW,gBAElCH,EAAW,YAAY;AACzB,YAAMI,IAAaJ,EAAW;AACzB,WAAA,aAAa,OAAO3zB,GAAMM,OAAY;AACzC,aAAK,uBAAuB;AAAA,UAAQ,CAAC+Z,MACnCA,EAAS,MAAM,MAAM,CAAC/Z,EAAO,CAAC;AAAA,QAChC;AACI,YAAA;AACK,iBAAA,MAAMyzB,EAAW/zB,GAAMM,EAAO;AAAA,QAAA,UACrC;AACA,eAAK,qBAAqB;AAAA,YAAQ,CAAC+Z,MACjCA,EAAS,MAAM,MAAM,CAAC/Z,EAAO,CAAC;AAAA,UAChC;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA;AAGF,SAAK,iBAAiBqzB,EAAW,gBACjC,KAAK,WAAWA,EAAW;AAE3B,UAAMK,IACJ,iBAAiB,KAAK,cACtB,yBAAyB,KAAK;AAE5B,IAAAA,KAAwBL,EAAW,kBAE7B,QAAA;AAAA,MACN;AAAA,IACF;AAGI,UAAAM,IACJN,EAAW,mBACVK,IACG;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,IAAI;AAAA,MAAA;AAAA,IACN,IAEF;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,IAAIzwC,GAAS,QAAQ,WAAW;AAAA,MAAA;AAAA,IAClC;AAGR,QAAI,CAAC,MAAM,QAAQ0wC,CAAc,KAAKA,EAAe,WAAW;AAC9D,YAAM,IAAI;AAAA,QACR,mEACEA;AAAA,MACJ;AAGF,UAAMlD,IAAmB;AAAA,MACvB,GAAG,OAAO,QAAQ,KAAK,UAAU,EAAE,IAAI,CAAC,CAAC9tC,GAAKguC,CAAG,MAAM;AACrD,YACEA,aAAeztC,KACfytC,aAAeiD,MACfjD,aAAe99B;AAGR,iBAAA89B;AAGT,YAAI,EAAAA,aAAe3W,KAAsB,CAAC2W,EAAI,QAAQ;AAKtD,iBAAOztC,EAAU,OAAO;AAAA,YACtB,MAAMP;AAAA,YACN,UAAUguC,EAAI;AAAA,YACd,uBAAuB,MAAMA,EAAI;AAAA,UAAA,CAClC;AAAA,MACF,CAAA;AAAA,IACD,EAAA,OAAO,CAACA,MAA0BA,MAAQ,MAAS,GAE/CkD,IAA8C;AAAA,MAClD,GAAGZ;AAAA,MACH,GAAGI,EAAW;AAAA,MACd,SAASM;AAAA,MACT,YAAYlD;AAAA,MACZ,aAAa;AAAA,QACX,IAAGqD,IAAAT,EAAW,mBAAX,gBAAAS,EAA2B;AAAA,QAC9B,YAAY;AAAA;AAAA;AAAA;AAAA,UAIV,UAAU;AAAA,UACV,IAAGC,KAAAC,IAAAX,EAAW,mBAAX,gBAAAW,EAA2B,gBAA3B,gBAAAD,EAAwC;AAAA,UAC3C,IAAGE,IAAAZ,EAAW,kBAAX,gBAAAY,EAA0B;AAAA,UAC7B,OAAOxsC;AAAA,YACL;AAAA,YACA4rC,EAAW,gBAAgB,sBAAsB;AAAA,cACjDa,KAAAC,IAAAd,EAAW,kBAAX,gBAAAc,EAA0B,WAA1B,gBAAAD,EAAkC,UAAS;AAAA,UAAA;AAAA,QAE/C;AAAA,QACA,iBAAAzwC;AAAA,MAAA;AAAA,IAEJ;AAEI,IAAC,KAAK,WAYH,KAAA,WAAW2wC,GAAUP,EAAc,UAAW,KAXnD,KAAK,gBAAgBb,GAAsB;AAAA,MACzCa;AAAA,MACA,KAAK,OAAO;AAAA,IACd,GAIK,KAAA,WAAW,KAAK,cAAc,SAMhC,KAAA,SAAS,OAAO,kBAAkB,MACvC,KAAK,KAAK,QAAQ;AAAA,EAAA;AAAA,EAlRpB,OAAc,OAIZl3B,IAAsE,IAAI;AACnE,WAAA,IAAIu2B,GAA2Cv2B,CAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiSxD,KAAK03B,GAAkB;AAC5B,QAAI,KAAK;AACP,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEI,UAAA1mC,IAAQ,KAAK,cAAc,OAC3BpI,IAAO,KAAK,cAAc;AAGzB,WAAA8uC,EAAQ1mC,GAFE,CAACzJ,MAAoB,KAAK,cAAc,SAASA,CAAE,GAEpCqB,CAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAe/B,QAAQ8uC,GAA2B;AACxC,QAAI,KAAK;AACP,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEI,UAAA1mC,IAAQ,KAAK,cAAc,OAC3BpI,IAAO,KAAK,cAAc;AAEzB,WAAA8uC,EAAQ1mC,GAAO,QAAWpI,CAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBhC,SACLw0B,GAOG;AACH,QAAI,KAAK;AAEA,aAAAA,EAAS,KAAK,iBAAiB;AAGpC,QAAA;AAEG,WAAA,oBAAoB,KAAK,cAAc,MAAM;AAG5C,YAAAlE,IAASkE,EAAS,KAAK,iBAAiB,GAGxCua,IAAW,KAAK;AAEtB,kBAAK,oBAAoB,MAEvBA;AAAA,OAECA,EAAS,cACRA,EAAS,gBACTA,EAAS,oBACTA,EAAS,kBACT,CAACA,EAAS,cAGP,KAAA,cAAc,SAASA,CAAQ,GAG/Bze;AAAA,IAAA,UACP;AAEA,WAAK,oBAAoB;AAAA,IAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYK,UACL8a,GACAhuC,IAAMguC,EAAI,OACP;AACG,UAAAhnB,IAAY,KAAK,WAAWhnB,CAAG;AACrC,QAAI,CAACgnB;AACH,YAAM,IAAI,MAAM,aAAahnB,CAAG,YAAY;AAEvC,WAAAgnB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBT,IAAW,mBAAmB;AAC5B,QAAI,KAAK;AACP,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,WAAO,KAAK,cAAc;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5B,IAAW,kBAAkB;AAC3B,WAAO,KAAK,cAAc;AAAA,EAAA;AAAA,EAG5B,IAAW,aAAa;;AACtB,YAAOxlB,IAAA,KAAK,oBAAL,gBAAAA,EAAsB;AAAA,EAAA;AAAA,EAGxB,YAAY;;AACV,aAAAA,IAAA,KAAK,oBAAL,gBAAAA,EAAsB,eAAc;AAAA,EAAA;AAAA,EAGtC,QAAQ;;AACb,KAAAA,IAAA,KAAK,oBAAL,QAAAA,EAAsB;AAAA,EAAM;AAAA,EAGvB,cAAc41B,GAAsC;AACpD,gBAAA,uBAAuB,KAAKA,CAAQ,GAElC,MAAM;AACX,YAAM/2B,IAAQ,KAAK,uBAAuB,QAAQ+2B,CAAQ;AAC1D,MAAI/2B,IAAQ,MACL,KAAA,uBAAuB,OAAOA,GAAO,CAAC;AAAA,IAE/C;AAAA,EAAA;AAAA,EAGK,YAAY+2B,GAAsC;AAClD,gBAAA,qBAAqB,KAAKA,CAAQ,GAEhC,MAAM;AACX,YAAM/2B,IAAQ,KAAK,qBAAqB,QAAQ+2B,CAAQ;AACxD,MAAI/2B,IAAQ,MACL,KAAA,qBAAqB,OAAOA,GAAO,CAAC;AAAA,IAE7C;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMF,IAAW,iBAAqD;AAC9D,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,IAAW,WAA+C;AACjD,WAAA,KAAK,SAAS,CAACkB,MACbqM,GAAYrM,EAAG,KAAK,KAAK,QAAQ,CACzC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUI,SACLiG,GAC8C;AACvC,WAAA,KAAK,SAAS,CAACjG,MAAO8sB,GAAS9sB,EAAG,KAAKiG,CAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYzD,aACLA,GAC8C;AACvC,WAAA,KAAK,SAAS,CAACjG,MAAO+sB,GAAa/sB,EAAG,KAAKiG,CAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW7D,aACLA,GAC8C;AACvC,WAAA,KAAK,SAAS,CAACjG,MAAOitB,GAAajtB,EAAG,KAAKiG,CAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU7D,eACLA,GAC8C;AACvC,WAAA,KAAK,SAAS,CAACjG,MAAOktB,GAAeltB,EAAG,KAAKiG,CAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ/D,aACL4vB,GACAwa,IAAU,IACJ;AACA,UAAA/jC,IAAS,KAAK,SAAS,MAAM;AAEnC,IAAI+jC,KACF/jC,EAAO,QAAQ;AAGjB,aAASgkC,EACPC,GACS;AACT,iBAAWlsC,KAASksC,GAAY;AAC1B,YAAA1a,EAASxxB,CAAK,MAAM;AACf,iBAAA;AAGH,cAAA+H,IAAWikC,IACbhsC,EAAM,SAAS,QAAQ,YACvBA,EAAM;AAEN,YAAA,CAACisC,EAAmBlkC,CAAQ;AACvB,iBAAA;AAAA,MACT;AAGK,aAAA;AAAA,IAAA;AAGT,IAAAkkC,EAAmBhkC,CAAM;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,sBAAsBupB,GAAsB;AAC5C,SAAA,cAAc,GAAG,UAAUA,CAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnC,wBAAwBA,GAAsB;AAC9C,SAAA,cAAc,GAAG,mBAAmBA,CAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5C,wBAIL;AACA,WAAO,KAAK,SAAS,CAAC71B,MAAOqvB,GAAsBrvB,CAAE,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASjD,sBACLyvB,GACAvZ,IAA6B,SAC7B;AACA,WAAO,KAAK;AAAA,MAAS,CAAClW,MACpBwvB,GAAsBxvB,GAAIyvB,GAAavZ,CAAS;AAAA,IAClD;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASK,eAAiE;AACtE,WAAO,KAAK,SAAS,CAAClW,MAAO0tB,GAAa1tB,CAAE,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUxC,wBAAwB;AAC7B,WAAO,KAAK,SAAS,CAACA,MAAOmvB,GAAsBnvB,CAAE,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjD,aAAamuB,GAA6BC,GAA2B;AACnE,WAAA,KAAK,SAAS,CAACpuB,MAAOkuB,GAAaluB,GAAImuB,GAAYC,CAAQ,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrE,IAAW,aAAsB;AAC3B,QAAA,CAAC,KAAK,eAAe;AACnB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,mCAAmC;AAE9C,aAAA;AAAA,IAAA;AAET,WAAO,KAAK,cAAc,eAAe,SACrC,KACA,KAAK,cAAc;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOzB,IAAW,WAAWoiB,GAAmB;AACnC,QAAA,CAAC,KAAK,eAAe;AACnB,UAAA,CAAC,KAAK;AACF,cAAA,IAAI,MAAM,mCAAmC;AAGrD;AAAA,IAAA;AAEF,IAAI,KAAK,cAAc,QAAQ,aAAaA,KACrC,KAAA,cAAc,YAAYA,CAAQ;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWK,aACLx6B,GACAC,GACAC,IAAgC,UAChC;AACA,WAAO,KAAK;AAAA,MAAS,CAAClW,MACpB+V,GAAa/V,GAAIgW,GAAgBC,GAAgBC,CAAS;AAAA,IAC5D;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUK,YACLiC,GACArK,GACA;AACO,WAAA,KAAK,SAAS,CAAC9N,MAAOkY,GAAYlY,GAAImY,GAAerK,CAAM,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO9D,aAAawI,GAAmC;AACrD,WAAO,KAAK;AAAA,MACV,CAACtW,MAAOqW,GAAsBrW,GAAIsW,GAAgB,CAAE,CAAA,EAAE;AAAA,IACxD;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUK,cACLA,GACAN,GACA;AACA,WAAO,KAAK;AAAA,MAAS,CAAChW,MACpBqW,GAAsBrW,GAAIsW,GAAgBN,CAAc;AAAA,IAC1D;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMK,OAAO;AACR,WAAA,KAAK,QAAQ,gBACR,KAAK,KAAKy6B,EAAW,IAGvB,KAAK,KAAKC,EAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,OAAO;AACR,WAAA,KAAK,QAAQ,gBACR,KAAK,KAAKC,EAAW,IAEvB,KAAK,KAAKC,EAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhB,oBACL5uC,GACA,EAAE,iBAAA6uC,IAAkB,GAAM,IAAmC,CAAA,GAC7D;AACA,UAAMj9B,IAAQ7F,EAAqB/L,GAAS,KAAK,QAAQ;AAEpD,SAAA,SAAS,CAAChC,MAAO;AACpB,MAAAstB;AAAA,QACEttB;AAAA,QACA;AAAA,UACE,MAAMA,EAAG,UAAU;AAAA,UACnB,IAAIA,EAAG,UAAU;AAAA,QACnB;AAAA,QACA4T;AAAA,QACA;AAAA,UACE,iBAAAi9B;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA,CACD;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMI,kBAAkB;AAChB,WAAA,KAAK,SAAS,CAAC7wC,MAAO;AAC3B,YAAM0L,IAA0B,CAAC,GAC3B4H,IAAQtT,EAAG,UAAU,IAAI,MAAM;AAErC,iBAAW4L,KAAQ0H,GAAO;AACxB,cAAM3M,IAAS,KAAK,OAAO,YAAYiF,EAAK,KAAK,IAAI;AACrD,YAAI,CAACjF,GAAQ;AACX;AAAA,UAEEiF,EAAK,KAAK,SAAS;AAAA,UAEnB,CAACA,EAAK,KAAK,KAAK,mBAGhB,QAAQ,KAAK,iCAAiCA,EAAK,KAAK,IAAI;AAG9D;AAAA,QAAA;AAEE,QAAAjF,EAAO,eAAe,YACvB+E,EAAe/E,EAAO,IAAI,IAAI,KAE9B+E,EAAe/E,EAAO,IAAI,IAAIiF,EAAK,MAAM;AAAA,MAC5C;AAGK,aAAAF;AAAA,IAAA,CACR;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOI,UAAUA,GAAyB;AACxC,eAAW,CAAC6H,GAAOrP,CAAK,KAAK,OAAO,QAAQwH,CAAM,GAAG;AACnD,YAAM/E,IAAS,KAAK,OAAO,YAAY4M,CAAK;AAC5C,UAAI,CAAC5M;AACH,cAAM,IAAI,MAAM,SAAS4M,CAAK,2BAA2B;AAEvD,UAAA5M,EAAO,eAAe;AACnB,aAAA,cAAc,SAAS,QAAQ4M,CAAK;AAAA,eAChC5M,EAAO,eAAe;AAC/B,aAAK,cAAc,SAAS,QAAQ4M,GAAO,EAAE,aAAarP,GAAO;AAAA;AAE3D,cAAA,IAAItB,EAAqB+D,EAAO,UAAU;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOK,aAAa+E,GAAyB;AAC3C,eAAW6H,KAAS,OAAO,KAAK7H,CAAM;AAC/B,WAAA,cAAc,SAAS,UAAU6H,CAAK;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAOK,aAAa7H,GAAyB;AAC3C,eAAW,CAAC6H,GAAOrP,CAAK,KAAK,OAAO,QAAQwH,CAAM,GAAG;AACnD,YAAM/E,IAAS,KAAK,OAAO,YAAY4M,CAAK;AAC5C,UAAI,CAAC5M;AACH,cAAM,IAAI,MAAM,SAAS4M,CAAK,2BAA2B;AAEvD,UAAA5M,EAAO,eAAe;AACnB,aAAA,cAAc,SAAS,WAAW4M,CAAK;AAAA,eACnC5M,EAAO,eAAe;AAC/B,aAAK,cAAc,SAAS,WAAW4M,GAAO,EAAE,aAAarP,GAAO;AAAA;AAE9D,cAAA,IAAItB,EAAqB+D,EAAO,UAAU;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMK,kBAAkB;AAChB,WAAA,KAAK,SAAS,CAAC3G,MACbA,EAAG,IAAI,YAAYA,EAAG,UAAU,MAAMA,EAAG,UAAU,EAAE,CAC7D;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMI,qBAAqB;AAC1B,WAAO,KAAK,cAAc,cAAc,MAAM,EAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3C,WAAWoF,GAAaoO,GAAe;AAC5C,QAAIpO,MAAQ;AACV;AAEI,UAAAwG,IAAO,KAAK,SAAS,KAAK,QAAQ,EAAE,MAAMxG,GAAK;AAChD,SAAA,SAAS,CAACpF,MAAO;AACpB,YAAM,EAAE,MAAAgT,GAAM,IAAAC,EAAG,IAAIjT,EAAG;AAExB,MAAIwT,IACCxT,EAAA,WAAWwT,GAAMR,GAAMC,CAAE,EAAE,QAAQD,GAAMA,IAAOQ,EAAK,QAAQ5H,CAAI,IAEpE5L,EAAG,aAAa6e,EAAc,OAAO7e,EAAG,KAAKiT,CAAE,CAAC,EAAE;AAAA,QAChDD;AAAA,QACAC;AAAA,QACArH;AAAA,MACF;AAAA,IACF,CACD;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMI,eAAe;AACpB,WAAOghB,GAAa,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMnB,YAAY;AACjB,IAAAF,GAAU,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMT,iBAAiB;AACtB,WAAOG,GAAe,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,cAAc;AACnB,IAAAF,GAAY,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQX,eAAe;AACpB,WAAOf,GAAa,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQnB,iBAAiB;AACtB,WAAOE,GAAe,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU5B,MAAa,kBACXxf,IAAoD,KAAK,UACxC;AAEjB,WADiBqN,GAA2B,KAAK,UAAU,IAAI,EAC/C,aAAarN,GAAQ,EAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYzC,MAAa,iBACXA,GACiB;AAEjB,WADiBiO,GAA6B,KAAK,UAAU,IAAI,EACjD,gBAAgBjO,GAAQ,EAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS5C,MAAa,qBACXuN,GAC6C;AACtC,WAAA0X,GAAa1X,GAAM,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASzC,MAAa,sBACXvN,IAAoD,KAAK,UACxC;AACjB,WAAOkkB,GAAiBlkB,GAAQ,KAAK,UAAU,MAAM,CAAA,CAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUzD,MAAa,yBACXulB,GAC6C;AACtC,WAAAC,GAAiBD,GAAU,KAAK,QAAQ;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAM1C,4BAA4BsE,GAAuC;AACpE,QAAA,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGD,SAAK,WAAW,cAAkC,WAAWA,CAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS7D,SACLN,GASA;AACA,QAAI,KAAK;AAEP;AAGF,UAAM4B,IAAK,CAAC;AAAA,MACV,aAAA33B;AAAA,MACA,sBAAAqV;AAAA,IAAA,MAII;AACJ,MAAA0gB,EAAS,MAAM;AAAA,QACb,YAAY,MACV3gB,GAA8BpV,GAAaqV,CAAoB;AAAA,MAAA,CAClE;AAAA,IACH;AAEK,gBAAA,cAAc,GAAG,aAAasiB,CAAE,GAE9B,MAAM;AACN,WAAA,cAAc,IAAI,aAAaA,CAAE;AAAA,IACxC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASK,kBACL5B,GACAib,GACA;AACA,QAAI,KAAK;AACP;AAGI,UAAArZ,IAAK,CAACgD,MAAoC;AAC9C,MACEA,EAAE,YAAY,QAAQtB,EAAc,KACpC,CAAC2X,KAMHjb,EAAS,IAAI;AAAA,IACf;AAEK,gBAAA,cAAc,GAAG,mBAAmB4B,CAAE,GAEpC,MAAM;AACN,WAAA,cAAc,IAAI,mBAAmBA,CAAE;AAAA,IAC9C;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQK,SAAS5B,GAAsB;AAC/B,gBAAA,GAAG,UAAUA,CAAQ,GAEnB,MAAM;AACN,WAAA,IAAI,UAAUA,CAAQ;AAAA,IAC7B;AAAA,EAAA;AAAA,EAGK,0BAA0B;AAC3B,QAAA,CAAC,KAAK;AACD;AAGH,UAAA,EAAE,WAAA/W,MAAc,KAAK,kBAGrB,EAAE,QAAA8b,MAAW9b,GACb9L,IAAO,KAAK,IAAI,GAAG4nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,MAAM,GAAG,CAAC,GACzDxC,IAAK,KAAK,IAAI,GAAG2nB,EAAO,IAAI,CAACnlB,MAAUA,EAAM,IAAI,GAAG,CAAC;AAEvD,QAAA6kB,GAAgBxb,CAAS,GAAG;AAC9B,YAAMje,IAAO,KAAK,gBAAgB,QAAQmS,CAAI;AAC9C,UAAInS;AACF,eAAOA,EAAK,sBAAsB;AAAA,IACpC;AAGF,WAAOm6B,GAAa,KAAK,iBAAiBhoB,GAAMC,CAAE;AAAA,EAAA;AAAA,EAGpD,IAAW,UAAU;AACnB,UAAMhL,IAAM,KAAK;AAGjB,WACEA,EAAI,WAAW,KACdA,EAAI,WAAW,KACdA,EAAI,CAAC,EAAE,SAAS,eACfA,EAAI,CAAC,EAAE,QAAgB,WAAW;AAAA,EAAA;AAAA,EAIlC,mBACL09B,GACAhM,GAIA;AACI,IAAC,KAAK,oBAIV,KAAK,MAAM,GACN,KAAA,SAAS,CAAC35B,MAAO;AACpB,MAAI25B,KAAA,QAAAA,EAAa,0BACf35B,EAAG,WAAW2lC,CAAgB,GAEhC3lC,EAAG,iBAAiB,QAAQ,KAAK,gBAAgB,QAAQ,CAAC,GAAG;AAAA,QAC3D,kBAAA2lC;AAAA,QACA,yBAAwBhM,KAAA,gBAAAA,EAAa,2BAA0B;AAAA,QAC/D,oBAAmBA,KAAA,gBAAAA,EAAa,sBAAqB;AAAA,MAAA,CACtD;AAAA,IAAA,CACF;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQI,2BAA2B;AACzB,WAAA,KAAK,oBAAoB,WAAW;AAAA,EAAA;AAAA,EAGtC,yBAAyBoX,GAAgC;AACzD,SAAA,oBAAoB,WAAWA,CAAqB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMnD,2BAA2Bl3B,GAAc;AAE/C,WADiBwX,GAAgCxX,EAAK,KAAA,CAAM,EAC5C;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQX,UAAUA,GAAcm3B,IAAM,IAAO;;AAC1C,QAAIC,IAAcp3B;AAIlB,IAHKm3B,MACWC,IAAA,KAAK,2BAA2Bp3B,CAAI,IAE/Co3B,OAGAhxC,IAAA,KAAA,oBAAA,QAAAA,EAAiB,UAAUgxC;AAAA,EAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtC,UAAUz9B,GAAc;;AACtB,YAAAvT,IAAA,KAAK,oBAAL,gBAAAA,EAAsB,UAAUuT;AAAA,EAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7C,MAAa,cAAcqe,GAAkB;AAC3C,WAAO,KAAK,UAAU,MAAMD,GAAeC,CAAQ,CAAC;AAAA,EAAA;AAExD;AC5vDO,MAAMqf,KAAiB;AAAA,EAC5B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EAAA;AAEhB,GAEaC,KAA2B;AAAA,EACtC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,EAAA;AAEhB;ACvCO,MAAeC,GAQpB;AAAA,EACO,YACLC,GACmBC,GAKH74B,GAChB;AANmB,SAAA,WAAA64B,GAKH,KAAA,UAAA74B;AAAA,EAAA;AAAA,EAGlB,MAAa,YAAYrT,GAAa;;AAChC,QAAA,GAACnF,IAAA,KAAK,YAAL,QAAAA,EAAc;AACjB,cAAQ,MAAM,MAAMmF,CAAG,GAAG,KAAK;AAEjC,UAAMoF,IAAM,MAAM,KAAK,QAAQ,eAAepF,CAAG;AACjD,WAAIoF,aAAe,OACVA,KAED,MAAM,MAAMA,CAAG,GAAG,KAAK;AAAA,EAAA;AAAA,EAG1B,UAAUkB,GAAmB;AAK3B,WAJa,OAAO,QAAQA,CAAM,EAAE,IAAI,CAAC,CAACjN,GAAKyF,CAAK,MACrC,KAAK,SAAS,aAAazF,CAAG,EAAEyF,GAAO,IAAI,CAEhE;AAAA,EACM;AAAA,EAGF,iBAAiBC,GAAoC;AAC1D,WAAO,KAAK,SAAS,qBAAqBA,EAAc,IAAI;AAAA,MAC1DA;AAAA,MACA;AAAA,IACF;AAAA,EAAA;AAAA,EAGK,uBAAuBotC,GAA2C;AACvE,WAAOA,EAAmB,IAAI,CAACr4B,MAAO,KAAK,iBAAiBA,CAAE,CAAC;AAAA,EAAA;AAAA,EAKjE,MAAa,SACX7U,GACAmtC,GACAC,GACA;AACA,WAAO,KAAK,SAAS,aAAaptC,EAAM,IAAI;AAAA,MAC1CA;AAAA,MACA;AAAA,MACAmtC;AAAA,MACAC;AAAA,IACF;AAAA,EAAA;AAEJ;ACvCO,SAASC,GAIdL,GAAmC;AAC5B,SAAA;AAAA,IACL,oBAAoB,CAAQ7wC,MAC1BA;AAAA,IACF,4BAA4B,CAC1BA,MACGA;AAAA,IACL,oBAAoB,CAAIA,MAAgCA;AAAA,EAC1D;AACF;AC9DA,IAAImxC;AAOJ,eAAeC,KAAgB;AAC7B,SAAID,OAIJA,MAAuB,YAAY;AAEjC,UAAM,CAACE,GAAiBC,CAAe,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC3D,OAAO,YAAY;AAAA;AAAA;AAAA,MAGnB,OAAO,kBAAkB;AAAA,IAAA,CAC1B,GAEKC,IACJ,aAAaF,IAAkBA,EAAgB,UAAUA,GACrDG,IACJ,aAAaF,IACRA,EAAgB,UAChBA;AAEP,iBAAMC,EAAU,KAAK,EAAE,MAAMC,GAAW,GAEjC,EAAE,WAAAD,GAAW,WAAAC,EAAU;AAAA,EAAA,GAC7B,GAEIL;AACT;AAEsB,eAAAM,GAKpB3tC,GACAmlB,GACsC;AACtC,MAAI,CAACnB,GAAsC,QAAQhkB,CAAM;AACvD,WAAO,CAAC;AAGV,QAAM,EAAE,WAAA0tC,GAAW,WAAAD,EAAU,IAAI,MAAMH,GAAc;AAO9C,UAJLnoB,EAAM,KAAK,MAAM,KACb,OAAO,OAAOuoB,EAAU,MAAM,IAC5B,MAAMD,EAAW,YAAY,OAAOtoB,CAAK,GAE7B,IAAI,CAACyoB,OAAW;AAAA,IAClC,IAAIA,EAAM,MAAM,CAAC,EAAE;AAAA,IACnB,aAAa,MAAM5tC,EAAO,oBAAoB4tC,EAAM,MAAM,CAAC,EAAE,SAAS,GAAG;AAAA,EAAA,EACzE;AACJ;ACnEgB,SAAAC,GACdxzC,MACGyzC,GAGH;AACM,QAAAC,IAAgB,CAAC,GAAG1zC,CAAK;AAC/B,aAAW2zC,KAAmBF;AAC5B,eAAWG,KAAkBD,GAAiB;AAC5C,YAAME,IAAwBH,EAAc;AAAA,QAC1C,CAAC7zC,MAASA,EAAK,UAAU+zC,EAAe;AAAA,MAC1C;AACA,MAAIC,MAA0B,KAC5BH,EAAc,KAAKE,CAAmB,IAEtCF,EAAc,OAAOG,IAAwB,GAAG,GAAGD,CAAmB;AAAA,IACxE;AAGG,SAAAF;AACT;"}