@restless-dreams/orbit 0.0.0-stage → 0.1.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.
Files changed (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +165 -2
  3. package/dist/bin/orbit.js +8907 -0
  4. package/dist/bin/orbit.js.map +48 -0
  5. package/dist/chunk-0gwh723s.js +408 -0
  6. package/dist/chunk-0gwh723s.js.map +10 -0
  7. package/dist/chunk-7n00wx0t.js +82 -0
  8. package/dist/chunk-7n00wx0t.js.map +10 -0
  9. package/dist/chunk-mtrnm0yc.js +16993 -0
  10. package/dist/chunk-mtrnm0yc.js.map +63 -0
  11. package/dist/core/auto-render.d.ts +85 -0
  12. package/dist/core/browser.d.ts +23 -0
  13. package/dist/core/create.d.ts +23 -0
  14. package/dist/core/diagnostics.d.ts +40 -0
  15. package/dist/core/dispatch.d.ts +23 -0
  16. package/dist/core/document-options.d.ts +18 -0
  17. package/dist/core/document-source.d.ts +128 -0
  18. package/dist/core/editing.d.ts +63 -0
  19. package/dist/core/engine/animation-clock.d.ts +40 -0
  20. package/dist/core/engine/camera.d.ts +70 -0
  21. package/dist/core/engine/colors.d.ts +51 -0
  22. package/dist/core/engine/display.d.ts +125 -0
  23. package/dist/core/engine/export.d.ts +32 -0
  24. package/dist/core/engine/glide.d.ts +34 -0
  25. package/dist/core/engine/labels.d.ts +106 -0
  26. package/dist/core/engine/node-drag.d.ts +49 -0
  27. package/dist/core/engine/scene.d.ts +159 -0
  28. package/dist/core/engine/spin.d.ts +62 -0
  29. package/dist/core/engine/surface-pattern.d.ts +20 -0
  30. package/dist/core/engine/text-measure.d.ts +116 -0
  31. package/dist/core/engine/views.d.ts +353 -0
  32. package/dist/core/extensions.d.ts +155 -0
  33. package/dist/core/format-upgrades.d.ts +33 -0
  34. package/dist/core/index.d.ts +36 -0
  35. package/dist/core/input-controller.d.ts +109 -0
  36. package/dist/core/languages.d.ts +199 -0
  37. package/dist/core/layout.d.ts +61 -0
  38. package/dist/core/map-tools/definitions.d.ts +71 -0
  39. package/dist/core/map-tools/input.d.ts +62 -0
  40. package/dist/core/map-tools/reading.d.ts +40 -0
  41. package/dist/core/map-tools/tools.d.ts +51 -0
  42. package/dist/core/markdown-writing.d.ts +87 -0
  43. package/dist/core/material.d.ts +25 -0
  44. package/dist/core/media.d.ts +42 -0
  45. package/dist/core/node-attributes.d.ts +31 -0
  46. package/dist/core/node-links.d.ts +25 -0
  47. package/dist/core/parser-markdown.d.ts +42 -0
  48. package/dist/core/parser-yaml.d.ts +8 -0
  49. package/dist/core/render-to-svg.d.ts +57 -0
  50. package/dist/core/serializer-markdown.d.ts +18 -0
  51. package/dist/core/serializer-yaml.d.ts +2 -0
  52. package/dist/core/source-patch.d.ts +24 -0
  53. package/dist/core/source.d.ts +27 -0
  54. package/dist/core/styles.d.ts +6 -0
  55. package/dist/core/suggest.d.ts +8 -0
  56. package/dist/core/svg-renderer.d.ts +729 -0
  57. package/dist/core/text-layout.d.ts +54 -0
  58. package/dist/core/themes.d.ts +62 -0
  59. package/dist/core/types.d.ts +463 -0
  60. package/dist/core/ui/actions.d.ts +75 -0
  61. package/dist/core/ui/controls.d.ts +61 -0
  62. package/dist/core/ui/detail-sheet.d.ts +88 -0
  63. package/dist/core/ui/frames.d.ts +11 -0
  64. package/dist/core/ui/icons.d.ts +14 -0
  65. package/dist/core/ui/inline-editor.d.ts +79 -0
  66. package/dist/core/ui/media-players.d.ts +65 -0
  67. package/dist/core/ui/media-viewer.d.ts +169 -0
  68. package/dist/core/ui/media-zoom.d.ts +51 -0
  69. package/dist/core/ui/note-markdown.d.ts +19 -0
  70. package/dist/core/ui/outline.d.ts +44 -0
  71. package/dist/core/url-guard.d.ts +40 -0
  72. package/dist/core/utils.d.ts +23 -0
  73. package/dist/core/web-page/page.d.ts +58 -0
  74. package/dist/core/web-page/runtime.d.ts +13 -0
  75. package/dist/core/web-page/start.d.ts +1 -0
  76. package/dist/core/yaml-mini.d.ts +54 -0
  77. package/dist/index.d.ts +1 -0
  78. package/dist/index.js +1448 -0
  79. package/dist/index.js.map +17 -0
  80. package/dist/marked/index.d.ts +31 -0
  81. package/dist/marked/index.js +110 -0
  82. package/dist/marked/index.js.map +10 -0
  83. package/dist/react/index.d.ts +55 -0
  84. package/dist/react/index.js +352 -0
  85. package/dist/react/index.js.map +1 -0
  86. package/dist/web-page.d.ts +2 -0
  87. package/dist/web-page.js +130 -0
  88. package/llms-full.txt +2585 -0
  89. package/llms.txt +35 -0
  90. package/package.json +118 -4
  91. package/skills/orbit/SKILL.md +140 -0
  92. package/skills/orbit/references/editing.md +194 -0
  93. package/skills/orbit/references/extending.md +247 -0
  94. package/skills/orbit/references/format.md +303 -0
  95. package/skills/orbit/references/guide.md +522 -0
  96. package/skills/orbit/references/languages.md +159 -0
  97. package/skills/orbit/references/map-tools.md +188 -0
  98. package/skills/orbit/references/media.md +160 -0
  99. package/skills/orbit/references/recipes.md +227 -0
  100. package/skills/orbit/references/theming.md +184 -0
@@ -0,0 +1,17 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/serializer-yaml.ts", "../src/core/create.ts", "../src/core/web-page/page.ts", "../src/core/map-tools/input.ts", "../src/core/map-tools/definitions.ts", "../src/core/map-tools/reading.ts", "../src/core/map-tools/tools.ts", "../src/core/material.ts"],
4
+ "sourcesContent": [
5
+ "import type { OrbitDocument, OrbitNode } from './types.js';\nimport { assignKey, emitYaml, type YamlValue } from './yaml-mini.js';\nimport { nodesWithExplicitIds } from './utils.js';\nimport { mediaExtras } from './node-attributes.js';\n\nexport const serializeOrbitYAML = (doc: OrbitDocument): string => {\n const out: Record<string, YamlValue> = {};\n const opts = doc.options;\n\n if (opts.title) {\n out.title = opts.title;\n }\n\n if (opts.theme) {\n out.theme = opts.theme;\n }\n\n if (opts.viewMode) {\n out.view = opts.viewMode;\n }\n\n if (opts.showRings !== undefined) {\n out.showRings = opts.showRings;\n }\n\n if (opts.interactive !== undefined) {\n out.interactive = opts.interactive;\n }\n\n if (opts.orbitAnimation !== undefined) {\n out.animation = opts.orbitAnimation;\n }\n\n if (opts.orbitSpeed !== undefined) {\n out.speed = opts.orbitSpeed;\n }\n\n if (opts.palette) {\n out.palette = opts.palette as YamlValue;\n }\n\n if (opts.height !== undefined) {\n out.height = opts.height;\n }\n\n if (opts.maxDepth !== undefined) {\n out.maxDepth = opts.maxDepth;\n }\n\n if (opts.className) {\n out.className = opts.className;\n }\n\n if (opts.baseUrl) {\n out.baseUrl = opts.baseUrl;\n }\n\n if (opts.schemaVersion !== undefined) {\n out.schemaVersion = opts.schemaVersion;\n }\n\n // Keys Orbit doesn't read, after its own: as they were written.\n for (const [key, value] of Object.entries(doc.extra ?? {})) {\n if (!Object.prototype.hasOwnProperty.call(out, key) && key !== 'nodes') {\n assignKey(out, key, value as YamlValue);\n }\n }\n\n out.nodes = [serializeNode(doc.root, nodesWithExplicitIds(doc.root))];\n return emitYaml(out);\n};\n\nconst serializeNode = (n: OrbitNode, explicitIds: ReadonlySet<OrbitNode>): YamlValue => {\n const obj: Record<string, YamlValue> = { text: n.text };\n\n if (explicitIds.has(n)) {\n obj.id = n.id;\n }\n\n if (n.icon) {\n obj.icon = n.icon;\n }\n\n if (n.color) {\n obj.color = n.color;\n }\n\n if (n.type) {\n obj.type = n.typeVersion === undefined ? n.type : `${n.type}@${n.typeVersion}`;\n }\n\n if (n.link) {\n obj.link = n.link;\n }\n\n if (n.tags) {\n obj.tags = n.tags;\n }\n\n if (n.status) {\n obj.status = n.status;\n }\n\n if (n.priority !== undefined) {\n obj.priority = n.priority;\n }\n\n if (n.collapsed !== undefined) {\n obj.collapsed = n.collapsed;\n }\n\n // A picture, video or embed keeps the fields Orbit doesn't read.\n if (n.image) {\n obj.image = { ...mediaExtras(n.image), ...n.image } as unknown as YamlValue;\n }\n\n if (n.video) {\n obj.video = { ...mediaExtras(n.video), ...n.video } as unknown as YamlValue;\n }\n\n if (n.embed) {\n obj.embed = { ...mediaExtras(n.embed), ...n.embed } as unknown as YamlValue;\n }\n\n if (n.note) {\n obj.note = n.note;\n\n if (n.noteFormat && n.noteFormat !== 'markdown') {\n obj.noteFormat = n.noteFormat;\n }\n }\n\n if (n.attrs) {\n for (const [k, v] of Object.entries(n.attrs)) {\n // A value Orbit couldn't read for one of its own attributes is written back, unless one was set since:\n // it reads back the same way. Keys a node map reads as structure (its\n // text, its children) are never written from attrs: they would reparse\n // as real structure.\n if (!RESERVED_NODE_KEYS.has(k) && !Object.prototype.hasOwnProperty.call(obj, k)) {\n assignKey(obj, k, v as YamlValue);\n }\n }\n }\n\n if (n.children.length) {\n obj.children = n.children.map((child) => serializeNode(child, explicitIds));\n }\n\n return obj;\n};\n\n/** Keys `buildNode` reads as the node's structure: a value under them would become a title or children. */\nconst RESERVED_NODE_KEYS = new Set(['text', 'children']);\n",
6
+ "import { OrbitSVGRenderer } from './svg-renderer.js';\nimport { parseOrbit } from './dispatch.js';\nimport { reportParseDiagnostics } from './diagnostics.js';\nimport { wordsFor } from './languages.js';\nimport type { OrbitDocument, OrbitNode, RendererOptions } from './types.js';\n\nexport interface CreateOrbitMapOptions extends RendererOptions {\n /** Throw on the first problem in the source instead of working around it. */\n strict?: boolean;\n}\n\n/**\n * Draws a map into `target` in one call: markdown or YAML source, a parsed\n * document or a node tree. Returns the renderer, to listen for events\n * (`renderer.on('focus-change', …)`), draw new versions (`renderer.render(source)`)\n * and clean up (`renderer.destroy()`).\n *\n * The map fills `target`, so give it a height.\n *\n * @example\n * ```ts\n * import { createOrbitMap } from '@restless-dreams/orbit';\n *\n * const map = createOrbitMap(document.querySelector('#map')!, '# Launch\\n## Research\\n## Build', { theme: 'auto' });\n * map.on('focus-change', ({ node }) => console.log(node.text));\n * ```\n */\nexport const createOrbitMap = (\n target: HTMLElement,\n source: string | OrbitDocument | OrbitNode,\n options: CreateOrbitMapOptions = {},\n): OrbitSVGRenderer => {\n const { strict, ...rendererOptions } = options;\n const renderer = new OrbitSVGRenderer(target, rendererOptions);\n\n if (typeof source === 'string') {\n const doc = parseOrbit(source, { strict, untitled: wordsFor(rendererOptions.language, target, rendererOptions.strings).text('untitledMap') });\n reportParseDiagnostics(doc);\n renderer.render(doc);\n } else {\n renderer.render(source);\n }\n\n return renderer;\n};\n",
7
+ "/**\n * A map as a web page: one HTML file with Orbit, the map and its pictures\n * inside, which opens in any browser, offline. Readers explore it with\n * Orbit's own controls, or present it: one idea at a time, in reading order,\n * with its note as a caption (see runtime.ts, the page's script).\n */\n\nimport { parseOrbit } from '../dispatch.js';\nimport { serializeOrbitMarkdown } from '../serializer-markdown.js';\nimport { OrbitWords, type OrbitStrings } from '../languages.js';\nimport { expandTheme, isOrbitThemePreset, themeTokens, type OrbitThemeTokens } from '../themes.js';\nimport type { OrbitDocument, OrbitRendererTheme, ViewMode } from '../types.js';\n\nexport interface OrbitWebPageOptions {\n /**\n * Orbit's web page script, the file `@restless-dreams/orbit/web-page.js`,\n * as text. It goes inside the page, so the page needs nothing else.\n */\n script: string;\n\n /** The page's title. Default: the map's `title`, or its root's text. */\n title?: string;\n\n /** The map's theme, instead of its frontmatter's: a theme name or `{ preset, tokens }`. */\n theme?: string | OrbitRendererTheme;\n\n /** How the map opens: `focus` (default) or `all`, the overview. */\n viewMode?: ViewMode;\n\n /** The node in focus when the map opens, by id. Default: the root. */\n focus?: string;\n\n /** The language of the page and the map's words: a tag like `es`. Default: English. */\n language?: string;\n\n /** Single words to change: `{ present: 'Show' }`. */\n strings?: Partial<OrbitStrings>;\n\n /**\n * Pictures to put inside the page, by the address the map gives them:\n * `{ 'photos/summit.jpg': 'data:image/jpeg;base64,…' }`. A node's picture,\n * a video's thumbnail and pictures in notes are swapped for them, so they\n * show wherever the page goes.\n */\n media?: Record<string, string>;\n}\n\n/** Orbit's logo, the page's icon. */\nconst ORBIT_ICON = \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='18 18 72 72'%3E%3Cdefs%3E%3CradialGradient id='d' gradientUnits='userSpaceOnUse' cx='32.4' cy='23.76' r='102.6'%3E%3Cstop offset='0' stop-color='%234A35A8'/%3E%3Cstop offset='1' stop-color='%2318134A'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect x='18' y='18' width='72' height='72' rx='16' fill='url(%23d)'/%3E%3Cpath d='M67.53,35.36 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M69.84,37.38 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M71.86,39.69 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M76.52,57.07 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M75.92,60.08 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M74.93,62.99 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M62.21,75.71 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M59.3,76.7 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M56.29,77.3 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M38.91,72.64 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M36.6,70.62 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M34.58,68.31 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M29.92,50.93 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M30.52,47.92 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M31.51,45.01 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M44.23,32.29 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M47.14,31.3 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M50.15,30.7 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z' fill='%23E2E6FF' fill-opacity='.5'/%3E%3Ccircle cx='54' cy='54' r='11' fill='%23FAD86F'/%3E%3Ccircle cx='60.08' cy='31.3' r='6.4' fill='%23FF9E96'/%3E%3Ccircle cx='76.7' cy='47.92' r='6.4' fill='%23F8B478'/%3E%3Ccircle cx='70.62' cy='70.62' r='6.4' fill='%237FDAAB'/%3E%3Ccircle cx='47.92' cy='76.7' r='6.4' fill='%2386CDFF'/%3E%3Ccircle cx='31.3' cy='60.08' r='6.4' fill='%23C9B1FE'/%3E%3Ccircle cx='37.38' cy='37.38' r='6.4' fill='%23F7A3D4'/%3E%3C/svg%3E\";\n\n/** What a web page carries for its script, as JSON in `#orbit-page`. */\nexport interface WebPageData {\n /** The map, in markdown or YAML. */\n source: string;\n\n theme?: string | OrbitRendererTheme;\n viewMode?: ViewMode;\n focus?: string;\n language?: string;\n strings?: Partial<OrbitStrings>;\n media: Record<string, string>;\n}\n\n/**\n * The map as one HTML page, with Orbit inside (`options.script`): open it in\n * any browser, offline, to explore the map or present it.\n *\n * ```ts\n * import { readFileSync } from 'node:fs';\n * import { exportWebPage } from '@restless-dreams/orbit';\n *\n * const script = readFileSync(new URL(import.meta.resolve('@restless-dreams/orbit/web-page.js')), 'utf8');\n * const html = exportWebPage(markdown, { script, theme: 'night' });\n * ```\n */\nexport const exportWebPage = (input: string | OrbitDocument, options: OrbitWebPageOptions): string => {\n const document = typeof input === 'string' ? parseOrbit(input) : input;\n const source = typeof input === 'string' ? input : serializeOrbitMarkdown(input);\n const words = new OrbitWords(options.language, options.strings);\n const title = options.title ?? (document.options.title || document.root.text || 'Orbit');\n const data: WebPageData = {\n source,\n theme: options.theme,\n viewMode: options.viewMode,\n focus: options.focus,\n language: options.language,\n strings: options.strings,\n media: options.media ?? {},\n };\n const theme = options.theme ?? document.options.theme;\n return `<!doctype html>\n<html lang=\"${escapeAttribute(words.locale)}\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n<meta name=\"generator\" content=\"Orbit\">\n<link rel=\"icon\" href=\"${ORBIT_ICON}\">\n<title>${escapeText(title)}</title>\n<style>\n${pageStyles(theme)}\n</style>\n</head>\n<body>\n<div class=\"page\" id=\"page\">\n <div class=\"page__map\" id=\"page-map\" aria-label=\"${escapeAttribute(title)}\"></div>\n <button class=\"page__present\" type=\"button\" data-present><span aria-hidden=\"true\">▶</span> ${escapeText(words.text('present'))}</button>\n <section class=\"page__caption\" id=\"page-caption\" aria-live=\"polite\" hidden>\n <h1 class=\"page__title\" id=\"page-title\"></h1>\n <div class=\"page__note\" id=\"page-note\"></div>\n </section>\n <nav class=\"page__controls\" id=\"page-controls\" hidden>\n <button class=\"page__button\" type=\"button\" data-step=\"-1\" aria-label=\"${escapeAttribute(words.text('previous'))}\">‹</button>\n <span class=\"page__count\" id=\"page-count\"></span>\n <button class=\"page__button\" type=\"button\" data-step=\"1\" aria-label=\"${escapeAttribute(words.text('next'))}\">›</button>\n <button class=\"page__button\" type=\"button\" data-close aria-label=\"${escapeAttribute(words.text('close'))}\">✕</button>\n </nav>\n</div>\n<script type=\"application/json\" id=\"orbit-page\">${scriptJson(data)}</script>\n<script type=\"application/json\" id=\"orbit-script\">${scriptJson(options.script)}</script>\n<script>\n // Orbit runs from a script element made here: text inside one is never read as HTML.\n (function () {\n var script = document.createElement('script');\n script.textContent = JSON.parse(document.getElementById('orbit-script').textContent);\n document.body.appendChild(script);\n })();\n</script>\n</body>\n</html>\n`;\n};\n\n/** The colors the page takes from the theme: its background, and the caption's, from the detail sheet's. */\nconst pageColors = (tokens: OrbitThemeTokens): string => {\n const surface = tokens.surface === 'transparent' ? '#ffffff' : tokens.surface;\n return [\n `--page-background: ${surface};`,\n `--page-card: ${tokens['sheet-background']};`,\n `--page-text: ${tokens['sheet-text']};`,\n `--page-muted: ${tokens['sheet-muted-text']};`,\n `--page-border: ${tokens['sheet-border']};`,\n `--page-shadow: ${tokens['sheet-shadow']};`,\n ].join(' ');\n};\n\n/** The tokens a theme option stands for: a built-in theme's, with the option's own on top. */\nconst tokensOf = (theme: string | OrbitRendererTheme | undefined): OrbitThemeTokens => {\n const expanded = expandTheme(theme);\n const preset = typeof expanded === 'string' ? expanded : expanded?.preset;\n const base = themeTokens(isOrbitThemePreset(preset) ? preset : 'paper');\n return typeof expanded === 'object' && expanded?.tokens ? { ...base, ...expanded.tokens } as OrbitThemeTokens : base;\n};\n\nconst pageStyles = (theme: string | OrbitRendererTheme | undefined): string => {\n const automatic = (typeof theme === 'string' ? theme : theme?.preset) === 'auto';\n const colors = automatic\n ? `:root { ${pageColors(themeTokens('paper'))} }\\n@media (prefers-color-scheme: dark) { :root { ${pageColors(themeTokens('night'))} } }`\n : `:root { ${pageColors(tokensOf(theme))} }`;\n return `${colors}\nhtml, body { margin: 0; height: 100%; background: var(--page-background); }\nbody { font: 16px/1.5 system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif; color: var(--page-text); }\n.page__map { position: fixed; inset: 0; }\n.page__present, .page__controls {\n position: fixed; left: 50%; bottom: max(16px, env(safe-area-inset-bottom)); transform: translateX(-50%);\n display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 18px; border: 1px solid var(--page-border);\n border-radius: 22px; background: var(--page-card); color: var(--page-text); box-shadow: var(--page-shadow); font: inherit; font-weight: 600;\n}\n.page__present { cursor: pointer; }\n.page__controls { padding: 0 6px; transition: opacity 200ms ease; }\n.page__button { min-width: 44px; min-height: 44px; border: 0; border-radius: 22px; background: none; color: inherit; font: inherit; font-size: 20px; cursor: pointer; }\n.page__button:focus-visible, .page__present:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.page__count { min-width: 4em; text-align: center; color: var(--page-muted); font-variant-numeric: tabular-nums; }\n.page__caption {\n position: fixed; left: 50%; bottom: calc(max(16px, env(safe-area-inset-bottom)) + 60px); transform: translateX(-50%);\n box-sizing: border-box; width: min(720px, calc(100% - 32px)); max-height: 40vh; overflow: auto; padding: 16px 20px;\n border: 1px solid var(--page-border); border-radius: 16px; background: var(--page-card); color: var(--page-text); box-shadow: var(--page-shadow);\n}\n.page__title { margin: 0; font-size: 20px; line-height: 1.3; }\n.page__note:not(:empty) { margin-top: 8px; }\n.page__note p { margin: 0 0 8px; }\n.page__note img { max-width: 100%; border-radius: 8px; }\n.page__note a { color: inherit; }\n.page--presenting .page__present { display: none; }\n.page--presenting:not(.page--controls) .page__controls { opacity: 0; }\n.page--presenting:not(.page--controls) { cursor: none; }\n[hidden] { display: none !important; }`;\n};\n\n/** JSON inside a script element: `<` written as `\\\\u003c`, so nothing in it can end the element or open a comment. */\nconst scriptJson = (value: unknown): string => {\n return JSON.stringify(value).replace(/</g, '\\\\u003c').replace(/\\u2028/g, '\\\\u2028').replace(/\\u2029/g, '\\\\u2029');\n};\n\nconst escapeText = (text: string): string => {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n};\n\nconst escapeAttribute = (text: string): string => {\n return escapeText(text).replace(/\"/g, '&quot;');\n};\n",
8
+ "/**\n * What each map tool takes, written once: as the JSON Schema a model reads,\n * and as the checks a call goes through before anything changes. The checks\n * forgive what models often send (a number as text, a list as words\n * separated by commas, null for a field they leave out, a field's usual\n * other name) and explain the rest in words a model can act on.\n */\n\nimport { suggest } from '../suggest.js';\n\nexport type FieldType = 'string' | 'integer' | 'number' | 'boolean' | 'list' | 'record';\n\nexport interface Field {\n type: FieldType;\n description: string;\n required?: boolean;\n\n /** The words a list takes. */\n values?: readonly string[];\n\n /** The smallest number it takes. */\n minimum?: number;\n\n /** A record's own fields. Text alone stands for the first one: a picture's address for `{ src }`. */\n fields?: Fields;\n}\n\nexport type Fields = Record<string, Field>;\n\n/** A property of a tool's input, as JSON Schema. */\nexport type MapToolProperty = {\n type: 'string' | 'integer' | 'number' | 'boolean' | 'array' | 'object';\n description: string;\n minimum?: number;\n items?: { type: 'string'; enum?: string[] };\n properties?: Record<string, MapToolProperty>;\n required?: string[];\n};\n\n/** A tool's input, as JSON Schema: an object with the tool's fields. */\nexport type MapToolSchema = {\n type: 'object';\n properties: Record<string, MapToolProperty>;\n required?: string[];\n};\n\n/** The JSON Schema for an object with `fields`. */\nexport const schemaOf = (fields: Fields): MapToolSchema => {\n const required = Object.keys(fields).filter((name) => fields[name].required);\n return {\n type: 'object',\n properties: Object.fromEntries(Object.entries(fields).map(([name, field]) => [name, propertyOf(field)])),\n ...(required.length > 0 ? { required } : {}),\n };\n};\n\nconst propertyOf = (field: Field): MapToolProperty => {\n if (field.type === 'list') {\n return { type: 'array', description: field.description, items: field.values ? { type: 'string', enum: [...field.values] } : { type: 'string' } };\n }\n\n if (field.type === 'record') {\n return { ...schemaOf(field.fields ?? {}), description: field.description };\n }\n\n return { type: field.type, description: field.description, ...(field.minimum === undefined ? {} : { minimum: field.minimum }) };\n};\n\n/** A call's input, read: its values, and the fields it gave that the tool doesn't take, which were left out. */\nexport interface ReadInput {\n values: Record<string, unknown>;\n ignored: string[];\n}\n\n/** Thrown with a message for the model when a call's input can't be used. */\nexport class InputError extends Error {}\n\n/**\n * Reads a call's input for `tool`: an object, or the JSON text of one, as\n * OpenAI sends it. Null stands for a field left out. A field under another\n * name it often goes by (`synonyms`) counts as that field; one that looks\n * like a misspelled field is an error, so nothing changes by mistake; any\n * other is left out, and reported.\n */\nexport const readInput = (tool: string, fields: Fields, input: unknown, synonyms: Readonly<Record<string, string>> = {}): ReadInput => {\n const record = inputRecord(tool, fields, input);\n const values: Record<string, unknown> = {};\n const ignored: string[] = [];\n const names = Object.keys(fields);\n\n for (const [given, value] of Object.entries(record)) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const name = owns(fields, given) ? given : synonymOf(given, names, synonyms);\n\n if (name === undefined) {\n const near = suggest(given, names);\n\n if (near !== undefined) {\n throw new InputError(`${tool} has no field \"${given}\". Did you mean \"${near}\"? It takes ${list(names)}.`);\n }\n\n ignored.push(given);\n continue;\n }\n\n if (owns(values, name)) {\n throw new InputError(`${tool} got ${name} twice, as \"${name}\" and as \"${given}\": give it once.`);\n }\n\n values[name] = readValue(name, fields[name], value);\n }\n\n for (const name of names) {\n if (fields[name].required && !owns(values, name)) {\n throw new InputError(`${tool} needs ${name}: ${lowerFirst(fields[name].description)}`);\n }\n }\n\n return { values, ignored };\n};\n\nconst inputRecord = (tool: string, fields: Fields, input: unknown): Record<string, unknown> => {\n let value = input;\n\n if (typeof value === 'string') {\n if (value.trim() === '') {\n return {};\n }\n\n try {\n value = JSON.parse(value);\n } catch (error) {\n throw new InputError(`${tool}'s input isn't valid JSON (${(error as Error).message}). Send an object, like ${example(fields)}.`);\n }\n }\n\n if (value === null || value === undefined) {\n return {};\n }\n\n if (typeof value !== 'object' || Array.isArray(value)) {\n throw new InputError(`${tool} takes an object, like ${example(fields)}, not ${describe(value)}.`);\n }\n\n return value as Record<string, unknown>;\n};\n\n/** The field `given` names in another case, or under another name it often goes by. */\nconst synonymOf = (given: string, names: readonly string[], synonyms: Readonly<Record<string, string>>): string | undefined => {\n const lowered = given.toLowerCase();\n return names.find((name) => name.toLowerCase() === lowered) ?? (owns(synonyms, lowered) ? synonyms[lowered] : undefined);\n};\n\n/** Whether `record` has `key` of its own, not one every object inherits, such as `constructor`. */\nexport const owns = (record: object, key: string): boolean => {\n return Object.prototype.hasOwnProperty.call(record, key);\n};\n\nconst readValue = (name: string, field: Field, value: unknown): unknown => {\n switch (field.type) {\n case 'string':\n if (typeof value === 'string') {\n return value;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n\n throw new InputError(`${name} takes text, not ${describe(value)}.`);\n case 'integer':\n case 'number': {\n const number = typeof value === 'number' ? value : typeof value === 'string' && value.trim() !== '' ? Number(value) : Number.NaN;\n\n if (!Number.isFinite(number) || (field.type === 'integer' && !Number.isInteger(number))) {\n throw new InputError(`${name} takes ${field.type === 'integer' ? 'a whole number' : 'a number'}, like ${field.minimum ?? 1}, not ${describe(value)}.`);\n }\n\n if (field.minimum !== undefined && number < field.minimum) {\n throw new InputError(`${name} takes ${field.minimum} or more, not ${number}. ${field.description}`);\n }\n\n return number;\n }\n case 'boolean': {\n const word = typeof value === 'string' ? value.trim().toLowerCase() : value;\n\n if (word === true || word === 'true' || word === 'yes') {\n return true;\n }\n\n if (word === false || word === 'false' || word === 'no') {\n return false;\n }\n\n throw new InputError(`${name} takes true or false, not ${describe(value)}.`);\n }\n case 'list': {\n const items = Array.isArray(value) ? value : typeof value === 'string' ? (value.trim() === '' ? [] : value.split(',')) : null;\n\n if (!items || items.some((item) => typeof item !== 'string' && typeof item !== 'number')) {\n throw new InputError(`${name} takes a list of words, like [\"${field.values?.[0] ?? 'design'}\"], not ${describe(value)}.`);\n }\n\n const words = items.map((item) => String(item).trim()).filter((item) => item !== '');\n\n for (const word of words) {\n if (field.values && !field.values.includes(word)) {\n const near = suggest(word, field.values);\n throw new InputError(`${name} can't take \"${word}\".${near === undefined ? '' : ` Did you mean \"${near}\"?`} It takes ${list(field.values)}.`);\n }\n }\n\n return words;\n }\n case 'record': {\n const fields = field.fields ?? {};\n const first = Object.keys(fields)[0];\n\n if (typeof value === 'string') {\n return { [first]: value };\n }\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new InputError(`${name} takes an object, like {\"${first}\": \"…\"}, not ${describe(value)}.`);\n }\n\n return readInput(name, fields, value).values;\n }\n }\n};\n\n/** A value, as an error message names it. */\nexport const describe = (value: unknown): string => {\n if (value === null) {\n return 'null';\n }\n\n if (Array.isArray(value)) {\n return 'a list';\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}…` : value);\n }\n\n if (typeof value === 'object') {\n return 'an object';\n }\n\n return String(value);\n};\n\n/** \"a, b and c\" */\nexport const list = (words: readonly string[]): string => {\n return words.length <= 1 ? words.join('') : `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`;\n};\n\nconst example = (fields: Fields): string => {\n const name = Object.keys(fields).find((key) => fields[key].required) ?? Object.keys(fields)[0];\n return name === undefined ? '{}' : `{\"${name}\": \"…\"}`;\n};\n\nconst lowerFirst = (text: string): string => {\n return text.charAt(0).toLowerCase() + text.slice(1);\n};\n",
9
+ "/**\n * The map tools as a model sees them: names, descriptions and inputs, and\n * the shapes each provider's API takes them in.\n */\n\nimport { schemaOf, type Fields, type MapToolSchema } from './input.js';\n\nexport type MapToolName =\n | 'read_map'\n | 'find_nodes'\n | 'read_node'\n | 'add_nodes'\n | 'update_node'\n | 'move_node'\n | 'reorder_children'\n | 'remove_node'\n | 'show_node';\n\n/** A tool as `MapTools.definitions` lists it: the shape MCP uses, and the data to build any other. */\nexport type MapToolDefinition = {\n name: MapToolName;\n description: string;\n\n /** The tool's input, as JSON Schema. */\n inputSchema: MapToolSchema;\n\n /** Hints for clients that ask before running some tools: whether it only reads, and whether it can remove or overwrite what's there. */\n annotations: { readOnlyHint: boolean; destructiveHint: boolean };\n};\n\n/** The tools in the shape each provider's API takes them. */\nexport type MapToolFormats = {\n /** Anthropic's Messages API (`tools`). */\n anthropic: { name: string; description: string; input_schema: MapToolSchema }[];\n\n /** OpenAI's Responses API (`tools`). */\n openai: { type: 'function'; name: string; description: string; parameters: MapToolSchema; strict: false }[];\n\n /** OpenAI's Chat Completions API (`tools`), which most other providers and local servers take too. */\n 'openai-chat': { type: 'function'; function: { name: string; description: string; parameters: MapToolSchema } }[];\n\n /** Google's Gemini API (`config.tools` in `@google/genai`). */\n gemini: { functionDeclarations: { name: string; description: string; parametersJsonSchema: MapToolSchema }[] }[];\n};\n\nexport type MapToolProvider = keyof MapToolFormats;\n\nconst PROVIDERS: readonly MapToolProvider[] = ['anthropic', 'openai', 'openai-chat', 'gemini'];\n\n/** A tool, before it's written as a definition. */\nexport interface ToolSpec {\n name: MapToolName;\n description: string;\n fields: Fields;\n\n /** Other names models give its fields, lowercase. */\n synonyms?: Record<string, string>;\n\n readOnly: boolean;\n destructive: boolean;\n}\n\n/** The attributes `update_node` sets and `clear` removes. */\nexport const ATTRIBUTES = ['note', 'status', 'priority', 'tags', 'icon', 'color', 'link', 'image', 'video', 'embed', 'collapsed'] as const;\n\nexport type ToolAttribute = (typeof ATTRIBUTES)[number];\n\nconst NODE_ID = 'node_id';\nconst NODE_SYNONYMS = { id: NODE_ID, node: NODE_ID, nodeid: NODE_ID };\n\n/** Every tool, in the order they're offered. `show_node` is only for a map on screen. */\nexport const TOOL_SPECS: readonly ToolSpec[] = [\n {\n name: 'read_map',\n description: 'Read the mind map as an outline: a line for each node (an idea), indented under its parent, with its id after a #, its attributes in parentheses, and the start of its note on the next line after >. Read it before changing the map: the other tools take these ids. A big map is cut short: read a branch with node_id, or search with find_nodes.',\n fields: {\n node_id: { type: 'string', description: 'Read only this node and the nodes under it. Leave out to read the whole map.' },\n depth: { type: 'integer', minimum: 1, description: 'How many levels under it to read: 1 for its children only. Leave out to read them all.' },\n },\n synonyms: NODE_SYNONYMS,\n readOnly: true,\n destructive: false,\n },\n {\n name: 'find_nodes',\n description: 'Search the map for nodes by the words in their titles, notes and tags, by status or by tag. Returns each match with its id and where it is in the map.',\n fields: {\n query: { type: 'string', description: 'Words to look for, in any case, with or without accents. A node matches when it has every word.' },\n status: { type: 'string', description: 'Only nodes with this status. todo, active, done and blocked also find the words that mean the same, such as planned, in progress, shipped or stuck.' },\n tag: { type: 'string', description: 'Only nodes with this tag.' },\n },\n synonyms: { text: 'query', search: 'query', words: 'query', tags: 'tag' },\n readOnly: true,\n destructive: false,\n },\n {\n name: 'read_node',\n description: 'Read everything about one node: its title, its whole note, its attributes, its picture, video or embedded page, where it is in the map, its children, and the nodes that link to it.',\n fields: {\n node_id: { type: 'string', required: true, description: 'The node to read, by the id read_map or find_nodes gave.' },\n },\n synonyms: NODE_SYNONYMS,\n readOnly: true,\n destructive: false,\n },\n {\n name: 'add_nodes',\n description: 'Add nodes under a node: one, several, or whole branches at once, written as a markdown list. Each item is a node, items indented under it are its children, at any depth, and indented lines under an item that aren\\'t items are its note. On an item\\'s line, [ ], [/] or [x] first sets its status to todo, active or done, an emoji first sets its icon, words after a # at the end are its tags, and <!-- orbit color: tomato, priority: 1 --> at the end sets other attributes. Returns the new nodes with their ids.',\n fields: {\n parent_id: { type: 'string', required: true, description: 'The node to add them under.' },\n outline: { type: 'string', required: true, description: 'The nodes, as a markdown list: \"- Social media\\\\n - Instagram\\\\n- Newsletter\".' },\n index: { type: 'integer', minimum: 0, description: 'Where they go among the children of parent_id: 0 puts them first. Leave out to put them last.' },\n },\n synonyms: { parent: 'parent_id', parentid: 'parent_id', under: 'parent_id', markdown: 'outline', nodes: 'outline', items: 'outline', children: 'outline', text: 'outline', position: 'index' },\n readOnly: false,\n destructive: false,\n },\n {\n name: 'update_node',\n description: 'Change a node\\'s title or attributes. Only the fields you give change; to remove an attribute, name it in clear. A new title can give the node a new id, which the result says.',\n fields: {\n node_id: { type: 'string', required: true, description: 'The node to change.' },\n text: { type: 'string', description: 'Its title: plain text, a few words.' },\n note: { type: 'string', description: 'Its note, in markdown, for details and longer text. Replaces the note it has.' },\n status: { type: 'string', description: 'todo, active, done or blocked, which show a colored dot, or any other word.' },\n priority: { type: 'number', description: 'A number, such as 1 for the most important.' },\n tags: { type: 'list', description: 'All its tags, as words: they replace the ones it has.' },\n icon: { type: 'string', description: 'An emoji shown before its title.' },\n color: { type: 'string', description: 'A CSS color, such as #E8A33D or tomato: its children take shades of it. Nodes without one take the theme\\'s colors, so set it only when asked.' },\n link: { type: 'string', description: 'A web address it links to, or #id to link to another node of the map.' },\n image: {\n type: 'record',\n description: 'A picture shown in the node.',\n fields: {\n src: { type: 'string', required: true, description: 'The picture\\'s address.' },\n alt: { type: 'string', description: 'What the picture shows, for people who can\\'t see it.' },\n caption: { type: 'string', description: 'A caption.' },\n },\n },\n video: {\n type: 'record',\n description: 'A video the node plays.',\n fields: {\n src: { type: 'string', required: true, description: 'The video\\'s address: YouTube, Vimeo or a video file.' },\n caption: { type: 'string', description: 'A caption.' },\n },\n },\n embed: {\n type: 'record',\n description: 'A web page shown in a frame in the node\\'s details.',\n fields: {\n src: { type: 'string', required: true, description: 'The page\\'s address.' },\n caption: { type: 'string', description: 'A caption.' },\n },\n },\n collapsed: { type: 'boolean', description: 'true hides its children until the reader opens it.' },\n clear: { type: 'list', values: ATTRIBUTES, description: 'Attributes to remove, such as [\"status\", \"color\"].' },\n },\n synonyms: {\n ...NODE_SYNONYMS, title: 'text', name: 'text', label: 'text', notes: 'note', description: 'note', details: 'note', state: 'status',\n tag: 'tags', labels: 'tags', emoji: 'icon', colour: 'color', url: 'link', href: 'link', picture: 'image', photo: 'image',\n remove: 'clear', unset: 'clear', delete: 'clear',\n },\n readOnly: false,\n destructive: true,\n },\n {\n name: 'move_node',\n description: 'Move a node, with everything under it, under another node, or to another place among its siblings.',\n fields: {\n node_id: { type: 'string', required: true, description: 'The node to move.' },\n parent_id: { type: 'string', description: 'The node to move it under. Leave out to keep its parent and change only its place.' },\n index: { type: 'integer', minimum: 0, description: 'Its place among the children of its new parent: 0 puts it first. Leave out to put it last.' },\n },\n synonyms: { ...NODE_SYNONYMS, parent: 'parent_id', parentid: 'parent_id', under: 'parent_id', to: 'parent_id', position: 'index' },\n readOnly: false,\n destructive: false,\n },\n {\n name: 'reorder_children',\n description: 'Put the children of a node in a new order, all at once: to sort them, or to group the ones that go together.',\n fields: {\n parent_id: { type: 'string', required: true, description: 'The node whose children to reorder.' },\n order: { type: 'list', required: true, description: 'The ids of all its children, in their new order.' },\n },\n synonyms: { parent: 'parent_id', parentid: 'parent_id', node_id: 'parent_id', id: 'parent_id', ids: 'order', children: 'order', child_ids: 'order' },\n readOnly: false,\n destructive: false,\n },\n {\n name: 'remove_node',\n description: 'Remove a node and everything under it. Remove nodes only when asked to.',\n fields: {\n node_id: { type: 'string', required: true, description: 'The node to remove. The root can\\'t be removed.' },\n },\n synonyms: NODE_SYNONYMS,\n readOnly: false,\n destructive: true,\n },\n {\n name: 'show_node',\n description: 'Show the reader a node: the map flies to it, with its children around it. Use it when they ask to see or go to something, or to show them what you changed.',\n fields: {\n node_id: { type: 'string', required: true, description: 'The node to show.' },\n },\n synonyms: NODE_SYNONYMS,\n readOnly: true,\n destructive: false,\n },\n];\n\nexport const definitionOf = (spec: ToolSpec): MapToolDefinition => {\n return {\n name: spec.name,\n description: spec.description,\n inputSchema: schemaOf(spec.fields),\n annotations: { readOnlyHint: spec.readOnly, destructiveHint: spec.destructive },\n };\n};\n\n/** The definitions in the shape `provider`'s API takes. */\nexport const formatDefinitions = <Provider extends MapToolProvider>(definitions: readonly MapToolDefinition[], provider: Provider): MapToolFormats[Provider] => {\n const tools = definitions.map(({ name, description, inputSchema }) => ({ name, description, schema: structuredCopy(inputSchema) }));\n\n switch (provider as MapToolProvider) {\n case 'anthropic':\n return tools.map(({ name, description, schema }) => ({ name, description, input_schema: schema })) as MapToolFormats[Provider];\n case 'openai':\n // Strict mode would make every field required: models would send each one, and couldn't leave any out.\n return tools.map(({ name, description, schema }) => ({ type: 'function', name, description, parameters: schema, strict: false })) as MapToolFormats[Provider];\n case 'openai-chat':\n return tools.map(({ name, description, schema }) => ({ type: 'function', function: { name, description, parameters: schema } })) as MapToolFormats[Provider];\n case 'gemini':\n return [{ functionDeclarations: tools.map(({ name, description, schema }) => ({ name, description, parametersJsonSchema: schema })) }] as MapToolFormats[Provider];\n default:\n throw new TypeError(`Map tools come in the shapes of ${PROVIDERS.map((name) => `\"${name}\"`).join(', ')}, not ${JSON.stringify(provider)}. For any other, build them from tools.definitions: each has a name, a description and an inputSchema (JSON Schema).`);\n }\n};\n\n/** A copy a caller can change without changing the definitions. */\nconst structuredCopy = <Value>(value: Value): Value => {\n return JSON.parse(JSON.stringify(value)) as Value;\n};\n",
10
+ "/**\n * The map as the tools describe it to a model: an outline with each node's\n * id, everything about one node, and search results. Plain text, short on\n * tokens: a line a node, with what an edit needs to know.\n */\n\nimport type { OrbitNode } from '../types.js';\nimport { findIndexedLinkedNode, indexNodes, nodeLinksOf } from '../node-links.js';\nimport { statusTone } from '../ui/detail-sheet.js';\n\n/** How much of a note an outline shows. */\nconst NOTE_PREVIEW = 100;\n/** How many matches find_nodes lists. */\nconst MATCH_LIMIT = 50;\n\n/** A node as the tools name it in a sentence: its title and id. */\nexport const nameOf = (node: OrbitNode): string => {\n return `\"${node.text}\" #${node.id}`;\n};\n\n/** A node's line in an outline: its title, its id, and its attributes. */\nexport const outlineLine = (node: OrbitNode, depth: number): string => {\n const details = attributesOf(node);\n return `${' '.repeat(depth)}- ${node.text} #${node.id}${details.length > 0 ? ` (${details.join('; ')})` : ''}`;\n};\n\nconst attributesOf = (node: OrbitNode): string[] => {\n const details: string[] = [];\n\n if (node.icon) {\n details.push(`icon: ${node.icon}`);\n }\n\n if (node.status) {\n details.push(`status: ${node.status}`);\n }\n\n if (node.priority !== undefined) {\n details.push(`priority: ${node.priority}`);\n }\n\n if (node.tags && node.tags.length > 0) {\n details.push(`tags: ${node.tags.join(', ')}`);\n }\n\n if (node.color) {\n details.push(`color: ${node.color}`);\n }\n\n if (node.link) {\n details.push(`link: ${node.link}`);\n }\n\n for (const media of ['image', 'video', 'embed'] as const) {\n if (node[media]) {\n details.push(media);\n }\n }\n\n if (node.type) {\n details.push(`type: ${node.type}`);\n }\n\n if (node.collapsed) {\n details.push('collapsed');\n }\n\n return details;\n};\n\n/** The first line of a note, cut short. */\nconst notePreview = (note: string): string => {\n const text = note.trim().replace(/\\s+/g, ' ');\n return text.length > NOTE_PREVIEW ? `${text.slice(0, NOTE_PREVIEW - 1).trimEnd()}…` : text;\n};\n\n/** A node's line, and its note's start under it. */\nconst headOf = (node: OrbitNode, depth: number): string[] => {\n const lines = [outlineLine(node, depth)];\n\n if (node.note?.trim()) {\n lines.push(`${' '.repeat(depth + 1)}> ${notePreview(node.note)}`);\n }\n\n return lines;\n};\n\n/** A node and `levels` levels under it as outline lines; what's further down is counted. */\nexport const outlineOf = (node: OrbitNode, depth = 0, levels = Infinity): string[] => {\n const lines = headOf(node, depth);\n\n if (levels > 0) {\n for (const child of node.children) {\n lines.push(...outlineOf(child, depth + 1, levels - 1));\n }\n } else if (node.children.length > 0) {\n lines.push(`${' '.repeat(depth + 1)}- … ${count(node.children.length, 'child', 'children')}, ${count(descendants(node), 'node')} in all under it`);\n }\n\n return lines;\n};\n\n/**\n * The outline read_map gives: `start` and up to `levels` levels under it,\n * as many whole levels as fit in `limit` nodes, so the shape of a big map\n * shows, with what's left out counted. `complete` when nothing asked for\n * was left out.\n */\nexport const readOutline = (start: OrbitNode, levels: number, limit: number): { lines: string[]; complete: boolean } => {\n let shown = 0;\n let total = 1;\n let level: OrbitNode[] = [start];\n\n while (shown < levels) {\n const next = level.flatMap((node) => node.children);\n\n if (next.length === 0 || total + next.length > limit) {\n break;\n }\n\n total += next.length;\n level = next;\n shown += 1;\n }\n\n const complete = shown === levels || level.every((node) => node.children.length === 0);\n\n if (shown === 0 && !complete) {\n // More children than the limit: as many of them as fit.\n const children = start.children.slice(0, Math.max(1, limit - 1));\n return {\n lines: [\n ...headOf(start, 0),\n ...children.flatMap((child) => outlineOf(child, 1, 0)),\n ` - … ${count(start.children.length - children.length, 'more child', 'more children')} of ${nameOf(start)}`,\n ],\n complete,\n };\n }\n\n return { lines: outlineOf(start, 0, shown), complete };\n};\n\n/** How many nodes are under a node, at any depth. */\nexport const descendants = (node: OrbitNode): number => {\n return node.children.reduce((sum, child) => sum + 1 + descendants(child), 0);\n};\n\n/** \"1 node\", \"3 nodes\" */\nexport const count = (amount: number, one: string, many = `${one}s`): string => {\n return `${amount} ${amount === 1 ? one : many}`;\n};\n\n/** Everything about a node, for read_node. */\nexport const nodeDetails = (root: OrbitNode, node: OrbitNode, path: OrbitNode[]): string => {\n const lines = [nameOf(node)];\n lines.push(path.length > 1 ? `Where: ${path.map((step) => step.text).join(' › ')}` : 'Where: the root of the map');\n const fields: [string, unknown][] = [\n ['Icon', node.icon],\n ['Status', node.status],\n ['Priority', node.priority],\n ['Tags', node.tags && node.tags.length > 0 ? node.tags.join(', ') : undefined],\n ['Color', node.color],\n ['Link', node.link],\n ['Picture', node.image && mediaLine(node.image.src, { alt: node.image.alt, caption: node.image.caption })],\n ['Video', node.video && mediaLine(node.video.src, { caption: node.video.caption })],\n ['Embedded page', node.embed && mediaLine(node.embed.src, { caption: node.embed.caption })],\n ['Type', node.type],\n ['Collapsed', node.collapsed ? 'yes: its children are hidden until the reader opens it' : undefined],\n ];\n\n for (const [label, value] of fields) {\n if (value !== undefined && value !== '') {\n lines.push(`${label}: ${String(value)}`);\n }\n }\n\n const custom = Object.entries(node.attrs ?? {});\n\n if (custom.length > 0) {\n lines.push(`Other attributes: ${custom.map(([key, value]) => `${key}: ${typeof value === 'string' ? value : JSON.stringify(value)}`).join('; ')}`);\n }\n\n lines.push(node.note?.trim() ? `Note${node.noteFormat === 'plain' ? ' (plain text)' : ''}:\\n${node.note.trim()}` : 'Note: none');\n lines.push(node.children.length > 0 ? `Children (${node.children.length}): ${node.children.map(nameOf).join(', ')}` : 'Children: none');\n const linking = nodesLinkingTo(root, node);\n\n if (linking.length > 0) {\n lines.push(`Linked from: ${linking.map(nameOf).join(', ')}`);\n }\n\n return lines.join('\\n');\n};\n\nconst mediaLine = (src: string, extras: Record<string, string | undefined>): string => {\n const described = Object.entries(extras).filter(([, value]) => value).map(([key, value]) => `${key}: ${value}`);\n return described.length > 0 ? `${src} (${described.join('; ')})` : src;\n};\n\n/** The nodes whose link, or a link in whose note, points at `target`. */\nexport const nodesLinkingTo = (root: OrbitNode, target: OrbitNode): OrbitNode[] => {\n const nodes = indexNodes(root);\n const linking: OrbitNode[] = [];\n\n const visit = (node: OrbitNode): void => {\n if (nodeLinksOf(node).some((href) => findIndexedLinkedNode(nodes, href) === target)) {\n linking.push(node);\n }\n\n node.children.forEach(visit);\n };\n\n visit(root);\n return linking;\n};\n\n/** Text as search compares it: lowercase, without accents. */\nexport const searchable = (text: string): string => {\n return text.normalize('NFKD').replace(/\\p{M}+/gu, '').toLowerCase();\n};\n\n/** What find_nodes looks for. */\nexport interface Search {\n query?: string;\n status?: string;\n tag?: string;\n}\n\n/** The nodes that match, titles matching first, as find_nodes lists them. */\nexport const findNodes = (root: OrbitNode, search: Search): string => {\n const words = searchable(search.query ?? '').split(/\\s+/).filter((word) => word !== '');\n const status = search.status === undefined ? undefined : searchable(search.status.trim());\n const tag = search.tag === undefined ? undefined : searchable(search.tag.trim().replace(/^#/, ''));\n\n const statusMatches = (node: OrbitNode): boolean => {\n if (status === undefined) {\n return true;\n }\n\n if (!node.status) {\n return false;\n }\n\n const own = searchable(node.status.trim());\n const tone = statusTone(status);\n return own === status || (tone !== 'neutral' && statusTone(own) === tone);\n };\n\n const matches: { node: OrbitNode; path: OrbitNode[]; inTitle: boolean }[] = [];\n\n const visit = (node: OrbitNode, path: OrbitNode[]): void => {\n const title = searchable([node.text, ...(node.tags ?? [])].join(' '));\n const everything = `${title} ${searchable(node.note ?? '')}`;\n\n if (words.every((word) => everything.includes(word))\n && statusMatches(node)\n && (tag === undefined || (node.tags ?? []).some((own) => searchable(own) === tag))) {\n matches.push({ node, path, inTitle: words.every((word) => title.includes(word)) });\n }\n\n node.children.forEach((child) => visit(child, [...path, node]));\n };\n\n visit(root, []);\n\n if (matches.length === 0) {\n return 'No node matches. Try fewer or other words, or read the map with read_map.';\n }\n\n matches.sort((first, second) => Number(second.inTitle) - Number(first.inTitle));\n const shown = matches.slice(0, MATCH_LIMIT);\n const lines = [`${count(matches.length, 'node matches', 'nodes match')}${matches.length > shown.length ? `; the first ${shown.length}` : ''}:`];\n\n for (const { node, path } of shown) {\n lines.push(`${outlineLine(node, 0)}${path.length > 0 ? ` in ${path.map((step) => step.text).join(' › ')}` : ' (the root)'}`);\n }\n\n if (matches.length > shown.length) {\n lines.push('Narrow the search to see the others.');\n }\n\n return lines.join('\\n');\n};\n",
11
+ "/**\n * Map tools: what a language model needs to read a map and change it, from\n * any provider. The definitions come in each provider's shape, and `run`\n * carries out a call on a map on screen, where each change animates into\n * place and fires `edit` as anyone's would, or on a document without one,\n * on a server. A call that can't be carried out changes nothing and says\n * why, in words a model can act on: the id it meant, a move that can't be\n * made, a value the map can't use.\n */\n\nimport type { OrbitDocument, OrbitNewNode, OrbitNode, OrbitNodeInput } from '../types.js';\nimport type { OrbitSVGRenderer } from '../svg-renderer.js';\nimport { parseOrbit } from '../dispatch.js';\nimport { leadingEmoji, parseOrbitMarkdown } from '../parser-markdown.js';\nimport { formatDiagnostic } from '../diagnostics.js';\nimport { addToTree, moveInTree, newNodeFrom, removeFromTree, updateInTree } from '../editing.js';\nimport { findIndexedLinkedNode, findLinkedNode, indexNodes, isNodeLink, nodeLinksOf } from '../node-links.js';\nimport { findNodeById, getNodePath, nodeSlug } from '../utils.js';\nimport { suggest } from '../suggest.js';\nimport { guardUrl } from '../url-guard.js';\nimport { ATTRIBUTES, definitionOf, formatDefinitions, TOOL_SPECS, type MapToolDefinition, type MapToolFormats, type MapToolName, type MapToolProvider, type ToolAttribute, type ToolSpec } from './definitions.js';\nimport { InputError, list, readInput } from './input.js';\nimport { count, descendants, findNodes, nameOf, nodeDetails, outlineOf, readOutline, searchable, type Search } from './reading.js';\n\n/** How many nodes read_map shows at once, unless `readLimit` says otherwise. */\nconst READ_LIMIT = 250;\n/** Titles longer than this, in characters, get a hint to keep them short. */\nconst LONG_TITLE = 60;\n/** What a CSS color looks like: a hex code, a name, or a color function. Browsers check the rest. */\nconst COLOR_SYNTAX = /^(?:#(?:[\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})|[a-z]+|(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color|color-mix|light-dark|var)\\(.+\\))$/i;\n/** Diagnostics an outline of new nodes always has, or can't judge alone. */\nconst OUTLINE_CODES_LEFT_OUT = new Set(['synthetic-root', 'no-structure', 'unknown-link-target']);\n\nexport interface MapToolsOptions {\n /** Offer only the tools that read the map, for an assistant that answers questions about it. Default false. */\n readOnly?: boolean;\n\n /** The most nodes `read_map` shows at once; a bigger map is cut short, whole levels first. Default 250. */\n readLimit?: number;\n}\n\n/** What a tool call did, to send back to the model. */\nexport interface MapToolResult {\n /** False when the call couldn't be carried out: nothing changed, and `text` says why and what to send instead. */\n ok: boolean;\n\n /** What happened, for the model, with the ids to use next. */\n text: string;\n\n /** Whether the map changed. */\n changed: boolean;\n}\n\n/** Map tools for one map (see `createMapTools`). */\nexport interface MapTools {\n /** The tools: name, description, input as JSON Schema, and hints. The shape MCP takes, and the data for any other. */\n readonly definitions: MapToolDefinition[];\n\n /** How to use the tools, to add to the model's system prompt. */\n readonly instructions: string;\n\n /** The tools in the shape a provider's API takes: `anthropic`, `openai` (Responses), `openai-chat` (Chat Completions, and most other providers) or `gemini`. */\n for<Provider extends MapToolProvider>(provider: Provider): MapToolFormats[Provider];\n\n /**\n * Carries out a tool call: its name, and its input as an object or as\n * the JSON text OpenAI sends. Never throws for a call a model gets wrong:\n * the result says what went wrong instead.\n */\n run(name: string, input?: unknown): MapToolResult;\n\n /** The map as it is now. Edits change it in place. */\n readonly document: OrbitDocument | null;\n}\n\n/** What a map on screen offers the tools: an `OrbitSVGRenderer` has it all. */\ntype LiveMap = Pick<OrbitSVGRenderer, 'getDocument' | 'addNode' | 'updateNode' | 'moveNode' | 'removeNode' | 'flyTo' | 'getFocusedNode' | 'getViewMode'>;\n\n/** What the tools change: a map on screen, through its methods, or a document. */\ninterface Target {\n document(): OrbitDocument | null;\n add(parentId: string, input: OrbitNewNode, index?: number): OrbitNode | null;\n update(id: string, changes: OrbitNodeInput): OrbitNode | null;\n move(id: string, parentId: string, index?: number): OrbitNode | null;\n remove(id: string): OrbitNode | null;\n\n /** A map on screen. */\n live: LiveMap | null;\n\n /** Written for a newer version of the format, so this one could lose what it doesn't read by changing it. */\n newer: boolean;\n}\n\n/** A call that can't be carried out, with what to do instead. */\nclass CallError extends Error {}\n\n/** What a tool did, and what's worth knowing besides. */\ninterface Outcome {\n text: string;\n changed: boolean;\n}\n\n/**\n * Tools a language model calls to read and edit a map: on screen (an\n * `OrbitSVGRenderer`, such as `createOrbitMap` returns or `<orbit-map>`'s\n * `renderer`), where each change animates and fires `edit`, or a document\n * (or its markdown or YAML), which they change in place.\n */\nexport const createMapTools = (map: OrbitSVGRenderer | OrbitDocument | string, options: MapToolsOptions = {}): MapTools => {\n const target = targetOf(map);\n const readLimit = typeof options.readLimit === 'number' && Number.isFinite(options.readLimit) ? Math.max(10, Math.trunc(options.readLimit)) : READ_LIMIT;\n const specs = TOOL_SPECS.filter((spec) => (spec.name !== 'show_node' || target.live !== null) && (spec.readOnly || !options.readOnly));\n const definitions = specs.map(definitionOf);\n // Ids this session changed or removed, so a call with an id from before still finds its node, or says what happened to it.\n const renamed = new Map<string, string>();\n const removed = new Map<string, string>();\n const notes: string[] = [];\n\n /** The node an id names: a node's id, with or without its #, an id from before a rename, or a title only one node has. */\n const resolve = (root: OrbitNode, given: string, field: string): OrbitNode => {\n const id = given.trim().replace(/^#/, '');\n const direct = findNodeById(root, id);\n\n if (direct) {\n return direct;\n }\n\n let current = id;\n const seen = new Set<string>();\n\n while (renamed.has(current) && !seen.has(current)) {\n seen.add(current);\n current = renamed.get(current)!;\n }\n\n const followed = current === id ? null : findNodeById(root, current);\n\n if (followed) {\n notes.push(`#${id} is ${nameOf(followed)} now.`);\n return followed;\n }\n\n if (removed.has(id)) {\n throw new CallError(`${field} names #${id}, but \"${removed.get(id)}\" was removed.`);\n }\n\n const wanted = searchable(id);\n const titled = allNodes(root).filter((node) => searchable(node.text.trim()) === wanted || node.id === nodeSlug(id));\n\n if (titled.length === 1) {\n notes.push(`${field} takes ids: the id of \"${titled[0].text}\" is #${titled[0].id}.`);\n return titled[0];\n }\n\n if (titled.length > 1) {\n throw new CallError(`${titled.length} nodes are called \"${given}\": ${titled.map((node) => `${nameOf(node)}${node.parent ? ` under \"${node.parent.text}\"` : ''}`).join(', ')}. Give ${field} one of their ids.`);\n }\n\n const near = suggest(id, allNodes(root).map((node) => node.id));\n const nearNode = near === undefined ? null : findNodeById(root, near);\n throw new CallError(`No node has the id \"${id}\".${nearNode ? ` Did you mean ${nameOf(nearNode)}?` : ''} read_map and find_nodes give every node's id.`);\n };\n\n const calls: Record<MapToolName, (values: Record<string, unknown>, root: OrbitNode, document: OrbitDocument) => Outcome> = {\n read_map: (values, root, document) => {\n const start = typeof values.node_id === 'string' ? resolve(root, values.node_id, 'node_id') : root;\n const levels = typeof values.depth === 'number' ? values.depth : Infinity;\n const { lines, complete } = readOutline(start, levels, readLimit);\n const header: string[] = [];\n\n if (start === root) {\n const title = document.options.title ?? root.text;\n header.push(`The map \"${title}\" has ${count(1 + descendants(root), 'node')}.`);\n } else {\n const path = getNodePath(root, start.id);\n header.push(`${nameOf(start)}, in ${path.slice(0, -1).map((node) => node.text).join(' › ')}, has ${count(descendants(start), 'node')} under it.`);\n }\n\n const live = target.live;\n\n if (live) {\n const focused = live.getFocusedNode();\n header.push(live.getViewMode() === 'all' || !focused ? 'The reader is looking at the whole map.' : `The reader is looking at ${nameOf(focused)}.`);\n }\n\n const footer = complete ? [] : ['Nodes further down aren\\'t shown: read a branch with read_map and its node_id, or search with find_nodes.'];\n return { text: [header.join(' '), ...lines, ...footer].join('\\n'), changed: false };\n },\n\n find_nodes: (values, root) => {\n if (values.query === undefined && values.status === undefined && values.tag === undefined) {\n throw new CallError('find_nodes needs something to look for: query, status, tag, or more than one.');\n }\n\n return { text: findNodes(root, values as Search), changed: false };\n },\n\n read_node: (values, root) => {\n const node = resolve(root, values.node_id as string, 'node_id');\n return { text: nodeDetails(root, node, getNodePath(root, node.id)), changed: false };\n },\n\n add_nodes: (values, root) => {\n const parent = resolve(root, values.parent_id as string, 'parent_id');\n const nodes = readNewNodes(values.outline as string);\n const index = values.index as number | undefined;\n const added: OrbitNode[] = [];\n\n nodes.forEach((input, offset) => {\n const node = target.add(parent.id, input, index === undefined ? undefined : index + offset);\n\n if (node) {\n added.push(node);\n }\n });\n\n if (added.length === 0) {\n throw new CallError(`Nothing could be added under ${nameOf(parent)}.`);\n }\n\n for (const node of added) {\n const twin = parent.children.find((sibling) => sibling !== node && !added.includes(sibling) && searchable(sibling.text) === searchable(node.text));\n\n if (twin) {\n notes.push(`${nameOf(node)} has the same title as ${nameOf(twin)} beside it. If it's there twice by mistake, remove one with remove_node.`);\n }\n }\n\n const all = added.flatMap(allNodes);\n const long = all.filter((node) => node.text.length > LONG_TITLE);\n\n if (long.length > 0) {\n notes.push(`${long.map(nameOf).join(', ')} ${long.length === 1 ? 'has a long title' : 'have long titles'}: a few words read best on the map, with the rest in the note.`);\n }\n\n notes.push(...brokenLinks(target.document()?.root ?? root, all));\n return {\n text: [`Added ${count(all.length, 'node')} under ${nameOf(parent)}${placeOf(added, parent)}:`, ...added.flatMap((node) => outlineOf(node))].join('\\n'),\n changed: added.length > 0,\n };\n },\n\n update_node: (values, root) => {\n const node = resolve(root, values.node_id as string, 'node_id');\n const previousId = node.id;\n const { changes, set, cleared, absent } = readChanges(values, root, node);\n\n if (set.length === 0 && cleared.length === 0) {\n if (absent.length === 0) {\n throw new CallError(`update_node needs something to change: ${list(['text', ...ATTRIBUTES])}, or clear to remove attributes.`);\n }\n\n return { text: `${nameOf(node)} has no ${list(absent)} to remove: nothing changed.`, changed: false };\n }\n\n const updated = target.update(node.id, changes);\n\n if (!updated) {\n throw new CallError(`${nameOf(node)} couldn't be changed.`);\n }\n\n if (changes.note !== undefined) {\n notes.push(...brokenLinks(root, [updated]));\n }\n\n const described = [set.length > 0 ? `set its ${list(set)}` : '', cleared.length > 0 ? `removed its ${list(cleared)}` : ''].filter((part) => part !== '').join('; ');\n let text = `Changed ${nameOf(updated)}: ${described}.`;\n\n if (updated.id !== previousId) {\n renamed.set(previousId, updated.id);\n text += ` Its id is #${updated.id} now: it was #${previousId}.`;\n }\n\n return { text, changed: true };\n },\n\n move_node: (values, root) => {\n const node = resolve(root, values.node_id as string, 'node_id');\n\n if (values.parent_id === undefined && values.index === undefined) {\n throw new CallError('move_node needs where to move the node: parent_id, index, or both.');\n }\n\n const path = getNodePath(root, node.id);\n\n if (path.length < 2) {\n throw new CallError(`${nameOf(node)} is the root: it can't move, as every other node is under it.`);\n }\n\n const parent = values.parent_id === undefined ? path[path.length - 2] : resolve(root, values.parent_id as string, 'parent_id');\n\n if (parent === node) {\n throw new CallError(`${nameOf(node)} can't go under itself. Give parent_id another node.`);\n }\n\n if (getNodePath(root, parent.id).includes(node)) {\n throw new CallError(`${nameOf(node)} can't go under ${nameOf(parent)}, which is inside it. Move ${nameOf(parent)} out of it first, or choose another parent.`);\n }\n\n const under = descendants(node);\n const moved = target.move(node.id, parent.id, values.index as number | undefined);\n\n if (!moved) {\n throw new CallError(`${nameOf(node)} couldn't be moved.`);\n }\n\n return { text: `Moved ${nameOf(moved)}${under > 0 ? `, with the ${count(under, 'node')} under it,` : ''} under ${nameOf(parent)}${placeOf([moved], parent)}.`, changed: true };\n },\n\n reorder_children: (values, root) => {\n const parent = resolve(root, values.parent_id as string, 'parent_id');\n const children = [...parent.children];\n\n if (children.length === 0) {\n throw new CallError(`${nameOf(parent)} has no children to reorder.`);\n }\n\n const order = (values.order as string[]).map((given) => childNamed(parent, given));\n const twice = order.find((child, position) => order.indexOf(child) !== position);\n\n if (twice) {\n throw new CallError(`order lists ${nameOf(twice)} twice: list each child once.`);\n }\n\n const missing = children.filter((child) => !order.includes(child));\n\n if (missing.length > 0) {\n throw new CallError(`order needs all ${children.length} children of ${nameOf(parent)}, and leaves out ${missing.map(nameOf).join(', ')}.`);\n }\n\n if (order.every((child, position) => children[position] === child)) {\n return { text: `The children of ${nameOf(parent)} are in that order already.`, changed: false };\n }\n\n order.forEach((child, position) => {\n const current = findNodeById(target.document()?.root ?? root, parent.id) ?? parent;\n\n if (current.children[position]?.id !== child.id) {\n target.move(child.id, parent.id, position);\n }\n });\n\n return { text: `The children of ${nameOf(parent)} are in this order now: ${order.map(nameOf).join(', ')}.`, changed: true };\n },\n\n remove_node: (values, root) => {\n const node = resolve(root, values.node_id as string, 'node_id');\n\n if (node === root) {\n throw new CallError(`${nameOf(node)} is the root, and the map is all under it: it can't be removed. Remove the nodes under it one by one, or give it a new title with update_node.`);\n }\n\n const gone = allNodes(node);\n\n if (!target.remove(node.id)) {\n throw new CallError(`${nameOf(node)} couldn't be removed.`);\n }\n\n for (const each of gone) {\n removed.set(each.id, each.text);\n }\n\n return { text: `Removed ${nameOf(node)}${gone.length > 1 ? ` and the ${count(gone.length - 1, 'node')} under it` : ''}.`, changed: true };\n },\n\n show_node: (values, root) => {\n const node = resolve(root, values.node_id as string, 'node_id');\n target.live?.flyTo(node.id);\n return { text: `The map shows ${nameOf(node)} now, with its children around it.`, changed: false };\n },\n };\n\n /** The child of `parent` that `given` names. */\n const childNamed = (parent: OrbitNode, given: string): OrbitNode => {\n const id = given.trim().replace(/^#/, '');\n const child = parent.children.find((each) => each.id === id || each.id === renamed.get(id))\n ?? parent.children.find((each) => searchable(each.text.trim()) === searchable(id));\n\n if (!child) {\n throw new CallError(`${given} isn't a child of ${nameOf(parent)}. Its children: ${parent.children.map(nameOf).join(', ')}.`);\n }\n\n return child;\n };\n\n const run = (name: string, input?: unknown): MapToolResult => {\n notes.length = 0;\n const spec = TOOL_SPECS.find((each) => each.name === name);\n const offered = specs.find((each) => each.name === name);\n\n if (!offered) {\n if (spec?.name === 'show_node') {\n return failure('show_node only works on a map on screen.');\n }\n\n if (spec) {\n return failure(`${name} isn't available: this map can only be read.`);\n }\n\n const near = suggest(String(name), specs.map((each) => each.name));\n return failure(`There's no tool \"${String(name)}\".${near === undefined ? '' : ` Did you mean ${near}?`} The tools are ${list(specs.map((each) => each.name))}.`);\n }\n\n const document = target.document();\n\n if (!document) {\n return failure('There\\'s no map to read yet: it hasn\\'t been drawn.');\n }\n\n if (!offered.readOnly && target.newer) {\n return failure('This map was written for a newer version of Orbit, and changing it here could lose what this version doesn\\'t read. It can be read, but not changed.');\n }\n\n try {\n const { values, ignored } = readInput(offered.name, offered.fields, input, offered.synonyms);\n const outcome = calls[offered.name](values, document.root, document);\n\n if (ignored.length > 0) {\n notes.push(`${offered.name} doesn't take ${list(ignored.map((key) => `\"${key}\"`))}, so ${ignored.length === 1 ? 'it was' : 'they were'} left out. It takes ${list(Object.keys(offered.fields))}.`);\n }\n\n return { ok: true, text: [outcome.text, ...notes.map((note) => `Note: ${note}`)].join('\\n'), changed: outcome.changed };\n } catch (error) {\n if (error instanceof CallError || error instanceof InputError) {\n return failure(error.message, offered);\n }\n\n throw error;\n }\n };\n\n return {\n definitions,\n instructions: instructionsFor(target.live !== null, options.readOnly === true),\n for: (provider) => formatDefinitions(definitions, provider),\n run,\n get document() {\n return target.document();\n },\n };\n};\n\nconst failure = (message: string, spec?: ToolSpec): MapToolResult => {\n return { ok: false, text: spec && !spec.readOnly ? `${message} Nothing changed.` : message, changed: false };\n};\n\nconst targetOf = (map: OrbitSVGRenderer | OrbitDocument | string): Target => {\n if (isLiveMap(map)) {\n return {\n document: () => map.getDocument(),\n add: (parentId, input, index) => map.addNode(parentId, input, index),\n update: (id, changes) => map.updateNode(id, changes),\n move: (id, parentId, index) => map.moveNode(id, parentId, index),\n remove: (id) => map.removeNode(id),\n live: map,\n newer: false,\n };\n }\n\n const document = typeof map === 'string' ? parseOrbit(map) : map;\n\n if (!document || typeof document !== 'object' || !document.root || !Array.isArray(document.root.children)) {\n throw new TypeError(`createMapTools() takes a map on screen (createOrbitMap's result, or <orbit-map>'s renderer), a parsed document, or a map's markdown or YAML, but got ${map === null ? 'null' : typeof map}.`);\n }\n\n return {\n document: () => document,\n add: (parentId, input, index) => addToTree(document.root, parentId, input, index)?.node ?? null,\n update: (id, changes) => updateInTree(document.root, id, changes)?.node ?? null,\n move: (id, parentId, index) => moveInTree(document.root, id, parentId, index)?.node ?? null,\n remove: (id) => removeFromTree(document.root, id)?.node ?? null,\n live: null,\n newer: (document.diagnostics ?? []).some((diagnostic) => diagnostic.code === 'unsupported-schema-version'),\n };\n};\n\nconst isLiveMap = (map: unknown): map is LiveMap => {\n const candidate = map as Partial<LiveMap> | null;\n return typeof candidate === 'object' && candidate !== null && typeof candidate.getDocument === 'function' && typeof candidate.addNode === 'function';\n};\n\n/** The text for the system prompt. */\nconst instructionsFor = (live: boolean, readOnly: boolean): string => {\n const lines = readOnly\n ? [\n 'You can read the mind map with the map tools. Each node is an idea, with an id.',\n '- read_map shows the map as an outline, with every node\\'s id; find_nodes searches a big one, and read_node shows everything about one node, its whole note included.',\n '- Answer from what the map says, and say when it doesn\\'t say.',\n ]\n : [\n 'You can read and change the mind map with the map tools. Each node is an idea, with an id.',\n '- Read the map before you change it: read_map shows it as an outline with every node\\'s id, and find_nodes searches a big one. The other tools take those ids.',\n '- Keep titles to a few words, and put details and longer text in the note.',\n '- Write in the language the map is written in.',\n '- Add several nodes, or whole branches, with one add_nodes call.',\n '- A new title can give a node a new id: use the ids the latest results give.',\n '- Remove nodes only when asked to.',\n ];\n\n if (live) {\n lines.push(readOnly ? '- show_node takes the reader to a node.' : '- The reader sees each change on the map as you make it, and show_node takes them to a node.');\n }\n\n return lines.join('\\n');\n};\n\n/** Every node from `root` down, in reading order. */\nconst allNodes = (root: OrbitNode): OrbitNode[] => {\n return [root, ...root.children.flatMap(allNodes)];\n};\n\n/** Where `nodes`, siblings in a row, are among their parent's children, as a result says it: after the one before them, or first. */\nconst placeOf = (nodes: OrbitNode[], parent: OrbitNode): string => {\n const first = parent.children.indexOf(nodes[0]);\n const last = parent.children.indexOf(nodes[nodes.length - 1]);\n\n if (first > 0) {\n return `, after ${nameOf(parent.children[first - 1])}`;\n }\n\n if (first === 0 && last < parent.children.length - 1) {\n return `, first, before ${nameOf(parent.children[last + 1])}`;\n }\n\n return '';\n};\n\n/** The `#id` links of `nodes` that point at no node, with the id they probably meant. */\nconst brokenLinks = (root: OrbitNode, nodes: OrbitNode[]): string[] => {\n const index = indexNodes(root);\n const ids = [...index.keys()];\n\n return nodes.flatMap((node) => nodeLinksOf(node)\n .filter((href) => !findIndexedLinkedNode(index, href))\n .map((href) => {\n const near = suggest(href.slice(1), ids);\n return `${nameOf(node)} links to ${href}, but no node has that id.${near === undefined ? '' : ` Did you mean #${near}?`}`;\n }));\n};\n\n/**\n * The nodes an outline lists, read as orbit-md: a list, headings, or lines\n * of plain text, a node each. An outline that doesn't read cleanly, such as\n * a misspelled attribute, adds nothing: the error says what to fix.\n */\nconst readNewNodes = (outline: string): OrbitNewNode[] => {\n let source = outline.replace(/\\r\\n?/g, '\\n');\n\n if (/^\\s*---\\s*\\n/.test(source)) {\n throw new CallError('outline takes the nodes to add as a markdown list, without frontmatter.');\n }\n\n let document = parseOrbitMarkdown(source);\n\n if (document.diagnostics.some((diagnostic) => diagnostic.code === 'no-structure')) {\n source = source.split('\\n').map((line) => line.trim()).filter((line) => line !== '').map((line) => `- ${line}`).join('\\n');\n document = parseOrbitMarkdown(source);\n }\n\n const roots = document.diagnostics.some((diagnostic) => diagnostic.code === 'synthetic-root') ? document.root.children : [document.root];\n const untitled = roots.flatMap(allNodes).find((node) => node.text.trim() === '');\n\n if (roots.length === 0 || untitled) {\n throw new CallError(untitled?.source\n ? `Line ${untitled.source.line} of outline has an item without a title.`\n : 'outline has no nodes: write them as a markdown list, like \"- Social media\\\\n- Newsletter\".');\n }\n\n // Nothing is kept from an outline with problems, so the parser's \"kept as written\" doesn't apply.\n const problems = document.diagnostics\n .filter((diagnostic) => !OUTLINE_CODES_LEFT_OUT.has(diagnostic.code))\n .map((diagnostic) => formatDiagnostic(diagnostic).replace(/[,;] kept as (?:a custom attribute|written)(?:, but not used)?/, ''));\n\n if (problems.length > 0) {\n throw new CallError(`outline doesn't read cleanly. Fix ${problems.length === 1 ? 'this' : 'these'}, and send it again:\\n${problems.map((problem) => `- ${problem}`).join('\\n')}\\nLines count from the outline's first line.`);\n }\n\n return roots.map(newNodeFrom);\n};\n\n/** What update_node changes: the changes, checked; what they set and remove; and what they'd remove that isn't there. */\ninterface Changes {\n changes: OrbitNodeInput;\n set: string[];\n cleared: string[];\n absent: string[];\n}\n\n/** The changes update_node asks for, checked. */\nconst readChanges = (values: Record<string, unknown>, root: OrbitNode, node: OrbitNode): Changes => {\n const changes: OrbitNodeInput = {};\n const set: string[] = [];\n const clear = new Set((values.clear as ToolAttribute[] | undefined) ?? []);\n const cleared: string[] = [];\n const absent: string[] = [];\n\n const remove = (name: ToolAttribute) => {\n if (node[name] === undefined) {\n absent.push(name);\n return;\n }\n\n (changes as Record<string, unknown>)[name] = undefined;\n cleared.push(name);\n };\n\n for (const name of clear) {\n if (values[name] !== undefined) {\n throw new CallError(`${name} is both given and in clear: give it a value, or clear it.`);\n }\n\n remove(name);\n }\n\n if (values.text !== undefined) {\n let text = String(values.text).replace(/\\s+/g, ' ').trim();\n\n if (text === '') {\n throw new CallError('text can\\'t be empty: every node has a title. To take the node out of the map, use remove_node.');\n }\n\n const emoji = leadingEmoji(text);\n\n if (emoji && values.icon === undefined && !clear.has('icon')) {\n // Saved, the map would read the emoji back as the node's icon.\n changes.icon = emoji.icon;\n text = emoji.text;\n set.push('icon');\n }\n\n changes.text = text;\n set.push('title');\n }\n\n const text = (name: 'note' | 'status' | 'icon' | 'color' | 'link'): string | undefined => {\n const value = values[name];\n\n if (value === undefined) {\n return undefined;\n }\n\n const written = name === 'note' ? String(value).trim() : String(value).replace(/\\s+/g, ' ').trim();\n\n if (written === '') {\n remove(name);\n return undefined;\n }\n\n set.push(name);\n return written;\n };\n\n const note = text('note');\n\n if (note !== undefined) {\n changes.note = note;\n }\n\n const status = text('status');\n\n if (status !== undefined) {\n changes.status = status;\n }\n\n if (values.priority !== undefined) {\n changes.priority = values.priority as number;\n set.push('priority');\n }\n\n if (values.tags !== undefined) {\n const tags = [...new Set((values.tags as string[]).map((tag) => tag.replace(/^#/, '').trim()).filter((tag) => tag !== ''))];\n\n if (tags.length === 0) {\n remove('tags');\n } else {\n changes.tags = tags;\n set.push('tags');\n }\n }\n\n const icon = text('icon');\n\n if (icon !== undefined) {\n if (/^[\\p{L}\\p{N}][\\p{L}\\p{N}\\s'-]+$/u.test(icon) || Array.from(icon).length > 8) {\n throw new CallError(`icon takes an emoji, such as 🚀, not ${JSON.stringify(icon)}.`);\n }\n\n changes.icon = icon;\n }\n\n const color = text('color');\n\n if (color !== undefined) {\n const supports = typeof CSS !== 'undefined' && typeof CSS.supports === 'function' ? CSS.supports('color', color) : true;\n\n if (!COLOR_SYNTAX.test(color) || !supports) {\n throw new CallError(`\"${color}\" isn't a CSS color. Use a color name, such as tomato, or a code, such as #E8A33D.`);\n }\n\n changes.color = color;\n }\n\n const link = text('link');\n\n if (link !== undefined) {\n if (isNodeLink(link)) {\n if (!findLinkedNode(root, link)) {\n const near = suggest(link.slice(1), allNodes(root).map((each) => each.id));\n throw new CallError(`link ${link} points at no node.${near === undefined ? '' : ` Did you mean #${near}?`} Node links are # and a node's id.`);\n }\n } else if (guardUrl(link, 'link', false) === null) {\n throw new CallError(`\"${link}\" isn't an address the map can open: use a web address, such as https://example.com.`);\n }\n\n changes.link = link;\n }\n\n for (const name of ['image', 'video', 'embed'] as const) {\n const media = values[name] as Record<string, string> | undefined;\n\n if (media === undefined) {\n continue;\n }\n\n const src = media.src.trim();\n\n if (src === '') {\n remove(name);\n continue;\n }\n\n if (guardUrl(src, name, false) === null) {\n throw new CallError(`${name} can't show \"${src}\": use a web address, such as https://example.com/${name === 'image' ? 'photo.jpg' : name === 'video' ? 'video.mp4' : 'page'}.`);\n }\n\n const extras = Object.fromEntries(Object.entries(media).filter(([key, value]) => key !== 'src' && value.trim() !== '').map(([key, value]) => [key, value.trim()]));\n (changes as Record<string, unknown>)[name] = { src, ...extras };\n set.push(name === 'image' ? 'picture' : name === 'embed' ? 'embedded page' : 'video');\n }\n\n if (values.collapsed !== undefined) {\n if (values.collapsed === true) {\n changes.collapsed = true;\n set.push('collapsed');\n } else {\n remove('collapsed');\n }\n }\n\n return { changes, set, cleared, absent };\n};\n",
12
+ "import { parseColor, toHex, toneColor, toOklch } from './engine/colors.js';\nimport type { OrbitRendererTheme } from './types.js';\n\n/**\n * Material 3 themes from one color, the way Material You colors an app from\n * its wallpaper: tonal palettes in the color's hue, surfaces and containers\n * picked by tone, and branches in hues spread evenly around the color wheel\n * from it. Picking colors by tone is what keeps text readable: two tones 50\n * apart always have at least 4.5:1 contrast.\n */\n\n/** Material's baseline color: the `material` and `material-night` themes are built from it. */\nexport const MATERIAL_SEED = '#6750A4';\n\nexport interface MaterialThemeOptions {\n /** Dark surfaces with light text, like `material-night`, instead of light ones. */\n dark?: boolean;\n}\n\n/** The tokens a Material theme takes from its color: everything else comes from `material` or `material-night`. */\nexport const MATERIAL_COLOR_TOKENS = [\n 'surface', 'text', 'muted-text', 'root-text', 'node-text', 'node-text-inverse',\n 'color-root', 'color-1', 'color-2', 'color-3', 'color-4', 'color-5', 'color-6', 'color-7',\n 'shade-light', 'shade-dark', 'node-stroke', 'badge-stroke', 'sun-halo', 'ring-stroke', 'link-stroke',\n 'focus-ring', 'note-indicator',\n 'control-background', 'control-text', 'control-muted-text', 'control-active-background', 'control-active-text',\n 'tooltip-background', 'tooltip-text', 'action-background', 'action-text',\n 'sheet-background', 'sheet-text', 'sheet-muted-text', 'sheet-border', 'chip-background', 'chip-text', 'link-text',\n 'status-active', 'status-done', 'status-blocked', 'status-todo', 'status-neutral',\n 'error-background', 'error-border', 'error-text',\n] as const;\n\nexport type MaterialColorToken = (typeof MATERIAL_COLOR_TOKENS)[number];\n\n/** How far around the wheel each branch's hue is from the seed's: a seventh of a turn apart, three sevenths between neighbors. */\nconst BRANCH_HUES = [0, 3, 6, 2, 5, 1, 4].map((step) => (step * 360) / 7);\n/** The most chroma any palette keeps: more, and containers would stop looking like Material's. */\nconst MOST_CHROMA = 0.16;\n/** Branch containers: colorful whatever the seed, as categories need to be told apart. */\nconst BRANCH_CHROMA = 0.11;\nconst ERROR = { hue: 25, chroma: 0.19 };\nconst SUCCESS = { hue: 145, chroma: 0.13 };\n\n/**\n * A Material 3 theme built from `seed`, any CSS color Orbit reads (hex,\n * `rgb()`, `oklch()`…). Use it as the `theme` option, or name it for every\n * map: `registerTheme('brand', materialTheme('#0B57D0'))`.\n */\nexport const materialTheme = (seed: string, options: MaterialThemeOptions = {}): OrbitRendererTheme => {\n const dark = options.dark === true;\n return { preset: dark ? 'material-night' : 'material', tokens: materialColors(seed, dark) };\n};\n\n/** Every color token of a Material theme built from `seed`. */\nexport const materialColors = (seed: string, dark: boolean): Record<MaterialColorToken, string> => {\n const parsed = parseColor(seed);\n\n if (!parsed) {\n throw new Error(`A Material theme needs a color Orbit can read, such as \"#0B57D0\" or \"oklch(0.55 0.15 260)\": got \"${seed}\".`);\n }\n\n const { hue, chroma } = toOklch(parsed);\n const primaryChroma = Math.min(chroma, MOST_CHROMA);\n const palette = (paletteHue: number, paletteChroma: number) => (tone: number) => toHex(toneColor(paletteHue, paletteChroma, tone));\n const primary = palette(hue, primaryChroma);\n const secondary = palette(hue, Math.min(primaryChroma / 3, 0.05));\n const neutral = palette(hue, Math.min(primaryChroma / 10, 0.012));\n const neutralVariant = palette(hue, Math.min(primaryChroma / 5, 0.024));\n const error = palette(ERROR.hue, ERROR.chroma);\n const success = palette(SUCCESS.hue, SUCCESS.chroma);\n const branches = BRANCH_HUES.map((offset) => palette((hue + offset) % 360, BRANCH_CHROMA));\n // Light themes use tone 40 for what stands out, 90 for containers and 10 on them; dark ones 80, 30 and 90.\n const [accent, container, onContainer] = dark ? [80, 30, 90] : [40, 90, 10];\n // Branches a little deeper than Material's containers, so a small moon still shows on the surface.\n const branchTone = dark ? 32 : 88;\n const [colorRoot, ...colors] = [primary(accent), ...branches.map((branch) => branch(branchTone))];\n return {\n surface: neutral(dark ? 6 : 98),\n text: neutral(dark ? 90 : 10),\n 'muted-text': neutralVariant(dark ? 80 : 30),\n 'root-text': neutral(10),\n 'node-text': neutral(10),\n 'node-text-inverse': neutral(dark ? 90 : 100),\n 'color-root': colorRoot,\n 'color-1': colors[0],\n 'color-2': colors[1],\n 'color-3': colors[2],\n 'color-4': colors[3],\n 'color-5': colors[4],\n 'color-6': colors[5],\n 'color-7': colors[6],\n // Siblings step a few tones lighter or darker, staying on their side of the text's contrast\n // and clear of the surface.\n 'shade-light': dark ? neutral(40) : neutralVariant(80),\n 'shade-dark': dark ? neutral(12) : neutralVariant(50),\n 'node-stroke': neutralVariant(dark ? 30 : 80),\n 'badge-stroke': neutral(dark ? 6 : 98),\n 'sun-halo': primary(accent),\n 'ring-stroke': neutralVariant(dark ? 30 : 80),\n 'link-stroke': neutralVariant(dark ? 60 : 50),\n 'focus-ring': primary(accent),\n 'note-indicator': primary(accent),\n 'control-background': neutral(dark ? 12 : 94),\n 'control-text': neutral(dark ? 90 : 10),\n 'control-muted-text': neutralVariant(dark ? 80 : 30),\n 'control-active-background': secondary(container),\n 'control-active-text': secondary(onContainer),\n 'tooltip-background': neutral(dark ? 90 : 20),\n 'tooltip-text': neutral(dark ? 20 : 95),\n 'action-background': neutral(dark ? 17 : 92),\n 'action-text': neutral(dark ? 90 : 10),\n 'sheet-background': neutral(dark ? 10 : 96),\n 'sheet-text': neutral(dark ? 90 : 10),\n 'sheet-muted-text': neutralVariant(dark ? 80 : 30),\n 'sheet-border': neutralVariant(dark ? 30 : 80),\n 'chip-background': secondary(container),\n 'chip-text': secondary(onContainer),\n 'link-text': primary(accent),\n 'status-active': primary(accent),\n 'status-done': success(accent),\n 'status-blocked': error(accent),\n 'status-todo': neutralVariant(60),\n 'status-neutral': neutralVariant(dark ? 70 : 50),\n 'error-background': error(container),\n 'error-border': error(accent),\n 'error-text': error(onContainer),\n };\n};\n"
13
+ ],
14
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKO,IAAM,qBAAqB,CAAC,QAA+B;AAAA,EAChE,MAAM,MAAiC,CAAC;AAAA,EACxC,MAAM,OAAO,IAAI;AAAA,EAEjB,IAAI,KAAK,OAAO;AAAA,IACd,IAAI,QAAQ,KAAK;AAAA,EACnB;AAAA,EAEA,IAAI,KAAK,OAAO;AAAA,IACd,IAAI,QAAQ,KAAK;AAAA,EACnB;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IACjB,IAAI,OAAO,KAAK;AAAA,EAClB;AAAA,EAEA,IAAI,KAAK,cAAc,WAAW;AAAA,IAChC,IAAI,YAAY,KAAK;AAAA,EACvB;AAAA,EAEA,IAAI,KAAK,gBAAgB,WAAW;AAAA,IAClC,IAAI,cAAc,KAAK;AAAA,EACzB;AAAA,EAEA,IAAI,KAAK,mBAAmB,WAAW;AAAA,IACrC,IAAI,YAAY,KAAK;AAAA,EACvB;AAAA,EAEA,IAAI,KAAK,eAAe,WAAW;AAAA,IACjC,IAAI,QAAQ,KAAK;AAAA,EACnB;AAAA,EAEA,IAAI,KAAK,SAAS;AAAA,IAChB,IAAI,UAAU,KAAK;AAAA,EACrB;AAAA,EAEA,IAAI,KAAK,WAAW,WAAW;AAAA,IAC7B,IAAI,SAAS,KAAK;AAAA,EACpB;AAAA,EAEA,IAAI,KAAK,aAAa,WAAW;AAAA,IAC/B,IAAI,WAAW,KAAK;AAAA,EACtB;AAAA,EAEA,IAAI,KAAK,WAAW;AAAA,IAClB,IAAI,YAAY,KAAK;AAAA,EACvB;AAAA,EAEA,IAAI,KAAK,SAAS;AAAA,IAChB,IAAI,UAAU,KAAK;AAAA,EACrB;AAAA,EAEA,IAAI,KAAK,kBAAkB,WAAW;AAAA,IACpC,IAAI,gBAAgB,KAAK;AAAA,EAC3B;AAAA,EAGA,YAAY,KAAK,UAAU,OAAO,QAAQ,IAAI,SAAS,CAAC,CAAC,GAAG;AAAA,IAC1D,IAAI,CAAC,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG,KAAK,QAAQ,SAAS;AAAA,MACtE,UAAU,KAAK,KAAK,KAAkB;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,IAAI,QAAQ,CAAC,cAAc,IAAI,MAAM,qBAAqB,IAAI,IAAI,CAAC,CAAC;AAAA,EACpE,OAAO,SAAS,GAAG;AAAA;AAGrB,IAAM,gBAAgB,CAAC,GAAc,gBAAmD;AAAA,EACtF,MAAM,MAAiC,EAAE,MAAM,EAAE,KAAK;AAAA,EAEtD,IAAI,YAAY,IAAI,CAAC,GAAG;AAAA,IACtB,IAAI,KAAK,EAAE;AAAA,EACb;AAAA,EAEA,IAAI,EAAE,MAAM;AAAA,IACV,IAAI,OAAO,EAAE;AAAA,EACf;AAAA,EAEA,IAAI,EAAE,OAAO;AAAA,IACX,IAAI,QAAQ,EAAE;AAAA,EAChB;AAAA,EAEA,IAAI,EAAE,MAAM;AAAA,IACV,IAAI,OAAO,EAAE,gBAAgB,YAAY,EAAE,OAAO,GAAG,EAAE,QAAQ,EAAE;AAAA,EACnE;AAAA,EAEA,IAAI,EAAE,MAAM;AAAA,IACV,IAAI,OAAO,EAAE;AAAA,EACf;AAAA,EAEA,IAAI,EAAE,MAAM;AAAA,IACV,IAAI,OAAO,EAAE;AAAA,EACf;AAAA,EAEA,IAAI,EAAE,QAAQ;AAAA,IACZ,IAAI,SAAS,EAAE;AAAA,EACjB;AAAA,EAEA,IAAI,EAAE,aAAa,WAAW;AAAA,IAC5B,IAAI,WAAW,EAAE;AAAA,EACnB;AAAA,EAEA,IAAI,EAAE,cAAc,WAAW;AAAA,IAC7B,IAAI,YAAY,EAAE;AAAA,EACpB;AAAA,EAGA,IAAI,EAAE,OAAO;AAAA,IACX,IAAI,QAAQ,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM;AAAA,EACpD;AAAA,EAEA,IAAI,EAAE,OAAO;AAAA,IACX,IAAI,QAAQ,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM;AAAA,EACpD;AAAA,EAEA,IAAI,EAAE,OAAO;AAAA,IACX,IAAI,QAAQ,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM;AAAA,EACpD;AAAA,EAEA,IAAI,EAAE,MAAM;AAAA,IACV,IAAI,OAAO,EAAE;AAAA,IAEb,IAAI,EAAE,cAAc,EAAE,eAAe,YAAY;AAAA,MAC/C,IAAI,aAAa,EAAE;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,IAAI,EAAE,OAAO;AAAA,IACX,YAAY,GAAG,MAAM,OAAO,QAAQ,EAAE,KAAK,GAAG;AAAA,MAK5C,IAAI,CAAC,mBAAmB,IAAI,CAAC,KAAK,CAAC,OAAO,UAAU,eAAe,KAAK,KAAK,CAAC,GAAG;AAAA,QAC/E,UAAU,KAAK,GAAG,CAAc;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,EAAE,SAAS,QAAQ;AAAA,IACrB,IAAI,WAAW,EAAE,SAAS,IAAI,CAAC,UAAU,cAAc,OAAO,WAAW,CAAC;AAAA,EAC5E;AAAA,EAEA,OAAO;AAAA;AAIT,IAAM,qBAAqB,IAAI,IAAI,CAAC,QAAQ,UAAU,CAAC;;AC7HhD,IAAM,iBAAiB,CAC5B,QACA,QACA,UAAiC,CAAC,MACb;AAAA,EACrB,QAAQ,WAAW,oBAAoB;AAAA,EACvC,MAAM,WAAW,IAAI,kBAAiB,QAAQ,eAAe;AAAA,EAE7D,IAAI,OAAO,WAAW,UAAU;AAAA,IAC9B,MAAM,MAAM,YAAW,QAAQ,EAAE,QAAQ,UAAU,SAAS,gBAAgB,UAAU,QAAQ,gBAAgB,OAAO,EAAE,KAAK,aAAa,EAAE,CAAC;AAAA,IAC5I,uBAAuB,GAAG;AAAA,IAC1B,SAAS,OAAO,GAAG;AAAA,EACrB,EAAO;AAAA,IACL,SAAS,OAAO,MAAM;AAAA;AAAA,EAGxB,OAAO;AAAA;;ACKT,IAAM,aAAa;AA2BZ,IAAM,gBAAgB,CAAC,OAA+B,YAAyC;AAAA,EACpG,MAAM,WAAW,OAAO,UAAU,WAAW,YAAW,KAAK,IAAI;AAAA,EACjE,MAAM,SAAS,OAAO,UAAU,WAAW,QAAQ,wBAAuB,KAAK;AAAA,EAC/E,MAAM,QAAQ,IAAI,WAAW,QAAQ,UAAU,QAAQ,OAAO;AAAA,EAC9D,MAAM,QAAQ,QAAQ,UAAU,SAAS,QAAQ,SAAS,SAAS,KAAK,QAAQ;AAAA,EAChF,MAAM,OAAoB;AAAA,IACxB;AAAA,IACA,OAAO,QAAQ;AAAA,IACf,UAAU,QAAQ;AAAA,IAClB,OAAO,QAAQ;AAAA,IACf,UAAU,QAAQ;AAAA,IAClB,SAAS,QAAQ;AAAA,IACjB,OAAO,QAAQ,SAAS,CAAC;AAAA,EAC3B;AAAA,EACA,MAAM,QAAQ,QAAQ,SAAS,SAAS,QAAQ;AAAA,EAChD,OAAO;AAAA,cACK,gBAAgB,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,yBAKjB;AAAA,SAChB,WAAW,KAAK;AAAA;AAAA,EAEvB,WAAW,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,qDAKmC,gBAAgB,KAAK;AAAA,+FACqB,WAAW,MAAM,KAAK,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4EAMnD,gBAAgB,MAAM,KAAK,UAAU,CAAC;AAAA;AAAA,2EAEvC,gBAAgB,MAAM,KAAK,MAAM,CAAC;AAAA,wEACrC,gBAAgB,MAAM,KAAK,OAAO,CAAC;AAAA;AAAA;AAAA,kDAGzD,WAAW,IAAI;AAAA,oDACb,WAAW,QAAQ,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAe7E,IAAM,aAAa,CAAC,WAAqC;AAAA,EACvD,MAAM,UAAU,OAAO,YAAY,gBAAgB,YAAY,OAAO;AAAA,EACtE,OAAO;AAAA,IACL,sBAAsB;AAAA,IACtB,gBAAgB,OAAO;AAAA,IACvB,gBAAgB,OAAO;AAAA,IACvB,iBAAiB,OAAO;AAAA,IACxB,kBAAkB,OAAO;AAAA,IACzB,kBAAkB,OAAO;AAAA,EAC3B,EAAE,KAAK,GAAG;AAAA;AAIZ,IAAM,WAAW,CAAC,UAAqE;AAAA,EACrF,MAAM,WAAW,YAAY,KAAK;AAAA,EAClC,MAAM,SAAS,OAAO,aAAa,WAAW,WAAW,UAAU;AAAA,EACnE,MAAM,OAAO,aAAY,oBAAmB,MAAM,IAAI,SAAS,OAAO;AAAA,EACtE,OAAO,OAAO,aAAa,YAAY,UAAU,SAAS,KAAK,SAAS,SAAS,OAAO,IAAwB;AAAA;AAGlH,IAAM,aAAa,CAAC,UAA2D;AAAA,EAC7E,MAAM,aAAa,OAAO,UAAU,WAAW,QAAQ,OAAO,YAAY;AAAA,EAC1E,MAAM,SAAS,YACX,WAAW,WAAW,aAAY,OAAO,CAAC;AAAA,gDAAsD,WAAW,aAAY,OAAO,CAAC,UAC/H,WAAW,WAAW,SAAS,KAAK,CAAC;AAAA,EACzC,OAAO,GAAG;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;AA+BZ,IAAM,aAAa,CAAC,UAA2B;AAAA,EAC7C,OAAO,KAAK,UAAU,KAAK,EAAE,QAAQ,MAAM,SAAS,EAAE,QAAQ,WAAW,SAAS,EAAE,QAAQ,WAAW,SAAS;AAAA;AAGlH,IAAM,aAAa,CAAC,SAAyB;AAAA,EAC3C,OAAO,KAAK,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM;AAAA;AAG/E,IAAM,kBAAkB,CAAC,SAAyB;AAAA,EAChD,OAAO,WAAW,IAAI,EAAE,QAAQ,MAAM,QAAQ;AAAA;;ACvJzC,IAAM,WAAW,CAAC,WAAkC;AAAA,EACzD,MAAM,WAAW,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,SAAS,OAAO,MAAM,QAAQ;AAAA,EAC3E,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC,MAAM,WAAW,KAAK,CAAC,CAAC,CAAC;AAAA,OACnG,SAAS,SAAS,IAAI,EAAE,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA;AAGF,IAAM,aAAa,CAAC,UAAkC;AAAA,EACpD,IAAI,MAAM,SAAS,QAAQ;AAAA,IACzB,OAAO,EAAE,MAAM,SAAS,aAAa,MAAM,aAAa,OAAO,MAAM,SAAS,EAAE,MAAM,UAAU,MAAM,CAAC,GAAG,MAAM,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,EAAE;AAAA,EACjJ;AAAA,EAEA,IAAI,MAAM,SAAS,UAAU;AAAA,IAC3B,OAAO,KAAK,SAAS,MAAM,UAAU,CAAC,CAAC,GAAG,aAAa,MAAM,YAAY;AAAA,EAC3E;AAAA,EAEA,OAAO,EAAE,MAAM,MAAM,MAAM,aAAa,MAAM,gBAAiB,MAAM,YAAY,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ,EAAG;AAAA;AAAA;AAUzH,MAAM,mBAAmB,MAAM;AAAC;AAShC,IAAM,YAAY,CAAC,MAAc,QAAgB,OAAgB,WAA6C,CAAC,MAAiB;AAAA,EACrI,MAAM,SAAS,YAAY,MAAM,QAAQ,KAAK;AAAA,EAC9C,MAAM,SAAkC,CAAC;AAAA,EACzC,MAAM,UAAoB,CAAC;AAAA,EAC3B,MAAM,QAAQ,OAAO,KAAK,MAAM;AAAA,EAEhC,YAAY,OAAO,UAAU,OAAO,QAAQ,MAAM,GAAG;AAAA,IACnD,IAAI,UAAU,QAAQ,UAAU,WAAW;AAAA,MACzC;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,KAAK,QAAQ,KAAK,IAAI,QAAQ,UAAU,OAAO,OAAO,QAAQ;AAAA,IAE3E,IAAI,SAAS,WAAW;AAAA,MACtB,MAAM,OAAO,QAAQ,OAAO,KAAK;AAAA,MAEjC,IAAI,SAAS,WAAW;AAAA,QACtB,MAAM,IAAI,WAAW,GAAG,sBAAsB,yBAAyB,mBAAmB,KAAK,KAAK,IAAI;AAAA,MAC1G;AAAA,MAEA,QAAQ,KAAK,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IAEA,IAAI,KAAK,QAAQ,IAAI,GAAG;AAAA,MACtB,MAAM,IAAI,WAAW,GAAG,YAAY,mBAAmB,iBAAiB,uBAAuB;AAAA,IACjG;AAAA,IAEA,OAAO,QAAQ,UAAU,MAAM,OAAO,OAAO,KAAK;AAAA,EACpD;AAAA,EAEA,WAAW,QAAQ,OAAO;AAAA,IACxB,IAAI,OAAO,MAAM,YAAY,CAAC,KAAK,QAAQ,IAAI,GAAG;AAAA,MAChD,MAAM,IAAI,WAAW,GAAG,cAAc,SAAS,WAAW,OAAO,MAAM,WAAW,GAAG;AAAA,IACvF;AAAA,EACF;AAAA,EAEA,OAAO,EAAE,QAAQ,QAAQ;AAAA;AAG3B,IAAM,cAAc,CAAC,MAAc,QAAgB,UAA4C;AAAA,EAC7F,IAAI,QAAQ;AAAA,EAEZ,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,IAAI,MAAM,KAAK,MAAM,IAAI;AAAA,MACvB,OAAO,CAAC;AAAA,IACV;AAAA,IAEA,IAAI;AAAA,MACF,QAAQ,KAAK,MAAM,KAAK;AAAA,MACxB,OAAO,OAAO;AAAA,MACd,MAAM,IAAI,WAAW,GAAG,kCAAmC,MAAgB,kCAAkC,QAAQ,MAAM,IAAI;AAAA;AAAA,EAEnI;AAAA,EAEA,IAAI,UAAU,QAAQ,UAAU,WAAW;AAAA,IACzC,OAAO,CAAC;AAAA,EACV;AAAA,EAEA,IAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAAA,IACrD,MAAM,IAAI,WAAW,GAAG,8BAA8B,QAAQ,MAAM,UAAU,SAAS,KAAK,IAAI;AAAA,EAClG;AAAA,EAEA,OAAO;AAAA;AAIT,IAAM,YAAY,CAAC,OAAe,OAA0B,aAAmE;AAAA,EAC7H,MAAM,UAAU,MAAM,YAAY;AAAA,EAClC,OAAO,MAAM,KAAK,CAAC,SAAS,KAAK,YAAY,MAAM,OAAO,MAAM,KAAK,UAAU,OAAO,IAAI,SAAS,WAAW;AAAA;AAIzG,IAAM,OAAO,CAAC,QAAgB,QAAyB;AAAA,EAC5D,OAAO,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG;AAAA;AAGzD,IAAM,YAAY,CAAC,MAAc,OAAc,UAA4B;AAAA,EACzE,QAAQ,MAAM;AAAA,SACP;AAAA,MACH,IAAI,OAAO,UAAU,UAAU;AAAA,QAC7B,OAAO;AAAA,MACT;AAAA,MAEA,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW;AAAA,QAC3D,OAAO,OAAO,KAAK;AAAA,MACrB;AAAA,MAEA,MAAM,IAAI,WAAW,GAAG,wBAAwB,SAAS,KAAK,IAAI;AAAA,SAC/D;AAAA,SACA,UAAU;AAAA,MACb,MAAM,SAAS,OAAO,UAAU,WAAW,QAAQ,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,OAAO;AAAA,MAE7H,IAAI,CAAC,OAAO,SAAS,MAAM,KAAM,MAAM,SAAS,aAAa,CAAC,OAAO,UAAU,MAAM,GAAI;AAAA,QACvF,MAAM,IAAI,WAAW,GAAG,cAAc,MAAM,SAAS,YAAY,mBAAmB,oBAAoB,MAAM,WAAW,UAAU,SAAS,KAAK,IAAI;AAAA,MACvJ;AAAA,MAEA,IAAI,MAAM,YAAY,aAAa,SAAS,MAAM,SAAS;AAAA,QACzD,MAAM,IAAI,WAAW,GAAG,cAAc,MAAM,wBAAwB,WAAW,MAAM,aAAa;AAAA,MACpG;AAAA,MAEA,OAAO;AAAA,IACT;AAAA,SACK,WAAW;AAAA,MACd,MAAM,OAAO,OAAO,UAAU,WAAW,MAAM,KAAK,EAAE,YAAY,IAAI;AAAA,MAEtE,IAAI,SAAS,QAAQ,SAAS,UAAU,SAAS,OAAO;AAAA,QACtD,OAAO;AAAA,MACT;AAAA,MAEA,IAAI,SAAS,SAAS,SAAS,WAAW,SAAS,MAAM;AAAA,QACvD,OAAO;AAAA,MACT;AAAA,MAEA,MAAM,IAAI,WAAW,GAAG,iCAAiC,SAAS,KAAK,IAAI;AAAA,IAC7E;AAAA,SACK,QAAQ;AAAA,MACX,MAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO,UAAU,WAAY,MAAM,KAAK,MAAM,KAAK,CAAC,IAAI,MAAM,MAAM,GAAG,IAAK;AAAA,MAEzH,IAAI,CAAC,SAAS,MAAM,KAAK,CAAC,SAAS,OAAO,SAAS,YAAY,OAAO,SAAS,QAAQ,GAAG;AAAA,QACxF,MAAM,IAAI,WAAW,GAAG,sCAAsC,MAAM,SAAS,MAAM,mBAAmB,SAAS,KAAK,IAAI;AAAA,MAC1H;AAAA,MAEA,MAAM,QAAQ,MAAM,IAAI,CAAC,SAAS,OAAO,IAAI,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE;AAAA,MAEnF,WAAW,QAAQ,OAAO;AAAA,QACxB,IAAI,MAAM,UAAU,CAAC,MAAM,OAAO,SAAS,IAAI,GAAG;AAAA,UAChD,MAAM,OAAO,QAAQ,MAAM,MAAM,MAAM;AAAA,UACvC,MAAM,IAAI,WAAW,GAAG,oBAAoB,SAAS,SAAS,YAAY,KAAK,kBAAkB,qBAAqB,KAAK,MAAM,MAAM,IAAI;AAAA,QAC7I;AAAA,MACF;AAAA,MAEA,OAAO;AAAA,IACT;AAAA,SACK,UAAU;AAAA,MACb,MAAM,SAAS,MAAM,UAAU,CAAC;AAAA,MAChC,MAAM,QAAQ,OAAO,KAAK,MAAM,EAAE;AAAA,MAElC,IAAI,OAAO,UAAU,UAAU;AAAA,QAC7B,OAAO,GAAG,QAAQ,MAAM;AAAA,MAC1B;AAAA,MAEA,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AAAA,QACvE,MAAM,IAAI,WAAW,GAAG,gCAAgC,qBAAqB,SAAS,KAAK,IAAI;AAAA,MACjG;AAAA,MAEA,OAAO,UAAU,MAAM,QAAQ,KAAK,EAAE;AAAA,IACxC;AAAA;AAAA;AAKG,IAAM,WAAW,CAAC,UAA2B;AAAA,EAClD,IAAI,UAAU,MAAM;AAAA,IAClB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,MAAM,QAAQ,KAAK,GAAG;AAAA,IACxB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,OAAO,KAAK,UAAU,MAAM,SAAS,KAAK,GAAG,MAAM,MAAM,GAAG,EAAE,OAAO,KAAK;AAAA,EAC5E;AAAA,EAEA,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,OAAO;AAAA,EACT;AAAA,EAEA,OAAO,OAAO,KAAK;AAAA;AAId,IAAM,OAAO,CAAC,UAAqC;AAAA,EACxD,OAAO,MAAM,UAAU,IAAI,MAAM,KAAK,EAAE,IAAI,GAAG,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI,SAAS,MAAM,MAAM,SAAS;AAAA;AAG3G,IAAM,UAAU,CAAC,WAA2B;AAAA,EAC1C,MAAM,OAAO,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC,QAAQ,OAAO,KAAK,QAAQ,KAAK,OAAO,KAAK,MAAM,EAAE;AAAA,EAC5F,OAAO,SAAS,YAAY,OAAO,KAAK;AAAA;AAG1C,IAAM,aAAa,CAAC,SAAyB;AAAA,EAC3C,OAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AAAA;;;AC5NpD,IAAM,YAAwC,CAAC,aAAa,UAAU,eAAe,QAAQ;AAgBtF,IAAM,aAAa,CAAC,QAAQ,UAAU,YAAY,QAAQ,QAAQ,SAAS,QAAQ,SAAS,SAAS,SAAS,WAAW;AAIhI,IAAM,UAAU;AAChB,IAAM,gBAAgB,EAAE,IAAI,SAAS,MAAM,SAAS,QAAQ,QAAQ;AAG7D,IAAM,aAAkC;AAAA,EAC7C;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,SAAS,EAAE,MAAM,UAAU,aAAa,+EAA+E;AAAA,MACvH,OAAO,EAAE,MAAM,WAAW,SAAS,GAAG,aAAa,yFAAyF;AAAA,IAC9I;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,OAAO,EAAE,MAAM,UAAU,aAAa,kGAAkG;AAAA,MACxI,QAAQ,EAAE,MAAM,UAAU,aAAa,sJAAsJ;AAAA,MAC7L,KAAK,EAAE,MAAM,UAAU,aAAa,4BAA4B;AAAA,IAClE;AAAA,IACA,UAAU,EAAE,MAAM,SAAS,QAAQ,SAAS,OAAO,SAAS,MAAM,MAAM;AAAA,IACxE,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,SAAS,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,2DAA2D;AAAA,IACrH;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,WAAW,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,8BAA8B;AAAA,MACxF,SAAS,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,kFAAkF;AAAA,MAC1I,OAAO,EAAE,MAAM,WAAW,SAAS,GAAG,aAAa,gGAAgG;AAAA,IACrJ;AAAA,IACA,UAAU,EAAE,QAAQ,aAAa,UAAU,aAAa,OAAO,aAAa,UAAU,WAAW,OAAO,WAAW,OAAO,WAAW,UAAU,WAAW,MAAM,WAAW,UAAU,QAAQ;AAAA,IAC7L,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,SAAS,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,sBAAsB;AAAA,MAC9E,MAAM,EAAE,MAAM,UAAU,aAAa,sCAAsC;AAAA,MAC3E,MAAM,EAAE,MAAM,UAAU,aAAa,gFAAgF;AAAA,MACrH,QAAQ,EAAE,MAAM,UAAU,aAAa,8EAA8E;AAAA,MACrH,UAAU,EAAE,MAAM,UAAU,aAAa,8CAA8C;AAAA,MACvF,MAAM,EAAE,MAAM,QAAQ,aAAa,wDAAwD;AAAA,MAC3F,MAAM,EAAE,MAAM,UAAU,aAAa,mCAAmC;AAAA,MACxE,OAAO,EAAE,MAAM,UAAU,aAAa,gJAAiJ;AAAA,MACvL,MAAM,EAAE,MAAM,UAAU,aAAa,wEAAwE;AAAA,MAC7G,OAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,QACb,QAAQ;AAAA,UACN,KAAK,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,yBAA0B;AAAA,UAC9E,KAAK,EAAE,MAAM,UAAU,aAAa,uDAAwD;AAAA,UAC5F,SAAS,EAAE,MAAM,UAAU,aAAa,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,QACb,QAAQ;AAAA,UACN,KAAK,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,uDAAwD;AAAA,UAC5G,SAAS,EAAE,MAAM,UAAU,aAAa,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,QACb,QAAQ;AAAA,UACN,KAAK,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,sBAAuB;AAAA,UAC3E,SAAS,EAAE,MAAM,UAAU,aAAa,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,MACA,WAAW,EAAE,MAAM,WAAW,aAAa,qDAAqD;AAAA,MAChG,OAAO,EAAE,MAAM,QAAQ,QAAQ,YAAY,aAAa,qDAAqD;AAAA,IAC/G;AAAA,IACA,UAAU;AAAA,SACL;AAAA,MAAe,OAAO;AAAA,MAAQ,MAAM;AAAA,MAAQ,OAAO;AAAA,MAAQ,OAAO;AAAA,MAAQ,aAAa;AAAA,MAAQ,SAAS;AAAA,MAAQ,OAAO;AAAA,MAC1H,KAAK;AAAA,MAAQ,QAAQ;AAAA,MAAQ,OAAO;AAAA,MAAQ,QAAQ;AAAA,MAAS,KAAK;AAAA,MAAQ,MAAM;AAAA,MAAQ,SAAS;AAAA,MAAS,OAAO;AAAA,MACjH,QAAQ;AAAA,MAAS,OAAO;AAAA,MAAS,QAAQ;AAAA,IAC3C;AAAA,IACA,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,SAAS,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,oBAAoB;AAAA,MAC5E,WAAW,EAAE,MAAM,UAAU,aAAa,qFAAqF;AAAA,MAC/H,OAAO,EAAE,MAAM,WAAW,SAAS,GAAG,aAAa,6FAA6F;AAAA,IAClJ;AAAA,IACA,UAAU,KAAK,eAAe,QAAQ,aAAa,UAAU,aAAa,OAAO,aAAa,IAAI,aAAa,UAAU,QAAQ;AAAA,IACjI,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,WAAW,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,sCAAsC;AAAA,MAChG,OAAO,EAAE,MAAM,QAAQ,UAAU,MAAM,aAAa,mDAAmD;AAAA,IACzG;AAAA,IACA,UAAU,EAAE,QAAQ,aAAa,UAAU,aAAa,SAAS,aAAa,IAAI,aAAa,KAAK,SAAS,UAAU,SAAS,WAAW,QAAQ;AAAA,IACnJ,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,SAAS,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,iDAAkD;AAAA,IAC5G;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,SAAS,EAAE,MAAM,UAAU,UAAU,MAAM,aAAa,oBAAoB;AAAA,IAC9E;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AACF;AAEO,IAAM,eAAe,CAAC,SAAsC;AAAA,EACjE,OAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,aAAa,SAAS,KAAK,MAAM;AAAA,IACjC,aAAa,EAAE,cAAc,KAAK,UAAU,iBAAiB,KAAK,YAAY;AAAA,EAChF;AAAA;AAIK,IAAM,oBAAoB,CAAmC,aAA2C,aAAiD;AAAA,EAC9J,MAAM,QAAQ,YAAY,IAAI,GAAG,MAAM,aAAa,mBAAmB,EAAE,MAAM,aAAa,QAAQ,eAAe,WAAW,EAAE,EAAE;AAAA,EAElI,QAAQ;AAAA,SACD;AAAA,MACH,OAAO,MAAM,IAAI,GAAG,MAAM,aAAa,cAAc,EAAE,MAAM,aAAa,cAAc,OAAO,EAAE;AAAA,SAC9F;AAAA,MAEH,OAAO,MAAM,IAAI,GAAG,MAAM,aAAa,cAAc,EAAE,MAAM,YAAY,MAAM,aAAa,YAAY,QAAQ,QAAQ,MAAM,EAAE;AAAA,SAC7H;AAAA,MACH,OAAO,MAAM,IAAI,GAAG,MAAM,aAAa,cAAc,EAAE,MAAM,YAAY,UAAU,EAAE,MAAM,aAAa,YAAY,OAAO,EAAE,EAAE;AAAA,SAC5H;AAAA,MACH,OAAO,CAAC,EAAE,sBAAsB,MAAM,IAAI,GAAG,MAAM,aAAa,cAAc,EAAE,MAAM,aAAa,sBAAsB,OAAO,EAAE,EAAE,CAAC;AAAA;AAAA,MAErI,MAAM,IAAI,UAAU,mCAAmC,UAAU,IAAI,CAAC,SAAS,IAAI,OAAO,EAAE,KAAK,IAAI,UAAU,KAAK,UAAU,QAAQ,uHAAuH;AAAA;AAAA;AAKnQ,IAAM,iBAAiB,CAAQ,UAAwB;AAAA,EACrD,OAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AAAA;;;ACtOzC,IAAM,eAAe;AAErB,IAAM,cAAc;AAGb,IAAM,SAAS,CAAC,SAA4B;AAAA,EACjD,OAAO,IAAI,KAAK,UAAU,KAAK;AAAA;AAI1B,IAAM,cAAc,CAAC,MAAiB,UAA0B;AAAA,EACrE,MAAM,UAAU,aAAa,IAAI;AAAA,EACjC,OAAO,GAAG,KAAK,OAAO,KAAK,MAAM,KAAK,UAAU,KAAK,KAAK,QAAQ,SAAS,IAAI,MAAM,QAAQ,KAAK,IAAI,OAAO;AAAA;AAG/G,IAAM,eAAe,CAAC,SAA8B;AAAA,EAClD,MAAM,UAAoB,CAAC;AAAA,EAE3B,IAAI,KAAK,MAAM;AAAA,IACb,QAAQ,KAAK,SAAS,KAAK,MAAM;AAAA,EACnC;AAAA,EAEA,IAAI,KAAK,QAAQ;AAAA,IACf,QAAQ,KAAK,WAAW,KAAK,QAAQ;AAAA,EACvC;AAAA,EAEA,IAAI,KAAK,aAAa,WAAW;AAAA,IAC/B,QAAQ,KAAK,aAAa,KAAK,UAAU;AAAA,EAC3C;AAAA,EAEA,IAAI,KAAK,QAAQ,KAAK,KAAK,SAAS,GAAG;AAAA,IACrC,QAAQ,KAAK,SAAS,KAAK,KAAK,KAAK,IAAI,GAAG;AAAA,EAC9C;AAAA,EAEA,IAAI,KAAK,OAAO;AAAA,IACd,QAAQ,KAAK,UAAU,KAAK,OAAO;AAAA,EACrC;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IACb,QAAQ,KAAK,SAAS,KAAK,MAAM;AAAA,EACnC;AAAA,EAEA,WAAW,SAAS,CAAC,SAAS,SAAS,OAAO,GAAY;AAAA,IACxD,IAAI,KAAK,QAAQ;AAAA,MACf,QAAQ,KAAK,KAAK;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IACb,QAAQ,KAAK,SAAS,KAAK,MAAM;AAAA,EACnC;AAAA,EAEA,IAAI,KAAK,WAAW;AAAA,IAClB,QAAQ,KAAK,WAAW;AAAA,EAC1B;AAAA,EAEA,OAAO;AAAA;AAIT,IAAM,cAAc,CAAC,SAAyB;AAAA,EAC5C,MAAM,OAAO,KAAK,KAAK,EAAE,QAAQ,QAAQ,GAAG;AAAA,EAC5C,OAAO,KAAK,SAAS,eAAe,GAAG,KAAK,MAAM,GAAG,eAAe,CAAC,EAAE,QAAQ,OAAO;AAAA;AAIxF,IAAM,SAAS,CAAC,MAAiB,UAA4B;AAAA,EAC3D,MAAM,QAAQ,CAAC,YAAY,MAAM,KAAK,CAAC;AAAA,EAEvC,IAAI,KAAK,MAAM,KAAK,GAAG;AAAA,IACrB,MAAM,KAAK,GAAG,KAAK,OAAO,QAAQ,CAAC,MAAM,YAAY,KAAK,IAAI,GAAG;AAAA,EACnE;AAAA,EAEA,OAAO;AAAA;AAIF,IAAM,YAAY,CAAC,MAAiB,QAAQ,GAAG,SAAS,aAAuB;AAAA,EACpF,MAAM,QAAQ,OAAO,MAAM,KAAK;AAAA,EAEhC,IAAI,SAAS,GAAG;AAAA,IACd,WAAW,SAAS,KAAK,UAAU;AAAA,MACjC,MAAM,KAAK,GAAG,UAAU,OAAO,QAAQ,GAAG,SAAS,CAAC,CAAC;AAAA,IACvD;AAAA,EACF,EAAO,SAAI,KAAK,SAAS,SAAS,GAAG;AAAA,IACnC,MAAM,KAAK,GAAG,KAAK,OAAO,QAAQ,CAAC,QAAQ,MAAM,KAAK,SAAS,QAAQ,SAAS,UAAU,MAAM,MAAM,YAAY,IAAI,GAAG,MAAM,mBAAmB;AAAA,EACpJ;AAAA,EAEA,OAAO;AAAA;AASF,IAAM,cAAc,CAAC,OAAkB,QAAgB,UAA0D;AAAA,EACtH,IAAI,QAAQ;AAAA,EACZ,IAAI,QAAQ;AAAA,EACZ,IAAI,QAAqB,CAAC,KAAK;AAAA,EAE/B,OAAO,QAAQ,QAAQ;AAAA,IACrB,MAAM,OAAO,MAAM,QAAQ,CAAC,SAAS,KAAK,QAAQ;AAAA,IAElD,IAAI,KAAK,WAAW,KAAK,QAAQ,KAAK,SAAS,OAAO;AAAA,MACpD;AAAA,IACF;AAAA,IAEA,SAAS,KAAK;AAAA,IACd,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AAAA,EAEA,MAAM,WAAW,UAAU,UAAU,MAAM,MAAM,CAAC,SAAS,KAAK,SAAS,WAAW,CAAC;AAAA,EAErF,IAAI,UAAU,KAAK,CAAC,UAAU;AAAA,IAE5B,MAAM,WAAW,MAAM,SAAS,MAAM,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC;AAAA,IAC/D,OAAO;AAAA,MACL,OAAO;AAAA,QACL,GAAG,OAAO,OAAO,CAAC;AAAA,QAClB,GAAG,SAAS,QAAQ,CAAC,UAAU,UAAU,OAAO,GAAG,CAAC,CAAC;AAAA,QACrD,SAAS,MAAM,MAAM,SAAS,SAAS,SAAS,QAAQ,cAAc,eAAe,QAAQ,OAAO,KAAK;AAAA,MAC3G;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,EAAE,OAAO,UAAU,OAAO,GAAG,KAAK,GAAG,SAAS;AAAA;AAIhD,IAAM,cAAc,CAAC,SAA4B;AAAA,EACtD,OAAO,KAAK,SAAS,OAAO,CAAC,KAAK,UAAU,MAAM,IAAI,YAAY,KAAK,GAAG,CAAC;AAAA;AAItE,IAAM,QAAQ,CAAC,QAAgB,KAAa,OAAO,GAAG,WAAmB;AAAA,EAC9E,OAAO,GAAG,UAAU,WAAW,IAAI,MAAM;AAAA;AAIpC,IAAM,cAAc,CAAC,MAAiB,MAAiB,SAA8B;AAAA,EAC1F,MAAM,QAAQ,CAAC,OAAO,IAAI,CAAC;AAAA,EAC3B,MAAM,KAAK,KAAK,SAAS,IAAI,UAAU,KAAK,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,KAAK,KAAK,MAAM,4BAA4B;AAAA,EACjH,MAAM,SAA8B;AAAA,IAClC,CAAC,QAAQ,KAAK,IAAI;AAAA,IAClB,CAAC,UAAU,KAAK,MAAM;AAAA,IACtB,CAAC,YAAY,KAAK,QAAQ;AAAA,IAC1B,CAAC,QAAQ,KAAK,QAAQ,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,SAAS;AAAA,IAC7E,CAAC,SAAS,KAAK,KAAK;AAAA,IACpB,CAAC,QAAQ,KAAK,IAAI;AAAA,IAClB,CAAC,WAAW,KAAK,SAAS,UAAU,KAAK,MAAM,KAAK,EAAE,KAAK,KAAK,MAAM,KAAK,SAAS,KAAK,MAAM,QAAQ,CAAC,CAAC;AAAA,IACzG,CAAC,SAAS,KAAK,SAAS,UAAU,KAAK,MAAM,KAAK,EAAE,SAAS,KAAK,MAAM,QAAQ,CAAC,CAAC;AAAA,IAClF,CAAC,iBAAiB,KAAK,SAAS,UAAU,KAAK,MAAM,KAAK,EAAE,SAAS,KAAK,MAAM,QAAQ,CAAC,CAAC;AAAA,IAC1F,CAAC,QAAQ,KAAK,IAAI;AAAA,IAClB,CAAC,aAAa,KAAK,YAAY,2DAA2D,SAAS;AAAA,EACrG;AAAA,EAEA,YAAY,OAAO,UAAU,QAAQ;AAAA,IACnC,IAAI,UAAU,aAAa,UAAU,IAAI;AAAA,MACvC,MAAM,KAAK,GAAG,UAAU,OAAO,KAAK,GAAG;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC;AAAA,EAE9C,IAAI,OAAO,SAAS,GAAG;AAAA,IACrB,MAAM,KAAK,qBAAqB,OAAO,IAAI,EAAE,KAAK,WAAW,GAAG,QAAQ,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK,GAAG,EAAE,KAAK,IAAI,GAAG;AAAA,EACnJ;AAAA,EAEA,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,OAAO,KAAK,eAAe,UAAU,kBAAkB;AAAA,EAAQ,KAAK,KAAK,KAAK,MAAM,YAAY;AAAA,EAC/H,MAAM,KAAK,KAAK,SAAS,SAAS,IAAI,aAAa,KAAK,SAAS,YAAY,KAAK,SAAS,IAAI,MAAM,EAAE,KAAK,IAAI,MAAM,gBAAgB;AAAA,EACtI,MAAM,UAAU,eAAe,MAAM,IAAI;AAAA,EAEzC,IAAI,QAAQ,SAAS,GAAG;AAAA,IACtB,MAAM,KAAK,gBAAgB,QAAQ,IAAI,MAAM,EAAE,KAAK,IAAI,GAAG;AAAA,EAC7D;AAAA,EAEA,OAAO,MAAM,KAAK;AAAA,CAAI;AAAA;AAGxB,IAAM,YAAY,CAAC,KAAa,WAAuD;AAAA,EACrF,MAAM,YAAY,OAAO,QAAQ,MAAM,EAAE,OAAO,IAAI,WAAW,KAAK,EAAE,IAAI,EAAE,KAAK,WAAW,GAAG,QAAQ,OAAO;AAAA,EAC9G,OAAO,UAAU,SAAS,IAAI,GAAG,QAAQ,UAAU,KAAK,IAAI,OAAO;AAAA;AAI9D,IAAM,iBAAiB,CAAC,MAAiB,WAAmC;AAAA,EACjF,MAAM,QAAQ,WAAW,IAAI;AAAA,EAC7B,MAAM,UAAuB,CAAC;AAAA,EAE9B,MAAM,QAAQ,CAAC,SAA0B;AAAA,IACvC,IAAI,YAAY,IAAI,EAAE,KAAK,CAAC,SAAS,sBAAsB,OAAO,IAAI,MAAM,MAAM,GAAG;AAAA,MACnF,QAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,IAEA,KAAK,SAAS,QAAQ,KAAK;AAAA;AAAA,EAG7B,MAAM,IAAI;AAAA,EACV,OAAO;AAAA;AAIF,IAAM,aAAa,CAAC,SAAyB;AAAA,EAClD,OAAO,KAAK,UAAU,MAAM,EAAE,QAAQ,YAAY,EAAE,EAAE,YAAY;AAAA;AAW7D,IAAM,YAAY,CAAC,MAAiB,WAA2B;AAAA,EACpE,MAAM,QAAQ,WAAW,OAAO,SAAS,EAAE,EAAE,MAAM,KAAK,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE;AAAA,EACtF,MAAM,SAAS,OAAO,WAAW,YAAY,YAAY,WAAW,OAAO,OAAO,KAAK,CAAC;AAAA,EACxF,MAAM,MAAM,OAAO,QAAQ,YAAY,YAAY,WAAW,OAAO,IAAI,KAAK,EAAE,QAAQ,MAAM,EAAE,CAAC;AAAA,EAEjG,MAAM,gBAAgB,CAAC,SAA6B;AAAA,IAClD,IAAI,WAAW,WAAW;AAAA,MACxB,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,CAAC,KAAK,QAAQ;AAAA,MAChB,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,MAAM,WAAW,KAAK,OAAO,KAAK,CAAC;AAAA,IACzC,MAAM,OAAO,WAAW,MAAM;AAAA,IAC9B,OAAO,QAAQ,UAAW,SAAS,aAAa,WAAW,GAAG,MAAM;AAAA;AAAA,EAGtE,MAAM,UAAsE,CAAC;AAAA,EAE7E,MAAM,QAAQ,CAAC,MAAiB,SAA4B;AAAA,IAC1D,MAAM,QAAQ,WAAW,CAAC,KAAK,MAAM,GAAI,KAAK,QAAQ,CAAC,CAAE,EAAE,KAAK,GAAG,CAAC;AAAA,IACpE,MAAM,aAAa,GAAG,SAAS,WAAW,KAAK,QAAQ,EAAE;AAAA,IAEzD,IAAI,MAAM,MAAM,CAAC,SAAS,WAAW,SAAS,IAAI,CAAC,KAC9C,cAAc,IAAI,MACjB,QAAQ,cAAc,KAAK,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,WAAW,GAAG,MAAM,GAAG,IAAI;AAAA,MACpF,QAAQ,KAAK,EAAE,MAAM,MAAM,SAAS,MAAM,MAAM,CAAC,SAAS,MAAM,SAAS,IAAI,CAAC,EAAE,CAAC;AAAA,IACnF;AAAA,IAEA,KAAK,SAAS,QAAQ,CAAC,UAAU,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;AAAA;AAAA,EAGhE,MAAM,MAAM,CAAC,CAAC;AAAA,EAEd,IAAI,QAAQ,WAAW,GAAG;AAAA,IACxB,OAAO;AAAA,EACT;AAAA,EAEA,QAAQ,KAAK,CAAC,OAAO,WAAW,OAAO,OAAO,OAAO,IAAI,OAAO,MAAM,OAAO,CAAC;AAAA,EAC9E,MAAM,QAAQ,QAAQ,MAAM,GAAG,WAAW;AAAA,EAC1C,MAAM,QAAQ,CAAC,GAAG,MAAM,QAAQ,QAAQ,gBAAgB,aAAa,IAAI,QAAQ,SAAS,MAAM,SAAS,eAAe,MAAM,WAAW,KAAK;AAAA,EAE9I,aAAa,MAAM,UAAU,OAAO;AAAA,IAClC,MAAM,KAAK,GAAG,YAAY,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,KAAK,KAAK,MAAM,gBAAgB;AAAA,EAC/H;AAAA,EAEA,IAAI,QAAQ,SAAS,MAAM,QAAQ;AAAA,IACjC,MAAM,KAAK,sCAAsC;AAAA,EACnD;AAAA,EAEA,OAAO,MAAM,KAAK;AAAA,CAAI;AAAA;;;AChQxB,IAAM,aAAa;AAEnB,IAAM,aAAa;AAEnB,IAAM,eAAe;AAErB,IAAM,yBAAyB,IAAI,IAAI,CAAC,kBAAkB,gBAAgB,qBAAqB,CAAC;AAAA;AA+DhG,MAAM,kBAAkB,MAAM;AAAC;AAcxB,IAAM,iBAAiB,CAAC,KAAgD,UAA2B,CAAC,MAAgB;AAAA,EACzH,MAAM,SAAS,SAAS,GAAG;AAAA,EAC3B,MAAM,YAAY,OAAO,QAAQ,cAAc,YAAY,OAAO,SAAS,QAAQ,SAAS,IAAI,KAAK,IAAI,IAAI,KAAK,MAAM,QAAQ,SAAS,CAAC,IAAI;AAAA,EAC9I,MAAM,QAAQ,WAAW,OAAO,CAAC,UAAU,KAAK,SAAS,eAAe,OAAO,SAAS,UAAU,KAAK,YAAY,CAAC,QAAQ,SAAS;AAAA,EACrI,MAAM,cAAc,MAAM,IAAI,YAAY;AAAA,EAE1C,MAAM,UAAU,IAAI;AAAA,EACpB,MAAM,UAAU,IAAI;AAAA,EACpB,MAAM,QAAkB,CAAC;AAAA,EAGzB,MAAM,UAAU,CAAC,MAAiB,OAAe,UAA6B;AAAA,IAC5E,MAAM,KAAK,MAAM,KAAK,EAAE,QAAQ,MAAM,EAAE;AAAA,IACxC,MAAM,SAAS,cAAa,MAAM,EAAE;AAAA,IAEpC,IAAI,QAAQ;AAAA,MACV,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,UAAU;AAAA,IACd,MAAM,OAAO,IAAI;AAAA,IAEjB,OAAO,QAAQ,IAAI,OAAO,KAAK,CAAC,KAAK,IAAI,OAAO,GAAG;AAAA,MACjD,KAAK,IAAI,OAAO;AAAA,MAChB,UAAU,QAAQ,IAAI,OAAO;AAAA,IAC/B;AAAA,IAEA,MAAM,WAAW,YAAY,KAAK,OAAO,cAAa,MAAM,OAAO;AAAA,IAEnE,IAAI,UAAU;AAAA,MACZ,MAAM,KAAK,IAAI,SAAS,OAAO,QAAQ,QAAQ;AAAA,MAC/C,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,QAAQ,IAAI,EAAE,GAAG;AAAA,MACnB,MAAM,IAAI,UAAU,GAAG,gBAAgB,YAAY,QAAQ,IAAI,EAAE,iBAAiB;AAAA,IACpF;AAAA,IAEA,MAAM,SAAS,WAAW,EAAE;AAAA,IAC5B,MAAM,SAAS,SAAS,IAAI,EAAE,OAAO,CAAC,SAAS,WAAW,KAAK,KAAK,KAAK,CAAC,MAAM,UAAU,KAAK,OAAO,SAAS,EAAE,CAAC;AAAA,IAElH,IAAI,OAAO,WAAW,GAAG;AAAA,MACvB,MAAM,KAAK,GAAG,+BAA+B,OAAO,GAAG,aAAa,OAAO,GAAG,KAAK;AAAA,MACnF,OAAO,OAAO;AAAA,IAChB;AAAA,IAEA,IAAI,OAAO,SAAS,GAAG;AAAA,MACrB,MAAM,IAAI,UAAU,GAAG,OAAO,4BAA4B,WAAW,OAAO,IAAI,CAAC,SAAS,GAAG,OAAO,IAAI,IAAI,KAAK,SAAS,WAAW,KAAK,OAAO,UAAU,IAAI,EAAE,KAAK,IAAI,WAAW,yBAAyB;AAAA,IAChN;AAAA,IAEA,MAAM,OAAO,QAAQ,IAAI,SAAS,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAAA,IAC9D,MAAM,WAAW,SAAS,YAAY,OAAO,cAAa,MAAM,IAAI;AAAA,IACpE,MAAM,IAAI,UAAU,uBAAuB,OAAO,WAAW,iBAAiB,OAAO,QAAQ,OAAO,kDAAkD;AAAA;AAAA,EAGxJ,MAAM,QAAqH;AAAA,IACzH,UAAU,CAAC,QAAQ,MAAM,aAAa;AAAA,MACpC,MAAM,QAAQ,OAAO,OAAO,YAAY,WAAW,QAAQ,MAAM,OAAO,SAAS,SAAS,IAAI;AAAA,MAC9F,MAAM,SAAS,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAAA,MACjE,QAAQ,OAAO,aAAa,YAAY,OAAO,QAAQ,SAAS;AAAA,MAChE,MAAM,SAAmB,CAAC;AAAA,MAE1B,IAAI,UAAU,MAAM;AAAA,QAClB,MAAM,QAAQ,SAAS,QAAQ,SAAS,KAAK;AAAA,QAC7C,OAAO,KAAK,YAAY,cAAc,MAAM,IAAI,YAAY,IAAI,GAAG,MAAM,IAAI;AAAA,MAC/E,EAAO;AAAA,QACL,MAAM,OAAO,aAAY,MAAM,MAAM,EAAE;AAAA,QACvC,OAAO,KAAK,GAAG,OAAO,KAAK,SAAS,KAAK,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,KAAK,KAAK,UAAU,MAAM,YAAY,KAAK,GAAG,MAAM,aAAa;AAAA;AAAA,MAGlJ,MAAM,OAAO,OAAO;AAAA,MAEpB,IAAI,MAAM;AAAA,QACR,MAAM,UAAU,KAAK,eAAe;AAAA,QACpC,OAAO,KAAK,KAAK,YAAY,MAAM,SAAS,CAAC,UAAU,4CAA4C,4BAA4B,OAAO,OAAO,IAAI;AAAA,MACnJ;AAAA,MAEA,MAAM,SAAS,WAAW,CAAC,IAAI,CAAC,0GAA2G;AAAA,MAC3I,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,GAAG,GAAG,GAAG,OAAO,GAAG,MAAM,EAAE,KAAK;AAAA,CAAI,GAAG,SAAS,MAAM;AAAA;AAAA,IAGpF,YAAY,CAAC,QAAQ,SAAS;AAAA,MAC5B,IAAI,OAAO,UAAU,aAAa,OAAO,WAAW,aAAa,OAAO,QAAQ,WAAW;AAAA,QACzF,MAAM,IAAI,UAAU,+EAA+E;AAAA,MACrG;AAAA,MAEA,OAAO,EAAE,MAAM,UAAU,MAAM,MAAgB,GAAG,SAAS,MAAM;AAAA;AAAA,IAGnE,WAAW,CAAC,QAAQ,SAAS;AAAA,MAC3B,MAAM,OAAO,QAAQ,MAAM,OAAO,SAAmB,SAAS;AAAA,MAC9D,OAAO,EAAE,MAAM,YAAY,MAAM,MAAM,aAAY,MAAM,KAAK,EAAE,CAAC,GAAG,SAAS,MAAM;AAAA;AAAA,IAGrF,WAAW,CAAC,QAAQ,SAAS;AAAA,MAC3B,MAAM,SAAS,QAAQ,MAAM,OAAO,WAAqB,WAAW;AAAA,MACpE,MAAM,QAAQ,aAAa,OAAO,OAAiB;AAAA,MACnD,MAAM,QAAQ,OAAO;AAAA,MACrB,MAAM,QAAqB,CAAC;AAAA,MAE5B,MAAM,QAAQ,CAAC,OAAO,WAAW;AAAA,QAC/B,MAAM,OAAO,OAAO,IAAI,OAAO,IAAI,OAAO,UAAU,YAAY,YAAY,QAAQ,MAAM;AAAA,QAE1F,IAAI,MAAM;AAAA,UACR,MAAM,KAAK,IAAI;AAAA,QACjB;AAAA,OACD;AAAA,MAED,IAAI,MAAM,WAAW,GAAG;AAAA,QACtB,MAAM,IAAI,UAAU,gCAAgC,OAAO,MAAM,IAAI;AAAA,MACvE;AAAA,MAEA,WAAW,QAAQ,OAAO;AAAA,QACxB,MAAM,OAAO,OAAO,SAAS,KAAK,CAAC,YAAY,YAAY,QAAQ,CAAC,MAAM,SAAS,OAAO,KAAK,WAAW,QAAQ,IAAI,MAAM,WAAW,KAAK,IAAI,CAAC;AAAA,QAEjJ,IAAI,MAAM;AAAA,UACR,MAAM,KAAK,GAAG,OAAO,IAAI,2BAA2B,OAAO,IAAI,2EAA2E;AAAA,QAC5I;AAAA,MACF;AAAA,MAEA,MAAM,MAAM,MAAM,QAAQ,QAAQ;AAAA,MAClC,MAAM,OAAO,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,SAAS,UAAU;AAAA,MAE/D,IAAI,KAAK,SAAS,GAAG;AAAA,QACnB,MAAM,KAAK,GAAG,KAAK,IAAI,MAAM,EAAE,KAAK,IAAI,KAAK,KAAK,WAAW,IAAI,qBAAqB,kFAAkF;AAAA,MAC1K;AAAA,MAEA,MAAM,KAAK,GAAG,YAAY,OAAO,SAAS,GAAG,QAAQ,MAAM,GAAG,CAAC;AAAA,MAC/D,OAAO;AAAA,QACL,MAAM,CAAC,SAAS,MAAM,IAAI,QAAQ,MAAM,WAAW,OAAO,MAAM,IAAI,QAAQ,OAAO,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,SAAS,UAAU,IAAI,CAAC,CAAC,EAAE,KAAK;AAAA,CAAI;AAAA,QACrJ,SAAS,MAAM,SAAS;AAAA,MAC1B;AAAA;AAAA,IAGF,aAAa,CAAC,QAAQ,SAAS;AAAA,MAC7B,MAAM,OAAO,QAAQ,MAAM,OAAO,SAAmB,SAAS;AAAA,MAC9D,MAAM,aAAa,KAAK;AAAA,MACxB,QAAQ,SAAS,KAAK,SAAS,WAAW,YAAY,QAAQ,MAAM,IAAI;AAAA,MAExE,IAAI,IAAI,WAAW,KAAK,QAAQ,WAAW,GAAG;AAAA,QAC5C,IAAI,OAAO,WAAW,GAAG;AAAA,UACvB,MAAM,IAAI,UAAU,0CAA0C,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC,mCAAmC;AAAA,QAC/H;AAAA,QAEA,OAAO,EAAE,MAAM,GAAG,OAAO,IAAI,YAAY,KAAK,MAAM,iCAAiC,SAAS,MAAM;AAAA,MACtG;AAAA,MAEA,MAAM,UAAU,OAAO,OAAO,KAAK,IAAI,OAAO;AAAA,MAE9C,IAAI,CAAC,SAAS;AAAA,QACZ,MAAM,IAAI,UAAU,GAAG,OAAO,IAAI,wBAAwB;AAAA,MAC5D;AAAA,MAEA,IAAI,QAAQ,SAAS,WAAW;AAAA,QAC9B,MAAM,KAAK,GAAG,YAAY,MAAM,CAAC,OAAO,CAAC,CAAC;AAAA,MAC5C;AAAA,MAEA,MAAM,YAAY,CAAC,IAAI,SAAS,IAAI,WAAW,KAAK,GAAG,MAAM,IAAI,QAAQ,SAAS,IAAI,eAAe,KAAK,OAAO,MAAM,EAAE,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE,EAAE,KAAK,IAAI;AAAA,MAClK,IAAI,OAAO,WAAW,OAAO,OAAO,MAAM;AAAA,MAE1C,IAAI,QAAQ,OAAO,YAAY;AAAA,QAC7B,QAAQ,IAAI,YAAY,QAAQ,EAAE;AAAA,QAClC,QAAQ,eAAe,QAAQ,mBAAmB;AAAA,MACpD;AAAA,MAEA,OAAO,EAAE,MAAM,SAAS,KAAK;AAAA;AAAA,IAG/B,WAAW,CAAC,QAAQ,SAAS;AAAA,MAC3B,MAAM,OAAO,QAAQ,MAAM,OAAO,SAAmB,SAAS;AAAA,MAE9D,IAAI,OAAO,cAAc,aAAa,OAAO,UAAU,WAAW;AAAA,QAChE,MAAM,IAAI,UAAU,oEAAoE;AAAA,MAC1F;AAAA,MAEA,MAAM,OAAO,aAAY,MAAM,KAAK,EAAE;AAAA,MAEtC,IAAI,KAAK,SAAS,GAAG;AAAA,QACnB,MAAM,IAAI,UAAU,GAAG,OAAO,IAAI,gEAAgE;AAAA,MACpG;AAAA,MAEA,MAAM,SAAS,OAAO,cAAc,YAAY,KAAK,KAAK,SAAS,KAAK,QAAQ,MAAM,OAAO,WAAqB,WAAW;AAAA,MAE7H,IAAI,WAAW,MAAM;AAAA,QACnB,MAAM,IAAI,UAAU,GAAG,OAAO,IAAI,uDAAuD;AAAA,MAC3F;AAAA,MAEA,IAAI,aAAY,MAAM,OAAO,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,QAC/C,MAAM,IAAI,UAAU,GAAG,OAAO,IAAI,oBAAoB,OAAO,MAAM,+BAA+B,OAAO,MAAM,8CAA8C;AAAA,MAC/J;AAAA,MAEA,MAAM,QAAQ,YAAY,IAAI;AAAA,MAC9B,MAAM,QAAQ,OAAO,KAAK,KAAK,IAAI,OAAO,IAAI,OAAO,KAA2B;AAAA,MAEhF,IAAI,CAAC,OAAO;AAAA,QACV,MAAM,IAAI,UAAU,GAAG,OAAO,IAAI,sBAAsB;AAAA,MAC1D;AAAA,MAEA,OAAO,EAAE,MAAM,SAAS,OAAO,KAAK,IAAI,QAAQ,IAAI,cAAc,MAAM,OAAO,MAAM,gBAAgB,YAAY,OAAO,MAAM,IAAI,QAAQ,CAAC,KAAK,GAAG,MAAM,MAAM,SAAS,KAAK;AAAA;AAAA,IAG/K,kBAAkB,CAAC,QAAQ,SAAS;AAAA,MAClC,MAAM,SAAS,QAAQ,MAAM,OAAO,WAAqB,WAAW;AAAA,MACpE,MAAM,WAAW,CAAC,GAAG,OAAO,QAAQ;AAAA,MAEpC,IAAI,SAAS,WAAW,GAAG;AAAA,QACzB,MAAM,IAAI,UAAU,GAAG,OAAO,MAAM,+BAA+B;AAAA,MACrE;AAAA,MAEA,MAAM,QAAS,OAAO,MAAmB,IAAI,CAAC,UAAU,WAAW,QAAQ,KAAK,CAAC;AAAA,MACjF,MAAM,QAAQ,MAAM,KAAK,CAAC,OAAO,aAAa,MAAM,QAAQ,KAAK,MAAM,QAAQ;AAAA,MAE/E,IAAI,OAAO;AAAA,QACT,MAAM,IAAI,UAAU,eAAe,OAAO,KAAK,gCAAgC;AAAA,MACjF;AAAA,MAEA,MAAM,UAAU,SAAS,OAAO,CAAC,UAAU,CAAC,MAAM,SAAS,KAAK,CAAC;AAAA,MAEjE,IAAI,QAAQ,SAAS,GAAG;AAAA,QACtB,MAAM,IAAI,UAAU,mBAAmB,SAAS,sBAAsB,OAAO,MAAM,qBAAqB,QAAQ,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI;AAAA,MAC3I;AAAA,MAEA,IAAI,MAAM,MAAM,CAAC,OAAO,aAAa,SAAS,cAAc,KAAK,GAAG;AAAA,QAClE,OAAO,EAAE,MAAM,mBAAmB,OAAO,MAAM,gCAAgC,SAAS,MAAM;AAAA,MAChG;AAAA,MAEA,MAAM,QAAQ,CAAC,OAAO,aAAa;AAAA,QACjC,MAAM,UAAU,cAAa,OAAO,SAAS,GAAG,QAAQ,MAAM,OAAO,EAAE,KAAK;AAAA,QAE5E,IAAI,QAAQ,SAAS,WAAW,OAAO,MAAM,IAAI;AAAA,UAC/C,OAAO,KAAK,MAAM,IAAI,OAAO,IAAI,QAAQ;AAAA,QAC3C;AAAA,OACD;AAAA,MAED,OAAO,EAAE,MAAM,mBAAmB,OAAO,MAAM,4BAA4B,MAAM,IAAI,MAAM,EAAE,KAAK,IAAI,MAAM,SAAS,KAAK;AAAA;AAAA,IAG5H,aAAa,CAAC,QAAQ,SAAS;AAAA,MAC7B,MAAM,OAAO,QAAQ,MAAM,OAAO,SAAmB,SAAS;AAAA,MAE9D,IAAI,SAAS,MAAM;AAAA,QACjB,MAAM,IAAI,UAAU,GAAG,OAAO,IAAI,iJAAiJ;AAAA,MACrL;AAAA,MAEA,MAAM,OAAO,SAAS,IAAI;AAAA,MAE1B,IAAI,CAAC,OAAO,OAAO,KAAK,EAAE,GAAG;AAAA,QAC3B,MAAM,IAAI,UAAU,GAAG,OAAO,IAAI,wBAAwB;AAAA,MAC5D;AAAA,MAEA,WAAW,QAAQ,MAAM;AAAA,QACvB,QAAQ,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,MAChC;AAAA,MAEA,OAAO,EAAE,MAAM,WAAW,OAAO,IAAI,IAAI,KAAK,SAAS,IAAI,YAAY,MAAM,KAAK,SAAS,GAAG,MAAM,eAAe,OAAO,SAAS,KAAK;AAAA;AAAA,IAG1I,WAAW,CAAC,QAAQ,SAAS;AAAA,MAC3B,MAAM,OAAO,QAAQ,MAAM,OAAO,SAAmB,SAAS;AAAA,MAC9D,OAAO,MAAM,MAAM,KAAK,EAAE;AAAA,MAC1B,OAAO,EAAE,MAAM,iBAAiB,OAAO,IAAI,uCAAuC,SAAS,MAAM;AAAA;AAAA,EAErG;AAAA,EAGA,MAAM,aAAa,CAAC,QAAmB,UAA6B;AAAA,IAClE,MAAM,KAAK,MAAM,KAAK,EAAE,QAAQ,MAAM,EAAE;AAAA,IACxC,MAAM,QAAQ,OAAO,SAAS,KAAK,CAAC,SAAS,KAAK,OAAO,MAAM,KAAK,OAAO,QAAQ,IAAI,EAAE,CAAC,KACrF,OAAO,SAAS,KAAK,CAAC,SAAS,WAAW,KAAK,KAAK,KAAK,CAAC,MAAM,WAAW,EAAE,CAAC;AAAA,IAEnF,IAAI,CAAC,OAAO;AAAA,MACV,MAAM,IAAI,UAAU,GAAG,0BAA0B,OAAO,MAAM,oBAAoB,OAAO,SAAS,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI;AAAA,IAC7H;AAAA,IAEA,OAAO;AAAA;AAAA,EAGT,MAAM,MAAM,CAAC,MAAc,UAAmC;AAAA,IAC5D,MAAM,SAAS;AAAA,IACf,MAAM,OAAO,WAAW,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI;AAAA,IACzD,MAAM,UAAU,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI;AAAA,IAEvD,IAAI,CAAC,SAAS;AAAA,MACZ,IAAI,MAAM,SAAS,aAAa;AAAA,QAC9B,OAAO,QAAQ,0CAA0C;AAAA,MAC3D;AAAA,MAEA,IAAI,MAAM;AAAA,QACR,OAAO,QAAQ,GAAG,kDAAkD;AAAA,MACtE;AAAA,MAEA,MAAM,OAAO,QAAQ,OAAO,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;AAAA,MACjE,OAAO,QAAQ,oBAAoB,OAAO,IAAI,MAAM,SAAS,YAAY,KAAK,iBAAiB,yBAAyB,KAAK,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,IAAI;AAAA,IACjK;AAAA,IAEA,MAAM,WAAW,OAAO,SAAS;AAAA,IAEjC,IAAI,CAAC,UAAU;AAAA,MACb,OAAO,QAAQ,mDAAqD;AAAA,IACtE;AAAA,IAEA,IAAI,CAAC,QAAQ,YAAY,OAAO,OAAO;AAAA,MACrC,OAAO,QAAQ,qJAAsJ;AAAA,IACvK;AAAA,IAEA,IAAI;AAAA,MACF,QAAQ,QAAQ,YAAY,UAAU,QAAQ,MAAM,QAAQ,QAAQ,OAAO,QAAQ,QAAQ;AAAA,MAC3F,MAAM,UAAU,MAAM,QAAQ,MAAM,QAAQ,SAAS,MAAM,QAAQ;AAAA,MAEnE,IAAI,QAAQ,SAAS,GAAG;AAAA,QACtB,MAAM,KAAK,GAAG,QAAQ,qBAAqB,KAAK,QAAQ,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,SAAS,QAAQ,WAAW,IAAI,WAAW,kCAAkC,KAAK,OAAO,KAAK,QAAQ,MAAM,CAAC,IAAI;AAAA,MACnM;AAAA,MAEA,OAAO,EAAE,IAAI,MAAM,MAAM,CAAC,QAAQ,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,SAAS,MAAM,CAAC,EAAE,KAAK;AAAA,CAAI,GAAG,SAAS,QAAQ,QAAQ;AAAA,MACtH,OAAO,OAAO;AAAA,MACd,IAAI,iBAAiB,aAAa,iBAAiB,YAAY;AAAA,QAC7D,OAAO,QAAQ,MAAM,SAAS,OAAO;AAAA,MACvC;AAAA,MAEA,MAAM;AAAA;AAAA;AAAA,EAIV,OAAO;AAAA,IACL;AAAA,IACA,cAAc,gBAAgB,OAAO,SAAS,MAAM,QAAQ,aAAa,IAAI;AAAA,IAC7E,KAAK,CAAC,aAAa,kBAAkB,aAAa,QAAQ;AAAA,IAC1D;AAAA,QACI,QAAQ,GAAG;AAAA,MACb,OAAO,OAAO,SAAS;AAAA;AAAA,EAE3B;AAAA;AAGF,IAAM,UAAU,CAAC,SAAiB,SAAmC;AAAA,EACnE,OAAO,EAAE,IAAI,OAAO,MAAM,QAAQ,CAAC,KAAK,WAAW,GAAG,6BAA6B,SAAS,SAAS,MAAM;AAAA;AAG7G,IAAM,WAAW,CAAC,QAA2D;AAAA,EAC3E,IAAI,UAAU,GAAG,GAAG;AAAA,IAClB,OAAO;AAAA,MACL,UAAU,MAAM,IAAI,YAAY;AAAA,MAChC,KAAK,CAAC,UAAU,OAAO,UAAU,IAAI,QAAQ,UAAU,OAAO,KAAK;AAAA,MACnE,QAAQ,CAAC,IAAI,YAAY,IAAI,WAAW,IAAI,OAAO;AAAA,MACnD,MAAM,CAAC,IAAI,UAAU,UAAU,IAAI,SAAS,IAAI,UAAU,KAAK;AAAA,MAC/D,QAAQ,CAAC,OAAO,IAAI,WAAW,EAAE;AAAA,MACjC,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,OAAO,QAAQ,WAAW,YAAW,GAAG,IAAI;AAAA,EAE7D,IAAI,CAAC,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,QAAQ,CAAC,MAAM,QAAQ,SAAS,KAAK,QAAQ,GAAG;AAAA,IACzG,MAAM,IAAI,UAAU,wJAAwJ,QAAQ,OAAO,SAAS,OAAO,MAAM;AAAA,EACnN;AAAA,EAEA,OAAO;AAAA,IACL,UAAU,MAAM;AAAA,IAChB,KAAK,CAAC,UAAU,OAAO,UAAU,UAAU,SAAS,MAAM,UAAU,OAAO,KAAK,GAAG,QAAQ;AAAA,IAC3F,QAAQ,CAAC,IAAI,YAAY,aAAa,SAAS,MAAM,IAAI,OAAO,GAAG,QAAQ;AAAA,IAC3E,MAAM,CAAC,IAAI,UAAU,UAAU,WAAW,SAAS,MAAM,IAAI,UAAU,KAAK,GAAG,QAAQ;AAAA,IACvF,QAAQ,CAAC,OAAO,eAAe,SAAS,MAAM,EAAE,GAAG,QAAQ;AAAA,IAC3D,MAAM;AAAA,IACN,QAAQ,SAAS,eAAe,CAAC,GAAG,KAAK,CAAC,eAAe,WAAW,SAAS,4BAA4B;AAAA,EAC3G;AAAA;AAGF,IAAM,YAAY,CAAC,QAAiC;AAAA,EAClD,MAAM,YAAY;AAAA,EAClB,OAAO,OAAO,cAAc,YAAY,cAAc,QAAQ,OAAO,UAAU,gBAAgB,cAAc,OAAO,UAAU,YAAY;AAAA;AAI5I,IAAM,kBAAkB,CAAC,MAAe,aAA8B;AAAA,EACpE,MAAM,QAAQ,WACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEF,IAAI,MAAM;AAAA,IACR,MAAM,KAAK,WAAW,4CAA4C,8FAA8F;AAAA,EAClK;AAAA,EAEA,OAAO,MAAM,KAAK;AAAA,CAAI;AAAA;AAIxB,IAAM,WAAW,CAAC,SAAiC;AAAA,EACjD,OAAO,CAAC,MAAM,GAAG,KAAK,SAAS,QAAQ,QAAQ,CAAC;AAAA;AAIlD,IAAM,UAAU,CAAC,OAAoB,WAA8B;AAAA,EACjE,MAAM,QAAQ,OAAO,SAAS,QAAQ,MAAM,EAAE;AAAA,EAC9C,MAAM,OAAO,OAAO,SAAS,QAAQ,MAAM,MAAM,SAAS,EAAE;AAAA,EAE5D,IAAI,QAAQ,GAAG;AAAA,IACb,OAAO,WAAW,OAAO,OAAO,SAAS,QAAQ,EAAE;AAAA,EACrD;AAAA,EAEA,IAAI,UAAU,KAAK,OAAO,OAAO,SAAS,SAAS,GAAG;AAAA,IACpD,OAAO,mBAAmB,OAAO,OAAO,SAAS,OAAO,EAAE;AAAA,EAC5D;AAAA,EAEA,OAAO;AAAA;AAIT,IAAM,cAAc,CAAC,MAAiB,UAAiC;AAAA,EACrE,MAAM,QAAQ,WAAW,IAAI;AAAA,EAC7B,MAAM,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC;AAAA,EAE5B,OAAO,MAAM,QAAQ,CAAC,SAAS,YAAY,IAAI,EAC5C,OAAO,CAAC,SAAS,CAAC,sBAAsB,OAAO,IAAI,CAAC,EACpD,IAAI,CAAC,SAAS;AAAA,IACb,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC,GAAG,GAAG;AAAA,IACvC,OAAO,GAAG,OAAO,IAAI,cAAc,iCAAiC,SAAS,YAAY,KAAK,kBAAkB;AAAA,GACjH,CAAC;AAAA;AAQN,IAAM,eAAe,CAAC,YAAoC;AAAA,EACxD,IAAI,SAAS,QAAQ,QAAQ,UAAU;AAAA,CAAI;AAAA,EAE3C,IAAI,eAAe,KAAK,MAAM,GAAG;AAAA,IAC/B,MAAM,IAAI,UAAU,yEAAyE;AAAA,EAC/F;AAAA,EAEA,IAAI,WAAW,oBAAmB,MAAM;AAAA,EAExC,IAAI,SAAS,YAAY,KAAK,CAAC,eAAe,WAAW,SAAS,cAAc,GAAG;AAAA,IACjF,SAAS,OAAO,MAAM;AAAA,CAAI,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE,EAAE,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,CAAI;AAAA,IACzH,WAAW,oBAAmB,MAAM;AAAA,EACtC;AAAA,EAEA,MAAM,QAAQ,SAAS,YAAY,KAAK,CAAC,eAAe,WAAW,SAAS,gBAAgB,IAAI,SAAS,KAAK,WAAW,CAAC,SAAS,IAAI;AAAA,EACvI,MAAM,WAAW,MAAM,QAAQ,QAAQ,EAAE,KAAK,CAAC,SAAS,KAAK,KAAK,KAAK,MAAM,EAAE;AAAA,EAE/E,IAAI,MAAM,WAAW,KAAK,UAAU;AAAA,IAClC,MAAM,IAAI,UAAU,UAAU,SAC1B,QAAQ,SAAS,OAAO,iDACxB,4FAA4F;AAAA,EAClG;AAAA,EAGA,MAAM,WAAW,SAAS,YACvB,OAAO,CAAC,eAAe,CAAC,uBAAuB,IAAI,WAAW,IAAI,CAAC,EACnE,IAAI,CAAC,eAAe,kBAAiB,UAAU,EAAE,QAAQ,kEAAkE,EAAE,CAAC;AAAA,EAEjI,IAAI,SAAS,SAAS,GAAG;AAAA,IACvB,MAAM,IAAI,UAAU,qCAAqC,SAAS,WAAW,IAAI,SAAS;AAAA,EAAgC,SAAS,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,KAAK;AAAA,CAAI;AAAA,2CAA+C;AAAA,EAC9N;AAAA,EAEA,OAAO,MAAM,IAAI,WAAW;AAAA;AAY9B,IAAM,cAAc,CAAC,QAAiC,MAAiB,SAA6B;AAAA,EAClG,MAAM,UAA0B,CAAC;AAAA,EACjC,MAAM,MAAgB,CAAC;AAAA,EACvB,MAAM,QAAQ,IAAI,IAAK,OAAO,SAAyC,CAAC,CAAC;AAAA,EACzE,MAAM,UAAoB,CAAC;AAAA,EAC3B,MAAM,SAAmB,CAAC;AAAA,EAE1B,MAAM,SAAS,CAAC,SAAwB;AAAA,IACtC,IAAI,KAAK,UAAU,WAAW;AAAA,MAC5B,OAAO,KAAK,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,IAEC,QAAoC,QAAQ;AAAA,IAC7C,QAAQ,KAAK,IAAI;AAAA;AAAA,EAGnB,WAAW,QAAQ,OAAO;AAAA,IACxB,IAAI,OAAO,UAAU,WAAW;AAAA,MAC9B,MAAM,IAAI,UAAU,GAAG,gEAAgE;AAAA,IACzF;AAAA,IAEA,OAAO,IAAI;AAAA,EACb;AAAA,EAEA,IAAI,OAAO,SAAS,WAAW;AAAA,IAC7B,IAAI,OAAO,OAAO,OAAO,IAAI,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAAA,IAEzD,IAAI,SAAS,IAAI;AAAA,MACf,MAAM,IAAI,UAAU,gGAAiG;AAAA,IACvH;AAAA,IAEA,MAAM,QAAQ,aAAa,IAAI;AAAA,IAE/B,IAAI,SAAS,OAAO,SAAS,aAAa,CAAC,MAAM,IAAI,MAAM,GAAG;AAAA,MAE5D,QAAQ,OAAO,MAAM;AAAA,MACrB,OAAO,MAAM;AAAA,MACb,IAAI,KAAK,MAAM;AAAA,IACjB;AAAA,IAEA,QAAQ,OAAO;AAAA,IACf,IAAI,KAAK,OAAO;AAAA,EAClB;AAAA,EAEA,MAAM,OAAO,CAAC,SAA4E;AAAA,IACxF,MAAM,QAAQ,OAAO;AAAA,IAErB,IAAI,UAAU,WAAW;AAAA,MACvB;AAAA,IACF;AAAA,IAEA,MAAM,UAAU,SAAS,SAAS,OAAO,KAAK,EAAE,KAAK,IAAI,OAAO,KAAK,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAAA,IAEjG,IAAI,YAAY,IAAI;AAAA,MAClB,OAAO,IAAI;AAAA,MACX;AAAA,IACF;AAAA,IAEA,IAAI,KAAK,IAAI;AAAA,IACb,OAAO;AAAA;AAAA,EAGT,MAAM,OAAO,KAAK,MAAM;AAAA,EAExB,IAAI,SAAS,WAAW;AAAA,IACtB,QAAQ,OAAO;AAAA,EACjB;AAAA,EAEA,MAAM,SAAS,KAAK,QAAQ;AAAA,EAE5B,IAAI,WAAW,WAAW;AAAA,IACxB,QAAQ,SAAS;AAAA,EACnB;AAAA,EAEA,IAAI,OAAO,aAAa,WAAW;AAAA,IACjC,QAAQ,WAAW,OAAO;AAAA,IAC1B,IAAI,KAAK,UAAU;AAAA,EACrB;AAAA,EAEA,IAAI,OAAO,SAAS,WAAW;AAAA,IAC7B,MAAM,OAAO,CAAC,GAAG,IAAI,IAAK,OAAO,KAAkB,IAAI,CAAC,QAAQ,IAAI,QAAQ,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC;AAAA,IAE1H,IAAI,KAAK,WAAW,GAAG;AAAA,MACrB,OAAO,MAAM;AAAA,IACf,EAAO;AAAA,MACL,QAAQ,OAAO;AAAA,MACf,IAAI,KAAK,MAAM;AAAA;AAAA,EAEnB;AAAA,EAEA,MAAM,OAAO,KAAK,MAAM;AAAA,EAExB,IAAI,SAAS,WAAW;AAAA,IACtB,IAAI,mCAAmC,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI,EAAE,SAAS,GAAG;AAAA,MAChF,MAAM,IAAI,UAAU,kDAAwC,KAAK,UAAU,IAAI,IAAI;AAAA,IACrF;AAAA,IAEA,QAAQ,OAAO;AAAA,EACjB;AAAA,EAEA,MAAM,QAAQ,KAAK,OAAO;AAAA,EAE1B,IAAI,UAAU,WAAW;AAAA,IACvB,MAAM,WAAW,OAAO,QAAQ,eAAe,OAAO,IAAI,aAAa,aAAa,IAAI,SAAS,SAAS,KAAK,IAAI;AAAA,IAEnH,IAAI,CAAC,aAAa,KAAK,KAAK,KAAK,CAAC,UAAU;AAAA,MAC1C,MAAM,IAAI,UAAU,IAAI,yFAAyF;AAAA,IACnH;AAAA,IAEA,QAAQ,QAAQ;AAAA,EAClB;AAAA,EAEA,MAAM,OAAO,KAAK,MAAM;AAAA,EAExB,IAAI,SAAS,WAAW;AAAA,IACtB,IAAI,WAAW,IAAI,GAAG;AAAA,MACpB,IAAI,CAAC,eAAe,MAAM,IAAI,GAAG;AAAA,QAC/B,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC,GAAG,SAAS,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAAA,QACzE,MAAM,IAAI,UAAU,QAAQ,0BAA0B,SAAS,YAAY,KAAK,kBAAkB,2CAA2C;AAAA,MAC/I;AAAA,IACF,EAAO,SAAI,SAAS,MAAM,QAAQ,KAAK,MAAM,MAAM;AAAA,MACjD,MAAM,IAAI,UAAU,IAAI,0FAA0F;AAAA,IACpH;AAAA,IAEA,QAAQ,OAAO;AAAA,EACjB;AAAA,EAEA,WAAW,QAAQ,CAAC,SAAS,SAAS,OAAO,GAAY;AAAA,IACvD,MAAM,QAAQ,OAAO;AAAA,IAErB,IAAI,UAAU,WAAW;AAAA,MACvB;AAAA,IACF;AAAA,IAEA,MAAM,MAAM,MAAM,IAAI,KAAK;AAAA,IAE3B,IAAI,QAAQ,IAAI;AAAA,MACd,OAAO,IAAI;AAAA,MACX;AAAA,IACF;AAAA,IAEA,IAAI,SAAS,KAAK,MAAM,KAAK,MAAM,MAAM;AAAA,MACvC,MAAM,IAAI,UAAU,GAAG,oBAAoB,wDAAwD,SAAS,UAAU,cAAc,SAAS,UAAU,cAAc,SAAS;AAAA,IAChL;AAAA,IAEA,MAAM,SAAS,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,EAAE,KAAK,WAAW,QAAQ,SAAS,MAAM,KAAK,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,WAAW,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC,CAAC;AAAA,IAChK,QAAoC,QAAQ,EAAE,QAAQ,OAAO;AAAA,IAC9D,IAAI,KAAK,SAAS,UAAU,YAAY,SAAS,UAAU,kBAAkB,OAAO;AAAA,EACtF;AAAA,EAEA,IAAI,OAAO,cAAc,WAAW;AAAA,IAClC,IAAI,OAAO,cAAc,MAAM;AAAA,MAC7B,QAAQ,YAAY;AAAA,MACpB,IAAI,KAAK,WAAW;AAAA,IACtB,EAAO;AAAA,MACL,OAAO,WAAW;AAAA;AAAA,EAEtB;AAAA,EAEA,OAAO,EAAE,SAAS,KAAK,SAAS,OAAO;AAAA;;ACjuBlC,IAAM,gBAAgB;AAuB7B,IAAM,cAAc,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,SAAU,OAAO,MAAO,CAAC;AAExE,IAAM,cAAc;AAEpB,IAAM,gBAAgB;AACtB,IAAM,QAAQ,EAAE,KAAK,IAAI,QAAQ,KAAK;AACtC,IAAM,UAAU,EAAE,KAAK,KAAK,QAAQ,KAAK;AAOlC,IAAM,gBAAgB,CAAC,MAAc,UAAgC,CAAC,MAA0B;AAAA,EACrG,MAAM,OAAO,QAAQ,SAAS;AAAA,EAC9B,OAAO,EAAE,QAAQ,OAAO,mBAAmB,YAAY,QAAQ,eAAe,MAAM,IAAI,EAAE;AAAA;AAIrF,IAAM,iBAAiB,CAAC,MAAc,SAAsD;AAAA,EACjG,MAAM,SAAS,WAAW,IAAI;AAAA,EAE9B,IAAI,CAAC,QAAQ;AAAA,IACX,MAAM,IAAI,MAAM,oGAAoG,QAAQ;AAAA,EAC9H;AAAA,EAEA,QAAQ,KAAK,WAAW,QAAQ,MAAM;AAAA,EACtC,MAAM,gBAAgB,KAAK,IAAI,QAAQ,WAAW;AAAA,EAClD,MAAM,UAAU,CAAC,YAAoB,kBAA0B,CAAC,SAAiB,MAAM,UAAU,YAAY,eAAe,IAAI,CAAC;AAAA,EACjI,MAAM,UAAU,QAAQ,KAAK,aAAa;AAAA,EAC1C,MAAM,YAAY,QAAQ,KAAK,KAAK,IAAI,gBAAgB,GAAG,IAAI,CAAC;AAAA,EAChE,MAAM,UAAU,QAAQ,KAAK,KAAK,IAAI,gBAAgB,IAAI,KAAK,CAAC;AAAA,EAChE,MAAM,iBAAiB,QAAQ,KAAK,KAAK,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAAA,EACtE,MAAM,QAAQ,QAAQ,MAAM,KAAK,MAAM,MAAM;AAAA,EAC7C,MAAM,UAAU,QAAQ,QAAQ,KAAK,QAAQ,MAAM;AAAA,EACnD,MAAM,WAAW,YAAY,IAAI,CAAC,WAAW,SAAS,MAAM,UAAU,KAAK,aAAa,CAAC;AAAA,EAEzF,OAAO,QAAQ,WAAW,eAAe,OAAO,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;AAAA,EAE1E,MAAM,aAAa,OAAO,KAAK;AAAA,EAC/B,OAAO,cAAc,UAAU,CAAC,QAAQ,MAAM,GAAG,GAAG,SAAS,IAAI,CAAC,WAAW,OAAO,UAAU,CAAC,CAAC;AAAA,EAChG,OAAO;AAAA,IACL,SAAS,QAAQ,OAAO,IAAI,EAAE;AAAA,IAC9B,MAAM,QAAQ,OAAO,KAAK,EAAE;AAAA,IAC5B,cAAc,eAAe,OAAO,KAAK,EAAE;AAAA,IAC3C,aAAa,QAAQ,EAAE;AAAA,IACvB,aAAa,QAAQ,EAAE;AAAA,IACvB,qBAAqB,QAAQ,OAAO,KAAK,GAAG;AAAA,IAC5C,cAAc;AAAA,IACd,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,IAGlB,eAAe,OAAO,QAAQ,EAAE,IAAI,eAAe,EAAE;AAAA,IACrD,cAAc,OAAO,QAAQ,EAAE,IAAI,eAAe,EAAE;AAAA,IACpD,eAAe,eAAe,OAAO,KAAK,EAAE;AAAA,IAC5C,gBAAgB,QAAQ,OAAO,IAAI,EAAE;AAAA,IACrC,YAAY,QAAQ,MAAM;AAAA,IAC1B,eAAe,eAAe,OAAO,KAAK,EAAE;AAAA,IAC5C,eAAe,eAAe,OAAO,KAAK,EAAE;AAAA,IAC5C,cAAc,QAAQ,MAAM;AAAA,IAC5B,kBAAkB,QAAQ,MAAM;AAAA,IAChC,sBAAsB,QAAQ,OAAO,KAAK,EAAE;AAAA,IAC5C,gBAAgB,QAAQ,OAAO,KAAK,EAAE;AAAA,IACtC,sBAAsB,eAAe,OAAO,KAAK,EAAE;AAAA,IACnD,6BAA6B,UAAU,SAAS;AAAA,IAChD,uBAAuB,UAAU,WAAW;AAAA,IAC5C,sBAAsB,QAAQ,OAAO,KAAK,EAAE;AAAA,IAC5C,gBAAgB,QAAQ,OAAO,KAAK,EAAE;AAAA,IACtC,qBAAqB,QAAQ,OAAO,KAAK,EAAE;AAAA,IAC3C,eAAe,QAAQ,OAAO,KAAK,EAAE;AAAA,IACrC,oBAAoB,QAAQ,OAAO,KAAK,EAAE;AAAA,IAC1C,cAAc,QAAQ,OAAO,KAAK,EAAE;AAAA,IACpC,oBAAoB,eAAe,OAAO,KAAK,EAAE;AAAA,IACjD,gBAAgB,eAAe,OAAO,KAAK,EAAE;AAAA,IAC7C,mBAAmB,UAAU,SAAS;AAAA,IACtC,aAAa,UAAU,WAAW;AAAA,IAClC,aAAa,QAAQ,MAAM;AAAA,IAC3B,iBAAiB,QAAQ,MAAM;AAAA,IAC/B,eAAe,QAAQ,MAAM;AAAA,IAC7B,kBAAkB,MAAM,MAAM;AAAA,IAC9B,eAAe,eAAe,EAAE;AAAA,IAChC,kBAAkB,eAAe,OAAO,KAAK,EAAE;AAAA,IAC/C,oBAAoB,MAAM,SAAS;AAAA,IACnC,gBAAgB,MAAM,MAAM;AAAA,IAC5B,cAAc,MAAM,WAAW;AAAA,EACjC;AAAA;",
15
+ "debugId": "DE40EE65BFF35E2264756E2164756E21",
16
+ "names": []
17
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * marked integration: turns ```orbit (or ~~~orbit) fences into map
3
+ * placeholders that `hydrateOrbitBlocks()` brings to life in the browser.
4
+ */
5
+ import type { MarkedExtension, RendererExtension, TokenizerExtension } from 'marked';
6
+ import type { AutoRenderOptions } from '../core/auto-render.js';
7
+ import type { OrbitSVGRenderer } from '../core/svg-renderer.js';
8
+ /**
9
+ * The marked extension, for `new Marked(orbitMarked())` or
10
+ * `marked.use(orbitMarked())`.
11
+ */
12
+ export declare const orbitMarked: () => MarkedExtension;
13
+ /** The tokenizer and renderer that `orbitMarked()` wraps. */
14
+ export declare const createOrbitExtension: () => TokenizerExtension & RendererExtension;
15
+ /**
16
+ * Renders markdown to HTML with orbit fences turned into placeholders. Uses
17
+ * its own marked instance, so the global `marked` is left untouched.
18
+ */
19
+ export declare const renderOrbitMarkdown: (markdown: string) => Promise<string>;
20
+ /**
21
+ * Registers the extension on a marked instance (the global `marked` by
22
+ * default) and returns it. Calling it again for the same instance is a no-op.
23
+ */
24
+ export declare const configureMarked: <Instance extends {
25
+ use: (...extensions: MarkedExtension[]) => unknown;
26
+ }>(instance?: Instance) => Instance;
27
+ /**
28
+ * Turns every orbit placeholder under `root` (default: the whole document)
29
+ * into a live map. Call it after inserting the rendered HTML.
30
+ */
31
+ export declare const hydrateOrbitBlocks: (root?: ParentNode, options?: AutoRenderOptions) => OrbitSVGRenderer[];
@@ -0,0 +1,110 @@
1
+ import {
2
+ renderOrbitMarkdownBlocks2
3
+ } from "../chunk-0gwh723s.js";
4
+ import {
5
+ parseOrbit2
6
+ } from "../chunk-mtrnm0yc.js";
7
+
8
+ // src/marked/index.ts
9
+ import { Marked, marked } from "marked";
10
+ var SETTING_ATTRIBUTES = {
11
+ height: "data-height",
12
+ theme: "data-theme",
13
+ view: "data-view-mode",
14
+ "view-mode": "data-view-mode",
15
+ "max-depth": "data-max-depth",
16
+ maxDepth: "data-max-depth",
17
+ palette: "data-palette",
18
+ animation: "data-animation",
19
+ interactive: "data-interactive"
20
+ };
21
+ var FENCE_START = /^ {0,3}(?:`{3,}|~{3,})orbit(?=\s|$)/m;
22
+ var FENCE = /^ {0,3}(`{3,}|~{3,})orbit(?=\s|$)([^\n`]*)\n([\s\S]*?)(?:\n {0,3}\1[`~]*[ \t]*(?:\n+|$)|$)/;
23
+ var orbitMarked = () => {
24
+ return { extensions: [createOrbitExtension()] };
25
+ };
26
+ var createOrbitExtension = () => {
27
+ return {
28
+ name: "orbit",
29
+ level: "block",
30
+ start(source) {
31
+ const match = FENCE_START.exec(source);
32
+ return match ? match.index : undefined;
33
+ },
34
+ tokenizer(source) {
35
+ const match = FENCE.exec(source);
36
+ if (!match) {
37
+ return;
38
+ }
39
+ return {
40
+ type: "orbit",
41
+ raw: match[0],
42
+ text: match[3],
43
+ settings: parseSettings(match[2])
44
+ };
45
+ },
46
+ renderer(token) {
47
+ const orbitToken = token;
48
+ if (orbitToken.type !== "orbit") {
49
+ return "";
50
+ }
51
+ const attributes = [`class="orbit-mind-map"`, `data-orbit="${escapeHtml(orbitToken.text.trim())}"`];
52
+ for (const [key, value] of Object.entries(orbitToken.settings)) {
53
+ const attribute = SETTING_ATTRIBUTES[key];
54
+ if (attribute) {
55
+ attributes.push(`${attribute}="${escapeHtml(value)}"`);
56
+ }
57
+ }
58
+ return `<div ${attributes.join(" ")}>${fallbackOutline(orbitToken.text)}</div>
59
+ `;
60
+ }
61
+ };
62
+ };
63
+ var privateInstance = null;
64
+ var renderOrbitMarkdown = async (markdown) => {
65
+ privateInstance ??= new Marked(orbitMarked());
66
+ return privateInstance.parse(markdown);
67
+ };
68
+ var configuredInstances = new WeakSet;
69
+ var configureMarked = (instance = marked) => {
70
+ if (!configuredInstances.has(instance)) {
71
+ instance.use(orbitMarked());
72
+ configuredInstances.add(instance);
73
+ }
74
+ return instance;
75
+ };
76
+ var hydrateOrbitBlocks = (root, options = {}) => {
77
+ return renderOrbitMarkdownBlocks2(root, options);
78
+ };
79
+ var parseSettings = (infoString) => {
80
+ const settings = {};
81
+ for (const match of infoString.matchAll(/([\w-]+)=(?:"([^"]*)"|'([^']*)'|(\S+))/g)) {
82
+ settings[match[1]] = match[2] ?? match[3] ?? match[4];
83
+ }
84
+ return settings;
85
+ };
86
+ var fallbackOutline = (source) => {
87
+ const { root } = parseOrbit2(source);
88
+ if (!root.text && root.children.length === 0) {
89
+ return "";
90
+ }
91
+ return `<ul class="orbit-mind-map__outline">${outlineItem(root)}</ul>`;
92
+ };
93
+ var outlineItem = (node) => {
94
+ const label = escapeHtml([node.icon, node.text].filter(Boolean).join(" "));
95
+ const children = node.children.length > 0 ? `<ul>${node.children.map(outlineItem).join("")}</ul>` : "";
96
+ return `<li>${label}${children}</li>`;
97
+ };
98
+ var escapeHtml = (value) => {
99
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
100
+ };
101
+ export {
102
+ configureMarked,
103
+ createOrbitExtension,
104
+ hydrateOrbitBlocks,
105
+ orbitMarked,
106
+ renderOrbitMarkdown
107
+ };
108
+
109
+ //# debugId=2A6B8BC2016EF60F64756E2164756E21
110
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/marked/index.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * marked integration: turns ```orbit (or ~~~orbit) fences into map\n * placeholders that `hydrateOrbitBlocks()` brings to life in the browser.\n */\n\nimport { Marked, marked } from 'marked';\nimport type { MarkedExtension, RendererExtension, TokenizerExtension } from 'marked';\nimport { parseOrbit } from '../core/dispatch.js';\nimport { renderOrbitMarkdownBlocks } from '../core/auto-render.js';\nimport type { AutoRenderOptions } from '../core/auto-render.js';\nimport type { OrbitSVGRenderer } from '../core/svg-renderer.js';\nimport type { OrbitNode } from '../core/types.js';\n\ninterface OrbitToken {\n type: 'orbit';\n raw: string;\n text: string;\n settings: Record<string, string>;\n}\n\n// Options written after the language name: ```orbit height=480 theme=glass view=all\nconst SETTING_ATTRIBUTES: Record<string, string> = {\n height: 'data-height',\n theme: 'data-theme',\n view: 'data-view-mode',\n 'view-mode': 'data-view-mode',\n 'max-depth': 'data-max-depth',\n maxDepth: 'data-max-depth',\n palette: 'data-palette',\n animation: 'data-animation',\n interactive: 'data-interactive',\n};\n\nconst FENCE_START = /^ {0,3}(?:`{3,}|~{3,})orbit(?=\\s|$)/m;\nconst FENCE = /^ {0,3}(`{3,}|~{3,})orbit(?=\\s|$)([^\\n`]*)\\n([\\s\\S]*?)(?:\\n {0,3}\\1[`~]*[ \\t]*(?:\\n+|$)|$)/;\n\n/**\n * The marked extension, for `new Marked(orbitMarked())` or\n * `marked.use(orbitMarked())`.\n */\nexport const orbitMarked = (): MarkedExtension => {\n return { extensions: [createOrbitExtension()] };\n};\n\n/** The tokenizer and renderer that `orbitMarked()` wraps. */\nexport const createOrbitExtension = (): TokenizerExtension & RendererExtension => {\n return {\n name: 'orbit',\n level: 'block',\n start(source: string): number | undefined {\n const match = FENCE_START.exec(source);\n return match ? match.index : undefined;\n },\n tokenizer(source: string): OrbitToken | undefined {\n const match = FENCE.exec(source);\n\n if (!match) {\n return undefined;\n }\n\n return {\n type: 'orbit',\n raw: match[0],\n text: match[3],\n settings: parseSettings(match[2]),\n };\n },\n renderer(token): string {\n const orbitToken = token as unknown as OrbitToken;\n\n if (orbitToken.type !== 'orbit') {\n return '';\n }\n\n const attributes = [`class=\"orbit-mind-map\"`, `data-orbit=\"${escapeHtml(orbitToken.text.trim())}\"`];\n\n for (const [key, value] of Object.entries(orbitToken.settings)) {\n const attribute = SETTING_ATTRIBUTES[key];\n\n if (attribute) {\n attributes.push(`${attribute}=\"${escapeHtml(value)}\"`);\n }\n }\n\n return `<div ${attributes.join(' ')}>${fallbackOutline(orbitToken.text)}</div>\\n`;\n },\n };\n};\n\nlet privateInstance: Marked | null = null;\n\n/**\n * Renders markdown to HTML with orbit fences turned into placeholders. Uses\n * its own marked instance, so the global `marked` is left untouched.\n */\nexport const renderOrbitMarkdown = async (markdown: string): Promise<string> => {\n privateInstance ??= new Marked(orbitMarked());\n return privateInstance.parse(markdown);\n};\n\nconst configuredInstances = new WeakSet<object>();\n\n/**\n * Registers the extension on a marked instance (the global `marked` by\n * default) and returns it. Calling it again for the same instance is a no-op.\n */\nexport const configureMarked = <Instance extends { use: (...extensions: MarkedExtension[]) => unknown }>(\n instance: Instance = marked as unknown as Instance,\n): Instance => {\n if (!configuredInstances.has(instance)) {\n instance.use(orbitMarked());\n configuredInstances.add(instance);\n }\n\n return instance;\n};\n\n/**\n * Turns every orbit placeholder under `root` (default: the whole document)\n * into a live map. Call it after inserting the rendered HTML.\n */\nexport const hydrateOrbitBlocks = (root?: ParentNode, options: AutoRenderOptions = {}): OrbitSVGRenderer[] => {\n return renderOrbitMarkdownBlocks(root, options);\n};\n\nconst parseSettings = (infoString: string): Record<string, string> => {\n const settings: Record<string, string> = {};\n\n for (const match of infoString.matchAll(/([\\w-]+)=(?:\"([^\"]*)\"|'([^']*)'|(\\S+))/g)) {\n settings[match[1]] = match[2] ?? match[3] ?? match[4];\n }\n\n return settings;\n};\n\n/** A nested list of the map, shown to readers without JavaScript and replaced when the map hydrates. */\nconst fallbackOutline = (source: string): string => {\n const { root } = parseOrbit(source);\n\n if (!root.text && root.children.length === 0) {\n return '';\n }\n\n return `<ul class=\"orbit-mind-map__outline\">${outlineItem(root)}</ul>`;\n};\n\nconst outlineItem = (node: OrbitNode): string => {\n const label = escapeHtml([node.icon, node.text].filter(Boolean).join(' '));\n const children = node.children.length > 0 ? `<ul>${node.children.map(outlineItem).join('')}</ul>` : '';\n return `<li>${label}${children}</li>`;\n};\n\nconst escapeHtml = (value: string): string => {\n return value\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n};\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "2A6B8BC2016EF60F64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * React wrapper around the framework-agnostic `OrbitSVGRenderer`.
3
+ */
4
+ import type { HTMLAttributes } from 'react';
5
+ import { OrbitSVGRenderer } from '../core/svg-renderer.js';
6
+ import type { OrbitDocument, OrbitNode, RendererOptions, ViewMode } from '../core/types.js';
7
+ export interface OrbitMindMapProps extends RendererOptions, Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
8
+ /** Markdown or YAML source, parsed with `parseOrbit`. Its frontmatter options apply unless a prop overrides them. */
9
+ source?: string;
10
+ /** A parsed document. Its frontmatter options apply unless a prop overrides them. */
11
+ document?: OrbitDocument;
12
+ /** A node tree, for maps built in code. */
13
+ data?: OrbitNode;
14
+ /**
15
+ * The focused node's id, to control focus from your state. The map flies
16
+ * to it when it changes; pair it with `onFocusChange` to follow the reader.
17
+ */
18
+ focusedId?: string;
19
+ /**
20
+ * Render a static SVG of the map until the live one mounts, so server
21
+ * rendering and slow connections show the map right away. Default true.
22
+ */
23
+ staticFallback?: boolean;
24
+ }
25
+ export interface OrbitMindMapRef {
26
+ /** The renderer, once the map has mounted. */
27
+ readonly renderer: OrbitSVGRenderer | null;
28
+ /** Flies to a node by id, in focus mode. Returns false when there's no such node. */
29
+ flyTo(nodeId: string): boolean;
30
+ /** Flies out to the overview of the whole map. */
31
+ overview(): void;
32
+ getViewMode(): ViewMode | null;
33
+ setViewMode(mode: ViewMode): void;
34
+ /** Zooms by `factor` around the middle of the map (above 1 zooms in). */
35
+ zoomBy(factor: number): void;
36
+ /** Returns the camera to the fitted view. */
37
+ fit(): void;
38
+ }
39
+ /**
40
+ * Renders an orbit map that fills its parent element, so give the parent a
41
+ * size. Pass the map as `source` (markdown or YAML), `document` or `data`.
42
+ *
43
+ * Callback props can be inline functions and `theme` / `palette` can be
44
+ * inline objects: they never rebuild the map unless their values change.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * import { OrbitMindMap } from '@restless-dreams/orbit/react';
49
+ *
50
+ * <div style={{ height: 480 }}>
51
+ * <OrbitMindMap source={'# Launch\n## Research\n## Build'} theme="night" onFocusChange={(node) => console.log(node.text)} />
52
+ * </div>
53
+ * ```
54
+ */
55
+ export declare const OrbitMindMap: import("react").ForwardRefExoticComponent<OrbitMindMapProps & import("react").RefAttributes<OrbitMindMapRef>>;