From 1a4af73a59ff03e4f1199be3ef33e6e86fe59ecc Mon Sep 17 00:00:00 2001 From: Amit Gupta <1511590+coolamit@users.noreply.github.com> Date: Wed, 11 Feb 2026 02:31:51 +0530 Subject: [PATCH 1/8] Initial commit From 68ef474692d822f34e6d935a19eb9aca713ef635 Mon Sep 17 00:00:00 2001 From: Amit Gupta <1511590+coolamit@users.noreply.github.com> Date: Wed, 11 Feb 2026 02:42:00 +0530 Subject: [PATCH 2/8] Working copy with docker setup --- .dockerignore | 12 + .gitignore | 17 + Dockerfile | 28 + Makefile | 105 + README.md | 247 + compose.yaml | 8 + go.mod | 20 + go.sum | 31 + internal/cli/cli.go | 345 + internal/config/config.go | 87 + internal/icons/icons.go | 60 + internal/markdown/markdown.go | 88 + internal/renderer/browser.go | 83 + internal/renderer/renderer.go | 357 + internal/renderer/template.go | 134 + web/embed.go | 12 + web/mermaid-zenuml.js | 84029 ++++++++++++++++++++++++++++++++ web/mermaid.min.js | 2811 ++ web/template.html | 15 + 19 files changed, 88489 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 README.md create mode 100644 compose.yaml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/cli/cli.go create mode 100644 internal/config/config.go create mode 100644 internal/icons/icons.go create mode 100644 internal/markdown/markdown.go create mode 100644 internal/renderer/browser.go create mode 100644 internal/renderer/renderer.go create mode 100644 internal/renderer/template.go create mode 100644 web/embed.go create mode 100644 web/mermaid-zenuml.js create mode 100644 web/mermaid.min.js create mode 100644 web/template.html diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f19f626 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +.git +.idea +.vscode +.claude +.DS_Store +_docs +mmd-cli +mmd-cli-* +*.svg +*.png +*.pdf +compose.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1f890e --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +mmd-cli +/bin/ +/dist/ +*.test +coverage.out +coverage.html +go.work +go.work.sum +.idea/ +.vscode/ +.DS_Store +Thumbs.db +*.svg +*.png +*.pdf +!web/*.js +_docs diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2567903 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +FROM golang:1.25-alpine AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o mmd-cli ./cmd/mmd-cli + +FROM alpine:3.21 + +# Install Chromium +RUN apk add --no-cache \ + chromium \ + nss \ + freetype \ + harfbuzz \ + ca-certificates \ + ttf-freefont \ + font-noto-emoji + +# Tell chromedp where to find the browser +ENV CHROME_BIN=/usr/bin/chromium-browser + +WORKDIR /data + +COPY --from=builder /app/mmd-cli /usr/local/bin/mmd-cli + +ENTRYPOINT ["mmd-cli"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..269b8c2 --- /dev/null +++ b/Makefile @@ -0,0 +1,105 @@ +# Go build configuration +BINARY_NAME=mmd-cli +GO=/usr/local/go/bin/go +VERSION?=dev +LDFLAGS=-ldflags '-s -w -X github.com/coolamit/mermaid-cli/internal/cli.Version=$(VERSION)' + +# Declare phony targets +.PHONY: ssh-cmd up down build clean test tidy build-linux-x64 build-linux-arm64 build-macos-x64 build-macos-arm64 build-all docker-up docker-down docker-run docker-run-aloof docker-clean + +# Common function definitions +define CURRENT_HOMESTEAD_STATUS +cd ../.. && \ +if vagrant status | grep -qE "running \(virtualbox\)|running \(parallels\)"; then echo "running"; else echo "stopped"; fi +endef + +define SSH_EXEC +PROJECT_NAME=$$(basename $$(pwd)) && \ +(cd ../.. && vagrant ssh -- -t "cd code/$$PROJECT_NAME && $(1)") +endef + +# This command will start Homestead if it is not already running. +up: + @echo "Checking Homestead status..." + @STATUS=$$($(CURRENT_HOMESTEAD_STATUS)) && \ + if [ "$$STATUS" = "running" ]; then \ + echo "Homestead is already running."; \ + else \ + echo "Starting Homestead..." && cd ../.. && vagrant up; \ + fi + +# This command will stop Homestead if it is running. +down: + @echo "Checking Homestead status..." + @STATUS=$$($(CURRENT_HOMESTEAD_STATUS)) && \ + if [ "$$STATUS" = "running" ]; then \ + echo "Stopping Homestead..." && cd ../.. && vagrant halt; \ + else \ + echo "Homestead is NOT currently running."; \ + fi + +# Command to allow any command to be run in Homestead VM +# Usage: use -- separator before the command +# Example: make ssh-cmd -- ls -alt +# : make ssh-cmd -- mod tidy +ssh-cmd: + @$(call SSH_EXEC,$(filter-out $@,$(MAKECMDGOALS))) + +# The wildcard rule is needed to allow for artisan or other ssh commands which can have any name. +# This ensures that the catch-all only matches targets that come after +# 'ssh-cmd' in the command line. +ifneq (,$(filter $(firstword $(MAKECMDGOALS)),ssh-cmd docker-run docker-run-aloof)) +%: + @: +endif + +# Go build targets (run inside Homestead VM) +build: + @$(call SSH_EXEC,$(GO) build $(LDFLAGS) -o $(BINARY_NAME) ./cmd/mmd-cli) + @echo "Built $(BINARY_NAME)" + +test: + @$(call SSH_EXEC,$(GO) test ./...) + +tidy: + @$(call SSH_EXEC,$(GO) mod tidy) + +clean: + @$(call SSH_EXEC,rm -f $(BINARY_NAME)) + @echo "Cleaned" + +# Cross-compilation targets +build-linux-x64: + @$(call SSH_EXEC,GOOS=linux GOARCH=amd64 $(GO) build $(LDFLAGS) -o $(BINARY_NAME)-linux-x64 ./cmd/mmd-cli) + +build-linux-arm64: + @$(call SSH_EXEC,GOOS=linux GOARCH=arm64 $(GO) build $(LDFLAGS) -o $(BINARY_NAME)-linux-arm64 ./cmd/mmd-cli) + +build-macos-x64: + @$(call SSH_EXEC,GOOS=darwin GOARCH=amd64 $(GO) build $(LDFLAGS) -o $(BINARY_NAME)-macos-x64 ./cmd/mmd-cli) + +build-macos-arm64: + @$(call SSH_EXEC,GOOS=darwin GOARCH=arm64 $(GO) build $(LDFLAGS) -o $(BINARY_NAME)-macos-arm64 ./cmd/mmd-cli) + +build-all: build-linux-x64 build-linux-arm64 build-macos-x64 build-macos-arm64 + @echo "Built all platforms" + +# Docker Compose targets (run on host, not in Homestead VM) +docker-up: + docker compose up -d + +docker-down: + docker compose stop + +# Run a command in the running Docker container. +# Example: make docker-run -- mmd-cli -i diagram.mmd -o diagram.svg +docker-run: + docker compose exec mmd-cli $(filter-out $@,$(MAKECMDGOALS)) + +# Run mmd-cli in an ephemeral container (no docker-up needed). +# Example: make docker-run-aloof -- -i diagram.mmd -o diagram.svg +docker-run-aloof: + docker compose run --rm --entrypoint mmd-cli mmd-cli $(filter-out $@,$(MAKECMDGOALS)) + +docker-clean: + docker compose down --rmi local --volumes --remove-orphans diff --git a/README.md b/README.md new file mode 100644 index 0000000..9a88c57 --- /dev/null +++ b/README.md @@ -0,0 +1,247 @@ +# mmd-cli + +A drop-in replacement for `@mermaid-js/mermaid-cli` written in Go. Produces a single static binary with no Node.js dependency. Requires Chrome or Chromium at runtime. + +Converts Mermaid diagram definitions into SVG, PNG, and PDF files using a headless Chrome browser. + +## Table of Contents + +- [How it Works](#how-it-works) +- [Requirements](#requirements) +- [Installation](#installation) + - [From Source](#from-source) + - [Cross-Compilation](#cross-compilation) + - [Docker](#docker) +- [Usage](#usage) +- [CLI Flags](#cli-flags) +- [Configuration Files](#configuration-files) + - [Mermaid Config (-c)](#mermaid-config--c) + - [Browser Config (-p)](#browser-config--p) + - [CSS File (-C)](#css-file--c) +- [Docker](#docker-1) + - [Start / Stop](#start--stop) + - [Run Commands](#run-commands) + - [One-off (Ephemeral)](#one-off-ephemeral) + - [Without Docker Compose](#without-docker-compose) +- [License](#license) + +## How it Works + +- Single Go binary with mermaid.js embedded via `go:embed` +- Launches headless Chrome via [chromedp](https://github.com/chromedp/chromedp) (Chrome DevTools Protocol) +- Builds an HTML page with the mermaid diagram definition +- Chrome renders the diagram, then extracts SVG / captures PNG screenshot / prints PDF +- Browser instance is reused across multiple renders for efficiency + +## Requirements + +- Go 1.25+ (for building from source) +- Chrome or Chromium installed on the system (required at runtime) + - On macOS: bundled with the system or install via `brew install --cask chromium` + - On Linux: `apt install chromium-browser` or `apk add chromium` + - Or use the [Docker image](#docker) which bundles Chromium + +## Installation + +### From Source + +```bash +# Build from source +make build + +# Or install directly +go install github.com/coolamit/mermaid-cli/cmd/mmd-cli@latest +``` + +### Cross-Compilation + +| Make target | Platform | Architecture | Output binary | +|---|---|---|---| +| `build-linux-x64` | Linux | x64 (Intel/AMD) | `mmd-cli-linux-x64` | +| `build-linux-arm64` | Linux | ARM64 (Apple Silicon, AWS Graviton) | `mmd-cli-linux-arm64` | +| `build-macos-x64` | macOS | x64 (Intel Mac) | `mmd-cli-macos-x64` | +| `build-macos-arm64` | macOS | ARM64 (Apple Silicon) | `mmd-cli-macos-arm64` | + +```bash +# Build for all platforms +make build-all + +# Individual targets +make build-linux-x64 +make build-linux-arm64 +make build-macos-x64 +make build-macos-arm64 +``` + +### Docker + +```bash +# Using Docker Compose (recommended) +make docker-up + +# Or build manually +docker build -t mmd-cli . +``` + +The Docker image pre-bundles Chromium — no local Chrome installation needed. See [Docker usage](#docker-1) for full details. + +## Usage + +```bash +# Basic SVG output +mmd-cli -i diagram.mmd -o diagram.svg + +# PNG output with scale factor +mmd-cli -i diagram.mmd -o diagram.png -s 2 + +# PDF output fitted to content +mmd-cli -i diagram.mmd -o diagram.pdf -f + +# SVG with dimensions matching the diagram size +mmd-cli -i diagram.mmd -o diagram.svg --svgFit + +# Read from stdin, write to stdout +echo "graph TD; A-->B" | mmd-cli -i - -o - -e svg + +# Process markdown file (renders all mermaid blocks) +mmd-cli -i document.md -o output.md + +# Use dark theme +mmd-cli -i diagram.mmd -o diagram.svg -t dark + +# With custom mermaid config +mmd-cli -i diagram.mmd -o diagram.svg -c config.json + +# With browser config +mmd-cli -i diagram.mmd -o diagram.svg -p browser-config.json + +# Transparent background PNG +mmd-cli -i diagram.mmd -o diagram.png -b transparent + +# With icon packs +mmd-cli -i diagram.mmd -o diagram.svg --iconPacks @iconify-json/logos +``` + +## CLI Flags + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--input` | `-i` | (required) | Input mermaid file. Use `-` for stdin. | +| `--output` | `-o` | `{input}.svg` | Output file. Use `-` for stdout. | +| `--artefacts` | `-a` | output dir | Artefacts output path (markdown mode) | +| `--theme` | `-t` | `default` | Theme: default, forest, dark, neutral | +| `--width` | `-w` | `800` | Page width | +| `--height` | `-H` | `600` | Page height | +| `--backgroundColor` | `-b` | `white` | Background color | +| `--outputFormat` | `-e` | auto | Output format: svg, png, pdf | +| `--scale` | `-s` | `1` | Scale factor | +| `--pdfFit` | `-f` | `false` | Scale PDF to fit chart | +| `--svgFit` | | `false` | Set SVG dimensions to match diagram size | +| `--svgId` | `-I` | | SVG element id attribute | +| `--configFile` | `-c` | | Mermaid JSON config file | +| `--cssFile` | `-C` | | CSS file for styling | +| `--puppeteerConfigFile` | `-p` | | Browser JSON config file | +| `--iconPacks` | | | Icon packs (e.g. @iconify-json/logos) | +| `--iconPacksNamesAndUrls` | | | Icon packs as name#url | +| `--quiet` | `-q` | `false` | Suppress log output | +| `--version` | | | Show version | + +## Configuration Files + +### Mermaid Config (-c) + +JSON file with [mermaid.js configuration options](https://mermaid.js.org/config/schema-docs/config.html). Passed via `--configFile` / `-c`. + +```json +{ + "theme": "forest", + "flowchart": { + "curve": "basis" + }, + "sequence": { + "mirrorActors": false + } +} +``` + +### Browser Config (-p) + +JSON file with browser launch options. Passed via `--puppeteerConfigFile` / `-p`. + +| Field | Type | Description | +|-------|------|-------------| +| `executablePath` | string | Path to Chrome/Chromium binary | +| `args` | string[] | Extra command-line flags for Chrome | +| `timeout` | int | Browser launch timeout (ms) | +| `headless` | string | Headless mode (`"new"` or `"old"`) | + +```json +{ + "executablePath": "/usr/bin/chromium-browser", + "args": ["--no-sandbox", "--disable-gpu"], + "timeout": 30000, + "headless": "new" +} +``` + +### CSS File (-C) + +Custom CSS file applied to the diagram page. Passed via `--cssFile` / `-C`. Useful for custom fonts or overriding default mermaid styles. + +## Docker + +### Start / Stop + +```bash +# Build image (if needed) and start the container in the background +make docker-up + +# Stop the container (preserves it for quick restart) +make docker-down + +# Stop + remove container, image, and volumes +make docker-clean +``` + +### Run Commands + +With the container running (`make docker-up`), exec commands into it: + +```bash +# SVG output +make docker-run -- mmd-cli -i diagram.mmd -o diagram.svg + +# PNG output with scale factor +make docker-run -- mmd-cli -i diagram.mmd -o diagram.png -s 2 + +# PDF output fitted to content +make docker-run -- mmd-cli -i diagram.mmd -o diagram.pdf -f + +# Check version +make docker-run -- mmd-cli --version +``` + +### One-off (Ephemeral) + +Spin up a temporary container, run `mmd-cli`, and destroy it — no `docker-up` needed: + +```bash +make docker-run-aloof -- -i diagram.mmd -o diagram.svg +``` + +### Without Docker Compose + +If you prefer bare `docker run` commands: + +```bash +# Build +docker build -t mmd-cli . + +# SVG output +docker run --rm -v "$(pwd)":/data mmd-cli -i diagram.mmd -o diagram.svg + +# PNG output +docker run --rm -v "$(pwd)":/data mmd-cli -i diagram.mmd -o diagram.png -s 2 +``` + +The Docker image sets `CHROME_BIN=/usr/bin/chromium-browser` and `WORKDIR /data` automatically, so local filenames work directly. diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..88f9ede --- /dev/null +++ b/compose.yaml @@ -0,0 +1,8 @@ +services: + mmd-cli: + build: . + image: mmd-cli + working_dir: /data + volumes: + - .:/data + entrypoint: ["sleep", "infinity"] diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4093853 --- /dev/null +++ b/go.mod @@ -0,0 +1,20 @@ +module github.com/coolamit/mermaid-cli + +go 1.25.6 + +require ( + github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d + github.com/chromedp/chromedp v0.14.2 + github.com/spf13/cobra v1.10.2 +) + +require ( + github.com/chromedp/sysutil v1.1.0 // indirect + github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.4.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.9 // indirect + golang.org/x/sys v0.34.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a7bcff6 --- /dev/null +++ b/go.sum @@ -0,0 +1,31 @@ +github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d h1:ZtA1sedVbEW7EW80Iz2GR3Ye6PwbJAJXjv7D74xG6HU= +github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d/go.mod h1:NItd7aLkcfOA/dcMXvl8p1u+lQqioRMq/SqDp71Pb/k= +github.com/chromedp/chromedp v0.14.2 h1:r3b/WtwM50RsBZHMUm9fsNhhzRStTHrKdr2zmwbZSzM= +github.com/chromedp/chromedp v0.14.2/go.mod h1:rHzAv60xDE7VNy/MYtTUrYreSc0ujt2O1/C3bzctYBo= +github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM= +github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 h1:iizUGZ9pEquQS5jTGkh4AqeeHCMbfbjeb0zMt0aEFzs= +github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs= +github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/cli/cli.go b/internal/cli/cli.go new file mode 100644 index 0000000..199f338 --- /dev/null +++ b/internal/cli/cli.go @@ -0,0 +1,345 @@ +package cli + +import ( + "context" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/coolamit/mermaid-cli/internal/config" + "github.com/coolamit/mermaid-cli/internal/icons" + "github.com/coolamit/mermaid-cli/internal/markdown" + "github.com/coolamit/mermaid-cli/internal/renderer" + "github.com/spf13/cobra" +) + +// Version is set at build time. +var Version = "dev" + +// Flags holds all CLI flag values. +type Flags struct { + Input string + Output string + Artefacts string + Theme string + Width int + Height int + BackgroundColor string + OutputFormat string + Scale int + PdfFit bool + SvgFit bool + SVGId string + ConfigFile string + CSSFile string + PuppeteerConfigFile string + IconPacks []string + IconPacksNamesAndUrls []string + Quiet bool +} + +// NewRootCommand creates the cobra root command with all flags. +func NewRootCommand() *cobra.Command { + flags := &Flags{} + + cmd := &cobra.Command{ + Use: "mmd-cli", + Short: "Mermaid CLI - Generate diagrams from mermaid definitions", + Long: "A CLI tool to convert mermaid diagram definitions into SVG, PNG, and PDF files.", + Version: Version, + RunE: func(cmd *cobra.Command, args []string) error { + return run(flags) + }, + SilenceUsage: true, + SilenceErrors: true, + } + + // Define flags to match the official mermaid-cli exactly + cmd.Flags().StringVarP(&flags.Input, "input", "i", "", "Input mermaid file. Files ending in .md will be treated as Markdown. Use `-` to read from stdin.") + cmd.Flags().StringVarP(&flags.Output, "output", "o", "", "Output file. It should be either md, svg, png, pdf or use `-` for stdout. Default: input + \".svg\"") + cmd.Flags().StringVarP(&flags.Artefacts, "artefacts", "a", "", "Output artefacts path. Only used with Markdown input.") + cmd.Flags().StringVarP(&flags.Theme, "theme", "t", "default", "Theme of the chart (default, forest, dark, neutral)") + cmd.Flags().IntVarP(&flags.Width, "width", "w", 800, "Width of the page") + cmd.Flags().IntVarP(&flags.Height, "height", "H", 600, "Height of the page") + cmd.Flags().StringVarP(&flags.BackgroundColor, "backgroundColor", "b", "white", "Background color for pngs/svgs (not pdfs). Example: transparent, red, '#F0F0F0'.") + cmd.Flags().StringVarP(&flags.OutputFormat, "outputFormat", "e", "", "Output format for the generated image (svg, png, pdf). Default: from output file extension") + cmd.Flags().IntVarP(&flags.Scale, "scale", "s", 1, "Scale factor") + cmd.Flags().BoolVarP(&flags.PdfFit, "pdfFit", "f", false, "Scale PDF to fit chart") + cmd.Flags().BoolVar(&flags.SvgFit, "svgFit", false, "Set SVG dimensions to match diagram size (for standalone viewing)") + cmd.Flags().StringVarP(&flags.SVGId, "svgId", "I", "", "The id attribute for the SVG element to be rendered") + cmd.Flags().StringVarP(&flags.ConfigFile, "configFile", "c", "", "JSON configuration file for mermaid") + cmd.Flags().StringVarP(&flags.CSSFile, "cssFile", "C", "", "CSS file for the page") + cmd.Flags().StringVarP(&flags.PuppeteerConfigFile, "puppeteerConfigFile", "p", "", "JSON configuration file for the browser") + cmd.Flags().StringSliceVar(&flags.IconPacks, "iconPacks", nil, "Icon packs to use, e.g. @iconify-json/logos") + cmd.Flags().StringSliceVar(&flags.IconPacksNamesAndUrls, "iconPacksNamesAndUrls", nil, "Icon packs with name#url format") + cmd.Flags().BoolVarP(&flags.Quiet, "quiet", "q", false, "Suppress log output") + + return cmd +} + +// info logs a message unless quiet mode is enabled. +func info(quiet bool, format string, args ...interface{}) { + if !quiet { + fmt.Fprintf(os.Stderr, format+"\n", args...) + } +} + +// errorExit prints an error message in red and exits. +func errorExit(format string, args ...interface{}) { + fmt.Fprintf(os.Stderr, "\033[31m\n%s\n\033[0m", fmt.Sprintf(format, args...)) + os.Exit(1) +} + +func run(flags *Flags) error { + input := flags.Input + output := flags.Output + outputFormat := flags.OutputFormat + quiet := flags.Quiet + + // Validate input + if input == "" { + info(false, "No input file specified, reading from stdin. "+ + "If you want to specify an input file, please use `-i .` "+ + "You can use `-i -` to read from stdin and to suppress this warning.") + } else if input == "-" { + // stdin mode, suppress warning + input = "" + } else if _, err := os.Stat(input); os.IsNotExist(err) { + return fmt.Errorf("input file %q doesn't exist", input) + } + + // Determine output + if output == "" { + if outputFormat != "" { + if input != "" { + output = input + "." + outputFormat + } else { + output = "out." + outputFormat + } + } else { + if input != "" { + output = input + ".svg" + } else { + output = "out.svg" + } + } + } else if output == "-" { + output = "/dev/stdout" + quiet = true + if outputFormat == "" { + outputFormat = "svg" + info(false, "No output format specified, using svg. "+ + "If you want to specify an output format and suppress this warning, "+ + "please use `-e .`") + } + } else { + validExt := regexp.MustCompile(`\.(?:svg|png|pdf|md|markdown)$`) + if !validExt.MatchString(output) { + return fmt.Errorf("output file must end with \".md\"/\".markdown\", \".svg\", \".png\" or \".pdf\"") + } + } + + // Validate artefacts + if flags.Artefacts != "" { + if input == "" || !regexp.MustCompile(`\.(?:md|markdown)$`).MatchString(input) { + return fmt.Errorf("artefacts [-a|--artefacts] path can only be used with Markdown input file") + } + if err := os.MkdirAll(flags.Artefacts, 0755); err != nil { + return fmt.Errorf("failed to create artefacts directory: %w", err) + } + } + + // Check output directory exists + if output != "/dev/stdout" { + outputDir := filepath.Dir(output) + if _, err := os.Stat(outputDir); os.IsNotExist(err) { + return fmt.Errorf("output directory %q/ doesn't exist", outputDir) + } + } + + // Determine output format from extension + if outputFormat == "" { + ext := strings.TrimPrefix(filepath.Ext(output), ".") + if ext == "md" || ext == "markdown" { + outputFormat = "svg" + } else { + outputFormat = ext + } + } + + validFormats := regexp.MustCompile(`^(?:svg|png|pdf)$`) + if !validFormats.MatchString(outputFormat) { + return fmt.Errorf("output format must be one of \"svg\", \"png\" or \"pdf\"") + } + + // Load configs + mermaidConfig, err := config.LoadMermaidConfig(flags.ConfigFile, flags.Theme) + if err != nil { + return err + } + + browserConfig, err := config.LoadBrowserConfig(flags.PuppeteerConfigFile) + if err != nil { + return err + } + + css, err := config.LoadCSSFile(flags.CSSFile) + if err != nil { + return err + } + + // Collect icon packs + var allIconPacks []icons.IconPack + if len(flags.IconPacks) > 0 { + allIconPacks = append(allIconPacks, icons.ParseIconPacks(flags.IconPacks)...) + } + if len(flags.IconPacksNamesAndUrls) > 0 { + allIconPacks = append(allIconPacks, icons.ParseIconPacksNamesAndUrls(flags.IconPacksNamesAndUrls)...) + } + + // Build render options + renderOpts := renderer.RenderOpts{ + MermaidConfig: mermaidConfig, + BackgroundColor: flags.BackgroundColor, + CSS: css, + SVGId: flags.SVGId, + Width: flags.Width, + Height: flags.Height, + Scale: flags.Scale, + PdfFit: flags.PdfFit, + SvgFit: flags.SvgFit, + IconPacks: allIconPacks, + } + + // Read input + var definition string + if input != "" { + data, err := os.ReadFile(input) + if err != nil { + return fmt.Errorf("failed to read input file: %w", err) + } + definition = string(data) + } else { + data, err := readStdin() + if err != nil { + return fmt.Errorf("failed to read stdin: %w", err) + } + definition = string(data) + } + + // Set up renderer + browser := renderer.NewBrowser(browserConfig) + r := renderer.NewRenderer(browser) + defer r.Close() + + ctx := context.Background() + + // Handle markdown input + if input != "" && regexp.MustCompile(`\.(?:md|markdown)$`).MatchString(input) { + if output == "/dev/stdout" { + return fmt.Errorf("cannot use `stdout` with markdown input") + } + + diagrams := markdown.ExtractDiagrams(definition) + + if len(diagrams) > 0 { + info(quiet, "Found %d mermaid charts in Markdown input", len(diagrams)) + } else { + info(quiet, "No mermaid charts found in Markdown input") + } + + imageRefs := make([]markdown.ImageRef, 0, len(diagrams)) + + for _, diagram := range diagrams { + // Build numbered output filename + ext := filepath.Ext(output) + base := strings.TrimSuffix(output, ext) + // If output is .md/.markdown, use outputFormat extension for images + imgExt := ext + if ext == ".md" || ext == ".markdown" { + imgExt = "." + outputFormat + } + outputFile := fmt.Sprintf("%s-%d%s", base, diagram.Index, imgExt) + + if flags.Artefacts != "" { + outputFile = filepath.Join(flags.Artefacts, filepath.Base(outputFile)) + } + + // Calculate relative path from output dir + outputDir := filepath.Dir(filepath.Clean(output)) + relPath, err := filepath.Rel(outputDir, filepath.Clean(outputFile)) + if err != nil { + relPath = outputFile + } + outputFileRelative := "./" + relPath + + result, err := r.Render(ctx, diagram.Definition, outputFormat, renderOpts) + if err != nil { + return fmt.Errorf("failed to render diagram %d: %w", diagram.Index, err) + } + + if err := os.WriteFile(outputFile, result.Data, 0644); err != nil { + return fmt.Errorf("failed to write output file %q: %w", outputFile, err) + } + + info(quiet, " ✅ %s", outputFileRelative) + + imageRefs = append(imageRefs, markdown.ImageRef{ + URL: outputFileRelative, + Alt: result.Desc, + Title: result.Title, + }) + } + + // If output is markdown, replace code blocks with image references + if regexp.MustCompile(`\.(?:md|markdown)$`).MatchString(output) { + outContent := markdown.ReplaceDiagrams(definition, imageRefs) + if err := os.WriteFile(output, []byte(outContent), 0644); err != nil { + return fmt.Errorf("failed to write markdown output: %w", err) + } + info(quiet, " ✅ %s", output) + } + } else { + // Single diagram rendering + info(quiet, "Generating single mermaid chart") + + result, err := r.Render(ctx, definition, outputFormat, renderOpts) + if err != nil { + return err + } + + if output == "/dev/stdout" { + if _, err := os.Stdout.Write(result.Data); err != nil { + return fmt.Errorf("failed to write to stdout: %w", err) + } + } else { + if err := os.WriteFile(output, result.Data, 0644); err != nil { + return fmt.Errorf("failed to write output file: %w", err) + } + info(quiet, " ✅ %s", output) + } + } + + return nil +} + +// readStdin reads all data from stdin. +func readStdin() ([]byte, error) { + var data []byte + buf := make([]byte, 4096) + for { + n, err := os.Stdin.Read(buf) + if n > 0 { + data = append(data, buf[:n]...) + } + if err != nil { + if err.Error() == "EOF" { + break + } + return nil, err + } + } + return data, nil +} diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000..d535d69 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,87 @@ +package config + +import ( + "encoding/json" + "fmt" + "os" +) + +// MermaidConfig holds mermaid.js configuration options. +type MermaidConfig map[string]interface{} + +// BrowserConfig holds browser launch configuration. +type BrowserConfig struct { + ExecutablePath string `json:"executablePath,omitempty"` + Args []string `json:"args,omitempty"` + Timeout int `json:"timeout,omitempty"` + Headless string `json:"headless,omitempty"` +} + +// LoadMermaidConfig reads a mermaid config JSON file and merges it with defaults. +func LoadMermaidConfig(configFile string, theme string) (MermaidConfig, error) { + cfg := MermaidConfig{"theme": theme} + + if configFile == "" { + return cfg, nil + } + + data, err := os.ReadFile(configFile) + if err != nil { + return nil, fmt.Errorf("configuration file %q doesn't exist", configFile) + } + + var fileCfg MermaidConfig + if err := json.Unmarshal(data, &fileCfg); err != nil { + return nil, fmt.Errorf("invalid JSON in config file %q: %w", configFile, err) + } + + // Merge file config over defaults (file takes precedence) + for k, v := range fileCfg { + cfg[k] = v + } + + return cfg, nil +} + +// LoadBrowserConfig reads a browser config JSON file. +func LoadBrowserConfig(configFile string) (*BrowserConfig, error) { + cfg := &BrowserConfig{} + + if configFile == "" { + return cfg, nil + } + + data, err := os.ReadFile(configFile) + if err != nil { + return nil, fmt.Errorf("configuration file %q doesn't exist", configFile) + } + + if err := json.Unmarshal(data, cfg); err != nil { + return nil, fmt.Errorf("invalid JSON in browser config file %q: %w", configFile, err) + } + + return cfg, nil +} + +// LoadCSSFile reads a CSS file and returns its contents. +func LoadCSSFile(cssFile string) (string, error) { + if cssFile == "" { + return "", nil + } + + data, err := os.ReadFile(cssFile) + if err != nil { + return "", fmt.Errorf("CSS file %q doesn't exist", cssFile) + } + + return string(data), nil +} + +// ToJSON serializes a MermaidConfig to JSON string. +func (c MermaidConfig) ToJSON() (string, error) { + data, err := json.Marshal(c) + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/internal/icons/icons.go b/internal/icons/icons.go new file mode 100644 index 0000000..bc2b5f1 --- /dev/null +++ b/internal/icons/icons.go @@ -0,0 +1,60 @@ +package icons + +import ( + "fmt" + "strings" +) + +// IconPack represents an icon pack with a name and loader URL. +type IconPack struct { + Name string + URL string +} + +// ParseIconPacks parses --iconPacks flags into IconPack structs. +// Format: @iconify-json/logos -> name=logos, url=https://unpkg.com/@iconify-json/logos/icons.json +func ParseIconPacks(packs []string) []IconPack { + result := make([]IconPack, 0, len(packs)) + for _, pack := range packs { + parts := strings.Split(pack, "/") + name := parts[len(parts)-1] + url := fmt.Sprintf("https://unpkg.com/%s/icons.json", pack) + result = append(result, IconPack{Name: name, URL: url}) + } + return result +} + +// ParseIconPacksNamesAndUrls parses --iconPacksNamesAndUrls flags. +// Format: name#url +func ParseIconPacksNamesAndUrls(packs []string) []IconPack { + result := make([]IconPack, 0, len(packs)) + for _, pack := range packs { + idx := strings.Index(pack, "#") + if idx < 0 { + continue + } + name := pack[:idx] + url := pack[idx+1:] + result = append(result, IconPack{Name: name, URL: url}) + } + return result +} + +// GenerateIconPackJS generates JavaScript code to register icon packs with mermaid. +func GenerateIconPackJS(packs []IconPack) string { + if len(packs) == 0 { + return "" + } + + var sb strings.Builder + sb.WriteString("mermaid.registerIconPacks([\n") + for _, pack := range packs { + sb.WriteString(fmt.Sprintf(` { + name: %q, + loader: () => fetch(%q).then((res) => res.json()).catch(() => console.error("Failed to fetch icon: %s")) + }, +`, pack.Name, pack.URL, pack.Name)) + } + sb.WriteString("]);\n") + return sb.String() +} diff --git a/internal/markdown/markdown.go b/internal/markdown/markdown.go new file mode 100644 index 0000000..bcfddb6 --- /dev/null +++ b/internal/markdown/markdown.go @@ -0,0 +1,88 @@ +package markdown + +import ( + "fmt" + "regexp" + "strings" +) + +// mermaidBlockRegex matches ```mermaid ... ``` and :::mermaid ... ::: code blocks. +// Mirrors the official CLI regex: /^[^\S\n]*[`:]{3}(?:mermaid)([^\S\n]*\r?\n([\s\S]*?))[`:]{3}[^\S\n]*$/gm +var mermaidBlockRegex = regexp.MustCompile(`(?m)^[^\S\n]*[\x60:]{3}(?:mermaid)([^\S\n]*\r?\n([\s\S]*?))[\x60:]{3}[^\S\n]*$`) + +// DiagramBlock represents a mermaid diagram found in markdown. +type DiagramBlock struct { + // FullMatch is the entire matched text including fences + FullMatch string + // Definition is the mermaid diagram definition (inner content) + Definition string + // Index is the 1-based index of this diagram in the markdown + Index int +} + +// ExtractDiagrams finds all mermaid code blocks in markdown content. +func ExtractDiagrams(content string) []DiagramBlock { + matches := mermaidBlockRegex.FindAllStringSubmatch(content, -1) + blocks := make([]DiagramBlock, 0, len(matches)) + + for i, match := range matches { + blocks = append(blocks, DiagramBlock{ + FullMatch: match[0], + Definition: strings.TrimSpace(match[2]), + Index: i + 1, + }) + } + + return blocks +} + +// ImageRef holds information about a rendered diagram image. +type ImageRef struct { + URL string + Alt string + Title string +} + +// MarkdownImage creates a markdown image reference: ![alt](url "title") +func MarkdownImage(ref ImageRef) string { + alt := escapeMarkdownAlt(ref.Alt) + if alt == "" { + alt = "diagram" + } + + if ref.Title != "" { + title := escapeMarkdownTitle(ref.Title) + return fmt.Sprintf("![%s](%s \"%s\")", alt, ref.URL, title) + } + return fmt.Sprintf("![%s](%s)", alt, ref.URL) +} + +// ReplaceDiagrams replaces mermaid code blocks in markdown with image references. +func ReplaceDiagrams(content string, images []ImageRef) string { + idx := 0 + return mermaidBlockRegex.ReplaceAllStringFunc(content, func(match string) string { + if idx >= len(images) { + return match + } + img := images[idx] + idx++ + return MarkdownImage(img) + }) +} + +func escapeMarkdownAlt(s string) string { + replacer := strings.NewReplacer( + "[", "\\[", + "]", "\\]", + "\\", "\\\\", + ) + return replacer.Replace(s) +} + +func escapeMarkdownTitle(s string) string { + replacer := strings.NewReplacer( + `"`, `\"`, + `\`, `\\`, + ) + return replacer.Replace(s) +} diff --git a/internal/renderer/browser.go b/internal/renderer/browser.go new file mode 100644 index 0000000..b0d011d --- /dev/null +++ b/internal/renderer/browser.go @@ -0,0 +1,83 @@ +package renderer + +import ( + "context" + "sync" + + "github.com/coolamit/mermaid-cli/internal/config" + "github.com/chromedp/chromedp" +) + +// Browser manages a lazy-started headless Chrome instance that is reused across renders. +type Browser struct { + mu sync.Mutex + allocCtx context.Context + allocCancel context.CancelFunc + browserCtx context.Context + browserCancel context.CancelFunc + started bool + cfg *config.BrowserConfig +} + +// NewBrowser creates a new Browser manager with the given config. +func NewBrowser(cfg *config.BrowserConfig) *Browser { + if cfg == nil { + cfg = &config.BrowserConfig{} + } + return &Browser{cfg: cfg} +} + +// Context returns a chromedp context, lazily starting the browser if needed. +func (b *Browser) Context(ctx context.Context) (context.Context, error) { + b.mu.Lock() + defer b.mu.Unlock() + + if b.started { + return b.browserCtx, nil + } + + opts := append(chromedp.DefaultExecAllocatorOptions[:], + chromedp.Flag("disable-gpu", true), + chromedp.Flag("no-sandbox", true), + chromedp.Flag("disable-dev-shm-usage", true), + chromedp.Flag("disable-setuid-sandbox", true), + ) + + if b.cfg.ExecutablePath != "" { + opts = append(opts, chromedp.ExecPath(b.cfg.ExecutablePath)) + } + + for _, arg := range b.cfg.Args { + opts = append(opts, chromedp.Flag(arg, true)) + } + + b.allocCtx, b.allocCancel = chromedp.NewExecAllocator(ctx, opts...) + b.browserCtx, b.browserCancel = chromedp.NewContext(b.allocCtx) + + // Run a no-op to force the browser to start + if err := chromedp.Run(b.browserCtx); err != nil { + b.allocCancel() + return nil, err + } + + b.started = true + return b.browserCtx, nil +} + +// Close shuts down the browser. +func (b *Browser) Close() { + b.mu.Lock() + defer b.mu.Unlock() + + if !b.started { + return + } + + if b.browserCancel != nil { + b.browserCancel() + } + if b.allocCancel != nil { + b.allocCancel() + } + b.started = false +} diff --git a/internal/renderer/renderer.go b/internal/renderer/renderer.go new file mode 100644 index 0000000..5285ff0 --- /dev/null +++ b/internal/renderer/renderer.go @@ -0,0 +1,357 @@ +package renderer + +import ( + "context" + "encoding/json" + "fmt" + "math" + "time" + + "github.com/chromedp/cdproto/cdp" + "github.com/chromedp/cdproto/emulation" + "github.com/chromedp/cdproto/page" + "github.com/chromedp/chromedp" +) + +// RenderResult contains the output of rendering a mermaid diagram. +type RenderResult struct { + Data []byte + Title string + Desc string +} + +// Renderer handles mermaid diagram rendering via chromedp. +type Renderer struct { + browser *Browser +} + +// NewRenderer creates a new Renderer with the given browser. +func NewRenderer(browser *Browser) *Renderer { + return &Renderer{browser: browser} +} + +// Render renders a mermaid diagram to the specified output format. +func (r *Renderer) Render(ctx context.Context, definition string, outputFormat string, opts RenderOpts) (*RenderResult, error) { + browserCtx, err := r.browser.Context(ctx) + if err != nil { + return nil, fmt.Errorf("failed to start browser: %w", err) + } + + // Create a new tab + tabCtx, tabCancel := chromedp.NewContext(browserCtx) + defer tabCancel() + + // Set timeout + tabCtx, timeoutCancel := context.WithTimeout(tabCtx, 60*time.Second) + defer timeoutCancel() + + // Build the HTML page + pageHTML, err := BuildPageHTML(definition, opts) + if err != nil { + return nil, fmt.Errorf("failed to build page HTML: %w", err) + } + + // Set viewport + if err := chromedp.Run(tabCtx, + emulation.SetDeviceMetricsOverride(int64(opts.Width), int64(opts.Height), float64(opts.Scale), false), + ); err != nil { + return nil, fmt.Errorf("failed to set viewport: %w", err) + } + + // Navigate to about:blank, then set the HTML content via CDP + var frameTree *page.FrameTree + if err := chromedp.Run(tabCtx, + chromedp.Navigate("about:blank"), + chromedp.ActionFunc(func(ctx context.Context) error { + var err error + frameTree, err = page.GetFrameTree().Do(ctx) + return err + }), + ); err != nil { + return nil, fmt.Errorf("failed to navigate: %w", err) + } + + if err := chromedp.Run(tabCtx, chromedp.ActionFunc(func(ctx context.Context) error { + return page.SetDocumentContent(frameTree.Frame.ID, pageHTML).Do(ctx) + })); err != nil { + return nil, fmt.Errorf("failed to set page content: %w", err) + } + + // Wait for rendering to complete + if err := chromedp.Run(tabCtx, + chromedp.WaitReady("#container svg", chromedp.ByQuery), + ); err != nil { + // Check if there was a render error + var resultJSON string + _ = chromedp.Run(tabCtx, + chromedp.Evaluate(`JSON.stringify(window.__mmd_result || {})`, &resultJSON), + ) + return nil, fmt.Errorf("mermaid rendering failed (waited for SVG): %w\nrender result: %s", err, resultJSON) + } + + // Check for errors in the render result + var resultJSON string + if err := chromedp.Run(tabCtx, + chromedp.Evaluate(`JSON.stringify(window.__mmd_result || {})`, &resultJSON), + ); err != nil { + return nil, fmt.Errorf("failed to get render result: %w", err) + } + + var renderResult struct { + Title *string `json:"title"` + Desc *string `json:"desc"` + Success bool `json:"success"` + Error string `json:"error"` + } + if err := json.Unmarshal([]byte(resultJSON), &renderResult); err != nil { + return nil, fmt.Errorf("failed to parse render result: %w", err) + } + if !renderResult.Success { + return nil, fmt.Errorf("mermaid rendering error: %s", renderResult.Error) + } + + result := &RenderResult{} + if renderResult.Title != nil { + result.Title = *renderResult.Title + } + if renderResult.Desc != nil { + result.Desc = *renderResult.Desc + } + + switch outputFormat { + case "svg": + var data []byte + var err error + if opts.SvgFit { + data, err = extractSVGFit(tabCtx) + } else { + data, err = extractSVG(tabCtx) + } + if err != nil { + return nil, err + } + result.Data = data + + case "png": + data, err := capturePNG(tabCtx, opts) + if err != nil { + return nil, err + } + result.Data = data + + case "pdf": + data, err := capturePDF(tabCtx, opts) + if err != nil { + return nil, err + } + result.Data = data + + default: + return nil, fmt.Errorf("unsupported output format: %s", outputFormat) + } + + return result, nil +} + +// Close closes the browser. +func (r *Renderer) Close() { + r.browser.Close() +} + +// extractSVG extracts the SVG XML from the page using XMLSerializer. +func extractSVG(ctx context.Context) ([]byte, error) { + var svgXML string + err := chromedp.Run(ctx, + chromedp.Evaluate(`(() => { + const svg = document.querySelector('#container svg'); + if (!svg) return ''; + const serializer = new XMLSerializer(); + return serializer.serializeToString(svg); + })()`, &svgXML), + ) + if err != nil { + return nil, fmt.Errorf("failed to extract SVG: %w", err) + } + if svgXML == "" { + return nil, fmt.Errorf("no SVG element found in rendered output") + } + return []byte(svgXML), nil +} + +// extractSVGFit extracts the SVG XML with dimensions set to match the viewBox (for standalone viewing). +func extractSVGFit(ctx context.Context) ([]byte, error) { + var svgXML string + err := chromedp.Run(ctx, + chromedp.Evaluate(`(() => { + const svg = document.querySelector('#container svg'); + if (!svg) return ''; + const viewBox = svg.getAttribute('viewBox'); + if (viewBox) { + const parts = viewBox.split(/\s+/); + if (parts.length === 4) { + svg.setAttribute('width', parts[2]); + svg.setAttribute('height', parts[3]); + svg.style.removeProperty('max-width'); + } + } + const serializer = new XMLSerializer(); + return serializer.serializeToString(svg); + })()`, &svgXML), + ) + if err != nil { + return nil, fmt.Errorf("failed to extract SVG: %w", err) + } + if svgXML == "" { + return nil, fmt.Errorf("no SVG element found in rendered output") + } + return []byte(svgXML), nil +} + +// clipRect represents a bounding rectangle. +type clipRect struct { + X float64 `json:"x"` + Y float64 `json:"y"` + Width float64 `json:"width"` + Height float64 `json:"height"` +} + +// getSVGBounds gets the bounding rect of the SVG element. +func getSVGBounds(ctx context.Context) (*clipRect, error) { + var boundsJSON string + err := chromedp.Run(ctx, + chromedp.Evaluate(`(() => { + const svg = document.querySelector('#container svg'); + if (!svg) return JSON.stringify({x:0, y:0, width:800, height:600}); + const rect = svg.getBoundingClientRect(); + return JSON.stringify({ + x: Math.floor(rect.left), + y: Math.floor(rect.top), + width: Math.ceil(rect.width), + height: Math.ceil(rect.height) + }); + })()`, &boundsJSON), + ) + if err != nil { + return nil, fmt.Errorf("failed to get SVG bounds: %w", err) + } + + var bounds clipRect + if err := json.Unmarshal([]byte(boundsJSON), &bounds); err != nil { + return nil, fmt.Errorf("failed to parse SVG bounds: %w", err) + } + return &bounds, nil +} + +// capturePNG captures a PNG screenshot clipped to the SVG bounds. +func capturePNG(ctx context.Context, opts RenderOpts) ([]byte, error) { + bounds, err := getSVGBounds(ctx) + if err != nil { + return nil, err + } + + // Resize viewport to fit the SVG + newWidth := int64(bounds.X + bounds.Width) + newHeight := int64(bounds.Y + bounds.Height) + if err := chromedp.Run(ctx, + emulation.SetDeviceMetricsOverride(newWidth, newHeight, float64(opts.Scale), false), + ); err != nil { + return nil, fmt.Errorf("failed to resize viewport for PNG: %w", err) + } + + // Small delay to let the resize settle + time.Sleep(100 * time.Millisecond) + + clip := &page.Viewport{ + X: bounds.X, + Y: bounds.Y, + Width: bounds.Width, + Height: bounds.Height, + Scale: 1, + } + + // Set transparent background if requested + if opts.BackgroundColor == "transparent" { + if err := chromedp.Run(ctx, chromedp.ActionFunc(func(ctx context.Context) error { + return emulation.SetDefaultBackgroundColorOverride().WithColor(&cdp.RGBA{R: 0, G: 0, B: 0, A: 0}).Do(ctx) + })); err != nil { + return nil, fmt.Errorf("failed to set transparent background: %w", err) + } + } + + var buf []byte + captureParams := page.CaptureScreenshot(). + WithFormat(page.CaptureScreenshotFormatPng). + WithClip(clip). + WithCaptureBeyondViewport(true) + + if err := chromedp.Run(ctx, chromedp.ActionFunc(func(ctx context.Context) error { + var err error + buf, err = captureParams.Do(ctx) + return err + })); err != nil { + return nil, fmt.Errorf("failed to capture PNG: %w", err) + } + + // Reset background color override + if opts.BackgroundColor == "transparent" { + _ = chromedp.Run(ctx, chromedp.ActionFunc(func(ctx context.Context) error { + return emulation.SetDefaultBackgroundColorOverride().Do(ctx) + })) + } + + return buf, nil +} + +// capturePDF captures a PDF of the page. +func capturePDF(ctx context.Context, opts RenderOpts) ([]byte, error) { + // Set transparent background if requested + if opts.BackgroundColor == "transparent" { + if err := chromedp.Run(ctx, chromedp.ActionFunc(func(ctx context.Context) error { + return emulation.SetDefaultBackgroundColorOverride().WithColor(&cdp.RGBA{R: 0, G: 0, B: 0, A: 0}).Do(ctx) + })); err != nil { + return nil, fmt.Errorf("failed to set transparent background: %w", err) + } + } + + printParams := page.PrintToPDF() + + if opts.PdfFit { + bounds, err := getSVGBounds(ctx) + if err != nil { + return nil, err + } + + // Convert px to inches (96 DPI) + widthInches := (math.Ceil(bounds.Width) + bounds.X*2) / 96.0 + heightInches := (math.Ceil(bounds.Height) + bounds.Y*2) / 96.0 + + printParams = printParams. + WithPaperWidth(widthInches). + WithPaperHeight(heightInches). + WithMarginTop(0). + WithMarginBottom(0). + WithMarginLeft(0). + WithMarginRight(0). + WithPageRanges("1-1") + } + + printParams = printParams.WithPrintBackground(true) + + var buf []byte + if err := chromedp.Run(ctx, chromedp.ActionFunc(func(ctx context.Context) error { + var err error + buf, _, err = printParams.Do(ctx) + return err + })); err != nil { + return nil, fmt.Errorf("failed to generate PDF: %w", err) + } + + // Reset background color override + if opts.BackgroundColor == "transparent" { + _ = chromedp.Run(ctx, chromedp.ActionFunc(func(ctx context.Context) error { + return emulation.SetDefaultBackgroundColorOverride().Do(ctx) + })) + } + + return buf, nil +} diff --git a/internal/renderer/template.go b/internal/renderer/template.go new file mode 100644 index 0000000..7583f5f --- /dev/null +++ b/internal/renderer/template.go @@ -0,0 +1,134 @@ +package renderer + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/coolamit/mermaid-cli/internal/config" + "github.com/coolamit/mermaid-cli/internal/icons" + "github.com/coolamit/mermaid-cli/web" +) + +// RenderOpts contains all options needed to render a mermaid diagram. +type RenderOpts struct { + MermaidConfig config.MermaidConfig + BackgroundColor string + CSS string + SVGId string + Width int + Height int + Scale int + PdfFit bool + SvgFit bool + IconPacks []icons.IconPack +} + +// BuildPageHTML constructs the full HTML page with embedded mermaid.js, config, and diagram. +func BuildPageHTML(definition string, opts RenderOpts) (string, error) { + mermaidConfigJSON, err := opts.MermaidConfig.ToJSON() + if err != nil { + return "", fmt.Errorf("failed to serialize mermaid config: %w", err) + } + + definitionJSON, err := json.Marshal(definition) + if err != nil { + return "", fmt.Errorf("failed to serialize diagram definition: %w", err) + } + + svgIdJSON, err := json.Marshal(opts.SVGId) + if err != nil { + return "", fmt.Errorf("failed to serialize svgId: %w", err) + } + + bgColorJSON, err := json.Marshal(opts.BackgroundColor) + if err != nil { + return "", fmt.Errorf("failed to serialize backgroundColor: %w", err) + } + + cssJSON, err := json.Marshal(opts.CSS) + if err != nil { + return "", fmt.Errorf("failed to serialize CSS: %w", err) + } + + iconPackJS := icons.GenerateIconPackJS(opts.IconPacks) + + // Build the full HTML page + var sb strings.Builder + sb.WriteString(` + + + + + +
+ + + + +`, mermaidConfigJSON, string(definitionJSON), string(svgIdJSON), string(bgColorJSON), string(cssJSON))) + + return sb.String(), nil +} + diff --git a/web/embed.go b/web/embed.go new file mode 100644 index 0000000..7d156e6 --- /dev/null +++ b/web/embed.go @@ -0,0 +1,12 @@ +package web + +import _ "embed" + +//go:embed template.html +var TemplateHTML string + +//go:embed mermaid.min.js +var MermaidJS []byte + +//go:embed mermaid-zenuml.js +var MermaidZenUMLJS []byte diff --git a/web/mermaid-zenuml.js b/web/mermaid-zenuml.js new file mode 100644 index 0000000..d181ee3 --- /dev/null +++ b/web/mermaid-zenuml.js @@ -0,0 +1,84029 @@ +"use strict"; +var __esbuild_esm_mermaid_nm; +(__esbuild_esm_mermaid_nm ||= {})["mermaid-zenuml"] = (() => { + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); + var __esm = (fn, res) => function __init() { + return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; + }; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to2, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to2, key) && key !== except) + __defProp(to2, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to2; + }; + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // src/mermaidUtils.ts + var warning, log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox, injectUtils; + var init_mermaidUtils = __esm({ + "src/mermaidUtils.ts"() { + "use strict"; + warning = /* @__PURE__ */ __name((s) => { + console.error("Log function was called before initialization", s); + }, "warning"); + log = { + trace: warning, + debug: warning, + info: warning, + warn: warning, + error: warning, + fatal: warning + }; + injectUtils = /* @__PURE__ */ __name((_log, _setLogLevel, _getConfig, _sanitizeText, _setupGraphViewbox) => { + _log.info("Mermaid utils injected"); + log.trace = _log.trace; + log.debug = _log.debug; + log.info = _log.info; + log.warn = _log.warn; + log.error = _log.error; + log.fatal = _log.fatal; + setLogLevel = _setLogLevel; + getConfig = _getConfig; + sanitizeText = _sanitizeText; + setupGraphViewbox = _setupGraphViewbox; + }, "injectUtils"); + } + }); + + // src/parser.ts + var parser_default; + var init_parser = __esm({ + "src/parser.ts"() { + "use strict"; + parser_default = { + parse: /* @__PURE__ */ __name(() => { + }, "parse") + }; + } + }); + + // ../../node_modules/.pnpm/@zenuml+core@3.35.2/node_modules/@zenuml/core/dist/zenuml.esm.mjs + function hb(i, e) { + for (var t = 0; t < e.length; t++) { + const n = e[t]; + if (typeof n != "string" && !Array.isArray(n)) { + for (const s in n) + if (s !== "default" && !(s in i)) { + const l = Object.getOwnPropertyDescriptor(n, s); + l && Object.defineProperty(i, s, l.get ? l : { + enumerable: true, + get: /* @__PURE__ */ __name(() => n[s], "get") + }); + } + } + } + return Object.freeze(Object.defineProperty(i, Symbol.toStringTag, { value: "Module" })); + } + function K4(i) { + return i && i.__esModule && Object.prototype.hasOwnProperty.call(i, "default") ? i.default : i; + } + function fb() { + if (l_) return T5; + l_ = 1; + var i = Symbol.for("react.transitional.element"), e = Symbol.for("react.fragment"); + function t(n, s, l) { + var c = null; + if (l !== void 0 && (c = "" + l), s.key !== void 0 && (c = "" + s.key), "key" in s) { + l = {}; + for (var L in s) + L !== "key" && (l[L] = s[L]); + } else l = s; + return s = l.ref, { + $$typeof: i, + type: n, + key: c, + ref: s !== void 0 ? s : null, + props: l + }; + } + __name(t, "t"); + return T5.Fragment = e, T5.jsx = t, T5.jsxs = t, T5; + } + function Eb() { + return c_ || (c_ = 1, Wi.exports = fb()), Wi.exports; + } + function Sb() { + if (u_) return $i; + u_ = 1; + function i(t) { + try { + return JSON.stringify(t); + } catch { + return '"[Circular]"'; + } + } + __name(i, "i"); + $i = e; + function e(t, n, s) { + var l = s && s.stringify || i, c = 1; + if (typeof t == "object" && t !== null) { + var L = n.length + c; + if (L === 1) return t; + var d = new Array(L); + d[0] = l(t); + for (var _ = 1; _ < L; _++) + d[_] = l(n[_]); + return d.join(" "); + } + if (typeof t != "string") + return t; + var p = n.length; + if (p === 0) return t; + for (var m = "", f = 1 - c, h = -1, R = t && t.length || 0, b = 0; b < R; ) { + if (t.charCodeAt(b) === 37 && b + 1 < R) { + switch (h = h > -1 ? h : 0, t.charCodeAt(b + 1)) { + case 100: + // 'd' + case 102: + if (f >= p || n[f] == null) break; + h < b && (m += t.slice(h, b)), m += Number(n[f]), h = b + 2, b++; + break; + case 105: + if (f >= p || n[f] == null) break; + h < b && (m += t.slice(h, b)), m += Math.floor(Number(n[f])), h = b + 2, b++; + break; + case 79: + // 'O' + case 111: + // 'o' + case 106: + if (f >= p || n[f] === void 0) break; + h < b && (m += t.slice(h, b)); + var M = typeof n[f]; + if (M === "string") { + m += "'" + n[f] + "'", h = b + 2, b++; + break; + } + if (M === "function") { + m += n[f].name || "", h = b + 2, b++; + break; + } + m += l(n[f]), h = b + 2, b++; + break; + case 115: + if (f >= p) + break; + h < b && (m += t.slice(h, b)), m += String(n[f]), h = b + 2, b++; + break; + case 37: + h < b && (m += t.slice(h, b)), m += "%", h = b + 2, b++, f--; + break; + } + ++f; + } + ++b; + } + return h === -1 ? t : (h < R && (m += t.slice(h)), m); + } + __name(e, "e"); + return $i; + } + function Tb() { + if (L_) return v5.exports; + L_ = 1; + const i = Sb(); + v5.exports = p; + const e = R2().console || {}, t = { + mapHttpRequest: k, + mapHttpResponse: k, + wrapRequestSerializer: n2, + wrapResponseSerializer: n2, + wrapErrorSerializer: n2, + req: k, + res: k, + err: F, + errWithCause: F + }; + function n(H, A) { + return H === "silent" ? 1 / 0 : A.levels.values[H]; + } + __name(n, "n"); + const s = Symbol("pino.logFuncs"), l = Symbol("pino.hierarchy"), c = { + error: "log", + fatal: "error", + warn: "error", + info: "log", + debug: "log", + trace: "log" + }; + function L(H, A) { + const B = { + logger: A, + parent: H[l] + }; + A[l] = B; + } + __name(L, "L"); + function d(H, A, B) { + const e2 = {}; + A.forEach((u2) => { + e2[u2] = B[u2] ? B[u2] : e[u2] || e[c[u2] || "log"] || K; + }), H[s] = e2; + } + __name(d, "d"); + function _(H, A) { + return Array.isArray(H) ? H.filter(function(e2) { + return e2 !== "!stdSerializers.err"; + }) : H === true ? Object.keys(A) : false; + } + __name(_, "_"); + function p(H) { + H = H || {}, H.browser = H.browser || {}; + const A = H.browser.transmit; + if (A && typeof A.send != "function") + throw Error("pino: transmit option must have a send function"); + const B = H.browser.write || e; + H.browser.write && (H.browser.asObject = true); + const e2 = H.serializers || {}, u2 = _(H.browser.serialize, e2); + let y = H.browser.serialize; + Array.isArray(H.browser.serialize) && H.browser.serialize.indexOf("!stdSerializers.err") > -1 && (y = false); + const q = Object.keys(H.customLevels || {}), s2 = ["error", "fatal", "warn", "info", "debug", "trace"].concat(q); + typeof B == "function" && s2.forEach(function(p1) { + B[p1] = B; + }), (H.enabled === false || H.browser.disabled) && (H.level = "silent"); + const i2 = H.level || "info", a2 = Object.create(B); + a2.log || (a2.log = K), d(a2, s2, B), L({}, a2), Object.defineProperty(a2, "levelVal", { + get: f2 + }), Object.defineProperty(a2, "level", { + get: V2, + set: q2 + }); + const _2 = { + transmit: A, + serialize: u2, + asObject: H.browser.asObject, + formatters: H.browser.formatters, + levels: s2, + timestamp: U(H) + }; + a2.levels = m(H), a2.level = i2, a2.setMaxListeners = a2.getMaxListeners = a2.emit = a2.addListener = a2.on = a2.prependListener = a2.once = a2.prependOnceListener = a2.removeListener = a2.removeAllListeners = a2.listeners = a2.listenerCount = a2.eventNames = a2.write = a2.flush = K, a2.serializers = e2, a2._serialize = u2, a2._stdErrSerialize = y, a2.child = v1, A && (a2._logEvent = N()); + function f2() { + return n(this.level, this); + } + __name(f2, "f2"); + function V2() { + return this._level; + } + __name(V2, "V2"); + function q2(p1) { + if (p1 !== "silent" && !this.levels.values[p1]) + throw Error("unknown level " + p1); + this._level = p1, R(this, _2, a2, "error"), R(this, _2, a2, "fatal"), R(this, _2, a2, "warn"), R(this, _2, a2, "info"), R(this, _2, a2, "debug"), R(this, _2, a2, "trace"), q.forEach((P1) => { + R(this, _2, a2, P1); + }); + } + __name(q2, "q2"); + function v1(p1, P1) { + if (!p1) + throw new Error("missing bindings for child Pino"); + P1 = P1 || {}, u2 && p1.serializers && (P1.serializers = p1.serializers); + const z1 = P1.serializers; + if (u2 && z1) { + var he = Object.assign({}, e2, z1), de = H.browser.serialize === true ? Object.keys(he) : u2; + delete p1.serializers, O([p1], de, he, this._stdErrSerialize); + } + function g3(O1) { + this._childLevel = (O1._childLevel | 0) + 1, this.bindings = p1, he && (this.serializers = he, this._serialize = de), A && (this._logEvent = N( + [].concat(O1._logEvent.bindings, p1) + )); + } + __name(g3, "g3"); + g3.prototype = this; + const we = new g3(this); + return L(this, we), we.level = this.level, we; + } + __name(v1, "v1"); + return a2; + } + __name(p, "p"); + function m(H) { + const A = H.customLevels || {}, B = Object.assign({}, p.levels.values, A), e2 = Object.assign({}, p.levels.labels, f(A)); + return { + values: B, + labels: e2 + }; + } + __name(m, "m"); + function f(H) { + const A = {}; + return Object.keys(H).forEach(function(B) { + A[H[B]] = B; + }), A; + } + __name(f, "f"); + p.levels = { + values: { + fatal: 60, + error: 50, + warn: 40, + info: 30, + debug: 20, + trace: 10 + }, + labels: { + 10: "trace", + 20: "debug", + 30: "info", + 40: "warn", + 50: "error", + 60: "fatal" + } + }, p.stdSerializers = t, p.stdTimeFunctions = Object.assign({}, { nullTime: X, epochTime: r2, unixTime: t2, isoTime: g2 }); + function h(H) { + const A = []; + H.bindings && A.push(H.bindings); + let B = H[l]; + for (; B.parent; ) + B = B.parent, B.logger.bindings && A.push(B.logger.bindings); + return A.reverse(); + } + __name(h, "h"); + function R(H, A, B, e2) { + if (Object.defineProperty(H, e2, { + value: n(H.level, B) > n(e2, B) ? K : B[s][e2], + writable: true, + enumerable: true, + configurable: true + }), !A.transmit && H[e2] === K) + return; + H[e2] = M(H, A, B, e2); + const u2 = h(H); + u2.length !== 0 && (H[e2] = b(u2, H[e2])); + } + __name(R, "R"); + function b(H, A) { + return function() { + return A.apply(this, [...H, ...arguments]); + }; + } + __name(b, "b"); + function M(H, A, B, e2) { + return /* @__PURE__ */ function(u2) { + return function() { + const q = A.timestamp(), s2 = new Array(arguments.length), i2 = Object.getPrototypeOf && Object.getPrototypeOf(this) === e ? e : this; + for (var a2 = 0; a2 < s2.length; a2++) s2[a2] = arguments[a2]; + if (A.serialize && !A.asObject && O(s2, this._serialize, this.serializers, this._stdErrSerialize), A.asObject || A.formatters ? u2.call(i2, w(this, e2, s2, q, A.formatters)) : u2.apply(i2, s2), A.transmit) { + const _2 = A.transmit.level || H._level, f2 = B.levels.values[_2], V2 = B.levels.values[e2]; + if (V2 < f2) return; + D(this, { + ts: q, + methodLevel: e2, + methodValue: V2, + transmitValue: B.levels.values[A.transmit.level || H._level], + send: A.transmit.send, + val: n(H._level, B) + }, s2); + } + }; + }(H[s][e2]); + } + __name(M, "M"); + function w(H, A, B, e2, u2 = {}) { + const { + level: y = /* @__PURE__ */ __name(() => H.levels.values[A], "y"), + log: q = /* @__PURE__ */ __name((V2) => V2, "q") + } = u2; + H._serialize && O(B, H._serialize, H.serializers, H._stdErrSerialize); + const s2 = B.slice(); + let i2 = s2[0]; + const a2 = {}; + e2 && (a2.time = e2), a2.level = y(A, H.levels.values[A]); + let _2 = (H._childLevel | 0) + 1; + if (_2 < 1 && (_2 = 1), i2 !== null && typeof i2 == "object") { + for (; _2-- && typeof s2[0] == "object"; ) + Object.assign(a2, s2.shift()); + i2 = s2.length ? i(s2.shift(), s2) : void 0; + } else typeof i2 == "string" && (i2 = i(s2.shift(), s2)); + return i2 !== void 0 && (a2.msg = i2), q(a2); + } + __name(w, "w"); + function O(H, A, B, e2) { + for (const u2 in H) + if (e2 && H[u2] instanceof Error) + H[u2] = p.stdSerializers.err(H[u2]); + else if (typeof H[u2] == "object" && !Array.isArray(H[u2])) + for (const y in H[u2]) + A && A.indexOf(y) > -1 && y in B && (H[u2][y] = B[y](H[u2][y])); + } + __name(O, "O"); + function D(H, A, B) { + const e2 = A.send, u2 = A.ts, y = A.methodLevel, q = A.methodValue, s2 = A.val, i2 = H._logEvent.bindings; + O( + B, + H._serialize || Object.keys(H.serializers), + H.serializers, + H._stdErrSerialize === void 0 ? true : H._stdErrSerialize + ), H._logEvent.ts = u2, H._logEvent.messages = B.filter(function(a2) { + return i2.indexOf(a2) === -1; + }), H._logEvent.level.label = y, H._logEvent.level.value = q, e2(y, H._logEvent, s2), H._logEvent = N(i2); + } + __name(D, "D"); + function N(H) { + return { + ts: 0, + messages: [], + bindings: H || [], + level: { label: "", value: 0 } + }; + } + __name(N, "N"); + function F(H) { + const A = { + type: H.constructor.name, + msg: H.message, + stack: H.stack + }; + for (const B in H) + A[B] === void 0 && (A[B] = H[B]); + return A; + } + __name(F, "F"); + function U(H) { + return typeof H.timestamp == "function" ? H.timestamp : H.timestamp === false ? X : r2; + } + __name(U, "U"); + function k() { + return {}; + } + __name(k, "k"); + function n2(H) { + return H; + } + __name(n2, "n2"); + function K() { + } + __name(K, "K"); + function X() { + return false; + } + __name(X, "X"); + function r2() { + return Date.now(); + } + __name(r2, "r2"); + function t2() { + return Math.round(Date.now() / 1e3); + } + __name(t2, "t2"); + function g2() { + return new Date(Date.now()).toISOString(); + } + __name(g2, "g2"); + function R2() { + function H(A) { + return typeof A < "u" && A; + } + __name(H, "H"); + try { + return typeof globalThis < "u" || Object.defineProperty(Object.prototype, "globalThis", { + get: /* @__PURE__ */ __name(function() { + return delete Object.prototype.globalThis, this.globalThis = this; + }, "get"), + configurable: true + }), globalThis; + } catch { + return H(self) || H(window) || H(this) || {}; + } + } + __name(R2, "R2"); + return v5.exports.default = p, v5.exports.pino = p, v5.exports; + } + function xb(i, e) { + i[e] = (console[e] || console.log).bind(console); + } + function wb(i, e, t) { + i[e] = (console[e] || console.log).bind( + console, + t[0], + t[1] + ); + } + function Mb(i) { + d_.forEach((t) => xb(i, t)); + const e = i.child; + return i.child = function(t) { + const n = e.call(i, t); + return d_.forEach( + (s) => wb(n, s, ["%c" + t.name || "", "color: #00f"]) + ), n; + }, i; + } + function J1(i, e) { + const t = `atom${++kb}`, n = { + toString() { + return (oc ? "production" : void 0) !== "production" && this.debugLabel ? t + ":" + this.debugLabel : t; + } + }; + return typeof i == "function" ? n.read = i : (n.init = i, n.read = Pb, n.write = Fb), e && (n.write = e), n; + } + function Pb(i) { + return i(this); + } + function Fb(i, e, t) { + return e( + this, + typeof t == "function" ? t(i(this)) : t + ); + } + function lc() { + return (oc ? "production" : void 0) !== "production" ? Ub() : eE(); + } + function Zb() { + return R5 || (R5 = lc(), (oc ? "production" : void 0) !== "production" && (globalThis.__JOTAI_DEFAULT_STORE__ || (globalThis.__JOTAI_DEFAULT_STORE__ = R5), globalThis.__JOTAI_DEFAULT_STORE__ !== R5 && console.warn( + "Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044" + ))), R5; + } + function Bb() { + if (f_) return J2; + f_ = 1; + var i = Symbol.for("react.transitional.element"), e = Symbol.for("react.portal"), t = Symbol.for("react.fragment"), n = Symbol.for("react.strict_mode"), s = Symbol.for("react.profiler"), l = Symbol.for("react.consumer"), c = Symbol.for("react.context"), L = Symbol.for("react.forward_ref"), d = Symbol.for("react.suspense"), _ = Symbol.for("react.memo"), p = Symbol.for("react.lazy"), m = Symbol.iterator; + function f(y) { + return y === null || typeof y != "object" ? null : (y = m && y[m] || y["@@iterator"], typeof y == "function" ? y : null); + } + __name(f, "f"); + var h = { + isMounted: /* @__PURE__ */ __name(function() { + return false; + }, "isMounted"), + enqueueForceUpdate: /* @__PURE__ */ __name(function() { + }, "enqueueForceUpdate"), + enqueueReplaceState: /* @__PURE__ */ __name(function() { + }, "enqueueReplaceState"), + enqueueSetState: /* @__PURE__ */ __name(function() { + }, "enqueueSetState") + }, R = Object.assign, b = {}; + function M(y, q, s2) { + this.props = y, this.context = q, this.refs = b, this.updater = s2 || h; + } + __name(M, "M"); + M.prototype.isReactComponent = {}, M.prototype.setState = function(y, q) { + if (typeof y != "object" && typeof y != "function" && y != null) + throw Error( + "takes an object of state variables to update or a function which returns an object of state variables." + ); + this.updater.enqueueSetState(this, y, q, "setState"); + }, M.prototype.forceUpdate = function(y) { + this.updater.enqueueForceUpdate(this, y, "forceUpdate"); + }; + function w() { + } + __name(w, "w"); + w.prototype = M.prototype; + function O(y, q, s2) { + this.props = y, this.context = q, this.refs = b, this.updater = s2 || h; + } + __name(O, "O"); + var D = O.prototype = new w(); + D.constructor = O, R(D, M.prototype), D.isPureReactComponent = true; + var N = Array.isArray, F = { H: null, A: null, T: null, S: null, V: null }, U = Object.prototype.hasOwnProperty; + function k(y, q, s2, i2, a2, _2) { + return s2 = _2.ref, { + $$typeof: i, + type: y, + key: q, + ref: s2 !== void 0 ? s2 : null, + props: _2 + }; + } + __name(k, "k"); + function n2(y, q) { + return k( + y.type, + q, + void 0, + void 0, + void 0, + y.props + ); + } + __name(n2, "n2"); + function K(y) { + return typeof y == "object" && y !== null && y.$$typeof === i; + } + __name(K, "K"); + function X(y) { + var q = { "=": "=0", ":": "=2" }; + return "$" + y.replace(/[=:]/g, function(s2) { + return q[s2]; + }); + } + __name(X, "X"); + var r2 = /\/+/g; + function t2(y, q) { + return typeof y == "object" && y !== null && y.key != null ? X("" + y.key) : q.toString(36); + } + __name(t2, "t2"); + function g2() { + } + __name(g2, "g2"); + function R2(y) { + switch (y.status) { + case "fulfilled": + return y.value; + case "rejected": + throw y.reason; + default: + switch (typeof y.status == "string" ? y.then(g2, g2) : (y.status = "pending", y.then( + function(q) { + y.status === "pending" && (y.status = "fulfilled", y.value = q); + }, + function(q) { + y.status === "pending" && (y.status = "rejected", y.reason = q); + } + )), y.status) { + case "fulfilled": + return y.value; + case "rejected": + throw y.reason; + } + } + throw y; + } + __name(R2, "R2"); + function H(y, q, s2, i2, a2) { + var _2 = typeof y; + (_2 === "undefined" || _2 === "boolean") && (y = null); + var f2 = false; + if (y === null) f2 = true; + else + switch (_2) { + case "bigint": + case "string": + case "number": + f2 = true; + break; + case "object": + switch (y.$$typeof) { + case i: + case e: + f2 = true; + break; + case p: + return f2 = y._init, H( + f2(y._payload), + q, + s2, + i2, + a2 + ); + } + } + if (f2) + return a2 = a2(y), f2 = i2 === "" ? "." + t2(y, 0) : i2, N(a2) ? (s2 = "", f2 != null && (s2 = f2.replace(r2, "$&/") + "/"), H(a2, q, s2, "", function(v1) { + return v1; + })) : a2 != null && (K(a2) && (a2 = n2( + a2, + s2 + (a2.key == null || y && y.key === a2.key ? "" : ("" + a2.key).replace( + r2, + "$&/" + ) + "/") + f2 + )), q.push(a2)), 1; + f2 = 0; + var V2 = i2 === "" ? "." : i2 + ":"; + if (N(y)) + for (var q2 = 0; q2 < y.length; q2++) + i2 = y[q2], _2 = V2 + t2(i2, q2), f2 += H( + i2, + q, + s2, + _2, + a2 + ); + else if (q2 = f(y), typeof q2 == "function") + for (y = q2.call(y), q2 = 0; !(i2 = y.next()).done; ) + i2 = i2.value, _2 = V2 + t2(i2, q2++), f2 += H( + i2, + q, + s2, + _2, + a2 + ); + else if (_2 === "object") { + if (typeof y.then == "function") + return H( + R2(y), + q, + s2, + i2, + a2 + ); + throw q = String(y), Error( + "Objects are not valid as a React child (found: " + (q === "[object Object]" ? "object with keys {" + Object.keys(y).join(", ") + "}" : q) + "). If you meant to render a collection of children, use an array instead." + ); + } + return f2; + } + __name(H, "H"); + function A(y, q, s2) { + if (y == null) return y; + var i2 = [], a2 = 0; + return H(y, i2, "", "", function(_2) { + return q.call(s2, _2, a2++); + }), i2; + } + __name(A, "A"); + function B(y) { + if (y._status === -1) { + var q = y._result; + q = q(), q.then( + function(s2) { + (y._status === 0 || y._status === -1) && (y._status = 1, y._result = s2); + }, + function(s2) { + (y._status === 0 || y._status === -1) && (y._status = 2, y._result = s2); + } + ), y._status === -1 && (y._status = 0, y._result = q); + } + if (y._status === 1) return y._result.default; + throw y._result; + } + __name(B, "B"); + var e2 = typeof reportError == "function" ? reportError : function(y) { + if (typeof window == "object" && typeof window.ErrorEvent == "function") { + var q = new window.ErrorEvent("error", { + bubbles: true, + cancelable: true, + message: typeof y == "object" && y !== null && typeof y.message == "string" ? String(y.message) : String(y), + error: y + }); + if (!window.dispatchEvent(q)) return; + } else if (typeof process == "object" && typeof process.emit == "function") { + process.emit("uncaughtException", y); + return; + } + console.error(y); + }; + function u2() { + } + __name(u2, "u2"); + return J2.Children = { + map: A, + forEach: /* @__PURE__ */ __name(function(y, q, s2) { + A( + y, + function() { + q.apply(this, arguments); + }, + s2 + ); + }, "forEach"), + count: /* @__PURE__ */ __name(function(y) { + var q = 0; + return A(y, function() { + q++; + }), q; + }, "count"), + toArray: /* @__PURE__ */ __name(function(y) { + return A(y, function(q) { + return q; + }) || []; + }, "toArray"), + only: /* @__PURE__ */ __name(function(y) { + if (!K(y)) + throw Error( + "React.Children.only expected to receive a single React element child." + ); + return y; + }, "only") + }, J2.Component = M, J2.Fragment = t, J2.Profiler = s, J2.PureComponent = O, J2.StrictMode = n, J2.Suspense = d, J2.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = F, J2.__COMPILER_RUNTIME = { + __proto__: null, + c: /* @__PURE__ */ __name(function(y) { + return F.H.useMemoCache(y); + }, "c") + }, J2.cache = function(y) { + return function() { + return y.apply(null, arguments); + }; + }, J2.cloneElement = function(y, q, s2) { + if (y == null) + throw Error( + "The argument must be a React element, but you passed " + y + "." + ); + var i2 = R({}, y.props), a2 = y.key, _2 = void 0; + if (q != null) + for (f2 in q.ref !== void 0 && (_2 = void 0), q.key !== void 0 && (a2 = "" + q.key), q) + !U.call(q, f2) || f2 === "key" || f2 === "__self" || f2 === "__source" || f2 === "ref" && q.ref === void 0 || (i2[f2] = q[f2]); + var f2 = arguments.length - 2; + if (f2 === 1) i2.children = s2; + else if (1 < f2) { + for (var V2 = Array(f2), q2 = 0; q2 < f2; q2++) + V2[q2] = arguments[q2 + 2]; + i2.children = V2; + } + return k(y.type, a2, void 0, void 0, _2, i2); + }, J2.createContext = function(y) { + return y = { + $$typeof: c, + _currentValue: y, + _currentValue2: y, + _threadCount: 0, + Provider: null, + Consumer: null + }, y.Provider = y, y.Consumer = { + $$typeof: l, + _context: y + }, y; + }, J2.createElement = function(y, q, s2) { + var i2, a2 = {}, _2 = null; + if (q != null) + for (i2 in q.key !== void 0 && (_2 = "" + q.key), q) + U.call(q, i2) && i2 !== "key" && i2 !== "__self" && i2 !== "__source" && (a2[i2] = q[i2]); + var f2 = arguments.length - 2; + if (f2 === 1) a2.children = s2; + else if (1 < f2) { + for (var V2 = Array(f2), q2 = 0; q2 < f2; q2++) + V2[q2] = arguments[q2 + 2]; + a2.children = V2; + } + if (y && y.defaultProps) + for (i2 in f2 = y.defaultProps, f2) + a2[i2] === void 0 && (a2[i2] = f2[i2]); + return k(y, _2, void 0, void 0, null, a2); + }, J2.createRef = function() { + return { current: null }; + }, J2.forwardRef = function(y) { + return { $$typeof: L, render: y }; + }, J2.isValidElement = K, J2.lazy = function(y) { + return { + $$typeof: p, + _payload: { _status: -1, _result: y }, + _init: B + }; + }, J2.memo = function(y, q) { + return { + $$typeof: _, + type: y, + compare: q === void 0 ? null : q + }; + }, J2.startTransition = function(y) { + var q = F.T, s2 = {}; + F.T = s2; + try { + var i2 = y(), a2 = F.S; + a2 !== null && a2(s2, i2), typeof i2 == "object" && i2 !== null && typeof i2.then == "function" && i2.then(u2, e2); + } catch (_2) { + e2(_2); + } finally { + F.T = q; + } + }, J2.unstable_useCacheRefresh = function() { + return F.H.useCacheRefresh(); + }, J2.use = function(y) { + return F.H.use(y); + }, J2.useActionState = function(y, q, s2) { + return F.H.useActionState(y, q, s2); + }, J2.useCallback = function(y, q) { + return F.H.useCallback(y, q); + }, J2.useContext = function(y) { + return F.H.useContext(y); + }, J2.useDebugValue = function() { + }, J2.useDeferredValue = function(y, q) { + return F.H.useDeferredValue(y, q); + }, J2.useEffect = function(y, q, s2) { + var i2 = F.H; + if (typeof s2 == "function") + throw Error( + "useEffect CRUD overload is not enabled in this build of React." + ); + return i2.useEffect(y, q); + }, J2.useId = function() { + return F.H.useId(); + }, J2.useImperativeHandle = function(y, q, s2) { + return F.H.useImperativeHandle(y, q, s2); + }, J2.useInsertionEffect = function(y, q) { + return F.H.useInsertionEffect(y, q); + }, J2.useLayoutEffect = function(y, q) { + return F.H.useLayoutEffect(y, q); + }, J2.useMemo = function(y, q) { + return F.H.useMemo(y, q); + }, J2.useOptimistic = function(y, q) { + return F.H.useOptimistic(y, q); + }, J2.useReducer = function(y, q, s2) { + return F.H.useReducer(y, q, s2); + }, J2.useRef = function(y) { + return F.H.useRef(y); + }, J2.useState = function(y) { + return F.H.useState(y); + }, J2.useSyncExternalStore = function(y, q, s2) { + return F.H.useSyncExternalStore( + y, + q, + s2 + ); + }, J2.useTransition = function() { + return F.H.useTransition(); + }, J2.version = "19.1.0", J2; + } + function cc() { + return E_ || (E_ = 1, Xi.exports = Bb()), Xi.exports; + } + function uc(i) { + return v.useContext(tE) || Zb(); + } + function zb({ + children: i, + store: e + }) { + const t = v.useRef(void 0); + return !e && !t.current && (t.current = lc()), v.createElement( + tE.Provider, + { + value: e || t.current + }, + i + ); + } + function j2(i, e) { + const t = uc(), [[n, s, l], c] = v.useReducer( + (_) => { + const p = t.get(i); + return Object.is(_[0], p) && _[1] === t && _[2] === i ? _ : [p, t, i]; + }, + void 0, + () => [t.get(i), t, i] + ); + let L = n; + if ((s !== t || l !== i) && (c(), L = t.get(i)), v.useEffect(() => { + const _ = t.sub(i, () => { + c(); + }); + return c(), _; + }, [t, i, void 0]), v.useDebugValue(L), nE(L)) { + const _ = Vb(L, () => t.get(i)); + return Yb(_); + } + return L; + } + function E0(i, e) { + const t = uc(); + return v.useCallback( + (...s) => { + if ((Gb ? "production" : void 0) !== "production" && !("write" in i)) + throw new Error("not writable atom"); + return t.set(i, ...s); + }, + [t, i] + ); + } + function c4(i, e) { + return [ + j2(i), + // We do wrong type assertion here, which results in throwing an error. + E0(i) + ]; + } + function C0(i, e) { + if (!Array.isArray(i) || !Array.isArray(e)) + return false; + if (i === e) + return true; + if (i.length !== e.length) + return false; + for (let t = 0; t < i.length; t++) + if (i[t] !== e[t] && (!i[t].equals || !i[t].equals(e[t]))) + return false; + return true; + } + function rE(i) { + return i ? i.hashCode() : -1; + } + function aE(i, e) { + return i ? i.equals(e) : i === e; + } + function qb(i) { + return i === null ? "null" : i; + } + function It(i) { + return Array.isArray(i) ? "[" + i.map(qb).join(", ") + "]" : "null"; + } + function sE(i) { + const e = []; + return i.values().map(function(t) { + t instanceof g1.PrecedencePredicate && e.push(t); + }), e; + } + function S_(i, e) { + if (i === null) { + const t = { state: null, alt: null, context: null, semanticContext: null }; + return e && (t.reachesIntoOuterContext = 0), t; + } else { + const t = {}; + return t.state = i.state || null, t.alt = i.alt === void 0 ? null : i.alt, t.context = i.context || null, t.semanticContext = i.semanticContext || null, e && (t.reachesIntoOuterContext = i.reachesIntoOuterContext || 0, t.precedenceFilterSuppressed = i.precedenceFilterSuppressed || false), t; + } + } + function Kb(i, e) { + return i = i.replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r"), i; + } + function _c(i, e) { + if (e == null && (e = _0.EMPTY), e.parentCtx === null || e === _0.EMPTY) + return t1.EMPTY; + const t = _c(i, e.parentCtx), s = i.states[e.invokingState].transitions[0]; + return We.create(t, s.followState.stateNumber); + } + function cE(i, e, t) { + if (i.isEmpty()) + return i; + let n = t.get(i) || null; + if (n !== null) + return n; + if (n = e.get(i), n !== null) + return t.set(i, n), n; + let s = false, l = []; + for (let L = 0; L < l.length; L++) { + const d = cE(i.getParent(L), e, t); + if (s || d !== i.getParent(L)) { + if (!s) { + l = []; + for (let _ = 0; _ < i.length; _++) + l[_] = i.getParent(_); + s = true; + } + l[L] = d; + } + } + if (!s) + return e.add(i), t.set(i, i), i; + let c = null; + return l.length === 0 ? c = t1.EMPTY : l.length === 1 ? c = We.create(l[0], i.getReturnState(0)) : c = new x4(l, i.returnStates), e.add(c), t.set(c, c), t.set(i, c), c; + } + function gc(i, e, t, n) { + if (i === e) + return i; + if (i instanceof We && e instanceof We) + return Xb(i, e, t, n); + if (t) { + if (i instanceof Sl) + return i; + if (e instanceof Sl) + return e; + } + return i instanceof We && (i = new x4([i.getParent()], [i.returnState])), e instanceof We && (e = new x4([e.getParent()], [e.returnState])), Qb(i, e, t, n); + } + function Qb(i, e, t, n) { + if (n !== null) { + let p = n.get(i, e); + if (p !== null || (p = n.get(e, i), p !== null)) + return p; + } + let s = 0, l = 0, c = 0, L = [], d = []; + for (; s < i.returnStates.length && l < e.returnStates.length; ) { + const p = i.parents[s], m = e.parents[l]; + if (i.returnStates[s] === e.returnStates[l]) { + const f = i.returnStates[s]; + f === t1.EMPTY_RETURN_STATE && p === null && m === null || p !== null && m !== null && p === m ? (d[c] = p, L[c] = f) : (d[c] = gc(p, m, t, n), L[c] = f), s += 1, l += 1; + } else i.returnStates[s] < e.returnStates[l] ? (d[c] = p, L[c] = i.returnStates[s], s += 1) : (d[c] = m, L[c] = e.returnStates[l], l += 1); + c += 1; + } + if (s < i.returnStates.length) + for (let p = s; p < i.returnStates.length; p++) + d[c] = i.parents[p], L[c] = i.returnStates[p], c += 1; + else + for (let p = l; p < e.returnStates.length; p++) + d[c] = e.parents[p], L[c] = e.returnStates[p], c += 1; + if (c < d.length) { + if (c === 1) { + const p = We.create( + d[0], + L[0] + ); + return n !== null && n.set(i, e, p), p; + } + d = d.slice(0, c), L = L.slice(0, c); + } + const _ = new x4(d, L); + return _ === i ? (n !== null && n.set(i, e, i), i) : _ === e ? (n !== null && n.set(i, e, e), e) : (jb(d), n !== null && n.set(i, e, _), _); + } + function jb(i) { + const e = new nn(); + for (let t = 0; t < i.length; t++) { + const n = i[t]; + e.containsKey(n) || e.set(n, n); + } + for (let t = 0; t < i.length; t++) + i[t] = e.get(i[t]); + } + function Xb(i, e, t, n) { + if (n !== null) { + let l = n.get(i, e); + if (l !== null || (l = n.get(e, i), l !== null)) + return l; + } + const s = Jb(i, e, t); + if (s !== null) + return n !== null && n.set(i, e, s), s; + if (i.returnState === e.returnState) { + const l = gc(i.parentCtx, e.parentCtx, t, n); + if (l === i.parentCtx) + return i; + if (l === e.parentCtx) + return e; + const c = We.create(l, i.returnState); + return n !== null && n.set(i, e, c), c; + } else { + let l = null; + if ((i === e || i.parentCtx !== null && i.parentCtx === e.parentCtx) && (l = i.parentCtx), l !== null) { + const _ = [i.returnState, e.returnState]; + i.returnState > e.returnState && (_[0] = e.returnState, _[1] = i.returnState); + const p = [l, l], m = new x4(p, _); + return n !== null && n.set(i, e, m), m; + } + const c = [i.returnState, e.returnState]; + let L = [i.parentCtx, e.parentCtx]; + i.returnState > e.returnState && (c[0] = e.returnState, c[1] = i.returnState, L = [e.parentCtx, i.parentCtx]); + const d = new x4(L, c); + return n !== null && n.set(i, e, d), d; + } + } + function Jb(i, e, t) { + if (t) { + if (i === t1.EMPTY || e === t1.EMPTY) + return t1.EMPTY; + } else { + if (i === t1.EMPTY && e === t1.EMPTY) + return t1.EMPTY; + if (i === t1.EMPTY) { + const n = [ + e.returnState, + t1.EMPTY_RETURN_STATE + ], s = [e.parentCtx, null]; + return new x4(s, n); + } else if (e === t1.EMPTY) { + const n = [i.returnState, t1.EMPTY_RETURN_STATE], s = [i.parentCtx, null]; + return new x4(s, n); + } + } + return null; + } + function R8(i, e) { + const t = []; + return t[i - 1] = e, t.map(function(n) { + return e; + }); + } + function rx(i) { + return i.hashCodeForConfigSet(); + } + function ax(i, e) { + return i === e ? true : i === null || e === null ? false : i.equalsForConfigSet(e); + } + function M_(i) { + i.index = -1, i.line = 0, i.column = -1, i.dfaState = null; + } + function gx(i, e) { + return e !== null ? e : "failed predicate: {" + i + "}?"; + } + function VE(i) { + try { + if (i == null) return false; + const e = this.start.start, t = this.Body().stop.stop + 1; + return i >= e && i <= t; + } catch { + return false; + } + } + function ou(i) { + for (; i; ) { + if (i instanceof T0 || i instanceof su) + return i.Owner(); + i = i.parentCtx; + } + } + function tS() { + if (I_) return ar; + I_ = 1; + function i(e, t) { + switch (e) { + case 0: + return function() { + return t.apply(this, arguments); + }; + case 1: + return function(n) { + return t.apply(this, arguments); + }; + case 2: + return function(n, s) { + return t.apply(this, arguments); + }; + case 3: + return function(n, s, l) { + return t.apply(this, arguments); + }; + case 4: + return function(n, s, l, c) { + return t.apply(this, arguments); + }; + case 5: + return function(n, s, l, c, L) { + return t.apply(this, arguments); + }; + case 6: + return function(n, s, l, c, L, d) { + return t.apply(this, arguments); + }; + case 7: + return function(n, s, l, c, L, d, _) { + return t.apply(this, arguments); + }; + case 8: + return function(n, s, l, c, L, d, _, p) { + return t.apply(this, arguments); + }; + case 9: + return function(n, s, l, c, L, d, _, p, m) { + return t.apply(this, arguments); + }; + case 10: + return function(n, s, l, c, L, d, _, p, m, f) { + return t.apply(this, arguments); + }; + default: + throw new Error("First argument to _arity must be a non-negative integer no greater than ten"); + } + } + __name(i, "i"); + return ar = i, ar; + } + function aw() { + if (D_) return sr; + D_ = 1; + function i(e, t) { + return function() { + return t.call(this, e.apply(this, arguments)); + }; + } + __name(i, "i"); + return sr = i, sr; + } + function cu() { + if (k_) return or; + k_ = 1; + function i(e) { + return e != null && typeof e == "object" && e["@@functional/placeholder"] === true; + } + __name(i, "i"); + return or = i, or; + } + function b6() { + if (P_) return lr; + P_ = 1; + var i = /* @__PURE__ */ cu(); + function e(t) { + return /* @__PURE__ */ __name(function n(s) { + return arguments.length === 0 || i(s) ? n : t.apply(this, arguments); + }, "n"); + } + __name(e, "e"); + return lr = e, lr; + } + function nS() { + if (F_) return cr; + F_ = 1; + var i = /* @__PURE__ */ b6(), e = /* @__PURE__ */ cu(); + function t(n) { + return /* @__PURE__ */ __name(function s(l, c) { + switch (arguments.length) { + case 0: + return s; + case 1: + return e(l) ? s : i(function(L) { + return n(l, L); + }); + default: + return e(l) && e(c) ? s : e(l) ? i(function(L) { + return n(L, c); + }) : e(c) ? i(function(L) { + return n(l, L); + }) : n(l, c); + } + }, "s"); + } + __name(t, "t"); + return cr = t, cr; + } + function uu() { + if (U_) return ur; + U_ = 1; + var i = /* @__PURE__ */ b6(), e = /* @__PURE__ */ nS(), t = /* @__PURE__ */ cu(); + function n(s) { + return /* @__PURE__ */ __name(function l(c, L, d) { + switch (arguments.length) { + case 0: + return l; + case 1: + return t(c) ? l : e(function(_, p) { + return s(c, _, p); + }); + case 2: + return t(c) && t(L) ? l : t(c) ? e(function(_, p) { + return s(_, L, p); + }) : t(L) ? e(function(_, p) { + return s(c, _, p); + }) : i(function(_) { + return s(c, L, _); + }); + default: + return t(c) && t(L) && t(d) ? l : t(c) && t(L) ? e(function(_, p) { + return s(_, p, d); + }) : t(c) && t(d) ? e(function(_, p) { + return s(_, L, p); + }) : t(L) && t(d) ? e(function(_, p) { + return s(c, _, p); + }) : t(c) ? i(function(_) { + return s(_, L, d); + }) : t(L) ? i(function(_) { + return s(c, _, d); + }) : t(d) ? i(function(_) { + return s(c, L, _); + }) : s(c, L, d); + } + }, "l"); + } + __name(n, "n"); + return ur = n, ur; + } + function iS() { + return Z_ || (Z_ = 1, Lr = Array.isArray || function(e) { + return e != null && e.length >= 0 && Object.prototype.toString.call(e) === "[object Array]"; + }), Lr; + } + function sw() { + if (B_) return dr; + B_ = 1; + function i(e) { + return Object.prototype.toString.call(e) === "[object String]"; + } + __name(i, "i"); + return dr = i, dr; + } + function ow() { + if (G_) return Cr; + G_ = 1; + var i = /* @__PURE__ */ b6(), e = /* @__PURE__ */ iS(), t = /* @__PURE__ */ sw(), n = /* @__PURE__ */ i(function(l) { + return e(l) ? true : !l || typeof l != "object" || t(l) ? false : l.length === 0 ? true : l.length > 0 ? l.hasOwnProperty(0) && l.hasOwnProperty(l.length - 1) : false; + }); + return Cr = n, Cr; + } + function lw() { + if (z_) return _r; + z_ = 1; + var i = /* @__PURE__ */ function() { + function t(n) { + this.f = n; + } + __name(t, "t"); + return t.prototype["@@transducer/init"] = function() { + throw new Error("init not implemented on XWrap"); + }, t.prototype["@@transducer/result"] = function(n) { + return n; + }, t.prototype["@@transducer/step"] = function(n, s) { + return this.f(n, s); + }, t; + }(); + function e(t) { + return new i(t); + } + __name(e, "e"); + return _r = e, _r; + } + function cw() { + if (H_) return gr; + H_ = 1; + var i = /* @__PURE__ */ tS(), e = /* @__PURE__ */ nS(), t = /* @__PURE__ */ e(function(s, l) { + return i(s.length, function() { + return s.apply(l, arguments); + }); + }); + return gr = t, gr; + } + function uw() { + if (Y_) return pr; + Y_ = 1; + var i = /* @__PURE__ */ ow(), e = /* @__PURE__ */ lw(), t = /* @__PURE__ */ cw(); + function n(d, _, p) { + for (var m = 0, f = p.length; m < f; ) { + if (_ = d["@@transducer/step"](_, p[m]), _ && _["@@transducer/reduced"]) { + _ = _["@@transducer/value"]; + break; + } + m += 1; + } + return d["@@transducer/result"](_); + } + __name(n, "n"); + function s(d, _, p) { + for (var m = p.next(); !m.done; ) { + if (_ = d["@@transducer/step"](_, m.value), _ && _["@@transducer/reduced"]) { + _ = _["@@transducer/value"]; + break; + } + m = p.next(); + } + return d["@@transducer/result"](_); + } + __name(s, "s"); + function l(d, _, p, m) { + return d["@@transducer/result"](p[m](t(d["@@transducer/step"], d), _)); + } + __name(l, "l"); + var c = typeof Symbol < "u" ? Symbol.iterator : "@@iterator"; + function L(d, _, p) { + if (typeof d == "function" && (d = e(d)), i(p)) + return n(d, _, p); + if (typeof p["fantasy-land/reduce"] == "function") + return l(d, _, p, "fantasy-land/reduce"); + if (p[c] != null) + return s(d, _, p[c]()); + if (typeof p.next == "function") + return s(d, _, p); + if (typeof p.reduce == "function") + return l(d, _, p, "reduce"); + throw new TypeError("reduce: list must be array or iterable"); + } + __name(L, "L"); + return pr = L, pr; + } + function Lw() { + if (V_) return mr; + V_ = 1; + var i = /* @__PURE__ */ uu(), e = /* @__PURE__ */ uw(), t = /* @__PURE__ */ i(e); + return mr = t, mr; + } + function rS() { + if (q_) return hr; + q_ = 1; + var i = /* @__PURE__ */ iS(); + function e(t, n) { + return function() { + var s = arguments.length; + if (s === 0) + return n(); + var l = arguments[s - 1]; + return i(l) || typeof l[t] != "function" ? n.apply(this, arguments) : l[t].apply(l, Array.prototype.slice.call(arguments, 0, s - 1)); + }; + } + __name(e, "e"); + return hr = e, hr; + } + function dw() { + if (W_) return fr; + W_ = 1; + var i = /* @__PURE__ */ rS(), e = /* @__PURE__ */ uu(), t = /* @__PURE__ */ e( + /* @__PURE__ */ i("slice", function(s, l, c) { + return Array.prototype.slice.call(c, s, l); + }) + ); + return fr = t, fr; + } + function Cw() { + if ($_) return Er; + $_ = 1; + var i = /* @__PURE__ */ rS(), e = /* @__PURE__ */ b6(), t = /* @__PURE__ */ dw(), n = /* @__PURE__ */ e( + /* @__PURE__ */ i( + "tail", + /* @__PURE__ */ t(1, 1 / 0) + ) + ); + return Er = n, Er; + } + function _w() { + if (K_) return Sr; + K_ = 1; + var i = /* @__PURE__ */ tS(), e = /* @__PURE__ */ aw(), t = /* @__PURE__ */ Lw(), n = /* @__PURE__ */ Cw(); + function s() { + if (arguments.length === 0) + throw new Error("pipe requires at least one argument"); + return i(arguments[0].length, t(e, arguments[0], n(arguments))); + } + __name(s, "s"); + return Sr = s, Sr; + } + function mw() { + if (Q_) return Tr; + Q_ = 1; + var i = /* @__PURE__ */ uu(), e = /* @__PURE__ */ i(function(n, s, l) { + return l.replace(n, s); + }); + return Tr = e, Tr; + } + function ww(i) { + const e = new $.InputStream(i), t = new S2(e), n = new $.CommonTokenStream(t), s = new T(n); + return s.addErrorListener(new xw()), s._syntaxErrors ? null : s.prog(); + } + function Aw(i, e) { + const t = `WidthProviderOnBrowser_${i}_${e}`, n = Il(t); + if (n != null) + return n; + let s = document.querySelector( + ".textarea-hidden-div" + ); + if (!s) { + const c = document.createElement("div"); + c.className = "textarea-hidden-div ", c.style.fontSize = e === j8.MessageContent ? "0.875rem" : "1rem", c.style.fontFamily = "Helvetica, Verdana, serif", c.style.display = "inline", c.style.whiteSpace = "nowrap", c.style.visibility = "hidden", c.style.position = "absolute", c.style.top = "0", c.style.left = "0", c.style.overflow = "hidden", c.style.width = "0px", c.style.paddingLeft = "0px", c.style.paddingRight = "0px", c.style.margin = "0px", c.style.border = "0px", document.body.appendChild(c), s = c; + } + s.textContent = i; + const l = s.scrollWidth; + return Dl(t, l, true), l; + } + function x6(i) { + const e = $.tree.ParseTreeWalker.DEFAULT, t = new Dw(); + return e.walk(t, i), t.result(); + } + function Pw(i) { + const e = Be.getParticipants(i), t = Array.from(e.participants.entries()), n = x6(i), s = n.length === 0 && t.length === 0, l = n.some((L) => !L.from); + return (s || l) && t.unshift([ + Ze, + { ...zE, name: Ze, isStarter: true } + ]), t.map((L, d, _) => { + const p = L[1], m = d > 0 ? _[d - 1][1].name : ""; + return new kw( + p.name, + m, + p.label, + p.type + ); + }); + } + function w6(i, e) { + return { position: i, velocity: e }; + } + function eg(i, e) { + return w6(i.position + e.position, i.velocity + e.velocity); + } + function Fw(i, e) { + const t = i.position - e.position; + return t < -tg || Math.abs(t) <= tg && i.velocity < e.velocity; + } + function Uw() { + return { + delta: 1 / 0, + dualLessThan: /* @__PURE__ */ __name(function(i, e) { + const t = Fw(i, e); + return t && ([i, e] = [e, i]), i.velocity < e.velocity && (this.delta = Math.min( + this.delta, + (i.position - e.position) / (e.velocity - i.velocity) + )), t; + }, "dualLessThan") + }; + } + function Zw(i, e) { + const t = Array(); + for (let n = 0; n < i; n++) { + t.push([]); + for (let s = 0; s < n; s++) + e[s][n] > 0 && t[n].push({ i: s, length: w6(e[s][n], 0) }); + } + return t; + } + function Bw(i, e) { + const t = Uw(); + let n = w6(0, 0); + const s = []; + for (let l = 0; l < i.length; l++) { + let c = null; + l > 0 && (n = eg(n, e[l - 1])); + for (const L of i[l]) { + const d = eg(s[L.i].maximum, L.length); + t.dualLessThan(n, d) && (c = L.i, n = d); + } + s.push({ argument: c, maximum: n }); + } + return [t.delta, s]; + } + function Gw(i, e, t) { + let n = i.length - 1; + for (; n > 0; ) { + const s = i[n].argument; + s !== null ? n = s : (n--, t[n].velocity = 0); + } + } + function zw(i, e) { + for (let t = 0; t < i.length; t++) + i[t].position += i[t].velocity * e; + } + function Hw(i) { + const e = []; + for (const t of i) + e.push(t.maximum.position); + return e; + } + function Yw(i) { + const e = i.length, t = Zw(e, i), n = []; + for (let s = 1; s < e; s++) + n.push(w6(0, 1)); + for (; ; ) { + const [s, l] = Bw(t, n); + if (s == 1 / 0) + return Hw(l); + l[e - 1].maximum.velocity > 0 ? Gw(l, t, n) : zw(n, s); + } + } + function $w(i, e) { + if (i.match(/^[a-z]+:\/\//i)) + return i; + if (i.match(/^\/\//)) + return window.location.protocol + i; + if (i.match(/^[a-z]+:/i)) + return i; + const t = document.implementation.createHTMLDocument(), n = t.createElement("base"), s = t.createElement("a"); + return t.head.appendChild(n), t.body.appendChild(s), e && (n.href = e), s.href = i, s.href; + } + function kt(i) { + const e = []; + for (let t = 0, n = i.length; t < n; t++) + e.push(i[t]); + return e; + } + function hS(i = {}) { + return r0 || (i.includeStyleProperties ? (r0 = i.includeStyleProperties, r0) : (r0 = kt(window.getComputedStyle(document.documentElement)), r0)); + } + function X8(i, e) { + const n = (i.ownerDocument.defaultView || window).getComputedStyle(i).getPropertyValue(e); + return n ? parseFloat(n.replace("px", "")) : 0; + } + function Qw(i) { + const e = X8(i, "border-left-width"), t = X8(i, "border-right-width"); + return i.clientWidth + e + t; + } + function jw(i) { + const e = X8(i, "border-top-width"), t = X8(i, "border-bottom-width"); + return i.clientHeight + e + t; + } + function fS(i, e = {}) { + const t = e.width || Qw(i), n = e.height || jw(i); + return { width: t, height: n }; + } + function Xw() { + let i, e; + try { + e = process; + } catch { + } + const t = e && e.env ? e.env.devicePixelRatio : null; + return t && (i = parseInt(t, 10), Number.isNaN(i) && (i = 1)), i || window.devicePixelRatio || 1; + } + function Jw(i) { + (i.width > A3 || i.height > A3) && (i.width > A3 && i.height > A3 ? i.width > i.height ? (i.height *= A3 / i.width, i.width = A3) : (i.width *= A3 / i.height, i.height = A3) : i.width > A3 ? (i.height *= A3 / i.width, i.width = A3) : (i.width *= A3 / i.height, i.height = A3)); + } + function eM(i, e = {}) { + return i.toBlob ? new Promise((t) => { + i.toBlob(t, e.type ? e.type : "image/png", e.quality ? e.quality : 1); + }) : new Promise((t) => { + const n = window.atob(i.toDataURL(e.type ? e.type : void 0, e.quality ? e.quality : void 0).split(",")[1]), s = n.length, l = new Uint8Array(s); + for (let c = 0; c < s; c += 1) + l[c] = n.charCodeAt(c); + t(new Blob([l], { + type: e.type ? e.type : "image/png" + })); + }); + } + function J8(i) { + return new Promise((e, t) => { + const n = new Image(); + n.onload = () => { + n.decode().then(() => { + requestAnimationFrame(() => e(n)); + }); + }, n.onerror = t, n.crossOrigin = "anonymous", n.decoding = "async", n.src = i; + }); + } + async function tM(i) { + return Promise.resolve().then(() => new XMLSerializer().serializeToString(i)).then(encodeURIComponent).then((e) => `data:image/svg+xml;charset=utf-8,${e}`); + } + async function nM(i, e, t) { + const n = "http://www.w3.org/2000/svg", s = document.createElementNS(n, "svg"), l = document.createElementNS(n, "foreignObject"); + return s.setAttribute("width", `${e}`), s.setAttribute("height", `${t}`), s.setAttribute("viewBox", `0 0 ${e} ${t}`), l.setAttribute("width", "100%"), l.setAttribute("height", "100%"), l.setAttribute("x", "0"), l.setAttribute("y", "0"), l.setAttribute("externalResourcesRequired", "true"), s.appendChild(l), l.appendChild(i), tM(s); + } + function iM(i) { + const e = i.getPropertyValue("content"); + return `${i.cssText} content: '${e.replace(/'|"/g, "")}';`; + } + function rM(i, e) { + return hS(e).map((t) => { + const n = i.getPropertyValue(t), s = i.getPropertyPriority(t); + return `${t}: ${n}${s ? " !important" : ""};`; + }).join(" "); + } + function aM(i, e, t, n) { + const s = `.${i}:${e}`, l = t.cssText ? iM(t) : rM(t, n); + return document.createTextNode(`${s}{${l}}`); + } + function rg(i, e, t, n) { + const s = window.getComputedStyle(i, t), l = s.getPropertyValue("content"); + if (l === "" || l === "none") + return; + const c = Kw(); + try { + e.className = `${e.className} ${c}`; + } catch { + return; + } + const L = document.createElement("style"); + L.appendChild(aM(c, t, s, n)), e.appendChild(L); + } + function sM(i, e, t) { + rg(i, e, ":before", t), rg(i, e, ":after", t); + } + function lM(i) { + const e = /\.([^./]*?)$/g.exec(i); + return e ? e[1] : ""; + } + function hu(i) { + const e = lM(i).toLowerCase(); + return oM[e] || ""; + } + function cM(i) { + return i.split(/,/)[1]; + } + function Pl(i) { + return i.search(/^(data:)/) !== -1; + } + function uM(i, e) { + return `data:${e};base64,${i}`; + } + async function ES(i, e, t) { + const n = await fetch(i, e); + if (n.status === 404) + throw new Error(`Resource "${n.url}" not found`); + const s = await n.blob(); + return new Promise((l, c) => { + const L = new FileReader(); + L.onerror = c, L.onloadend = () => { + try { + l(t({ res: n, result: L.result })); + } catch (d) { + c(d); + } + }, L.readAsDataURL(s); + }); + } + function LM(i, e, t) { + let n = i.replace(/\?.*/, ""); + return t && (n = i), /ttf|otf|eot|woff2?/i.test(n) && (n = n.replace(/.*\//, "")), e ? `[${e}]${n}` : n; + } + async function fu(i, e, t) { + const n = LM(i, e, t.includeQueryParams); + if (vr[n] != null) + return vr[n]; + t.cacheBust && (i += (/\?/.test(i) ? "&" : "?") + (/* @__PURE__ */ new Date()).getTime()); + let s; + try { + const l = await ES(i, t.fetchRequestInit, ({ res: c, result: L }) => (e || (e = c.headers.get("Content-Type") || ""), cM(L))); + s = uM(l, e); + } catch (l) { + s = t.imagePlaceholder || ""; + let c = `Failed to fetch resource: ${i}`; + l && (c = typeof l == "string" ? l : l.message), c && console.warn(c); + } + return vr[n] = s, s; + } + async function dM(i) { + const e = i.toDataURL(); + return e === "data:," ? i.cloneNode(false) : J8(e); + } + async function CM(i, e) { + if (i.currentSrc) { + const l = document.createElement("canvas"), c = l.getContext("2d"); + l.width = i.clientWidth, l.height = i.clientHeight, c == null || c.drawImage(i, 0, 0, l.width, l.height); + const L = l.toDataURL(); + return J8(L); + } + const t = i.poster, n = hu(t), s = await fu(t, n, e); + return J8(s); + } + async function _M(i, e) { + var t; + try { + if (!((t = i == null ? void 0 : i.contentDocument) === null || t === void 0) && t.body) + return await A6(i.contentDocument.body, e, true); + } catch { + } + return i.cloneNode(false); + } + async function gM(i, e) { + return d3(i, HTMLCanvasElement) ? dM(i) : d3(i, HTMLVideoElement) ? CM(i, e) : d3(i, HTMLIFrameElement) ? _M(i, e) : i.cloneNode(SS(i)); + } + async function mM(i, e, t) { + var n, s; + if (SS(e)) + return e; + let l = []; + return pM(i) && i.assignedNodes ? l = kt(i.assignedNodes()) : d3(i, HTMLIFrameElement) && (!((n = i.contentDocument) === null || n === void 0) && n.body) ? l = kt(i.contentDocument.body.childNodes) : l = kt(((s = i.shadowRoot) !== null && s !== void 0 ? s : i).childNodes), l.length === 0 || d3(i, HTMLVideoElement) || await l.reduce((c, L) => c.then(() => A6(L, t)).then((d) => { + d && e.appendChild(d); + }), Promise.resolve()), e; + } + function hM(i, e, t) { + const n = e.style; + if (!n) + return; + const s = window.getComputedStyle(i); + s.cssText ? (n.cssText = s.cssText, n.transformOrigin = s.transformOrigin) : hS(t).forEach((l) => { + let c = s.getPropertyValue(l); + l === "font-size" && c.endsWith("px") && (c = `${Math.floor(parseFloat(c.substring(0, c.length - 2))) - 0.1}px`), d3(i, HTMLIFrameElement) && l === "display" && c === "inline" && (c = "block"), l === "d" && e.getAttribute("d") && (c = `path(${e.getAttribute("d")})`), n.setProperty(l, c, s.getPropertyPriority(l)); + }); + } + function fM(i, e) { + d3(i, HTMLTextAreaElement) && (e.innerHTML = i.value), d3(i, HTMLInputElement) && e.setAttribute("value", i.value); + } + function EM(i, e) { + if (d3(i, HTMLSelectElement)) { + const t = e, n = Array.from(t.children).find((s) => i.value === s.getAttribute("value")); + n && n.setAttribute("selected", ""); + } + } + function SM(i, e, t) { + return d3(e, Element) && (hM(i, e, t), sM(i, e, t), fM(i, e), EM(i, e)), e; + } + async function TM(i, e) { + const t = i.querySelectorAll ? i.querySelectorAll("use") : []; + if (t.length === 0) + return i; + const n = {}; + for (let l = 0; l < t.length; l++) { + const L = t[l].getAttribute("xlink:href"); + if (L) { + const d = i.querySelector(L), _ = document.querySelector(L); + !d && _ && !n[L] && (n[L] = await A6(_, e, true)); + } + } + const s = Object.values(n); + if (s.length) { + const l = "http://www.w3.org/1999/xhtml", c = document.createElementNS(l, "svg"); + c.setAttribute("xmlns", l), c.style.position = "absolute", c.style.width = "0", c.style.height = "0", c.style.overflow = "hidden", c.style.display = "none"; + const L = document.createElementNS(l, "defs"); + c.appendChild(L); + for (let d = 0; d < s.length; d++) + L.appendChild(s[d]); + i.appendChild(c); + } + return i; + } + async function A6(i, e, t) { + return !t && e.filter && !e.filter(i) ? null : Promise.resolve(i).then((n) => gM(n, e)).then((n) => mM(i, n, e)).then((n) => SM(i, n, e)).then((n) => TM(n, e)); + } + function bM(i) { + const e = i.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1"); + return new RegExp(`(url\\(['"]?)(${e})(['"]?\\))`, "g"); + } + function xM(i) { + const e = []; + return i.replace(TS, (t, n, s) => (e.push(s), t)), e.filter((t) => !Pl(t)); + } + async function wM(i, e, t, n, s) { + try { + const l = t ? $w(e, t) : e, c = hu(e); + let L; + return s || (L = await fu(l, c, n)), i.replace(bM(e), `$1${L}$3`); + } catch { + } + return i; + } + function MM(i, { preferredFontFormat: e }) { + return e ? i.replace(RM, (t) => { + for (; ; ) { + const [n, , s] = vM.exec(t) || []; + if (!s) + return ""; + if (s === e) + return `src: ${n};`; + } + }) : i; + } + function vS(i) { + return i.search(TS) !== -1; + } + async function RS(i, e, t) { + if (!vS(i)) + return i; + const n = MM(i, t); + return xM(n).reduce((l, c) => l.then((L) => wM(L, c, e, t)), Promise.resolve(n)); + } + async function a0(i, e, t) { + var n; + const s = (n = e.style) === null || n === void 0 ? void 0 : n.getPropertyValue(i); + if (s) { + const l = await RS(s, null, t); + return e.style.setProperty(i, l, e.style.getPropertyPriority(i)), true; + } + return false; + } + async function AM(i, e) { + await a0("background", i, e) || await a0("background-image", i, e), await a0("mask", i, e) || await a0("-webkit-mask", i, e) || await a0("mask-image", i, e) || await a0("-webkit-mask-image", i, e); + } + async function yM(i, e) { + const t = d3(i, HTMLImageElement); + if (!(t && !Pl(i.src)) && !(d3(i, SVGImageElement) && !Pl(i.href.baseVal))) + return; + const n = t ? i.src : i.href.baseVal, s = await fu(n, hu(n), e); + await new Promise((l, c) => { + i.onload = l, i.onerror = e.onImageErrorHandler ? (...d) => { + try { + l(e.onImageErrorHandler(...d)); + } catch (_) { + c(_); + } + } : c; + const L = i; + L.decode && (L.decode = l), L.loading === "lazy" && (L.loading = "eager"), t ? (i.srcset = "", i.src = s) : i.href.baseVal = s; + }); + } + async function NM(i, e) { + const n = kt(i.childNodes).map((s) => bS(s, e)); + await Promise.all(n).then(() => i); + } + async function bS(i, e) { + d3(i, Element) && (await AM(i, e), await yM(i, e), await NM(i, e)); + } + function OM(i, e) { + const { style: t } = i; + e.backgroundColor && (t.backgroundColor = e.backgroundColor), e.width && (t.width = `${e.width}px`), e.height && (t.height = `${e.height}px`); + const n = e.style; + return n != null && Object.keys(n).forEach((s) => { + t[s] = n[s]; + }), i; + } + async function lg(i) { + let e = og[i]; + if (e != null) + return e; + const n = await (await fetch(i)).text(); + return e = { url: i, cssText: n }, og[i] = e, e; + } + async function cg(i, e) { + let t = i.cssText; + const n = /url\(["']?([^"')]+)["']?\)/g, l = (t.match(/url\([^)]+\)/g) || []).map(async (c) => { + let L = c.replace(n, "$1"); + return L.startsWith("https://") || (L = new URL(L, i.url).href), ES(L, e.fetchRequestInit, ({ result: d }) => (t = t.replace(c, `url(${d})`), [c, d])); + }); + return Promise.all(l).then(() => t); + } + function ug(i) { + if (i == null) + return []; + const e = [], t = /(\/\*[\s\S]*?\*\/)/gi; + let n = i.replace(t, ""); + const s = new RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})", "gi"); + for (; ; ) { + const d = s.exec(n); + if (d === null) + break; + e.push(d[0]); + } + n = n.replace(s, ""); + const l = /@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi, c = "((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})", L = new RegExp(c, "gi"); + for (; ; ) { + let d = l.exec(n); + if (d === null) { + if (d = L.exec(n), d === null) + break; + l.lastIndex = L.lastIndex; + } else + L.lastIndex = l.lastIndex; + e.push(d[0]); + } + return e; + } + async function IM(i, e) { + const t = [], n = []; + return i.forEach((s) => { + if ("cssRules" in s) + try { + kt(s.cssRules || []).forEach((l, c) => { + if (l.type === CSSRule.IMPORT_RULE) { + let L = c + 1; + const d = l.href, _ = lg(d).then((p) => cg(p, e)).then((p) => ug(p).forEach((m) => { + try { + s.insertRule(m, m.startsWith("@import") ? L += 1 : s.cssRules.length); + } catch (f) { + console.error("Error inserting rule from remote css", { + rule: m, + error: f + }); + } + })).catch((p) => { + console.error("Error loading remote css", p.toString()); + }); + n.push(_); + } + }); + } catch (l) { + const c = i.find((L) => L.href == null) || document.styleSheets[0]; + s.href != null && n.push(lg(s.href).then((L) => cg(L, e)).then((L) => ug(L).forEach((d) => { + c.insertRule(d, c.cssRules.length); + })).catch((L) => { + console.error("Error loading remote stylesheet", L); + })), console.error("Error inlining remote css file", l); + } + }), Promise.all(n).then(() => (i.forEach((s) => { + if ("cssRules" in s) + try { + kt(s.cssRules || []).forEach((l) => { + t.push(l); + }); + } catch (l) { + console.error(`Error while reading CSS rules from ${s.href}`, l); + } + }), t)); + } + function DM(i) { + return i.filter((e) => e.type === CSSRule.FONT_FACE_RULE).filter((e) => vS(e.style.getPropertyValue("src"))); + } + async function kM(i, e) { + if (i.ownerDocument == null) + throw new Error("Provided element is not within a Document"); + const t = kt(i.ownerDocument.styleSheets), n = await IM(t, e); + return DM(n); + } + function xS(i) { + return i.trim().replace(/["']/g, ""); + } + function PM(i) { + const e = /* @__PURE__ */ new Set(); + function t(n) { + (n.style.fontFamily || getComputedStyle(n).fontFamily).split(",").forEach((l) => { + e.add(xS(l)); + }), Array.from(n.children).forEach((l) => { + l instanceof HTMLElement && t(l); + }); + } + __name(t, "t"); + return t(i), e; + } + async function FM(i, e) { + const t = await kM(i, e), n = PM(i); + return (await Promise.all(t.filter((l) => n.has(xS(l.style.fontFamily))).map((l) => { + const c = l.parentStyleSheet ? l.parentStyleSheet.href : null; + return RS(l.cssText, c, e); + }))).join(` +`); + } + async function UM(i, e) { + const t = e.fontEmbedCSS != null ? e.fontEmbedCSS : e.skipFonts ? null : await FM(i, e); + if (t) { + const n = document.createElement("style"), s = document.createTextNode(t); + n.appendChild(s), i.firstChild ? i.insertBefore(n, i.firstChild) : i.appendChild(n); + } + } + async function Eu(i, e = {}) { + const { width: t, height: n } = fS(i, e), s = await A6(i, e, true); + return await UM(s, e), await bS(s, e), OM(s, e), await nM(s, t, n); + } + async function Su(i, e = {}) { + const { width: t, height: n } = fS(i, e), s = await Eu(i, e), l = await J8(s), c = document.createElement("canvas"), L = c.getContext("2d"), d = e.pixelRatio || Xw(), _ = e.canvasWidth || t, p = e.canvasHeight || n; + return c.width = _ * d, c.height = p * d, e.skipAutoScale || Jw(c), c.style.width = `${_}`, c.style.height = `${p}`, e.backgroundColor && (L.fillStyle = e.backgroundColor, L.fillRect(0, 0, c.width, c.height)), L.drawImage(l, 0, 0, c.width, c.height), c; + } + async function wS(i, e = {}) { + return (await Su(i, e)).toDataURL(); + } + async function ZM(i, e = {}) { + return (await Su(i, e)).toDataURL("image/jpeg", e.quality || 1); + } + async function BM(i, e = {}) { + const t = await Su(i, e); + return await eM(t); + } + function MS(i) { + var e, t, n = ""; + if (typeof i == "string" || typeof i == "number") n += i; + else if (typeof i == "object") if (Array.isArray(i)) { + var s = i.length; + for (e = 0; e < s; e++) i[e] && (t = MS(i[e])) && (n && (n += " "), n += t); + } else for (t in i) i[t] && (n && (n += " "), n += t); + return n; + } + function GM() { + for (var i, e, t = 0, n = "", s = arguments.length; t < s; t++) (i = arguments[t]) && (e = MS(i)) && (n && (n += " "), n += e); + return n; + } + function eA() { + let i = 0, e, t, n = ""; + for (; i < arguments.length; ) + (e = arguments[i++]) && (t = yS(e)) && (n && (n += " "), n += t); + return n; + } + function tA(i, ...e) { + let t, n, s, l = c; + function c(d) { + const _ = e.reduce((p, m) => m(p), i()); + return t = jM(_), n = t.cache.get, s = t.cache.set, l = L, L(d); + } + __name(c, "c"); + function L(d) { + const _ = n(d); + if (_) + return _; + const p = JM(d, t); + return s(d, p), p; + } + __name(L, "L"); + return function() { + return l(eA.apply(null, arguments)); + }; + } + function z2(...i) { + return MA(GM(i)); + } + function LZ(i) { + const e = v.useRef(null); + return FS(() => { + e.current = i; + }, [ + i + ]), v.useCallback((...t) => { + const n = e.current; + return n == null ? void 0 : n(...t); + }, []); + } + function dZ(i) { + return i !== null && typeof i == "object" && "nodeType" in i && typeof i.nodeType == "number"; + } + function CZ(i) { + return dZ(i) && i.nodeType === Node.DOCUMENT_FRAGMENT_NODE && "host" in i; + } + function Ru() { + return _Z; + } + function US(i, e) { + if (!Ru()) return e && i ? i.contains(e) : false; + if (!i || !e) return false; + let t = e; + for (; t !== null; ) { + if (t === i) return true; + t.tagName === "SLOT" && t.assignedSlot ? t = t.assignedSlot.parentNode : CZ(t) ? t = t.host : t = t.parentNode; + } + return false; + } + function ZS(i) { + return Ru() && i.target.shadowRoot && i.composedPath ? i.composedPath()[0] : i.target; + } + function gZ(i) { + var e; + return typeof window > "u" || window.navigator == null ? false : ((e = window.navigator.userAgentData) === null || e === void 0 ? void 0 : e.brands.some((t) => i.test(t.brand))) || i.test(window.navigator.userAgent); + } + function pZ(i) { + var e; + return typeof window < "u" && window.navigator != null ? i.test(((e = window.navigator.userAgentData) === null || e === void 0 ? void 0 : e.platform) || window.navigator.platform) : false; + } + function BS(i) { + let e = null; + return () => (e == null && (e = i()), e); + } + function GS() { + let i = v.useRef(/* @__PURE__ */ new Map()), e = v.useCallback((s, l, c, L) => { + let d = L != null && L.once ? (..._) => { + i.current.delete(c), c(..._); + } : c; + i.current.set(c, { + type: l, + eventTarget: s, + fn: d, + options: L + }), s.addEventListener(l, d, L); + }, []), t = v.useCallback((s, l, c, L) => { + var d; + let _ = ((d = i.current.get(c)) === null || d === void 0 ? void 0 : d.fn) || c; + s.removeEventListener(l, _, L), i.current.delete(c); + }, []), n = v.useCallback(() => { + i.current.forEach((s, l) => { + t(s.eventTarget, s.type, l, s.options); + }); + }, [ + t + ]); + return v.useEffect(() => n, [ + n + ]), { + addGlobalListener: e, + removeGlobalListener: t, + removeAllGlobalListeners: n + }; + } + function fZ(i) { + return i.mozInputSource === 0 && i.isTrusted ? true : hZ() && i.pointerType ? i.type === "click" && i.buttons === 1 : i.detail === 0 && !i.pointerType; + } + function EZ() { + if (yg) return ke; + yg = 1; + var i = cc(); + function e(d) { + var _ = "https://react.dev/errors/" + d; + if (1 < arguments.length) { + _ += "?args[]=" + encodeURIComponent(arguments[1]); + for (var p = 2; p < arguments.length; p++) + _ += "&args[]=" + encodeURIComponent(arguments[p]); + } + return "Minified React error #" + d + "; visit " + _ + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings."; + } + __name(e, "e"); + function t() { + } + __name(t, "t"); + var n = { + d: { + f: t, + r: /* @__PURE__ */ __name(function() { + throw Error(e(522)); + }, "r"), + D: t, + C: t, + L: t, + m: t, + X: t, + S: t, + M: t + }, + p: 0, + findDOMNode: null + }, s = Symbol.for("react.portal"); + function l(d, _, p) { + var m = 3 < arguments.length && arguments[3] !== void 0 ? arguments[3] : null; + return { + $$typeof: s, + key: m == null ? null : "" + m, + children: d, + containerInfo: _, + implementation: p + }; + } + __name(l, "l"); + var c = i.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; + function L(d, _) { + if (d === "font") return ""; + if (typeof _ == "string") + return _ === "use-credentials" ? _ : ""; + } + __name(L, "L"); + return ke.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = n, ke.createPortal = function(d, _) { + var p = 2 < arguments.length && arguments[2] !== void 0 ? arguments[2] : null; + if (!_ || _.nodeType !== 1 && _.nodeType !== 9 && _.nodeType !== 11) + throw Error(e(299)); + return l(d, _, null, p); + }, ke.flushSync = function(d) { + var _ = c.T, p = n.p; + try { + if (c.T = null, n.p = 2, d) return d(); + } finally { + c.T = _, n.p = p, n.d.f(); + } + }, ke.preconnect = function(d, _) { + typeof d == "string" && (_ ? (_ = _.crossOrigin, _ = typeof _ == "string" ? _ === "use-credentials" ? _ : "" : void 0) : _ = null, n.d.C(d, _)); + }, ke.prefetchDNS = function(d) { + typeof d == "string" && n.d.D(d); + }, ke.preinit = function(d, _) { + if (typeof d == "string" && _ && typeof _.as == "string") { + var p = _.as, m = L(p, _.crossOrigin), f = typeof _.integrity == "string" ? _.integrity : void 0, h = typeof _.fetchPriority == "string" ? _.fetchPriority : void 0; + p === "style" ? n.d.S( + d, + typeof _.precedence == "string" ? _.precedence : void 0, + { + crossOrigin: m, + integrity: f, + fetchPriority: h + } + ) : p === "script" && n.d.X(d, { + crossOrigin: m, + integrity: f, + fetchPriority: h, + nonce: typeof _.nonce == "string" ? _.nonce : void 0 + }); + } + }, ke.preinitModule = function(d, _) { + if (typeof d == "string") + if (typeof _ == "object" && _ !== null) { + if (_.as == null || _.as === "script") { + var p = L( + _.as, + _.crossOrigin + ); + n.d.M(d, { + crossOrigin: p, + integrity: typeof _.integrity == "string" ? _.integrity : void 0, + nonce: typeof _.nonce == "string" ? _.nonce : void 0 + }); + } + } else _ == null && n.d.M(d); + }, ke.preload = function(d, _) { + if (typeof d == "string" && typeof _ == "object" && _ !== null && typeof _.as == "string") { + var p = _.as, m = L(p, _.crossOrigin); + n.d.L(d, p, { + crossOrigin: m, + integrity: typeof _.integrity == "string" ? _.integrity : void 0, + nonce: typeof _.nonce == "string" ? _.nonce : void 0, + type: typeof _.type == "string" ? _.type : void 0, + fetchPriority: typeof _.fetchPriority == "string" ? _.fetchPriority : void 0, + referrerPolicy: typeof _.referrerPolicy == "string" ? _.referrerPolicy : void 0, + imageSrcSet: typeof _.imageSrcSet == "string" ? _.imageSrcSet : void 0, + imageSizes: typeof _.imageSizes == "string" ? _.imageSizes : void 0, + media: typeof _.media == "string" ? _.media : void 0 + }); + } + }, ke.preloadModule = function(d, _) { + if (typeof d == "string") + if (_) { + var p = L(_.as, _.crossOrigin); + n.d.m(d, { + as: typeof _.as == "string" && _.as !== "script" ? _.as : void 0, + crossOrigin: p, + integrity: typeof _.integrity == "string" ? _.integrity : void 0 + }); + } else n.d.m(d); + }, ke.requestFormReset = function(d) { + n.d.r(d); + }, ke.unstable_batchedUpdates = function(d, _) { + return d(_); + }, ke.useFormState = function(d, _, p) { + return c.H.useFormState(d, _, p); + }, ke.useFormStatus = function() { + return c.H.useHostTransitionStatus(); + }, ke.version = "19.1.0", ke; + } + function zS() { + if (Ng) return wr.exports; + Ng = 1; + function i() { + if (!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ > "u" || typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE != "function")) + try { + __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i); + } catch (e) { + console.error(e); + } + } + __name(i, "i"); + return i(), wr.exports = EZ(), wr.exports; + } + function HS(i) { + let e = i; + return e.nativeEvent = i, e.isDefaultPrevented = () => e.defaultPrevented, e.isPropagationStopped = () => e.cancelBubble, e.persist = () => { + }, e; + } + function SZ(i, e) { + Object.defineProperty(i, "target", { + value: e + }), Object.defineProperty(i, "currentTarget", { + value: e + }); + } + function YS(i) { + let e = v.useRef({ + isFocused: false, + observer: null + }); + FS(() => { + const n = e.current; + return () => { + n.observer && (n.observer.disconnect(), n.observer = null); + }; + }, []); + let t = LZ((n) => { + i == null || i(n); + }); + return v.useCallback((n) => { + if (n.target instanceof HTMLButtonElement || n.target instanceof HTMLInputElement || n.target instanceof HTMLTextAreaElement || n.target instanceof HTMLSelectElement) { + e.current.isFocused = true; + let s = n.target, l = /* @__PURE__ */ __name((c) => { + if (e.current.isFocused = false, s.disabled) { + let L = HS(c); + t(L); + } + e.current.observer && (e.current.observer.disconnect(), e.current.observer = null); + }, "l"); + s.addEventListener("focusout", l, { + once: true + }), e.current.observer = new MutationObserver(() => { + if (e.current.isFocused && s.disabled) { + var c; + (c = e.current.observer) === null || c === void 0 || c.disconnect(); + let L = s === document.activeElement ? null : document.activeElement; + s.dispatchEvent(new FocusEvent("blur", { + relatedTarget: L + })), s.dispatchEvent(new FocusEvent("focusout", { + bubbles: true, + relatedTarget: L + })); + } + }), e.current.observer.observe(s, { + attributes: true, + attributeFilter: [ + "disabled" + ] + }); + } + }, [ + t + ]); + } + function xu(i, e) { + for (let t of zl) t(i, e); + } + function RZ(i) { + return !(i.metaKey || !mZ() && i.altKey || i.ctrlKey || i.key === "Control" || i.key === "Shift" || i.key === "Meta"); + } + function e6(i) { + T9 = true, RZ(i) && (un = "keyboard", xu("keyboard", i)); + } + function L0(i) { + un = "pointer", (i.type === "mousedown" || i.type === "pointerdown") && (T9 = true, xu("pointer", i)); + } + function VS(i) { + fZ(i) && (T9 = true, un = "virtual"); + } + function qS(i) { + i.target === window || i.target === document || TZ || !i.isTrusted || (!T9 && !Hl && (un = "virtual", xu("virtual", i)), T9 = false, Hl = false); + } + function WS() { + T9 = false, Hl = true; + } + function Yl(i) { + if (typeof window > "u" || G5.get(g9(i))) return; + const e = g9(i), t = zt(i); + let n = e.HTMLElement.prototype.focus; + e.HTMLElement.prototype.focus = function() { + T9 = true, n.apply(this, arguments); + }, t.addEventListener("keydown", e6, true), t.addEventListener("keyup", e6, true), t.addEventListener("click", VS, true), e.addEventListener("focus", qS, true), e.addEventListener("blur", WS, false), typeof PointerEvent < "u" && (t.addEventListener("pointerdown", L0, true), t.addEventListener("pointermove", L0, true), t.addEventListener("pointerup", L0, true)), e.addEventListener("beforeunload", () => { + $S(i); + }, { + once: true + }), G5.set(e, { + focus: n + }); + } + function bZ(i) { + const e = zt(i); + let t; + return e.readyState !== "loading" ? Yl(i) : (t = /* @__PURE__ */ __name(() => { + Yl(i); + }, "t"), e.addEventListener("DOMContentLoaded", t)), () => $S(i, t); + } + function KS() { + return un !== "pointer"; + } + function wZ(i, e, t) { + let n = zt(t == null ? void 0 : t.target); + const s = typeof window < "u" ? g9(t == null ? void 0 : t.target).HTMLInputElement : HTMLInputElement, l = typeof window < "u" ? g9(t == null ? void 0 : t.target).HTMLTextAreaElement : HTMLTextAreaElement, c = typeof window < "u" ? g9(t == null ? void 0 : t.target).HTMLElement : HTMLElement, L = typeof window < "u" ? g9(t == null ? void 0 : t.target).KeyboardEvent : KeyboardEvent; + return i = i || n.activeElement instanceof s && !xZ.has(n.activeElement.type) || n.activeElement instanceof l || n.activeElement instanceof c && n.activeElement.isContentEditable, !(i && e === "keyboard" && t instanceof L && !vZ[t.key]); + } + function MZ(i, e, t) { + Yl(), v.useEffect(() => { + let n = /* @__PURE__ */ __name((s, l) => { + wZ(!!(t != null && t.isTextInput), s, l) && i(KS()); + }, "n"); + return zl.add(n), () => { + zl.delete(n); + }; + }, e); + } + function AZ(i) { + let { isDisabled: e, onFocus: t, onBlur: n, onFocusChange: s } = i; + const l = v.useCallback((d) => { + if (d.target === d.currentTarget) + return n && n(d), s && s(false), true; + }, [ + n, + s + ]), c = YS(l), L = v.useCallback((d) => { + const _ = zt(d.target), p = _ ? Gl(_) : Gl(); + d.target === d.currentTarget && p === ZS(d.nativeEvent) && (t && t(d), s && s(true), c(d)); + }, [ + s, + t, + c + ]); + return { + focusProps: { + onFocus: !e && (t || s || n) ? L : void 0, + onBlur: !e && (n || s) ? l : void 0 + } + }; + } + function yZ(i) { + let { isDisabled: e, onBlurWithin: t, onFocusWithin: n, onFocusWithinChange: s } = i, l = v.useRef({ + isFocusWithin: false + }), { addGlobalListener: c, removeAllGlobalListeners: L } = GS(), d = v.useCallback((m) => { + m.currentTarget.contains(m.target) && l.current.isFocusWithin && !m.currentTarget.contains(m.relatedTarget) && (l.current.isFocusWithin = false, L(), t && t(m), s && s(false)); + }, [ + t, + s, + l, + L + ]), _ = YS(d), p = v.useCallback((m) => { + if (!m.currentTarget.contains(m.target)) return; + const f = zt(m.target), h = Gl(f); + if (!l.current.isFocusWithin && h === ZS(m.nativeEvent)) { + n && n(m), s && s(true), l.current.isFocusWithin = true, _(m); + let R = m.currentTarget; + c(f, "focus", (b) => { + if (l.current.isFocusWithin && !US(R, b.target)) { + let M = new f.defaultView.FocusEvent("blur", { + relatedTarget: b.target + }); + SZ(M, R); + let w = HS(M); + d(w); + } + }, { + capture: true + }); + } + }, [ + n, + s, + _, + c, + d + ]); + return e ? { + focusWithinProps: { + // These cannot be null, that would conflict in mergeProps + onFocus: void 0, + onBlur: void 0 + } + } : { + focusWithinProps: { + onFocus: p, + onBlur: d + } + }; + } + function NZ() { + Vl = true, setTimeout(() => { + Vl = false; + }, 50); + } + function Og(i) { + i.pointerType === "touch" && NZ(); + } + function OZ() { + if (!(typeof document > "u")) + return typeof PointerEvent < "u" && document.addEventListener("pointerup", Og), Mr++, () => { + Mr--, !(Mr > 0) && typeof PointerEvent < "u" && document.removeEventListener("pointerup", Og); + }; + } + function QS(i) { + let { onHoverStart: e, onHoverChange: t, onHoverEnd: n, isDisabled: s } = i, [l, c] = v.useState(false), L = v.useRef({ + isHovered: false, + ignoreEmulatedMouseEvents: false, + pointerType: "", + target: null + }).current; + v.useEffect(OZ, []); + let { addGlobalListener: d, removeAllGlobalListeners: _ } = GS(), { hoverProps: p, triggerHoverEnd: m } = v.useMemo(() => { + let f = /* @__PURE__ */ __name((b, M) => { + if (L.pointerType = M, s || M === "touch" || L.isHovered || !b.currentTarget.contains(b.target)) return; + L.isHovered = true; + let w = b.currentTarget; + L.target = w, d(zt(b.target), "pointerover", (O) => { + L.isHovered && L.target && !US(L.target, O.target) && h(O, O.pointerType); + }, { + capture: true + }), e && e({ + type: "hoverstart", + target: w, + pointerType: M + }), t && t(true), c(true); + }, "f"), h = /* @__PURE__ */ __name((b, M) => { + let w = L.target; + L.pointerType = "", L.target = null, !(M === "touch" || !L.isHovered || !w) && (L.isHovered = false, _(), n && n({ + type: "hoverend", + target: w, + pointerType: M + }), t && t(false), c(false)); + }, "h"), R = {}; + return typeof PointerEvent < "u" && (R.onPointerEnter = (b) => { + Vl && b.pointerType === "mouse" || f(b, b.pointerType); + }, R.onPointerLeave = (b) => { + !s && b.currentTarget.contains(b.target) && h(b, b.pointerType); + }), { + hoverProps: R, + triggerHoverEnd: h + }; + }, [ + e, + t, + n, + s, + L, + d, + _ + ]); + return v.useEffect(() => { + s && m({ + currentTarget: L.target + }, L.pointerType); + }, [ + s + ]), { + hoverProps: p, + isHovered: l + }; + } + function jS(i = {}) { + let { autoFocus: e = false, isTextInput: t, within: n } = i, s = v.useRef({ + isFocused: false, + isFocusVisible: e || KS() + }), [l, c] = v.useState(false), [L, d] = v.useState(() => s.current.isFocused && s.current.isFocusVisible), _ = v.useCallback(() => d(s.current.isFocused && s.current.isFocusVisible), []), p = v.useCallback((h) => { + s.current.isFocused = h, c(h), _(); + }, [ + _ + ]); + MZ((h) => { + s.current.isFocusVisible = h, _(); + }, [], { + isTextInput: t + }); + let { focusProps: m } = AZ({ + isDisabled: n, + onFocusChange: p + }), { focusWithinProps: f } = yZ({ + isDisabled: !n, + onFocusWithinChange: p + }); + return { + isFocused: l, + isFocusVisible: L, + focusProps: n ? f : m + }; + } + function Ln(i) { + var e, t; + return m9.isServer ? null : i ? "ownerDocument" in i ? i.ownerDocument : "current" in i ? (t = (e = i.current) == null ? void 0 : e.ownerDocument) != null ? t : document : null : document; + } + function y6(i) { + typeof queueMicrotask == "function" ? queueMicrotask(i) : Promise.resolve().then(i).catch((e) => setTimeout(() => { + throw e; + })); + } + function Ht() { + let i = [], e = { addEventListener(t, n, s, l) { + return t.addEventListener(n, s, l), e.add(() => t.removeEventListener(n, s, l)); + }, requestAnimationFrame(...t) { + let n = requestAnimationFrame(...t); + return e.add(() => cancelAnimationFrame(n)); + }, nextFrame(...t) { + return e.requestAnimationFrame(() => e.requestAnimationFrame(...t)); + }, setTimeout(...t) { + let n = setTimeout(...t); + return e.add(() => clearTimeout(n)); + }, microTask(...t) { + let n = { current: true }; + return y6(() => { + n.current && t[0](); + }), e.add(() => { + n.current = false; + }); + }, style(t, n, s) { + let l = t.style.getPropertyValue(n); + return Object.assign(t.style, { [n]: s }), this.add(() => { + Object.assign(t.style, { [n]: l }); + }); + }, group(t) { + let n = Ht(); + return t(n), this.add(() => n.dispose()); + }, add(t) { + return i.includes(t) || i.push(t), () => { + let n = i.indexOf(t); + if (n >= 0) for (let s of i.splice(n, 1)) s(); + }; + }, dispose() { + for (let t of i.splice(0)) t(); + } }; + return e; + } + function N6() { + let [i] = v.useState(Ht); + return v.useEffect(() => () => i.dispose(), [i]), i; + } + function X4(i) { + let e = v.useRef(i); + return be(() => { + e.current = i; + }, [i]), e; + } + function O6() { + return v.useContext(PZ); + } + function ql(...i) { + return Array.from(new Set(i.flatMap((e) => typeof e == "string" ? e.split(" ") : []))).filter(Boolean).join(" "); + } + function $4(i, e, ...t) { + if (i in e) { + let s = e[i]; + return typeof s == "function" ? s(...t) : s; + } + let n = new Error(`Tried to handle "${i}" but there is no handler defined. Only defined handlers are: ${Object.keys(e).map((s) => `"${s}"`).join(", ")}.`); + throw Error.captureStackTrace && Error.captureStackTrace(n, $4), n; + } + function Ge() { + let i = UZ(); + return v.useCallback((e) => FZ({ mergeRefs: i, ...e }), [i]); + } + function FZ({ ourProps: i, theirProps: e, slot: t, defaultTag: n, features: s, visible: l = true, name: c, mergeRefs: L }) { + L = L ?? ZZ; + let d = XS(e, i); + if (l) return x8(d, t, n, c, L); + let _ = s ?? 0; + if (_ & 2) { + let { static: p = false, ...m } = d; + if (p) return x8(m, t, n, c, L); + } + if (_ & 1) { + let { unmount: p = true, ...m } = d; + return $4(p ? 0 : 1, { 0() { + return null; + }, 1() { + return x8({ ...m, hidden: true, style: { display: "none" } }, t, n, c, L); + } }); + } + return x8(d, t, n, c, L); + } + function x8(i, e = {}, t, n, s) { + let { as: l = t, children: c, refName: L = "ref", ...d } = yr(i, ["unmount", "static"]), _ = i.ref !== void 0 ? { [L]: i.ref } : {}, p = typeof c == "function" ? c(e) : c; + "className" in d && d.className && typeof d.className == "function" && (d.className = d.className(e)), d["aria-labelledby"] && d["aria-labelledby"] === d.id && (d["aria-labelledby"] = void 0); + let m = {}; + if (e) { + let f = false, h = []; + for (let [R, b] of Object.entries(e)) typeof b == "boolean" && (f = true), b === true && h.push(R.replace(/([A-Z])/g, (M) => `-${M.toLowerCase()}`)); + if (f) { + m["data-headlessui-state"] = h.join(" "); + for (let R of h) m[`data-${R}`] = ""; + } + } + if (l === v.Fragment && (Object.keys(yt(d)).length > 0 || Object.keys(yt(m)).length > 0)) if (!v.isValidElement(p) || Array.isArray(p) && p.length > 1) { + if (Object.keys(yt(d)).length > 0) throw new Error(['Passing props on "Fragment"!', "", `The current component <${n} /> is rendering a "Fragment".`, "However we need to passthrough the following props:", Object.keys(yt(d)).concat(Object.keys(yt(m))).map((f) => ` - ${f}`).join(` +`), "", "You can apply a few solutions:", ['Add an `as="..."` prop, to ensure that we render an actual element instead of a "Fragment".', "Render a single element as the child so that we can forward the props onto that element."].map((f) => ` - ${f}`).join(` +`)].join(` +`)); + } else { + let f = p.props, h = f == null ? void 0 : f.className, R = typeof h == "function" ? (...w) => ql(h(...w), d.className) : ql(h, d.className), b = R ? { className: R } : {}, M = XS(p.props, yt(yr(d, ["ref"]))); + for (let w in m) w in M && delete m[w]; + return v.cloneElement(p, Object.assign({}, M, m, _, { ref: s(BZ(p), _.ref) }, b)); + } + return v.createElement(l, Object.assign({}, yr(d, ["ref"]), l !== v.Fragment && _, l !== v.Fragment && m), p); + } + function UZ() { + let i = v.useRef([]), e = v.useCallback((t) => { + for (let n of i.current) n != null && (typeof n == "function" ? n(t) : n.current = t); + }, []); + return (...t) => { + if (!t.every((n) => n == null)) return i.current = t, e; + }; + } + function ZZ(...i) { + return i.every((e) => e == null) ? void 0 : (e) => { + for (let t of i) t != null && (typeof t == "function" ? t(e) : t.current = e); + }; + } + function XS(...i) { + if (i.length === 0) return {}; + if (i.length === 1) return i[0]; + let e = {}, t = {}; + for (let n of i) for (let s in n) s.startsWith("on") && typeof n[s] == "function" ? (t[s] != null || (t[s] = []), t[s].push(n[s])) : e[s] = n[s]; + if (e.disabled || e["aria-disabled"]) for (let n in t) /^(on(?:Click|Pointer|Mouse|Key)(?:Down|Up|Press)?)$/.test(n) && (t[n] = [(s) => { + var l; + return (l = s == null ? void 0 : s.preventDefault) == null ? void 0 : l.call(s); + }]); + for (let n in t) Object.assign(e, { [n](s, ...l) { + let c = t[n]; + for (let L of c) { + if ((s instanceof Event || (s == null ? void 0 : s.nativeEvent) instanceof Event) && s.defaultPrevented) return; + L(s, ...l); + } + } }); + return e; + } + function JS(...i) { + if (i.length === 0) return {}; + if (i.length === 1) return i[0]; + let e = {}, t = {}; + for (let n of i) for (let s in n) s.startsWith("on") && typeof n[s] == "function" ? (t[s] != null || (t[s] = []), t[s].push(n[s])) : e[s] = n[s]; + for (let n in t) Object.assign(e, { [n](...s) { + let l = t[n]; + for (let c of l) c == null || c(...s); + } }); + return e; + } + function xe(i) { + var e; + return Object.assign(v.forwardRef(i), { displayName: (e = i.displayName) != null ? e : i.name }); + } + function yt(i) { + let e = Object.assign({}, i); + for (let t in e) e[t] === void 0 && delete e[t]; + return e; + } + function yr(i, e = []) { + let t = Object.assign({}, i); + for (let n of e) n in t && delete t[n]; + return t; + } + function BZ(i) { + return I2.version.split(".")[0] >= "19" ? i.props.ref : i.ref; + } + function GZ(i, e, t) { + let [n, s] = v.useState(t), l = i !== void 0, c = v.useRef(l), L = v.useRef(false), d = v.useRef(false); + return l && !c.current && !L.current ? (L.current = true, c.current = l, console.error("A component is changing from uncontrolled to controlled. This may be caused by the value changing from undefined to a defined value, which should not happen.")) : !l && c.current && !d.current && (d.current = true, c.current = l, console.error("A component is changing from controlled to uncontrolled. This may be caused by the value changing from a defined value to undefined, which should not happen.")), [l ? i : n, f1((_) => (l || s(_), e == null ? void 0 : e(_)))]; + } + function zZ(i) { + let [e] = v.useState(i); + return e; + } + function eT(i = {}, e = null, t = []) { + for (let [n, s] of Object.entries(i)) nT(t, tT(e, n), s); + return t; + } + function tT(i, e) { + return i ? i + "[" + e + "]" : e; + } + function nT(i, e, t) { + if (Array.isArray(t)) for (let [n, s] of t.entries()) nT(i, tT(e, n.toString()), s); + else t instanceof Date ? i.push([e, t.toISOString()]) : typeof t == "boolean" ? i.push([e, t ? "1" : "0"]) : typeof t == "string" ? i.push([e, t]) : typeof t == "number" ? i.push([e, `${t}`]) : t == null ? i.push([e, ""]) : eT(t, e, i); + } + function HZ(i) { + var e, t; + let n = (e = i == null ? void 0 : i.form) != null ? e : i.closest("form"); + if (n) { + for (let s of n.elements) if (s !== i && (s.tagName === "INPUT" && s.type === "submit" || s.tagName === "BUTTON" && s.type === "submit" || s.nodeName === "INPUT" && s.type === "image")) { + s.click(); + return; + } + (t = n.requestSubmit) == null || t.call(n); + } + } + function VZ(i, e) { + var t; + let { features: n = 1, ...s } = i, l = { ref: e, "aria-hidden": (n & 2) === 2 ? true : (t = s["aria-hidden"]) != null ? t : void 0, hidden: (n & 4) === 4 ? true : void 0, style: { position: "fixed", top: 1, left: 1, width: 1, height: 0, padding: 0, margin: -1, overflow: "hidden", clip: "rect(0, 0, 0, 0)", whiteSpace: "nowrap", borderWidth: "0", ...(n & 4) === 4 && (n & 2) !== 2 && { display: "none" } } }; + return Ge()({ ourProps: l, theirProps: s, slot: {}, defaultTag: YZ, name: "Hidden" }); + } + function WZ({ children: i }) { + let e = v.useContext(qZ); + if (!e) return I2.createElement(I2.Fragment, null, i); + let { target: t } = e; + return t ? bu.createPortal(I2.createElement(I2.Fragment, null, i), t) : null; + } + function $Z({ data: i, form: e, disabled: t, onReset: n, overrides: s }) { + let [l, c] = v.useState(null), L = N6(); + return v.useEffect(() => { + if (n && l) return L.addEventListener(l, "reset", n); + }, [l, e, n]), I2.createElement(WZ, null, I2.createElement(KZ, { setForm: c, formId: e }), eT(i).map(([d, _]) => I2.createElement(K5, { features: m0.Hidden, ...yt({ key: d, as: "input", type: "hidden", hidden: true, readOnly: true, form: e, disabled: t, name: d, value: _, ...s }) }))); + } + function KZ({ setForm: i, formId: e }) { + return v.useEffect(() => { + if (e) { + let t = document.getElementById(e); + t && i(t); + } + }, [i, e]), e ? null : I2.createElement(K5, { features: m0.Hidden, as: "input", type: "hidden", hidden: true, readOnly: true, ref: /* @__PURE__ */ __name((t) => { + if (!t) return; + let n = t.closest("form"); + n && i(n); + }, "ref") }); + } + function iT() { + return v.useContext(QZ); + } + function rT(i) { + let e = i.parentElement, t = null; + for (; e && !(e instanceof HTMLFieldSetElement); ) e instanceof HTMLLegendElement && (t = e), e = e.parentElement; + let n = (e == null ? void 0 : e.getAttribute("disabled")) === ""; + return n && jZ(t) ? false : n; + } + function jZ(i) { + if (!i) return false; + let e = i.previousElementSibling; + for (; e !== null; ) { + if (e instanceof HTMLLegendElement) return false; + e = e.previousElementSibling; + } + return true; + } + function XZ(i, e = true) { + return Object.assign(i, { [aT]: e }); + } + function _3(...i) { + let e = v.useRef(i); + v.useEffect(() => { + e.current = i; + }, [i]); + let t = f1((n) => { + for (let s of e.current) s != null && (typeof s == "function" ? s(n) : s.current = n); + }); + return i.every((n) => n == null || (n == null ? void 0 : n[aT])) ? void 0 : t; + } + function sT() { + let i = v.useContext(I6); + if (i === null) { + let e = new Error("You used a component, but it is not inside a relevant parent."); + throw Error.captureStackTrace && Error.captureStackTrace(e, sT), e; + } + return i; + } + function JZ() { + var i, e; + return (e = (i = v.useContext(I6)) == null ? void 0 : i.value) != null ? e : void 0; + } + function wu() { + let [i, e] = v.useState([]); + return [i.length > 0 ? i.join(" ") : void 0, v.useMemo(() => function(t) { + let n = f1((l) => (e((c) => [...c, l]), () => e((c) => { + let L = c.slice(), d = L.indexOf(l); + return d !== -1 && L.splice(d, 1), L; + }))), s = v.useMemo(() => ({ register: n, slot: t.slot, name: t.name, props: t.props, value: t.value }), [n, t.slot, t.name, t.props, t.value]); + return I2.createElement(I6.Provider, { value: s }, t.children); + }, [e])]; + } + function tB(i, e) { + let t = v.useId(), n = O6(), { id: s = `headlessui-description-${t}`, ...l } = i, c = sT(), L = _3(e); + be(() => c.register(s), [s, c.register]); + let d = n || false, _ = v.useMemo(() => ({ ...c.slot, disabled: d }), [c.slot, d]), p = { ref: L, ...c.props, id: s }; + return Ge()({ ourProps: p, theirProps: l, slot: _, defaultTag: eB, name: c.name || "Description" }); + } + function lT() { + let i = v.useContext(D6); + if (i === null) { + let e = new Error("You used a