blob: 3e10286dfe7cfc8e536ac04ff5e313e91e9eb6c9 [file] [log] [blame]
{
"version": 3,
"sources": ["../../../shared/playground/playground.ts", "../../../shared/analytics/analytics.ts", "../../../shared/keyboard/keyboard.ts", "../../../shared/jump/jump.ts", "../../../shared/outline/select.ts", "../../../shared/outline/tree.ts", "../../../shared/table/table.ts", "main.ts"],
"sourcesContent": ["/*!\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// This file implements the playground implementation of the documentation\n// page. The playground involves a \"play\" button that allows you to open up\n// a new link to play.golang.org using the example code.\n\n// The CSS is in static/frontend/unit/main/_doc.css\n\n/**\n * CSS classes used by PlaygroundExampleController\n */\nconst PlayExampleClassName = {\n PLAY_HREF: '.js-exampleHref',\n PLAY_CONTAINER: '.js-exampleContainer',\n EXAMPLE_INPUT: '.Documentation-exampleCode',\n EXAMPLE_OUTPUT: '.Documentation-exampleOutput',\n EXAMPLE_ERROR: '.Documentation-exampleError',\n PLAY_BUTTON: '.Documentation-examplePlayButton',\n SHARE_BUTTON: '.Documentation-exampleShareButton',\n FORMAT_BUTTON: '.Documentation-exampleFormatButton',\n RUN_BUTTON: '.Documentation-exampleRunButton',\n};\n\n/**\n * This controller enables playground examples to expand their dropdown or\n * generate shareable Go Playground URLs.\n */\nexport class PlaygroundExampleController {\n /**\n * The anchor tag used to identify the container with an example href.\n * There is only one in an example container div.\n */\n private readonly anchorEl: HTMLAnchorElement | null;\n\n /**\n * The error element\n */\n private readonly errorEl: Element | null;\n\n /**\n * Buttons that redirect to an example's playground, this element\n * only exists in executable examples.\n */\n private readonly playButtonEl: Element | null;\n private readonly shareButtonEl: Element | null;\n\n /**\n * Button that formats the code in an example's playground.\n */\n private readonly formatButtonEl: Element | null;\n\n /**\n * Button that runs the code in an example's playground, this element\n * only exists in executable examples.\n */\n private readonly runButtonEl: Element | null;\n\n /**\n * The executable code of an example.\n */\n private readonly inputEl: HTMLTextAreaElement | null;\n\n /**\n * The output of the given example code. This only exists if the\n * author of the package provides an output for this example.\n */\n private readonly outputEl: Element | null;\n\n /**\n * @param exampleEl The div that contains playground content for the given example.\n */\n constructor(private readonly exampleEl: HTMLDetailsElement) {\n this.exampleEl = exampleEl;\n this.anchorEl = exampleEl.querySelector('a');\n this.errorEl = exampleEl.querySelector(PlayExampleClassName.EXAMPLE_ERROR);\n this.playButtonEl = exampleEl.querySelector(PlayExampleClassName.PLAY_BUTTON);\n this.shareButtonEl = exampleEl.querySelector(PlayExampleClassName.SHARE_BUTTON);\n this.formatButtonEl = exampleEl.querySelector(PlayExampleClassName.FORMAT_BUTTON);\n this.runButtonEl = exampleEl.querySelector(PlayExampleClassName.RUN_BUTTON);\n this.inputEl = this.makeTextArea(exampleEl.querySelector(PlayExampleClassName.EXAMPLE_INPUT));\n this.outputEl = exampleEl.querySelector(PlayExampleClassName.EXAMPLE_OUTPUT);\n\n // This is legacy listener to be replaced the listener for shareButtonEl.\n this.playButtonEl?.addEventListener('click', () => this.handleShareButtonClick());\n this.shareButtonEl?.addEventListener('click', () => this.handleShareButtonClick());\n this.formatButtonEl?.addEventListener('click', () => this.handleFormatButtonClick());\n this.runButtonEl?.addEventListener('click', () => this.handleRunButtonClick());\n\n if (!this.inputEl) return;\n\n this.resize();\n this.inputEl.addEventListener('keyup', () => this.resize());\n this.inputEl.addEventListener('keydown', e => this.onKeydown(e));\n }\n\n /**\n * Replace the pre element with a textarea. The examples are initially rendered\n * as pre elements so they're fully visible when JS is disabled.\n */\n makeTextArea(el: Element | null): HTMLTextAreaElement {\n const t = document.createElement('textarea');\n t.classList.add('Documentation-exampleCode', 'code');\n t.spellcheck = false;\n t.value = el?.textContent ?? '';\n el?.parentElement?.replaceChild(t, el);\n return t;\n }\n\n /**\n * Retrieve the hash value of the anchor element.\n */\n getAnchorHash(): string | undefined {\n return this.anchorEl?.hash;\n }\n\n /**\n * Expands the current playground example.\n */\n expand(): void {\n this.exampleEl.open = true;\n }\n\n /**\n * Resizes the input element to accomodate the amount of text present.\n */\n private resize(): void {\n if (this.inputEl?.value) {\n const numLineBreaks = (this.inputEl.value.match(/\\n/g) || []).length;\n // min-height + lines x line-height + padding + border\n this.inputEl.style.height = `${(20 + numLineBreaks * 20 + 12 + 2) / 16}rem`;\n }\n }\n\n /**\n * Handler to override keyboard behavior in the playground's\n * textarea element.\n *\n * Tab key inserts tabs into the example playground instead of\n * switching to the next interactive element.\n * @param e input element keyboard event.\n */\n private onKeydown(e: KeyboardEvent) {\n if (e.key === 'Tab') {\n document.execCommand('insertText', false, '\\t');\n e.preventDefault();\n }\n }\n\n /**\n * Changes the text of the example's input box.\n */\n private setInputText(output: string) {\n if (this.inputEl) {\n this.inputEl.value = output;\n }\n }\n\n /**\n * Changes the text of the example's output box.\n */\n private setOutputText(output: string) {\n if (this.outputEl) {\n this.outputEl.textContent = output;\n }\n }\n\n /**\n * Sets the error message text and overwrites\n * output box to indicate a failed response.\n */\n private setErrorText(err: string) {\n if (this.errorEl) {\n this.errorEl.textContent = err;\n }\n this.setOutputText('An error has occurred\u2026');\n }\n\n /**\n * Opens a new window to play.golang.org using the\n * example snippet's code in the playground.\n */\n private handleShareButtonClick() {\n const PLAYGROUND_BASE_URL = 'https://play.golang.org/p/';\n\n this.setOutputText('Waiting for remote server\u2026');\n\n fetch('/play/share', {\n method: 'POST',\n body: this.inputEl?.value,\n })\n .then(res => res.text())\n .then(shareId => {\n const href = PLAYGROUND_BASE_URL + shareId;\n this.setOutputText(`<a href=\"${href}\">${href}</a>`);\n window.open(href);\n })\n .catch(err => {\n this.setErrorText(err);\n });\n }\n\n /**\n * Runs gofmt on the example snippet in the playground.\n */\n private handleFormatButtonClick() {\n this.setOutputText('Waiting for remote server\u2026');\n const body = new FormData();\n body.append('body', this.inputEl?.value ?? '');\n\n fetch('/play/fmt', {\n method: 'POST',\n body: body,\n })\n .then(res => res.json())\n .then(({ Body, Error }) => {\n this.setOutputText(Error || 'Done.');\n if (Body) {\n this.setInputText(Body);\n this.resize();\n }\n })\n .catch(err => {\n this.setErrorText(err);\n });\n }\n\n /**\n * Runs the code snippet in the example playground.\n */\n private handleRunButtonClick() {\n this.setOutputText('Waiting for remote server\u2026');\n\n fetch('/play/compile', {\n method: 'POST',\n body: JSON.stringify({ body: this.inputEl?.value, version: 2 }),\n })\n .then(res => res.json())\n .then(async ({ Events, Errors }) => {\n this.setOutputText(Errors || '');\n for (const e of Events || []) {\n this.setOutputText(e.Message);\n await new Promise(resolve => setTimeout(resolve, e.Delay / 1000000));\n }\n })\n .catch(err => {\n this.setErrorText(err);\n });\n }\n}\n\nexport function initPlaygrounds(): void {\n const exampleHashRegex = location.hash.match(/^#(example-.*)$/);\n if (exampleHashRegex) {\n const exampleHashEl = document.getElementById(exampleHashRegex[1]) as HTMLDetailsElement;\n if (exampleHashEl) {\n exampleHashEl.open = true;\n }\n }\n\n // We use a spread operator to convert a nodelist into an array of elements.\n const exampleHrefs = [\n ...document.querySelectorAll<HTMLAnchorElement>(PlayExampleClassName.PLAY_HREF),\n ];\n\n /**\n * Sometimes exampleHrefs and playContainers are in different order, so we\n * find an exampleHref from a common hash.\n * @param playContainer - playground container\n */\n const findExampleHash = (playContainer: PlaygroundExampleController) =>\n exampleHrefs.find(ex => {\n return ex.hash === playContainer.getAnchorHash();\n });\n\n for (const el of document.querySelectorAll(PlayExampleClassName.PLAY_CONTAINER)) {\n // There should be the same amount of hrefs referencing examples as example containers.\n const playContainer = new PlaygroundExampleController(el as HTMLDetailsElement);\n const exampleHref = findExampleHash(playContainer);\n if (exampleHref) {\n exampleHref.addEventListener('click', () => {\n playContainer.expand();\n });\n } else {\n console.warn('example href not found');\n }\n }\n}\n", "interface TagManagerEvent {\n /**\n * event is the name of the event, used to filter events in\n * Google Analytics.\n */\n event: string;\n\n /**\n * event_category is a name that you supply as a way to group objects\n * that to analyze. Typically, you will use the same category name\n * multiple times over related UI elements (buttons, links, etc).\n */\n event_category?: string;\n\n /**\n * event_action is used to name the type of event or interaction you\n * want to measure for a particular web object. For example, with a\n * single \"form\" category, you can analyze a number of specific events\n * with this parameter, such as: form entered, form submitted.\n */\n event_action?: string;\n\n /**\n * event_label provide additional information for events that you want\n * to analyze, such as the text label of a link.\n */\n event_label?: string;\n\n /**\n * gtm.start is used to initialize Google Tag Manager.\n */\n 'gtm.start'?: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare global {\n interface Window {\n dataLayer?: (TagManagerEvent | VoidFunction)[];\n ga?: unknown;\n }\n}\n\n/**\n * track sends events to Google Tag Manager.\n */\nexport function track(\n event: string | TagManagerEvent,\n category?: string,\n action?: string,\n label?: string\n): void {\n window.dataLayer ??= [];\n if (typeof event === 'string') {\n window.dataLayer.push({\n event,\n event_category: category,\n event_action: action,\n event_label: label,\n });\n } else {\n window.dataLayer.push(event);\n }\n}\n\n/**\n * func adds functions to run sequentionally after\n * Google Tag Manager is ready.\n */\nexport function func(fn: () => void): void {\n window.dataLayer ??= [];\n window.dataLayer.push(fn);\n}\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { track } from '../analytics/analytics';\n\n/**\n * Options are keyhandler callback options.\n */\ninterface Options {\n /**\n * target is the element the key event should filter on. The\n * default target is the document.\n */\n target?: Element;\n\n /**\n * withMeta specifies if the event callback should fire when\n * the key is pressed with a meta key (ctrl, alt, etc). By\n * default meta keypresses are ignored.\n */\n withMeta?: boolean;\n}\n\n/**\n * KeyHandler is the config for a keyboard event callback.\n */\ninterface KeyHandler extends Options {\n description: string;\n callback: (e: KeyboardEvent) => void;\n}\n\n/**\n * KeyboardController controls event callbacks for sitewide\n * keyboard events. Multiple callbacks can be registered for\n * a single key and by default the controller ignores events\n * for text input targets.\n */\nclass KeyboardController {\n handlers: Record<string, Set<KeyHandler>>;\n\n constructor() {\n this.handlers = {};\n document.addEventListener('keydown', e => this.handleKeyPress(e));\n }\n\n /**\n * on registers keyboard event callbacks.\n * @param key the key to register.\n * @param description name of the event.\n * @param callback event callback.\n * @param options set target and withMeta options to override the default behaviors.\n */\n on(key: string, description: string, callback: (e: KeyboardEvent) => void, options?: Options) {\n this.handlers[key] ??= new Set();\n this.handlers[key].add({ description, callback, ...options });\n return this;\n }\n\n private handleKeyPress(e: KeyboardEvent) {\n for (const handler of this.handlers[e.key.toLowerCase()] ?? new Set()) {\n if (handler.target && handler.target !== e.target) {\n return;\n }\n const t = e.target as HTMLElement | null;\n if (\n !handler.target &&\n (t?.tagName === 'INPUT' || t?.tagName === 'SELECT' || t?.tagName === 'TEXTAREA')\n ) {\n return;\n }\n if (t?.isContentEditable) {\n return;\n }\n if (\n (handler.withMeta && !(e.ctrlKey || e.metaKey)) ||\n (!handler.withMeta && (e.ctrlKey || e.metaKey))\n ) {\n return;\n }\n track('keypress', 'hotkeys', `${e.key} pressed`, handler.description);\n handler.callback(e);\n }\n }\n}\n\nexport const keyboard = new KeyboardController();\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// This file implements the behavior of the \"jump to symbol\" dialog for Go\n// package documentation, as well as the simple dialog that displays keyboard\n// shortcuts.\n\n// The DOM for the dialogs is at the bottom of static/frontend/unit/main/_modals.tmpl.\n// The CSS is in static/frontend/unit/main/_modals.css.\n\n// The dialog is activated by pressing the 'f' key. It presents a list\n// (#JumpDialog-list) of all Go symbols displayed in the documentation.\n// Entering text in the dialog's text box (#JumpDialog-filter) restricts the\n// list to symbols containing the text. Clicking on an symbol jumps to\n// its documentation.\n\n// This code is based on\n// https://go.googlesource.com/gddo/+/refs/heads/master/gddo-server/assets/site.js.\n// It was modified to remove the dependence on jquery and bootstrap.\n\nimport { keyboard } from '../keyboard/keyboard';\n\nconst jumpDialog = document.querySelector<HTMLDialogElement>('.JumpDialog');\nconst jumpBody = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-body');\nconst jumpList = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-list');\nconst jumpFilter = jumpDialog?.querySelector<HTMLInputElement>('.JumpDialog-input');\nconst doc = document.querySelector<HTMLDivElement>('.js-documentation');\n\ninterface JumpListItem {\n link: HTMLAnchorElement;\n name: string;\n kind: string;\n lower: string;\n}\n\nlet jumpListItems: JumpListItem[] | undefined; // All the symbols in the doc; computed only once.\n\n// collectJumpListItems returns a list of items, one for each symbol in the\n// documentation on the current page.\n//\n// It uses the data-kind attribute generated in the documentation HTML to find\n// the symbols and their id attributes.\n//\n// If there are no data-kind attributes, then we have older doc; fall back to\n// a less precise method.\nfunction collectJumpListItems() {\n const items = [];\n if (!doc) return;\n for (const el of doc.querySelectorAll('[data-kind]')) {\n items.push(newJumpListItem(el));\n }\n\n // Clicking on any of the links closes the dialog.\n for (const item of items) {\n item.link.addEventListener('click', function () {\n jumpDialog?.close();\n });\n }\n // Sort case-insensitively by symbol name.\n items.sort(function (a, b) {\n return a.lower.localeCompare(b.lower);\n });\n return items;\n}\n\n// newJumpListItem creates a new item for the DOM element el.\n// An item is an object with:\n// - name: the element's id (which is the symbol name)\n// - kind: the element's kind (function, variable, etc.),\n// - link: a link ('a' tag) to the element\n// - lower: the name in lower case, just for sorting\nfunction newJumpListItem(el: Element): JumpListItem {\n const a = document.createElement('a');\n const name = el.getAttribute('id');\n a.setAttribute('href', '#' + name);\n a.setAttribute('tabindex', '-1');\n a.setAttribute('data-gtmc', 'jump to link');\n const kind = el.getAttribute('data-kind');\n return {\n link: a,\n name: name ?? '',\n kind: kind ?? '',\n lower: name?.toLowerCase() ?? '', // for sorting\n };\n}\n\nlet lastFilterValue: string; // The last contents of the filter text box.\nlet activeJumpItem = -1; // The index of the currently active item in the list.\n\n// updateJumpList sets the elements of the dialog list to\n// everything whose name contains filter.\nfunction updateJumpList(filter: string) {\n lastFilterValue = filter;\n if (!jumpListItems) {\n jumpListItems = collectJumpListItems();\n }\n setActiveJumpItem(-1);\n\n // Remove all children from list.\n while (jumpList?.firstChild) {\n jumpList.firstChild.remove();\n }\n\n if (filter) {\n // A filter is set. We treat the filter as a substring that can appear in\n // an item name (case insensitive), and find the following matches - in\n // order of priority:\n //\n // 1. Exact matches (the filter matches the item's name exactly)\n // 2. Prefix matches (the item's name starts with filter)\n // 3. Infix matches (the filter is a substring of the item's name)\n const filterLowerCase = filter.toLowerCase();\n\n const exactMatches = [];\n const prefixMatches = [];\n const infixMatches = [];\n\n // makeLinkHtml creates the link name HTML for a list item. item is the DOM\n // item. item.name.substr(boldStart, boldEnd) will be bolded.\n const makeLinkHtml = (item: JumpListItem, boldStart: number, boldEnd: number) => {\n return (\n item.name.substring(0, boldStart) +\n '<b>' +\n item.name.substring(boldStart, boldEnd) +\n '</b>' +\n item.name.substring(boldEnd)\n );\n };\n\n for (const item of jumpListItems ?? []) {\n const nameLowerCase = item.name.toLowerCase();\n\n if (nameLowerCase === filterLowerCase) {\n item.link.innerHTML = makeLinkHtml(item, 0, item.name.length);\n exactMatches.push(item);\n } else if (nameLowerCase.startsWith(filterLowerCase)) {\n item.link.innerHTML = makeLinkHtml(item, 0, filter.length);\n prefixMatches.push(item);\n } else {\n const index = nameLowerCase.indexOf(filterLowerCase);\n if (index > -1) {\n item.link.innerHTML = makeLinkHtml(item, index, index + filter.length);\n infixMatches.push(item);\n }\n }\n }\n\n for (const item of exactMatches.concat(prefixMatches).concat(infixMatches)) {\n jumpList?.appendChild(item.link);\n }\n } else {\n if (!jumpListItems || jumpListItems.length === 0) {\n const msg = document.createElement('i');\n msg.innerHTML = 'There are no symbols on this page.';\n jumpList?.appendChild(msg);\n }\n // No filter set; display all items in their existing order.\n for (const item of jumpListItems ?? []) {\n item.link.innerHTML = item.name + ' <i>' + item.kind + '</i>';\n jumpList?.appendChild(item.link);\n }\n }\n\n if (jumpBody) {\n jumpBody.scrollTop = 0;\n }\n if (jumpListItems?.length && jumpList && jumpList.children.length > 0) {\n setActiveJumpItem(0);\n }\n}\n\n// Set the active jump item to n.\nfunction setActiveJumpItem(n: number) {\n const cs = jumpList?.children as HTMLCollectionOf<HTMLElement> | null | undefined;\n if (!cs || !jumpBody) {\n return;\n }\n if (activeJumpItem >= 0) {\n cs[activeJumpItem].classList.remove('JumpDialog-active');\n }\n if (n >= cs.length) {\n n = cs.length - 1;\n }\n if (n >= 0) {\n cs[n].classList.add('JumpDialog-active');\n\n // Scroll so the active item is visible.\n // For some reason cs[n].scrollIntoView() doesn't behave as I'd expect:\n // it moves the entire dialog box in the viewport.\n\n // Get the top and bottom of the active item relative to jumpBody.\n const activeTop = cs[n].offsetTop - cs[0].offsetTop;\n const activeBottom = activeTop + cs[n].clientHeight;\n if (activeTop < jumpBody.scrollTop) {\n // Off the top; scroll up.\n jumpBody.scrollTop = activeTop;\n } else if (activeBottom > jumpBody.scrollTop + jumpBody.clientHeight) {\n // Off the bottom; scroll down.\n jumpBody.scrollTop = activeBottom - jumpBody.clientHeight;\n }\n }\n activeJumpItem = n;\n}\n\n// Increment the activeJumpItem by delta.\nfunction incActiveJumpItem(delta: number) {\n if (activeJumpItem < 0) {\n return;\n }\n let n = activeJumpItem + delta;\n if (n < 0) {\n n = 0;\n }\n setActiveJumpItem(n);\n}\n\nexport function initModals(): void {\n // Pressing a key in the filter updates the list (if the filter actually changed).\n jumpFilter?.addEventListener('keyup', function () {\n if (jumpFilter.value.toUpperCase() != lastFilterValue.toUpperCase()) {\n updateJumpList(jumpFilter.value);\n }\n });\n\n // Pressing enter in the filter selects the first element in the list.\n jumpFilter?.addEventListener('keydown', function (event) {\n const upArrow = 38;\n const downArrow = 40;\n const enterKey = 13;\n switch (event.which) {\n case upArrow:\n incActiveJumpItem(-1);\n event.preventDefault();\n break;\n case downArrow:\n incActiveJumpItem(1);\n event.preventDefault();\n break;\n case enterKey:\n if (activeJumpItem >= 0) {\n if (jumpList) {\n (jumpList.children[activeJumpItem] as HTMLElement).click();\n event.preventDefault();\n }\n }\n break;\n }\n });\n\n const shortcutsDialog = document.querySelector<HTMLDialogElement>('.ShortcutsDialog');\n\n // - Pressing 'f' or 'F' opens the jump-to-symbol dialog.\n // - Pressing '?' opens up the shortcut dialog.\n // Ignore a keypress if a dialog is already open, or if it is pressed on a\n // component that wants to consume it.\n keyboard\n .on('f', 'open jump to modal', e => {\n if (jumpDialog?.open || shortcutsDialog?.open) {\n return;\n }\n e.preventDefault();\n if (jumpFilter) {\n jumpFilter.value = '';\n }\n jumpDialog?.showModal();\n jumpFilter?.focus();\n updateJumpList('');\n })\n .on('?', 'open shortcuts modal', () => {\n if (jumpDialog?.open || shortcutsDialog?.open) {\n return;\n }\n shortcutsDialog?.showModal();\n });\n\n const jumpOutlineInput = document.querySelector('.js-jumpToInput');\n if (jumpOutlineInput) {\n jumpOutlineInput.addEventListener('click', () => {\n if (jumpFilter) {\n jumpFilter.value = '';\n }\n updateJumpList('');\n });\n }\n\n document.querySelector('.js-openShortcuts')?.addEventListener('click', () => {\n shortcutsDialog?.showModal();\n });\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { TreeNavController } from './tree.js';\n\nexport class SelectNavController {\n constructor(private el: Element) {\n this.el.addEventListener('change', e => {\n const target = e.target as HTMLSelectElement;\n let href = target.value;\n if (!target.value.startsWith('/')) {\n href = '/' + href;\n }\n window.location.href = href;\n });\n }\n}\n\nexport function makeSelectNav(tree: TreeNavController): HTMLLabelElement {\n const label = document.createElement('label');\n label.classList.add('go-Label');\n label.setAttribute('aria-label', 'Menu');\n const select = document.createElement('select');\n select.classList.add('go-Select', 'js-selectNav');\n label.appendChild(select);\n const outline = document.createElement('optgroup');\n outline.label = 'Outline';\n select.appendChild(outline);\n const groupMap: Record<string, HTMLOptGroupElement> = {};\n let group: HTMLOptGroupElement;\n for (const t of tree.treeitems) {\n if (Number(t.depth) > 4) continue;\n if (t.groupTreeitem) {\n group = groupMap[t.groupTreeitem.label];\n if (!group) {\n group = groupMap[t.groupTreeitem.label] = document.createElement('optgroup');\n group.label = t.groupTreeitem.label;\n select.appendChild(group);\n }\n } else {\n group = outline;\n }\n const o = document.createElement('option');\n o.label = t.label;\n o.textContent = t.label;\n o.value = (t.el as HTMLAnchorElement).href.replace(window.location.origin, '').replace('/', '');\n group.appendChild(o);\n }\n tree.addObserver(t => {\n const hash = (t.el as HTMLAnchorElement).hash;\n const value = select.querySelector<HTMLOptionElement>(`[value$=\"${hash}\"]`)?.value;\n if (value) {\n select.value = value;\n }\n }, 50);\n return label;\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * TreeNavController is the navigation tree component of the documentation page.\n * It adds accessiblity attributes to a tree, observes the heading elements\n * focus the topmost link for headings visible on the page, and implements the\n * WAI-ARIA Treeview Design Pattern with full\n * [keyboard support](https://www.w3.org/TR/wai-aria-practices/examples/treeview/treeview-2/treeview-2a.html#kbd_label).\n */\nexport class TreeNavController {\n treeitems: TreeItem[];\n\n /**\n * firstChars is the first character of each treeitem in the same order\n * as this.treeitems. We use this array to set focus by character when\n * navigating the tree with a keyboard.\n */\n private firstChars: string[];\n private firstTreeitem: TreeItem | null;\n private lastTreeitem: TreeItem | null;\n private observerCallbacks: ((t: TreeItem) => void)[];\n\n constructor(private el: HTMLElement) {\n this.treeitems = [];\n this.firstChars = [];\n this.firstTreeitem = null;\n this.lastTreeitem = null;\n this.observerCallbacks = [];\n this.init();\n }\n\n private init(): void {\n this.handleResize();\n window.addEventListener('resize', this.handleResize);\n this.findTreeItems();\n this.updateVisibleTreeitems();\n this.observeTargets();\n if (this.firstTreeitem) {\n this.firstTreeitem.el.tabIndex = 0;\n }\n }\n\n private handleResize = (): void => {\n this.el.style.setProperty('--js-tree-height', '100vh');\n this.el.style.setProperty('--js-tree-height', this.el.clientHeight + 'px');\n };\n\n private observeTargets() {\n this.addObserver(treeitem => {\n this.expandTreeitem(treeitem);\n this.setSelected(treeitem);\n // TODO: Fix scroll issue in https://golang.org/issue/47450.\n // treeitem.el.scrollIntoView({ block: 'nearest' });\n });\n\n const targets = new Map<string, boolean>();\n const observer = new IntersectionObserver(\n entries => {\n for (const entry of entries) {\n targets.set(entry.target.id, entry.isIntersecting || entry.intersectionRatio === 1);\n }\n for (const [id, isIntersecting] of targets) {\n if (isIntersecting) {\n const active = this.treeitems.find(t =>\n (t.el as HTMLAnchorElement)?.href.endsWith(`#${id}`)\n );\n if (active) {\n for (const fn of this.observerCallbacks) {\n fn(active);\n }\n }\n break;\n }\n }\n },\n {\n threshold: 1.0,\n rootMargin: '-60px 0px 0px 0px',\n }\n );\n\n for (const href of this.treeitems.map(t => t.el.getAttribute('href'))) {\n if (href) {\n const id = href.replace(window.location.origin, '').replace('/', '').replace('#', '');\n const target = document.getElementById(id);\n if (target) {\n observer.observe(target);\n }\n }\n }\n }\n\n addObserver(fn: (t: TreeItem) => void, delay = 200): void {\n this.observerCallbacks.push(debounce(fn, delay));\n }\n\n setFocusToNextItem(currentItem: TreeItem): void {\n let nextItem = null;\n for (let i = currentItem.index + 1; i < this.treeitems.length; i++) {\n const ti = this.treeitems[i];\n if (ti.isVisible) {\n nextItem = ti;\n break;\n }\n }\n if (nextItem) {\n this.setFocusToItem(nextItem);\n }\n }\n\n setFocusToPreviousItem(currentItem: TreeItem): void {\n let prevItem = null;\n for (let i = currentItem.index - 1; i > -1; i--) {\n const ti = this.treeitems[i];\n if (ti.isVisible) {\n prevItem = ti;\n break;\n }\n }\n if (prevItem) {\n this.setFocusToItem(prevItem);\n }\n }\n\n setFocusToParentItem(currentItem: TreeItem): void {\n if (currentItem.groupTreeitem) {\n this.setFocusToItem(currentItem.groupTreeitem);\n }\n }\n\n setFocusToFirstItem(): void {\n this.firstTreeitem && this.setFocusToItem(this.firstTreeitem);\n }\n\n setFocusToLastItem(): void {\n this.lastTreeitem && this.setFocusToItem(this.lastTreeitem);\n }\n\n setSelected(currentItem: TreeItem): void {\n for (const l1 of this.el.querySelectorAll('[aria-expanded=\"true\"]')) {\n if (l1 === currentItem.el) continue;\n if (!l1.nextElementSibling?.contains(currentItem.el)) {\n l1.setAttribute('aria-expanded', 'false');\n }\n }\n for (const l1 of this.el.querySelectorAll('[aria-selected]')) {\n if (l1 !== currentItem.el) {\n l1.setAttribute('aria-selected', 'false');\n }\n }\n currentItem.el.setAttribute('aria-selected', 'true');\n this.updateVisibleTreeitems();\n this.setFocusToItem(currentItem, false);\n }\n\n expandTreeitem(treeitem: TreeItem): void {\n let currentItem: TreeItem | null = treeitem;\n while (currentItem) {\n if (currentItem.isExpandable) {\n currentItem.el.setAttribute('aria-expanded', 'true');\n }\n currentItem = currentItem.groupTreeitem;\n }\n this.updateVisibleTreeitems();\n }\n\n expandAllSiblingItems(currentItem: TreeItem): void {\n for (const ti of this.treeitems) {\n if (ti.groupTreeitem === currentItem.groupTreeitem && ti.isExpandable) {\n this.expandTreeitem(ti);\n }\n }\n }\n\n collapseTreeitem(currentItem: TreeItem): void {\n let groupTreeitem = null;\n\n if (currentItem.isExpanded()) {\n groupTreeitem = currentItem;\n } else {\n groupTreeitem = currentItem.groupTreeitem;\n }\n\n if (groupTreeitem) {\n groupTreeitem.el.setAttribute('aria-expanded', 'false');\n this.updateVisibleTreeitems();\n this.setFocusToItem(groupTreeitem);\n }\n }\n\n setFocusByFirstCharacter(currentItem: TreeItem, char: string): void {\n let start: number, index: number;\n char = char.toLowerCase();\n\n // Get start index for search based on position of currentItem\n start = currentItem.index + 1;\n if (start === this.treeitems.length) {\n start = 0;\n }\n\n // Check remaining slots in the menu\n index = this.getIndexFirstChars(start, char);\n\n // If not found in remaining slots, check from beginning\n if (index === -1) {\n index = this.getIndexFirstChars(0, char);\n }\n\n // If match was found...\n if (index > -1) {\n this.setFocusToItem(this.treeitems[index]);\n }\n }\n\n private findTreeItems() {\n const findItems = (el: HTMLElement, group: TreeItem | null) => {\n let ti = group;\n let curr = el.firstElementChild as HTMLElement;\n while (curr) {\n if (curr.tagName === 'A' || curr.tagName === 'SPAN') {\n ti = new TreeItem(curr, this, group);\n this.treeitems.push(ti);\n this.firstChars.push(ti.label.substring(0, 1).toLowerCase());\n }\n if (curr.firstElementChild) {\n findItems(curr, ti);\n }\n curr = curr.nextElementSibling as HTMLElement;\n }\n };\n findItems(this.el as HTMLElement, null);\n this.treeitems.map((ti, idx) => (ti.index = idx));\n }\n\n private updateVisibleTreeitems(): void {\n this.firstTreeitem = this.treeitems[0];\n\n for (const ti of this.treeitems) {\n let parent = ti.groupTreeitem;\n ti.isVisible = true;\n while (parent && parent.el !== this.el) {\n if (!parent.isExpanded()) {\n ti.isVisible = false;\n }\n parent = parent.groupTreeitem;\n }\n if (ti.isVisible) {\n this.lastTreeitem = ti;\n }\n }\n }\n\n private setFocusToItem(treeitem: TreeItem, focusEl = true) {\n treeitem.el.tabIndex = 0;\n if (focusEl) {\n treeitem.el.focus();\n }\n for (const ti of this.treeitems) {\n if (ti !== treeitem) {\n ti.el.tabIndex = -1;\n }\n }\n }\n\n private getIndexFirstChars(startIndex: number, char: string): number {\n for (let i = startIndex; i < this.firstChars.length; i++) {\n if (this.treeitems[i].isVisible && char === this.firstChars[i]) {\n return i;\n }\n }\n return -1;\n }\n}\n\nclass TreeItem {\n el: HTMLElement;\n groupTreeitem: TreeItem | null;\n label: string;\n isExpandable: boolean;\n isVisible: boolean;\n depth: number;\n index: number;\n\n private tree: TreeNavController;\n private isInGroup: boolean;\n\n constructor(el: HTMLElement, treeObj: TreeNavController, group: TreeItem | null) {\n el.tabIndex = -1;\n this.el = el;\n this.groupTreeitem = group;\n this.label = el.textContent?.trim() ?? '';\n this.tree = treeObj;\n this.depth = (group?.depth || 0) + 1;\n this.index = 0;\n\n const parent = el.parentElement;\n if (parent?.tagName.toLowerCase() === 'li') {\n parent?.setAttribute('role', 'none');\n }\n el.setAttribute('aria-level', this.depth + '');\n if (el.getAttribute('aria-label')) {\n this.label = el?.getAttribute('aria-label')?.trim() ?? '';\n }\n\n this.isExpandable = false;\n this.isVisible = false;\n this.isInGroup = !!group;\n\n let curr = el.nextElementSibling;\n while (curr) {\n if (curr.tagName.toLowerCase() == 'ul') {\n const groupId = `${group?.label ?? ''} nav group ${this.label}`.replace(/[\\W_]+/g, '_');\n el.setAttribute('aria-owns', groupId);\n el.setAttribute('aria-expanded', 'false');\n curr.setAttribute('role', 'group');\n curr.setAttribute('id', groupId);\n this.isExpandable = true;\n break;\n }\n\n curr = curr.nextElementSibling;\n }\n this.init();\n }\n\n private init() {\n this.el.tabIndex = -1;\n if (!this.el.getAttribute('role')) {\n this.el.setAttribute('role', 'treeitem');\n }\n this.el.addEventListener('keydown', this.handleKeydown.bind(this));\n this.el.addEventListener('click', this.handleClick.bind(this));\n this.el.addEventListener('focus', this.handleFocus.bind(this));\n this.el.addEventListener('blur', this.handleBlur.bind(this));\n }\n\n isExpanded() {\n if (this.isExpandable) {\n return this.el.getAttribute('aria-expanded') === 'true';\n }\n\n return false;\n }\n\n isSelected() {\n return this.el.getAttribute('aria-selected') === 'true';\n }\n\n private handleClick(event: MouseEvent) {\n // only process click events that directly happened on this treeitem\n if (event.target !== this.el && event.target !== this.el.firstElementChild) {\n return;\n }\n if (this.isExpandable) {\n if (this.isExpanded() && this.isSelected()) {\n this.tree.collapseTreeitem(this);\n } else {\n this.tree.expandTreeitem(this);\n }\n event.stopPropagation();\n }\n this.tree.setSelected(this);\n }\n\n private handleFocus() {\n let el = this.el;\n if (this.isExpandable) {\n el = (el.firstElementChild as HTMLElement) ?? el;\n }\n el.classList.add('focus');\n }\n\n private handleBlur() {\n let el = this.el;\n if (this.isExpandable) {\n el = (el.firstElementChild as HTMLElement) ?? el;\n }\n el.classList.remove('focus');\n }\n\n private handleKeydown(event: KeyboardEvent) {\n if (event.altKey || event.ctrlKey || event.metaKey) {\n return;\n }\n\n let captured = false;\n switch (event.key) {\n case ' ':\n case 'Enter':\n if (this.isExpandable) {\n if (this.isExpanded() && this.isSelected()) {\n this.tree.collapseTreeitem(this);\n } else {\n this.tree.expandTreeitem(this);\n }\n captured = true;\n } else {\n event.stopPropagation();\n }\n this.tree.setSelected(this);\n break;\n\n case 'ArrowUp':\n this.tree.setFocusToPreviousItem(this);\n captured = true;\n break;\n\n case 'ArrowDown':\n this.tree.setFocusToNextItem(this);\n captured = true;\n break;\n\n case 'ArrowRight':\n if (this.isExpandable) {\n if (this.isExpanded()) {\n this.tree.setFocusToNextItem(this);\n } else {\n this.tree.expandTreeitem(this);\n }\n }\n captured = true;\n break;\n\n case 'ArrowLeft':\n if (this.isExpandable && this.isExpanded()) {\n this.tree.collapseTreeitem(this);\n captured = true;\n } else {\n if (this.isInGroup) {\n this.tree.setFocusToParentItem(this);\n captured = true;\n }\n }\n break;\n\n case 'Home':\n this.tree.setFocusToFirstItem();\n captured = true;\n break;\n\n case 'End':\n this.tree.setFocusToLastItem();\n captured = true;\n break;\n\n default:\n if (event.key.length === 1 && event.key.match(/\\S/)) {\n if (event.key == '*') {\n this.tree.expandAllSiblingItems(this);\n } else {\n this.tree.setFocusByFirstCharacter(this, event.key);\n }\n captured = true;\n }\n break;\n }\n\n if (captured) {\n event.stopPropagation();\n event.preventDefault();\n }\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction debounce<T extends (...args: any[]) => any>(func: T, wait: number) {\n let timeout: ReturnType<typeof setTimeout> | null;\n return (...args: Parameters<T>) => {\n const later = () => {\n timeout = null;\n func(...args);\n };\n if (timeout) {\n clearTimeout(timeout);\n }\n timeout = setTimeout(later, wait);\n };\n}\n", "/*!\n * @license\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Controller for a table element with expandable rows. Adds event listeners to\n * a toggle within a table row that controls visiblity of additional related\n * rows in the table.\n *\n * @example\n * ```typescript\n * import {ExpandableRowsTableController} from '/static/js/table';\n *\n * const el = document .querySelector<HTMLTableElement>('.js-myTableElement')\n * new ExpandableRowsTableController(el));\n * ```\n */\nexport class ExpandableRowsTableController {\n private rows: HTMLTableRowElement[];\n private toggles: HTMLButtonElement[];\n\n /**\n * Create a table controller.\n * @param table - The table element to which the controller binds.\n */\n constructor(private table: HTMLTableElement, private toggleAll?: HTMLButtonElement | null) {\n this.rows = Array.from(table.querySelectorAll<HTMLTableRowElement>('[data-aria-controls]'));\n this.toggles = Array.from(this.table.querySelectorAll('[aria-expanded]'));\n this.setAttributes();\n this.attachEventListeners();\n this.update();\n }\n\n /**\n * setAttributes sets data-aria-* and data-id attributes to regular\n * html attributes as a workaround for limitations from safehtml.\n */\n private setAttributes() {\n for (const a of ['data-aria-controls', 'data-aria-labelledby', 'data-id']) {\n this.table.querySelectorAll(`[${a}]`).forEach(t => {\n t.setAttribute(a.replace('data-', ''), t.getAttribute(a) ?? '');\n t.removeAttribute(a);\n });\n }\n }\n\n private attachEventListeners() {\n this.rows.forEach(t => {\n t.addEventListener('click', e => {\n this.handleToggleClick(e);\n });\n });\n this.toggleAll?.addEventListener('click', () => {\n this.expandAllItems();\n });\n\n document.addEventListener('keydown', e => {\n if ((e.ctrlKey || e.metaKey) && e.key === 'f') {\n this.expandAllItems();\n }\n });\n }\n\n private handleToggleClick(e: MouseEvent) {\n let target = e.currentTarget as HTMLTableRowElement | null;\n if (!target?.hasAttribute('aria-expanded')) {\n target = this.table.querySelector(\n `button[aria-controls=\"${target?.getAttribute('aria-controls')}\"]`\n );\n }\n const isExpanded = target?.getAttribute('aria-expanded') === 'true';\n target?.setAttribute('aria-expanded', isExpanded ? 'false' : 'true');\n e.stopPropagation();\n this.update();\n }\n\n expandAllItems = (): void => {\n this.toggles.map(t => t.setAttribute('aria-expanded', 'true'));\n this.update();\n };\n\n private collapseAllItems = () => {\n this.toggles.map(t => t.setAttribute('aria-expanded', 'false'));\n this.update();\n };\n\n private update = () => {\n this.updateVisibleItems();\n setTimeout(() => this.updateGlobalToggle());\n };\n\n private updateVisibleItems() {\n this.rows.map(t => {\n const isExpanded = t?.getAttribute('aria-expanded') === 'true';\n const rowIds = t?.getAttribute('aria-controls')?.trimEnd().split(' ');\n rowIds?.map(id => {\n const target = document.getElementById(`${id}`);\n if (isExpanded) {\n target?.classList.add('visible');\n target?.classList.remove('hidden');\n } else {\n target?.classList.add('hidden');\n target?.classList.remove('visible');\n }\n });\n });\n }\n\n private updateGlobalToggle() {\n if (!this.toggleAll) return;\n if (this.rows.some(t => t.hasAttribute('aria-expanded'))) {\n this.toggleAll.style.display = 'block';\n }\n const someCollapsed = this.toggles.some(el => el.getAttribute('aria-expanded') === 'false');\n if (someCollapsed) {\n this.toggleAll.innerText = 'Expand all';\n this.toggleAll.onclick = this.expandAllItems;\n } else {\n this.toggleAll.innerText = 'Collapse all';\n this.toggleAll.onclick = this.collapseAllItems;\n }\n }\n}\n", "import { initPlaygrounds } from 'static/shared/playground/playground';\nimport { initModals } from 'static/shared/jump/jump';\nimport { SelectNavController, makeSelectNav } from 'static/shared/outline/select';\nimport { TreeNavController } from 'static/shared/outline/tree';\nimport { ExpandableRowsTableController } from 'static/shared/table/table';\n\ninitModals();\ninitPlaygrounds();\n\nconst directories = document.querySelector<HTMLTableElement>('.js-expandableTable');\nif (directories) {\n const table = new ExpandableRowsTableController(\n directories,\n document.querySelector<HTMLButtonElement>('.js-expandAllDirectories')\n );\n // Expand directories on page load with expand-directories query param.\n if (window.location.search.includes('expand-directories')) {\n table.expandAllItems();\n }\n}\n\nconst treeEl = document.querySelector<HTMLElement>('.js-tree');\nif (treeEl) {\n const treeCtrl = new TreeNavController(treeEl);\n const select = makeSelectNav(treeCtrl);\n const mobileNav = document.querySelector('.js-mainNavMobile');\n if (mobileNav && mobileNav.firstElementChild) {\n mobileNav?.replaceChild(select, mobileNav.firstElementChild);\n }\n if (select.firstElementChild) {\n new SelectNavController(select.firstElementChild);\n }\n}\n\n/**\n * Event handlers for expanding and collapsing the readme section.\n */\nconst readme = document.querySelector('.js-readme');\nconst readmeContent = document.querySelector('.js-readmeContent');\nconst readmeOutline = document.querySelector('.js-readmeOutline');\nconst readmeExpand = document.querySelectorAll('.js-readmeExpand');\nconst readmeCollapse = document.querySelector('.js-readmeCollapse');\nconst mobileNavSelect = document.querySelector<HTMLSelectElement>('.DocNavMobile-select');\nif (readme && readmeContent && readmeOutline && readmeExpand.length && readmeCollapse) {\n if (window.location.hash.includes('readme')) {\n expandReadme();\n }\n mobileNavSelect?.addEventListener('change', e => {\n if ((e.target as HTMLSelectElement).value.startsWith('readme-')) {\n expandReadme();\n }\n });\n readmeExpand.forEach(el =>\n el.addEventListener('click', e => {\n e.preventDefault();\n expandReadme();\n readme.scrollIntoView();\n })\n );\n readmeCollapse.addEventListener('click', e => {\n e.preventDefault();\n readme.classList.remove('UnitReadme--expanded');\n if (readmeExpand[1]) {\n readmeExpand[1].scrollIntoView({ block: 'center' });\n }\n });\n readmeContent.addEventListener('keyup', () => {\n expandReadme();\n });\n readmeContent.addEventListener('click', () => {\n expandReadme();\n });\n readmeOutline.addEventListener('click', () => {\n expandReadme();\n });\n document.addEventListener('keydown', e => {\n if ((e.ctrlKey || e.metaKey) && e.key === 'f') {\n expandReadme();\n }\n });\n}\n\n/**\n * expandReadme expands the readme and adds the section-readme hash to the\n * URL so it stays expanded when navigating back from an external link.\n */\nfunction expandReadme() {\n history.replaceState(null, '', `${location.pathname}#section-readme`);\n readme?.classList.add('UnitReadme--expanded');\n}\n\n/**\n * Expand details items that are focused. This will expand\n * deprecated symbols when they are navigated to from the index\n * or a direct link.\n */\nfunction openDeprecatedSymbol() {\n if (!location.hash) return;\n const heading = document.getElementById(location.hash.slice(1));\n const grandParent = heading?.parentElement?.parentElement as HTMLDetailsElement | null;\n if (grandParent?.nodeName === 'DETAILS') {\n grandParent.open = true;\n }\n}\nopenDeprecatedSymbol();\nwindow.addEventListener('hashchange', () => openDeprecatedSymbol());\n\n/**\n * Listen for changes in the build context dropdown.\n */\ndocument.querySelectorAll('.js-buildContextSelect').forEach(el => {\n el.addEventListener('change', e => {\n window.location.search = `?GOOS=${(e.target as HTMLSelectElement).value}`;\n });\n});\n"],
"mappings": "AAAA,AAgBA,GAAM,GAAuB,CAC3B,UAAW,kBACX,eAAgB,uBAChB,cAAe,6BACf,eAAgB,+BAChB,cAAe,8BACf,YAAa,mCACb,aAAc,oCACd,cAAe,qCACf,WAAY,mCAOP,OAAkC,CA4CvC,YAA6B,EAA+B,CAA/B,iBA5E/B,YA6FI,AAhBA,KAAK,UAAY,EACjB,KAAK,SAAW,EAAU,cAAc,KACxC,KAAK,QAAU,EAAU,cAAc,EAAqB,eAC5D,KAAK,aAAe,EAAU,cAAc,EAAqB,aACjE,KAAK,cAAgB,EAAU,cAAc,EAAqB,cAClE,KAAK,eAAiB,EAAU,cAAc,EAAqB,eACnE,KAAK,YAAc,EAAU,cAAc,EAAqB,YAChE,KAAK,QAAU,KAAK,aAAa,EAAU,cAAc,EAAqB,gBAC9E,KAAK,SAAW,EAAU,cAAc,EAAqB,gBAG7D,QAAK,eAAL,QAAmB,iBAAiB,QAAS,IAAM,KAAK,0BACxD,QAAK,gBAAL,QAAoB,iBAAiB,QAAS,IAAM,KAAK,0BACzD,QAAK,iBAAL,QAAqB,iBAAiB,QAAS,IAAM,KAAK,2BAC1D,QAAK,cAAL,QAAkB,iBAAiB,QAAS,IAAM,KAAK,wBAEnD,EAAC,KAAK,SAEV,MAAK,SACL,KAAK,QAAQ,iBAAiB,QAAS,IAAM,KAAK,UAClD,KAAK,QAAQ,iBAAiB,UAAW,GAAK,KAAK,UAAU,KAO/D,aAAa,EAAyC,CAxGxD,QAyGI,GAAM,GAAI,SAAS,cAAc,YACjC,SAAE,UAAU,IAAI,4BAA6B,QAC7C,EAAE,WAAa,GACf,EAAE,MAAQ,oBAAI,cAAJ,OAAmB,GAC7B,oBAAI,gBAAJ,QAAmB,aAAa,EAAG,GAC5B,EAMT,eAAoC,CApHtC,MAqHI,MAAO,QAAK,WAAL,cAAe,KAMxB,QAAe,CACb,KAAK,UAAU,KAAO,GAMhB,QAAe,CAlIzB,MAmII,GAAI,QAAK,UAAL,cAAc,MAAO,CACvB,GAAM,GAAiB,MAAK,QAAQ,MAAM,MAAM,QAAU,IAAI,OAE9D,KAAK,QAAQ,MAAM,OAAS,GAAI,IAAK,EAAgB,GAAK,GAAK,GAAK,SAYhE,UAAU,EAAkB,CAClC,AAAI,EAAE,MAAQ,OACZ,UAAS,YAAY,aAAc,GAAO,KAC1C,EAAE,kBAOE,aAAa,EAAgB,CACnC,AAAI,KAAK,SACP,MAAK,QAAQ,MAAQ,GAOjB,cAAc,EAAgB,CACpC,AAAI,KAAK,UACP,MAAK,SAAS,YAAc,GAQxB,aAAa,EAAa,CAChC,AAAI,KAAK,SACP,MAAK,QAAQ,YAAc,GAE7B,KAAK,cAAc,+BAOb,wBAAyB,CA1LnC,MA2LI,GAAM,GAAsB,6BAE5B,KAAK,cAAc,mCAEnB,MAAM,cAAe,CACnB,OAAQ,OACR,KAAM,QAAK,UAAL,cAAc,QAEnB,KAAK,GAAO,EAAI,QAChB,KAAK,GAAW,CACf,GAAM,GAAO,EAAsB,EACnC,KAAK,cAAc,YAAY,MAAS,SACxC,OAAO,KAAK,KAEb,MAAM,GAAO,CACZ,KAAK,aAAa,KAOhB,yBAA0B,CAjNpC,QAkNI,KAAK,cAAc,mCACnB,GAAM,GAAO,GAAI,UACjB,EAAK,OAAO,OAAQ,WAAK,UAAL,cAAc,QAAd,OAAuB,IAE3C,MAAM,YAAa,CACjB,OAAQ,OACR,KAAM,IAEL,KAAK,GAAO,EAAI,QAChB,KAAK,CAAC,CAAE,OAAM,WAAY,CACzB,KAAK,cAAc,GAAS,SACxB,GACF,MAAK,aAAa,GAClB,KAAK,YAGR,MAAM,GAAO,CACZ,KAAK,aAAa,KAOhB,sBAAuB,CA1OjC,MA2OI,KAAK,cAAc,mCAEnB,MAAM,gBAAiB,CACrB,OAAQ,OACR,KAAM,KAAK,UAAU,CAAE,KAAM,QAAK,UAAL,cAAc,MAAO,QAAS,MAE1D,KAAK,GAAO,EAAI,QAChB,KAAK,MAAO,CAAE,SAAQ,YAAa,CAClC,KAAK,cAAc,GAAU,IAC7B,OAAW,KAAK,IAAU,GACxB,KAAK,cAAc,EAAE,SACrB,KAAM,IAAI,SAAQ,GAAW,WAAW,EAAS,EAAE,MAAQ,QAG9D,MAAM,GAAO,CACZ,KAAK,aAAa,OAKnB,YAAiC,CACtC,GAAM,GAAmB,SAAS,KAAK,MAAM,mBAC7C,GAAI,EAAkB,CACpB,GAAM,GAAgB,SAAS,eAAe,EAAiB,IAC/D,AAAI,GACF,GAAc,KAAO,IAKzB,GAAM,GAAe,CACnB,GAAG,SAAS,iBAAoC,EAAqB,YAQjE,EAAkB,AAAC,GACvB,EAAa,KAAK,GACT,EAAG,OAAS,EAAc,iBAGrC,OAAW,KAAM,UAAS,iBAAiB,EAAqB,gBAAiB,CAE/E,GAAM,GAAgB,GAAI,GAA4B,GAChD,EAAc,EAAgB,GACpC,AAAI,EACF,EAAY,iBAAiB,QAAS,IAAM,CAC1C,EAAc,WAGhB,QAAQ,KAAK,2BCnPZ,WACL,EACA,EACA,EACA,EACM,CAlDR,MAmDE,UAAO,YAAP,cAAO,UAAc,IACrB,AAAI,MAAO,IAAU,SACnB,OAAO,UAAU,KAAK,CACpB,QACA,eAAgB,EAChB,aAAc,EACd,YAAa,IAGf,OAAO,UAAU,KAAK,GC5D1B,AAyCA,WAAyB,CAGvB,aAAc,CACZ,KAAK,SAAW,GAChB,SAAS,iBAAiB,UAAW,GAAK,KAAK,eAAe,IAUhE,GAAG,EAAa,EAAqB,EAAsC,EAAmB,CAxDhG,QAyDI,iBAAK,UAAL,iBAAuB,GAAI,MAC3B,KAAK,SAAS,GAAK,IAAI,CAAE,cAAa,cAAa,IAC5C,KAGD,eAAe,EAAkB,CA9D3C,MA+DI,OAAW,KAAW,QAAK,SAAS,EAAE,IAAI,iBAApB,OAAsC,GAAI,KAAO,CACrE,GAAI,EAAQ,QAAU,EAAQ,SAAW,EAAE,OACzC,OAEF,GAAM,GAAI,EAAE,OAUZ,GARE,CAAC,EAAQ,QACR,mBAAG,WAAY,SAAW,kBAAG,WAAY,UAAY,kBAAG,WAAY,aAInE,kBAAG,oBAIJ,EAAQ,UAAY,CAAE,GAAE,SAAW,EAAE,UACrC,CAAC,EAAQ,UAAa,GAAE,SAAW,EAAE,SAEtC,OAEF,EAAM,WAAY,UAAW,GAAG,EAAE,cAAe,EAAQ,aACzD,EAAQ,SAAS,MAKV,EAAW,GAAI,GCzF5B,AA0BA,GAAM,GAAa,SAAS,cAAiC,eACvD,EAAW,iBAAY,cAA8B,oBACrD,EAAW,iBAAY,cAA8B,oBACrD,EAAa,iBAAY,cAAgC,qBACzD,EAAM,SAAS,cAA8B,qBAS/C,EAUJ,YAAgC,CAC9B,GAAM,GAAQ,GACd,GAAI,EAAC,EACL,QAAW,KAAM,GAAI,iBAAiB,eACpC,EAAM,KAAK,EAAgB,IAI7B,OAAW,KAAQ,GACjB,EAAK,KAAK,iBAAiB,QAAS,UAAY,CAC9C,WAAY,UAIhB,SAAM,KAAK,SAAU,EAAG,EAAG,CACzB,MAAO,GAAE,MAAM,cAAc,EAAE,SAE1B,GAST,WAAyB,EAA2B,CA3EpD,MA4EE,GAAM,GAAI,SAAS,cAAc,KAC3B,EAAO,EAAG,aAAa,MAC7B,EAAE,aAAa,OAAQ,IAAM,GAC7B,EAAE,aAAa,WAAY,MAC3B,EAAE,aAAa,YAAa,gBAC5B,GAAM,GAAO,EAAG,aAAa,aAC7B,MAAO,CACL,KAAM,EACN,KAAM,UAAQ,GACd,KAAM,UAAQ,GACd,MAAO,oBAAM,gBAAN,OAAuB,IAIlC,GAAI,GACA,EAAiB,GAIrB,WAAwB,EAAgB,CAQtC,IAPA,EAAkB,EACb,GACH,GAAgB,KAElB,EAAkB,IAGX,iBAAU,YACf,EAAS,WAAW,SAGtB,GAAI,EAAQ,CAQV,GAAM,GAAkB,EAAO,cAEzB,EAAe,GACf,EAAgB,GAChB,EAAe,GAIf,EAAe,CAAC,EAAoB,EAAmB,IAEzD,EAAK,KAAK,UAAU,EAAG,GACvB,MACA,EAAK,KAAK,UAAU,EAAW,GAC/B,OACA,EAAK,KAAK,UAAU,GAIxB,OAAW,KAAQ,WAAiB,GAAI,CACtC,GAAM,GAAgB,EAAK,KAAK,cAEhC,GAAI,IAAkB,EACpB,EAAK,KAAK,UAAY,EAAa,EAAM,EAAG,EAAK,KAAK,QACtD,EAAa,KAAK,WACT,EAAc,WAAW,GAClC,EAAK,KAAK,UAAY,EAAa,EAAM,EAAG,EAAO,QACnD,EAAc,KAAK,OACd,CACL,GAAM,GAAQ,EAAc,QAAQ,GACpC,AAAI,EAAQ,IACV,GAAK,KAAK,UAAY,EAAa,EAAM,EAAO,EAAQ,EAAO,QAC/D,EAAa,KAAK,KAKxB,OAAW,KAAQ,GAAa,OAAO,GAAe,OAAO,GAC3D,WAAU,YAAY,EAAK,UAExB,CACL,GAAI,CAAC,GAAiB,EAAc,SAAW,EAAG,CAChD,GAAM,GAAM,SAAS,cAAc,KACnC,EAAI,UAAY,qCAChB,WAAU,YAAY,GAGxB,OAAW,KAAQ,WAAiB,GAClC,EAAK,KAAK,UAAY,EAAK,KAAO,OAAS,EAAK,KAAO,OACvD,WAAU,YAAY,EAAK,MAI/B,AAAI,GACF,GAAS,UAAY,GAEnB,kBAAe,SAAU,GAAY,EAAS,SAAS,OAAS,GAClE,EAAkB,GAKtB,WAA2B,EAAW,CACpC,GAAM,GAAK,iBAAU,SACrB,GAAI,GAAC,GAAM,CAAC,GASZ,IANI,GAAkB,GACpB,EAAG,GAAgB,UAAU,OAAO,qBAElC,GAAK,EAAG,QACV,GAAI,EAAG,OAAS,GAEd,GAAK,EAAG,CACV,EAAG,GAAG,UAAU,IAAI,qBAOpB,GAAM,GAAY,EAAG,GAAG,UAAY,EAAG,GAAG,UACpC,EAAe,EAAY,EAAG,GAAG,aACvC,AAAI,EAAY,EAAS,UAEvB,EAAS,UAAY,EACZ,EAAe,EAAS,UAAY,EAAS,cAEtD,GAAS,UAAY,EAAe,EAAS,cAGjD,EAAiB,GAInB,WAA2B,EAAe,CACxC,GAAI,EAAiB,EACnB,OAEF,GAAI,GAAI,EAAiB,EACzB,AAAI,EAAI,GACN,GAAI,GAEN,EAAkB,GAGb,YAA4B,CA5NnC,MA8NE,WAAY,iBAAiB,QAAS,UAAY,CAChD,AAAI,EAAW,MAAM,eAAiB,EAAgB,eACpD,EAAe,EAAW,SAK9B,WAAY,iBAAiB,UAAW,SAAU,EAAO,CACvD,GAAM,GAAU,GACV,EAAY,GACZ,EAAW,GACjB,OAAQ,EAAM,WACP,GACH,EAAkB,IAClB,EAAM,iBACN,UACG,GACH,EAAkB,GAClB,EAAM,iBACN,UACG,GACH,AAAI,GAAkB,GAChB,GACD,GAAS,SAAS,GAAgC,QACnD,EAAM,kBAGV,SAIN,GAAM,GAAkB,SAAS,cAAiC,oBAMlE,EACG,GAAG,IAAK,qBAAsB,GAAK,CAClC,AAAI,kBAAY,OAAQ,kBAAiB,OAGzC,GAAE,iBACE,GACF,GAAW,MAAQ,IAErB,WAAY,YACZ,WAAY,QACZ,EAAe,OAEhB,GAAG,IAAK,uBAAwB,IAAM,CACrC,AAAI,kBAAY,OAAQ,kBAAiB,OAGzC,WAAiB,cAGrB,GAAM,GAAmB,SAAS,cAAc,mBAChD,AAAI,GACF,EAAiB,iBAAiB,QAAS,IAAM,CAC/C,AAAI,GACF,GAAW,MAAQ,IAErB,EAAe,MAInB,YAAS,cAAc,uBAAvB,QAA6C,iBAAiB,QAAS,IAAM,CAC3E,WAAiB,cClSrB,AASO,WAA0B,CAC/B,YAAoB,EAAa,CAAb,UAClB,KAAK,GAAG,iBAAiB,SAAU,GAAK,CACtC,GAAM,GAAS,EAAE,OACb,EAAO,EAAO,MAClB,AAAK,EAAO,MAAM,WAAW,MAC3B,GAAO,IAAM,GAEf,OAAO,SAAS,KAAO,MAKtB,WAAuB,EAA2C,CACvE,GAAM,GAAQ,SAAS,cAAc,SACrC,EAAM,UAAU,IAAI,YACpB,EAAM,aAAa,aAAc,QACjC,GAAM,GAAS,SAAS,cAAc,UACtC,EAAO,UAAU,IAAI,YAAa,gBAClC,EAAM,YAAY,GAClB,GAAM,GAAU,SAAS,cAAc,YACvC,EAAQ,MAAQ,UAChB,EAAO,YAAY,GACnB,GAAM,GAAgD,GAClD,EACJ,OAAW,KAAK,GAAK,UAAW,CAC9B,GAAI,OAAO,EAAE,OAAS,EAAG,SACzB,AAAI,EAAE,cACJ,GAAQ,EAAS,EAAE,cAAc,OAC5B,GACH,GAAQ,EAAS,EAAE,cAAc,OAAS,SAAS,cAAc,YACjE,EAAM,MAAQ,EAAE,cAAc,MAC9B,EAAO,YAAY,KAGrB,EAAQ,EAEV,GAAM,GAAI,SAAS,cAAc,UACjC,EAAE,MAAQ,EAAE,MACZ,EAAE,YAAc,EAAE,MAClB,EAAE,MAAS,EAAE,GAAyB,KAAK,QAAQ,OAAO,SAAS,OAAQ,IAAI,QAAQ,IAAK,IAC5F,EAAM,YAAY,GAEpB,SAAK,YAAY,GAAK,CApDxB,MAqDI,GAAM,GAAQ,EAAE,GAAyB,KACnC,EAAQ,KAAO,cAAiC,YAAY,SAApD,cAA+D,MAC7E,AAAI,GACF,GAAO,MAAQ,IAEhB,IACI,EC3DT,AAcO,WAAwB,CAa7B,YAAoB,EAAiB,CAAjB,UAoBZ,kBAAe,IAAY,CACjC,KAAK,GAAG,MAAM,YAAY,mBAAoB,SAC9C,KAAK,GAAG,MAAM,YAAY,mBAAoB,KAAK,GAAG,aAAe,OArBrE,KAAK,UAAY,GACjB,KAAK,WAAa,GAClB,KAAK,cAAgB,KACrB,KAAK,aAAe,KACpB,KAAK,kBAAoB,GACzB,KAAK,OAGC,MAAa,CACnB,KAAK,eACL,OAAO,iBAAiB,SAAU,KAAK,cACvC,KAAK,gBACL,KAAK,yBACL,KAAK,iBACD,KAAK,eACP,MAAK,cAAc,GAAG,SAAW,GAS7B,gBAAiB,CACvB,KAAK,YAAY,GAAY,CAC3B,KAAK,eAAe,GACpB,KAAK,YAAY,KAKnB,GAAM,GAAU,GAAI,KACd,EAAW,GAAI,sBACnB,GAAW,CACT,OAAW,KAAS,GAClB,EAAQ,IAAI,EAAM,OAAO,GAAI,EAAM,gBAAkB,EAAM,oBAAsB,GAEnF,OAAW,CAAC,EAAI,IAAmB,GACjC,GAAI,EAAgB,CAClB,GAAM,GAAS,KAAK,UAAU,KAAK,GAAE,CApEjD,MAqEe,WAAE,KAAF,cAA4B,KAAK,SAAS,IAAI,OAEjD,GAAI,EACF,OAAW,KAAM,MAAK,kBACpB,EAAG,GAGP,QAIN,CACE,UAAW,EACX,WAAY,sBAIhB,OAAW,KAAQ,MAAK,UAAU,IAAI,GAAK,EAAE,GAAG,aAAa,SAC3D,GAAI,EAAM,CACR,GAAM,GAAK,EAAK,QAAQ,OAAO,SAAS,OAAQ,IAAI,QAAQ,IAAK,IAAI,QAAQ,IAAK,IAC5E,EAAS,SAAS,eAAe,GACvC,AAAI,GACF,EAAS,QAAQ,IAMzB,YAAY,EAA2B,EAAQ,IAAW,CACxD,KAAK,kBAAkB,KAAK,EAAS,EAAI,IAG3C,mBAAmB,EAA6B,CAC9C,GAAI,GAAW,KACf,OAAS,GAAI,EAAY,MAAQ,EAAG,EAAI,KAAK,UAAU,OAAQ,IAAK,CAClE,GAAM,GAAK,KAAK,UAAU,GAC1B,GAAI,EAAG,UAAW,CAChB,EAAW,EACX,OAGJ,AAAI,GACF,KAAK,eAAe,GAIxB,uBAAuB,EAA6B,CAClD,GAAI,GAAW,KACf,OAAS,GAAI,EAAY,MAAQ,EAAG,EAAI,GAAI,IAAK,CAC/C,GAAM,GAAK,KAAK,UAAU,GAC1B,GAAI,EAAG,UAAW,CAChB,EAAW,EACX,OAGJ,AAAI,GACF,KAAK,eAAe,GAIxB,qBAAqB,EAA6B,CAChD,AAAI,EAAY,eACd,KAAK,eAAe,EAAY,eAIpC,qBAA4B,CAC1B,KAAK,eAAiB,KAAK,eAAe,KAAK,eAGjD,oBAA2B,CACzB,KAAK,cAAgB,KAAK,eAAe,KAAK,cAGhD,YAAY,EAA6B,CA/I3C,MAgJI,OAAW,KAAM,MAAK,GAAG,iBAAiB,0BACxC,AAAI,IAAO,EAAY,IAClB,OAAG,qBAAH,cAAuB,SAAS,EAAY,MAC/C,EAAG,aAAa,gBAAiB,UAGrC,OAAW,KAAM,MAAK,GAAG,iBAAiB,mBACxC,AAAI,IAAO,EAAY,IACrB,EAAG,aAAa,gBAAiB,SAGrC,EAAY,GAAG,aAAa,gBAAiB,QAC7C,KAAK,yBACL,KAAK,eAAe,EAAa,IAGnC,eAAe,EAA0B,CACvC,GAAI,GAA+B,EACnC,KAAO,GACL,AAAI,EAAY,cACd,EAAY,GAAG,aAAa,gBAAiB,QAE/C,EAAc,EAAY,cAE5B,KAAK,yBAGP,sBAAsB,EAA6B,CACjD,OAAW,KAAM,MAAK,UACpB,AAAI,EAAG,gBAAkB,EAAY,eAAiB,EAAG,cACvD,KAAK,eAAe,GAK1B,iBAAiB,EAA6B,CAC5C,GAAI,GAAgB,KAEpB,AAAI,EAAY,aACd,EAAgB,EAEhB,EAAgB,EAAY,cAG1B,GACF,GAAc,GAAG,aAAa,gBAAiB,SAC/C,KAAK,yBACL,KAAK,eAAe,IAIxB,yBAAyB,EAAuB,EAAoB,CAClE,GAAI,GAAe,EACnB,EAAO,EAAK,cAGZ,EAAQ,EAAY,MAAQ,EACxB,IAAU,KAAK,UAAU,QAC3B,GAAQ,GAIV,EAAQ,KAAK,mBAAmB,EAAO,GAGnC,IAAU,IACZ,GAAQ,KAAK,mBAAmB,EAAG,IAIjC,EAAQ,IACV,KAAK,eAAe,KAAK,UAAU,IAI/B,eAAgB,CACtB,GAAM,GAAY,CAAC,EAAiB,IAA2B,CAC7D,GAAI,GAAK,EACL,EAAO,EAAG,kBACd,KAAO,GACL,AAAI,GAAK,UAAY,KAAO,EAAK,UAAY,SAC3C,GAAK,GAAI,GAAS,EAAM,KAAM,GAC9B,KAAK,UAAU,KAAK,GACpB,KAAK,WAAW,KAAK,EAAG,MAAM,UAAU,EAAG,GAAG,gBAE5C,EAAK,mBACP,EAAU,EAAM,GAElB,EAAO,EAAK,oBAGhB,EAAU,KAAK,GAAmB,MAClC,KAAK,UAAU,IAAI,CAAC,EAAI,IAAS,EAAG,MAAQ,GAGtC,wBAA+B,CACrC,KAAK,cAAgB,KAAK,UAAU,GAEpC,OAAW,KAAM,MAAK,UAAW,CAC/B,GAAI,GAAS,EAAG,cAEhB,IADA,EAAG,UAAY,GACR,GAAU,EAAO,KAAO,KAAK,IAClC,AAAK,EAAO,cACV,GAAG,UAAY,IAEjB,EAAS,EAAO,cAElB,AAAI,EAAG,WACL,MAAK,aAAe,IAKlB,eAAe,EAAoB,EAAU,GAAM,CACzD,EAAS,GAAG,SAAW,EACnB,GACF,EAAS,GAAG,QAEd,OAAW,KAAM,MAAK,UACpB,AAAI,IAAO,GACT,GAAG,GAAG,SAAW,IAKf,mBAAmB,EAAoB,EAAsB,CACnE,OAAS,GAAI,EAAY,EAAI,KAAK,WAAW,OAAQ,IACnD,GAAI,KAAK,UAAU,GAAG,WAAa,IAAS,KAAK,WAAW,GAC1D,MAAO,GAGX,MAAO,KAIX,OAAe,CAYb,YAAY,EAAiB,EAA4B,EAAwB,CAnSnF,cAoSI,EAAG,SAAW,GACd,KAAK,GAAK,EACV,KAAK,cAAgB,EACrB,KAAK,MAAQ,QAAG,cAAH,cAAgB,SAAhB,OAA0B,GACvC,KAAK,KAAO,EACZ,KAAK,MAAS,mBAAO,QAAS,GAAK,EACnC,KAAK,MAAQ,EAEb,GAAM,GAAS,EAAG,cAClB,AAAI,kBAAQ,QAAQ,iBAAkB,MACpC,YAAQ,aAAa,OAAQ,SAE/B,EAAG,aAAa,aAAc,KAAK,MAAQ,IACvC,EAAG,aAAa,eAClB,MAAK,MAAQ,uBAAI,aAAa,gBAAjB,cAAgC,SAAhC,OAA0C,IAGzD,KAAK,aAAe,GACpB,KAAK,UAAY,GACjB,KAAK,UAAY,CAAC,CAAC,EAEnB,GAAI,GAAO,EAAG,mBACd,KAAO,GAAM,CACX,GAAI,EAAK,QAAQ,eAAiB,KAAM,CACtC,GAAM,GAAU,GAAG,oBAAO,QAAP,OAAgB,gBAAgB,KAAK,QAAQ,QAAQ,UAAW,KACnF,EAAG,aAAa,YAAa,GAC7B,EAAG,aAAa,gBAAiB,SACjC,EAAK,aAAa,OAAQ,SAC1B,EAAK,aAAa,KAAM,GACxB,KAAK,aAAe,GACpB,MAGF,EAAO,EAAK,mBAEd,KAAK,OAGC,MAAO,CACb,KAAK,GAAG,SAAW,GACd,KAAK,GAAG,aAAa,SACxB,KAAK,GAAG,aAAa,OAAQ,YAE/B,KAAK,GAAG,iBAAiB,UAAW,KAAK,cAAc,KAAK,OAC5D,KAAK,GAAG,iBAAiB,QAAS,KAAK,YAAY,KAAK,OACxD,KAAK,GAAG,iBAAiB,QAAS,KAAK,YAAY,KAAK,OACxD,KAAK,GAAG,iBAAiB,OAAQ,KAAK,WAAW,KAAK,OAGxD,YAAa,CACX,MAAI,MAAK,aACA,KAAK,GAAG,aAAa,mBAAqB,OAG5C,GAGT,YAAa,CACX,MAAO,MAAK,GAAG,aAAa,mBAAqB,OAG3C,YAAY,EAAmB,CAErC,AAAI,EAAM,SAAW,KAAK,IAAM,EAAM,SAAW,KAAK,GAAG,mBAGrD,MAAK,cACP,CAAI,KAAK,cAAgB,KAAK,aAC5B,KAAK,KAAK,iBAAiB,MAE3B,KAAK,KAAK,eAAe,MAE3B,EAAM,mBAER,KAAK,KAAK,YAAY,OAGhB,aAAc,CAjXxB,MAkXI,GAAI,GAAK,KAAK,GACd,AAAI,KAAK,cACP,GAAM,KAAG,oBAAH,OAAwC,GAEhD,EAAG,UAAU,IAAI,SAGX,YAAa,CAzXvB,MA0XI,GAAI,GAAK,KAAK,GACd,AAAI,KAAK,cACP,GAAM,KAAG,oBAAH,OAAwC,GAEhD,EAAG,UAAU,OAAO,SAGd,cAAc,EAAsB,CAC1C,GAAI,EAAM,QAAU,EAAM,SAAW,EAAM,QACzC,OAGF,GAAI,GAAW,GACf,OAAQ,EAAM,SACP,QACA,QACH,AAAI,KAAK,aACP,CAAI,KAAK,cAAgB,KAAK,aAC5B,KAAK,KAAK,iBAAiB,MAE3B,KAAK,KAAK,eAAe,MAE3B,EAAW,IAEX,EAAM,kBAER,KAAK,KAAK,YAAY,MACtB,UAEG,UACH,KAAK,KAAK,uBAAuB,MACjC,EAAW,GACX,UAEG,YACH,KAAK,KAAK,mBAAmB,MAC7B,EAAW,GACX,UAEG,aACH,AAAI,KAAK,cACP,CAAI,KAAK,aACP,KAAK,KAAK,mBAAmB,MAE7B,KAAK,KAAK,eAAe,OAG7B,EAAW,GACX,UAEG,YACH,AAAI,KAAK,cAAgB,KAAK,aAC5B,MAAK,KAAK,iBAAiB,MAC3B,EAAW,IAEP,KAAK,WACP,MAAK,KAAK,qBAAqB,MAC/B,EAAW,IAGf,UAEG,OACH,KAAK,KAAK,sBACV,EAAW,GACX,UAEG,MACH,KAAK,KAAK,qBACV,EAAW,GACX,cAGA,AAAI,EAAM,IAAI,SAAW,GAAK,EAAM,IAAI,MAAM,OAC5C,CAAI,EAAM,KAAO,IACf,KAAK,KAAK,sBAAsB,MAEhC,KAAK,KAAK,yBAAyB,KAAM,EAAM,KAEjD,EAAW,IAEb,MAGJ,AAAI,GACF,GAAM,kBACN,EAAM,oBAMZ,WAAqD,EAAS,EAAc,CAC1E,GAAI,GACJ,MAAO,IAAI,IAAwB,CACjC,GAAM,GAAQ,IAAM,CAClB,EAAU,KACV,EAAK,GAAG,IAEV,AAAI,GACF,aAAa,GAEf,EAAU,WAAW,EAAO,IChehC,AAoBO,WAAoC,CAQzC,YAAoB,EAAiC,EAAsC,CAAvE,aAAiC,iBAmDrD,oBAAiB,IAAY,CAC3B,KAAK,QAAQ,IAAI,GAAK,EAAE,aAAa,gBAAiB,SACtD,KAAK,UAGC,sBAAmB,IAAM,CAC/B,KAAK,QAAQ,IAAI,GAAK,EAAE,aAAa,gBAAiB,UACtD,KAAK,UAGC,YAAS,IAAM,CACrB,KAAK,qBACL,WAAW,IAAM,KAAK,uBA9DtB,KAAK,KAAO,MAAM,KAAK,EAAM,iBAAsC,yBACnE,KAAK,QAAU,MAAM,KAAK,KAAK,MAAM,iBAAiB,oBACtD,KAAK,gBACL,KAAK,uBACL,KAAK,SAOC,eAAgB,CACtB,OAAW,KAAK,CAAC,qBAAsB,uBAAwB,WAC7D,KAAK,MAAM,iBAAiB,IAAI,MAAM,QAAQ,GAAK,CA1CzD,MA2CQ,EAAE,aAAa,EAAE,QAAQ,QAAS,IAAK,KAAE,aAAa,KAAf,OAAqB,IAC5D,EAAE,gBAAgB,KAKhB,sBAAuB,CAjDjC,MAkDI,KAAK,KAAK,QAAQ,GAAK,CACrB,EAAE,iBAAiB,QAAS,GAAK,CAC/B,KAAK,kBAAkB,OAG3B,QAAK,YAAL,QAAgB,iBAAiB,QAAS,IAAM,CAC9C,KAAK,mBAGP,SAAS,iBAAiB,UAAW,GAAK,CACxC,AAAK,GAAE,SAAW,EAAE,UAAY,EAAE,MAAQ,KACxC,KAAK,mBAKH,kBAAkB,EAAe,CACvC,GAAI,GAAS,EAAE,cACf,AAAK,kBAAQ,aAAa,mBACxB,GAAS,KAAK,MAAM,cAClB,yBAAyB,iBAAQ,aAAa,uBAGlD,GAAM,GAAa,kBAAQ,aAAa,oBAAqB,OAC7D,WAAQ,aAAa,gBAAiB,EAAa,QAAU,QAC7D,EAAE,kBACF,KAAK,SAkBC,oBAAqB,CAC3B,KAAK,KAAK,IAAI,GAAK,CA/FvB,MAgGM,GAAM,GAAa,kBAAG,aAAa,oBAAqB,OAClD,EAAS,oBAAG,aAAa,mBAAhB,cAAkC,UAAU,MAAM,KACjE,WAAQ,IAAI,GAAM,CAChB,GAAM,GAAS,SAAS,eAAe,GAAG,KAC1C,AAAI,EACF,YAAQ,UAAU,IAAI,WACtB,WAAQ,UAAU,OAAO,WAEzB,YAAQ,UAAU,IAAI,UACtB,WAAQ,UAAU,OAAO,gBAMzB,oBAAqB,CAC3B,GAAI,CAAC,KAAK,UAAW,OACrB,AAAI,KAAK,KAAK,KAAK,GAAK,EAAE,aAAa,mBACrC,MAAK,UAAU,MAAM,QAAU,SAGjC,AADsB,KAAK,QAAQ,KAAK,GAAM,EAAG,aAAa,mBAAqB,SAEjF,MAAK,UAAU,UAAY,aAC3B,KAAK,UAAU,QAAU,KAAK,gBAE9B,MAAK,UAAU,UAAY,eAC3B,KAAK,UAAU,QAAU,KAAK,oBCpHpC,IACA,IAEA,GAAM,GAAc,SAAS,cAAgC,uBAC7D,GAAI,EAAa,CACf,GAAM,GAAQ,GAAI,GAChB,EACA,SAAS,cAAiC,6BAG5C,AAAI,OAAO,SAAS,OAAO,SAAS,uBAClC,EAAM,iBAIV,GAAM,GAAS,SAAS,cAA2B,YACnD,GAAI,EAAQ,CACV,GAAM,GAAW,GAAI,GAAkB,GACjC,EAAS,EAAc,GACvB,EAAY,SAAS,cAAc,qBACzC,AAAI,GAAa,EAAU,mBACzB,YAAW,aAAa,EAAQ,EAAU,oBAExC,EAAO,mBACT,GAAI,GAAoB,EAAO,mBAOnC,GAAM,GAAS,SAAS,cAAc,cAChC,EAAgB,SAAS,cAAc,qBACvC,EAAgB,SAAS,cAAc,qBACvC,EAAe,SAAS,iBAAiB,oBACzC,EAAiB,SAAS,cAAc,sBACxC,EAAkB,SAAS,cAAiC,wBAClE,AAAI,GAAU,GAAiB,GAAiB,EAAa,QAAU,GACjE,QAAO,SAAS,KAAK,SAAS,WAChC,IAEF,WAAiB,iBAAiB,SAAU,GAAK,CAC/C,AAAK,EAAE,OAA6B,MAAM,WAAW,YACnD,MAGJ,EAAa,QAAQ,GACnB,EAAG,iBAAiB,QAAS,GAAK,CAChC,EAAE,iBACF,IACA,EAAO,oBAGX,EAAe,iBAAiB,QAAS,GAAK,CAC5C,EAAE,iBACF,EAAO,UAAU,OAAO,wBACpB,EAAa,IACf,EAAa,GAAG,eAAe,CAAE,MAAO,aAG5C,EAAc,iBAAiB,QAAS,IAAM,CAC5C,MAEF,EAAc,iBAAiB,QAAS,IAAM,CAC5C,MAEF,EAAc,iBAAiB,QAAS,IAAM,CAC5C,MAEF,SAAS,iBAAiB,UAAW,GAAK,CACxC,AAAK,GAAE,SAAW,EAAE,UAAY,EAAE,MAAQ,KACxC,OASN,YAAwB,CACtB,QAAQ,aAAa,KAAM,GAAI,GAAG,SAAS,2BAC3C,WAAQ,UAAU,IAAI,wBAQxB,YAAgC,CAhGhC,MAiGE,GAAI,CAAC,SAAS,KAAM,OACpB,GAAM,GAAU,SAAS,eAAe,SAAS,KAAK,MAAM,IACtD,EAAc,oBAAS,gBAAT,cAAwB,cAC5C,AAAI,kBAAa,YAAa,WAC5B,GAAY,KAAO,IAGvB,IACA,OAAO,iBAAiB,aAAc,IAAM,KAK5C,SAAS,iBAAiB,0BAA0B,QAAQ,GAAM,CAChE,EAAG,iBAAiB,SAAU,GAAK,CACjC,OAAO,SAAS,OAAS,SAAU,EAAE,OAA6B",
"names": []
}