diff --git a/Cargo.toml b/Cargo.toml index e2baec5f..accfe9ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "src/apps/cli", "src/apps/desktop", "src/apps/server", + "src/apps/relay-server", ] exclude = [ @@ -63,7 +64,7 @@ reqwest = { version = "0.12", default-features = false, features = ["rustls-tls- # Debug Log HTTP Server axum = { version = "0.7", features = ["json", "ws"] } -tower-http = { version = "0.6", features = ["cors"] } +tower-http = { version = "0.6", features = ["cors", "fs"] } # File system glob = "0.3" @@ -111,6 +112,24 @@ win32job = "2.0" fluent-bundle = "0.15" unic-langid = "0.9" +# Encryption (Remote Connect E2E) +x25519-dalek = { version = "2.0", features = ["static_secrets"] } +aes-gcm = "0.10" +sha2 = "0.10" +rand = "0.8" + +# Device/Network info (Remote Connect) +mac_address = "1.1" +local-ip-address = "0.6" +hostname = "0.4" + +# QR code generation +qrcode = "0.14" +image = { version = "0.25", default-features = false, features = ["png"] } + +# WebSocket client +tokio-tungstenite = { version = "0.21", features = ["native-tls"] } + [profile.dev] incremental = true diff --git a/package-lock.json b/package-lock.json index 0879afde..53d7c869 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "partial-json": "^0.1.7", "path-browserify": "^1.0.1", "prismjs": "^1.30.0", + "qrcode.react": "^4.2.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-i18next": "^16.5.3", @@ -6552,6 +6553,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/qrcode.react": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz", + "integrity": "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", diff --git a/package.json b/package.json index 745e7282..e7262dd5 100644 --- a/package.json +++ b/package.json @@ -17,15 +17,16 @@ "prebuild:web": "npm run copy-assets --silent && npm run generate-all --silent", "build": "cd src/web-ui && vite build", "build:web": "cd src/web-ui && vite build", + "build:mobile-web": "cd src/mobile-web && npm install --silent && npm run build", "preview": "cd src/web-ui && vite preview", "desktop:dev": "node scripts/dev.cjs desktop", "desktop:dev:raw": "cd src/apps/desktop && npm exec -- tauri dev", - "desktop:build": "cd src/apps/desktop && npm exec -- tauri build", + "desktop:build": "npm run build:web && npm run build:mobile-web && cd src/apps/desktop && npm exec -- tauri build", "desktop:build:fast": "cd src/apps/desktop && npm exec -- tauri build --debug --no-bundle", "desktop:build:release-fast": "cd src/apps/desktop && npm exec -- tauri build --no-bundle -- --profile release-fast", - "desktop:build:exe": "cd src/apps/desktop && npm exec -- tauri build --no-bundle", - "desktop:build:nsis": "cd src/apps/desktop && npm exec -- tauri build --bundles nsis", - "desktop:build:x86_64": "cd src/apps/desktop && npm exec -- tauri build --target x86_64-apple-darwin", + "desktop:build:exe": "npm run build:web && npm run build:mobile-web && cd src/apps/desktop && npm exec -- tauri build --no-bundle", + "desktop:build:nsis": "npm run build:web && npm run build:mobile-web && cd src/apps/desktop && npm exec -- tauri build --bundles nsis", + "desktop:build:x86_64": "npm run build:web && npm run build:mobile-web && cd src/apps/desktop && npm exec -- tauri build --target x86_64-apple-darwin", "installer:build": "npm --prefix BitFun-Installer run installer:build", "installer:build:fast": "npm --prefix BitFun-Installer run installer:build:fast", "installer:build:only": "npm --prefix BitFun-Installer run installer:build:only", @@ -90,6 +91,7 @@ "partial-json": "^0.1.7", "path-browserify": "^1.0.1", "prismjs": "^1.30.0", + "qrcode.react": "^4.2.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-i18next": "^16.5.3", diff --git a/scripts/dev.cjs b/scripts/dev.cjs index 4b838885..638d7aa5 100644 --- a/scripts/dev.cjs +++ b/scripts/dev.cjs @@ -115,9 +115,11 @@ async function main() { printHeader(`BitFun ${modeLabel} Development`); printBlank(); - + + const totalSteps = mode === 'desktop' ? 4 : 3; + // Step 1: Copy resources - printStep(1, 3, 'Copy resources'); + printStep(1, totalSteps, 'Copy resources'); const copyResult = runSilent('npm run copy-monaco --silent'); if (copyResult.ok) { printSuccess('Monaco Editor resources ready'); @@ -137,7 +139,7 @@ async function main() { } // Step 2: Generate version info - printStep(2, 3, 'Generate version info'); + printStep(2, totalSteps, 'Generate version info'); const versionResult = runInherit('node scripts/generate-version.cjs'); if (!versionResult.ok) { printError('Generate version info failed'); @@ -152,8 +154,30 @@ async function main() { const prepTime = ((Date.now() - startTime) / 1000).toFixed(1); - // Step 3: Start dev server - printStep(3, 3, 'Start dev server'); + // Step 3: Build mobile-web (desktop only) + if (mode === 'desktop') { + printStep(3, 4, 'Build mobile-web'); + const mobileWebDir = path.join(ROOT_DIR, 'src/mobile-web'); + const mobileWebResult = runSilent('npm install --silent', mobileWebDir); + if (!mobileWebResult.ok) { + printError('mobile-web npm install failed'); + const output = tailOutput(mobileWebResult.stderr || mobileWebResult.stdout); + if (output) printError(output); + process.exit(1); + } + const buildResult = runInherit('npm run build', mobileWebDir); + if (!buildResult.ok) { + printError('mobile-web build failed'); + if (buildResult.error && buildResult.error.message) { + printError(buildResult.error.message); + } + process.exit(1); + } + printSuccess('mobile-web build complete'); + } + + // Final step: Start dev server + printStep(totalSteps, totalSteps, 'Start dev server'); printInfo(`Prep took ${prepTime}s`); printComplete('Initialization complete'); diff --git a/src/apps/cli/src/agent/core_adapter.rs b/src/apps/cli/src/agent/core_adapter.rs index 82e0d873..68ad0201 100644 --- a/src/apps/cli/src/agent/core_adapter.rs +++ b/src/apps/cli/src/agent/core_adapter.rs @@ -85,6 +85,7 @@ impl Agent for CoreAgentAdapter { message.clone(), None, self.agent_type.clone(), + false, ).await?; let mut accumulated_text = String::new(); diff --git a/src/apps/desktop/src/api/agentic_api.rs b/src/apps/desktop/src/api/agentic_api.rs index fefde152..10fa5c9d 100644 --- a/src/apps/desktop/src/api/agentic_api.rs +++ b/src/apps/desktop/src/api/agentic_api.rs @@ -152,6 +152,7 @@ pub async fn create_session( max_turns: c.max_turns.unwrap_or(200), enable_context_compression: c.enable_context_compression.unwrap_or(true), compression_threshold: c.compression_threshold.unwrap_or(0.8), + workspace_path: None, }) .unwrap_or_default(); @@ -184,6 +185,7 @@ pub async fn start_dialog_turn( request.user_input, request.turn_id, request.agent_type, + false, ) .await .map_err(|e| format!("Failed to start dialog turn: {}", e))?; diff --git a/src/apps/desktop/src/api/app_state.rs b/src/apps/desktop/src/api/app_state.rs index 860c5855..34b08ae7 100644 --- a/src/apps/desktop/src/api/app_state.rs +++ b/src/apps/desktop/src/api/app_state.rs @@ -61,6 +61,7 @@ impl AppState { }; let workspace_service = Arc::new(workspace::WorkspaceService::new().await?); + workspace::set_global_workspace_service(workspace_service.clone()); let filesystem_service = Arc::new(filesystem::FileSystemServiceFactory::create_default()); ai_rules::initialize_global_ai_rules_service() diff --git a/src/apps/desktop/src/api/conversation_api.rs b/src/apps/desktop/src/api/conversation_api.rs index 3cf99b25..d37eb829 100644 --- a/src/apps/desktop/src/api/conversation_api.rs +++ b/src/apps/desktop/src/api/conversation_api.rs @@ -59,14 +59,16 @@ pub async fn get_conversation_sessions( ) -> Result, String> { let workspace_path = PathBuf::from(&request.workspace_path); - let manager = ConversationPersistenceManager::new(path_manager.inner().clone(), workspace_path) + let manager = ConversationPersistenceManager::new(path_manager.inner().clone(), workspace_path.clone()) .await .map_err(|e| format!("Failed to create persistence manager: {}", e))?; - manager + let sessions = manager .get_session_list() .await - .map_err(|e| format!("Failed to get session list: {}", e)) + .map_err(|e| format!("Failed to get session list: {}", e))?; + + Ok(sessions) } #[tauri::command] diff --git a/src/apps/desktop/src/api/image_analysis_api.rs b/src/apps/desktop/src/api/image_analysis_api.rs index 4726b23f..09035c0b 100644 --- a/src/apps/desktop/src/api/image_analysis_api.rs +++ b/src/apps/desktop/src/api/image_analysis_api.rs @@ -111,6 +111,7 @@ pub async fn send_enhanced_message( enhanced_message.clone(), Some(request.dialog_turn_id.clone()), request.agent_type.clone(), + false, ) .await .map_err(|e| format!("Failed to send enhanced message: {}", e))?; diff --git a/src/apps/desktop/src/api/mod.rs b/src/apps/desktop/src/api/mod.rs index 14e384eb..5bfbf6b1 100644 --- a/src/apps/desktop/src/api/mod.rs +++ b/src/apps/desktop/src/api/mod.rs @@ -29,5 +29,6 @@ pub mod subagent_api; pub mod system_api; pub mod terminal_api; pub mod tool_api; +pub mod remote_connect_api; pub use app_state::{AppState, AppStatistics, HealthStatus}; diff --git a/src/apps/desktop/src/api/remote_connect_api.rs b/src/apps/desktop/src/api/remote_connect_api.rs new file mode 100644 index 00000000..2486875a --- /dev/null +++ b/src/apps/desktop/src/api/remote_connect_api.rs @@ -0,0 +1,427 @@ +//! Tauri commands for Remote Connect. + +use bitfun_core::service::remote_connect::{ + bot::BotConfig, ConnectionMethod, ConnectionResult, PairingState, RemoteConnectConfig, + RemoteConnectService, +}; +use once_cell::sync::OnceCell; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; +use std::sync::Arc; +use tokio::sync::RwLock; + +static REMOTE_CONNECT_SERVICE: OnceCell>>> = + OnceCell::new(); + +/// Tauri resource directory path for mobile-web, set during app setup. +static MOBILE_WEB_RESOURCE_PATH: OnceCell = OnceCell::new(); + +fn get_service_holder() -> &'static Arc>> { + REMOTE_CONNECT_SERVICE.get_or_init(|| Arc::new(RwLock::new(None))) +} + +/// Called from Tauri setup to register the resolved resource directory path +/// for the bundled mobile-web files. +pub fn set_mobile_web_resource_path(path: PathBuf) { + log::info!("Registered mobile-web resource path: {}", path.display()); + let _ = MOBILE_WEB_RESOURCE_PATH.set(path); +} + +/// Called from Tauri setup to eagerly initialize the remote connect service +/// and restore any previously paired bot connections. Without this, bots +/// only start listening after the user first opens the Remote Connect dialog. +pub fn init_on_startup() { + tokio::spawn(async { + if let Err(e) = ensure_service().await { + log::warn!("Remote connect startup init failed: {e}"); + } + }); +} + +/// Synchronous cleanup called when the application exits. +pub fn cleanup_on_exit() { + bitfun_core::service::remote_connect::ngrok::cleanup_all_ngrok(); + log::info!("Remote connect cleanup completed on exit"); +} + +async fn ensure_service() -> Result<(), String> { + let holder = get_service_holder(); + let guard = holder.read().await; + if guard.is_some() { + return Ok(()); + } + drop(guard); + + let mut config = RemoteConnectConfig::default(); + config.mobile_web_dir = detect_mobile_web_dir(); + let service = + RemoteConnectService::new(config).map_err(|e| format!("init remote connect: {e}"))?; + *holder.write().await = Some(service); + + // Auto-restore previously paired bots + restore_saved_bots().await; + + Ok(()) +} + +/// Restore any bot connections that were previously saved to disk. +async fn restore_saved_bots() { + use bitfun_core::service::remote_connect::bot; + + let data = bot::load_bot_persistence(); + if data.connections.is_empty() { + return; + } + + let holder = get_service_holder(); + let guard = holder.read().await; + let Some(service) = guard.as_ref() else { return }; + + for conn in &data.connections { + if !conn.chat_state.paired { + continue; + } + log::info!( + "Restoring {} bot connection for chat_id={}", + conn.bot_type, + conn.chat_id + ); + let result = service.restore_bot(conn).await; + if let Err(e) = result { + log::warn!("Failed to restore {} bot: {e}", conn.bot_type); + } + } +} + +/// Auto-detect the mobile-web build output directory. +fn detect_mobile_web_dir() -> Option { + if let Ok(dir) = std::env::var("BITFUN_MOBILE_WEB_DIR") { + let p = std::path::Path::new(&dir); + if p.join("index.html").exists() { + log::info!("Using BITFUN_MOBILE_WEB_DIR: {dir}"); + return Some(dir); + } + log::warn!("BITFUN_MOBILE_WEB_DIR set but index.html not found: {dir}"); + } + + if let Some(resource_path) = MOBILE_WEB_RESOURCE_PATH.get() { + if is_valid_mobile_web_dir(resource_path) { + let dir = resource_path.to_string_lossy().into_owned(); + log::info!("Using Tauri bundled mobile-web: {dir}"); + return Some(dir); + } + log::debug!( + "Tauri resource path registered but not a valid mobile-web dir: {}", + resource_path.display() + ); + } + + if let Some(dir) = detect_from_exe() { + return Some(dir); + } + + if let Some(dir) = detect_from_cwd() { + return Some(dir); + } + + log::warn!("mobile-web dist directory not found; LAN/Ngrok modes will not serve static files"); + None +} + +fn detect_from_exe() -> Option { + let exe = std::env::current_exe().ok()?; + let exe_dir = exe.parent()?; + + let mut candidates: Vec = Vec::new(); + + if cfg!(target_os = "macos") { + // Primary: tauri.conf.json maps dist -> mobile-web/dist in Resources + candidates.push(exe_dir.join("../Resources/mobile-web/dist")); + // Fallback: legacy layout without dist subdirectory + candidates.push(exe_dir.join("../Resources/mobile-web")); + // Fallback: array-format bundling may place files at Resources/dist directly + candidates.push(exe_dir.join("../Resources/dist")); + } + candidates.push(exe_dir.join("mobile-web/dist")); + candidates.push(exe_dir.join("mobile-web")); + candidates.push(exe_dir.join("resources/mobile-web/dist")); + candidates.push(exe_dir.join("resources/mobile-web")); + + if cfg!(target_os = "linux") { + candidates.push(exe_dir.join("../lib/bitfun/mobile-web/dist")); + candidates.push(exe_dir.join("../lib/bitfun/mobile-web")); + candidates.push(exe_dir.join("../share/bitfun/mobile-web/dist")); + candidates.push(exe_dir.join("../share/bitfun/mobile-web")); + candidates.push(exe_dir.join("../share/com.bitfun.desktop/mobile-web/dist")); + candidates.push(exe_dir.join("../share/com.bitfun.desktop/mobile-web")); + } + + check_candidates(&candidates, "exe-relative") +} + +fn detect_from_cwd() -> Option { + let cwd = std::env::current_dir().ok()?; + let candidates = [ + cwd.join("src/mobile-web/dist"), + cwd.join("../../mobile-web/dist"), + cwd.join("../mobile-web/dist"), + ]; + + check_candidates(&candidates, "cwd-relative") +} + +fn check_candidates(candidates: &[PathBuf], source: &str) -> Option { + for candidate in candidates { + if is_valid_mobile_web_dir(candidate) { + if let Ok(abs) = candidate.canonicalize() { + log::info!("Detected mobile-web dir ({}): {}", source, abs.display()); + return Some(abs.to_string_lossy().into_owned()); + } + } + } + None +} + +fn is_valid_mobile_web_dir(dir: &std::path::Path) -> bool { + dir.join("index.html").exists() && dir.join("assets").is_dir() +} + +// ── Request / Response DTOs ──────────────────────────────────────── + +#[derive(Debug, Deserialize)] +pub struct StartRemoteConnectRequest { + pub method: String, + pub custom_server_url: Option, +} + +#[derive(Debug, Serialize)] +pub struct RemoteConnectStatusResponse { + pub is_connected: bool, + pub pairing_state: PairingState, + pub active_method: Option, + pub peer_device_name: Option, + /// Independent bot connection info — e.g. "Telegram(7096812005)". + /// Present when a bot is active, regardless of relay pairing state. + pub bot_connected: Option, +} + +#[derive(Debug, Serialize)] +pub struct ConnectionMethodInfo { + pub id: String, + pub name: String, + pub available: bool, + pub description: String, +} + +#[derive(Debug, Serialize)] +pub struct DeviceInfo { + pub device_id: String, + pub device_name: String, + pub mac_address: String, +} + +// ── Tauri Commands ───────────────────────────────────────────────── + +#[tauri::command] +pub async fn remote_connect_get_device_info() -> Result { + ensure_service().await?; + let holder = get_service_holder(); + let guard = holder.read().await; + let service = guard.as_ref().ok_or("service not initialized")?; + let id = service.device_identity(); + Ok(DeviceInfo { + device_id: id.device_id.clone(), + device_name: id.device_name.clone(), + mac_address: id.mac_address.clone(), + }) +} + +#[tauri::command] +pub async fn remote_connect_get_methods() -> Result, String> { + ensure_service().await?; + let holder = get_service_holder(); + let guard = holder.read().await; + let service = guard.as_ref().ok_or("service not initialized")?; + let methods = service.available_methods().await; + + let infos = methods + .into_iter() + .map(|m| match m { + ConnectionMethod::Lan => ConnectionMethodInfo { + id: "lan".into(), + name: "LAN".into(), + available: true, + description: "Same local network".into(), + }, + ConnectionMethod::Ngrok => ConnectionMethodInfo { + id: "ngrok".into(), + name: "ngrok".into(), + available: true, + description: "Internet via ngrok tunnel".into(), + }, + ConnectionMethod::BitfunServer => ConnectionMethodInfo { + id: "bitfun_server".into(), + name: "BitFun Server".into(), + available: true, + description: "Official BitFun relay".into(), + }, + ConnectionMethod::CustomServer { url } => ConnectionMethodInfo { + id: "custom_server".into(), + name: "Custom Server".into(), + available: true, + description: format!("Self-hosted: {url}"), + }, + ConnectionMethod::BotFeishu => ConnectionMethodInfo { + id: "bot_feishu".into(), + name: "Feishu Bot".into(), + available: true, + description: "Via Feishu messenger".into(), + }, + ConnectionMethod::BotTelegram => ConnectionMethodInfo { + id: "bot_telegram".into(), + name: "Telegram Bot".into(), + available: true, + description: "Via Telegram".into(), + }, + }) + .collect(); + + Ok(infos) +} + +fn parse_connection_method( + method: &str, + custom_url: Option, +) -> Result { + match method { + "lan" => Ok(ConnectionMethod::Lan), + "ngrok" => Ok(ConnectionMethod::Ngrok), + "bitfun_server" => Ok(ConnectionMethod::BitfunServer), + "custom_server" => Ok(ConnectionMethod::CustomServer { + url: custom_url.unwrap_or_default(), + }), + "bot_feishu" => Ok(ConnectionMethod::BotFeishu), + "bot_telegram" => Ok(ConnectionMethod::BotTelegram), + _ => Err(format!("unknown connection method: {method}")), + } +} + +#[tauri::command] +pub async fn remote_connect_start( + request: StartRemoteConnectRequest, +) -> Result { + ensure_service().await?; + let method = parse_connection_method(&request.method, request.custom_server_url)?; + + let holder = get_service_holder(); + let guard = holder.read().await; + let service = guard.as_ref().ok_or("service not initialized")?; + service + .start(method) + .await + .map_err(|e| format!("start remote connect: {e}")) +} + +#[tauri::command] +pub async fn remote_connect_stop() -> Result<(), String> { + let holder = get_service_holder(); + let guard = holder.read().await; + if let Some(service) = guard.as_ref() { + service.stop_relay().await; + } + Ok(()) +} + +#[tauri::command] +pub async fn remote_connect_stop_bot() -> Result<(), String> { + let holder = get_service_holder(); + let guard = holder.read().await; + if let Some(service) = guard.as_ref() { + service.stop_bots().await; + } + // Remove persistence so the bot is not auto-restored + use bitfun_core::service::remote_connect::bot; + let mut data = bot::load_bot_persistence(); + data.connections.clear(); + bot::save_bot_persistence(&data); + Ok(()) +} + +#[tauri::command] +pub async fn remote_connect_status() -> Result { + ensure_service().await?; + let holder = get_service_holder(); + let guard = holder.read().await; + let service = guard.as_ref().ok_or("service not initialized")?; + + let state = service.pairing_state().await; + let method = service.active_method().await; + let peer = service.peer_device_name().await; + let bot_connected = service.bot_connected_info().await; + + Ok(RemoteConnectStatusResponse { + is_connected: state == PairingState::Connected, + pairing_state: state, + active_method: method.map(|m| format!("{m:?}")), + peer_device_name: peer, + bot_connected, + }) +} + +#[tauri::command] +pub async fn remote_connect_configure_custom_server(url: String) -> Result<(), String> { + let holder = get_service_holder(); + let mut guard = holder.write().await; + if guard.is_none() { + let mut config = RemoteConnectConfig::default(); + config.custom_server_url = Some(url); + let service = + RemoteConnectService::new(config).map_err(|e| format!("init: {e}"))?; + *guard = Some(service); + } + Ok(()) +} + +#[derive(Debug, Deserialize)] +pub struct ConfigureBotRequest { + pub bot_type: String, + pub app_id: Option, + pub app_secret: Option, + pub bot_token: Option, +} + +#[tauri::command] +pub async fn remote_connect_configure_bot( + request: ConfigureBotRequest, +) -> Result<(), String> { + let holder = get_service_holder(); + let mut guard = holder.write().await; + + let bot_config = match request.bot_type.as_str() { + "feishu" => BotConfig::Feishu { + app_id: request.app_id.unwrap_or_default(), + app_secret: request.app_secret.unwrap_or_default(), + }, + "telegram" => BotConfig::Telegram { + bot_token: request.bot_token.unwrap_or_default(), + }, + _ => return Err(format!("unknown bot type: {}", request.bot_type)), + }; + + if guard.is_none() { + let mut config = RemoteConnectConfig::default(); + config.mobile_web_dir = detect_mobile_web_dir(); + match &bot_config { + BotConfig::Feishu { .. } => config.bot_feishu = Some(bot_config), + BotConfig::Telegram { .. } => config.bot_telegram = Some(bot_config), + } + let service = + RemoteConnectService::new(config).map_err(|e| format!("init: {e}"))?; + *guard = Some(service); + } else if let Some(service) = guard.as_mut() { + service.update_bot_config(bot_config); + } + + Ok(()) +} + diff --git a/src/apps/desktop/src/lib.rs b/src/apps/desktop/src/lib.rs index 6c714a07..4e0af015 100644 --- a/src/apps/desktop/src/lib.rs +++ b/src/apps/desktop/src/lib.rs @@ -155,6 +155,42 @@ pub async fn run() { .setup(move |app| { logging::register_runtime_log_state(startup_log_level, session_log_dir.clone()); + // Register bundled mobile-web resource path for remote connect. + // tauri.conf.json maps "../../mobile-web/dist" -> "mobile-web/dist", + // so the primary candidate is "mobile-web/dist". Additional fallbacks + // handle legacy or non-standard bundle layouts. + { + let candidates = [ + "mobile-web/dist", + "mobile-web", + "dist", + ]; + let mut found = false; + for candidate in &candidates { + if let Ok(p) = app.path().resolve(candidate, tauri::path::BaseDirectory::Resource) { + if p.join("index.html").exists() { + log::info!("Found bundled mobile-web at: {}", p.display()); + api::remote_connect_api::set_mobile_web_resource_path(p); + found = true; + break; + } + } + } + if !found { + // Last resort: scan the resource root for any index.html + if let Ok(res_dir) = app.path().resource_dir() { + for sub in &["mobile-web/dist", "mobile-web", "dist", ""] { + let p = if sub.is_empty() { res_dir.clone() } else { res_dir.join(sub) }; + if p.join("index.html").exists() { + log::info!("Found mobile-web via resource root scan: {}", p.display()); + api::remote_connect_api::set_mobile_web_resource_path(p); + break; + } + } + } + } + } + let app_handle = app.handle().clone(); theme::create_main_window(&app_handle); @@ -190,6 +226,10 @@ pub async fn run() { start_event_loop_with_transport(event_queue, event_router, transport); + // Eagerly initialize the remote connect service so previously + // paired bots start listening immediately on app startup. + api::remote_connect_api::init_on_startup(); + { let _terminal_state: tauri::State<'_, api::terminal_api::TerminalState> = app.state(); @@ -224,6 +264,7 @@ pub async fn run() { { log::info!("Main window close requested, cleaning up"); bitfun_core::util::process_manager::cleanup_all_processes(); + api::remote_connect_api::cleanup_on_exit(); window.app_handle().exit(0); } else { @@ -514,6 +555,15 @@ pub async fn run() { i18n_get_supported_languages, i18n_get_config, i18n_set_config, + // Remote Connect + api::remote_connect_api::remote_connect_get_device_info, + api::remote_connect_api::remote_connect_get_methods, + api::remote_connect_api::remote_connect_start, + api::remote_connect_api::remote_connect_stop, + api::remote_connect_api::remote_connect_stop_bot, + api::remote_connect_api::remote_connect_status, + api::remote_connect_api::remote_connect_configure_custom_server, + api::remote_connect_api::remote_connect_configure_bot, ]) .run(tauri::generate_context!()); if let Err(e) = run_result { diff --git a/src/apps/desktop/tauri.conf.json b/src/apps/desktop/tauri.conf.json index c5cd59db..9eeb926f 100644 --- a/src/apps/desktop/tauri.conf.json +++ b/src/apps/desktop/tauri.conf.json @@ -5,7 +5,7 @@ "build": { "beforeDevCommand": "npm run dev:web", "devUrl": "http://localhost:1422", - "beforeBuildCommand": "npm run build:web", + "beforeBuildCommand": "npm run build:web && npm run build:mobile-web", "frontendDist": "../../../dist" }, "bundle": { @@ -14,7 +14,10 @@ "icon": [ "icons/icon.icns", "icons/icon.ico" - ] + ], + "resources": { + "../../mobile-web/dist": "mobile-web/dist" + } }, "app": { "windows": [], diff --git a/src/apps/relay-server/Caddyfile b/src/apps/relay-server/Caddyfile new file mode 100644 index 00000000..7fb8134a --- /dev/null +++ b/src/apps/relay-server/Caddyfile @@ -0,0 +1,24 @@ +# Caddyfile for BitFun Relay Server +# Replace YOUR_DOMAIN with your actual domain, or use :443 with self-signed cert. +# +# Option A: With a domain (Let's Encrypt auto-HTTPS) +# relay.yourdomain.com { +# reverse_proxy relay-server:9700 +# } +# +# Option A2: With a /relay path prefix +# relay.yourdomain.com { +# handle_path /relay/* { +# reverse_proxy relay-server:9700 +# } +# } +# +# Option B: IP-only with self-signed cert +:443 { + tls internal + reverse_proxy relay-server:9700 +} + +:80 { + reverse_proxy relay-server:9700 +} diff --git a/src/apps/relay-server/Cargo.toml b/src/apps/relay-server/Cargo.toml new file mode 100644 index 00000000..40d4b262 --- /dev/null +++ b/src/apps/relay-server/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "bitfun-relay-server" +version.workspace = true +authors.workspace = true +edition.workspace = true +description = "BitFun Relay Server - WebSocket relay for Remote Connect" + +[[bin]] +name = "bitfun-relay-server" +path = "src/main.rs" + +[dependencies] +# Web framework +axum = { workspace = true } +tower-http = { workspace = true, features = ["cors", "fs"] } + +# Async runtime +tokio = { workspace = true, features = ["full"] } +futures-util = { workspace = true } + +# Serialization +serde = { workspace = true } +serde_json = { workspace = true } + +# Error handling +anyhow = { workspace = true } + +# Logging +tracing = { workspace = true } +tracing-subscriber = { workspace = true } + +# Utilities +uuid = { workspace = true } +chrono = { workspace = true } +dashmap = { workspace = true } +rand = { workspace = true } +base64 = { workspace = true } +sha2 = { workspace = true } diff --git a/src/apps/relay-server/Dockerfile b/src/apps/relay-server/Dockerfile new file mode 100644 index 00000000..c91ac4cc --- /dev/null +++ b/src/apps/relay-server/Dockerfile @@ -0,0 +1,54 @@ +# Multi-stage build for BitFun Relay Server +FROM rust:1.82-slim AS builder + +WORKDIR /build + +# Install build dependencies +RUN apt-get update && apt-get install -y pkg-config libssl-dev && rm -rf /var/lib/apt/lists/* + +# Copy workspace files +COPY Cargo.toml Cargo.lock ./ +COPY src/crates/events/Cargo.toml src/crates/events/Cargo.toml +COPY src/crates/core/Cargo.toml src/crates/core/Cargo.toml +COPY src/crates/transport/Cargo.toml src/crates/transport/Cargo.toml +COPY src/crates/api-layer/Cargo.toml src/crates/api-layer/Cargo.toml +COPY src/apps/cli/Cargo.toml src/apps/cli/Cargo.toml +COPY src/apps/desktop/Cargo.toml src/apps/desktop/Cargo.toml +COPY src/apps/server/Cargo.toml src/apps/server/Cargo.toml +COPY src/apps/relay-server/Cargo.toml src/apps/relay-server/Cargo.toml + +# Create dummy source files for dependency caching +RUN mkdir -p src/crates/events/src && echo "pub fn dummy() {}" > src/crates/events/src/lib.rs && \ + mkdir -p src/crates/core/src && echo "pub fn dummy() {}" > src/crates/core/src/lib.rs && \ + mkdir -p src/crates/transport/src && echo "pub fn dummy() {}" > src/crates/transport/src/lib.rs && \ + mkdir -p src/crates/api-layer/src && echo "pub fn dummy() {}" > src/crates/api-layer/src/lib.rs && \ + mkdir -p src/apps/cli/src && echo "fn main() {}" > src/apps/cli/src/main.rs && \ + mkdir -p src/apps/desktop/src && echo "fn main() {}" > src/apps/desktop/src/main.rs && \ + mkdir -p src/apps/server/src && echo "fn main() {}" > src/apps/server/src/main.rs && \ + mkdir -p src/apps/relay-server/src && echo "fn main() {}" > src/apps/relay-server/src/main.rs + +# Build dependencies only (cached layer) +RUN cargo build --release -p bitfun-relay-server 2>/dev/null || true + +# Copy actual source code +COPY src/apps/relay-server/src src/apps/relay-server/src + +# Build the relay server +RUN cargo build --release -p bitfun-relay-server + +# ── Runtime stage ───────────────────────────────────────── +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* + +WORKDIR /app +COPY --from=builder /build/target/release/bitfun-relay-server /app/bitfun-relay-server + +# Optional: copy mobile-web static files +# COPY src/mobile-web/dist /app/static + +ENV RELAY_PORT=9700 +ENV RELAY_STATIC_DIR=/app/static +EXPOSE 9700 + +CMD ["/app/bitfun-relay-server"] diff --git a/src/apps/relay-server/README.md b/src/apps/relay-server/README.md new file mode 100644 index 00000000..541b9ba0 --- /dev/null +++ b/src/apps/relay-server/README.md @@ -0,0 +1,130 @@ +# BitFun Relay Server + +WebSocket relay server for BitFun Remote Connect. Provides room-based message relaying between desktop and mobile clients with E2E encryption support. + +## Features + +- Room-based WebSocket relay +- End-to-end encrypted message passthrough (server cannot decrypt) +- Heartbeat-based connection management +- Static file serving for mobile web client +- Docker deployment ready + +## Quick Start + +### Docker (Recommended) + +```bash +# One-click deploy +bash deploy.sh + +# With mobile web client +bash deploy.sh --build-mobile +``` + +### What URL should I fill in BitFun Desktop? + +In **Remote Connect → Self-Hosted → Server URL**, use one of: + +- Direct relay port: `http://:9700` +- Reverse proxy on domain root: `https://relay.example.com` +- Reverse proxy with `/relay` prefix: `https://relay.example.com/relay` + +`/relay` is **not mandatory**. It is only needed when your reverse proxy is configured with that path prefix. + +### Manual + +```bash +# From project root +cargo build --release -p bitfun-relay-server + +# Run +RELAY_PORT=9700 ./target/release/bitfun-relay-server +``` + +## Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `RELAY_PORT` | `9700` | Server listen port | +| `RELAY_STATIC_DIR` | `./static` | Path to mobile web static files | +| `RELAY_ROOM_TTL` | `3600` | Room TTL in seconds (0 = no expiry) | + +## API Endpoints + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/health` | GET | Health check | +| `/api/info` | GET | Server info | +| `/ws` | WebSocket | Main relay endpoint | + +## WebSocket Protocol + +### Client → Server + +```json +// Create a room (desktop) +{ "type": "create_room", "room_id": "...", "device_id": "...", "device_type": "desktop", "public_key": "base64..." } + +// Join a room (mobile) +{ "type": "join_room", "room_id": "...", "device_id": "...", "device_type": "mobile", "public_key": "base64..." } + +// Relay an encrypted message +{ "type": "relay", "room_id": "...", "encrypted_data": "base64...", "nonce": "base64..." } + +// Heartbeat +{ "type": "heartbeat" } +``` + +### Server → Client + +```json +// Peer joined notification +{ "type": "peer_joined", "device_id": "...", "device_type": "...", "public_key": "base64..." } + +// Relayed message +{ "type": "relay", "from_device_id": "...", "encrypted_data": "base64...", "nonce": "base64..." } + +// Peer disconnected +{ "type": "peer_disconnected", "device_id": "..." } + +// Heartbeat acknowledgment +{ "type": "heartbeat_ack" } +``` + +## Self-Hosted Deployment + +1. Clone the repository +2. Navigate to `src/apps/relay-server/` +3. Run `bash deploy.sh --build-mobile` +4. Configure DNS/firewall as needed +5. In BitFun desktop, select "Custom Server" and enter your server URL + +### Deployment Checklist (Recommended) + +1. Open required ports: + - `9700` (relay direct access, optional if only via reverse proxy) + - `80/443` (for Caddy reverse proxy) +2. Verify health endpoint: + - `http://:9700/health` +3. Configure your final URL strategy: + - root domain (`https://relay.example.com`) or + - path prefix (`https://relay.example.com/relay`) +4. Fill the same URL into BitFun Desktop "Custom Server". + +### About `src/apps/server` vs `src/apps/relay-server` + +- Remote Connect self-hosted deployment uses **`src/apps/relay-server`**. +- `src/apps/server` is a different application and not the relay service used by mobile/desktop Remote Connect. + +## Architecture + +``` +Mobile Phone ──WSS──► Relay Server ◄──WSS── Desktop Client + │ + E2E Encrypted + (server cannot + read messages) +``` + +The relay server only manages rooms and forwards opaque encrypted payloads. All encryption/decryption happens on the client side. diff --git a/src/apps/relay-server/deploy.sh b/src/apps/relay-server/deploy.sh new file mode 100755 index 00000000..61c806c1 --- /dev/null +++ b/src/apps/relay-server/deploy.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# BitFun Relay Server — one-click deploy script. +# Usage: bash deploy.sh [--build-mobile] [--skip-build] [--skip-health-check] +# +# Prerequisites: Docker, Docker Compose + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" + +BUILD_MOBILE=false +SKIP_BUILD=false +SKIP_HEALTH_CHECK=false + +usage() { + cat <<'EOF' +BitFun Relay Server deploy script + +Usage: + bash deploy.sh [options] + +Options: + --build-mobile Build mobile-web static files before deploy + --skip-build Skip docker compose build, only restart services + --skip-health-check Skip post-deploy health check + -h, --help Show this help message +EOF +} + +check_command() { + local cmd="$1" + if ! command -v "$cmd" >/dev/null 2>&1; then + echo "Error: '$cmd' is required but not installed." + exit 1 + fi +} + +check_docker_compose() { + if docker compose version >/dev/null 2>&1; then + return 0 + fi + echo "Error: Docker Compose (docker compose) is required." + exit 1 +} + +for arg in "$@"; do + case "$arg" in + --build-mobile) BUILD_MOBILE=true ;; + --skip-build) SKIP_BUILD=true ;; + --skip-health-check) SKIP_HEALTH_CHECK=true ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown option: $arg" + usage + exit 1 + ;; + esac +done + +echo "=== BitFun Relay Server Deploy ===" +check_command docker +check_docker_compose + +# Build mobile web static files if requested +if [ "$BUILD_MOBILE" = true ] && [ -d "$PROJECT_ROOT/src/mobile-web" ]; then + check_command npm + echo "[1/3] Building mobile web client..." + cd "$PROJECT_ROOT/src/mobile-web" + npm ci + npm run build + mkdir -p "$SCRIPT_DIR/static" + cp -r dist/* "$SCRIPT_DIR/static/" + cd "$SCRIPT_DIR" + echo " Mobile web built → $SCRIPT_DIR/static/" +else + echo "[1/3] Skipping mobile web build (use --build-mobile to include)" +fi + +# Build and start containers +cd "$SCRIPT_DIR" +if [ "$SKIP_BUILD" = true ]; then + echo "[2/3] Skipping Docker build (--skip-build)" +else + echo "[2/3] Building Docker images..." + docker compose build +fi + +echo "[3/3] Starting services..." +docker compose up -d + +if [ "$SKIP_HEALTH_CHECK" = false ]; then + echo "Checking relay health endpoint..." + if command -v curl >/dev/null 2>&1; then + if curl -fsS --max-time 8 "http://127.0.0.1:9700/health" >/dev/null; then + echo "Health check passed: http://127.0.0.1:9700/health" + else + echo "Warning: health check failed. Check logs below." + fi + else + echo "Warning: 'curl' not found, skipped health check." + fi +fi + +echo "" +echo "=== Deploy complete ===" +echo "Relay server running on port 9700" +echo "Caddy proxy on ports 80/443" +echo "" +echo "Custom Server URL examples for BitFun Desktop:" +echo " - Direct relay: http://:9700" +echo " - Reverse proxy root: https://" +echo " - Reverse proxy /relay:https:///relay (if you configured path prefix)" +echo "" +echo "Check status: docker compose ps" +echo "View logs: docker compose logs -f relay-server" +echo "Stop: docker compose down" diff --git a/src/apps/relay-server/deploy/Cargo.toml b/src/apps/relay-server/deploy/Cargo.toml new file mode 100644 index 00000000..b5212ad6 --- /dev/null +++ b/src/apps/relay-server/deploy/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "bitfun-relay-server" +version = "0.1.1" +authors = ["BitFun Team"] +edition = "2021" +description = "BitFun Relay Server - WebSocket relay for Remote Connect" + +[[bin]] +name = "bitfun-relay-server" +path = "src/main.rs" + +[dependencies] +axum = { version = "0.7", features = ["json", "ws"] } +tower-http = { version = "0.6", features = ["cors", "fs"] } +tokio = { version = "1.0", features = ["full"] } +futures-util = "0.3" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +anyhow = "1.0" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +uuid = { version = "1.0", features = ["v4", "serde"] } +chrono = { version = "0.4", features = ["serde", "clock"] } +dashmap = "5.5" +rand = "0.8" +base64 = "0.21" +sha2 = "0.10" + +[profile.release] +opt-level = 3 +lto = true +codegen-units = 1 +strip = true diff --git a/src/apps/relay-server/deploy/Dockerfile b/src/apps/relay-server/deploy/Dockerfile new file mode 100644 index 00000000..b8d743c7 --- /dev/null +++ b/src/apps/relay-server/deploy/Dockerfile @@ -0,0 +1,29 @@ +FROM rust:1.85-slim AS builder + +WORKDIR /build + +RUN apt-get update && apt-get install -y pkg-config libssl-dev && rm -rf /var/lib/apt/lists/* + +COPY Cargo.toml ./ +RUN mkdir -p src && echo 'fn main() { println!("placeholder"); }' > src/main.rs +RUN cargo build --release 2>/dev/null || true + +RUN rm -rf src target/release/bitfun-relay-server target/release/deps/bitfun* + +COPY src/ src/ + +RUN cargo build --release + +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* + +WORKDIR /app +COPY --from=builder /build/target/release/bitfun-relay-server /app/bitfun-relay-server +RUN mkdir -p /app/static + +ENV RELAY_PORT=9700 +ENV RELAY_STATIC_DIR=/app/static +EXPOSE 9700 + +CMD ["/app/bitfun-relay-server"] diff --git a/src/apps/relay-server/deploy/docker-compose.yml b/src/apps/relay-server/deploy/docker-compose.yml new file mode 100644 index 00000000..6ce5a4cf --- /dev/null +++ b/src/apps/relay-server/deploy/docker-compose.yml @@ -0,0 +1,20 @@ +services: + relay-server: + build: + context: . + dockerfile: Dockerfile + container_name: bitfun-relay + restart: unless-stopped + ports: + - "9700:9700" + environment: + - RELAY_PORT=9700 + - RELAY_STATIC_DIR=/app/static + - RELAY_ROOM_WEB_DIR=/app/room-web + - RELAY_ROOM_TTL=3600 + volumes: + - ./static:/app/static:ro + - room-web:/app/room-web + +volumes: + room-web: diff --git a/src/apps/relay-server/deploy/src/config.rs b/src/apps/relay-server/deploy/src/config.rs new file mode 100644 index 00000000..626d1009 --- /dev/null +++ b/src/apps/relay-server/deploy/src/config.rs @@ -0,0 +1,53 @@ +//! Relay server configuration. + +use std::net::SocketAddr; + +#[derive(Debug, Clone)] +#[allow(dead_code)] +pub struct RelayConfig { + pub listen_addr: SocketAddr, + pub room_ttl_secs: u64, + pub heartbeat_interval_secs: u64, + pub heartbeat_timeout_secs: u64, + pub static_dir: Option, + /// Directory where per-room uploaded mobile-web files are stored. + pub room_web_dir: String, + pub cors_allow_origins: Vec, +} + +impl Default for RelayConfig { + fn default() -> Self { + Self { + listen_addr: ([0, 0, 0, 0], 9700).into(), + room_ttl_secs: 3600, + heartbeat_interval_secs: 30, + heartbeat_timeout_secs: 90, + static_dir: None, + room_web_dir: "/tmp/bitfun-room-web".to_string(), + cors_allow_origins: vec!["*".to_string()], + } + } +} + +impl RelayConfig { + pub fn from_env() -> Self { + let mut cfg = Self::default(); + if let Ok(port) = std::env::var("RELAY_PORT") { + if let Ok(p) = port.parse::() { + cfg.listen_addr = ([0, 0, 0, 0], p).into(); + } + } + if let Ok(dir) = std::env::var("RELAY_STATIC_DIR") { + cfg.static_dir = Some(dir); + } + if let Ok(dir) = std::env::var("RELAY_ROOM_WEB_DIR") { + cfg.room_web_dir = dir; + } + if let Ok(ttl) = std::env::var("RELAY_ROOM_TTL") { + if let Ok(t) = ttl.parse() { + cfg.room_ttl_secs = t; + } + } + cfg + } +} diff --git a/src/apps/relay-server/deploy/src/main.rs b/src/apps/relay-server/deploy/src/main.rs new file mode 100644 index 00000000..a7f80237 --- /dev/null +++ b/src/apps/relay-server/deploy/src/main.rs @@ -0,0 +1,98 @@ +//! BitFun Relay Server +//! +//! WebSocket relay for Remote Connect. Manages rooms and forwards E2E encrypted +//! messages between desktop and mobile clients. Also serves mobile web static files. + +use axum::extract::DefaultBodyLimit; +use axum::routing::{get, post}; +use axum::Router; +use tower_http::cors::CorsLayer; +use tracing::info; + +mod config; +mod relay; +mod routes; + +use config::RelayConfig; +use relay::RoomManager; +use routes::api::{self, AppState}; +use routes::websocket; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt() + .with_max_level(tracing::Level::DEBUG) + .init(); + + let cfg = RelayConfig::from_env(); + info!("BitFun Relay Server v{}", env!("CARGO_PKG_VERSION")); + + let room_manager = RoomManager::new(); + + let cleanup_rm = room_manager.clone(); + let cleanup_ttl = cfg.room_ttl_secs; + let cleanup_room_web_dir = cfg.room_web_dir.clone(); + tokio::spawn(async move { + loop { + tokio::time::sleep(std::time::Duration::from_secs(60)).await; + let stale_ids = cleanup_rm.cleanup_stale_rooms(cleanup_ttl); + for room_id in &stale_ids { + api::cleanup_room_web(&cleanup_room_web_dir, room_id); + } + } + }); + + let store_dir = std::path::PathBuf::from(&cfg.room_web_dir).join("_store"); + let _ = std::fs::create_dir_all(&store_dir); + let content_store = std::sync::Arc::new(api::ContentStore::new(&store_dir)); + + let state = AppState { + room_manager, + start_time: std::time::Instant::now(), + room_web_dir: cfg.room_web_dir.clone(), + content_store, + }; + + let mut app = Router::new() + .route("/health", get(api::health_check)) + .route("/api/info", get(api::server_info)) + .route("/api/rooms/:room_id/join", post(api::join_room)) + .route("/api/rooms/:room_id/message", post(api::relay_message)) + .route("/api/rooms/:room_id/poll", get(api::poll_messages)) + .route("/api/rooms/:room_id/ack", post(api::ack_messages)) + .route( + "/api/rooms/:room_id/upload-web", + post(api::upload_web).layer(DefaultBodyLimit::max(10 * 1024 * 1024)), + ) + .route( + "/api/rooms/:room_id/check-web-files", + post(api::check_web_files), + ) + .route( + "/api/rooms/:room_id/upload-web-files", + post(api::upload_web_files).layer(DefaultBodyLimit::max(10 * 1024 * 1024)), + ) + .route("/r/*rest", get(api::serve_room_web_catchall)) + .route("/ws", get(websocket::websocket_handler)) + .layer(CorsLayer::permissive()) + .with_state(state); + + // Serve mobile web static files as a fallback for requests that + // don't match any API or WebSocket route. + if let Some(static_dir) = &cfg.static_dir { + info!("Serving static files from: {static_dir}"); + app = app.fallback_service( + tower_http::services::ServeDir::new(static_dir) + .append_index_html_on_directories(true), + ); + } + + info!("Room web upload dir: {}", cfg.room_web_dir); + + let listener = tokio::net::TcpListener::bind(cfg.listen_addr).await?; + info!("Relay server listening on {}", cfg.listen_addr); + info!("WebSocket endpoint: ws://{}/ws", cfg.listen_addr); + + axum::serve(listener, app).await?; + Ok(()) +} diff --git a/src/apps/relay-server/deploy/src/relay/mod.rs b/src/apps/relay-server/deploy/src/relay/mod.rs new file mode 100644 index 00000000..c24d4265 --- /dev/null +++ b/src/apps/relay-server/deploy/src/relay/mod.rs @@ -0,0 +1,5 @@ +//! Core relay logic: room management and message routing. + +pub mod room; + +pub use room::RoomManager; diff --git a/src/apps/relay-server/deploy/src/relay/room.rs b/src/apps/relay-server/deploy/src/relay/room.rs new file mode 100644 index 00000000..8b336d85 --- /dev/null +++ b/src/apps/relay-server/deploy/src/relay/room.rs @@ -0,0 +1,497 @@ +//! Room management for the relay server. +//! +//! Each room holds at most 2 participants (desktop + mobile). +//! Messages are relayed without decryption (E2E encrypted between clients). +//! Desktop→mobile messages are buffered so that the mobile client can poll +//! for missed messages via the HTTP API. + +use chrono::Utc; +use dashmap::DashMap; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::mpsc; +use tracing::{debug, info, warn}; + +pub type ConnId = u64; + +#[derive(Debug, Clone)] +pub struct OutboundMessage { + pub text: String, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum MessageDirection { + ToMobile, + ToDesktop, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BufferedMessage { + pub seq: u64, + pub timestamp: i64, + pub direction: MessageDirection, + pub encrypted_data: String, + pub nonce: String, +} + +#[derive(Debug)] +pub struct Participant { + pub conn_id: ConnId, + pub device_id: String, + pub device_type: String, + pub public_key: String, + pub tx: Option>, + #[allow(dead_code)] + pub joined_at: i64, + pub last_heartbeat: i64, +} + +#[derive(Debug)] +pub struct RelayRoom { + pub room_id: String, + #[allow(dead_code)] + pub created_at: i64, + pub last_activity: i64, + pub participants: Vec, + pub message_store: Vec, + pub next_seq: u64, +} + +impl RelayRoom { + pub fn new(room_id: String) -> Self { + let now = Utc::now().timestamp(); + Self { + room_id, + created_at: now, + last_activity: now, + participants: Vec::with_capacity(2), + message_store: Vec::new(), + next_seq: 1, + } + } + + pub fn add_participant(&mut self, participant: Participant) -> bool { + if self.participants.len() >= 2 { + return false; + } + self.participants.push(participant); + self.touch(); + true + } + + pub fn remove_participant(&mut self, conn_id: ConnId) -> Option { + if let Some(idx) = self.participants.iter().position(|p| p.conn_id == conn_id) { + Some(self.participants.remove(idx)) + } else { + None + } + } + + pub fn relay_to_peer(&self, sender_conn_id: ConnId, message: &str) -> bool { + for p in &self.participants { + if p.conn_id != sender_conn_id { + if let Some(ref tx) = p.tx { + let _ = tx.send(OutboundMessage { + text: message.to_string(), + }); + } + return true; + } + } + false + } + + #[allow(dead_code)] + pub fn send_to(&self, conn_id: ConnId, message: &str) { + for p in &self.participants { + if p.conn_id == conn_id { + if let Some(ref tx) = p.tx { + let _ = tx.send(OutboundMessage { + text: message.to_string(), + }); + } + return; + } + } + } + + pub fn broadcast(&self, message: &str) { + for p in &self.participants { + if let Some(ref tx) = p.tx { + let _ = tx.send(OutboundMessage { + text: message.to_string(), + }); + } + } + } + + pub fn is_empty(&self) -> bool { + self.participants.is_empty() + } + + #[allow(dead_code)] + pub fn participant_count(&self) -> usize { + self.participants.len() + } + + pub fn update_heartbeat(&mut self, conn_id: ConnId) { + let now = Utc::now().timestamp(); + for p in &mut self.participants { + if p.conn_id == conn_id { + p.last_heartbeat = now; + break; + } + } + // Do not update room's last_activity here, so that if the other peer is inactive, + // we can still detect it. + } + + fn touch(&mut self) { + self.last_activity = Utc::now().timestamp(); + } + + /// Buffer an encrypted message for later polling by the target device. + pub fn buffer_message( + &mut self, + direction: MessageDirection, + encrypted_data: String, + nonce: String, + ) -> u64 { + let seq = self.next_seq; + self.next_seq += 1; + self.message_store.push(BufferedMessage { + seq, + timestamp: Utc::now().timestamp(), + direction, + encrypted_data, + nonce, + }); + self.touch(); + seq + } + + /// Return buffered messages for a given direction with seq > since_seq. + pub fn poll_messages( + &self, + direction: MessageDirection, + since_seq: u64, + ) -> Vec { + self.message_store + .iter() + .filter(|m| m.direction == direction && m.seq > since_seq) + .cloned() + .collect() + } + + /// Remove buffered messages with seq <= ack_seq for a given direction. + pub fn ack_messages(&mut self, direction: MessageDirection, ack_seq: u64) { + self.message_store + .retain(|m| !(m.direction == direction && m.seq <= ack_seq)); + } + + /// Get the device_type of the sender identified by conn_id. + pub fn sender_device_type(&self, conn_id: ConnId) -> Option<&str> { + self.participants + .iter() + .find(|p| p.conn_id == conn_id) + .map(|p| p.device_type.as_str()) + } +} + +pub struct RoomManager { + rooms: DashMap, + conn_to_room: DashMap, + next_conn_id: std::sync::atomic::AtomicU64, +} + +impl RoomManager { + pub fn new() -> Arc { + Arc::new(Self { + rooms: DashMap::new(), + conn_to_room: DashMap::new(), + next_conn_id: std::sync::atomic::AtomicU64::new(1), + }) + } + + pub fn next_conn_id(&self) -> ConnId { + self.next_conn_id + .fetch_add(1, std::sync::atomic::Ordering::Relaxed) + } + + /// If conn_id is already in a room, remove it from that room first. + fn leave_current_room(&self, conn_id: ConnId) { + if let Some((_, old_room_id)) = self.conn_to_room.remove(&conn_id) { + let mut should_remove = false; + if let Some(mut room) = self.rooms.get_mut(&old_room_id) { + room.remove_participant(conn_id); + should_remove = room.is_empty(); + } + if should_remove { + self.rooms.remove(&old_room_id); + debug!("Cleaned up old room {old_room_id} after conn moved"); + } + } + } + + pub fn create_room( + &self, + room_id: &str, + conn_id: ConnId, + device_id: &str, + device_type: &str, + public_key: &str, + tx: Option>, + ) -> bool { + if self.rooms.contains_key(room_id) { + warn!("Room {room_id} already exists"); + return false; + } + + self.leave_current_room(conn_id); + + let now = Utc::now().timestamp(); + let mut room = RelayRoom::new(room_id.to_string()); + room.add_participant(Participant { + conn_id, + device_id: device_id.to_string(), + device_type: device_type.to_string(), + public_key: public_key.to_string(), + tx, + joined_at: now, + last_heartbeat: now, + }); + + self.rooms.insert(room_id.to_string(), room); + self.conn_to_room.insert(conn_id, room_id.to_string()); + + info!("Room {room_id} created by {device_id} ({device_type})"); + true + } + + pub fn join_room( + &self, + room_id: &str, + conn_id: ConnId, + device_id: &str, + device_type: &str, + public_key: &str, + tx: Option>, + ) -> bool { + self.leave_current_room(conn_id); + + let mut room_ref = match self.rooms.get_mut(room_id) { + Some(r) => r, + None => { + warn!("Room {room_id} not found"); + return false; + } + }; + + let now = Utc::now().timestamp(); + let ok = room_ref.add_participant(Participant { + conn_id, + device_id: device_id.to_string(), + device_type: device_type.to_string(), + public_key: public_key.to_string(), + tx, + joined_at: now, + last_heartbeat: now, + }); + + if ok { + drop(room_ref); + self.conn_to_room.insert(conn_id, room_id.to_string()); + info!("Device {device_id} ({device_type}) joined room {room_id}"); + } else { + warn!("Room {room_id} is full"); + } + + ok + } + + /// Relay a message to the peer. If the sender is desktop, also buffer for mobile polling. + pub fn relay_message(&self, conn_id: ConnId, encrypted_data: &str, nonce: &str) -> bool { + if let Some(room_id) = self.conn_to_room.get(&conn_id) { + if let Some(mut room) = self.rooms.get_mut(room_id.value()) { + let sender_type = room + .sender_device_type(conn_id) + .unwrap_or("unknown") + .to_string(); + + let direction = if sender_type == "desktop" { + MessageDirection::ToMobile + } else { + MessageDirection::ToDesktop + }; + room.buffer_message( + direction, + encrypted_data.to_string(), + nonce.to_string(), + ); + + let relay_json = serde_json::json!({ + "type": "relay", + "room_id": room_id.value(), + "encrypted_data": encrypted_data, + "nonce": nonce, + }) + .to_string(); + + return room.relay_to_peer(conn_id, &relay_json); + } + } + false + } + + pub fn on_disconnect(&self, conn_id: ConnId) { + if let Some((_, room_id)) = self.conn_to_room.remove(&conn_id) { + let mut should_remove = false; + + if let Some(mut room) = self.rooms.get_mut(&room_id) { + if let Some(removed) = room.remove_participant(conn_id) { + info!( + "Device {} disconnected from room {}", + removed.device_id, room_id + ); + + let notification = serde_json::json!({ + "type": "peer_disconnected", + "device_id": removed.device_id, + }) + .to_string(); + room.broadcast(¬ification); + } + should_remove = room.is_empty(); + } + + if should_remove { + self.rooms.remove(&room_id); + debug!("Empty room {room_id} removed"); + } + } + } + + pub fn heartbeat(&self, conn_id: ConnId) -> bool { + if let Some(room_id) = self.conn_to_room.get(&conn_id) { + if let Some(mut room) = self.rooms.get_mut(room_id.value()) { + room.update_heartbeat(conn_id); + return true; + } + } + false + } + + /// Returns (device_id, device_type, public_key) of the peer. + pub fn get_peer_info( + &self, + room_id: &str, + conn_id: ConnId, + ) -> Option<(String, String, String)> { + if let Some(room) = self.rooms.get(room_id) { + for p in &room.participants { + if p.conn_id != conn_id { + return Some(( + p.device_id.clone(), + p.device_type.clone(), + p.public_key.clone(), + )); + } + } + } + None + } + + /// Find conn_id by device_id in a specific room + pub fn get_conn_id_by_device(&self, room_id: &str, device_id: &str) -> Option { + if let Some(room) = self.rooms.get(room_id) { + for p in &room.participants { + if p.device_id == device_id { + return Some(p.conn_id); + } + } + } + None + } + + /// Check if the room has a peer of the opposite device type + pub fn has_peer(&self, room_id: &str, my_device_type: &str) -> bool { + if let Some(room) = self.rooms.get(room_id) { + room.participants.iter().any(|p| p.device_type != my_device_type) + } else { + false + } + } + + /// Clean up stale rooms based on last_activity rather than created_at. + /// Returns the list of room IDs that were removed. + pub fn cleanup_stale_rooms(&self, ttl_secs: u64) -> Vec { + let now = Utc::now().timestamp(); + let stale_ids: Vec = self + .rooms + .iter() + .filter(|r| (now - r.last_activity) as u64 > ttl_secs) + .map(|r| r.room_id.clone()) + .collect(); + + for room_id in &stale_ids { + if let Some((_, room)) = self.rooms.remove(room_id) { + for p in &room.participants { + self.conn_to_room.remove(&p.conn_id); + } + info!("Stale room {room_id} cleaned up"); + } + } + + stale_ids + } + + pub fn send_to_others_in_room(&self, room_id: &str, exclude_conn_id: ConnId, message: &str) { + if let Some(room) = self.rooms.get(room_id) { + for p in &room.participants { + if p.conn_id != exclude_conn_id { + if let Some(ref tx) = p.tx { + let _ = tx.send(OutboundMessage { + text: message.to_string(), + }); + } + } + } + } + } + + /// Poll buffered messages for a specific room and direction. + pub fn poll_messages( + &self, + room_id: &str, + direction: MessageDirection, + since_seq: u64, + ) -> Vec { + if let Some(mut room) = self.rooms.get_mut(room_id) { + room.last_activity = Utc::now().timestamp(); + room.poll_messages(direction, since_seq) + } else { + Vec::new() + } + } + + /// Acknowledge receipt of messages up to ack_seq. + pub fn ack_messages(&self, room_id: &str, direction: MessageDirection, ack_seq: u64) { + if let Some(mut room) = self.rooms.get_mut(room_id) { + room.last_activity = Utc::now().timestamp(); + room.ack_messages(direction, ack_seq); + } + } + + pub fn room_exists(&self, room_id: &str) -> bool { + self.rooms.contains_key(room_id) + } + + pub fn room_count(&self) -> usize { + self.rooms.len() + } + + pub fn connection_count(&self) -> usize { + self.conn_to_room.len() + } +} diff --git a/src/apps/relay-server/deploy/src/routes/api.rs b/src/apps/relay-server/deploy/src/routes/api.rs new file mode 100644 index 00000000..e21d9862 --- /dev/null +++ b/src/apps/relay-server/deploy/src/routes/api.rs @@ -0,0 +1,538 @@ +//! REST API routes for the relay server. + +use axum::extract::{Path, Query, State}; +use axum::http::StatusCode; +use axum::Json; +use dashmap::DashMap; +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; +use std::collections::HashMap; +use std::sync::Arc; + +use crate::relay::room::{BufferedMessage, MessageDirection}; +use crate::relay::RoomManager; + +#[derive(Clone)] +pub struct AppState { + pub room_manager: Arc, + pub start_time: std::time::Instant, + /// Base directory for per-room uploaded mobile-web files. + pub room_web_dir: String, + /// Global content-addressed file store: sha256 hex -> stored on disk at `{room_web_dir}/_store/{hash}`. + pub content_store: Arc, +} + +/// Tracks which SHA-256 hashes are already persisted in the `_store/` directory. +pub struct ContentStore { + known_hashes: DashMap, +} + +impl ContentStore { + pub fn new(store_dir: &std::path::Path) -> Self { + let known: DashMap = DashMap::new(); + if store_dir.is_dir() { + if let Ok(entries) = std::fs::read_dir(store_dir) { + for entry in entries.flatten() { + if let Ok(meta) = entry.metadata() { + if meta.is_file() { + if let Some(name) = entry.file_name().to_str() { + known.insert(name.to_string(), meta.len()); + } + } + } + } + } + } + tracing::info!("Content store initialized with {} entries", known.len()); + Self { known_hashes: known } + } + + pub fn contains(&self, hash: &str) -> bool { + self.known_hashes.contains_key(hash) + } + + pub fn insert(&self, hash: String, size: u64) { + self.known_hashes.insert(hash, size); + } +} + +#[derive(Serialize)] +pub struct HealthResponse { + pub status: String, + pub version: String, + pub uptime_seconds: u64, + pub rooms: usize, + pub connections: usize, +} + +pub async fn health_check(State(state): State) -> Json { + Json(HealthResponse { + status: "healthy".to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + uptime_seconds: state.start_time.elapsed().as_secs(), + rooms: state.room_manager.room_count(), + connections: state.room_manager.connection_count(), + }) +} + +#[derive(Serialize)] +pub struct ServerInfo { + pub name: String, + pub version: String, + pub protocol_version: u8, +} + +pub async fn server_info() -> Json { + Json(ServerInfo { + name: "BitFun Relay Server".to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + protocol_version: 1, + }) +} + +#[derive(Deserialize)] +pub struct JoinRoomRequest { + pub device_id: String, + pub device_type: String, + pub public_key: String, +} + +/// `POST /api/rooms/:room_id/join` +pub async fn join_room( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> Result, StatusCode> { + let conn_id = state.room_manager.next_conn_id(); + let existing_peer = state.room_manager.get_peer_info(&room_id, conn_id); + + let ok = state.room_manager.join_room( + &room_id, + conn_id, + &body.device_id, + &body.device_type, + &body.public_key, + None, // HTTP client, no websocket tx + ); + + if ok { + let joiner_notification = serde_json::to_string(&crate::routes::websocket::OutboundProtocol::PeerJoined { + device_id: body.device_id.clone(), + device_type: body.device_type.clone(), + public_key: body.public_key.clone(), + }).unwrap_or_default(); + state.room_manager.send_to_others_in_room(&room_id, conn_id, &joiner_notification); + + if let Some((peer_did, peer_dt, peer_pk)) = existing_peer { + Ok(Json(serde_json::json!({ + "status": "joined", + "peer": { + "device_id": peer_did, + "device_type": peer_dt, + "public_key": peer_pk + } + }))) + } else { + Ok(Json(serde_json::json!({ + "status": "joined", + "peer": null + }))) + } + } else { + Err(StatusCode::BAD_REQUEST) + } +} + +#[derive(Deserialize)] +pub struct RelayMessageRequest { + pub device_id: String, + pub encrypted_data: String, + pub nonce: String, +} + +/// `POST /api/rooms/:room_id/message` +pub async fn relay_message( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> StatusCode { + // Find conn_id by device_id in the room + if let Some(conn_id) = state.room_manager.get_conn_id_by_device(&room_id, &body.device_id) { + if state.room_manager.relay_message(conn_id, &body.encrypted_data, &body.nonce) { + StatusCode::OK + } else { + StatusCode::NOT_FOUND + } + } else { + StatusCode::UNAUTHORIZED + } +} + +#[derive(Deserialize)] +pub struct PollQuery { + pub since_seq: Option, + pub device_type: Option, +} + +#[derive(Serialize)] +pub struct PollResponse { + pub messages: Vec, + pub peer_connected: bool, +} + +/// `GET /api/rooms/:room_id/poll?since_seq=0&device_type=mobile` +pub async fn poll_messages( + State(state): State, + Path(room_id): Path, + Query(query): Query, +) -> Result, StatusCode> { + let since = query.since_seq.unwrap_or(0); + let direction = match query.device_type.as_deref() { + Some("desktop") => MessageDirection::ToDesktop, + _ => MessageDirection::ToMobile, + }; + + let peer_connected = state.room_manager.has_peer(&room_id, query.device_type.as_deref().unwrap_or("mobile")); + let messages = state.room_manager.poll_messages(&room_id, direction, since); + + Ok(Json(PollResponse { messages, peer_connected })) +} + +#[derive(Deserialize)] +pub struct AckRequest { + pub ack_seq: u64, + pub device_type: Option, +} + +/// `POST /api/rooms/:room_id/ack` +pub async fn ack_messages( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> StatusCode { + let direction = match body.device_type.as_deref() { + Some("desktop") => MessageDirection::ToDesktop, + _ => MessageDirection::ToMobile, + }; + state + .room_manager + .ack_messages(&room_id, direction, body.ack_seq); + StatusCode::OK +} + +// ── Per-room mobile-web upload & serving ─────────────────────────────────── + +#[derive(Deserialize)] +pub struct UploadWebRequest { + pub files: HashMap, +} + +/// `POST /api/rooms/:room_id/upload-web` +/// +/// Desktop uploads mobile-web dist files (base64-encoded) so the mobile +/// browser can load the exact same version the desktop is running. +/// Now uses the global content store + symlinks to avoid storing duplicates. +pub async fn upload_web( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> Result, StatusCode> { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + + if !state.room_manager.room_exists(&room_id) { + return Err(StatusCode::NOT_FOUND); + } + + let store_dir = std::path::PathBuf::from(&state.room_web_dir).join("_store"); + let _ = std::fs::create_dir_all(&store_dir); + + let room_dir = std::path::PathBuf::from(&state.room_web_dir).join(&room_id); + if let Err(e) = std::fs::create_dir_all(&room_dir) { + tracing::error!("Failed to create room web dir {}: {e}", room_dir.display()); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + + let mut written = 0usize; + let mut reused = 0usize; + for (rel_path, b64_content) in &body.files { + if rel_path.contains("..") { + continue; + } + let decoded = B64.decode(b64_content).map_err(|_| StatusCode::BAD_REQUEST)?; + let hash = hex_sha256(&decoded); + + let store_path = store_dir.join(&hash); + if !store_path.exists() { + std::fs::write(&store_path, &decoded) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + state.content_store.insert(hash.clone(), decoded.len() as u64); + written += 1; + } else { + reused += 1; + } + + let dest = room_dir.join(rel_path); + if let Some(parent) = dest.parent() { + let _ = std::fs::create_dir_all(parent); + } + let _ = std::fs::remove_file(&dest); + create_link(&store_path, &dest) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + } + + tracing::info!( + "Room {room_id}: upload-web complete (new={written}, reused={reused})" + ); + Ok(Json(serde_json::json!({ + "status": "ok", + "files_written": written, + "files_reused": reused + }))) +} + +// ── Incremental upload protocol ──────────────────────────────────────────── + +#[derive(Deserialize)] +pub struct FileManifestEntry { + pub path: String, + pub hash: String, + #[allow(dead_code)] + pub size: u64, +} + +#[derive(Deserialize)] +pub struct CheckWebFilesRequest { + pub files: Vec, +} + +#[derive(Serialize)] +pub struct CheckWebFilesResponse { + pub needed: Vec, + pub existing_count: usize, + pub total_count: usize, +} + +/// `POST /api/rooms/:room_id/check-web-files` +/// +/// Accepts a manifest of file metadata (path, sha256, size). Registers the +/// room's file manifest and returns which files the server still needs. Files +/// whose hash already exists in the global content store are skipped. +pub async fn check_web_files( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> Result, StatusCode> { + if !state.room_manager.room_exists(&room_id) { + return Err(StatusCode::NOT_FOUND); + } + + let store_dir = std::path::PathBuf::from(&state.room_web_dir).join("_store"); + let _ = std::fs::create_dir_all(&store_dir); + + let room_dir = std::path::PathBuf::from(&state.room_web_dir).join(&room_id); + let _ = std::fs::create_dir_all(&room_dir); + + let mut needed = Vec::new(); + let mut existing_count = 0usize; + let total_count = body.files.len(); + + for entry in &body.files { + if entry.path.contains("..") { + continue; + } + if state.content_store.contains(&entry.hash) { + existing_count += 1; + let store_path = store_dir.join(&entry.hash); + let dest = room_dir.join(&entry.path); + if let Some(parent) = dest.parent() { + let _ = std::fs::create_dir_all(parent); + } + let _ = std::fs::remove_file(&dest); + let _ = create_link(&store_path, &dest); + } else { + needed.push(entry.path.clone()); + } + } + + tracing::info!( + "Room {room_id}: check-web-files total={total_count}, existing={existing_count}, needed={}", + needed.len() + ); + + Ok(Json(CheckWebFilesResponse { + needed, + existing_count, + total_count, + })) +} + +#[derive(Deserialize)] +pub struct UploadWebFilesEntry { + pub content: String, + pub hash: String, +} + +#[derive(Deserialize)] +pub struct UploadWebFilesRequest { + pub files: HashMap, +} + +/// `POST /api/rooms/:room_id/upload-web-files` +/// +/// Upload only the files that the server requested via `check-web-files`. +/// Each entry includes the base64 content and its expected sha256 hash. +/// Files are stored in the global content store and symlinked into the room. +pub async fn upload_web_files( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> Result, StatusCode> { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + + if !state.room_manager.room_exists(&room_id) { + return Err(StatusCode::NOT_FOUND); + } + + let store_dir = std::path::PathBuf::from(&state.room_web_dir).join("_store"); + let _ = std::fs::create_dir_all(&store_dir); + + let room_dir = std::path::PathBuf::from(&state.room_web_dir).join(&room_id); + let _ = std::fs::create_dir_all(&room_dir); + + let mut stored = 0usize; + for (rel_path, entry) in &body.files { + if rel_path.contains("..") { + continue; + } + let decoded = B64.decode(&entry.content).map_err(|_| StatusCode::BAD_REQUEST)?; + let actual_hash = hex_sha256(&decoded); + if actual_hash != entry.hash { + tracing::warn!( + "Room {room_id}: hash mismatch for {rel_path} (expected={}, actual={actual_hash})", + entry.hash + ); + return Err(StatusCode::BAD_REQUEST); + } + + let store_path = store_dir.join(&actual_hash); + if !store_path.exists() { + std::fs::write(&store_path, &decoded) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + state + .content_store + .insert(actual_hash.clone(), decoded.len() as u64); + } + + let dest = room_dir.join(rel_path); + if let Some(parent) = dest.parent() { + let _ = std::fs::create_dir_all(parent); + } + let _ = std::fs::remove_file(&dest); + create_link(&store_path, &dest) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + stored += 1; + } + + tracing::info!("Room {room_id}: upload-web-files stored {stored} new files"); + Ok(Json(serde_json::json!({ "status": "ok", "files_stored": stored }))) +} + +fn hex_sha256(data: &[u8]) -> String { + let mut hasher = Sha256::new(); + hasher.update(data); + format!("{:x}", hasher.finalize()) +} + +/// Create a symlink (Unix) or hard link fallback (Windows). +fn create_link( + original: &std::path::Path, + link: &std::path::Path, +) -> std::io::Result<()> { + #[cfg(unix)] + { + std::os::unix::fs::symlink(original, link) + } + #[cfg(not(unix))] + { + std::fs::hard_link(original, link) + .or_else(|_| std::fs::copy(original, link).map(|_| ())) + } +} + +/// `GET /r/{*rest}` — serve per-room mobile-web static files. +/// +/// The `rest` path is expected to be `room_id` or `room_id/file/path`. +/// Falls back to `index.html` for SPA routing. +pub async fn serve_room_web_catchall( + State(state): State, + Path(rest): Path, +) -> Result { + use axum::body::Body; + use axum::http::header; + use axum::response::IntoResponse; + + let rest = rest.trim_start_matches('/'); + let (room_id, file_path) = match rest.find('/') { + Some(idx) => (&rest[..idx], &rest[idx + 1..]), + None => (rest, ""), + }; + + if room_id.is_empty() { + return Err(StatusCode::NOT_FOUND); + } + + let room_dir = std::path::PathBuf::from(&state.room_web_dir).join(room_id); + if !room_dir.exists() { + return Err(StatusCode::NOT_FOUND); + } + + let target = if file_path.is_empty() { + room_dir.join("index.html") + } else { + room_dir.join(file_path) + }; + + let file = if target.is_file() { + target + } else { + room_dir.join("index.html") + }; + + if !file.is_file() { + return Err(StatusCode::NOT_FOUND); + } + + let content = std::fs::read(&file).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + let mime = mime_from_path(&file); + + Ok(([(header::CONTENT_TYPE, mime)], Body::from(content)).into_response()) +} + +fn mime_from_path(p: &std::path::Path) -> &'static str { + match p.extension().and_then(|e| e.to_str()) { + Some("html") => "text/html; charset=utf-8", + Some("js") => "application/javascript; charset=utf-8", + Some("css") => "text/css; charset=utf-8", + Some("json") => "application/json", + Some("png") => "image/png", + Some("svg") => "image/svg+xml", + Some("ico") => "image/x-icon", + Some("woff2") => "font/woff2", + Some("woff") => "font/woff", + Some("ttf") => "font/ttf", + Some("wasm") => "application/wasm", + _ => "application/octet-stream", + } +} + +/// Remove the per-room web directory (called on room cleanup). +pub fn cleanup_room_web(room_web_dir: &str, room_id: &str) { + let dir = std::path::PathBuf::from(room_web_dir).join(room_id); + if dir.exists() { + if let Err(e) = std::fs::remove_dir_all(&dir) { + tracing::warn!("Failed to clean up room web dir {}: {e}", dir.display()); + } else { + tracing::info!("Cleaned up room web dir for {room_id}"); + } + } +} diff --git a/src/apps/relay-server/deploy/src/routes/mod.rs b/src/apps/relay-server/deploy/src/routes/mod.rs new file mode 100644 index 00000000..ae5fb74d --- /dev/null +++ b/src/apps/relay-server/deploy/src/routes/mod.rs @@ -0,0 +1,4 @@ +//! HTTP and WebSocket routes for the relay server. + +pub mod api; +pub mod websocket; diff --git a/src/apps/relay-server/deploy/src/routes/websocket.rs b/src/apps/relay-server/deploy/src/routes/websocket.rs new file mode 100644 index 00000000..bfc80e70 --- /dev/null +++ b/src/apps/relay-server/deploy/src/routes/websocket.rs @@ -0,0 +1,218 @@ +//! WebSocket handler for the relay server. +//! +//! Each connected client sends/receives JSON messages following the relay protocol. +//! The server never decrypts application data — it only handles room management +//! and forwards encrypted payloads between paired devices. +//! Desktop→mobile messages are also buffered for later polling. + +use axum::{ + extract::{ + ws::{Message, WebSocket, WebSocketUpgrade}, + State, + }, + response::Response, +}; +use futures_util::{SinkExt, StreamExt}; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::mpsc; +use tracing::{debug, error, info, warn}; + +use crate::relay::room::{ConnId, OutboundMessage, RoomManager}; +use crate::routes::api::AppState; + +#[derive(Debug, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +#[allow(dead_code)] +pub enum InboundMessage { + CreateRoom { + room_id: Option, + device_id: String, + device_type: String, + public_key: String, + }, + JoinRoom { + room_id: String, + device_id: String, + device_type: String, + public_key: String, + }, + Relay { + room_id: String, + encrypted_data: String, + nonce: String, + }, + Heartbeat, +} + +#[derive(Debug, Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +#[allow(dead_code)] +pub enum OutboundProtocol { + RoomCreated { room_id: String }, + PeerJoined { device_id: String, device_type: String, public_key: String }, + Relay { room_id: String, encrypted_data: String, nonce: String }, + HeartbeatAck, + PeerDisconnected { device_id: String }, + Error { message: String }, +} + +pub async fn websocket_handler( + ws: WebSocketUpgrade, + State(state): State, +) -> Response { + ws.on_upgrade(move |socket| handle_socket(socket, state)) +} + +async fn handle_socket(socket: WebSocket, state: AppState) { + let (mut ws_sender, mut ws_receiver) = socket.split(); + let (out_tx, mut out_rx) = mpsc::unbounded_channel::(); + + let conn_id = state.room_manager.next_conn_id(); + info!("WebSocket connected: conn_id={conn_id}"); + + let write_task = tokio::spawn(async move { + while let Some(msg) = out_rx.recv().await { + if !msg.text.is_empty() { + if ws_sender.send(Message::Text(msg.text)).await.is_err() { + break; + } + } + } + }); + + while let Some(msg_result) = ws_receiver.next().await { + match msg_result { + Ok(Message::Text(text)) => { + handle_text_message(&text, conn_id, &state.room_manager, &out_tx); + } + Ok(Message::Ping(_)) => { + // Axum auto-replies Pong for Ping frames + } + Ok(Message::Close(_)) => { + info!("WebSocket close from conn_id={conn_id}"); + break; + } + Err(e) => { + error!("WebSocket error conn_id={conn_id}: {e}"); + break; + } + _ => {} + } + } + + state.room_manager.on_disconnect(conn_id); + drop(out_tx); + let _ = write_task.await; + info!("WebSocket disconnected: conn_id={conn_id}"); +} + +fn handle_text_message( + text: &str, + conn_id: ConnId, + room_manager: &Arc, + out_tx: &mpsc::UnboundedSender, +) { + debug!("Received from conn_id={conn_id}: {}", &text[..text.len().min(200)]); + let msg: InboundMessage = match serde_json::from_str(text) { + Ok(m) => m, + Err(e) => { + warn!("Invalid message from conn_id={conn_id}: {e}"); + send_json(out_tx, &OutboundProtocol::Error { + message: format!("invalid message format: {e}"), + }); + return; + } + }; + + match msg { + InboundMessage::CreateRoom { + room_id, + device_id, + device_type, + public_key, + } => { + let room_id = room_id.unwrap_or_else(generate_room_id); + let ok = room_manager.create_room( + &room_id, conn_id, &device_id, &device_type, &public_key, Some(out_tx.clone()), + ); + if ok { + send_json(out_tx, &OutboundProtocol::RoomCreated { room_id }); + } else { + send_json(out_tx, &OutboundProtocol::Error { + message: "failed to create room".into(), + }); + } + } + + InboundMessage::JoinRoom { + room_id, + device_id, + device_type, + public_key, + } => { + let existing_peer = room_manager.get_peer_info(&room_id, conn_id); + + let ok = room_manager.join_room( + &room_id, conn_id, &device_id, &device_type, &public_key, Some(out_tx.clone()), + ); + + if ok { + let joiner_notification = serde_json::to_string(&OutboundProtocol::PeerJoined { + device_id: device_id.clone(), + device_type: device_type.clone(), + public_key: public_key.clone(), + }).unwrap_or_default(); + room_manager.send_to_others_in_room(&room_id, conn_id, &joiner_notification); + + if let Some((peer_did, peer_dt, peer_pk)) = existing_peer { + send_json(out_tx, &OutboundProtocol::PeerJoined { + device_id: peer_did, + device_type: peer_dt, + public_key: peer_pk, + }); + } else { + warn!("No existing peer found for room {room_id} to send back to joiner"); + } + } else { + send_json(out_tx, &OutboundProtocol::Error { + message: format!("failed to join room {room_id}"), + }); + } + } + + InboundMessage::Relay { + room_id: _, + encrypted_data, + nonce, + } => { + debug!("Relay message from conn_id={conn_id} data_len={}", encrypted_data.len()); + if room_manager.relay_message(conn_id, &encrypted_data, &nonce) { + debug!("Relay message forwarded from conn_id={conn_id}"); + } else { + warn!("Relay failed for conn_id={conn_id}: no peer found"); + } + } + + InboundMessage::Heartbeat => { + if room_manager.heartbeat(conn_id) { + send_json(out_tx, &OutboundProtocol::HeartbeatAck); + } else { + send_json(out_tx, &OutboundProtocol::Error { + message: "Room not found or expired".into(), + }); + } + } + } +} + +fn send_json(tx: &mpsc::UnboundedSender, msg: &T) { + if let Ok(json) = serde_json::to_string(msg) { + let _ = tx.send(OutboundMessage { text: json }); + } +} + +fn generate_room_id() -> String { + let bytes: [u8; 6] = rand::random(); + bytes.iter().map(|b| format!("{b:02x}")).collect() +} diff --git a/src/apps/relay-server/docker-compose.yml b/src/apps/relay-server/docker-compose.yml new file mode 100644 index 00000000..d8ed1f72 --- /dev/null +++ b/src/apps/relay-server/docker-compose.yml @@ -0,0 +1,37 @@ +version: '3.8' + +services: + relay-server: + build: + context: ../../.. + dockerfile: src/apps/relay-server/Dockerfile + container_name: bitfun-relay + restart: unless-stopped + ports: + - "9700:9700" + environment: + - RELAY_PORT=9700 + - RELAY_STATIC_DIR=/app/static + - RELAY_ROOM_TTL=3600 + volumes: + - relay-data:/app/data + + # Caddy reverse proxy for automatic HTTPS + caddy: + image: caddy:2-alpine + container_name: bitfun-caddy + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - caddy-data:/data + - caddy-config:/config + depends_on: + - relay-server + +volumes: + relay-data: + caddy-data: + caddy-config: diff --git a/src/apps/relay-server/src/config.rs b/src/apps/relay-server/src/config.rs new file mode 100644 index 00000000..626d1009 --- /dev/null +++ b/src/apps/relay-server/src/config.rs @@ -0,0 +1,53 @@ +//! Relay server configuration. + +use std::net::SocketAddr; + +#[derive(Debug, Clone)] +#[allow(dead_code)] +pub struct RelayConfig { + pub listen_addr: SocketAddr, + pub room_ttl_secs: u64, + pub heartbeat_interval_secs: u64, + pub heartbeat_timeout_secs: u64, + pub static_dir: Option, + /// Directory where per-room uploaded mobile-web files are stored. + pub room_web_dir: String, + pub cors_allow_origins: Vec, +} + +impl Default for RelayConfig { + fn default() -> Self { + Self { + listen_addr: ([0, 0, 0, 0], 9700).into(), + room_ttl_secs: 3600, + heartbeat_interval_secs: 30, + heartbeat_timeout_secs: 90, + static_dir: None, + room_web_dir: "/tmp/bitfun-room-web".to_string(), + cors_allow_origins: vec!["*".to_string()], + } + } +} + +impl RelayConfig { + pub fn from_env() -> Self { + let mut cfg = Self::default(); + if let Ok(port) = std::env::var("RELAY_PORT") { + if let Ok(p) = port.parse::() { + cfg.listen_addr = ([0, 0, 0, 0], p).into(); + } + } + if let Ok(dir) = std::env::var("RELAY_STATIC_DIR") { + cfg.static_dir = Some(dir); + } + if let Ok(dir) = std::env::var("RELAY_ROOM_WEB_DIR") { + cfg.room_web_dir = dir; + } + if let Ok(ttl) = std::env::var("RELAY_ROOM_TTL") { + if let Ok(t) = ttl.parse() { + cfg.room_ttl_secs = t; + } + } + cfg + } +} diff --git a/src/apps/relay-server/src/main.rs b/src/apps/relay-server/src/main.rs new file mode 100644 index 00000000..a7f80237 --- /dev/null +++ b/src/apps/relay-server/src/main.rs @@ -0,0 +1,98 @@ +//! BitFun Relay Server +//! +//! WebSocket relay for Remote Connect. Manages rooms and forwards E2E encrypted +//! messages between desktop and mobile clients. Also serves mobile web static files. + +use axum::extract::DefaultBodyLimit; +use axum::routing::{get, post}; +use axum::Router; +use tower_http::cors::CorsLayer; +use tracing::info; + +mod config; +mod relay; +mod routes; + +use config::RelayConfig; +use relay::RoomManager; +use routes::api::{self, AppState}; +use routes::websocket; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt() + .with_max_level(tracing::Level::DEBUG) + .init(); + + let cfg = RelayConfig::from_env(); + info!("BitFun Relay Server v{}", env!("CARGO_PKG_VERSION")); + + let room_manager = RoomManager::new(); + + let cleanup_rm = room_manager.clone(); + let cleanup_ttl = cfg.room_ttl_secs; + let cleanup_room_web_dir = cfg.room_web_dir.clone(); + tokio::spawn(async move { + loop { + tokio::time::sleep(std::time::Duration::from_secs(60)).await; + let stale_ids = cleanup_rm.cleanup_stale_rooms(cleanup_ttl); + for room_id in &stale_ids { + api::cleanup_room_web(&cleanup_room_web_dir, room_id); + } + } + }); + + let store_dir = std::path::PathBuf::from(&cfg.room_web_dir).join("_store"); + let _ = std::fs::create_dir_all(&store_dir); + let content_store = std::sync::Arc::new(api::ContentStore::new(&store_dir)); + + let state = AppState { + room_manager, + start_time: std::time::Instant::now(), + room_web_dir: cfg.room_web_dir.clone(), + content_store, + }; + + let mut app = Router::new() + .route("/health", get(api::health_check)) + .route("/api/info", get(api::server_info)) + .route("/api/rooms/:room_id/join", post(api::join_room)) + .route("/api/rooms/:room_id/message", post(api::relay_message)) + .route("/api/rooms/:room_id/poll", get(api::poll_messages)) + .route("/api/rooms/:room_id/ack", post(api::ack_messages)) + .route( + "/api/rooms/:room_id/upload-web", + post(api::upload_web).layer(DefaultBodyLimit::max(10 * 1024 * 1024)), + ) + .route( + "/api/rooms/:room_id/check-web-files", + post(api::check_web_files), + ) + .route( + "/api/rooms/:room_id/upload-web-files", + post(api::upload_web_files).layer(DefaultBodyLimit::max(10 * 1024 * 1024)), + ) + .route("/r/*rest", get(api::serve_room_web_catchall)) + .route("/ws", get(websocket::websocket_handler)) + .layer(CorsLayer::permissive()) + .with_state(state); + + // Serve mobile web static files as a fallback for requests that + // don't match any API or WebSocket route. + if let Some(static_dir) = &cfg.static_dir { + info!("Serving static files from: {static_dir}"); + app = app.fallback_service( + tower_http::services::ServeDir::new(static_dir) + .append_index_html_on_directories(true), + ); + } + + info!("Room web upload dir: {}", cfg.room_web_dir); + + let listener = tokio::net::TcpListener::bind(cfg.listen_addr).await?; + info!("Relay server listening on {}", cfg.listen_addr); + info!("WebSocket endpoint: ws://{}/ws", cfg.listen_addr); + + axum::serve(listener, app).await?; + Ok(()) +} diff --git a/src/apps/relay-server/src/relay/mod.rs b/src/apps/relay-server/src/relay/mod.rs new file mode 100644 index 00000000..c24d4265 --- /dev/null +++ b/src/apps/relay-server/src/relay/mod.rs @@ -0,0 +1,5 @@ +//! Core relay logic: room management and message routing. + +pub mod room; + +pub use room::RoomManager; diff --git a/src/apps/relay-server/src/relay/room.rs b/src/apps/relay-server/src/relay/room.rs new file mode 100644 index 00000000..8b336d85 --- /dev/null +++ b/src/apps/relay-server/src/relay/room.rs @@ -0,0 +1,497 @@ +//! Room management for the relay server. +//! +//! Each room holds at most 2 participants (desktop + mobile). +//! Messages are relayed without decryption (E2E encrypted between clients). +//! Desktop→mobile messages are buffered so that the mobile client can poll +//! for missed messages via the HTTP API. + +use chrono::Utc; +use dashmap::DashMap; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::mpsc; +use tracing::{debug, info, warn}; + +pub type ConnId = u64; + +#[derive(Debug, Clone)] +pub struct OutboundMessage { + pub text: String, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum MessageDirection { + ToMobile, + ToDesktop, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BufferedMessage { + pub seq: u64, + pub timestamp: i64, + pub direction: MessageDirection, + pub encrypted_data: String, + pub nonce: String, +} + +#[derive(Debug)] +pub struct Participant { + pub conn_id: ConnId, + pub device_id: String, + pub device_type: String, + pub public_key: String, + pub tx: Option>, + #[allow(dead_code)] + pub joined_at: i64, + pub last_heartbeat: i64, +} + +#[derive(Debug)] +pub struct RelayRoom { + pub room_id: String, + #[allow(dead_code)] + pub created_at: i64, + pub last_activity: i64, + pub participants: Vec, + pub message_store: Vec, + pub next_seq: u64, +} + +impl RelayRoom { + pub fn new(room_id: String) -> Self { + let now = Utc::now().timestamp(); + Self { + room_id, + created_at: now, + last_activity: now, + participants: Vec::with_capacity(2), + message_store: Vec::new(), + next_seq: 1, + } + } + + pub fn add_participant(&mut self, participant: Participant) -> bool { + if self.participants.len() >= 2 { + return false; + } + self.participants.push(participant); + self.touch(); + true + } + + pub fn remove_participant(&mut self, conn_id: ConnId) -> Option { + if let Some(idx) = self.participants.iter().position(|p| p.conn_id == conn_id) { + Some(self.participants.remove(idx)) + } else { + None + } + } + + pub fn relay_to_peer(&self, sender_conn_id: ConnId, message: &str) -> bool { + for p in &self.participants { + if p.conn_id != sender_conn_id { + if let Some(ref tx) = p.tx { + let _ = tx.send(OutboundMessage { + text: message.to_string(), + }); + } + return true; + } + } + false + } + + #[allow(dead_code)] + pub fn send_to(&self, conn_id: ConnId, message: &str) { + for p in &self.participants { + if p.conn_id == conn_id { + if let Some(ref tx) = p.tx { + let _ = tx.send(OutboundMessage { + text: message.to_string(), + }); + } + return; + } + } + } + + pub fn broadcast(&self, message: &str) { + for p in &self.participants { + if let Some(ref tx) = p.tx { + let _ = tx.send(OutboundMessage { + text: message.to_string(), + }); + } + } + } + + pub fn is_empty(&self) -> bool { + self.participants.is_empty() + } + + #[allow(dead_code)] + pub fn participant_count(&self) -> usize { + self.participants.len() + } + + pub fn update_heartbeat(&mut self, conn_id: ConnId) { + let now = Utc::now().timestamp(); + for p in &mut self.participants { + if p.conn_id == conn_id { + p.last_heartbeat = now; + break; + } + } + // Do not update room's last_activity here, so that if the other peer is inactive, + // we can still detect it. + } + + fn touch(&mut self) { + self.last_activity = Utc::now().timestamp(); + } + + /// Buffer an encrypted message for later polling by the target device. + pub fn buffer_message( + &mut self, + direction: MessageDirection, + encrypted_data: String, + nonce: String, + ) -> u64 { + let seq = self.next_seq; + self.next_seq += 1; + self.message_store.push(BufferedMessage { + seq, + timestamp: Utc::now().timestamp(), + direction, + encrypted_data, + nonce, + }); + self.touch(); + seq + } + + /// Return buffered messages for a given direction with seq > since_seq. + pub fn poll_messages( + &self, + direction: MessageDirection, + since_seq: u64, + ) -> Vec { + self.message_store + .iter() + .filter(|m| m.direction == direction && m.seq > since_seq) + .cloned() + .collect() + } + + /// Remove buffered messages with seq <= ack_seq for a given direction. + pub fn ack_messages(&mut self, direction: MessageDirection, ack_seq: u64) { + self.message_store + .retain(|m| !(m.direction == direction && m.seq <= ack_seq)); + } + + /// Get the device_type of the sender identified by conn_id. + pub fn sender_device_type(&self, conn_id: ConnId) -> Option<&str> { + self.participants + .iter() + .find(|p| p.conn_id == conn_id) + .map(|p| p.device_type.as_str()) + } +} + +pub struct RoomManager { + rooms: DashMap, + conn_to_room: DashMap, + next_conn_id: std::sync::atomic::AtomicU64, +} + +impl RoomManager { + pub fn new() -> Arc { + Arc::new(Self { + rooms: DashMap::new(), + conn_to_room: DashMap::new(), + next_conn_id: std::sync::atomic::AtomicU64::new(1), + }) + } + + pub fn next_conn_id(&self) -> ConnId { + self.next_conn_id + .fetch_add(1, std::sync::atomic::Ordering::Relaxed) + } + + /// If conn_id is already in a room, remove it from that room first. + fn leave_current_room(&self, conn_id: ConnId) { + if let Some((_, old_room_id)) = self.conn_to_room.remove(&conn_id) { + let mut should_remove = false; + if let Some(mut room) = self.rooms.get_mut(&old_room_id) { + room.remove_participant(conn_id); + should_remove = room.is_empty(); + } + if should_remove { + self.rooms.remove(&old_room_id); + debug!("Cleaned up old room {old_room_id} after conn moved"); + } + } + } + + pub fn create_room( + &self, + room_id: &str, + conn_id: ConnId, + device_id: &str, + device_type: &str, + public_key: &str, + tx: Option>, + ) -> bool { + if self.rooms.contains_key(room_id) { + warn!("Room {room_id} already exists"); + return false; + } + + self.leave_current_room(conn_id); + + let now = Utc::now().timestamp(); + let mut room = RelayRoom::new(room_id.to_string()); + room.add_participant(Participant { + conn_id, + device_id: device_id.to_string(), + device_type: device_type.to_string(), + public_key: public_key.to_string(), + tx, + joined_at: now, + last_heartbeat: now, + }); + + self.rooms.insert(room_id.to_string(), room); + self.conn_to_room.insert(conn_id, room_id.to_string()); + + info!("Room {room_id} created by {device_id} ({device_type})"); + true + } + + pub fn join_room( + &self, + room_id: &str, + conn_id: ConnId, + device_id: &str, + device_type: &str, + public_key: &str, + tx: Option>, + ) -> bool { + self.leave_current_room(conn_id); + + let mut room_ref = match self.rooms.get_mut(room_id) { + Some(r) => r, + None => { + warn!("Room {room_id} not found"); + return false; + } + }; + + let now = Utc::now().timestamp(); + let ok = room_ref.add_participant(Participant { + conn_id, + device_id: device_id.to_string(), + device_type: device_type.to_string(), + public_key: public_key.to_string(), + tx, + joined_at: now, + last_heartbeat: now, + }); + + if ok { + drop(room_ref); + self.conn_to_room.insert(conn_id, room_id.to_string()); + info!("Device {device_id} ({device_type}) joined room {room_id}"); + } else { + warn!("Room {room_id} is full"); + } + + ok + } + + /// Relay a message to the peer. If the sender is desktop, also buffer for mobile polling. + pub fn relay_message(&self, conn_id: ConnId, encrypted_data: &str, nonce: &str) -> bool { + if let Some(room_id) = self.conn_to_room.get(&conn_id) { + if let Some(mut room) = self.rooms.get_mut(room_id.value()) { + let sender_type = room + .sender_device_type(conn_id) + .unwrap_or("unknown") + .to_string(); + + let direction = if sender_type == "desktop" { + MessageDirection::ToMobile + } else { + MessageDirection::ToDesktop + }; + room.buffer_message( + direction, + encrypted_data.to_string(), + nonce.to_string(), + ); + + let relay_json = serde_json::json!({ + "type": "relay", + "room_id": room_id.value(), + "encrypted_data": encrypted_data, + "nonce": nonce, + }) + .to_string(); + + return room.relay_to_peer(conn_id, &relay_json); + } + } + false + } + + pub fn on_disconnect(&self, conn_id: ConnId) { + if let Some((_, room_id)) = self.conn_to_room.remove(&conn_id) { + let mut should_remove = false; + + if let Some(mut room) = self.rooms.get_mut(&room_id) { + if let Some(removed) = room.remove_participant(conn_id) { + info!( + "Device {} disconnected from room {}", + removed.device_id, room_id + ); + + let notification = serde_json::json!({ + "type": "peer_disconnected", + "device_id": removed.device_id, + }) + .to_string(); + room.broadcast(¬ification); + } + should_remove = room.is_empty(); + } + + if should_remove { + self.rooms.remove(&room_id); + debug!("Empty room {room_id} removed"); + } + } + } + + pub fn heartbeat(&self, conn_id: ConnId) -> bool { + if let Some(room_id) = self.conn_to_room.get(&conn_id) { + if let Some(mut room) = self.rooms.get_mut(room_id.value()) { + room.update_heartbeat(conn_id); + return true; + } + } + false + } + + /// Returns (device_id, device_type, public_key) of the peer. + pub fn get_peer_info( + &self, + room_id: &str, + conn_id: ConnId, + ) -> Option<(String, String, String)> { + if let Some(room) = self.rooms.get(room_id) { + for p in &room.participants { + if p.conn_id != conn_id { + return Some(( + p.device_id.clone(), + p.device_type.clone(), + p.public_key.clone(), + )); + } + } + } + None + } + + /// Find conn_id by device_id in a specific room + pub fn get_conn_id_by_device(&self, room_id: &str, device_id: &str) -> Option { + if let Some(room) = self.rooms.get(room_id) { + for p in &room.participants { + if p.device_id == device_id { + return Some(p.conn_id); + } + } + } + None + } + + /// Check if the room has a peer of the opposite device type + pub fn has_peer(&self, room_id: &str, my_device_type: &str) -> bool { + if let Some(room) = self.rooms.get(room_id) { + room.participants.iter().any(|p| p.device_type != my_device_type) + } else { + false + } + } + + /// Clean up stale rooms based on last_activity rather than created_at. + /// Returns the list of room IDs that were removed. + pub fn cleanup_stale_rooms(&self, ttl_secs: u64) -> Vec { + let now = Utc::now().timestamp(); + let stale_ids: Vec = self + .rooms + .iter() + .filter(|r| (now - r.last_activity) as u64 > ttl_secs) + .map(|r| r.room_id.clone()) + .collect(); + + for room_id in &stale_ids { + if let Some((_, room)) = self.rooms.remove(room_id) { + for p in &room.participants { + self.conn_to_room.remove(&p.conn_id); + } + info!("Stale room {room_id} cleaned up"); + } + } + + stale_ids + } + + pub fn send_to_others_in_room(&self, room_id: &str, exclude_conn_id: ConnId, message: &str) { + if let Some(room) = self.rooms.get(room_id) { + for p in &room.participants { + if p.conn_id != exclude_conn_id { + if let Some(ref tx) = p.tx { + let _ = tx.send(OutboundMessage { + text: message.to_string(), + }); + } + } + } + } + } + + /// Poll buffered messages for a specific room and direction. + pub fn poll_messages( + &self, + room_id: &str, + direction: MessageDirection, + since_seq: u64, + ) -> Vec { + if let Some(mut room) = self.rooms.get_mut(room_id) { + room.last_activity = Utc::now().timestamp(); + room.poll_messages(direction, since_seq) + } else { + Vec::new() + } + } + + /// Acknowledge receipt of messages up to ack_seq. + pub fn ack_messages(&self, room_id: &str, direction: MessageDirection, ack_seq: u64) { + if let Some(mut room) = self.rooms.get_mut(room_id) { + room.last_activity = Utc::now().timestamp(); + room.ack_messages(direction, ack_seq); + } + } + + pub fn room_exists(&self, room_id: &str) -> bool { + self.rooms.contains_key(room_id) + } + + pub fn room_count(&self) -> usize { + self.rooms.len() + } + + pub fn connection_count(&self) -> usize { + self.conn_to_room.len() + } +} diff --git a/src/apps/relay-server/src/routes/api.rs b/src/apps/relay-server/src/routes/api.rs new file mode 100644 index 00000000..e21d9862 --- /dev/null +++ b/src/apps/relay-server/src/routes/api.rs @@ -0,0 +1,538 @@ +//! REST API routes for the relay server. + +use axum::extract::{Path, Query, State}; +use axum::http::StatusCode; +use axum::Json; +use dashmap::DashMap; +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; +use std::collections::HashMap; +use std::sync::Arc; + +use crate::relay::room::{BufferedMessage, MessageDirection}; +use crate::relay::RoomManager; + +#[derive(Clone)] +pub struct AppState { + pub room_manager: Arc, + pub start_time: std::time::Instant, + /// Base directory for per-room uploaded mobile-web files. + pub room_web_dir: String, + /// Global content-addressed file store: sha256 hex -> stored on disk at `{room_web_dir}/_store/{hash}`. + pub content_store: Arc, +} + +/// Tracks which SHA-256 hashes are already persisted in the `_store/` directory. +pub struct ContentStore { + known_hashes: DashMap, +} + +impl ContentStore { + pub fn new(store_dir: &std::path::Path) -> Self { + let known: DashMap = DashMap::new(); + if store_dir.is_dir() { + if let Ok(entries) = std::fs::read_dir(store_dir) { + for entry in entries.flatten() { + if let Ok(meta) = entry.metadata() { + if meta.is_file() { + if let Some(name) = entry.file_name().to_str() { + known.insert(name.to_string(), meta.len()); + } + } + } + } + } + } + tracing::info!("Content store initialized with {} entries", known.len()); + Self { known_hashes: known } + } + + pub fn contains(&self, hash: &str) -> bool { + self.known_hashes.contains_key(hash) + } + + pub fn insert(&self, hash: String, size: u64) { + self.known_hashes.insert(hash, size); + } +} + +#[derive(Serialize)] +pub struct HealthResponse { + pub status: String, + pub version: String, + pub uptime_seconds: u64, + pub rooms: usize, + pub connections: usize, +} + +pub async fn health_check(State(state): State) -> Json { + Json(HealthResponse { + status: "healthy".to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + uptime_seconds: state.start_time.elapsed().as_secs(), + rooms: state.room_manager.room_count(), + connections: state.room_manager.connection_count(), + }) +} + +#[derive(Serialize)] +pub struct ServerInfo { + pub name: String, + pub version: String, + pub protocol_version: u8, +} + +pub async fn server_info() -> Json { + Json(ServerInfo { + name: "BitFun Relay Server".to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + protocol_version: 1, + }) +} + +#[derive(Deserialize)] +pub struct JoinRoomRequest { + pub device_id: String, + pub device_type: String, + pub public_key: String, +} + +/// `POST /api/rooms/:room_id/join` +pub async fn join_room( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> Result, StatusCode> { + let conn_id = state.room_manager.next_conn_id(); + let existing_peer = state.room_manager.get_peer_info(&room_id, conn_id); + + let ok = state.room_manager.join_room( + &room_id, + conn_id, + &body.device_id, + &body.device_type, + &body.public_key, + None, // HTTP client, no websocket tx + ); + + if ok { + let joiner_notification = serde_json::to_string(&crate::routes::websocket::OutboundProtocol::PeerJoined { + device_id: body.device_id.clone(), + device_type: body.device_type.clone(), + public_key: body.public_key.clone(), + }).unwrap_or_default(); + state.room_manager.send_to_others_in_room(&room_id, conn_id, &joiner_notification); + + if let Some((peer_did, peer_dt, peer_pk)) = existing_peer { + Ok(Json(serde_json::json!({ + "status": "joined", + "peer": { + "device_id": peer_did, + "device_type": peer_dt, + "public_key": peer_pk + } + }))) + } else { + Ok(Json(serde_json::json!({ + "status": "joined", + "peer": null + }))) + } + } else { + Err(StatusCode::BAD_REQUEST) + } +} + +#[derive(Deserialize)] +pub struct RelayMessageRequest { + pub device_id: String, + pub encrypted_data: String, + pub nonce: String, +} + +/// `POST /api/rooms/:room_id/message` +pub async fn relay_message( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> StatusCode { + // Find conn_id by device_id in the room + if let Some(conn_id) = state.room_manager.get_conn_id_by_device(&room_id, &body.device_id) { + if state.room_manager.relay_message(conn_id, &body.encrypted_data, &body.nonce) { + StatusCode::OK + } else { + StatusCode::NOT_FOUND + } + } else { + StatusCode::UNAUTHORIZED + } +} + +#[derive(Deserialize)] +pub struct PollQuery { + pub since_seq: Option, + pub device_type: Option, +} + +#[derive(Serialize)] +pub struct PollResponse { + pub messages: Vec, + pub peer_connected: bool, +} + +/// `GET /api/rooms/:room_id/poll?since_seq=0&device_type=mobile` +pub async fn poll_messages( + State(state): State, + Path(room_id): Path, + Query(query): Query, +) -> Result, StatusCode> { + let since = query.since_seq.unwrap_or(0); + let direction = match query.device_type.as_deref() { + Some("desktop") => MessageDirection::ToDesktop, + _ => MessageDirection::ToMobile, + }; + + let peer_connected = state.room_manager.has_peer(&room_id, query.device_type.as_deref().unwrap_or("mobile")); + let messages = state.room_manager.poll_messages(&room_id, direction, since); + + Ok(Json(PollResponse { messages, peer_connected })) +} + +#[derive(Deserialize)] +pub struct AckRequest { + pub ack_seq: u64, + pub device_type: Option, +} + +/// `POST /api/rooms/:room_id/ack` +pub async fn ack_messages( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> StatusCode { + let direction = match body.device_type.as_deref() { + Some("desktop") => MessageDirection::ToDesktop, + _ => MessageDirection::ToMobile, + }; + state + .room_manager + .ack_messages(&room_id, direction, body.ack_seq); + StatusCode::OK +} + +// ── Per-room mobile-web upload & serving ─────────────────────────────────── + +#[derive(Deserialize)] +pub struct UploadWebRequest { + pub files: HashMap, +} + +/// `POST /api/rooms/:room_id/upload-web` +/// +/// Desktop uploads mobile-web dist files (base64-encoded) so the mobile +/// browser can load the exact same version the desktop is running. +/// Now uses the global content store + symlinks to avoid storing duplicates. +pub async fn upload_web( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> Result, StatusCode> { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + + if !state.room_manager.room_exists(&room_id) { + return Err(StatusCode::NOT_FOUND); + } + + let store_dir = std::path::PathBuf::from(&state.room_web_dir).join("_store"); + let _ = std::fs::create_dir_all(&store_dir); + + let room_dir = std::path::PathBuf::from(&state.room_web_dir).join(&room_id); + if let Err(e) = std::fs::create_dir_all(&room_dir) { + tracing::error!("Failed to create room web dir {}: {e}", room_dir.display()); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + + let mut written = 0usize; + let mut reused = 0usize; + for (rel_path, b64_content) in &body.files { + if rel_path.contains("..") { + continue; + } + let decoded = B64.decode(b64_content).map_err(|_| StatusCode::BAD_REQUEST)?; + let hash = hex_sha256(&decoded); + + let store_path = store_dir.join(&hash); + if !store_path.exists() { + std::fs::write(&store_path, &decoded) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + state.content_store.insert(hash.clone(), decoded.len() as u64); + written += 1; + } else { + reused += 1; + } + + let dest = room_dir.join(rel_path); + if let Some(parent) = dest.parent() { + let _ = std::fs::create_dir_all(parent); + } + let _ = std::fs::remove_file(&dest); + create_link(&store_path, &dest) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + } + + tracing::info!( + "Room {room_id}: upload-web complete (new={written}, reused={reused})" + ); + Ok(Json(serde_json::json!({ + "status": "ok", + "files_written": written, + "files_reused": reused + }))) +} + +// ── Incremental upload protocol ──────────────────────────────────────────── + +#[derive(Deserialize)] +pub struct FileManifestEntry { + pub path: String, + pub hash: String, + #[allow(dead_code)] + pub size: u64, +} + +#[derive(Deserialize)] +pub struct CheckWebFilesRequest { + pub files: Vec, +} + +#[derive(Serialize)] +pub struct CheckWebFilesResponse { + pub needed: Vec, + pub existing_count: usize, + pub total_count: usize, +} + +/// `POST /api/rooms/:room_id/check-web-files` +/// +/// Accepts a manifest of file metadata (path, sha256, size). Registers the +/// room's file manifest and returns which files the server still needs. Files +/// whose hash already exists in the global content store are skipped. +pub async fn check_web_files( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> Result, StatusCode> { + if !state.room_manager.room_exists(&room_id) { + return Err(StatusCode::NOT_FOUND); + } + + let store_dir = std::path::PathBuf::from(&state.room_web_dir).join("_store"); + let _ = std::fs::create_dir_all(&store_dir); + + let room_dir = std::path::PathBuf::from(&state.room_web_dir).join(&room_id); + let _ = std::fs::create_dir_all(&room_dir); + + let mut needed = Vec::new(); + let mut existing_count = 0usize; + let total_count = body.files.len(); + + for entry in &body.files { + if entry.path.contains("..") { + continue; + } + if state.content_store.contains(&entry.hash) { + existing_count += 1; + let store_path = store_dir.join(&entry.hash); + let dest = room_dir.join(&entry.path); + if let Some(parent) = dest.parent() { + let _ = std::fs::create_dir_all(parent); + } + let _ = std::fs::remove_file(&dest); + let _ = create_link(&store_path, &dest); + } else { + needed.push(entry.path.clone()); + } + } + + tracing::info!( + "Room {room_id}: check-web-files total={total_count}, existing={existing_count}, needed={}", + needed.len() + ); + + Ok(Json(CheckWebFilesResponse { + needed, + existing_count, + total_count, + })) +} + +#[derive(Deserialize)] +pub struct UploadWebFilesEntry { + pub content: String, + pub hash: String, +} + +#[derive(Deserialize)] +pub struct UploadWebFilesRequest { + pub files: HashMap, +} + +/// `POST /api/rooms/:room_id/upload-web-files` +/// +/// Upload only the files that the server requested via `check-web-files`. +/// Each entry includes the base64 content and its expected sha256 hash. +/// Files are stored in the global content store and symlinked into the room. +pub async fn upload_web_files( + State(state): State, + Path(room_id): Path, + Json(body): Json, +) -> Result, StatusCode> { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + + if !state.room_manager.room_exists(&room_id) { + return Err(StatusCode::NOT_FOUND); + } + + let store_dir = std::path::PathBuf::from(&state.room_web_dir).join("_store"); + let _ = std::fs::create_dir_all(&store_dir); + + let room_dir = std::path::PathBuf::from(&state.room_web_dir).join(&room_id); + let _ = std::fs::create_dir_all(&room_dir); + + let mut stored = 0usize; + for (rel_path, entry) in &body.files { + if rel_path.contains("..") { + continue; + } + let decoded = B64.decode(&entry.content).map_err(|_| StatusCode::BAD_REQUEST)?; + let actual_hash = hex_sha256(&decoded); + if actual_hash != entry.hash { + tracing::warn!( + "Room {room_id}: hash mismatch for {rel_path} (expected={}, actual={actual_hash})", + entry.hash + ); + return Err(StatusCode::BAD_REQUEST); + } + + let store_path = store_dir.join(&actual_hash); + if !store_path.exists() { + std::fs::write(&store_path, &decoded) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + state + .content_store + .insert(actual_hash.clone(), decoded.len() as u64); + } + + let dest = room_dir.join(rel_path); + if let Some(parent) = dest.parent() { + let _ = std::fs::create_dir_all(parent); + } + let _ = std::fs::remove_file(&dest); + create_link(&store_path, &dest) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + stored += 1; + } + + tracing::info!("Room {room_id}: upload-web-files stored {stored} new files"); + Ok(Json(serde_json::json!({ "status": "ok", "files_stored": stored }))) +} + +fn hex_sha256(data: &[u8]) -> String { + let mut hasher = Sha256::new(); + hasher.update(data); + format!("{:x}", hasher.finalize()) +} + +/// Create a symlink (Unix) or hard link fallback (Windows). +fn create_link( + original: &std::path::Path, + link: &std::path::Path, +) -> std::io::Result<()> { + #[cfg(unix)] + { + std::os::unix::fs::symlink(original, link) + } + #[cfg(not(unix))] + { + std::fs::hard_link(original, link) + .or_else(|_| std::fs::copy(original, link).map(|_| ())) + } +} + +/// `GET /r/{*rest}` — serve per-room mobile-web static files. +/// +/// The `rest` path is expected to be `room_id` or `room_id/file/path`. +/// Falls back to `index.html` for SPA routing. +pub async fn serve_room_web_catchall( + State(state): State, + Path(rest): Path, +) -> Result { + use axum::body::Body; + use axum::http::header; + use axum::response::IntoResponse; + + let rest = rest.trim_start_matches('/'); + let (room_id, file_path) = match rest.find('/') { + Some(idx) => (&rest[..idx], &rest[idx + 1..]), + None => (rest, ""), + }; + + if room_id.is_empty() { + return Err(StatusCode::NOT_FOUND); + } + + let room_dir = std::path::PathBuf::from(&state.room_web_dir).join(room_id); + if !room_dir.exists() { + return Err(StatusCode::NOT_FOUND); + } + + let target = if file_path.is_empty() { + room_dir.join("index.html") + } else { + room_dir.join(file_path) + }; + + let file = if target.is_file() { + target + } else { + room_dir.join("index.html") + }; + + if !file.is_file() { + return Err(StatusCode::NOT_FOUND); + } + + let content = std::fs::read(&file).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + let mime = mime_from_path(&file); + + Ok(([(header::CONTENT_TYPE, mime)], Body::from(content)).into_response()) +} + +fn mime_from_path(p: &std::path::Path) -> &'static str { + match p.extension().and_then(|e| e.to_str()) { + Some("html") => "text/html; charset=utf-8", + Some("js") => "application/javascript; charset=utf-8", + Some("css") => "text/css; charset=utf-8", + Some("json") => "application/json", + Some("png") => "image/png", + Some("svg") => "image/svg+xml", + Some("ico") => "image/x-icon", + Some("woff2") => "font/woff2", + Some("woff") => "font/woff", + Some("ttf") => "font/ttf", + Some("wasm") => "application/wasm", + _ => "application/octet-stream", + } +} + +/// Remove the per-room web directory (called on room cleanup). +pub fn cleanup_room_web(room_web_dir: &str, room_id: &str) { + let dir = std::path::PathBuf::from(room_web_dir).join(room_id); + if dir.exists() { + if let Err(e) = std::fs::remove_dir_all(&dir) { + tracing::warn!("Failed to clean up room web dir {}: {e}", dir.display()); + } else { + tracing::info!("Cleaned up room web dir for {room_id}"); + } + } +} diff --git a/src/apps/relay-server/src/routes/mod.rs b/src/apps/relay-server/src/routes/mod.rs new file mode 100644 index 00000000..ae5fb74d --- /dev/null +++ b/src/apps/relay-server/src/routes/mod.rs @@ -0,0 +1,4 @@ +//! HTTP and WebSocket routes for the relay server. + +pub mod api; +pub mod websocket; diff --git a/src/apps/relay-server/src/routes/websocket.rs b/src/apps/relay-server/src/routes/websocket.rs new file mode 100644 index 00000000..bfc80e70 --- /dev/null +++ b/src/apps/relay-server/src/routes/websocket.rs @@ -0,0 +1,218 @@ +//! WebSocket handler for the relay server. +//! +//! Each connected client sends/receives JSON messages following the relay protocol. +//! The server never decrypts application data — it only handles room management +//! and forwards encrypted payloads between paired devices. +//! Desktop→mobile messages are also buffered for later polling. + +use axum::{ + extract::{ + ws::{Message, WebSocket, WebSocketUpgrade}, + State, + }, + response::Response, +}; +use futures_util::{SinkExt, StreamExt}; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::mpsc; +use tracing::{debug, error, info, warn}; + +use crate::relay::room::{ConnId, OutboundMessage, RoomManager}; +use crate::routes::api::AppState; + +#[derive(Debug, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +#[allow(dead_code)] +pub enum InboundMessage { + CreateRoom { + room_id: Option, + device_id: String, + device_type: String, + public_key: String, + }, + JoinRoom { + room_id: String, + device_id: String, + device_type: String, + public_key: String, + }, + Relay { + room_id: String, + encrypted_data: String, + nonce: String, + }, + Heartbeat, +} + +#[derive(Debug, Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +#[allow(dead_code)] +pub enum OutboundProtocol { + RoomCreated { room_id: String }, + PeerJoined { device_id: String, device_type: String, public_key: String }, + Relay { room_id: String, encrypted_data: String, nonce: String }, + HeartbeatAck, + PeerDisconnected { device_id: String }, + Error { message: String }, +} + +pub async fn websocket_handler( + ws: WebSocketUpgrade, + State(state): State, +) -> Response { + ws.on_upgrade(move |socket| handle_socket(socket, state)) +} + +async fn handle_socket(socket: WebSocket, state: AppState) { + let (mut ws_sender, mut ws_receiver) = socket.split(); + let (out_tx, mut out_rx) = mpsc::unbounded_channel::(); + + let conn_id = state.room_manager.next_conn_id(); + info!("WebSocket connected: conn_id={conn_id}"); + + let write_task = tokio::spawn(async move { + while let Some(msg) = out_rx.recv().await { + if !msg.text.is_empty() { + if ws_sender.send(Message::Text(msg.text)).await.is_err() { + break; + } + } + } + }); + + while let Some(msg_result) = ws_receiver.next().await { + match msg_result { + Ok(Message::Text(text)) => { + handle_text_message(&text, conn_id, &state.room_manager, &out_tx); + } + Ok(Message::Ping(_)) => { + // Axum auto-replies Pong for Ping frames + } + Ok(Message::Close(_)) => { + info!("WebSocket close from conn_id={conn_id}"); + break; + } + Err(e) => { + error!("WebSocket error conn_id={conn_id}: {e}"); + break; + } + _ => {} + } + } + + state.room_manager.on_disconnect(conn_id); + drop(out_tx); + let _ = write_task.await; + info!("WebSocket disconnected: conn_id={conn_id}"); +} + +fn handle_text_message( + text: &str, + conn_id: ConnId, + room_manager: &Arc, + out_tx: &mpsc::UnboundedSender, +) { + debug!("Received from conn_id={conn_id}: {}", &text[..text.len().min(200)]); + let msg: InboundMessage = match serde_json::from_str(text) { + Ok(m) => m, + Err(e) => { + warn!("Invalid message from conn_id={conn_id}: {e}"); + send_json(out_tx, &OutboundProtocol::Error { + message: format!("invalid message format: {e}"), + }); + return; + } + }; + + match msg { + InboundMessage::CreateRoom { + room_id, + device_id, + device_type, + public_key, + } => { + let room_id = room_id.unwrap_or_else(generate_room_id); + let ok = room_manager.create_room( + &room_id, conn_id, &device_id, &device_type, &public_key, Some(out_tx.clone()), + ); + if ok { + send_json(out_tx, &OutboundProtocol::RoomCreated { room_id }); + } else { + send_json(out_tx, &OutboundProtocol::Error { + message: "failed to create room".into(), + }); + } + } + + InboundMessage::JoinRoom { + room_id, + device_id, + device_type, + public_key, + } => { + let existing_peer = room_manager.get_peer_info(&room_id, conn_id); + + let ok = room_manager.join_room( + &room_id, conn_id, &device_id, &device_type, &public_key, Some(out_tx.clone()), + ); + + if ok { + let joiner_notification = serde_json::to_string(&OutboundProtocol::PeerJoined { + device_id: device_id.clone(), + device_type: device_type.clone(), + public_key: public_key.clone(), + }).unwrap_or_default(); + room_manager.send_to_others_in_room(&room_id, conn_id, &joiner_notification); + + if let Some((peer_did, peer_dt, peer_pk)) = existing_peer { + send_json(out_tx, &OutboundProtocol::PeerJoined { + device_id: peer_did, + device_type: peer_dt, + public_key: peer_pk, + }); + } else { + warn!("No existing peer found for room {room_id} to send back to joiner"); + } + } else { + send_json(out_tx, &OutboundProtocol::Error { + message: format!("failed to join room {room_id}"), + }); + } + } + + InboundMessage::Relay { + room_id: _, + encrypted_data, + nonce, + } => { + debug!("Relay message from conn_id={conn_id} data_len={}", encrypted_data.len()); + if room_manager.relay_message(conn_id, &encrypted_data, &nonce) { + debug!("Relay message forwarded from conn_id={conn_id}"); + } else { + warn!("Relay failed for conn_id={conn_id}: no peer found"); + } + } + + InboundMessage::Heartbeat => { + if room_manager.heartbeat(conn_id) { + send_json(out_tx, &OutboundProtocol::HeartbeatAck); + } else { + send_json(out_tx, &OutboundProtocol::Error { + message: "Room not found or expired".into(), + }); + } + } + } +} + +fn send_json(tx: &mpsc::UnboundedSender, msg: &T) { + if let Ok(json) = serde_json::to_string(msg) { + let _ = tx.send(OutboundMessage { text: json }); + } +} + +fn generate_room_id() -> String { + let bytes: [u8; 6] = rand::random(); + bytes.iter().map(|b| format!("{b:02x}")).collect() +} diff --git a/src/apps/relay-server/static/assets/index-C-fgJuft.css b/src/apps/relay-server/static/assets/index-C-fgJuft.css new file mode 100644 index 00000000..ddb321f6 --- /dev/null +++ b/src/apps/relay-server/static/assets/index-C-fgJuft.css @@ -0,0 +1 @@ +:root{--bg-primary: #0f0f1a;--bg-secondary: #1a1a2e;--bg-card: #222240;--text-primary: #e0e0e0;--text-muted: #888;--accent: #6c63ff;--danger: #ff4757;--border: #333355;--radius: 10px}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{height:100%;width:100%;overflow:hidden}.mobile-app{height:100%;width:100%;background:var(--bg-primary);color:var(--text-primary);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;display:flex;flex-direction:column}.pairing-page{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:24px;padding:32px}.pairing-page__logo{font-size:28px;font-weight:700;color:var(--accent)}.pairing-page__state{font-size:14px;color:var(--text-muted)}.pairing-page__error{font-size:13px;color:var(--danger);text-align:center;max-width:280px}.pairing-page__retry{margin-top:16px;padding:10px 32px;background:var(--accent);color:#fff;border:none;border-radius:8px;font-size:15px;cursor:pointer}.pairing-page__retry:active{opacity:.8}.spinner{width:32px;height:32px;border:3px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.workspace-page{display:flex;flex-direction:column;height:100%}.workspace-page__header{display:flex;align-items:center;padding:16px 20px;border-bottom:1px solid var(--border)}.workspace-page__header h1{font-size:18px;font-weight:600}.workspace-page__content{flex:1;overflow-y:auto;padding:20px;-webkit-overflow-scrolling:touch}.workspace-page__loading{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:16px;color:var(--text-muted);font-size:14px}.workspace-page__current{display:flex;flex-direction:column;gap:16px}.workspace-page__current-label,.workspace-page__recent-label{font-size:12px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.workspace-page__current-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px}.workspace-page__project-name{font-size:17px;font-weight:600;margin-bottom:6px}.workspace-page__project-path{font-size:12px;color:var(--text-muted);word-break:break-all;margin-bottom:8px}.workspace-page__git-branch{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--accent);background:#6c63ff26;padding:2px 8px;border-radius:4px}.workspace-page__branch-icon{font-size:14px}.workspace-page__actions{display:flex;gap:10px}.workspace-page__btn{flex:1;padding:12px 16px;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer}.workspace-page__btn--primary{background:var(--accent);color:#fff}.workspace-page__btn--secondary{background:var(--bg-card);color:var(--text-primary);border:1px solid var(--border)}.workspace-page__btn:disabled{opacity:.5;cursor:not-allowed}.workspace-page__no-workspace{display:flex;flex-direction:column;align-items:center;text-align:center;padding:40px 20px;gap:12px}.workspace-page__no-workspace-icon{font-size:40px}.workspace-page__no-workspace-text{font-size:15px;font-weight:500}.workspace-page__no-workspace-hint{font-size:13px;color:var(--text-muted);max-width:280px}.workspace-page__recent{margin-top:20px;display:flex;flex-direction:column;gap:10px}.workspace-page__recent-empty{text-align:center;color:var(--text-muted);font-size:13px;padding:24px 0}.workspace-page__recent-list{display:flex;flex-direction:column;gap:6px}.workspace-page__recent-item{display:flex;flex-direction:column;align-items:flex-start;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;cursor:pointer;text-align:left;color:var(--text-primary);transition:background .15s}.workspace-page__recent-item:active{background:var(--bg-secondary)}.workspace-page__recent-item:disabled{opacity:.5;cursor:not-allowed}.workspace-page__recent-item-name{font-size:14px;font-weight:500;margin-bottom:4px}.workspace-page__recent-item-path{font-size:11px;color:var(--text-muted);word-break:break-all}.workspace-page__switching{display:flex;align-items:center;justify-content:center;gap:10px;padding:16px;color:var(--text-muted);font-size:13px}.workspace-page__error{margin-top:12px;font-size:13px;color:var(--danger);text-align:center}.session-list{display:flex;flex-direction:column;height:100%}.session-list__header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--border)}.session-list__header h1{font-size:18px;font-weight:600}.session-list__new-wrapper{position:relative}.session-list__new-btn{background:var(--accent);color:#fff;border:none;border-radius:6px;padding:6px 16px;font-size:13px;font-weight:500;cursor:pointer}.session-list__new-menu{position:absolute;top:100%;right:0;margin-top:6px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;overflow:hidden;z-index:10;min-width:180px;box-shadow:0 8px 24px #0006}.session-list__menu-item{display:flex;align-items:center;gap:10px;width:100%;padding:12px 16px;background:none;border:none;border-bottom:1px solid var(--border);color:var(--text-primary);font-size:14px;cursor:pointer;text-align:left}.session-list__menu-item:last-child{border-bottom:none}.session-list__menu-item:active{background:var(--bg-secondary)}.session-list__menu-icon{font-family:monospace;font-size:14px;color:var(--accent);min-width:28px;text-align:center}.session-list__workspace-bar{display:flex;align-items:center;gap:6px;padding:8px 20px;background:var(--bg-secondary);border-bottom:1px solid var(--border);cursor:pointer;min-height:36px;transition:background .15s}.session-list__workspace-bar:active{background:var(--bg-card)}.session-list__workspace-icon{font-size:13px;flex-shrink:0}.session-list__workspace-name{font-size:12px;font-weight:500;color:var(--accent);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__workspace-branch{font-size:11px;color:var(--text-muted);background:#6c63ff1a;padding:1px 6px;border-radius:4px;flex-shrink:0;max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.session-list__workspace-switch{font-size:11px;color:var(--text-muted);flex-shrink:0}.session-list__items{flex:1;overflow-y:auto;padding:8px 0;-webkit-overflow-scrolling:touch}.session-list__empty{text-align:center;color:var(--text-muted);padding:48px 20px;font-size:14px}.session-list__item{padding:14px 20px;border-bottom:1px solid var(--border);cursor:pointer;transition:background .15s}.session-list__item:active{background:var(--bg-secondary)}.session-list__item-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.session-list__item-name{font-size:15px;font-weight:500;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px}.session-list__agent-badge{font-size:11px;font-weight:600;padding:2px 8px;border-radius:4px;background:var(--bg-secondary);color:var(--text-muted);flex-shrink:0}.session-list__agent-badge--code,.session-list__agent-badge--agentic{background:#6c63ff33;color:var(--accent)}.session-list__agent-badge--cowork,.session-list__agent-badge--Cowork{background:#2ed57333;color:#2ed573}.session-list__item-meta{font-size:12px;color:var(--text-muted);display:flex;justify-content:space-between}.session-list__item-time{flex-shrink:0}.session-list__load-more{text-align:center;font-size:12px;color:var(--text-muted);padding:12px 0}.session-list__refresh{padding:12px;background:var(--bg-secondary);color:var(--text-muted);border:none;border-top:1px solid var(--border);font-size:13px;cursor:pointer}.chat-page{display:flex;flex-direction:column;height:100%}.chat-page__header{display:flex;align-items:center;padding:12px 16px;border-bottom:1px solid var(--border);gap:12px}.chat-page__back{background:none;border:none;color:var(--accent);font-size:20px;cursor:pointer;padding:4px}.chat-page__title{flex:1;font-size:16px;font-weight:600}.chat-page__cancel{background:var(--danger);color:#fff;border:none;border-radius:6px;padding:4px 12px;font-size:12px;cursor:pointer}.chat-page__messages{flex:1;overflow-y:auto;padding:12px 16px;-webkit-overflow-scrolling:touch}.chat-msg{margin-bottom:16px}.chat-msg__role{font-size:11px;font-weight:600;color:var(--text-muted);margin-bottom:4px;text-transform:uppercase}.chat-msg--user .chat-msg__content{background:var(--accent);color:#fff;border-radius:var(--radius) var(--radius) 4px var(--radius);padding:10px 14px;font-size:14px;line-height:1.5;display:inline-block;max-width:85%}.chat-msg--assistant .chat-msg__content{background:var(--bg-card);border-radius:var(--radius) var(--radius) var(--radius) 4px;padding:10px 14px;font-size:14px;line-height:1.6;word-break:break-word;overflow-wrap:break-word}.chat-msg--assistant .chat-msg__content code{background:#ffffff1a;padding:2px 5px;border-radius:4px;font-size:12px;font-family:Fira Code,JetBrains Mono,Consolas,monospace}.chat-msg--assistant .chat-msg__content pre{margin:8px 0;border-radius:8px;overflow-x:auto;-webkit-overflow-scrolling:touch}.chat-msg--assistant .chat-msg__content pre code{background:none;padding:0;font-size:12px}.chat-msg--assistant .chat-msg__content p{margin-bottom:8px}.chat-msg--assistant .chat-msg__content p:last-child{margin-bottom:0}.chat-msg--assistant .chat-msg__content ul,.chat-msg--assistant .chat-msg__content ol{padding-left:20px;margin-bottom:8px}.chat-msg--assistant .chat-msg__content ul li,.chat-msg--assistant .chat-msg__content ol li{margin-bottom:4px}.chat-msg--assistant .chat-msg__content h1,.chat-msg--assistant .chat-msg__content h2,.chat-msg--assistant .chat-msg__content h3,.chat-msg--assistant .chat-msg__content h4,.chat-msg--assistant .chat-msg__content h5,.chat-msg--assistant .chat-msg__content h6{color:var(--text-primary);font-weight:600;margin-top:12px;margin-bottom:6px;line-height:1.3}.chat-msg--assistant .chat-msg__content h1:first-child,.chat-msg--assistant .chat-msg__content h2:first-child,.chat-msg--assistant .chat-msg__content h3:first-child,.chat-msg--assistant .chat-msg__content h4:first-child,.chat-msg--assistant .chat-msg__content h5:first-child,.chat-msg--assistant .chat-msg__content h6:first-child{margin-top:0}.chat-msg--assistant .chat-msg__content h1{font-size:18px}.chat-msg--assistant .chat-msg__content h2{font-size:16px}.chat-msg--assistant .chat-msg__content h3{font-size:15px}.chat-msg--assistant .chat-msg__content h4,.chat-msg--assistant .chat-msg__content h5,.chat-msg--assistant .chat-msg__content h6{font-size:14px}.chat-msg--assistant .chat-msg__content blockquote{border-left:3px solid var(--accent);margin:8px 0;padding:6px 12px;background:#6c63ff14;border-radius:0 4px 4px 0;color:var(--text-muted);font-style:italic}.chat-msg--assistant .chat-msg__content blockquote p{margin-bottom:0}.chat-msg--assistant .chat-msg__content a{color:var(--accent);text-decoration:none;word-break:break-all}.chat-msg--assistant .chat-msg__content a:active{text-decoration:underline}.chat-msg--assistant .chat-msg__content hr{border:none;border-top:1px solid var(--border);margin:12px 0}.chat-msg--assistant .chat-msg__content strong{font-weight:600;color:var(--text-primary)}.chat-msg--assistant .chat-msg__content em{font-style:italic}.chat-msg--assistant .chat-msg__content del{color:var(--text-muted)}.chat-msg--assistant .chat-msg__content table{width:100%;border-collapse:collapse;margin:8px 0;font-size:13px;display:block;overflow-x:auto;-webkit-overflow-scrolling:touch}.chat-msg--assistant .chat-msg__content thead{background:#6c63ff26}.chat-msg--assistant .chat-msg__content th,.chat-msg--assistant .chat-msg__content td{border:1px solid var(--border);padding:6px 10px;text-align:left;white-space:nowrap}.chat-msg--assistant .chat-msg__content th{font-weight:600;color:var(--text-primary)}.chat-msg--assistant .chat-msg__content td{color:var(--text-primary)}.chat-msg--assistant .chat-msg__content tbody tr:nth-child(2n){background:#ffffff08}.chat-msg--assistant .chat-msg__content input[type=checkbox]{margin-right:6px;accent-color:var(--accent)}.chat-msg__thinking{margin-bottom:8px;border-left:2px solid var(--accent);padding-left:8px}.chat-msg__thinking-toggle{background:none;border:none;color:var(--text-muted);font-size:12px;cursor:pointer;padding:2px 0;font-style:italic}.chat-msg__thinking-toggle:hover{color:var(--text-primary)}.chat-msg__thinking-content{margin-top:6px;font-size:12px;color:var(--text-muted);line-height:1.5;white-space:pre-wrap}.chat-msg__tools{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px}.chat-msg__tool-badge{font-size:11px;padding:2px 8px;border-radius:12px;white-space:nowrap}.chat-msg__tool-badge--running{background:#ffb40026;color:#ffb400;border:1px solid rgba(255,180,0,.3)}.chat-msg__tool-badge--done{background:#50c87826;color:#50c878;border:1px solid rgba(80,200,120,.3)}.chat-msg__tool-badge--error{background:#ff505026;color:#ff5050;border:1px solid rgba(255,80,80,.3)}.chat-msg__typing{display:inline-block;letter-spacing:4px;color:var(--text-muted);font-size:16px;animation:typing-pulse 1.2s ease-in-out infinite}@keyframes typing-pulse{0%,to{opacity:.3}50%{opacity:1}}.chat-page__input-bar{display:flex;align-items:flex-end;padding:10px 12px;border-top:1px solid var(--border);background:var(--bg-secondary);gap:8px}.chat-page__input{flex:1;background:var(--bg-primary);border:1px solid var(--border);border-radius:8px;color:var(--text-primary);font-size:14px;padding:10px 14px;resize:none;min-height:40px;max-height:120px;outline:none;font-family:inherit}.chat-page__input:focus{border-color:var(--accent)}.chat-page__send{background:var(--accent);color:#fff;border:none;border-radius:8px;padding:10px 16px;font-size:14px;font-weight:500;cursor:pointer;white-space:nowrap}.chat-page__send:disabled{opacity:.5;cursor:not-allowed} diff --git a/src/apps/relay-server/static/assets/index-RWXIAc4-.js b/src/apps/relay-server/static/assets/index-RWXIAc4-.js new file mode 100644 index 00000000..d9a6227e --- /dev/null +++ b/src/apps/relay-server/static/assets/index-RWXIAc4-.js @@ -0,0 +1,99 @@ +var rI=Object.defineProperty;var aI=(e,t,n)=>t in e?rI(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var se=(e,t,n)=>aI(e,typeof t!="symbol"?t+"":t,n);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))r(a);new MutationObserver(a=>{for(const i of a)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(a){const i={};return a.integrity&&(i.integrity=a.integrity),a.referrerPolicy&&(i.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?i.credentials="include":a.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function r(a){if(a.ep)return;a.ep=!0;const i=n(a);fetch(a.href,i)}})();var Tn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Wa(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Lw={exports:{}},To={},Dw={exports:{}},te={};/** + * @license React + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Ya=Symbol.for("react.element"),iI=Symbol.for("react.portal"),oI=Symbol.for("react.fragment"),sI=Symbol.for("react.strict_mode"),lI=Symbol.for("react.profiler"),uI=Symbol.for("react.provider"),cI=Symbol.for("react.context"),dI=Symbol.for("react.forward_ref"),pI=Symbol.for("react.suspense"),fI=Symbol.for("react.memo"),gI=Symbol.for("react.lazy"),Xm=Symbol.iterator;function mI(e){return e===null||typeof e!="object"?null:(e=Xm&&e[Xm]||e["@@iterator"],typeof e=="function"?e:null)}var Mw={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Fw=Object.assign,Pw={};function Ur(e,t,n){this.props=e,this.context=t,this.refs=Pw,this.updater=n||Mw}Ur.prototype.isReactComponent={};Ur.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};Ur.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function Uw(){}Uw.prototype=Ur.prototype;function lg(e,t,n){this.props=e,this.context=t,this.refs=Pw,this.updater=n||Mw}var ug=lg.prototype=new Uw;ug.constructor=lg;Fw(ug,Ur.prototype);ug.isPureReactComponent=!0;var Zm=Array.isArray,Bw=Object.prototype.hasOwnProperty,cg={current:null},$w={key:!0,ref:!0,__self:!0,__source:!0};function zw(e,t,n){var r,a={},i=null,o=null;if(t!=null)for(r in t.ref!==void 0&&(o=t.ref),t.key!==void 0&&(i=""+t.key),t)Bw.call(t,r)&&!$w.hasOwnProperty(r)&&(a[r]=t[r]);var s=arguments.length-2;if(s===1)a.children=n;else if(1>>1,G=x[P];if(0>>1;Pa(ue,S))Za(ce,ue)?(x[P]=ce,x[Z]=S,P=Z):(x[P]=ue,x[Q]=S,P=Q);else if(Za(ce,S))x[P]=ce,x[Z]=S,P=Z;else break e}}return M}function a(x,M){var S=x.sortIndex-M.sortIndex;return S!==0?S:x.id-M.id}if(typeof performance=="object"&&typeof performance.now=="function"){var i=performance;e.unstable_now=function(){return i.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var l=[],u=[],d=1,c=null,f=3,p=!1,h=!1,y=!1,T=typeof setTimeout=="function"?setTimeout:null,b=typeof clearTimeout=="function"?clearTimeout:null,g=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function m(x){for(var M=n(u);M!==null;){if(M.callback===null)r(u);else if(M.startTime<=x)r(u),M.sortIndex=M.expirationTime,t(l,M);else break;M=n(u)}}function v(x){if(y=!1,m(x),!h)if(n(l)!==null)h=!0,H(_);else{var M=n(u);M!==null&&Y(v,M.startTime-x)}}function _(x,M){h=!1,y&&(y=!1,b(C),C=-1),p=!0;var S=f;try{for(m(M),c=n(l);c!==null&&(!(c.expirationTime>M)||x&&!I());){var P=c.callback;if(typeof P=="function"){c.callback=null,f=c.priorityLevel;var G=P(c.expirationTime<=M);M=e.unstable_now(),typeof G=="function"?c.callback=G:c===n(l)&&r(l),m(M)}else r(l);c=n(l)}if(c!==null)var A=!0;else{var Q=n(u);Q!==null&&Y(v,Q.startTime-M),A=!1}return A}finally{c=null,f=S,p=!1}}var E=!1,R=null,C=-1,N=5,k=-1;function I(){return!(e.unstable_now()-kx||125P?(x.sortIndex=S,t(u,x),n(l)===null&&x===n(u)&&(y?(b(C),C=-1):y=!0,Y(v,S-P))):(x.sortIndex=G,t(l,x),h||p||(h=!0,H(_))),x},e.unstable_shouldYield=I,e.unstable_wrapCallback=function(x){var M=f;return function(){var S=f;f=M;try{return x.apply(this,arguments)}finally{f=S}}}})(Vw);Hw.exports=Vw;var AI=Hw.exports;/** + * @license React + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var RI=W,ct=AI;function F(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Yp=Object.prototype.hasOwnProperty,II=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,Jm={},eh={};function CI(e){return Yp.call(eh,e)?!0:Yp.call(Jm,e)?!1:II.test(e)?eh[e]=!0:(Jm[e]=!0,!1)}function NI(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function xI(e,t,n,r){if(t===null||typeof t>"u"||NI(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function He(e,t,n,r,a,i,o){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=a,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=i,this.removeEmptyString=o}var Oe={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){Oe[e]=new He(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];Oe[t]=new He(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){Oe[e]=new He(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){Oe[e]=new He(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){Oe[e]=new He(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){Oe[e]=new He(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){Oe[e]=new He(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){Oe[e]=new He(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){Oe[e]=new He(e,5,!1,e.toLowerCase(),null,!1,!1)});var pg=/[\-:]([a-z])/g;function fg(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(pg,fg);Oe[t]=new He(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(pg,fg);Oe[t]=new He(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(pg,fg);Oe[t]=new He(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){Oe[e]=new He(e,1,!1,e.toLowerCase(),null,!1,!1)});Oe.xlinkHref=new He("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){Oe[e]=new He(e,1,!1,e.toLowerCase(),null,!0,!0)});function gg(e,t,n,r){var a=Oe.hasOwnProperty(t)?Oe[t]:null;(a!==null?a.type!==0:r||!(2s||a[o]!==i[s]){var l=` +`+a[o].replace(" at new "," at ");return e.displayName&&l.includes("")&&(l=l.replace("",e.displayName)),l}while(1<=o&&0<=s);break}}}finally{ns=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?sa(e):""}function OI(e){switch(e.tag){case 5:return sa(e.type);case 16:return sa("Lazy");case 13:return sa("Suspense");case 19:return sa("SuspenseList");case 0:case 2:case 15:return e=rs(e.type,!1),e;case 11:return e=rs(e.type.render,!1),e;case 1:return e=rs(e.type,!0),e;default:return""}}function Qp(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case cr:return"Fragment";case ur:return"Portal";case Kp:return"Profiler";case mg:return"StrictMode";case Xp:return"Suspense";case Zp:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Kw:return(e.displayName||"Context")+".Consumer";case Yw:return(e._context.displayName||"Context")+".Provider";case hg:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case bg:return t=e.displayName||null,t!==null?t:Qp(e.type)||"Memo";case cn:t=e._payload,e=e._init;try{return Qp(e(t))}catch{}}return null}function LI(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Qp(t);case 8:return t===mg?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function An(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function Zw(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function DI(e){var t=Zw(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var a=n.get,i=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return a.call(this)},set:function(o){r=""+o,i.call(this,o)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(o){r=""+o},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function si(e){e._valueTracker||(e._valueTracker=DI(e))}function Qw(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=Zw(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function Yi(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Jp(e,t){var n=t.checked;return Ee({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function nh(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=An(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function Jw(e,t){t=t.checked,t!=null&&gg(e,"checked",t,!1)}function ef(e,t){Jw(e,t);var n=An(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?tf(e,t.type,n):t.hasOwnProperty("defaultValue")&&tf(e,t.type,An(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function rh(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function tf(e,t,n){(t!=="number"||Yi(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var la=Array.isArray;function kr(e,t,n,r){if(e=e.options,t){t={};for(var a=0;a"+t.valueOf().toString()+"",t=li.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function Ia(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var ga={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},MI=["Webkit","ms","Moz","O"];Object.keys(ga).forEach(function(e){MI.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),ga[t]=ga[e]})});function r_(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||ga.hasOwnProperty(e)&&ga[e]?(""+t).trim():t+"px"}function a_(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,a=r_(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,a):e[n]=a}}var FI=Ee({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function af(e,t){if(t){if(FI[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(F(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(F(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(F(61))}if(t.style!=null&&typeof t.style!="object")throw Error(F(62))}}function of(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var sf=null;function yg(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var lf=null,wr=null,_r=null;function oh(e){if(e=Za(e)){if(typeof lf!="function")throw Error(F(280));var t=e.stateNode;t&&(t=No(t),lf(e.stateNode,e.type,t))}}function i_(e){wr?_r?_r.push(e):_r=[e]:wr=e}function o_(){if(wr){var e=wr,t=_r;if(_r=wr=null,oh(e),t)for(e=0;e>>=0,e===0?32:31-(WI(e)/YI|0)|0}var ui=64,ci=4194304;function ua(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function Qi(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,a=e.suspendedLanes,i=e.pingedLanes,o=n&268435455;if(o!==0){var s=o&~a;s!==0?r=ua(s):(i&=o,i!==0&&(r=ua(i)))}else o=n&~a,o!==0?r=ua(o):i!==0&&(r=ua(i));if(r===0)return 0;if(t!==0&&t!==r&&!(t&a)&&(a=r&-r,i=t&-t,a>=i||a===16&&(i&4194240)!==0))return t;if(r&4&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Ka(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-Ct(t),e[t]=n}function QI(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=ha),mh=" ",hh=!1;function A_(e,t){switch(e){case"keyup":return AC.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function R_(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var dr=!1;function IC(e,t){switch(e){case"compositionend":return R_(t);case"keypress":return t.which!==32?null:(hh=!0,mh);case"textInput":return e=t.data,e===mh&&hh?null:e;default:return null}}function CC(e,t){if(dr)return e==="compositionend"||!Ag&&A_(e,t)?(e=__(),Mi=wg=gn=null,dr=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Sh(n)}}function x_(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?x_(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function O_(){for(var e=window,t=Yi();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=Yi(e.document)}return t}function Rg(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function UC(e){var t=O_(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&x_(n.ownerDocument.documentElement,n)){if(r!==null&&Rg(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var a=n.textContent.length,i=Math.min(r.start,a);r=r.end===void 0?i:Math.min(r.end,a),!e.extend&&i>r&&(a=r,r=i,i=a),a=vh(n,i);var o=vh(n,r);a&&o&&(e.rangeCount!==1||e.anchorNode!==a.node||e.anchorOffset!==a.offset||e.focusNode!==o.node||e.focusOffset!==o.offset)&&(t=t.createRange(),t.setStart(a.node,a.offset),e.removeAllRanges(),i>r?(e.addRange(t),e.extend(o.node,o.offset)):(t.setEnd(o.node,o.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,pr=null,gf=null,ya=null,mf=!1;function kh(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;mf||pr==null||pr!==Yi(r)||(r=pr,"selectionStart"in r&&Rg(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),ya&&Da(ya,r)||(ya=r,r=to(gf,"onSelect"),0mr||(e.current=vf[mr],vf[mr]=null,mr--)}function pe(e,t){mr++,vf[mr]=e.current,e.current=t}var Rn={},Pe=Cn(Rn),Qe=Cn(!1),jn=Rn;function Nr(e,t){var n=e.type.contextTypes;if(!n)return Rn;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var a={},i;for(i in n)a[i]=t[i];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=a),a}function Je(e){return e=e.childContextTypes,e!=null}function ro(){me(Qe),me(Pe)}function Ch(e,t,n){if(Pe.current!==Rn)throw Error(F(168));pe(Pe,t),pe(Qe,n)}function z_(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var a in r)if(!(a in t))throw Error(F(108,LI(e)||"Unknown",a));return Ee({},n,r)}function ao(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Rn,jn=Pe.current,pe(Pe,e),pe(Qe,Qe.current),!0}function Nh(e,t,n){var r=e.stateNode;if(!r)throw Error(F(169));n?(e=z_(e,t,jn),r.__reactInternalMemoizedMergedChildContext=e,me(Qe),me(Pe),pe(Pe,e)):me(Qe),pe(Qe,n)}var Wt=null,xo=!1,bs=!1;function G_(e){Wt===null?Wt=[e]:Wt.push(e)}function XC(e){xo=!0,G_(e)}function Nn(){if(!bs&&Wt!==null){bs=!0;var e=0,t=ie;try{var n=Wt;for(ie=1;e>=o,a-=o,Kt=1<<32-Ct(t)+a|n<C?(N=R,R=null):N=R.sibling;var k=f(b,R,m[C],v);if(k===null){R===null&&(R=N);break}e&&R&&k.alternate===null&&t(b,R),g=i(k,g,C),E===null?_=k:E.sibling=k,E=k,R=N}if(C===m.length)return n(b,R),he&&Fn(b,C),_;if(R===null){for(;CC?(N=R,R=null):N=R.sibling;var I=f(b,R,k.value,v);if(I===null){R===null&&(R=N);break}e&&R&&I.alternate===null&&t(b,R),g=i(I,g,C),E===null?_=I:E.sibling=I,E=I,R=N}if(k.done)return n(b,R),he&&Fn(b,C),_;if(R===null){for(;!k.done;C++,k=m.next())k=c(b,k.value,v),k!==null&&(g=i(k,g,C),E===null?_=k:E.sibling=k,E=k);return he&&Fn(b,C),_}for(R=r(b,R);!k.done;C++,k=m.next())k=p(R,b,C,k.value,v),k!==null&&(e&&k.alternate!==null&&R.delete(k.key===null?C:k.key),g=i(k,g,C),E===null?_=k:E.sibling=k,E=k);return e&&R.forEach(function(D){return t(b,D)}),he&&Fn(b,C),_}function T(b,g,m,v){if(typeof m=="object"&&m!==null&&m.type===cr&&m.key===null&&(m=m.props.children),typeof m=="object"&&m!==null){switch(m.$$typeof){case oi:e:{for(var _=m.key,E=g;E!==null;){if(E.key===_){if(_=m.type,_===cr){if(E.tag===7){n(b,E.sibling),g=a(E,m.props.children),g.return=b,b=g;break e}}else if(E.elementType===_||typeof _=="object"&&_!==null&&_.$$typeof===cn&&Lh(_)===E.type){n(b,E.sibling),g=a(E,m.props),g.ref=ea(b,E,m),g.return=b,b=g;break e}n(b,E);break}else t(b,E);E=E.sibling}m.type===cr?(g=qn(m.props.children,b.mode,v,m.key),g.return=b,b=g):(v=qi(m.type,m.key,m.props,null,b.mode,v),v.ref=ea(b,g,m),v.return=b,b=v)}return o(b);case ur:e:{for(E=m.key;g!==null;){if(g.key===E)if(g.tag===4&&g.stateNode.containerInfo===m.containerInfo&&g.stateNode.implementation===m.implementation){n(b,g.sibling),g=a(g,m.children||[]),g.return=b,b=g;break e}else{n(b,g);break}else t(b,g);g=g.sibling}g=Ts(m,b.mode,v),g.return=b,b=g}return o(b);case cn:return E=m._init,T(b,g,E(m._payload),v)}if(la(m))return h(b,g,m,v);if(Kr(m))return y(b,g,m,v);bi(b,m)}return typeof m=="string"&&m!==""||typeof m=="number"?(m=""+m,g!==null&&g.tag===6?(n(b,g.sibling),g=a(g,m),g.return=b,b=g):(n(b,g),g=_s(m,b.mode,v),g.return=b,b=g),o(b)):n(b,g)}return T}var Or=V_(!0),W_=V_(!1),so=Cn(null),lo=null,yr=null,xg=null;function Og(){xg=yr=lo=null}function Lg(e){var t=so.current;me(so),e._currentValue=t}function _f(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Ar(e,t){lo=e,xg=yr=null,e=e.dependencies,e!==null&&e.firstContext!==null&&(e.lanes&t&&(Ze=!0),e.firstContext=null)}function St(e){var t=e._currentValue;if(xg!==e)if(e={context:e,memoizedValue:t,next:null},yr===null){if(lo===null)throw Error(F(308));yr=e,lo.dependencies={lanes:0,firstContext:e}}else yr=yr.next=e;return t}var $n=null;function Dg(e){$n===null?$n=[e]:$n.push(e)}function Y_(e,t,n,r){var a=t.interleaved;return a===null?(n.next=n,Dg(t)):(n.next=a.next,a.next=n),t.interleaved=n,tn(e,r)}function tn(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var dn=!1;function Mg(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function K_(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Zt(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function vn(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,ae&2){var a=r.pending;return a===null?t.next=t:(t.next=a.next,a.next=t),r.pending=t,tn(e,n)}return a=r.interleaved,a===null?(t.next=t,Dg(r)):(t.next=a.next,a.next=t),r.interleaved=t,tn(e,n)}function Pi(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Sg(e,n)}}function Dh(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var a=null,i=null;if(n=n.firstBaseUpdate,n!==null){do{var o={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};i===null?a=i=o:i=i.next=o,n=n.next}while(n!==null);i===null?a=i=t:i=i.next=t}else a=i=t;n={baseState:r.baseState,firstBaseUpdate:a,lastBaseUpdate:i,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function uo(e,t,n,r){var a=e.updateQueue;dn=!1;var i=a.firstBaseUpdate,o=a.lastBaseUpdate,s=a.shared.pending;if(s!==null){a.shared.pending=null;var l=s,u=l.next;l.next=null,o===null?i=u:o.next=u,o=l;var d=e.alternate;d!==null&&(d=d.updateQueue,s=d.lastBaseUpdate,s!==o&&(s===null?d.firstBaseUpdate=u:s.next=u,d.lastBaseUpdate=l))}if(i!==null){var c=a.baseState;o=0,d=u=l=null,s=i;do{var f=s.lane,p=s.eventTime;if((r&f)===f){d!==null&&(d=d.next={eventTime:p,lane:0,tag:s.tag,payload:s.payload,callback:s.callback,next:null});e:{var h=e,y=s;switch(f=t,p=n,y.tag){case 1:if(h=y.payload,typeof h=="function"){c=h.call(p,c,f);break e}c=h;break e;case 3:h.flags=h.flags&-65537|128;case 0:if(h=y.payload,f=typeof h=="function"?h.call(p,c,f):h,f==null)break e;c=Ee({},c,f);break e;case 2:dn=!0}}s.callback!==null&&s.lane!==0&&(e.flags|=64,f=a.effects,f===null?a.effects=[s]:f.push(s))}else p={eventTime:p,lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},d===null?(u=d=p,l=c):d=d.next=p,o|=f;if(s=s.next,s===null){if(s=a.shared.pending,s===null)break;f=s,s=f.next,f.next=null,a.lastBaseUpdate=f,a.shared.pending=null}}while(!0);if(d===null&&(l=c),a.baseState=l,a.firstBaseUpdate=u,a.lastBaseUpdate=d,t=a.shared.interleaved,t!==null){a=t;do o|=a.lane,a=a.next;while(a!==t)}else i===null&&(a.shared.lanes=0);Wn|=o,e.lanes=o,e.memoizedState=c}}function Mh(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=Es.transition;Es.transition={};try{e(!1),t()}finally{ie=n,Es.transition=r}}function pT(){return vt().memoizedState}function eN(e,t,n){var r=wn(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},fT(e))gT(t,n);else if(n=Y_(e,t,n,r),n!==null){var a=qe();Nt(n,e,r,a),mT(n,t,r)}}function tN(e,t,n){var r=wn(e),a={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(fT(e))gT(t,a);else{var i=e.alternate;if(e.lanes===0&&(i===null||i.lanes===0)&&(i=t.lastRenderedReducer,i!==null))try{var o=t.lastRenderedState,s=i(o,n);if(a.hasEagerState=!0,a.eagerState=s,Ot(s,o)){var l=t.interleaved;l===null?(a.next=a,Dg(t)):(a.next=l.next,l.next=a),t.interleaved=a;return}}catch{}finally{}n=Y_(e,t,a,r),n!==null&&(a=qe(),Nt(n,e,r,a),mT(n,t,r))}}function fT(e){var t=e.alternate;return e===ye||t!==null&&t===ye}function gT(e,t){Ea=po=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function mT(e,t,n){if(n&4194240){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Sg(e,n)}}var fo={readContext:St,useCallback:Le,useContext:Le,useEffect:Le,useImperativeHandle:Le,useInsertionEffect:Le,useLayoutEffect:Le,useMemo:Le,useReducer:Le,useRef:Le,useState:Le,useDebugValue:Le,useDeferredValue:Le,useTransition:Le,useMutableSource:Le,useSyncExternalStore:Le,useId:Le,unstable_isNewReconciler:!1},nN={readContext:St,useCallback:function(e,t){return Dt().memoizedState=[e,t===void 0?null:t],e},useContext:St,useEffect:Ph,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,Bi(4194308,4,sT.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Bi(4194308,4,e,t)},useInsertionEffect:function(e,t){return Bi(4,2,e,t)},useMemo:function(e,t){var n=Dt();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=Dt();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=eN.bind(null,ye,e),[r.memoizedState,e]},useRef:function(e){var t=Dt();return e={current:e},t.memoizedState=e},useState:Fh,useDebugValue:qg,useDeferredValue:function(e){return Dt().memoizedState=e},useTransition:function(){var e=Fh(!1),t=e[0];return e=JC.bind(null,e[1]),Dt().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=ye,a=Dt();if(he){if(n===void 0)throw Error(F(407));n=n()}else{if(n=t(),Ce===null)throw Error(F(349));Vn&30||J_(r,t,n)}a.memoizedState=n;var i={value:n,getSnapshot:t};return a.queue=i,Ph(tT.bind(null,r,i,e),[e]),r.flags|=2048,Ga(9,eT.bind(null,r,i,n,t),void 0,null),n},useId:function(){var e=Dt(),t=Ce.identifierPrefix;if(he){var n=Xt,r=Kt;n=(r&~(1<<32-Ct(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=$a++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=o.createElement(n,{is:r.is}):(e=o.createElement(n),n==="select"&&(o=e,r.multiple?o.multiple=!0:r.size&&(o.size=r.size))):e=o.createElementNS(e,n),e[Pt]=t,e[Pa]=r,TT(e,t,!1,!1),t.stateNode=e;e:{switch(o=of(n,r),n){case"dialog":ge("cancel",e),ge("close",e),a=r;break;case"iframe":case"object":case"embed":ge("load",e),a=r;break;case"video":case"audio":for(a=0;aMr&&(t.flags|=128,r=!0,ta(i,!1),t.lanes=4194304)}else{if(!r)if(e=co(o),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),ta(i,!0),i.tail===null&&i.tailMode==="hidden"&&!o.alternate&&!he)return De(t),null}else 2*ve()-i.renderingStartTime>Mr&&n!==1073741824&&(t.flags|=128,r=!0,ta(i,!1),t.lanes=4194304);i.isBackwards?(o.sibling=t.child,t.child=o):(n=i.last,n!==null?n.sibling=o:t.child=o,i.last=o)}return i.tail!==null?(t=i.tail,i.rendering=t,i.tail=t.sibling,i.renderingStartTime=ve(),t.sibling=null,n=be.current,pe(be,r?n&1|2:n&1),t):(De(t),null);case 22:case 23:return Kg(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&t.mode&1?ot&1073741824&&(De(t),t.subtreeFlags&6&&(t.flags|=8192)):De(t),null;case 24:return null;case 25:return null}throw Error(F(156,t.tag))}function cN(e,t){switch(Cg(t),t.tag){case 1:return Je(t.type)&&ro(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Lr(),me(Qe),me(Pe),Ug(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return Pg(t),null;case 13:if(me(be),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(F(340));xr()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return me(be),null;case 4:return Lr(),null;case 10:return Lg(t.type._context),null;case 22:case 23:return Kg(),null;case 24:return null;default:return null}}var Ei=!1,Me=!1,dN=typeof WeakSet=="function"?WeakSet:Set,j=null;function Er(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){Se(e,t,r)}else n.current=null}function Lf(e,t,n){try{n()}catch(r){Se(e,t,r)}}var Yh=!1;function pN(e,t){if(hf=Ji,e=O_(),Rg(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,i=r.focusNode;r=r.focusOffset;try{n.nodeType,i.nodeType}catch{n=null;break e}var o=0,s=-1,l=-1,u=0,d=0,c=e,f=null;t:for(;;){for(var p;c!==n||a!==0&&c.nodeType!==3||(s=o+a),c!==i||r!==0&&c.nodeType!==3||(l=o+r),c.nodeType===3&&(o+=c.nodeValue.length),(p=c.firstChild)!==null;)f=c,c=p;for(;;){if(c===e)break t;if(f===n&&++u===a&&(s=o),f===i&&++d===r&&(l=o),(p=c.nextSibling)!==null)break;c=f,f=c.parentNode}c=p}n=s===-1||l===-1?null:{start:s,end:l}}else n=null}n=n||{start:0,end:0}}else n=null;for(bf={focusedElem:e,selectionRange:n},Ji=!1,j=t;j!==null;)if(t=j,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,j=e;else for(;j!==null;){t=j;try{var h=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(h!==null){var y=h.memoizedProps,T=h.memoizedState,b=t.stateNode,g=b.getSnapshotBeforeUpdate(t.elementType===t.type?y:At(t.type,y),T);b.__reactInternalSnapshotBeforeUpdate=g}break;case 3:var m=t.stateNode.containerInfo;m.nodeType===1?m.textContent="":m.nodeType===9&&m.documentElement&&m.removeChild(m.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(F(163))}}catch(v){Se(t,t.return,v)}if(e=t.sibling,e!==null){e.return=t.return,j=e;break}j=t.return}return h=Yh,Yh=!1,h}function Sa(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var a=r=r.next;do{if((a.tag&e)===e){var i=a.destroy;a.destroy=void 0,i!==void 0&&Lf(t,n,i)}a=a.next}while(a!==r)}}function Do(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function Df(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function IT(e){var t=e.alternate;t!==null&&(e.alternate=null,IT(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[Pt],delete t[Pa],delete t[Sf],delete t[YC],delete t[KC])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function CT(e){return e.tag===5||e.tag===3||e.tag===4}function Kh(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||CT(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Mf(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=no));else if(r!==4&&(e=e.child,e!==null))for(Mf(e,t,n),e=e.sibling;e!==null;)Mf(e,t,n),e=e.sibling}function Ff(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(Ff(e,t,n),e=e.sibling;e!==null;)Ff(e,t,n),e=e.sibling}var Ne=null,Rt=!1;function ln(e,t,n){for(n=n.child;n!==null;)NT(e,t,n),n=n.sibling}function NT(e,t,n){if(Bt&&typeof Bt.onCommitFiberUnmount=="function")try{Bt.onCommitFiberUnmount(Ao,n)}catch{}switch(n.tag){case 5:Me||Er(n,t);case 6:var r=Ne,a=Rt;Ne=null,ln(e,t,n),Ne=r,Rt=a,Ne!==null&&(Rt?(e=Ne,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):Ne.removeChild(n.stateNode));break;case 18:Ne!==null&&(Rt?(e=Ne,n=n.stateNode,e.nodeType===8?hs(e.parentNode,n):e.nodeType===1&&hs(e,n),Oa(e)):hs(Ne,n.stateNode));break;case 4:r=Ne,a=Rt,Ne=n.stateNode.containerInfo,Rt=!0,ln(e,t,n),Ne=r,Rt=a;break;case 0:case 11:case 14:case 15:if(!Me&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){a=r=r.next;do{var i=a,o=i.destroy;i=i.tag,o!==void 0&&(i&2||i&4)&&Lf(n,t,o),a=a.next}while(a!==r)}ln(e,t,n);break;case 1:if(!Me&&(Er(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(s){Se(n,t,s)}ln(e,t,n);break;case 21:ln(e,t,n);break;case 22:n.mode&1?(Me=(r=Me)||n.memoizedState!==null,ln(e,t,n),Me=r):ln(e,t,n);break;default:ln(e,t,n)}}function Xh(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new dN),t.forEach(function(r){var a=vN.bind(null,e,r);n.has(r)||(n.add(r),r.then(a,a))})}}function _t(e,t){var n=t.deletions;if(n!==null)for(var r=0;ra&&(a=o),r&=~i}if(r=a,r=ve()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*gN(r/1960))-r,10e?16:e,mn===null)var r=!1;else{if(e=mn,mn=null,ho=0,ae&6)throw Error(F(331));var a=ae;for(ae|=4,j=e.current;j!==null;){var i=j,o=i.child;if(j.flags&16){var s=i.deletions;if(s!==null){for(var l=0;lve()-Wg?Gn(e,0):Vg|=n),et(e,t)}function UT(e,t){t===0&&(e.mode&1?(t=ci,ci<<=1,!(ci&130023424)&&(ci=4194304)):t=1);var n=qe();e=tn(e,t),e!==null&&(Ka(e,t,n),et(e,n))}function SN(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),UT(e,n)}function vN(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(F(314))}r!==null&&r.delete(t),UT(e,n)}var BT;BT=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||Qe.current)Ze=!0;else{if(!(e.lanes&n)&&!(t.flags&128))return Ze=!1,lN(e,t,n);Ze=!!(e.flags&131072)}else Ze=!1,he&&t.flags&1048576&&q_(t,oo,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;$i(e,t),e=t.pendingProps;var a=Nr(t,Pe.current);Ar(t,n),a=$g(null,t,r,e,a,n);var i=zg();return t.flags|=1,typeof a=="object"&&a!==null&&typeof a.render=="function"&&a.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Je(r)?(i=!0,ao(t)):i=!1,t.memoizedState=a.state!==null&&a.state!==void 0?a.state:null,Mg(t),a.updater=Lo,t.stateNode=a,a._reactInternals=t,Af(t,r,e,n),t=Cf(null,t,r,!0,i,n)):(t.tag=0,he&&i&&Ig(t),ze(null,t,a,n),t=t.child),t;case 16:r=t.elementType;e:{switch($i(e,t),e=t.pendingProps,a=r._init,r=a(r._payload),t.type=r,a=t.tag=wN(r),e=At(r,e),a){case 0:t=If(null,t,r,e,n);break e;case 1:t=Hh(null,t,r,e,n);break e;case 11:t=qh(null,t,r,e,n);break e;case 14:t=jh(null,t,r,At(r.type,e),n);break e}throw Error(F(306,r,""))}return t;case 0:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:At(r,a),If(e,t,r,a,n);case 1:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:At(r,a),Hh(e,t,r,a,n);case 3:e:{if(kT(t),e===null)throw Error(F(387));r=t.pendingProps,i=t.memoizedState,a=i.element,K_(e,t),uo(t,r,null,n);var o=t.memoizedState;if(r=o.element,i.isDehydrated)if(i={element:r,isDehydrated:!1,cache:o.cache,pendingSuspenseBoundaries:o.pendingSuspenseBoundaries,transitions:o.transitions},t.updateQueue.baseState=i,t.memoizedState=i,t.flags&256){a=Dr(Error(F(423)),t),t=Vh(e,t,r,n,a);break e}else if(r!==a){a=Dr(Error(F(424)),t),t=Vh(e,t,r,n,a);break e}else for(st=Sn(t.stateNode.containerInfo.firstChild),lt=t,he=!0,It=null,n=W_(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(xr(),r===a){t=nn(e,t,n);break e}ze(e,t,r,n)}t=t.child}return t;case 5:return X_(t),e===null&&wf(t),r=t.type,a=t.pendingProps,i=e!==null?e.memoizedProps:null,o=a.children,yf(r,a)?o=null:i!==null&&yf(r,i)&&(t.flags|=32),vT(e,t),ze(e,t,o,n),t.child;case 6:return e===null&&wf(t),null;case 13:return wT(e,t,n);case 4:return Fg(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Or(t,null,r,n):ze(e,t,r,n),t.child;case 11:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:At(r,a),qh(e,t,r,a,n);case 7:return ze(e,t,t.pendingProps,n),t.child;case 8:return ze(e,t,t.pendingProps.children,n),t.child;case 12:return ze(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,a=t.pendingProps,i=t.memoizedProps,o=a.value,pe(so,r._currentValue),r._currentValue=o,i!==null)if(Ot(i.value,o)){if(i.children===a.children&&!Qe.current){t=nn(e,t,n);break e}}else for(i=t.child,i!==null&&(i.return=t);i!==null;){var s=i.dependencies;if(s!==null){o=i.child;for(var l=s.firstContext;l!==null;){if(l.context===r){if(i.tag===1){l=Zt(-1,n&-n),l.tag=2;var u=i.updateQueue;if(u!==null){u=u.shared;var d=u.pending;d===null?l.next=l:(l.next=d.next,d.next=l),u.pending=l}}i.lanes|=n,l=i.alternate,l!==null&&(l.lanes|=n),_f(i.return,n,t),s.lanes|=n;break}l=l.next}}else if(i.tag===10)o=i.type===t.type?null:i.child;else if(i.tag===18){if(o=i.return,o===null)throw Error(F(341));o.lanes|=n,s=o.alternate,s!==null&&(s.lanes|=n),_f(o,n,t),o=i.sibling}else o=i.child;if(o!==null)o.return=i;else for(o=i;o!==null;){if(o===t){o=null;break}if(i=o.sibling,i!==null){i.return=o.return,o=i;break}o=o.return}i=o}ze(e,t,a.children,n),t=t.child}return t;case 9:return a=t.type,r=t.pendingProps.children,Ar(t,n),a=St(a),r=r(a),t.flags|=1,ze(e,t,r,n),t.child;case 14:return r=t.type,a=At(r,t.pendingProps),a=At(r.type,a),jh(e,t,r,a,n);case 15:return ET(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:At(r,a),$i(e,t),t.tag=1,Je(r)?(e=!0,ao(t)):e=!1,Ar(t,n),hT(t,r,a),Af(t,r,a,n),Cf(null,t,r,!0,e,n);case 19:return _T(e,t,n);case 22:return ST(e,t,n)}throw Error(F(156,t.tag))};function $T(e,t){return f_(e,t)}function kN(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function yt(e,t,n,r){return new kN(e,t,n,r)}function Zg(e){return e=e.prototype,!(!e||!e.isReactComponent)}function wN(e){if(typeof e=="function")return Zg(e)?1:0;if(e!=null){if(e=e.$$typeof,e===hg)return 11;if(e===bg)return 14}return 2}function _n(e,t){var n=e.alternate;return n===null?(n=yt(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function qi(e,t,n,r,a,i){var o=2;if(r=e,typeof e=="function")Zg(e)&&(o=1);else if(typeof e=="string")o=5;else e:switch(e){case cr:return qn(n.children,a,i,t);case mg:o=8,a|=8;break;case Kp:return e=yt(12,n,t,a|2),e.elementType=Kp,e.lanes=i,e;case Xp:return e=yt(13,n,t,a),e.elementType=Xp,e.lanes=i,e;case Zp:return e=yt(19,n,t,a),e.elementType=Zp,e.lanes=i,e;case Xw:return Fo(n,a,i,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Yw:o=10;break e;case Kw:o=9;break e;case hg:o=11;break e;case bg:o=14;break e;case cn:o=16,r=null;break e}throw Error(F(130,e==null?e:typeof e,""))}return t=yt(o,n,t,a),t.elementType=e,t.type=r,t.lanes=i,t}function qn(e,t,n,r){return e=yt(7,e,r,t),e.lanes=n,e}function Fo(e,t,n,r){return e=yt(22,e,r,t),e.elementType=Xw,e.lanes=n,e.stateNode={isHidden:!1},e}function _s(e,t,n){return e=yt(6,e,null,t),e.lanes=n,e}function Ts(e,t,n){return t=yt(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function _N(e,t,n,r,a){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=is(0),this.expirationTimes=is(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=is(0),this.identifierPrefix=r,this.onRecoverableError=a,this.mutableSourceEagerHydrationData=null}function Qg(e,t,n,r,a,i,o,s,l){return e=new _N(e,t,n,s,l),t===1?(t=1,i===!0&&(t|=8)):t=0,i=yt(3,null,null,t),e.current=i,i.stateNode=e,i.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Mg(i),e}function TN(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(jT)}catch(e){console.error(e)}}jT(),jw.exports=dt;var NN=jw.exports,ab=NN;Wp.createRoot=ab.createRoot,Wp.hydrateRoot=ab.hydrateRoot;/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */function xN(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function HT(e,t=""){if(!Number.isSafeInteger(e)||e<0){const n=t&&`"${t}" `;throw new Error(`${n}expected integer >= 0, got ${e}`)}}function wa(e,t,n=""){const r=xN(e),a=e==null?void 0:e.length,i=t!==void 0;if(!r||i&&a!==t){const o=n&&`"${n}" `,s=i?` of length ${t}`:"",l=r?`length=${a}`:`type=${typeof e}`;throw new Error(o+"expected Uint8Array"+s+", got "+l)}return e}const VT=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",ON=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function LN(e){if(wa(e),VT)return e.toHex();let t="";for(let n=0;n=Ht._0&&e<=Ht._9)return e-Ht._0;if(e>=Ht.A&&e<=Ht.F)return e-(Ht.A-10);if(e>=Ht.a&&e<=Ht.f)return e-(Ht.a-10)}function DN(e){if(typeof e!="string")throw new Error("hex string expected, got "+typeof e);if(VT)return Uint8Array.fromHex(e);const t=e.length,n=t/2;if(t%2)throw new Error("hex string expected, got unpadded hex of length "+t);const r=new Uint8Array(n);for(let a=0,i=0;atypeof e=="bigint"&&WT<=e;function $N(e,t,n){return ji(e)&&ji(t)&&ji(n)&&t<=e&&eObject.entries(i).forEach(([s,l])=>r(s,l,o));a(t,!1),a(n,!0)}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const YT=BigInt(0);function KT(e,t){const n=e%t;return n>=YT?n:t+n}function Tt(e,t,n){let r=e;for(;t-- >YT;)r*=r,r%=n;return r}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */function GN(e,t){return function(r){const a=e(r);return{secretKey:a,publicKey:t(a)}}}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const ra=BigInt(0),ar=BigInt(1),ki=BigInt(2);function qN(e){return zN(e,{adjustScalarBytes:"function",powPminus2:"function"}),Object.freeze({...e})}function jN(e){const t=qN(e),{P:n,type:r,adjustScalarBytes:a,powPminus2:i,randomBytes:o}=t,s=r==="x25519";if(!s&&r!=="x448")throw new Error("invalid type");const l=o||MN,u=s?255:448,d=s?32:56,c=BigInt(s?9:5),f=BigInt(s?121665:39081),p=s?ki**BigInt(254):ki**BigInt(447),h=s?BigInt(8)*ki**BigInt(251)-ar:BigInt(4)*ki**BigInt(445)-ar,y=p+h+ar,T=$=>KT($,n),b=g(c);function g($){return BN(T($),d)}function m($){const z=zf(wa($,d,"uCoordinate"));return s&&(z[31]&=127),T(ob(z))}function v($){return ob(a(zf(wa($,d,"scalar"))))}function _($,z){const H=k(m(z),v($));if(H===ra)throw new Error("invalid private or public key received");return g(H)}function E($){return _($,b)}const R=E,C=_;function N($,z,H){const Y=T($*(z-H));return z=T(z-Y),H=T(H+Y),{x_2:z,x_3:H}}function k($,z){sb("u",$,ra,n),sb("scalar",z,p,y);const H=z,Y=$;let x=ar,M=ra,S=$,P=ar,G=ra;for(let Q=BigInt(u-1);Q>=ra;Q--){const ue=H>>Q&ar;G^=ue,{x_2:x,x_3:S}=N(G,x,S),{x_2:M,x_3:P}=N(G,M,P),G=ue;const Z=x+M,ce=T(Z*Z),ke=x-M,Ve=T(ke*ke),Be=ce-Ve,rt=S+P,jr=S-P,sn=T(jr*Z),ai=T(rt*ke),Hr=sn+ai,Vr=sn-ai;S=T(Hr*Hr),P=T(Y*T(Vr*Vr)),x=T(ce*Ve),M=T(Be*(ce+T(f*Be)))}({x_2:x,x_3:S}=N(G,x,S)),{x_2:M,x_3:P}=N(G,M,P);const A=i(M);return T(x*A)}const I={secretKey:d,publicKey:d,seed:d},D=($=l(d))=>(wa($,I.seed,"seed"),$),q={randomSecretKey:D};return Object.freeze({keygen:GN(D,R),getSharedSecret:C,getPublicKey:R,scalarMult:_,scalarMultBase:E,utils:q,GuBytes:b.slice(),lengths:I})}/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */const HN=BigInt(1),lb=BigInt(2),VN=BigInt(3),WN=BigInt(5);BigInt(8);const XT=BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed");function YN(e){const t=BigInt(10),n=BigInt(20),r=BigInt(40),a=BigInt(80),i=XT,s=e*e%i*e%i,l=Tt(s,lb,i)*s%i,u=Tt(l,HN,i)*e%i,d=Tt(u,WN,i)*u%i,c=Tt(d,t,i)*d%i,f=Tt(c,n,i)*c%i,p=Tt(f,r,i)*f%i,h=Tt(p,a,i)*p%i,y=Tt(h,a,i)*p%i,T=Tt(y,t,i)*d%i;return{pow_p_5_8:Tt(T,lb,i)*e%i,b2:s}}function KN(e){return e[0]&=248,e[31]&=127,e[31]|=64,e}const ZT=(()=>{const e=XT;return jN({P:e,type:"x25519",powPminus2:t=>{const{pow_p_5_8:n,b2:r}=YN(t);return KT(Tt(n,VN,e)*r,e)},adjustScalarBytes:KN})})();/*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */function XN(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function Xe(e,t,n=""){const r=XN(e),a=e==null?void 0:e.length,i=t!==void 0;if(!r||i&&a!==t){const o=n&&`"${n}" `,s=i?` of length ${t}`:"",l=r?`length=${a}`:`type=${typeof e}`;throw new Error(o+"expected Uint8Array"+s+", got "+l)}return e}function Eo(e,t=!0){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}function QT(e,t){Xe(e,void 0,"output");const n=t.outputLen;if(e.length{function n(r,...a){if(Xe(r,void 0,"key"),!QN)throw new Error("Non little-endian hardware is not yet supported");if(e.nonceLength!==void 0){const d=a[0];Xe(d,e.varSizeNonce?void 0:e.nonceLength,"nonce")}const i=e.tagLength;i&&a[1]!==void 0&&Xe(a[1],void 0,"AAD");const o=t(r,...a),s=(d,c)=>{if(c!==void 0){if(d!==2)throw new Error("cipher output not supported");Xe(c,void 0,"output")}};let l=!1;return{encrypt(d,c){if(l)throw new Error("cannot encrypt() twice with same key + nonce");return l=!0,Xe(d),s(o.encrypt.length,c),o.encrypt(d,c)},decrypt(d,c){if(Xe(d),i&&d.length{const a=r&1;return{s3:n<<31|r>>>1,s2:t<<31|n>>>1,s1:e<<31|t>>>1,s0:e>>>1^rx<<24&-(a&1)}},gt=e=>(e>>>0&255)<<24|(e>>>8&255)<<16|(e>>>16&255)<<8|e>>>24&255|0;function ix(e){e.reverse();const t=e[15]&1;let n=0;for(let r=0;r>>1|n,n=(a&1)<<7}return e[0]^=-t&225,e}const ox=e=>e>64*1024?8:e>1024?4:2;class JT{constructor(t,n){se(this,"blockLen",Yt);se(this,"outputLen",Yt);se(this,"s0",0);se(this,"s1",0);se(this,"s2",0);se(this,"s3",0);se(this,"finished",!1);se(this,"t");se(this,"W");se(this,"windowSize");Xe(t,16,"key"),t=Kn(t);const r=zo(t);let a=r.getUint32(0,!1),i=r.getUint32(4,!1),o=r.getUint32(8,!1),s=r.getUint32(12,!1);const l=[];for(let h=0;h<128;h++)l.push({s0:gt(a),s1:gt(i),s2:gt(o),s3:gt(s)}),{s0:a,s1:i,s2:o,s3:s}=ax(a,i,o,s);const u=ox(n||1024);if(![1,2,4,8].includes(u))throw new Error("ghash: invalid window size, expected 2, 4 or 8");this.W=u;const c=128/u,f=this.windowSize=2**u,p=[];for(let h=0;h>>u-v-1&1))continue;const{s0:E,s1:R,s2:C,s3:N}=l[u*h+v];T^=E,b^=R,g^=C,m^=N}p.push({s0:T,s1:b,s2:g,s3:m})}this.t=p}_updateBlock(t,n,r,a){t^=this.s0,n^=this.s1,r^=this.s2,a^=this.s3;const{W:i,t:o,windowSize:s}=this;let l=0,u=0,d=0,c=0;const f=(1<>>8*y&255;for(let b=8/i-1;b>=0;b--){const g=T>>>i*b&f,{s0:m,s1:v,s2:_,s3:E}=o[p*s+g];l^=m,u^=v,d^=_,c^=E,p+=1}}this.s0=l,this.s1=u,this.s2=d,this.s3=c}update(t){Eo(this),Xe(t),t=Kn(t);const n=Qt(t),r=Math.floor(t.length/Yt),a=t.length%Yt;for(let i=0;ie(a,r.length).update(r).digest(),n=e(new Uint8Array(16),0);return t.outputLen=n.outputLen,t.blockLen=n.blockLen,t.create=(r,a)=>e(r,a),t}const ub=eA((e,t)=>new JT(e,t));eA((e,t)=>new sx(e,t));const Gf=16,lx=4,wi=new Uint8Array(Gf),ux=283;function cx(e){if(![16,24,32].includes(e.length))throw new Error('"aes key" expected Uint8Array of length 16/24/32, got length='+e.length)}function rm(e){return e<<1^ux&-(e>>7)}function cb(e,t){let n=0;for(;t>0;t>>=1)n^=e&-(t&1),e=rm(e);return n}const dx=(()=>{const e=new Uint8Array(256);for(let n=0,r=1;n<256;n++,r^=rm(r))e[n]=r;const t=new Uint8Array(256);t[0]=99;for(let n=0;n<255;n++){let r=e[255-n];r|=r<<8,t[e[n]]=(r^r>>4^r>>5^r>>6^r>>7^99)&255}return rn(e),t})(),px=e=>e<<24|e>>>8,As=e=>e<<8|e>>>24;function fx(e,t){if(e.length!==256)throw new Error("Wrong sbox length");const n=new Uint32Array(256).map((u,d)=>t(e[d])),r=n.map(As),a=r.map(As),i=a.map(As),o=new Uint32Array(256*256),s=new Uint32Array(256*256),l=new Uint16Array(256*256);for(let u=0;u<256;u++)for(let d=0;d<256;d++){const c=u*256+d;o[c]=n[u]^r[d],s[c]=a[u]^i[d],l[c]=e[u]<<8|e[d]}return{sbox:e,sbox2:l,T0:n,T1:r,T2:a,T3:i,T01:o,T23:s}}const tA=fx(dx,e=>cb(e,3)<<24|e<<16|e<<8|cb(e,2)),gx=(()=>{const e=new Uint8Array(16);for(let t=0,n=1;t<16;t++,n=rm(n))e[t]=n;return e})();function mx(e){Xe(e);const t=e.length;cx(e);const{sbox2:n}=tA,r=[];So(e)||r.push(e=Kn(e));const a=Qt(e),i=a.length,o=l=>da(n,l,l,l,l),s=new Uint32Array(t+28);s.set(a);for(let l=i;l6&&l%i===4&&(u=o(u)),s[l]=s[l-i]^u}return rn(...r),s}function _i(e,t,n,r,a,i){return e[n<<8&65280|r>>>8&255]^t[a>>>8&65280|i>>>24&255]}function da(e,t,n,r,a){return e[t&255|n&65280]|e[r>>>16&255|a>>>16&65280]<<16}function db(e,t,n,r,a){const{sbox2:i,T01:o,T23:s}=tA;let l=0;t^=e[l++],n^=e[l++],r^=e[l++],a^=e[l++];const u=e.length/4-2;for(let h=0;h>>0,s.setUint32(d,f,t),{s0:p,s1:h,s2:y,s3:T}=db(e,o[0],o[1],o[2],o[3]);const b=Gf*Math.floor(l.length/lx);if(bt+=String.fromCharCode(n)),btoa(t)}function jf(e){const t=atob(e),n=new Uint8Array(t.length);for(let r=0;r{this.destroyed||(this.ws.send(JSON.stringify({type:"join_room",room_id:this.roomId,device_id:this.mobileDeviceId,device_type:"mobile",public_key:qf(this.keyPair.publicKey)})),this.callbacks.onStateChange("connected"),this.startHeartbeat())},this.ws.onmessage=async n=>{if(!this.destroyed)try{const r=JSON.parse(n.data);await this.handleWsMessage(r)}catch{}},this.ws.onclose=n=>{this.destroyed||(this.stopHeartbeat(),this.sharedKey=null,this.callbacks.onStateChange("disconnected"))},this.ws.onerror=n=>{this.destroyed||this.callbacks.onError("WebSocket connection error")}}async handleWsMessage(t){switch(t.type){case"relay":{if(!this.sharedKey)return;try{const n=await vx(this.sharedKey,t.encrypted_data,t.nonce),r=JSON.parse(n);if(r.challenge&&r.timestamp){const a=JSON.stringify({challenge_echo:r.challenge,device_id:this.mobileDeviceId,device_name:this.getMobileDeviceName()});await this.sendEncrypted(a),this.callbacks.onStateChange("paired")}else this.callbacks.onMessage(n)}catch{}break}case"peer_disconnected":{this.stopHeartbeat(),this.sharedKey=null,this.callbacks.onStateChange("disconnected");break}case"error":{this.callbacks.onError(`Join failed: ${t.message}`),this.callbacks.onStateChange("disconnected");break}}}async sendEncrypted(t){if(!this.sharedKey||!this.ws||this.ws.readyState!==WebSocket.OPEN)return;const{data:n,nonce:r}=await Sx(this.sharedKey,t);this.ws.send(JSON.stringify({type:"relay",room_id:this.roomId,encrypted_data:n,nonce:r}))}async sendCommand(t){await this.sendEncrypted(JSON.stringify(t))}getMobileDeviceName(){const t=navigator.userAgent;return/iPhone/i.test(t)?"iPhone":/iPad/i.test(t)?"iPad":/Android/i.test(t)?"Android":"Mobile Browser"}setMessageHandler(t){this.callbacks.onMessage=t}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{var t;((t=this.ws)==null?void 0:t.readyState)===WebSocket.OPEN&&this.ws.send(JSON.stringify({type:"heartbeat"}))},25e3)}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null)}async pollMessages(){return{messages:[],peer_connected:!!this.sharedKey}}async ackMessages(){}startPolling(t=2e3){}stopPolling(){}disconnect(){var t;this.destroyed=!0,this.stopHeartbeat(),(t=this.ws)==null||t.close(),this.ws=null,this.sharedKey=null,this.callbacks.onStateChange("disconnected")}get isPaired(){return this.sharedKey!==null}}class wx{constructor(t){se(this,"relay");se(this,"pendingCallbacks",new Map);se(this,"streamListeners",[]);this.relay=t,this.relay.startPolling(2e3)}onStreamEvent(t){return this.streamListeners.push(t),()=>{this.streamListeners=this.streamListeners.filter(n=>n!==t)}}handleMessage(t){try{const n=JSON.parse(t);if(n.resp==="stream_event"){this.streamListeners.forEach(r=>r(n));return}if(n._request_id&&this.pendingCallbacks.has(n._request_id)){const r=this.pendingCallbacks.get(n._request_id);this.pendingCallbacks.delete(n._request_id),r(n)}}catch(n){console.error("[SessionMgr] Failed to parse message",n)}}async request(t){const n=`req_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,r={...t,_request_id:n};return new Promise((a,i)=>{const o=setTimeout(()=>{this.pendingCallbacks.delete(n),i(new Error("Request timeout"))},3e4);this.pendingCallbacks.set(n,s=>{clearTimeout(o),s.resp==="error"?i(new Error(s.message)):a(s)}),this.relay.sendCommand(r).catch(i)})}async getWorkspaceInfo(){const t=await this.request({cmd:"get_workspace_info"});return{has_workspace:t.has_workspace,path:t.path,project_name:t.project_name,git_branch:t.git_branch}}async listRecentWorkspaces(){return(await this.request({cmd:"list_recent_workspaces"})).workspaces||[]}async setWorkspace(t){return await this.request({cmd:"set_workspace",path:t})}async listSessions(t,n=30,r=0){const a=await this.request({cmd:"list_sessions",workspace_path:t??null,limit:n,offset:r});return{sessions:a.sessions||[],has_more:a.has_more??!1}}async createSession(t,n,r){return(await this.request({cmd:"create_session",agent_type:t||void 0,session_name:n||void 0,workspace_path:r??null})).session_id}async getSessionMessages(t,n,r){const a=await this.request({cmd:"get_session_messages",session_id:t,limit:n,before_message_id:r});return{messages:a.messages||[],has_more:a.has_more||!1}}async subscribeSession(t){await this.request({cmd:"subscribe_session",session_id:t})}async unsubscribeSession(t){await this.request({cmd:"unsubscribe_session",session_id:t})}async sendMessage(t,n){return(await this.request({cmd:"send_message",session_id:t,content:n})).turn_id}async cancelTask(t){await this.request({cmd:"cancel_task",session_id:t})}async deleteSession(t){await this.request({cmd:"delete_session",session_id:t})}async ping(){await this.request({cmd:"ping"})}dispose(){this.relay.stopPolling(),this.pendingCallbacks.clear(),this.streamListeners=[]}}const _x={},pb=e=>{let t;const n=new Set,r=(d,c)=>{const f=typeof d=="function"?d(t):d;if(!Object.is(f,t)){const p=t;t=c??(typeof f!="object"||f===null)?f:Object.assign({},t,f),n.forEach(h=>h(t,p))}},a=()=>t,l={setState:r,getState:a,getInitialState:()=>u,subscribe:d=>(n.add(d),()=>n.delete(d)),destroy:()=>{(_x?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),n.clear()}},u=t=e(r,a,l);return l},Tx=e=>e?pb(e):pb;var aA={exports:{}},iA={},oA={exports:{}},sA={};/** + * @license React + * use-sync-external-store-shim.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Fr=W;function Ax(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var Rx=typeof Object.is=="function"?Object.is:Ax,Ix=Fr.useState,Cx=Fr.useEffect,Nx=Fr.useLayoutEffect,xx=Fr.useDebugValue;function Ox(e,t){var n=t(),r=Ix({inst:{value:n,getSnapshot:t}}),a=r[0].inst,i=r[1];return Nx(function(){a.value=n,a.getSnapshot=t,Rs(a)&&i({inst:a})},[e,n,t]),Cx(function(){return Rs(a)&&i({inst:a}),e(function(){Rs(a)&&i({inst:a})})},[e]),xx(n),n}function Rs(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!Rx(e,n)}catch{return!0}}function Lx(e,t){return t()}var Dx=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?Lx:Ox;sA.useSyncExternalStore=Fr.useSyncExternalStore!==void 0?Fr.useSyncExternalStore:Dx;oA.exports=sA;var Mx=oA.exports;/** + * @license React + * use-sync-external-store-shim/with-selector.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Go=W,Fx=Mx;function Px(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var Ux=typeof Object.is=="function"?Object.is:Px,Bx=Fx.useSyncExternalStore,$x=Go.useRef,zx=Go.useEffect,Gx=Go.useMemo,qx=Go.useDebugValue;iA.useSyncExternalStoreWithSelector=function(e,t,n,r,a){var i=$x(null);if(i.current===null){var o={hasValue:!1,value:null};i.current=o}else o=i.current;i=Gx(function(){function l(p){if(!u){if(u=!0,d=p,p=r(p),a!==void 0&&o.hasValue){var h=o.value;if(a(h,p))return c=h}return c=p}if(h=c,Ux(d,p))return h;var y=r(p);return a!==void 0&&a(h,y)?(d=p,h):(d=p,c=y)}var u=!1,d,c,f=n===void 0?null:n;return[function(){return l(t())},f===null?void 0:function(){return l(f())}]},[t,n,r,a]);var s=Bx(e,i[0],i[1]);return zx(function(){o.hasValue=!0,o.value=s},[s]),qx(s),s};aA.exports=iA;var jx=aA.exports;const Hx=Wa(jx),lA={},{useDebugValue:Vx}=Ft,{useSyncExternalStoreWithSelector:Wx}=Hx;let fb=!1;const Yx=e=>e;function Kx(e,t=Yx,n){(lA?"production":void 0)!=="production"&&n&&!fb&&(console.warn("[DEPRECATED] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`. They can be imported from 'zustand/traditional'. https://github.com/pmndrs/zustand/discussions/1937"),fb=!0);const r=Wx(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,n);return Vx(r),r}const gb=e=>{(lA?"production":void 0)!=="production"&&typeof e!="function"&&console.warn("[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`.");const t=typeof e=="function"?Tx(e):e,n=(r,a)=>Kx(t,r,a);return Object.assign(n,t),n},Xx=e=>e?gb(e):gb,am=Xx((e,t)=>({connectionState:"disconnected",setConnectionState:n=>e({connectionState:n}),currentWorkspace:null,setCurrentWorkspace:n=>e({currentWorkspace:n}),sessions:[],setSessions:n=>e({sessions:n}),appendSessions:n=>e(r=>({sessions:[...r.sessions,...n]})),activeSessionId:null,setActiveSessionId:n=>e({activeSessionId:n}),messagesBySession:{},getMessages:n=>t().messagesBySession[n]||[],setMessages:(n,r)=>e(a=>({messagesBySession:{...a.messagesBySession,[n]:r}})),appendMessage:(n,r)=>e(a=>{const i=a.messagesBySession[n]||[];return{messagesBySession:{...a.messagesBySession,[n]:[...i,r]}}}),updateLastMessage:(n,r)=>e(a=>{const i=[...a.messagesBySession[n]||[]];return i.length>0&&(i[i.length-1]={...i[i.length-1],content:r}),{messagesBySession:{...a.messagesBySession,[n]:i}}}),updateLastMessageFull:(n,r,a)=>e(i=>{const o=[...i.messagesBySession[n]||[]];return o.length>0&&(o[o.length-1]={...o[o.length-1],content:r,metadata:a}),{messagesBySession:{...i.messagesBySession,[n]:o}}}),error:null,setError:n=>e({error:n}),isStreaming:!1,setIsStreaming:n=>e({isStreaming:n})})),Zx=({onPaired:e})=>{const{connectionState:t,setConnectionState:n,setError:r,error:a}=am(),i=W.useRef(null),o=W.useRef(!1);W.useEffect(()=>{const d=window.location.hash,c=new URLSearchParams(d.replace(/^#\/pair\?/,"")),f=c.get("room"),p=c.get("pk"),h=c.get("did"),y=c.get("relay");if(!f||!p){r("Invalid QR code: missing room or public key");return}let T;y?T=y:T=(window.location.origin+window.location.pathname.replace(/\/$/,"")).replace(/^https/,"wss").replace(/^http/,"ws");const b=new kx(T,f,p,h||"",{onStateChange:g=>{if(n(g),g==="paired"){o.current=!0;const m=new wx(b);e(b,m)}},onMessage:()=>{},onError:g=>r(g)});return i.current=b,b.connect(),()=>{o.current||b.disconnect()}},[]);const s={disconnected:"Disconnected",connecting:"Connecting to relay server...",connected:"Connected, exchanging keys...",paired:"Paired! Loading sessions...",error:"Connection error"},l=()=>{window.location.reload()},u=(t==="error"||t==="disconnected")&&!!a;return L.jsxs("div",{className:"pairing-page",children:[L.jsx("div",{className:"pairing-page__logo",children:"BitFun"}),L.jsx("div",{className:"pairing-page__spinner",children:t!=="error"&&t!=="disconnected"&&L.jsx("div",{className:"spinner"})}),L.jsx("div",{className:"pairing-page__state",children:s[t]||t}),a&&L.jsx("div",{className:"pairing-page__error",children:a}),u&&L.jsx("button",{className:"pairing-page__retry",onClick:l,children:"Retry"})]})},Qx=({sessionMgr:e,onReady:t})=>{const[n,r]=W.useState(null),[a,i]=W.useState([]),[o,s]=W.useState(!0),[l,u]=W.useState(!1),[d,c]=W.useState(null),[f,p]=W.useState(!1),h=W.useCallback(async()=>{try{const m=await e.getWorkspaceInfo();r(m)}catch(m){c(m.message)}finally{s(!1)}},[e]),y=W.useCallback(async()=>{try{const m=await e.listRecentWorkspaces();i(m)}catch(m){c(m.message)}},[e]);W.useEffect(()=>{h()},[h]);const T=async()=>{p(!0),await y()},b=async m=>{if(!l){u(!0),c(null);try{const v=await e.setWorkspace(m);v.success?(await h(),p(!1)):c(v.error||"Failed to set workspace")}catch(v){c(v.message)}finally{u(!1)}}},g=()=>{t()};return o?L.jsx("div",{className:"workspace-page",children:L.jsxs("div",{className:"workspace-page__loading",children:[L.jsx("div",{className:"spinner"}),L.jsx("span",{children:"Loading workspace info..."})]})}):L.jsxs("div",{className:"workspace-page",children:[L.jsx("div",{className:"workspace-page__header",children:L.jsx("h1",{children:"Workspace"})}),L.jsxs("div",{className:"workspace-page__content",children:[n!=null&&n.has_workspace?L.jsxs("div",{className:"workspace-page__current",children:[L.jsx("div",{className:"workspace-page__current-label",children:"Current Workspace"}),L.jsxs("div",{className:"workspace-page__current-card",children:[L.jsx("div",{className:"workspace-page__project-name",children:n.project_name||"Unknown Project"}),L.jsx("div",{className:"workspace-page__project-path",children:n.path}),n.git_branch&&L.jsxs("div",{className:"workspace-page__git-branch",children:[L.jsx("span",{className:"workspace-page__branch-icon",children:"⎇"}),n.git_branch]})]}),L.jsxs("div",{className:"workspace-page__actions",children:[L.jsx("button",{className:"workspace-page__btn workspace-page__btn--primary",onClick:g,children:"Continue"}),L.jsx("button",{className:"workspace-page__btn workspace-page__btn--secondary",onClick:T,children:"Switch Workspace"})]})]}):L.jsxs("div",{className:"workspace-page__no-workspace",children:[L.jsx("div",{className:"workspace-page__no-workspace-icon",children:"📂"}),L.jsx("div",{className:"workspace-page__no-workspace-text",children:"No workspace is currently open on the desktop."}),L.jsx("div",{className:"workspace-page__no-workspace-hint",children:"Select a recent workspace below, or open one on the desktop first."}),!f&&L.jsx("button",{className:"workspace-page__btn workspace-page__btn--primary",onClick:T,children:"Select Workspace"})]}),f&&L.jsxs("div",{className:"workspace-page__recent",children:[L.jsx("div",{className:"workspace-page__recent-label",children:"Recent Workspaces"}),a.length===0?L.jsx("div",{className:"workspace-page__recent-empty",children:"No recent workspaces found. Please open a workspace on the desktop first."}):L.jsx("div",{className:"workspace-page__recent-list",children:a.map(m=>L.jsxs("button",{className:"workspace-page__recent-item",onClick:()=>b(m.path),disabled:l,children:[L.jsx("div",{className:"workspace-page__recent-item-name",children:m.name}),L.jsx("div",{className:"workspace-page__recent-item-path",children:m.path})]},m.path))}),(n==null?void 0:n.has_workspace)&&L.jsx("button",{className:"workspace-page__btn workspace-page__btn--secondary",onClick:()=>p(!1),children:"Cancel"})]}),l&&L.jsxs("div",{className:"workspace-page__switching",children:[L.jsx("div",{className:"spinner"}),L.jsx("span",{children:"Opening workspace..."})]}),d&&L.jsx("div",{className:"workspace-page__error",children:d})]})]})},mb=30;function Jx(e){const t=parseInt(e,10);if(!t||isNaN(t))return"";const n=new Date(t*1e3),a=new Date().getTime()-n.getTime(),i=Math.floor(a/6e4);if(i<1)return"just now";if(i<60)return`${i}m ago`;const o=Math.floor(i/60);if(o<24)return`${o}h ago`;const s=Math.floor(o/24);return s<7?`${s}d ago`:n.toLocaleDateString()}function eO(e){switch(e){case"code":case"agentic":return"Code";case"cowork":case"Cowork":return"Cowork";default:return e||"Default"}}const tO=({sessionMgr:e,onSelectSession:t,onOpenWorkspace:n})=>{const{sessions:r,setSessions:a,appendSessions:i,setError:o,currentWorkspace:s,setCurrentWorkspace:l}=am(),[u,d]=W.useState(!1),[c,f]=W.useState(!1),[p,h]=W.useState(!1),[y,T]=W.useState(!1),[b,g]=W.useState(!1),m=W.useRef(0),v=W.useRef(null),_=W.useCallback(async k=>{f(!0),m.current=0;try{const I=await e.listSessions(k,mb,0);a(I.sessions),T(I.has_more),m.current=I.sessions.length}catch(I){o(I.message)}finally{f(!1)}},[e,a,o]),E=W.useCallback(async k=>{if(!(p||!y)){h(!0);try{const I=await e.listSessions(k,mb,m.current);i(I.sessions),T(I.has_more),m.current+=I.sessions.length}catch(I){o(I.message)}finally{h(!1)}}},[e,i,o,p,y]);W.useEffect(()=>{let k=!1;return(async()=>{try{const D=await e.getWorkspaceInfo();if(k)return;const q=D.has_workspace?D:null;l(q),await _(q==null?void 0:q.path)}catch(D){k||o(D.message)}})(),()=>{k=!0}},[]);const R=W.useCallback(k=>{const I=k.currentTarget;I.scrollHeight-I.scrollTop-I.clientHeight<150&&E(s==null?void 0:s.path)},[s==null?void 0:s.path,E]),C=async()=>{try{const k=await e.getWorkspaceInfo(),I=k.has_workspace?k:null;l(I),await _(I==null?void 0:I.path)}catch(k){o(k.message)}},N=async k=>{if(!u){d(!0),g(!1);try{const I=await e.createSession(k,void 0,s==null?void 0:s.path);await _(s==null?void 0:s.path),t(I)}catch(I){o(I.message)}finally{d(!1)}}};return L.jsxs("div",{className:"session-list",children:[L.jsxs("div",{className:"session-list__header",children:[L.jsx("h1",{children:"BitFun Sessions"}),L.jsxs("div",{className:"session-list__new-wrapper",children:[L.jsx("button",{className:"session-list__new-btn",onClick:()=>g(!b),disabled:u,style:{opacity:u?.5:1},children:u?"Creating...":"+ New"}),b&&L.jsxs("div",{className:"session-list__new-menu",children:[L.jsxs("button",{className:"session-list__menu-item",onClick:()=>N("code"),children:[L.jsx("span",{className:"session-list__menu-icon",children:""}),"Code Session"]}),L.jsxs("button",{className:"session-list__menu-item",onClick:()=>N("cowork"),children:[L.jsx("span",{className:"session-list__menu-icon",children:"<>"}),"Cowork Session"]})]})]})]}),L.jsxs("div",{className:"session-list__workspace-bar",onClick:n,children:[L.jsx("span",{className:"session-list__workspace-icon",children:"📂"}),L.jsx("span",{className:"session-list__workspace-name",children:(s==null?void 0:s.project_name)||(s==null?void 0:s.path)||"No workspace"}),(s==null?void 0:s.git_branch)&&L.jsxs("span",{className:"session-list__workspace-branch",children:["⎇ ",s.git_branch]}),L.jsx("span",{className:"session-list__workspace-switch",children:"Switch ›"})]}),L.jsxs("div",{className:"session-list__items",ref:v,onScroll:R,children:[c&&r.length===0&&L.jsx("div",{className:"session-list__empty",children:"Loading sessions..."}),!c&&r.length===0&&L.jsx("div",{className:"session-list__empty",children:"No sessions yet. Create one to get started."}),r.map(k=>L.jsxs("div",{className:"session-list__item",onClick:()=>t(k.session_id),children:[L.jsxs("div",{className:"session-list__item-top",children:[L.jsx("div",{className:"session-list__item-name",children:k.name||"Untitled Session"}),L.jsx("span",{className:`session-list__agent-badge session-list__agent-badge--${k.agent_type}`,children:eO(k.agent_type)})]}),L.jsxs("div",{className:"session-list__item-meta",children:[L.jsxs("span",{children:[k.message_count," messages"]}),L.jsx("span",{className:"session-list__item-time",children:Jx(k.updated_at)})]})]},k.session_id)),p&&L.jsx("div",{className:"session-list__load-more",children:"Loading more..."})]}),L.jsx("button",{className:"session-list__refresh",onClick:C,disabled:c||p,children:c?"Refreshing...":"Refresh"})]})};function nO(e,t){const n={};return(e[e.length-1]===""?[...e,""]:e).join((n.padRight?" ":"")+","+(n.padLeft===!1?"":" ")).trim()}const rO=/^[$_\p{ID_Start}][$_\u{200C}\u{200D}\p{ID_Continue}]*$/u,aO=/^[$_\p{ID_Start}][-$_\u{200C}\u{200D}\p{ID_Continue}]*$/u,iO={};function hb(e,t){return(iO.jsx?aO:rO).test(e)}const oO=/[ \t\n\f\r]/g;function sO(e){return typeof e=="object"?e.type==="text"?bb(e.value):!1:bb(e)}function bb(e){return e.replace(oO,"")===""}let Ja=class{constructor(t,n,r){this.normal=n,this.property=t,r&&(this.space=r)}};Ja.prototype.normal={};Ja.prototype.property={};Ja.prototype.space=void 0;function uA(e,t){const n={},r={};for(const a of e)Object.assign(n,a.property),Object.assign(r,a.normal);return new Ja(n,r,t)}function Hf(e){return e.toLowerCase()}let tt=class{constructor(t,n){this.attribute=n,this.property=t}};tt.prototype.attribute="";tt.prototype.booleanish=!1;tt.prototype.boolean=!1;tt.prototype.commaOrSpaceSeparated=!1;tt.prototype.commaSeparated=!1;tt.prototype.defined=!1;tt.prototype.mustUseProperty=!1;tt.prototype.number=!1;tt.prototype.overloadedBoolean=!1;tt.prototype.property="";tt.prototype.spaceSeparated=!1;tt.prototype.space=void 0;let lO=0;const X=Jn(),we=Jn(),Vf=Jn(),U=Jn(),de=Jn(),Ir=Jn(),it=Jn();function Jn(){return 2**++lO}const Wf=Object.freeze(Object.defineProperty({__proto__:null,boolean:X,booleanish:we,commaOrSpaceSeparated:it,commaSeparated:Ir,number:U,overloadedBoolean:Vf,spaceSeparated:de},Symbol.toStringTag,{value:"Module"})),Is=Object.keys(Wf);let im=class extends tt{constructor(t,n,r,a){let i=-1;if(super(t,n),yb(this,"space",a),typeof r=="number")for(;++i4&&n.slice(0,4)==="data"&&fO.test(t)){if(t.charAt(4)==="-"){const i=t.slice(5).replace(Eb,hO);r="data"+i.charAt(0).toUpperCase()+i.slice(1)}else{const i=t.slice(4);if(!Eb.test(i)){let o=i.replace(pO,mO);o.charAt(0)!=="-"&&(o="-"+o),t="data"+o}}a=im}return new a(r,t)}function mO(e){return"-"+e.toLowerCase()}function hO(e){return e.charAt(1).toUpperCase()}const bO=uA([cA,uO,fA,gA,mA],"html"),om=uA([cA,cO,fA,gA,mA],"svg");function yO(e){return e.join(" ").trim()}var sm={},Sb=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//g,EO=/\n/g,SO=/^\s*/,vO=/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/,kO=/^:\s*/,wO=/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/,_O=/^[;\s]*/,TO=/^\s+|\s+$/g,AO=` +`,vb="/",kb="*",Un="",RO="comment",IO="declaration";function CO(e,t){if(typeof e!="string")throw new TypeError("First argument must be a string");if(!e)return[];t=t||{};var n=1,r=1;function a(h){var y=h.match(EO);y&&(n+=y.length);var T=h.lastIndexOf(AO);r=~T?h.length-T:r+h.length}function i(){var h={line:n,column:r};return function(y){return y.position=new o(h),u(),y}}function o(h){this.start=h,this.end={line:n,column:r},this.source=t.source}o.prototype.content=e;function s(h){var y=new Error(t.source+":"+n+":"+r+": "+h);if(y.reason=h,y.filename=t.source,y.line=n,y.column=r,y.source=e,!t.silent)throw y}function l(h){var y=h.exec(e);if(y){var T=y[0];return a(T),e=e.slice(T.length),y}}function u(){l(SO)}function d(h){var y;for(h=h||[];y=c();)y!==!1&&h.push(y);return h}function c(){var h=i();if(!(vb!=e.charAt(0)||kb!=e.charAt(1))){for(var y=2;Un!=e.charAt(y)&&(kb!=e.charAt(y)||vb!=e.charAt(y+1));)++y;if(y+=2,Un===e.charAt(y-1))return s("End of comment missing");var T=e.slice(2,y-2);return r+=2,a(T),e=e.slice(y),r+=2,h({type:RO,comment:T})}}function f(){var h=i(),y=l(vO);if(y){if(c(),!l(kO))return s("property missing ':'");var T=l(wO),b=h({type:IO,property:wb(y[0].replace(Sb,Un)),value:T?wb(T[0].replace(Sb,Un)):Un});return l(_O),b}}function p(){var h=[];d(h);for(var y;y=f();)y!==!1&&(h.push(y),d(h));return h}return u(),p()}function wb(e){return e?e.replace(TO,Un):Un}var NO=CO,xO=Tn&&Tn.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(sm,"__esModule",{value:!0});sm.default=LO;const OO=xO(NO);function LO(e,t){let n=null;if(!e||typeof e!="string")return n;const r=(0,OO.default)(e),a=typeof t=="function";return r.forEach(i=>{if(i.type!=="declaration")return;const{property:o,value:s}=i;a?t(o,s,i):s&&(n=n||{},n[o]=s)}),n}var qo={};Object.defineProperty(qo,"__esModule",{value:!0});qo.camelCase=void 0;var DO=/^--[a-zA-Z0-9_-]+$/,MO=/-([a-z])/g,FO=/^[^-]+$/,PO=/^-(webkit|moz|ms|o|khtml)-/,UO=/^-(ms)-/,BO=function(e){return!e||FO.test(e)||DO.test(e)},$O=function(e,t){return t.toUpperCase()},_b=function(e,t){return"".concat(t,"-")},zO=function(e,t){return t===void 0&&(t={}),BO(e)?e:(e=e.toLowerCase(),t.reactCompat?e=e.replace(UO,_b):e=e.replace(PO,_b),e.replace(MO,$O))};qo.camelCase=zO;var GO=Tn&&Tn.__importDefault||function(e){return e&&e.__esModule?e:{default:e}},qO=GO(sm),jO=qo;function Yf(e,t){var n={};return!e||typeof e!="string"||(0,qO.default)(e,function(r,a){r&&a&&(n[(0,jO.camelCase)(r,t)]=a)}),n}Yf.default=Yf;var HO=Yf;const VO=Wa(HO),hA=bA("end"),lm=bA("start");function bA(e){return t;function t(n){const r=n&&n.position&&n.position[e]||{};if(typeof r.line=="number"&&r.line>0&&typeof r.column=="number"&&r.column>0)return{line:r.line,column:r.column,offset:typeof r.offset=="number"&&r.offset>-1?r.offset:void 0}}}function WO(e){const t=lm(e),n=hA(e);if(t&&n)return{start:t,end:n}}function _a(e){return!e||typeof e!="object"?"":"position"in e||"type"in e?Tb(e.position):"start"in e||"end"in e?Tb(e):"line"in e||"column"in e?Kf(e):""}function Kf(e){return Ab(e&&e.line)+":"+Ab(e&&e.column)}function Tb(e){return Kf(e&&e.start)+"-"+Kf(e&&e.end)}function Ab(e){return e&&typeof e=="number"?e:1}class Ue extends Error{constructor(t,n,r){super(),typeof n=="string"&&(r=n,n=void 0);let a="",i={},o=!1;if(n&&("line"in n&&"column"in n?i={place:n}:"start"in n&&"end"in n?i={place:n}:"type"in n?i={ancestors:[n],place:n.position}:i={...n}),typeof t=="string"?a=t:!i.cause&&t&&(o=!0,a=t.message,i.cause=t),!i.ruleId&&!i.source&&typeof r=="string"){const l=r.indexOf(":");l===-1?i.ruleId=r:(i.source=r.slice(0,l),i.ruleId=r.slice(l+1))}if(!i.place&&i.ancestors&&i.ancestors){const l=i.ancestors[i.ancestors.length-1];l&&(i.place=l.position)}const s=i.place&&"start"in i.place?i.place.start:i.place;this.ancestors=i.ancestors||void 0,this.cause=i.cause||void 0,this.column=s?s.column:void 0,this.fatal=void 0,this.file="",this.message=a,this.line=s?s.line:void 0,this.name=_a(i.place)||"1:1",this.place=i.place||void 0,this.reason=this.message,this.ruleId=i.ruleId||void 0,this.source=i.source||void 0,this.stack=o&&i.cause&&typeof i.cause.stack=="string"?i.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}}Ue.prototype.file="";Ue.prototype.name="";Ue.prototype.reason="";Ue.prototype.message="";Ue.prototype.stack="";Ue.prototype.column=void 0;Ue.prototype.line=void 0;Ue.prototype.ancestors=void 0;Ue.prototype.cause=void 0;Ue.prototype.fatal=void 0;Ue.prototype.place=void 0;Ue.prototype.ruleId=void 0;Ue.prototype.source=void 0;const um={}.hasOwnProperty,YO=new Map,KO=/[A-Z]/g,XO=new Set(["table","tbody","thead","tfoot","tr"]),ZO=new Set(["td","th"]),yA="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function QO(e,t){if(!t||t.Fragment===void 0)throw new TypeError("Expected `Fragment` in options");const n=t.filePath||void 0;let r;if(t.development){if(typeof t.jsxDEV!="function")throw new TypeError("Expected `jsxDEV` in options when `development: true`");r=o1(n,t.jsxDEV)}else{if(typeof t.jsx!="function")throw new TypeError("Expected `jsx` in production options");if(typeof t.jsxs!="function")throw new TypeError("Expected `jsxs` in production options");r=i1(n,t.jsx,t.jsxs)}const a={Fragment:t.Fragment,ancestors:[],components:t.components||{},create:r,elementAttributeNameCase:t.elementAttributeNameCase||"react",evaluater:t.createEvaluater?t.createEvaluater():void 0,filePath:n,ignoreInvalidStyle:t.ignoreInvalidStyle||!1,passKeys:t.passKeys!==!1,passNode:t.passNode||!1,schema:t.space==="svg"?om:bO,stylePropertyNameCase:t.stylePropertyNameCase||"dom",tableCellAlignToStyle:t.tableCellAlignToStyle!==!1},i=EA(a,e,void 0);return i&&typeof i!="string"?i:a.create(e,a.Fragment,{children:i||void 0},void 0)}function EA(e,t,n){if(t.type==="element")return JO(e,t,n);if(t.type==="mdxFlowExpression"||t.type==="mdxTextExpression")return e1(e,t);if(t.type==="mdxJsxFlowElement"||t.type==="mdxJsxTextElement")return n1(e,t,n);if(t.type==="mdxjsEsm")return t1(e,t);if(t.type==="root")return r1(e,t,n);if(t.type==="text")return a1(e,t)}function JO(e,t,n){const r=e.schema;let a=r;t.tagName.toLowerCase()==="svg"&&r.space==="html"&&(a=om,e.schema=a),e.ancestors.push(t);const i=vA(e,t.tagName,!1),o=s1(e,t);let s=dm(e,t);return XO.has(t.tagName)&&(s=s.filter(function(l){return typeof l=="string"?!sO(l):!0})),SA(e,o,i,t),cm(o,s),e.ancestors.pop(),e.schema=r,e.create(t,i,o,n)}function e1(e,t){if(t.data&&t.data.estree&&e.evaluater){const r=t.data.estree.body[0];return r.type,e.evaluater.evaluateExpression(r.expression)}ja(e,t.position)}function t1(e,t){if(t.data&&t.data.estree&&e.evaluater)return e.evaluater.evaluateProgram(t.data.estree);ja(e,t.position)}function n1(e,t,n){const r=e.schema;let a=r;t.name==="svg"&&r.space==="html"&&(a=om,e.schema=a),e.ancestors.push(t);const i=t.name===null?e.Fragment:vA(e,t.name,!0),o=l1(e,t),s=dm(e,t);return SA(e,o,i,t),cm(o,s),e.ancestors.pop(),e.schema=r,e.create(t,i,o,n)}function r1(e,t,n){const r={};return cm(r,dm(e,t)),e.create(t,e.Fragment,r,n)}function a1(e,t){return t.value}function SA(e,t,n,r){typeof n!="string"&&n!==e.Fragment&&e.passNode&&(t.node=r)}function cm(e,t){if(t.length>0){const n=t.length>1?t:t[0];n&&(e.children=n)}}function i1(e,t,n){return r;function r(a,i,o,s){const u=Array.isArray(o.children)?n:t;return s?u(i,o,s):u(i,o)}}function o1(e,t){return n;function n(r,a,i,o){const s=Array.isArray(i.children),l=lm(r);return t(a,i,o,s,{columnNumber:l?l.column-1:void 0,fileName:e,lineNumber:l?l.line:void 0},void 0)}}function s1(e,t){const n={};let r,a;for(a in t.properties)if(a!=="children"&&um.call(t.properties,a)){const i=u1(e,a,t.properties[a]);if(i){const[o,s]=i;e.tableCellAlignToStyle&&o==="align"&&typeof s=="string"&&ZO.has(t.tagName)?r=s:n[o]=s}}if(r){const i=n.style||(n.style={});i[e.stylePropertyNameCase==="css"?"text-align":"textAlign"]=r}return n}function l1(e,t){const n={};for(const r of t.attributes)if(r.type==="mdxJsxExpressionAttribute")if(r.data&&r.data.estree&&e.evaluater){const i=r.data.estree.body[0];i.type;const o=i.expression;o.type;const s=o.properties[0];s.type,Object.assign(n,e.evaluater.evaluateExpression(s.argument))}else ja(e,t.position);else{const a=r.name;let i;if(r.value&&typeof r.value=="object")if(r.value.data&&r.value.data.estree&&e.evaluater){const s=r.value.data.estree.body[0];s.type,i=e.evaluater.evaluateExpression(s.expression)}else ja(e,t.position);else i=r.value===null?!0:r.value;n[a]=i}return n}function dm(e,t){const n=[];let r=-1;const a=e.passKeys?new Map:YO;for(;++ra?0:a+t:t=t>a?a:t,n=n>0?n:0,r.length<1e4)o=Array.from(r),o.unshift(t,n),e.splice(...o);else for(n&&e.splice(t,n);i0?(ut(e,e.length,0,t),e):t}const Cb={}.hasOwnProperty;function wA(e){const t={};let n=-1;for(;++n13&&n<32||n>126&&n<160||n>55295&&n<57344||n>64975&&n<65008||(n&65535)===65535||(n&65535)===65534||n>1114111?"�":String.fromCodePoint(n)}function xt(e){return e.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}const Ge=xn(/[A-Za-z]/),Fe=xn(/[\dA-Za-z]/),y1=xn(/[#-'*+\--9=?A-Z^-~]/);function vo(e){return e!==null&&(e<32||e===127)}const Xf=xn(/\d/),E1=xn(/[\dA-Fa-f]/),S1=xn(/[!-/:-@[-`{-~]/);function V(e){return e!==null&&e<-2}function le(e){return e!==null&&(e<0||e===32)}function ee(e){return e===-2||e===-1||e===32}const jo=xn(new RegExp("\\p{P}|\\p{S}","u")),Xn=xn(/\s/);function xn(e){return t;function t(n){return n!==null&&n>-1&&e.test(String.fromCharCode(n))}}function Gr(e){const t=[];let n=-1,r=0,a=0;for(;++n55295&&i<57344){const s=e.charCodeAt(n+1);i<56320&&s>56319&&s<57344?(o=String.fromCharCode(i,s),a=1):o="�"}else o=String.fromCharCode(i);o&&(t.push(e.slice(r,n),encodeURIComponent(o)),r=n+a+1,o=""),a&&(n+=a,a=0)}return t.join("")+e.slice(r)}function re(e,t,n,r){const a=r?r-1:Number.POSITIVE_INFINITY;let i=0;return o;function o(l){return ee(l)?(e.enter(n),s(l)):t(l)}function s(l){return ee(l)&&i++o))return;const R=t.events.length;let C=R,N,k;for(;C--;)if(t.events[C][0]==="exit"&&t.events[C][1].type==="chunkFlow"){if(N){k=t.events[C][1].end;break}N=!0}for(b(r),E=R;Em;){const _=n[v];t.containerState=_[1],_[0].exit.call(t,e)}n.length=m}function g(){a.write([null]),i=void 0,a=void 0,t.containerState._closeFlow=void 0}}function T1(e,t,n){return re(e,e.attempt(this.parser.constructs.document,t,n),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}function Pr(e){if(e===null||le(e)||Xn(e))return 1;if(jo(e))return 2}function Ho(e,t,n){const r=[];let a=-1;for(;++a1&&e[n][1].end.offset-e[n][1].start.offset>1?2:1;const c={...e[r][1].end},f={...e[n][1].start};xb(c,-l),xb(f,l),o={type:l>1?"strongSequence":"emphasisSequence",start:c,end:{...e[r][1].end}},s={type:l>1?"strongSequence":"emphasisSequence",start:{...e[n][1].start},end:f},i={type:l>1?"strongText":"emphasisText",start:{...e[r][1].end},end:{...e[n][1].start}},a={type:l>1?"strong":"emphasis",start:{...o.start},end:{...s.end}},e[r][1].end={...o.start},e[n][1].start={...s.end},u=[],e[r][1].end.offset-e[r][1].start.offset&&(u=bt(u,[["enter",e[r][1],t],["exit",e[r][1],t]])),u=bt(u,[["enter",a,t],["enter",o,t],["exit",o,t],["enter",i,t]]),u=bt(u,Ho(t.parser.constructs.insideSpan.null,e.slice(r+1,n),t)),u=bt(u,[["exit",i,t],["enter",s,t],["exit",s,t],["exit",a,t]]),e[n][1].end.offset-e[n][1].start.offset?(d=2,u=bt(u,[["enter",e[n][1],t],["exit",e[n][1],t]])):d=0,ut(e,r-1,n-r+3,u),n=r+u.length-d-2;break}}for(n=-1;++n0&&ee(E)?re(e,g,"linePrefix",i+1)(E):g(E)}function g(E){return E===null||V(E)?e.check(Ob,y,v)(E):(e.enter("codeFlowValue"),m(E))}function m(E){return E===null||V(E)?(e.exit("codeFlowValue"),g(E)):(e.consume(E),m)}function v(E){return e.exit("codeFenced"),t(E)}function _(E,R,C){let N=0;return k;function k(z){return E.enter("lineEnding"),E.consume(z),E.exit("lineEnding"),I}function I(z){return E.enter("codeFencedFence"),ee(z)?re(E,D,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(z):D(z)}function D(z){return z===s?(E.enter("codeFencedFenceSequence"),q(z)):C(z)}function q(z){return z===s?(N++,E.consume(z),q):N>=o?(E.exit("codeFencedFenceSequence"),ee(z)?re(E,$,"whitespace")(z):$(z)):C(z)}function $(z){return z===null||V(z)?(E.exit("codeFencedFence"),R(z)):C(z)}}}function P1(e,t,n){const r=this;return a;function a(o){return o===null?n(o):(e.enter("lineEnding"),e.consume(o),e.exit("lineEnding"),i)}function i(o){return r.parser.lazy[r.now().line]?n(o):t(o)}}const Ns={name:"codeIndented",tokenize:B1},U1={partial:!0,tokenize:$1};function B1(e,t,n){const r=this;return a;function a(u){return e.enter("codeIndented"),re(e,i,"linePrefix",5)(u)}function i(u){const d=r.events[r.events.length-1];return d&&d[1].type==="linePrefix"&&d[2].sliceSerialize(d[1],!0).length>=4?o(u):n(u)}function o(u){return u===null?l(u):V(u)?e.attempt(U1,o,l)(u):(e.enter("codeFlowValue"),s(u))}function s(u){return u===null||V(u)?(e.exit("codeFlowValue"),o(u)):(e.consume(u),s)}function l(u){return e.exit("codeIndented"),t(u)}}function $1(e,t,n){const r=this;return a;function a(o){return r.parser.lazy[r.now().line]?n(o):V(o)?(e.enter("lineEnding"),e.consume(o),e.exit("lineEnding"),a):re(e,i,"linePrefix",5)(o)}function i(o){const s=r.events[r.events.length-1];return s&&s[1].type==="linePrefix"&&s[2].sliceSerialize(s[1],!0).length>=4?t(o):V(o)?a(o):n(o)}}const z1={name:"codeText",previous:q1,resolve:G1,tokenize:j1};function G1(e){let t=e.length-4,n=3,r,a;if((e[n][1].type==="lineEnding"||e[n][1].type==="space")&&(e[t][1].type==="lineEnding"||e[t][1].type==="space")){for(r=n;++r=this.left.length+this.right.length)throw new RangeError("Cannot access index `"+t+"` in a splice buffer of size `"+(this.left.length+this.right.length)+"`");return tthis.left.length?this.right.slice(this.right.length-r+this.left.length,this.right.length-t+this.left.length).reverse():this.left.slice(t).concat(this.right.slice(this.right.length-r+this.left.length).reverse())}splice(t,n,r){const a=n||0;this.setCursor(Math.trunc(t));const i=this.right.splice(this.right.length-a,Number.POSITIVE_INFINITY);return r&&aa(this.left,r),i.reverse()}pop(){return this.setCursor(Number.POSITIVE_INFINITY),this.left.pop()}push(t){this.setCursor(Number.POSITIVE_INFINITY),this.left.push(t)}pushMany(t){this.setCursor(Number.POSITIVE_INFINITY),aa(this.left,t)}unshift(t){this.setCursor(0),this.right.push(t)}unshiftMany(t){this.setCursor(0),aa(this.right,t.reverse())}setCursor(t){if(!(t===this.left.length||t>this.left.length&&this.right.length===0||t<0&&this.left.length===0))if(t=4?t(o):e.interrupt(r.parser.constructs.flow,n,t)(o)}}function CA(e,t,n,r,a,i,o,s,l){const u=l||Number.POSITIVE_INFINITY;let d=0;return c;function c(b){return b===60?(e.enter(r),e.enter(a),e.enter(i),e.consume(b),e.exit(i),f):b===null||b===32||b===41||vo(b)?n(b):(e.enter(r),e.enter(o),e.enter(s),e.enter("chunkString",{contentType:"string"}),y(b))}function f(b){return b===62?(e.enter(i),e.consume(b),e.exit(i),e.exit(a),e.exit(r),t):(e.enter(s),e.enter("chunkString",{contentType:"string"}),p(b))}function p(b){return b===62?(e.exit("chunkString"),e.exit(s),f(b)):b===null||b===60||V(b)?n(b):(e.consume(b),b===92?h:p)}function h(b){return b===60||b===62||b===92?(e.consume(b),p):p(b)}function y(b){return!d&&(b===null||b===41||le(b))?(e.exit("chunkString"),e.exit(s),e.exit(o),e.exit(r),t(b)):d999||p===null||p===91||p===93&&!l||p===94&&!s&&"_hiddenFootnoteSupport"in o.parser.constructs?n(p):p===93?(e.exit(i),e.enter(a),e.consume(p),e.exit(a),e.exit(r),t):V(p)?(e.enter("lineEnding"),e.consume(p),e.exit("lineEnding"),d):(e.enter("chunkString",{contentType:"string"}),c(p))}function c(p){return p===null||p===91||p===93||V(p)||s++>999?(e.exit("chunkString"),d(p)):(e.consume(p),l||(l=!ee(p)),p===92?f:c)}function f(p){return p===91||p===92||p===93?(e.consume(p),s++,c):c(p)}}function xA(e,t,n,r,a,i){let o;return s;function s(f){return f===34||f===39||f===40?(e.enter(r),e.enter(a),e.consume(f),e.exit(a),o=f===40?41:f,l):n(f)}function l(f){return f===o?(e.enter(a),e.consume(f),e.exit(a),e.exit(r),t):(e.enter(i),u(f))}function u(f){return f===o?(e.exit(i),l(o)):f===null?n(f):V(f)?(e.enter("lineEnding"),e.consume(f),e.exit("lineEnding"),re(e,u,"linePrefix")):(e.enter("chunkString",{contentType:"string"}),d(f))}function d(f){return f===o||f===null||V(f)?(e.exit("chunkString"),u(f)):(e.consume(f),f===92?c:d)}function c(f){return f===o||f===92?(e.consume(f),d):d(f)}}function Ta(e,t){let n;return r;function r(a){return V(a)?(e.enter("lineEnding"),e.consume(a),e.exit("lineEnding"),n=!0,r):ee(a)?re(e,r,n?"linePrefix":"lineSuffix")(a):t(a)}}const Q1={name:"definition",tokenize:eL},J1={partial:!0,tokenize:tL};function eL(e,t,n){const r=this;let a;return i;function i(p){return e.enter("definition"),o(p)}function o(p){return NA.call(r,e,s,n,"definitionLabel","definitionLabelMarker","definitionLabelString")(p)}function s(p){return a=xt(r.sliceSerialize(r.events[r.events.length-1][1]).slice(1,-1)),p===58?(e.enter("definitionMarker"),e.consume(p),e.exit("definitionMarker"),l):n(p)}function l(p){return le(p)?Ta(e,u)(p):u(p)}function u(p){return CA(e,d,n,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(p)}function d(p){return e.attempt(J1,c,c)(p)}function c(p){return ee(p)?re(e,f,"whitespace")(p):f(p)}function f(p){return p===null||V(p)?(e.exit("definition"),r.parser.defined.push(a),t(p)):n(p)}}function tL(e,t,n){return r;function r(s){return le(s)?Ta(e,a)(s):n(s)}function a(s){return xA(e,i,n,"definitionTitle","definitionTitleMarker","definitionTitleString")(s)}function i(s){return ee(s)?re(e,o,"whitespace")(s):o(s)}function o(s){return s===null||V(s)?t(s):n(s)}}const nL={name:"hardBreakEscape",tokenize:rL};function rL(e,t,n){return r;function r(i){return e.enter("hardBreakEscape"),e.consume(i),a}function a(i){return V(i)?(e.exit("hardBreakEscape"),t(i)):n(i)}}const aL={name:"headingAtx",resolve:iL,tokenize:oL};function iL(e,t){let n=e.length-2,r=3,a,i;return e[r][1].type==="whitespace"&&(r+=2),n-2>r&&e[n][1].type==="whitespace"&&(n-=2),e[n][1].type==="atxHeadingSequence"&&(r===n-1||n-4>r&&e[n-2][1].type==="whitespace")&&(n-=r+1===n?2:4),n>r&&(a={type:"atxHeadingText",start:e[r][1].start,end:e[n][1].end},i={type:"chunkText",start:e[r][1].start,end:e[n][1].end,contentType:"text"},ut(e,r,n-r+1,[["enter",a,t],["enter",i,t],["exit",i,t],["exit",a,t]])),e}function oL(e,t,n){let r=0;return a;function a(d){return e.enter("atxHeading"),i(d)}function i(d){return e.enter("atxHeadingSequence"),o(d)}function o(d){return d===35&&r++<6?(e.consume(d),o):d===null||le(d)?(e.exit("atxHeadingSequence"),s(d)):n(d)}function s(d){return d===35?(e.enter("atxHeadingSequence"),l(d)):d===null||V(d)?(e.exit("atxHeading"),t(d)):ee(d)?re(e,s,"whitespace")(d):(e.enter("atxHeadingText"),u(d))}function l(d){return d===35?(e.consume(d),l):(e.exit("atxHeadingSequence"),s(d))}function u(d){return d===null||d===35||le(d)?(e.exit("atxHeadingText"),s(d)):(e.consume(d),u)}}const sL=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],Db=["pre","script","style","textarea"],lL={concrete:!0,name:"htmlFlow",resolveTo:dL,tokenize:pL},uL={partial:!0,tokenize:gL},cL={partial:!0,tokenize:fL};function dL(e){let t=e.length;for(;t--&&!(e[t][0]==="enter"&&e[t][1].type==="htmlFlow"););return t>1&&e[t-2][1].type==="linePrefix"&&(e[t][1].start=e[t-2][1].start,e[t+1][1].start=e[t-2][1].start,e.splice(t-2,2)),e}function pL(e,t,n){const r=this;let a,i,o,s,l;return u;function u(A){return d(A)}function d(A){return e.enter("htmlFlow"),e.enter("htmlFlowData"),e.consume(A),c}function c(A){return A===33?(e.consume(A),f):A===47?(e.consume(A),i=!0,y):A===63?(e.consume(A),a=3,r.interrupt?t:S):Ge(A)?(e.consume(A),o=String.fromCharCode(A),T):n(A)}function f(A){return A===45?(e.consume(A),a=2,p):A===91?(e.consume(A),a=5,s=0,h):Ge(A)?(e.consume(A),a=4,r.interrupt?t:S):n(A)}function p(A){return A===45?(e.consume(A),r.interrupt?t:S):n(A)}function h(A){const Q="CDATA[";return A===Q.charCodeAt(s++)?(e.consume(A),s===Q.length?r.interrupt?t:D:h):n(A)}function y(A){return Ge(A)?(e.consume(A),o=String.fromCharCode(A),T):n(A)}function T(A){if(A===null||A===47||A===62||le(A)){const Q=A===47,ue=o.toLowerCase();return!Q&&!i&&Db.includes(ue)?(a=1,r.interrupt?t(A):D(A)):sL.includes(o.toLowerCase())?(a=6,Q?(e.consume(A),b):r.interrupt?t(A):D(A)):(a=7,r.interrupt&&!r.parser.lazy[r.now().line]?n(A):i?g(A):m(A))}return A===45||Fe(A)?(e.consume(A),o+=String.fromCharCode(A),T):n(A)}function b(A){return A===62?(e.consume(A),r.interrupt?t:D):n(A)}function g(A){return ee(A)?(e.consume(A),g):k(A)}function m(A){return A===47?(e.consume(A),k):A===58||A===95||Ge(A)?(e.consume(A),v):ee(A)?(e.consume(A),m):k(A)}function v(A){return A===45||A===46||A===58||A===95||Fe(A)?(e.consume(A),v):_(A)}function _(A){return A===61?(e.consume(A),E):ee(A)?(e.consume(A),_):m(A)}function E(A){return A===null||A===60||A===61||A===62||A===96?n(A):A===34||A===39?(e.consume(A),l=A,R):ee(A)?(e.consume(A),E):C(A)}function R(A){return A===l?(e.consume(A),l=null,N):A===null||V(A)?n(A):(e.consume(A),R)}function C(A){return A===null||A===34||A===39||A===47||A===60||A===61||A===62||A===96||le(A)?_(A):(e.consume(A),C)}function N(A){return A===47||A===62||ee(A)?m(A):n(A)}function k(A){return A===62?(e.consume(A),I):n(A)}function I(A){return A===null||V(A)?D(A):ee(A)?(e.consume(A),I):n(A)}function D(A){return A===45&&a===2?(e.consume(A),H):A===60&&a===1?(e.consume(A),Y):A===62&&a===4?(e.consume(A),P):A===63&&a===3?(e.consume(A),S):A===93&&a===5?(e.consume(A),M):V(A)&&(a===6||a===7)?(e.exit("htmlFlowData"),e.check(uL,G,q)(A)):A===null||V(A)?(e.exit("htmlFlowData"),q(A)):(e.consume(A),D)}function q(A){return e.check(cL,$,G)(A)}function $(A){return e.enter("lineEnding"),e.consume(A),e.exit("lineEnding"),z}function z(A){return A===null||V(A)?q(A):(e.enter("htmlFlowData"),D(A))}function H(A){return A===45?(e.consume(A),S):D(A)}function Y(A){return A===47?(e.consume(A),o="",x):D(A)}function x(A){if(A===62){const Q=o.toLowerCase();return Db.includes(Q)?(e.consume(A),P):D(A)}return Ge(A)&&o.length<8?(e.consume(A),o+=String.fromCharCode(A),x):D(A)}function M(A){return A===93?(e.consume(A),S):D(A)}function S(A){return A===62?(e.consume(A),P):A===45&&a===2?(e.consume(A),S):D(A)}function P(A){return A===null||V(A)?(e.exit("htmlFlowData"),G(A)):(e.consume(A),P)}function G(A){return e.exit("htmlFlow"),t(A)}}function fL(e,t,n){const r=this;return a;function a(o){return V(o)?(e.enter("lineEnding"),e.consume(o),e.exit("lineEnding"),i):n(o)}function i(o){return r.parser.lazy[r.now().line]?n(o):t(o)}}function gL(e,t,n){return r;function r(a){return e.enter("lineEnding"),e.consume(a),e.exit("lineEnding"),e.attempt(ei,t,n)}}const mL={name:"htmlText",tokenize:hL};function hL(e,t,n){const r=this;let a,i,o;return s;function s(S){return e.enter("htmlText"),e.enter("htmlTextData"),e.consume(S),l}function l(S){return S===33?(e.consume(S),u):S===47?(e.consume(S),_):S===63?(e.consume(S),m):Ge(S)?(e.consume(S),C):n(S)}function u(S){return S===45?(e.consume(S),d):S===91?(e.consume(S),i=0,h):Ge(S)?(e.consume(S),g):n(S)}function d(S){return S===45?(e.consume(S),p):n(S)}function c(S){return S===null?n(S):S===45?(e.consume(S),f):V(S)?(o=c,Y(S)):(e.consume(S),c)}function f(S){return S===45?(e.consume(S),p):c(S)}function p(S){return S===62?H(S):S===45?f(S):c(S)}function h(S){const P="CDATA[";return S===P.charCodeAt(i++)?(e.consume(S),i===P.length?y:h):n(S)}function y(S){return S===null?n(S):S===93?(e.consume(S),T):V(S)?(o=y,Y(S)):(e.consume(S),y)}function T(S){return S===93?(e.consume(S),b):y(S)}function b(S){return S===62?H(S):S===93?(e.consume(S),b):y(S)}function g(S){return S===null||S===62?H(S):V(S)?(o=g,Y(S)):(e.consume(S),g)}function m(S){return S===null?n(S):S===63?(e.consume(S),v):V(S)?(o=m,Y(S)):(e.consume(S),m)}function v(S){return S===62?H(S):m(S)}function _(S){return Ge(S)?(e.consume(S),E):n(S)}function E(S){return S===45||Fe(S)?(e.consume(S),E):R(S)}function R(S){return V(S)?(o=R,Y(S)):ee(S)?(e.consume(S),R):H(S)}function C(S){return S===45||Fe(S)?(e.consume(S),C):S===47||S===62||le(S)?N(S):n(S)}function N(S){return S===47?(e.consume(S),H):S===58||S===95||Ge(S)?(e.consume(S),k):V(S)?(o=N,Y(S)):ee(S)?(e.consume(S),N):H(S)}function k(S){return S===45||S===46||S===58||S===95||Fe(S)?(e.consume(S),k):I(S)}function I(S){return S===61?(e.consume(S),D):V(S)?(o=I,Y(S)):ee(S)?(e.consume(S),I):N(S)}function D(S){return S===null||S===60||S===61||S===62||S===96?n(S):S===34||S===39?(e.consume(S),a=S,q):V(S)?(o=D,Y(S)):ee(S)?(e.consume(S),D):(e.consume(S),$)}function q(S){return S===a?(e.consume(S),a=void 0,z):S===null?n(S):V(S)?(o=q,Y(S)):(e.consume(S),q)}function $(S){return S===null||S===34||S===39||S===60||S===61||S===96?n(S):S===47||S===62||le(S)?N(S):(e.consume(S),$)}function z(S){return S===47||S===62||le(S)?N(S):n(S)}function H(S){return S===62?(e.consume(S),e.exit("htmlTextData"),e.exit("htmlText"),t):n(S)}function Y(S){return e.exit("htmlTextData"),e.enter("lineEnding"),e.consume(S),e.exit("lineEnding"),x}function x(S){return ee(S)?re(e,M,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(S):M(S)}function M(S){return e.enter("htmlTextData"),o(S)}}const gm={name:"labelEnd",resolveAll:SL,resolveTo:vL,tokenize:kL},bL={tokenize:wL},yL={tokenize:_L},EL={tokenize:TL};function SL(e){let t=-1;const n=[];for(;++t=3&&(u===null||V(u))?(e.exit("thematicBreak"),t(u)):n(u)}function l(u){return u===a?(e.consume(u),r++,l):(e.exit("thematicBreakSequence"),ee(u)?re(e,s,"whitespace")(u):s(u))}}const Ye={continuation:{tokenize:ML},exit:PL,name:"list",tokenize:DL},OL={partial:!0,tokenize:UL},LL={partial:!0,tokenize:FL};function DL(e,t,n){const r=this,a=r.events[r.events.length-1];let i=a&&a[1].type==="linePrefix"?a[2].sliceSerialize(a[1],!0).length:0,o=0;return s;function s(p){const h=r.containerState.type||(p===42||p===43||p===45?"listUnordered":"listOrdered");if(h==="listUnordered"?!r.containerState.marker||p===r.containerState.marker:Xf(p)){if(r.containerState.type||(r.containerState.type=h,e.enter(h,{_container:!0})),h==="listUnordered")return e.enter("listItemPrefix"),p===42||p===45?e.check(Hi,n,u)(p):u(p);if(!r.interrupt||p===49)return e.enter("listItemPrefix"),e.enter("listItemValue"),l(p)}return n(p)}function l(p){return Xf(p)&&++o<10?(e.consume(p),l):(!r.interrupt||o<2)&&(r.containerState.marker?p===r.containerState.marker:p===41||p===46)?(e.exit("listItemValue"),u(p)):n(p)}function u(p){return e.enter("listItemMarker"),e.consume(p),e.exit("listItemMarker"),r.containerState.marker=r.containerState.marker||p,e.check(ei,r.interrupt?n:d,e.attempt(OL,f,c))}function d(p){return r.containerState.initialBlankLine=!0,i++,f(p)}function c(p){return ee(p)?(e.enter("listItemPrefixWhitespace"),e.consume(p),e.exit("listItemPrefixWhitespace"),f):n(p)}function f(p){return r.containerState.size=i+r.sliceSerialize(e.exit("listItemPrefix"),!0).length,t(p)}}function ML(e,t,n){const r=this;return r.containerState._closeFlow=void 0,e.check(ei,a,i);function a(s){return r.containerState.furtherBlankLines=r.containerState.furtherBlankLines||r.containerState.initialBlankLine,re(e,t,"listItemIndent",r.containerState.size+1)(s)}function i(s){return r.containerState.furtherBlankLines||!ee(s)?(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,o(s)):(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,e.attempt(LL,t,o)(s))}function o(s){return r.containerState._closeFlow=!0,r.interrupt=void 0,re(e,e.attempt(Ye,t,n),"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(s)}}function FL(e,t,n){const r=this;return re(e,a,"listItemIndent",r.containerState.size+1);function a(i){const o=r.events[r.events.length-1];return o&&o[1].type==="listItemIndent"&&o[2].sliceSerialize(o[1],!0).length===r.containerState.size?t(i):n(i)}}function PL(e){e.exit(this.containerState.type)}function UL(e,t,n){const r=this;return re(e,a,"listItemPrefixWhitespace",r.parser.constructs.disable.null.includes("codeIndented")?void 0:5);function a(i){const o=r.events[r.events.length-1];return!ee(i)&&o&&o[1].type==="listItemPrefixWhitespace"?t(i):n(i)}}const Mb={name:"setextUnderline",resolveTo:BL,tokenize:$L};function BL(e,t){let n=e.length,r,a,i;for(;n--;)if(e[n][0]==="enter"){if(e[n][1].type==="content"){r=n;break}e[n][1].type==="paragraph"&&(a=n)}else e[n][1].type==="content"&&e.splice(n,1),!i&&e[n][1].type==="definition"&&(i=n);const o={type:"setextHeading",start:{...e[r][1].start},end:{...e[e.length-1][1].end}};return e[a][1].type="setextHeadingText",i?(e.splice(a,0,["enter",o,t]),e.splice(i+1,0,["exit",e[r][1],t]),e[r][1].end={...e[i][1].end}):e[r][1]=o,e.push(["exit",o,t]),e}function $L(e,t,n){const r=this;let a;return i;function i(u){let d=r.events.length,c;for(;d--;)if(r.events[d][1].type!=="lineEnding"&&r.events[d][1].type!=="linePrefix"&&r.events[d][1].type!=="content"){c=r.events[d][1].type==="paragraph";break}return!r.parser.lazy[r.now().line]&&(r.interrupt||c)?(e.enter("setextHeadingLine"),a=u,o(u)):n(u)}function o(u){return e.enter("setextHeadingLineSequence"),s(u)}function s(u){return u===a?(e.consume(u),s):(e.exit("setextHeadingLineSequence"),ee(u)?re(e,l,"lineSuffix")(u):l(u))}function l(u){return u===null||V(u)?(e.exit("setextHeadingLine"),t(u)):n(u)}}const zL={tokenize:GL};function GL(e){const t=this,n=e.attempt(ei,r,e.attempt(this.parser.constructs.flowInitial,a,re(e,e.attempt(this.parser.constructs.flow,a,e.attempt(W1,a)),"linePrefix")));return n;function r(i){if(i===null){e.consume(i);return}return e.enter("lineEndingBlank"),e.consume(i),e.exit("lineEndingBlank"),t.currentConstruct=void 0,n}function a(i){if(i===null){e.consume(i);return}return e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),t.currentConstruct=void 0,n}}const qL={resolveAll:LA()},jL=OA("string"),HL=OA("text");function OA(e){return{resolveAll:LA(e==="text"?VL:void 0),tokenize:t};function t(n){const r=this,a=this.parser.constructs[e],i=n.attempt(a,o,s);return o;function o(d){return u(d)?i(d):s(d)}function s(d){if(d===null){n.consume(d);return}return n.enter("data"),n.consume(d),l}function l(d){return u(d)?(n.exit("data"),i(d)):(n.consume(d),l)}function u(d){if(d===null)return!0;const c=a[d];let f=-1;if(c)for(;++f-1){const s=o[0];typeof s=="string"?o[0]=s.slice(r):o.shift()}i>0&&o.push(e[a].slice(0,i))}return o}function iD(e,t){let n=-1;const r=[];let a;for(;++n0){const wt=K.tokenStack[K.tokenStack.length-1];(wt[1]||Pb).call(K,void 0,wt[0])}for(B.position={start:un(O.length>0?O[0][1].start:{line:1,column:1,offset:0}),end:un(O.length>0?O[O.length-2][1].end:{line:1,column:1,offset:0})},oe=-1;++oe0&&(r.className=["language-"+a[0]]);let i={type:"element",tagName:"code",properties:r,children:[{type:"text",value:n}]};return t.meta&&(i.data={meta:t.meta}),e.patch(t,i),i=e.applyData(t,i),i={type:"element",tagName:"pre",properties:{},children:[i]},e.patch(t,i),i}function ED(e,t){const n={type:"element",tagName:"del",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function SD(e,t){const n={type:"element",tagName:"em",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function vD(e,t){const n=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",r=String(t.identifier).toUpperCase(),a=Gr(r.toLowerCase()),i=e.footnoteOrder.indexOf(r);let o,s=e.footnoteCounts.get(r);s===void 0?(s=0,e.footnoteOrder.push(r),o=e.footnoteOrder.length):o=i+1,s+=1,e.footnoteCounts.set(r,s);const l={type:"element",tagName:"a",properties:{href:"#"+n+"fn-"+a,id:n+"fnref-"+a+(s>1?"-"+s:""),dataFootnoteRef:!0,ariaDescribedBy:["footnote-label"]},children:[{type:"text",value:String(o)}]};e.patch(t,l);const u={type:"element",tagName:"sup",properties:{},children:[l]};return e.patch(t,u),e.applyData(t,u)}function kD(e,t){const n={type:"element",tagName:"h"+t.depth,properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function wD(e,t){if(e.options.allowDangerousHtml){const n={type:"raw",value:t.value};return e.patch(t,n),e.applyData(t,n)}}function FA(e,t){const n=t.referenceType;let r="]";if(n==="collapsed"?r+="[]":n==="full"&&(r+="["+(t.label||t.identifier)+"]"),t.type==="imageReference")return[{type:"text",value:"!["+t.alt+r}];const a=e.all(t),i=a[0];i&&i.type==="text"?i.value="["+i.value:a.unshift({type:"text",value:"["});const o=a[a.length-1];return o&&o.type==="text"?o.value+=r:a.push({type:"text",value:r}),a}function _D(e,t){const n=String(t.identifier).toUpperCase(),r=e.definitionById.get(n);if(!r)return FA(e,t);const a={src:Gr(r.url||""),alt:t.alt};r.title!==null&&r.title!==void 0&&(a.title=r.title);const i={type:"element",tagName:"img",properties:a,children:[]};return e.patch(t,i),e.applyData(t,i)}function TD(e,t){const n={src:Gr(t.url)};t.alt!==null&&t.alt!==void 0&&(n.alt=t.alt),t.title!==null&&t.title!==void 0&&(n.title=t.title);const r={type:"element",tagName:"img",properties:n,children:[]};return e.patch(t,r),e.applyData(t,r)}function AD(e,t){const n={type:"text",value:t.value.replace(/\r?\n|\r/g," ")};e.patch(t,n);const r={type:"element",tagName:"code",properties:{},children:[n]};return e.patch(t,r),e.applyData(t,r)}function RD(e,t){const n=String(t.identifier).toUpperCase(),r=e.definitionById.get(n);if(!r)return FA(e,t);const a={href:Gr(r.url||"")};r.title!==null&&r.title!==void 0&&(a.title=r.title);const i={type:"element",tagName:"a",properties:a,children:e.all(t)};return e.patch(t,i),e.applyData(t,i)}function ID(e,t){const n={href:Gr(t.url)};t.title!==null&&t.title!==void 0&&(n.title=t.title);const r={type:"element",tagName:"a",properties:n,children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function CD(e,t,n){const r=e.all(t),a=n?ND(n):PA(t),i={},o=[];if(typeof t.checked=="boolean"){const d=r[0];let c;d&&d.type==="element"&&d.tagName==="p"?c=d:(c={type:"element",tagName:"p",properties:{},children:[]},r.unshift(c)),c.children.length>0&&c.children.unshift({type:"text",value:" "}),c.children.unshift({type:"element",tagName:"input",properties:{type:"checkbox",checked:t.checked,disabled:!0},children:[]}),i.className=["task-list-item"]}let s=-1;for(;++s1}function xD(e,t){const n={},r=e.all(t);let a=-1;for(typeof t.start=="number"&&t.start!==1&&(n.start=t.start);++a0){const o={type:"element",tagName:"tbody",properties:{},children:e.wrap(n,!0)},s=lm(t.children[1]),l=hA(t.children[t.children.length-1]);s&&l&&(o.position={start:s,end:l}),a.push(o)}const i={type:"element",tagName:"table",properties:{},children:e.wrap(a,!0)};return e.patch(t,i),e.applyData(t,i)}function FD(e,t,n){const r=n?n.children:void 0,i=(r?r.indexOf(t):1)===0?"th":"td",o=n&&n.type==="table"?n.align:void 0,s=o?o.length:t.children.length;let l=-1;const u=[];for(;++l0,!0),r[0]),a=r.index+r[0].length,r=n.exec(t);return i.push($b(t.slice(a),a>0,!1)),i.join("")}function $b(e,t,n){let r=0,a=e.length;if(t){let i=e.codePointAt(r);for(;i===Ub||i===Bb;)r++,i=e.codePointAt(r)}if(n){let i=e.codePointAt(a-1);for(;i===Ub||i===Bb;)a--,i=e.codePointAt(a-1)}return a>r?e.slice(r,a):""}function BD(e,t){const n={type:"text",value:UD(String(t.value))};return e.patch(t,n),e.applyData(t,n)}function $D(e,t){const n={type:"element",tagName:"hr",properties:{},children:[]};return e.patch(t,n),e.applyData(t,n)}const zD={blockquote:hD,break:bD,code:yD,delete:ED,emphasis:SD,footnoteReference:vD,heading:kD,html:wD,imageReference:_D,image:TD,inlineCode:AD,linkReference:RD,link:ID,listItem:CD,list:xD,paragraph:OD,root:LD,strong:DD,table:MD,tableCell:PD,tableRow:FD,text:BD,thematicBreak:$D,toml:Ai,yaml:Ai,definition:Ai,footnoteDefinition:Ai};function Ai(){}const UA=-1,Vo=0,Aa=1,ko=2,mm=3,hm=4,bm=5,ym=6,BA=7,$A=8,zb=typeof self=="object"?self:globalThis,GD=(e,t)=>{const n=(a,i)=>(e.set(i,a),a),r=a=>{if(e.has(a))return e.get(a);const[i,o]=t[a];switch(i){case Vo:case UA:return n(o,a);case Aa:{const s=n([],a);for(const l of o)s.push(r(l));return s}case ko:{const s=n({},a);for(const[l,u]of o)s[r(l)]=r(u);return s}case mm:return n(new Date(o),a);case hm:{const{source:s,flags:l}=o;return n(new RegExp(s,l),a)}case bm:{const s=n(new Map,a);for(const[l,u]of o)s.set(r(l),r(u));return s}case ym:{const s=n(new Set,a);for(const l of o)s.add(r(l));return s}case BA:{const{name:s,message:l}=o;return n(new zb[s](l),a)}case $A:return n(BigInt(o),a);case"BigInt":return n(Object(BigInt(o)),a);case"ArrayBuffer":return n(new Uint8Array(o).buffer,o);case"DataView":{const{buffer:s}=new Uint8Array(o);return n(new DataView(s),o)}}return n(new zb[i](o),a)};return r},Gb=e=>GD(new Map,e)(0),ir="",{toString:qD}={},{keys:jD}=Object,ia=e=>{const t=typeof e;if(t!=="object"||!e)return[Vo,t];const n=qD.call(e).slice(8,-1);switch(n){case"Array":return[Aa,ir];case"Object":return[ko,ir];case"Date":return[mm,ir];case"RegExp":return[hm,ir];case"Map":return[bm,ir];case"Set":return[ym,ir];case"DataView":return[Aa,n]}return n.includes("Array")?[Aa,n]:n.includes("Error")?[BA,n]:[ko,n]},Ri=([e,t])=>e===Vo&&(t==="function"||t==="symbol"),HD=(e,t,n,r)=>{const a=(o,s)=>{const l=r.push(o)-1;return n.set(s,l),l},i=o=>{if(n.has(o))return n.get(o);let[s,l]=ia(o);switch(s){case Vo:{let d=o;switch(l){case"bigint":s=$A,d=o.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+l);d=null;break;case"undefined":return a([UA],o)}return a([s,d],o)}case Aa:{if(l){let f=o;return l==="DataView"?f=new Uint8Array(o.buffer):l==="ArrayBuffer"&&(f=new Uint8Array(o)),a([l,[...f]],o)}const d=[],c=a([s,d],o);for(const f of o)d.push(i(f));return c}case ko:{if(l)switch(l){case"BigInt":return a([l,o.toString()],o);case"Boolean":case"Number":case"String":return a([l,o.valueOf()],o)}if(t&&"toJSON"in o)return i(o.toJSON());const d=[],c=a([s,d],o);for(const f of jD(o))(e||!Ri(ia(o[f])))&&d.push([i(f),i(o[f])]);return c}case mm:return a([s,o.toISOString()],o);case hm:{const{source:d,flags:c}=o;return a([s,{source:d,flags:c}],o)}case bm:{const d=[],c=a([s,d],o);for(const[f,p]of o)(e||!(Ri(ia(f))||Ri(ia(p))))&&d.push([i(f),i(p)]);return c}case ym:{const d=[],c=a([s,d],o);for(const f of o)(e||!Ri(ia(f)))&&d.push(i(f));return c}}const{message:u}=o;return a([s,{name:l,message:u}],o)};return i},qb=(e,{json:t,lossy:n}={})=>{const r=[];return HD(!(t||n),!!t,new Map,r)(e),r},wo=typeof structuredClone=="function"?(e,t)=>t&&("json"in t||"lossy"in t)?Gb(qb(e,t)):structuredClone(e):(e,t)=>Gb(qb(e,t));function VD(e,t){const n=[{type:"text",value:"↩"}];return t>1&&n.push({type:"element",tagName:"sup",properties:{},children:[{type:"text",value:String(t)}]}),n}function WD(e,t){return"Back to reference "+(e+1)+(t>1?"-"+t:"")}function YD(e){const t=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",n=e.options.footnoteBackContent||VD,r=e.options.footnoteBackLabel||WD,a=e.options.footnoteLabel||"Footnotes",i=e.options.footnoteLabelTagName||"h2",o=e.options.footnoteLabelProperties||{className:["sr-only"]},s=[];let l=-1;for(;++l0&&h.push({type:"text",value:" "});let g=typeof n=="string"?n:n(l,p);typeof g=="string"&&(g={type:"text",value:g}),h.push({type:"element",tagName:"a",properties:{href:"#"+t+"fnref-"+f+(p>1?"-"+p:""),dataFootnoteBackref:"",ariaLabel:typeof r=="string"?r:r(l,p),className:["data-footnote-backref"]},children:Array.isArray(g)?g:[g]})}const T=d[d.length-1];if(T&&T.type==="element"&&T.tagName==="p"){const g=T.children[T.children.length-1];g&&g.type==="text"?g.value+=" ":T.children.push({type:"text",value:" "}),T.children.push(...h)}else d.push(...h);const b={type:"element",tagName:"li",properties:{id:t+"fn-"+f},children:e.wrap(d,!0)};e.patch(u,b),s.push(b)}if(s.length!==0)return{type:"element",tagName:"section",properties:{dataFootnotes:!0,className:["footnotes"]},children:[{type:"element",tagName:i,properties:{...wo(o),id:"footnote-label"},children:[{type:"text",value:a}]},{type:"text",value:` +`},{type:"element",tagName:"ol",properties:{},children:e.wrap(s,!0)},{type:"text",value:` +`}]}}const Wo=function(e){if(e==null)return QD;if(typeof e=="function")return Yo(e);if(typeof e=="object")return Array.isArray(e)?KD(e):XD(e);if(typeof e=="string")return ZD(e);throw new Error("Expected function, string, or object as test")};function KD(e){const t=[];let n=-1;for(;++n":""))+")"})}return f;function f(){let p=zA,h,y,T;if((!t||i(l,u,d[d.length-1]||void 0))&&(p=n0(n(l,d)),p[0]===Qf))return p;if("children"in l&&l.children){const b=l;if(b.children&&p[0]!==t0)for(y=(r?b.children.length:-1)+o,T=d.concat(b);y>-1&&y0&&n.push({type:"text",value:` +`}),n}function jb(e){let t=0,n=e.charCodeAt(t);for(;n===9||n===32;)t++,n=e.charCodeAt(t);return e.slice(t)}function Hb(e,t){const n=a0(e,t),r=n.one(e,void 0),a=YD(n),i=Array.isArray(r)?{type:"root",children:r}:r||{type:"root",children:[]};return a&&i.children.push({type:"text",value:` +`},a),i}function u0(e,t){return e&&"run"in e?async function(n,r){const a=Hb(n,{file:r,...t});await e.run(a,r)}:function(n,r){return Hb(n,{file:r,...e||t})}}function Vb(e){if(e)throw e}var Vi=Object.prototype.hasOwnProperty,qA=Object.prototype.toString,Wb=Object.defineProperty,Yb=Object.getOwnPropertyDescriptor,Kb=function(t){return typeof Array.isArray=="function"?Array.isArray(t):qA.call(t)==="[object Array]"},Xb=function(t){if(!t||qA.call(t)!=="[object Object]")return!1;var n=Vi.call(t,"constructor"),r=t.constructor&&t.constructor.prototype&&Vi.call(t.constructor.prototype,"isPrototypeOf");if(t.constructor&&!n&&!r)return!1;var a;for(a in t);return typeof a>"u"||Vi.call(t,a)},Zb=function(t,n){Wb&&n.name==="__proto__"?Wb(t,n.name,{enumerable:!0,configurable:!0,value:n.newValue,writable:!0}):t[n.name]=n.newValue},Qb=function(t,n){if(n==="__proto__")if(Vi.call(t,n)){if(Yb)return Yb(t,n).value}else return;return t[n]},c0=function e(){var t,n,r,a,i,o,s=arguments[0],l=1,u=arguments.length,d=!1;for(typeof s=="boolean"&&(d=s,s=arguments[1]||{},l=2),(s==null||typeof s!="object"&&typeof s!="function")&&(s={});lo.length;let l;s&&o.push(a);try{l=e.apply(this,o)}catch(u){const d=u;if(s&&n)throw d;return a(d)}s||(l&&l.then&&typeof l.then=="function"?l.then(i,a):l instanceof Error?a(l):i(l))}function a(o,...s){n||(n=!0,t(o,...s))}function i(o){a(null,o)}}const Mt={basename:f0,dirname:g0,extname:m0,join:h0,sep:"/"};function f0(e,t){if(t!==void 0&&typeof t!="string")throw new TypeError('"ext" argument must be a string');ti(e);let n=0,r=-1,a=e.length,i;if(t===void 0||t.length===0||t.length>e.length){for(;a--;)if(e.codePointAt(a)===47){if(i){n=a+1;break}}else r<0&&(i=!0,r=a+1);return r<0?"":e.slice(n,r)}if(t===e)return"";let o=-1,s=t.length-1;for(;a--;)if(e.codePointAt(a)===47){if(i){n=a+1;break}}else o<0&&(i=!0,o=a+1),s>-1&&(e.codePointAt(a)===t.codePointAt(s--)?s<0&&(r=a):(s=-1,r=o));return n===r?r=o:r<0&&(r=e.length),e.slice(n,r)}function g0(e){if(ti(e),e.length===0)return".";let t=-1,n=e.length,r;for(;--n;)if(e.codePointAt(n)===47){if(r){t=n;break}}else r||(r=!0);return t<0?e.codePointAt(0)===47?"/":".":t===1&&e.codePointAt(0)===47?"//":e.slice(0,t)}function m0(e){ti(e);let t=e.length,n=-1,r=0,a=-1,i=0,o;for(;t--;){const s=e.codePointAt(t);if(s===47){if(o){r=t+1;break}continue}n<0&&(o=!0,n=t+1),s===46?a<0?a=t:i!==1&&(i=1):a>-1&&(i=-1)}return a<0||n<0||i===0||i===1&&a===n-1&&a===r+1?"":e.slice(a,n)}function h0(...e){let t=-1,n;for(;++t0&&e.codePointAt(e.length-1)===47&&(n+="/"),t?"/"+n:n}function y0(e,t){let n="",r=0,a=-1,i=0,o=-1,s,l;for(;++o<=e.length;){if(o2){if(l=n.lastIndexOf("/"),l!==n.length-1){l<0?(n="",r=0):(n=n.slice(0,l),r=n.length-1-n.lastIndexOf("/")),a=o,i=0;continue}}else if(n.length>0){n="",r=0,a=o,i=0;continue}}t&&(n=n.length>0?n+"/..":"..",r=2)}else n.length>0?n+="/"+e.slice(a+1,o):n=e.slice(a+1,o),r=o-a-1;a=o,i=0}else s===46&&i>-1?i++:i=-1}return n}function ti(e){if(typeof e!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}const E0={cwd:S0};function S0(){return"/"}function tg(e){return!!(e!==null&&typeof e=="object"&&"href"in e&&e.href&&"protocol"in e&&e.protocol&&e.auth===void 0)}function v0(e){if(typeof e=="string")e=new URL(e);else if(!tg(e)){const t=new TypeError('The "path" argument must be of type string or an instance of URL. Received `'+e+"`");throw t.code="ERR_INVALID_ARG_TYPE",t}if(e.protocol!=="file:"){const t=new TypeError("The URL must be of scheme file");throw t.code="ERR_INVALID_URL_SCHEME",t}return k0(e)}function k0(e){if(e.hostname!==""){const r=new TypeError('File URL host must be "localhost" or empty on darwin');throw r.code="ERR_INVALID_FILE_URL_HOST",r}const t=e.pathname;let n=-1;for(;++n0){let[p,...h]=d;const y=r[f][1];eg(y)&&eg(p)&&(p=Os(!0,y,p)),r[f]=[u,p,...h]}}}}const A0=new Sm().freeze();function Fs(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `parser`")}function Ps(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `compiler`")}function Us(e,t){if(t)throw new Error("Cannot call `"+e+"` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.")}function ey(e){if(!eg(e)||typeof e.type!="string")throw new TypeError("Expected node, got `"+e+"`")}function ty(e,t,n){if(!n)throw new Error("`"+e+"` finished async. Use `"+t+"` instead")}function Ii(e){return R0(e)?e:new jA(e)}function R0(e){return!!(e&&typeof e=="object"&&"message"in e&&"messages"in e)}function I0(e){return typeof e=="string"||C0(e)}function C0(e){return!!(e&&typeof e=="object"&&"byteLength"in e&&"byteOffset"in e)}const N0="https://github.com/remarkjs/react-markdown/blob/main/changelog.md",ny=[],ry={allowDangerousHtml:!0},x0=/^(https?|ircs?|mailto|xmpp)$/i,O0=[{from:"astPlugins",id:"remove-buggy-html-in-markdown-parser"},{from:"allowDangerousHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"allowNode",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowElement"},{from:"allowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowedElements"},{from:"disallowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"disallowedElements"},{from:"escapeHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"includeElementIndex",id:"#remove-includeelementindex"},{from:"includeNodeIndex",id:"change-includenodeindex-to-includeelementindex"},{from:"linkTarget",id:"remove-linktarget"},{from:"plugins",id:"change-plugins-to-remarkplugins",to:"remarkPlugins"},{from:"rawSourcePos",id:"#remove-rawsourcepos"},{from:"renderers",id:"change-renderers-to-components",to:"components"},{from:"source",id:"change-source-to-children",to:"children"},{from:"sourcePos",id:"#remove-sourcepos"},{from:"transformImageUri",id:"#add-urltransform",to:"urlTransform"},{from:"transformLinkUri",id:"#add-urltransform",to:"urlTransform"}];function L0(e){const t=D0(e),n=M0(e);return F0(t.runSync(t.parse(n),n),e)}function D0(e){const t=e.rehypePlugins||ny,n=e.remarkPlugins||ny,r=e.remarkRehypeOptions?{...e.remarkRehypeOptions,...ry}:ry;return A0().use(mD).use(n).use(u0,r).use(t)}function M0(e){const t=e.children||"",n=new jA;return typeof t=="string"&&(n.value=t),n}function F0(e,t){const n=t.allowedElements,r=t.allowElement,a=t.components,i=t.disallowedElements,o=t.skipHtml,s=t.unwrapDisallowed,l=t.urlTransform||P0;for(const d of O0)Object.hasOwn(t,d.from)&&(""+d.from+(d.to?"use `"+d.to+"` instead":"remove it")+N0+d.id,void 0);return t.className&&(e={type:"element",tagName:"div",properties:{className:t.className},children:e.type==="root"?e.children:[e]}),Em(e,u),QO(e,{Fragment:L.Fragment,components:a,ignoreInvalidStyle:!0,jsx:L.jsx,jsxs:L.jsxs,passKeys:!0,passNode:!0});function u(d,c,f){if(d.type==="raw"&&f&&typeof c=="number")return o?f.children.splice(c,1):f.children[c]={type:"text",value:d.value},c;if(d.type==="element"){let p;for(p in Cs)if(Object.hasOwn(Cs,p)&&Object.hasOwn(d.properties,p)){const h=d.properties[p],y=Cs[p];(y===null||y.includes(d.tagName))&&(d.properties[p]=l(String(h||""),p,d))}}if(d.type==="element"){let p=n?!n.includes(d.tagName):i?i.includes(d.tagName):!1;if(!p&&r&&typeof c=="number"&&(p=!r(d,c,f)),p&&f&&typeof c=="number")return s&&d.children?f.children.splice(c,1,...d.children):f.children.splice(c,1),c}}}function P0(e){const t=e.indexOf(":"),n=e.indexOf("?"),r=e.indexOf("#"),a=e.indexOf("/");return t===-1||a!==-1&&t>a||n!==-1&&t>n||r!==-1&&t>r||x0.test(e.slice(0,t))?e:""}function ay(e,t){const n=String(e);if(typeof t!="string")throw new TypeError("Expected character");let r=0,a=n.indexOf(t);for(;a!==-1;)r++,a=n.indexOf(t,a+t.length);return r}function U0(e){if(typeof e!="string")throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}function B0(e,t,n){const a=Wo((n||{}).ignore||[]),i=$0(t);let o=-1;for(;++o0?{type:"text",value:E}:void 0),E===!1?f.lastIndex=v+1:(h!==v&&g.push({type:"text",value:u.value.slice(h,v)}),Array.isArray(E)?g.push(...E):E&&g.push(E),h=v+m[0].length,b=!0),!f.global)break;m=f.exec(u.value)}return b?(h?\]}]+$/.exec(e);if(!t)return[e,void 0];e=e.slice(0,t.index);let n=t[0],r=n.indexOf(")");const a=ay(e,"(");let i=ay(e,")");for(;r!==-1&&a>i;)e+=n.slice(0,r+1),n=n.slice(r+1),r=n.indexOf(")"),i++;return[e,n]}function HA(e,t){const n=e.input.charCodeAt(e.index-1);return(e.index===0||Xn(n)||jo(n))&&(!t||n!==47)}VA.peek=uM;function tM(){this.buffer()}function nM(e){this.enter({type:"footnoteReference",identifier:"",label:""},e)}function rM(){this.buffer()}function aM(e){this.enter({type:"footnoteDefinition",identifier:"",label:"",children:[]},e)}function iM(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=xt(this.sliceSerialize(e)).toLowerCase(),n.label=t}function oM(e){this.exit(e)}function sM(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=xt(this.sliceSerialize(e)).toLowerCase(),n.label=t}function lM(e){this.exit(e)}function uM(){return"["}function VA(e,t,n,r){const a=n.createTracker(r);let i=a.move("[^");const o=n.enter("footnoteReference"),s=n.enter("reference");return i+=a.move(n.safe(n.associationId(e),{after:"]",before:i})),s(),o(),i+=a.move("]"),i}function cM(){return{enter:{gfmFootnoteCallString:tM,gfmFootnoteCall:nM,gfmFootnoteDefinitionLabelString:rM,gfmFootnoteDefinition:aM},exit:{gfmFootnoteCallString:iM,gfmFootnoteCall:oM,gfmFootnoteDefinitionLabelString:sM,gfmFootnoteDefinition:lM}}}function dM(e){let t=!1;return e&&e.firstLineBlank&&(t=!0),{handlers:{footnoteDefinition:n,footnoteReference:VA},unsafe:[{character:"[",inConstruct:["label","phrasing","reference"]}]};function n(r,a,i,o){const s=i.createTracker(o);let l=s.move("[^");const u=i.enter("footnoteDefinition"),d=i.enter("label");return l+=s.move(i.safe(i.associationId(r),{before:l,after:"]"})),d(),l+=s.move("]:"),r.children&&r.children.length>0&&(s.shift(4),l+=s.move((t?` +`:" ")+i.indentLines(i.containerFlow(r,s.current()),t?WA:pM))),u(),l}}function pM(e,t,n){return t===0?e:WA(e,t,n)}function WA(e,t,n){return(n?"":" ")+e}const fM=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"];YA.peek=yM;function gM(){return{canContainEols:["delete"],enter:{strikethrough:hM},exit:{strikethrough:bM}}}function mM(){return{unsafe:[{character:"~",inConstruct:"phrasing",notInConstruct:fM}],handlers:{delete:YA}}}function hM(e){this.enter({type:"delete",children:[]},e)}function bM(e){this.exit(e)}function YA(e,t,n,r){const a=n.createTracker(r),i=n.enter("strikethrough");let o=a.move("~~");return o+=n.containerPhrasing(e,{...a.current(),before:o,after:"~"}),o+=a.move("~~"),i(),o}function yM(){return"~"}function EM(e){return e.length}function SM(e,t){const n=t||{},r=(n.align||[]).concat(),a=n.stringLength||EM,i=[],o=[],s=[],l=[];let u=0,d=-1;for(;++du&&(u=e[d].length);++bl[b])&&(l[b]=m)}y.push(g)}o[d]=y,s[d]=T}let c=-1;if(typeof r=="object"&&"length"in r)for(;++cl[c]&&(l[c]=g),p[c]=g),f[c]=m}o.splice(1,0,f),s.splice(1,0,p),d=-1;const h=[];for(;++d "),i.shift(2);const o=n.indentLines(n.containerFlow(e,i.current()),wM);return a(),o}function wM(e,t,n){return">"+(n?"":" ")+e}function _M(e,t){return oy(e,t.inConstruct,!0)&&!oy(e,t.notInConstruct,!1)}function oy(e,t,n){if(typeof t=="string"&&(t=[t]),!t||t.length===0)return n;let r=-1;for(;++ro&&(o=i):i=1,a=r+t.length,r=n.indexOf(t,a);return o}function AM(e,t){return!!(t.options.fences===!1&&e.value&&!e.lang&&/[^ \r\n]/.test(e.value)&&!/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(e.value))}function RM(e){const t=e.options.fence||"`";if(t!=="`"&&t!=="~")throw new Error("Cannot serialize code with `"+t+"` for `options.fence`, expected `` ` `` or `~`");return t}function IM(e,t,n,r){const a=RM(n),i=e.value||"",o=a==="`"?"GraveAccent":"Tilde";if(AM(e,n)){const c=n.enter("codeIndented"),f=n.indentLines(i,CM);return c(),f}const s=n.createTracker(r),l=a.repeat(Math.max(TM(i,a)+1,3)),u=n.enter("codeFenced");let d=s.move(l);if(e.lang){const c=n.enter(`codeFencedLang${o}`);d+=s.move(n.safe(e.lang,{before:d,after:" ",encode:["`"],...s.current()})),c()}if(e.lang&&e.meta){const c=n.enter(`codeFencedMeta${o}`);d+=s.move(" "),d+=s.move(n.safe(e.meta,{before:d,after:` +`,encode:["`"],...s.current()})),c()}return d+=s.move(` +`),i&&(d+=s.move(i+` +`)),d+=s.move(l),u(),d}function CM(e,t,n){return(n?"":" ")+e}function vm(e){const t=e.options.quote||'"';if(t!=='"'&&t!=="'")throw new Error("Cannot serialize title with `"+t+"` for `options.quote`, expected `\"`, or `'`");return t}function NM(e,t,n,r){const a=vm(n),i=a==='"'?"Quote":"Apostrophe",o=n.enter("definition");let s=n.enter("label");const l=n.createTracker(r);let u=l.move("[");return u+=l.move(n.safe(n.associationId(e),{before:u,after:"]",...l.current()})),u+=l.move("]: "),s(),!e.url||/[\0- \u007F]/.test(e.url)?(s=n.enter("destinationLiteral"),u+=l.move("<"),u+=l.move(n.safe(e.url,{before:u,after:">",...l.current()})),u+=l.move(">")):(s=n.enter("destinationRaw"),u+=l.move(n.safe(e.url,{before:u,after:e.title?" ":` +`,...l.current()}))),s(),e.title&&(s=n.enter(`title${i}`),u+=l.move(" "+a),u+=l.move(n.safe(e.title,{before:u,after:a,...l.current()})),u+=l.move(a),s()),o(),u}function xM(e){const t=e.options.emphasis||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize emphasis with `"+t+"` for `options.emphasis`, expected `*`, or `_`");return t}function Ha(e){return"&#x"+e.toString(16).toUpperCase()+";"}function _o(e,t,n){const r=Pr(e),a=Pr(t);return r===void 0?a===void 0?n==="_"?{inside:!0,outside:!0}:{inside:!1,outside:!1}:a===1?{inside:!0,outside:!0}:{inside:!1,outside:!0}:r===1?a===void 0?{inside:!1,outside:!1}:a===1?{inside:!0,outside:!0}:{inside:!1,outside:!1}:a===void 0?{inside:!1,outside:!1}:a===1?{inside:!0,outside:!1}:{inside:!1,outside:!1}}KA.peek=OM;function KA(e,t,n,r){const a=xM(n),i=n.enter("emphasis"),o=n.createTracker(r),s=o.move(a);let l=o.move(n.containerPhrasing(e,{after:a,before:s,...o.current()}));const u=l.charCodeAt(0),d=_o(r.before.charCodeAt(r.before.length-1),u,a);d.inside&&(l=Ha(u)+l.slice(1));const c=l.charCodeAt(l.length-1),f=_o(r.after.charCodeAt(0),c,a);f.inside&&(l=l.slice(0,-1)+Ha(c));const p=o.move(a);return i(),n.attentionEncodeSurroundingInfo={after:f.outside,before:d.outside},s+l+p}function OM(e,t,n){return n.options.emphasis||"*"}function LM(e,t){let n=!1;return Em(e,function(r){if("value"in r&&/\r?\n|\r/.test(r.value)||r.type==="break")return n=!0,Qf}),!!((!e.depth||e.depth<3)&&pm(e)&&(t.options.setext||n))}function DM(e,t,n,r){const a=Math.max(Math.min(6,e.depth||1),1),i=n.createTracker(r);if(LM(e,n)){const d=n.enter("headingSetext"),c=n.enter("phrasing"),f=n.containerPhrasing(e,{...i.current(),before:` +`,after:` +`});return c(),d(),f+` +`+(a===1?"=":"-").repeat(f.length-(Math.max(f.lastIndexOf("\r"),f.lastIndexOf(` +`))+1))}const o="#".repeat(a),s=n.enter("headingAtx"),l=n.enter("phrasing");i.move(o+" ");let u=n.containerPhrasing(e,{before:"# ",after:` +`,...i.current()});return/^[\t ]/.test(u)&&(u=Ha(u.charCodeAt(0))+u.slice(1)),u=u?o+" "+u:o,n.options.closeAtx&&(u+=" "+o),l(),s(),u}XA.peek=MM;function XA(e){return e.value||""}function MM(){return"<"}ZA.peek=FM;function ZA(e,t,n,r){const a=vm(n),i=a==='"'?"Quote":"Apostrophe",o=n.enter("image");let s=n.enter("label");const l=n.createTracker(r);let u=l.move("![");return u+=l.move(n.safe(e.alt,{before:u,after:"]",...l.current()})),u+=l.move("]("),s(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(s=n.enter("destinationLiteral"),u+=l.move("<"),u+=l.move(n.safe(e.url,{before:u,after:">",...l.current()})),u+=l.move(">")):(s=n.enter("destinationRaw"),u+=l.move(n.safe(e.url,{before:u,after:e.title?" ":")",...l.current()}))),s(),e.title&&(s=n.enter(`title${i}`),u+=l.move(" "+a),u+=l.move(n.safe(e.title,{before:u,after:a,...l.current()})),u+=l.move(a),s()),u+=l.move(")"),o(),u}function FM(){return"!"}QA.peek=PM;function QA(e,t,n,r){const a=e.referenceType,i=n.enter("imageReference");let o=n.enter("label");const s=n.createTracker(r);let l=s.move("![");const u=n.safe(e.alt,{before:l,after:"]",...s.current()});l+=s.move(u+"]["),o();const d=n.stack;n.stack=[],o=n.enter("reference");const c=n.safe(n.associationId(e),{before:l,after:"]",...s.current()});return o(),n.stack=d,i(),a==="full"||!u||u!==c?l+=s.move(c+"]"):a==="shortcut"?l=l.slice(0,-1):l+=s.move("]"),l}function PM(){return"!"}JA.peek=UM;function JA(e,t,n){let r=e.value||"",a="`",i=-1;for(;new RegExp("(^|[^`])"+a+"([^`]|$)").test(r);)a+="`";for(/[^ \r\n]/.test(r)&&(/^[ \r\n]/.test(r)&&/[ \r\n]$/.test(r)||/^`|`$/.test(r))&&(r=" "+r+" ");++i\u007F]/.test(e.url))}tR.peek=BM;function tR(e,t,n,r){const a=vm(n),i=a==='"'?"Quote":"Apostrophe",o=n.createTracker(r);let s,l;if(eR(e,n)){const d=n.stack;n.stack=[],s=n.enter("autolink");let c=o.move("<");return c+=o.move(n.containerPhrasing(e,{before:c,after:">",...o.current()})),c+=o.move(">"),s(),n.stack=d,c}s=n.enter("link"),l=n.enter("label");let u=o.move("[");return u+=o.move(n.containerPhrasing(e,{before:u,after:"](",...o.current()})),u+=o.move("]("),l(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(l=n.enter("destinationLiteral"),u+=o.move("<"),u+=o.move(n.safe(e.url,{before:u,after:">",...o.current()})),u+=o.move(">")):(l=n.enter("destinationRaw"),u+=o.move(n.safe(e.url,{before:u,after:e.title?" ":")",...o.current()}))),l(),e.title&&(l=n.enter(`title${i}`),u+=o.move(" "+a),u+=o.move(n.safe(e.title,{before:u,after:a,...o.current()})),u+=o.move(a),l()),u+=o.move(")"),s(),u}function BM(e,t,n){return eR(e,n)?"<":"["}nR.peek=$M;function nR(e,t,n,r){const a=e.referenceType,i=n.enter("linkReference");let o=n.enter("label");const s=n.createTracker(r);let l=s.move("[");const u=n.containerPhrasing(e,{before:l,after:"]",...s.current()});l+=s.move(u+"]["),o();const d=n.stack;n.stack=[],o=n.enter("reference");const c=n.safe(n.associationId(e),{before:l,after:"]",...s.current()});return o(),n.stack=d,i(),a==="full"||!u||u!==c?l+=s.move(c+"]"):a==="shortcut"?l=l.slice(0,-1):l+=s.move("]"),l}function $M(){return"["}function km(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function zM(e){const t=km(e),n=e.options.bulletOther;if(!n)return t==="*"?"-":"*";if(n!=="*"&&n!=="+"&&n!=="-")throw new Error("Cannot serialize items with `"+n+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(n===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+n+"`) to be different");return n}function GM(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function rR(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function qM(e,t,n,r){const a=n.enter("list"),i=n.bulletCurrent;let o=e.ordered?GM(n):km(n);const s=e.ordered?o==="."?")":".":zM(n);let l=t&&n.bulletLastUsed?o===n.bulletLastUsed:!1;if(!e.ordered){const d=e.children?e.children[0]:void 0;if((o==="*"||o==="-")&&d&&(!d.children||!d.children[0])&&n.stack[n.stack.length-1]==="list"&&n.stack[n.stack.length-2]==="listItem"&&n.stack[n.stack.length-3]==="list"&&n.stack[n.stack.length-4]==="listItem"&&n.indexStack[n.indexStack.length-1]===0&&n.indexStack[n.indexStack.length-2]===0&&n.indexStack[n.indexStack.length-3]===0&&(l=!0),rR(n)===o&&d){let c=-1;for(;++c-1?t.start:1)+(n.options.incrementListMarker===!1?0:t.children.indexOf(e))+i);let o=i.length+1;(a==="tab"||a==="mixed"&&(t&&t.type==="list"&&t.spread||e.spread))&&(o=Math.ceil(o/4)*4);const s=n.createTracker(r);s.move(i+" ".repeat(o-i.length)),s.shift(o);const l=n.enter("listItem"),u=n.indentLines(n.containerFlow(e,s.current()),d);return l(),u;function d(c,f,p){return f?(p?"":" ".repeat(o))+c:(p?i:i+" ".repeat(o-i.length))+c}}function VM(e,t,n,r){const a=n.enter("paragraph"),i=n.enter("phrasing"),o=n.containerPhrasing(e,r);return i(),a(),o}const WM=Wo(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function YM(e,t,n,r){return(e.children.some(function(o){return WM(o)})?n.containerPhrasing:n.containerFlow).call(n,e,r)}function KM(e){const t=e.options.strong||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize strong with `"+t+"` for `options.strong`, expected `*`, or `_`");return t}aR.peek=XM;function aR(e,t,n,r){const a=KM(n),i=n.enter("strong"),o=n.createTracker(r),s=o.move(a+a);let l=o.move(n.containerPhrasing(e,{after:a,before:s,...o.current()}));const u=l.charCodeAt(0),d=_o(r.before.charCodeAt(r.before.length-1),u,a);d.inside&&(l=Ha(u)+l.slice(1));const c=l.charCodeAt(l.length-1),f=_o(r.after.charCodeAt(0),c,a);f.inside&&(l=l.slice(0,-1)+Ha(c));const p=o.move(a+a);return i(),n.attentionEncodeSurroundingInfo={after:f.outside,before:d.outside},s+l+p}function XM(e,t,n){return n.options.strong||"*"}function ZM(e,t,n,r){return n.safe(e.value,r)}function QM(e){const t=e.options.ruleRepetition||3;if(t<3)throw new Error("Cannot serialize rules with repetition `"+t+"` for `options.ruleRepetition`, expected `3` or more");return t}function JM(e,t,n){const r=(rR(n)+(n.options.ruleSpaces?" ":"")).repeat(QM(n));return n.options.ruleSpaces?r.slice(0,-1):r}const iR={blockquote:kM,break:sy,code:IM,definition:NM,emphasis:KA,hardBreak:sy,heading:DM,html:XA,image:ZA,imageReference:QA,inlineCode:JA,link:tR,linkReference:nR,list:qM,listItem:HM,paragraph:VM,root:YM,strong:aR,text:ZM,thematicBreak:JM};function eF(){return{enter:{table:tF,tableData:ly,tableHeader:ly,tableRow:rF},exit:{codeText:aF,table:nF,tableData:Gs,tableHeader:Gs,tableRow:Gs}}}function tF(e){const t=e._align;this.enter({type:"table",align:t.map(function(n){return n==="none"?null:n}),children:[]},e),this.data.inTable=!0}function nF(e){this.exit(e),this.data.inTable=void 0}function rF(e){this.enter({type:"tableRow",children:[]},e)}function Gs(e){this.exit(e)}function ly(e){this.enter({type:"tableCell",children:[]},e)}function aF(e){let t=this.resume();this.data.inTable&&(t=t.replace(/\\([\\|])/g,iF));const n=this.stack[this.stack.length-1];n.type,n.value=t,this.exit(e)}function iF(e,t){return t==="|"?t:e}function oF(e){const t=e||{},n=t.tableCellPadding,r=t.tablePipeAlign,a=t.stringLength,i=n?" ":"|";return{unsafe:[{character:"\r",inConstruct:"tableCell"},{character:` +`,inConstruct:"tableCell"},{atBreak:!0,character:"|",after:"[ :-]"},{character:"|",inConstruct:"tableCell"},{atBreak:!0,character:":",after:"-"},{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{inlineCode:f,table:o,tableCell:l,tableRow:s}};function o(p,h,y,T){return u(d(p,y,T),p.align)}function s(p,h,y,T){const b=c(p,y,T),g=u([b]);return g.slice(0,g.indexOf(` +`))}function l(p,h,y,T){const b=y.enter("tableCell"),g=y.enter("phrasing"),m=y.containerPhrasing(p,{...T,before:i,after:i});return g(),b(),m}function u(p,h){return SM(p,{align:h,alignDelimiters:r,padding:n,stringLength:a})}function d(p,h,y){const T=p.children;let b=-1;const g=[],m=h.enter("table");for(;++b0&&!n&&(e[e.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),n}const _F={tokenize:OF,partial:!0};function TF(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:CF,continuation:{tokenize:NF},exit:xF}},text:{91:{name:"gfmFootnoteCall",tokenize:IF},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:AF,resolveTo:RF}}}}function AF(e,t,n){const r=this;let a=r.events.length;const i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o;for(;a--;){const l=r.events[a][1];if(l.type==="labelImage"){o=l;break}if(l.type==="gfmFootnoteCall"||l.type==="labelLink"||l.type==="label"||l.type==="image"||l.type==="link")break}return s;function s(l){if(!o||!o._balanced)return n(l);const u=xt(r.sliceSerialize({start:o.end,end:r.now()}));return u.codePointAt(0)!==94||!i.includes(u.slice(1))?n(l):(e.enter("gfmFootnoteCallLabelMarker"),e.consume(l),e.exit("gfmFootnoteCallLabelMarker"),t(l))}}function RF(e,t){let n=e.length;for(;n--;)if(e[n][1].type==="labelImage"&&e[n][0]==="enter"){e[n][1];break}e[n+1][1].type="data",e[n+3][1].type="gfmFootnoteCallLabelMarker";const r={type:"gfmFootnoteCall",start:Object.assign({},e[n+3][1].start),end:Object.assign({},e[e.length-1][1].end)},a={type:"gfmFootnoteCallMarker",start:Object.assign({},e[n+3][1].end),end:Object.assign({},e[n+3][1].end)};a.end.column++,a.end.offset++,a.end._bufferIndex++;const i={type:"gfmFootnoteCallString",start:Object.assign({},a.end),end:Object.assign({},e[e.length-1][1].start)},o={type:"chunkString",contentType:"string",start:Object.assign({},i.start),end:Object.assign({},i.end)},s=[e[n+1],e[n+2],["enter",r,t],e[n+3],e[n+4],["enter",a,t],["exit",a,t],["enter",i,t],["enter",o,t],["exit",o,t],["exit",i,t],e[e.length-2],e[e.length-1],["exit",r,t]];return e.splice(n,e.length-n+1,...s),e}function IF(e,t,n){const r=this,a=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let i=0,o;return s;function s(c){return e.enter("gfmFootnoteCall"),e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),l}function l(c){return c!==94?n(c):(e.enter("gfmFootnoteCallMarker"),e.consume(c),e.exit("gfmFootnoteCallMarker"),e.enter("gfmFootnoteCallString"),e.enter("chunkString").contentType="string",u)}function u(c){if(i>999||c===93&&!o||c===null||c===91||le(c))return n(c);if(c===93){e.exit("chunkString");const f=e.exit("gfmFootnoteCallString");return a.includes(xt(r.sliceSerialize(f)))?(e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),e.exit("gfmFootnoteCall"),t):n(c)}return le(c)||(o=!0),i++,e.consume(c),c===92?d:u}function d(c){return c===91||c===92||c===93?(e.consume(c),i++,u):u(c)}}function CF(e,t,n){const r=this,a=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let i,o=0,s;return l;function l(h){return e.enter("gfmFootnoteDefinition")._container=!0,e.enter("gfmFootnoteDefinitionLabel"),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(h),e.exit("gfmFootnoteDefinitionLabelMarker"),u}function u(h){return h===94?(e.enter("gfmFootnoteDefinitionMarker"),e.consume(h),e.exit("gfmFootnoteDefinitionMarker"),e.enter("gfmFootnoteDefinitionLabelString"),e.enter("chunkString").contentType="string",d):n(h)}function d(h){if(o>999||h===93&&!s||h===null||h===91||le(h))return n(h);if(h===93){e.exit("chunkString");const y=e.exit("gfmFootnoteDefinitionLabelString");return i=xt(r.sliceSerialize(y)),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(h),e.exit("gfmFootnoteDefinitionLabelMarker"),e.exit("gfmFootnoteDefinitionLabel"),f}return le(h)||(s=!0),o++,e.consume(h),h===92?c:d}function c(h){return h===91||h===92||h===93?(e.consume(h),o++,d):d(h)}function f(h){return h===58?(e.enter("definitionMarker"),e.consume(h),e.exit("definitionMarker"),a.includes(i)||a.push(i),re(e,p,"gfmFootnoteDefinitionWhitespace")):n(h)}function p(h){return t(h)}}function NF(e,t,n){return e.check(ei,t,e.attempt(_F,t,n))}function xF(e){e.exit("gfmFootnoteDefinition")}function OF(e,t,n){const r=this;return re(e,a,"gfmFootnoteDefinitionIndent",5);function a(i){const o=r.events[r.events.length-1];return o&&o[1].type==="gfmFootnoteDefinitionIndent"&&o[2].sliceSerialize(o[1],!0).length===4?t(i):n(i)}}function LF(e){let n=(e||{}).singleTilde;const r={name:"strikethrough",tokenize:i,resolveAll:a};return n==null&&(n=!0),{text:{126:r},insideSpan:{null:[r]},attentionMarkers:{null:[126]}};function a(o,s){let l=-1;for(;++l1?l(h):(o.consume(h),c++,p);if(c<2&&!n)return l(h);const T=o.exit("strikethroughSequenceTemporary"),b=Pr(h);return T._open=!b||b===2&&!!y,T._close=!y||y===2&&!!b,s(h)}}}class DF{constructor(){this.map=[]}add(t,n,r){MF(this,t,n,r)}consume(t){if(this.map.sort(function(i,o){return i[0]-o[0]}),this.map.length===0)return;let n=this.map.length;const r=[];for(;n>0;)n-=1,r.push(t.slice(this.map[n][0]+this.map[n][1]),this.map[n][2]),t.length=this.map[n][0];r.push(t.slice()),t.length=0;let a=r.pop();for(;a;){for(const i of a)t.push(i);a=r.pop()}this.map.length=0}}function MF(e,t,n,r){let a=0;if(!(n===0&&r.length===0)){for(;a-1;){const $=r.events[I][1].type;if($==="lineEnding"||$==="linePrefix")I--;else break}const D=I>-1?r.events[I][1].type:null,q=D==="tableHead"||D==="tableRow"?E:l;return q===E&&r.parser.lazy[r.now().line]?n(k):q(k)}function l(k){return e.enter("tableHead"),e.enter("tableRow"),u(k)}function u(k){return k===124||(o=!0,i+=1),d(k)}function d(k){return k===null?n(k):V(k)?i>1?(i=0,r.interrupt=!0,e.exit("tableRow"),e.enter("lineEnding"),e.consume(k),e.exit("lineEnding"),p):n(k):ee(k)?re(e,d,"whitespace")(k):(i+=1,o&&(o=!1,a+=1),k===124?(e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),o=!0,d):(e.enter("data"),c(k)))}function c(k){return k===null||k===124||le(k)?(e.exit("data"),d(k)):(e.consume(k),k===92?f:c)}function f(k){return k===92||k===124?(e.consume(k),c):c(k)}function p(k){return r.interrupt=!1,r.parser.lazy[r.now().line]?n(k):(e.enter("tableDelimiterRow"),o=!1,ee(k)?re(e,h,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(k):h(k))}function h(k){return k===45||k===58?T(k):k===124?(o=!0,e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),y):_(k)}function y(k){return ee(k)?re(e,T,"whitespace")(k):T(k)}function T(k){return k===58?(i+=1,o=!0,e.enter("tableDelimiterMarker"),e.consume(k),e.exit("tableDelimiterMarker"),b):k===45?(i+=1,b(k)):k===null||V(k)?v(k):_(k)}function b(k){return k===45?(e.enter("tableDelimiterFiller"),g(k)):_(k)}function g(k){return k===45?(e.consume(k),g):k===58?(o=!0,e.exit("tableDelimiterFiller"),e.enter("tableDelimiterMarker"),e.consume(k),e.exit("tableDelimiterMarker"),m):(e.exit("tableDelimiterFiller"),m(k))}function m(k){return ee(k)?re(e,v,"whitespace")(k):v(k)}function v(k){return k===124?h(k):k===null||V(k)?!o||a!==i?_(k):(e.exit("tableDelimiterRow"),e.exit("tableHead"),t(k)):_(k)}function _(k){return n(k)}function E(k){return e.enter("tableRow"),R(k)}function R(k){return k===124?(e.enter("tableCellDivider"),e.consume(k),e.exit("tableCellDivider"),R):k===null||V(k)?(e.exit("tableRow"),t(k)):ee(k)?re(e,R,"whitespace")(k):(e.enter("data"),C(k))}function C(k){return k===null||k===124||le(k)?(e.exit("data"),R(k)):(e.consume(k),k===92?N:C)}function N(k){return k===92||k===124?(e.consume(k),C):C(k)}}function BF(e,t){let n=-1,r=!0,a=0,i=[0,0,0,0],o=[0,0,0,0],s=!1,l=0,u,d,c;const f=new DF;for(;++nn[2]+1){const h=n[2]+1,y=n[3]-n[2]-1;e.add(h,y,[])}}e.add(n[3]+1,0,[["exit",c,t]])}return a!==void 0&&(i.end=Object.assign({},sr(t.events,a)),e.add(a,0,[["exit",i,t]]),i=void 0),i}function cy(e,t,n,r,a){const i=[],o=sr(t.events,n);a&&(a.end=Object.assign({},o),i.push(["exit",a,t])),r.end=Object.assign({},o),i.push(["exit",r,t]),e.add(n+1,0,i)}function sr(e,t){const n=e[t],r=n[0]==="enter"?"start":"end";return n[1][r]}const $F={name:"tasklistCheck",tokenize:GF};function zF(){return{text:{91:$F}}}function GF(e,t,n){const r=this;return a;function a(l){return r.previous!==null||!r._gfmTasklistFirstContentOfListItem?n(l):(e.enter("taskListCheck"),e.enter("taskListCheckMarker"),e.consume(l),e.exit("taskListCheckMarker"),i)}function i(l){return le(l)?(e.enter("taskListCheckValueUnchecked"),e.consume(l),e.exit("taskListCheckValueUnchecked"),o):l===88||l===120?(e.enter("taskListCheckValueChecked"),e.consume(l),e.exit("taskListCheckValueChecked"),o):n(l)}function o(l){return l===93?(e.enter("taskListCheckMarker"),e.consume(l),e.exit("taskListCheckMarker"),e.exit("taskListCheck"),s):n(l)}function s(l){return V(l)?t(l):ee(l)?e.check({tokenize:qF},t,n)(l):n(l)}}function qF(e,t,n){return re(e,r,"whitespace");function r(a){return a===null?n(a):t(a)}}function jF(e){return wA([mF(),TF(),LF(e),PF(),zF()])}const HF={};function VF(e){const t=this,n=e||HF,r=t.data(),a=r.micromarkExtensions||(r.micromarkExtensions=[]),i=r.fromMarkdownExtensions||(r.fromMarkdownExtensions=[]),o=r.toMarkdownExtensions||(r.toMarkdownExtensions=[]);a.push(jF(n)),i.push(dF()),o.push(pF(n))}function WF(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function YF(e,t){if(e==null)return{};var n,r,a=WF(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;re.length)&&(t=e.length);for(var n=0,r=Array(t);n=4)return[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]}var qs={};function nP(e){if(e.length===0||e.length===1)return e;var t=e.join(".");return qs[t]||(qs[t]=tP(e)),qs[t]}function rP(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0,r=e.filter(function(i){return i!=="token"}),a=nP(r);return a.reduce(function(i,o){return vr(vr({},i),n[o])},t)}function py(e){return e.join(" ")}function aP(e,t){var n=0;return function(r){return n+=1,r.map(function(a,i){return mR({node:a,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function mR(e){var t=e.node,n=e.stylesheet,r=e.style,a=r===void 0?{}:r,i=e.useInlineStyles,o=e.key,s=t.properties,l=t.type,u=t.tagName,d=t.value;if(l==="text")return d;if(u){var c=aP(n,i),f;if(!i)f=vr(vr({},s),{},{className:py(s.className)});else{var p=Object.keys(n).reduce(function(b,g){return g.split(".").forEach(function(m){b.includes(m)||b.push(m)}),b},[]),h=s.className&&s.className.includes("token")?["token"]:[],y=s.className&&h.concat(s.className.filter(function(b){return!p.includes(b)}));f=vr(vr({},s),{},{className:py(y)||void 0,style:rP(s.className,Object.assign({},s.style,a),n)})}var T=c(t.children);return Ft.createElement(u,ig({key:o},f),T)}}const iP=function(e,t){var n=e.listLanguages();return n.indexOf(t)!==-1};var oP=["language","children","style","customStyle","codeTagProps","useInlineStyles","showLineNumbers","showInlineLineNumbers","startingLineNumber","lineNumberContainerStyle","lineNumberStyle","wrapLines","wrapLongLines","lineProps","renderer","PreTag","CodeTag","code","astGenerator"];function fy(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable})),n.push.apply(n,r)}return n}function hn(e){for(var t=1;t1&&arguments[1]!==void 0?arguments[1]:[],n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[],r=0;r2&&arguments[2]!==void 0?arguments[2]:[];return Wi({children:_,lineNumber:E,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:a,lineProps:n,className:R,showLineNumbers:r,wrapLongLines:l,wrapLines:t})}function y(_,E){if(r&&E&&a){var R=bR(s,E,o);_.unshift(hR(E,R))}return _}function T(_,E){var R=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[];return t||R.length>0?h(_,E,R):y(_,E)}for(var b=function(){var E=d[p],R=E.children[0].value,C=lP(R);if(C){var N=R.split(` +`);N.forEach(function(k,I){var D=r&&c.length+i,q={type:"text",value:"".concat(k,` +`)};if(I===0){var $=d.slice(f+1,p).concat(Wi({children:[q],className:E.properties.className})),z=T($,D);c.push(z)}else if(I===N.length-1){var H=d[p+1]&&d[p+1].children&&d[p+1].children[0],Y={type:"text",value:"".concat(k)};if(H){var x=Wi({children:[Y],className:E.properties.className});d.splice(p+1,0,x)}else{var M=[Y],S=T(M,D,E.properties.className);c.push(S)}}else{var P=[q],G=T(P,D,E.properties.className);c.push(G)}}),f=p}p++};p4&&n.slice(0,4)===Im&&oU.test(t)&&(t.charAt(4)==="-"?r=uU(t):t=cU(t),a=rU),new a(r,t))}function uU(e){var t=e.slice(5).replace(IR,pU);return Im+t.charAt(0).toUpperCase()+t.slice(1)}function cU(e){var t=e.slice(4);return IR.test(t)?e:(t=t.replace(sU,dU),t.charAt(0)!=="-"&&(t="-"+t),Im+t)}function dU(e){return"-"+e.toLowerCase()}function pU(e){return e.charAt(1).toUpperCase()}var fU=gU,yy=/[#.]/g;function gU(e,t){for(var n=e||"",r=t||"div",a={},i=0,o,s,l;i=48&&t<=57}var F2=P2;function P2(e){var t=typeof e=="string"?e.charCodeAt(0):e;return t>=97&&t<=102||t>=65&&t<=70||t>=48&&t<=57}var U2=B2;function B2(e){var t=typeof e=="string"?e.charCodeAt(0):e;return t>=97&&t<=122||t>=65&&t<=90}var $2=U2,z2=xR,G2=q2;function q2(e){return $2(e)||z2(e)}var xi,j2=59,H2=V2;function V2(e){var t="&"+e+";",n;return xi=xi||document.createElement("i"),xi.innerHTML=t,n=xi.textContent,n.charCodeAt(n.length-1)===j2&&e!=="semi"||n===t?!1:n}var Ty=L2,Ay=D2,W2=xR,Y2=F2,OR=G2,K2=H2,X2=u$,Z2={}.hasOwnProperty,or=String.fromCharCode,Q2=Function.prototype,Ry={warning:null,reference:null,text:null,warningContext:null,referenceContext:null,textContext:null,position:{},additional:null,attribute:!1,nonTerminated:!0},J2=9,Iy=10,e$=12,t$=32,Cy=38,n$=59,r$=60,a$=61,i$=35,o$=88,s$=120,l$=65533,lr="named",xm="hexadecimal",Om="decimal",Lm={};Lm[xm]=16;Lm[Om]=10;var Ko={};Ko[lr]=OR;Ko[Om]=W2;Ko[xm]=Y2;var LR=1,DR=2,MR=3,FR=4,PR=5,sg=6,UR=7,On={};On[LR]="Named character references must be terminated by a semicolon";On[DR]="Numeric character references must be terminated by a semicolon";On[MR]="Named character references cannot be empty";On[FR]="Numeric character references cannot be empty";On[PR]="Named character references must be known";On[sg]="Numeric character references cannot be disallowed";On[UR]="Numeric character references cannot be outside the permissible Unicode range";function u$(e,t){var n={},r,a;t||(t={});for(a in Ry)r=t[a],n[a]=r??Ry[a];return(n.position.indent||n.position.start)&&(n.indent=n.position.indent||[],n.position=n.position.start),c$(e,n)}function c$(e,t){var n=t.additional,r=t.nonTerminated,a=t.text,i=t.reference,o=t.warning,s=t.textContext,l=t.referenceContext,u=t.warningContext,d=t.position,c=t.indent||[],f=e.length,p=0,h=-1,y=d.column||1,T=d.line||1,b="",g=[],m,v,_,E,R,C,N,k,I,D,q,$,z,H,Y,x,M,S,P;for(typeof n=="string"&&(n=n.charCodeAt(0)),x=G(),k=o?A:Q2,p--,f++;++p65535&&(C-=65536,D+=or(C>>>10|55296),C=56320|C&1023),C=D+or(C))):H!==lr&&k(FR,S)),C?(Q(),x=G(),p=P-1,y+=P-z+1,g.push(C),M=G(),M.offset++,i&&i.call(l,C,{start:x,end:M},e.slice(z-1,P)),x=M):(E=e.slice(z-1,P),b+=E,y+=E.length,p=P-1)}else R===10&&(T++,h++,y=0),R===R?(b+=or(R),y++):Q();return g.join("");function G(){return{line:T,column:y,offset:p+(d.offset||0)}}function A(ue,Z){var ce=G();ce.column+=Z,ce.offset+=Z,o.call(u,On[ue],ce,ue)}function Q(){b&&(g.push(b),a&&a.call(s,b,{start:x,end:G()}),b="")}}function d$(e){return e>=55296&&e<=57343||e>1114111}function p$(e){return e>=1&&e<=8||e===11||e>=13&&e<=31||e>=127&&e<=159||e>=64976&&e<=65007||(e&65535)===65535||(e&65535)===65534}var BR={exports:{}};(function(e){var t=typeof window<"u"?window:typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?self:{};/** + * Prism: Lightweight, robust, elegant syntax highlighting + * + * @license MIT + * @author Lea Verou + * @namespace + * @public + */var n=function(r){var a=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,i=0,o={},s={manual:r.Prism&&r.Prism.manual,disableWorkerMessageHandler:r.Prism&&r.Prism.disableWorkerMessageHandler,util:{encode:function g(m){return m instanceof l?new l(m.type,g(m.content),m.alias):Array.isArray(m)?m.map(g):m.replace(/&/g,"&").replace(/"u")return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(_){var g=(/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(_.stack)||[])[1];if(g){var m=document.getElementsByTagName("script");for(var v in m)if(m[v].src==g)return m[v]}return null}},isActive:function(g,m,v){for(var _="no-"+m;g;){var E=g.classList;if(E.contains(m))return!0;if(E.contains(_))return!1;g=g.parentElement}return!!v}},languages:{plain:o,plaintext:o,text:o,txt:o,extend:function(g,m){var v=s.util.clone(s.languages[g]);for(var _ in m)v[_]=m[_];return v},insertBefore:function(g,m,v,_){_=_||s.languages;var E=_[g],R={};for(var C in E)if(E.hasOwnProperty(C)){if(C==m)for(var N in v)v.hasOwnProperty(N)&&(R[N]=v[N]);v.hasOwnProperty(C)||(R[C]=E[C])}var k=_[g];return _[g]=R,s.languages.DFS(s.languages,function(I,D){D===k&&I!=g&&(this[I]=R)}),R},DFS:function g(m,v,_,E){E=E||{};var R=s.util.objId;for(var C in m)if(m.hasOwnProperty(C)){v.call(m,C,m[C],_||C);var N=m[C],k=s.util.type(N);k==="Object"&&!E[R(N)]?(E[R(N)]=!0,g(N,v,null,E)):k==="Array"&&!E[R(N)]&&(E[R(N)]=!0,g(N,v,C,E))}}},plugins:{},highlightAll:function(g,m){s.highlightAllUnder(document,g,m)},highlightAllUnder:function(g,m,v){var _={callback:v,container:g,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};s.hooks.run("before-highlightall",_),_.elements=Array.prototype.slice.apply(_.container.querySelectorAll(_.selector)),s.hooks.run("before-all-elements-highlight",_);for(var E=0,R;R=_.elements[E++];)s.highlightElement(R,m===!0,_.callback)},highlightElement:function(g,m,v){var _=s.util.getLanguage(g),E=s.languages[_];s.util.setLanguage(g,_);var R=g.parentElement;R&&R.nodeName.toLowerCase()==="pre"&&s.util.setLanguage(R,_);var C=g.textContent,N={element:g,language:_,grammar:E,code:C};function k(D){N.highlightedCode=D,s.hooks.run("before-insert",N),N.element.innerHTML=N.highlightedCode,s.hooks.run("after-highlight",N),s.hooks.run("complete",N),v&&v.call(N.element)}if(s.hooks.run("before-sanity-check",N),R=N.element.parentElement,R&&R.nodeName.toLowerCase()==="pre"&&!R.hasAttribute("tabindex")&&R.setAttribute("tabindex","0"),!N.code){s.hooks.run("complete",N),v&&v.call(N.element);return}if(s.hooks.run("before-highlight",N),!N.grammar){k(s.util.encode(N.code));return}if(m&&r.Worker){var I=new Worker(s.filename);I.onmessage=function(D){k(D.data)},I.postMessage(JSON.stringify({language:N.language,code:N.code,immediateClose:!0}))}else k(s.highlight(N.code,N.grammar,N.language))},highlight:function(g,m,v){var _={code:g,grammar:m,language:v};if(s.hooks.run("before-tokenize",_),!_.grammar)throw new Error('The language "'+_.language+'" has no grammar.');return _.tokens=s.tokenize(_.code,_.grammar),s.hooks.run("after-tokenize",_),l.stringify(s.util.encode(_.tokens),_.language)},tokenize:function(g,m){var v=m.rest;if(v){for(var _ in v)m[_]=v[_];delete m.rest}var E=new c;return f(E,E.head,g),d(g,E,m,E.head,0),h(E)},hooks:{all:{},add:function(g,m){var v=s.hooks.all;v[g]=v[g]||[],v[g].push(m)},run:function(g,m){var v=s.hooks.all[g];if(!(!v||!v.length))for(var _=0,E;E=v[_++];)E(m)}},Token:l};r.Prism=s;function l(g,m,v,_){this.type=g,this.content=m,this.alias=v,this.length=(_||"").length|0}l.stringify=function g(m,v){if(typeof m=="string")return m;if(Array.isArray(m)){var _="";return m.forEach(function(k){_+=g(k,v)}),_}var E={type:m.type,content:g(m.content,v),tag:"span",classes:["token",m.type],attributes:{},language:v},R=m.alias;R&&(Array.isArray(R)?Array.prototype.push.apply(E.classes,R):E.classes.push(R)),s.hooks.run("wrap",E);var C="";for(var N in E.attributes)C+=" "+N+'="'+(E.attributes[N]||"").replace(/"/g,""")+'"';return"<"+E.tag+' class="'+E.classes.join(" ")+'"'+C+">"+E.content+""};function u(g,m,v,_){g.lastIndex=m;var E=g.exec(v);if(E&&_&&E[1]){var R=E[1].length;E.index+=R,E[0]=E[0].slice(R)}return E}function d(g,m,v,_,E,R){for(var C in v)if(!(!v.hasOwnProperty(C)||!v[C])){var N=v[C];N=Array.isArray(N)?N:[N];for(var k=0;k=R.reach);M+=x.value.length,x=x.next){var S=x.value;if(m.length>g.length)return;if(!(S instanceof l)){var P=1,G;if($){if(G=u(Y,M,g,q),!G||G.index>=g.length)break;var Z=G.index,A=G.index+G[0].length,Q=M;for(Q+=x.value.length;Z>=Q;)x=x.next,Q+=x.value.length;if(Q-=x.value.length,M=Q,x.value instanceof l)continue;for(var ue=x;ue!==m.tail&&(QR.reach&&(R.reach=Be);var rt=x.prev;ke&&(rt=f(m,rt,ke),M+=ke.length),p(m,rt,P);var jr=new l(C,D?s.tokenize(ce,D):ce,z,ce);if(x=f(m,rt,jr),Ve&&f(m,x,Ve),P>1){var sn={cause:C+","+k,reach:Be};d(g,m,v,x.prev,M,sn),R&&sn.reach>R.reach&&(R.reach=sn.reach)}}}}}}function c(){var g={value:null,prev:null,next:null},m={value:null,prev:g,next:null};g.next=m,this.head=g,this.tail=m,this.length=0}function f(g,m,v){var _=m.next,E={value:v,prev:m,next:_};return m.next=E,_.prev=E,g.length++,E}function p(g,m,v){for(var _=m.next,E=0;E/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},e.languages.markup.tag.inside["attr-value"].inside.entity=e.languages.markup.entity,e.languages.markup.doctype.inside["internal-subset"].inside=e.languages.markup,e.hooks.add("wrap",function(t){t.type==="entity"&&(t.attributes.title=t.content.value.replace(/&/,"&"))}),Object.defineProperty(e.languages.markup.tag,"addInlined",{value:function(n,r){var a={};a["language-"+r]={pattern:/(^$)/i,lookbehind:!0,inside:e.languages[r]},a.cdata=/^$/i;var i={"included-cdata":{pattern://i,inside:a}};i["language-"+r]={pattern:/[\s\S]+/,inside:e.languages[r]};var o={};o[n]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return n}),"i"),lookbehind:!0,greedy:!0,inside:i},e.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(e.languages.markup.tag,"addAttribute",{value:function(t,n){e.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+t+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[n,"language-"+n],inside:e.languages[n]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),e.languages.html=e.languages.markup,e.languages.mathml=e.languages.markup,e.languages.svg=e.languages.markup,e.languages.xml=e.languages.extend("markup",{}),e.languages.ssml=e.languages.xml,e.languages.atom=e.languages.xml,e.languages.rss=e.languages.xml}var m$=Mm;Mm.displayName="css";Mm.aliases=[];function Mm(e){(function(t){var n=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;t.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+n.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+n.source+"$"),alias:"url"}}},selector:{pattern:RegExp(`(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|`+n.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:n,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},t.languages.css.atrule.inside.rest=t.languages.css;var r=t.languages.markup;r&&(r.tag.addInlined("style","css"),r.tag.addAttribute("style","css"))})(e)}var h$=Fm;Fm.displayName="clike";Fm.aliases=[];function Fm(e){e.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}}var b$=Pm;Pm.displayName="javascript";Pm.aliases=["js"];function Pm(e){e.languages.javascript=e.languages.extend("clike",{"class-name":[e.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+(/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source)+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),e.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,e.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:e.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:e.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:e.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:e.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:e.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),e.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:e.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),e.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),e.languages.markup&&(e.languages.markup.tag.addInlined("script","javascript"),e.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),e.languages.js=e.languages.javascript}var fa=typeof globalThis=="object"?globalThis:typeof self=="object"?self:typeof window=="object"?window:typeof Tn=="object"?Tn:{},y$=D$();fa.Prism={manual:!0,disableWorkerMessageHandler:!0};var E$=DU,S$=X2,$R=f$,v$=g$,k$=m$,w$=h$,_$=b$;y$();var Um={}.hasOwnProperty;function zR(){}zR.prototype=$R;var Te=new zR,T$=Te;Te.highlight=R$;Te.register=ri;Te.alias=A$;Te.registered=I$;Te.listLanguages=C$;ri(v$);ri(k$);ri(w$);ri(_$);Te.util.encode=O$;Te.Token.stringify=N$;function ri(e){if(typeof e!="function"||!e.displayName)throw new Error("Expected `function` for `grammar`, got `"+e+"`");Te.languages[e.displayName]===void 0&&e(Te)}function A$(e,t){var n=Te.languages,r=e,a,i,o,s;t&&(r={},r[e]=t);for(a in r)for(i=r[a],i=typeof i=="string"?[i]:i,o=i.length,s=-1;++s code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var js,Ny;function F$(){if(Ny)return js;Ny=1,js=e,e.displayName="abap",e.aliases=[];function e(t){t.languages.abap={comment:/^\*.*/m,string:/(`|')(?:\\.|(?!\1)[^\\\r\n])*\1/,"string-template":{pattern:/([|}])(?:\\.|[^\\|{\r\n])*(?=[|{])/,lookbehind:!0,alias:"string"},"eol-comment":{pattern:/(^|\s)".*/m,lookbehind:!0,alias:"comment"},keyword:{pattern:/(\s|\.|^)(?:SCIENTIFIC_WITH_LEADING_ZERO|SCALE_PRESERVING_SCIENTIFIC|RMC_COMMUNICATION_FAILURE|END-ENHANCEMENT-SECTION|MULTIPLY-CORRESPONDING|SUBTRACT-CORRESPONDING|VERIFICATION-MESSAGE|DIVIDE-CORRESPONDING|ENHANCEMENT-SECTION|CURRENCY_CONVERSION|RMC_SYSTEM_FAILURE|START-OF-SELECTION|MOVE-CORRESPONDING|RMC_INVALID_STATUS|CUSTOMER-FUNCTION|END-OF-DEFINITION|ENHANCEMENT-POINT|SYSTEM-EXCEPTIONS|ADD-CORRESPONDING|SCALE_PRESERVING|SELECTION-SCREEN|CURSOR-SELECTION|END-OF-SELECTION|LOAD-OF-PROGRAM|SCROLL-BOUNDARY|SELECTION-TABLE|EXCEPTION-TABLE|IMPLEMENTATIONS|PARAMETER-TABLE|RIGHT-JUSTIFIED|UNIT_CONVERSION|AUTHORITY-CHECK|LIST-PROCESSING|SIGN_AS_POSTFIX|COL_BACKGROUND|IMPLEMENTATION|INTERFACE-POOL|TRANSFORMATION|IDENTIFICATION|ENDENHANCEMENT|LINE-SELECTION|INITIALIZATION|LEFT-JUSTIFIED|SELECT-OPTIONS|SELECTION-SETS|COMMUNICATION|CORRESPONDING|DECIMAL_SHIFT|PRINT-CONTROL|VALUE-REQUEST|CHAIN-REQUEST|FUNCTION-POOL|FIELD-SYMBOLS|FUNCTIONALITY|INVERTED-DATE|SELECTION-SET|CLASS-METHODS|OUTPUT-LENGTH|CLASS-CODING|COL_NEGATIVE|ERRORMESSAGE|FIELD-GROUPS|HELP-REQUEST|NO-EXTENSION|NO-TOPOFPAGE|REDEFINITION|DISPLAY-MODE|ENDINTERFACE|EXIT-COMMAND|FIELD-SYMBOL|NO-SCROLLING|SHORTDUMP-ID|ACCESSPOLICY|CLASS-EVENTS|COL_POSITIVE|DECLARATIONS|ENHANCEMENTS|FILTER-TABLE|SWITCHSTATES|SYNTAX-CHECK|TRANSPORTING|ASYNCHRONOUS|SYNTAX-TRACE|TOKENIZATION|USER-COMMAND|WITH-HEADING|ABAP-SOURCE|BREAK-POINT|CHAIN-INPUT|COMPRESSION|FIXED-POINT|NEW-SECTION|NON-UNICODE|OCCURRENCES|RESPONSIBLE|SYSTEM-CALL|TRACE-TABLE|ABBREVIATED|CHAR-TO-HEX|END-OF-FILE|ENDFUNCTION|ENVIRONMENT|ASSOCIATION|COL_HEADING|EDITOR-CALL|END-OF-PAGE|ENGINEERING|IMPLEMENTED|INTENSIFIED|RADIOBUTTON|SYSTEM-EXIT|TOP-OF-PAGE|TRANSACTION|APPLICATION|CONCATENATE|DESTINATION|ENHANCEMENT|IMMEDIATELY|NO-GROUPING|PRECOMPILED|REPLACEMENT|TITLE-LINES|ACTIVATION|BYTE-ORDER|CLASS-POOL|CONNECTION|CONVERSION|DEFINITION|DEPARTMENT|EXPIRATION|INHERITING|MESSAGE-ID|NO-HEADING|PERFORMING|QUEUE-ONLY|RIGHTSPACE|SCIENTIFIC|STATUSINFO|STRUCTURES|SYNCPOINTS|WITH-TITLE|ATTRIBUTES|BOUNDARIES|CLASS-DATA|COL_NORMAL|DD\/MM\/YYYY|DESCENDING|INTERFACES|LINE-COUNT|MM\/DD\/YYYY|NON-UNIQUE|PRESERVING|SELECTIONS|STATEMENTS|SUBROUTINE|TRUNCATION|TYPE-POOLS|ARITHMETIC|BACKGROUND|ENDPROVIDE|EXCEPTIONS|IDENTIFIER|INDEX-LINE|OBLIGATORY|PARAMETERS|PERCENTAGE|PUSHBUTTON|RESOLUTION|COMPONENTS|DEALLOCATE|DISCONNECT|DUPLICATES|FIRST-LINE|HEAD-LINES|NO-DISPLAY|OCCURRENCE|RESPECTING|RETURNCODE|SUBMATCHES|TRACE-FILE|ASCENDING|BYPASSING|ENDMODULE|EXCEPTION|EXCLUDING|EXPORTING|INCREMENT|MATCHCODE|PARAMETER|PARTIALLY|PREFERRED|REFERENCE|REPLACING|RETURNING|SELECTION|SEPARATED|SPECIFIED|STATEMENT|TIMESTAMP|TYPE-POOL|ACCEPTING|APPENDAGE|ASSIGNING|COL_GROUP|COMPARING|CONSTANTS|DANGEROUS|IMPORTING|INSTANCES|LEFTSPACE|LOG-POINT|QUICKINFO|READ-ONLY|SCROLLING|SQLSCRIPT|STEP-LOOP|TOP-LINES|TRANSLATE|APPENDING|AUTHORITY|CHARACTER|COMPONENT|CONDITION|DIRECTORY|DUPLICATE|MESSAGING|RECEIVING|SUBSCREEN|ACCORDING|COL_TOTAL|END-LINES|ENDMETHOD|ENDSELECT|EXPANDING|EXTENSION|INCLUDING|INFOTYPES|INTERFACE|INTERVALS|LINE-SIZE|PF-STATUS|PROCEDURE|PROTECTED|REQUESTED|RESUMABLE|RIGHTPLUS|SAP-SPOOL|SECONDARY|STRUCTURE|SUBSTRING|TABLEVIEW|NUMOFCHAR|ADJACENT|ANALYSIS|ASSIGNED|BACKWARD|CHANNELS|CHECKBOX|CONTINUE|CRITICAL|DATAINFO|DD\/MM\/YY|DURATION|ENCODING|ENDCLASS|FUNCTION|LEFTPLUS|LINEFEED|MM\/DD\/YY|OVERFLOW|RECEIVED|SKIPPING|SORTABLE|STANDARD|SUBTRACT|SUPPRESS|TABSTRIP|TITLEBAR|TRUNCATE|UNASSIGN|WHENEVER|ANALYZER|COALESCE|COMMENTS|CONDENSE|DECIMALS|DEFERRED|ENDWHILE|EXPLICIT|KEYWORDS|MESSAGES|POSITION|PRIORITY|RECEIVER|RENAMING|TIMEZONE|TRAILING|ALLOCATE|CENTERED|CIRCULAR|CONTROLS|CURRENCY|DELETING|DESCRIBE|DISTANCE|ENDCATCH|EXPONENT|EXTENDED|GENERATE|IGNORING|INCLUDES|INTERNAL|MAJOR-ID|MODIFIER|NEW-LINE|OPTIONAL|PROPERTY|ROLLBACK|STARTING|SUPPLIED|ABSTRACT|CHANGING|CONTEXTS|CREATING|CUSTOMER|DATABASE|DAYLIGHT|DEFINING|DISTINCT|DIVISION|ENABLING|ENDCHAIN|ESCAPING|HARMLESS|IMPLICIT|INACTIVE|LANGUAGE|MINOR-ID|MULTIPLY|NEW-PAGE|NO-TITLE|POS_HIGH|SEPARATE|TEXTPOOL|TRANSFER|SELECTOR|DBMAXLEN|ITERATOR|ARCHIVE|BIT-XOR|BYTE-CO|COLLECT|COMMENT|CURRENT|DEFAULT|DISPLAY|ENDFORM|EXTRACT|LEADING|LISTBOX|LOCATOR|MEMBERS|METHODS|NESTING|POS_LOW|PROCESS|PROVIDE|RAISING|RESERVE|SECONDS|SUMMARY|VISIBLE|BETWEEN|BIT-AND|BYTE-CS|CLEANUP|COMPUTE|CONTROL|CONVERT|DATASET|ENDCASE|FORWARD|HEADERS|HOTSPOT|INCLUDE|INVERSE|KEEPING|NO-ZERO|OBJECTS|OVERLAY|PADDING|PATTERN|PROGRAM|REFRESH|SECTION|SUMMING|TESTING|VERSION|WINDOWS|WITHOUT|BIT-NOT|BYTE-CA|BYTE-NA|CASTING|CONTEXT|COUNTRY|DYNAMIC|ENABLED|ENDLOOP|EXECUTE|FRIENDS|HANDLER|HEADING|INITIAL|\*-INPUT|LOGFILE|MAXIMUM|MINIMUM|NO-GAPS|NO-SIGN|PRAGMAS|PRIMARY|PRIVATE|REDUCED|REPLACE|REQUEST|RESULTS|UNICODE|WARNING|ALIASES|BYTE-CN|BYTE-NS|CALLING|COL_KEY|COLUMNS|CONNECT|ENDEXEC|ENTRIES|EXCLUDE|FILTERS|FURTHER|HELP-ID|LOGICAL|MAPPING|MESSAGE|NAMETAB|OPTIONS|PACKAGE|PERFORM|RECEIVE|STATICS|VARYING|BINDING|CHARLEN|GREATER|XSTRLEN|ACCEPT|APPEND|DETAIL|ELSEIF|ENDING|ENDTRY|FORMAT|FRAMES|GIVING|HASHED|HEADER|IMPORT|INSERT|MARGIN|MODULE|NATIVE|OBJECT|OFFSET|REMOTE|RESUME|SAVING|SIMPLE|SUBMIT|TABBED|TOKENS|UNIQUE|UNPACK|UPDATE|WINDOW|YELLOW|ACTUAL|ASPECT|CENTER|CURSOR|DELETE|DIALOG|DIVIDE|DURING|ERRORS|EVENTS|EXTEND|FILTER|HANDLE|HAVING|IGNORE|LITTLE|MEMORY|NO-GAP|OCCURS|OPTION|PERSON|PLACES|PUBLIC|REDUCE|REPORT|RESULT|SINGLE|SORTED|SWITCH|SYNTAX|TARGET|VALUES|WRITER|ASSERT|BLOCKS|BOUNDS|BUFFER|CHANGE|COLUMN|COMMIT|CONCAT|COPIES|CREATE|DDMMYY|DEFINE|ENDIAN|ESCAPE|EXPAND|KERNEL|LAYOUT|LEGACY|LEVELS|MMDDYY|NUMBER|OUTPUT|RANGES|READER|RETURN|SCREEN|SEARCH|SELECT|SHARED|SOURCE|STABLE|STATIC|SUBKEY|SUFFIX|TABLES|UNWIND|YYMMDD|ASSIGN|BACKUP|BEFORE|BINARY|BIT-OR|BLANKS|CLIENT|CODING|COMMON|DEMAND|DYNPRO|EXCEPT|EXISTS|EXPORT|FIELDS|GLOBAL|GROUPS|LENGTH|LOCALE|MEDIUM|METHOD|MODIFY|NESTED|OTHERS|REJECT|SCROLL|SUPPLY|SYMBOL|ENDFOR|STRLEN|ALIGN|BEGIN|BOUND|ENDAT|ENTRY|EVENT|FINAL|FLUSH|GRANT|INNER|SHORT|USING|WRITE|AFTER|BLACK|BLOCK|CLOCK|COLOR|COUNT|DUMMY|EMPTY|ENDDO|ENDON|GREEN|INDEX|INOUT|LEAVE|LEVEL|LINES|MODIF|ORDER|OUTER|RANGE|RESET|RETRY|RIGHT|SMART|SPLIT|STYLE|TABLE|THROW|UNDER|UNTIL|UPPER|UTF-8|WHERE|ALIAS|BLANK|CLEAR|CLOSE|EXACT|FETCH|FIRST|FOUND|GROUP|LLANG|LOCAL|OTHER|REGEX|SPOOL|TITLE|TYPES|VALID|WHILE|ALPHA|BOXED|CATCH|CHAIN|CHECK|CLASS|COVER|ENDIF|EQUIV|FIELD|FLOOR|FRAME|INPUT|LOWER|MATCH|NODES|PAGES|PRINT|RAISE|ROUND|SHIFT|SPACE|SPOTS|STAMP|STATE|TASKS|TIMES|TRMAC|ULINE|UNION|VALUE|WIDTH|EQUAL|LOG10|TRUNC|BLOB|CASE|CEIL|CLOB|COND|EXIT|FILE|GAPS|HOLD|INCL|INTO|KEEP|KEYS|LAST|LINE|LONG|LPAD|MAIL|MODE|OPEN|PINK|READ|ROWS|TEST|THEN|ZERO|AREA|BACK|BADI|BYTE|CAST|EDIT|EXEC|FAIL|FIND|FKEQ|FONT|FREE|GKEQ|HIDE|INIT|ITNO|LATE|LOOP|MAIN|MARK|MOVE|NEXT|NULL|RISK|ROLE|UNIT|WAIT|ZONE|BASE|CALL|CODE|DATA|DATE|FKGE|GKGE|HIGH|KIND|LEFT|LIST|MASK|MESH|NAME|NODE|PACK|PAGE|POOL|SEND|SIGN|SIZE|SOME|STOP|TASK|TEXT|TIME|USER|VARY|WITH|WORD|BLUE|CONV|COPY|DEEP|ELSE|FORM|FROM|HINT|ICON|JOIN|LIKE|LOAD|ONLY|PART|SCAN|SKIP|SORT|TYPE|UNIX|VIEW|WHEN|WORK|ACOS|ASIN|ATAN|COSH|EACH|FRAC|LESS|RTTI|SINH|SQRT|TANH|AVG|BIT|DIV|ISO|LET|OUT|PAD|SQL|ALL|CI_|CPI|END|LOB|LPI|MAX|MIN|NEW|OLE|RUN|SET|\?TO|YES|ABS|ADD|AND|BIG|FOR|HDB|JOB|LOW|NOT|SAP|TRY|VIA|XML|ANY|GET|IDS|KEY|MOD|OFF|PUT|RAW|RED|REF|SUM|TAB|XSD|CNT|COS|EXP|LOG|SIN|TAN|XOR|AT|CO|CP|DO|GT|ID|IF|NS|OR|BT|CA|CS|GE|NA|NB|EQ|IN|LT|NE|NO|OF|ON|PF|TO|AS|BY|CN|IS|LE|NP|UP|E|I|M|O|Z|C|X)\b/i,lookbehind:!0},number:/\b\d+\b/,operator:{pattern:/(\s)(?:\*\*?|<[=>]?|>=?|\?=|[-+\/=])(?=\s)/,lookbehind:!0},"string-operator":{pattern:/(\s)&&?(?=\s)/,lookbehind:!0,alias:"keyword"},"token-operator":[{pattern:/(\w)(?:->?|=>|[~|{}])(?=\w)/,lookbehind:!0,alias:"punctuation"},{pattern:/[|{}]/,alias:"punctuation"}],punctuation:/[,.:()]/}}return js}var Hs,xy;function P$(){if(xy)return Hs;xy=1,Hs=e,e.displayName="abnf",e.aliases=[];function e(t){(function(n){var r="(?:ALPHA|BIT|CHAR|CR|CRLF|CTL|DIGIT|DQUOTE|HEXDIG|HTAB|LF|LWSP|OCTET|SP|VCHAR|WSP)";n.languages.abnf={comment:/;.*/,string:{pattern:/(?:%[is])?"[^"\n\r]*"/,greedy:!0,inside:{punctuation:/^%[is]/}},range:{pattern:/%(?:b[01]+-[01]+|d\d+-\d+|x[A-F\d]+-[A-F\d]+)/i,alias:"number"},terminal:{pattern:/%(?:b[01]+(?:\.[01]+)*|d\d+(?:\.\d+)*|x[A-F\d]+(?:\.[A-F\d]+)*)/i,alias:"number"},repetition:{pattern:/(^|[^\w-])(?:\d*\*\d*|\d+)/,lookbehind:!0,alias:"operator"},definition:{pattern:/(^[ \t]*)(?:[a-z][\w-]*|<[^<>\r\n]*>)(?=\s*=)/m,lookbehind:!0,alias:"keyword",inside:{punctuation:/<|>/}},"core-rule":{pattern:RegExp("(?:(^|[^<\\w-])"+r+"|<"+r+">)(?![\\w-])","i"),lookbehind:!0,alias:["rule","constant"],inside:{punctuation:/<|>/}},rule:{pattern:/(^|[^<\w-])[a-z][\w-]*|<[^<>\r\n]*>/i,lookbehind:!0,inside:{punctuation:/<|>/}},operator:/=\/?|\//,punctuation:/[()\[\]]/}})(t)}return Hs}var Vs,Oy;function U$(){if(Oy)return Vs;Oy=1,Vs=e,e.displayName="actionscript",e.aliases=[];function e(t){t.languages.actionscript=t.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|dynamic|each|else|extends|final|finally|for|function|get|if|implements|import|in|include|instanceof|interface|internal|is|namespace|native|new|null|override|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|use|var|void|while|with)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),t.languages.actionscript["class-name"].alias="function",delete t.languages.actionscript.parameter,delete t.languages.actionscript["literal-property"],t.languages.markup&&t.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:t.languages.markup}})}return Vs}var Ws,Ly;function B$(){if(Ly)return Ws;Ly=1,Ws=e,e.displayName="ada",e.aliases=[];function e(t){t.languages.ada={comment:/--.*/,string:/"(?:""|[^"\r\f\n])*"/,number:[{pattern:/\b\d(?:_?\d)*#[\dA-F](?:_?[\dA-F])*(?:\.[\dA-F](?:_?[\dA-F])*)?#(?:E[+-]?\d(?:_?\d)*)?/i},{pattern:/\b\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:E[+-]?\d(?:_?\d)*)?\b/i}],"attr-name":/\b'\w+/,keyword:/\b(?:abort|abs|abstract|accept|access|aliased|all|and|array|at|begin|body|case|constant|declare|delay|delta|digits|do|else|elsif|end|entry|exception|exit|for|function|generic|goto|if|in|interface|is|limited|loop|mod|new|not|null|of|others|out|overriding|package|pragma|private|procedure|protected|raise|range|record|rem|renames|requeue|return|reverse|select|separate|some|subtype|synchronized|tagged|task|terminate|then|type|until|use|when|while|with|xor)\b/i,boolean:/\b(?:false|true)\b/i,operator:/<[=>]?|>=?|=>?|:=|\/=?|\*\*?|[&+-]/,punctuation:/\.\.?|[,;():]/,char:/'.'/,variable:/\b[a-z](?:\w)*\b/i}}return Ws}var Ys,Dy;function $$(){if(Dy)return Ys;Dy=1,Ys=e,e.displayName="agda",e.aliases=[];function e(t){(function(n){n.languages.agda={comment:/\{-[\s\S]*?(?:-\}|$)|--.*/,string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},punctuation:/[(){}⦃⦄.;@]/,"class-name":{pattern:/((?:data|record) +)\S+/,lookbehind:!0},function:{pattern:/(^[ \t]*)(?!\s)[^:\r\n]+(?=:)/m,lookbehind:!0},operator:{pattern:/(^\s*|\s)(?:[=|:∀→λ\\?_]|->)(?=\s)/,lookbehind:!0},keyword:/\b(?:Set|abstract|constructor|data|eta-equality|field|forall|hiding|import|in|inductive|infix|infixl|infixr|instance|let|macro|module|mutual|no-eta-equality|open|overlap|pattern|postulate|primitive|private|public|quote|quoteContext|quoteGoal|quoteTerm|record|renaming|rewrite|syntax|tactic|unquote|unquoteDecl|unquoteDef|using|variable|where|with)\b/}})(t)}return Ys}var Ks,My;function z$(){if(My)return Ks;My=1,Ks=e,e.displayName="al",e.aliases=[];function e(t){t.languages.al={comment:/\/\/.*|\/\*[\s\S]*?\*\//,string:{pattern:/'(?:''|[^'\r\n])*'(?!')|"(?:""|[^"\r\n])*"(?!")/,greedy:!0},function:{pattern:/(\b(?:event|procedure|trigger)\s+|(?:^|[^.])\.\s*)[a-z_]\w*(?=\s*\()/i,lookbehind:!0},keyword:[/\b(?:array|asserterror|begin|break|case|do|downto|else|end|event|exit|for|foreach|function|if|implements|in|indataset|interface|internal|local|of|procedure|program|protected|repeat|runonclient|securityfiltering|suppressdispose|temporary|then|to|trigger|until|var|while|with|withevents)\b/i,/\b(?:action|actions|addafter|addbefore|addfirst|addlast|area|assembly|chartpart|codeunit|column|controladdin|cuegroup|customizes|dataitem|dataset|dotnet|elements|enum|enumextension|extends|field|fieldattribute|fieldelement|fieldgroup|fieldgroups|fields|filter|fixed|grid|group|key|keys|label|labels|layout|modify|moveafter|movebefore|movefirst|movelast|page|pagecustomization|pageextension|part|profile|query|repeater|report|requestpage|schema|separator|systempart|table|tableelement|tableextension|textattribute|textelement|type|usercontrol|value|xmlport)\b/i],number:/\b(?:0x[\da-f]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)(?:F|LL?|U(?:LL?)?)?\b/i,boolean:/\b(?:false|true)\b/i,variable:/\b(?:Curr(?:FieldNo|Page|Report)|x?Rec|RequestOptionsPage)\b/,"class-name":/\b(?:automation|biginteger|bigtext|blob|boolean|byte|char|clienttype|code|completiontriggererrorlevel|connectiontype|database|dataclassification|datascope|date|dateformula|datetime|decimal|defaultlayout|dialog|dictionary|dotnetassembly|dotnettypedeclaration|duration|errorinfo|errortype|executioncontext|executionmode|fieldclass|fieldref|fieldtype|file|filterpagebuilder|guid|httpclient|httpcontent|httpheaders|httprequestmessage|httpresponsemessage|instream|integer|joker|jsonarray|jsonobject|jsontoken|jsonvalue|keyref|list|moduledependencyinfo|moduleinfo|none|notification|notificationscope|objecttype|option|outstream|pageresult|record|recordid|recordref|reportformat|securityfilter|sessionsettings|tableconnectiontype|tablefilter|testaction|testfield|testfilterfield|testpage|testpermissions|testrequestpage|text|textbuilder|textconst|textencoding|time|transactionmodel|transactiontype|variant|verbosity|version|view|views|webserviceactioncontext|webserviceactionresultcode|xmlattribute|xmlattributecollection|xmlcdata|xmlcomment|xmldeclaration|xmldocument|xmldocumenttype|xmlelement|xmlnamespacemanager|xmlnametable|xmlnode|xmlnodelist|xmlprocessinginstruction|xmlreadoptions|xmltext|xmlwriteoptions)\b/i,operator:/\.\.|:[=:]|[-+*/]=?|<>|[<>]=?|=|\b(?:and|div|mod|not|or|xor)\b/i,punctuation:/[()\[\]{}:.;,]/}}return Ks}var Xs,Fy;function G$(){if(Fy)return Xs;Fy=1,Xs=e,e.displayName="antlr4",e.aliases=["g4"];function e(t){t.languages.antlr4={comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,string:{pattern:/'(?:\\.|[^\\'\r\n])*'/,greedy:!0},"character-class":{pattern:/\[(?:\\.|[^\\\]\r\n])*\]/,greedy:!0,alias:"regex",inside:{range:{pattern:/([^[]|(?:^|[^\\])(?:\\\\)*\\\[)-(?!\])/,lookbehind:!0,alias:"punctuation"},escape:/\\(?:u(?:[a-fA-F\d]{4}|\{[a-fA-F\d]+\})|[pP]\{[=\w-]+\}|[^\r\nupP])/,punctuation:/[\[\]]/}},action:{pattern:/\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*\}/,greedy:!0,inside:{content:{pattern:/(\{)[\s\S]+(?=\})/,lookbehind:!0},punctuation:/[{}]/}},command:{pattern:/(->\s*(?!\s))(?:\s*(?:,\s*)?\b[a-z]\w*(?:\s*\([^()\r\n]*\))?)+(?=\s*;)/i,lookbehind:!0,inside:{function:/\b\w+(?=\s*(?:[,(]|$))/,punctuation:/[,()]/}},annotation:{pattern:/@\w+(?:::\w+)*/,alias:"keyword"},label:{pattern:/#[ \t]*\w+/,alias:"punctuation"},keyword:/\b(?:catch|channels|finally|fragment|grammar|import|lexer|locals|mode|options|parser|returns|throws|tokens)\b/,definition:[{pattern:/\b[a-z]\w*(?=\s*:)/,alias:["rule","class-name"]},{pattern:/\b[A-Z]\w*(?=\s*:)/,alias:["token","constant"]}],constant:/\b[A-Z][A-Z_]*\b/,operator:/\.\.|->|[|~]|[*+?]\??/,punctuation:/[;:()=]/},t.languages.g4=t.languages.antlr4}return Xs}var Zs,Py;function q$(){if(Py)return Zs;Py=1,Zs=e,e.displayName="apacheconf",e.aliases=[];function e(t){t.languages.apacheconf={comment:/#.*/,"directive-inline":{pattern:/(^[\t ]*)\b(?:AcceptFilter|AcceptPathInfo|AccessFileName|Action|Add(?:Alt|AltByEncoding|AltByType|Charset|DefaultCharset|Description|Encoding|Handler|Icon|IconByEncoding|IconByType|InputFilter|Language|ModuleInfo|OutputFilter|OutputFilterByType|Type)|Alias|AliasMatch|Allow(?:CONNECT|EncodedSlashes|Methods|Override|OverrideList)?|Anonymous(?:_LogEmail|_MustGiveEmail|_NoUserID|_VerifyEmail)?|AsyncRequestWorkerFactor|Auth(?:BasicAuthoritative|BasicFake|BasicProvider|BasicUseDigestAlgorithm|DBDUserPWQuery|DBDUserRealmQuery|DBMGroupFile|DBMType|DBMUserFile|Digest(?:Algorithm|Domain|NonceLifetime|Provider|Qop|ShmemSize)|Form(?:Authoritative|Body|DisableNoStore|FakeBasicAuth|Location|LoginRequiredLocation|LoginSuccessLocation|LogoutLocation|Method|Mimetype|Password|Provider|SitePassphrase|Size|Username)|GroupFile|LDAP(?:AuthorizePrefix|BindAuthoritative|BindDN|BindPassword|CharsetConfig|CompareAsUser|CompareDNOnServer|DereferenceAliases|GroupAttribute|GroupAttributeIsDN|InitialBindAsUser|InitialBindPattern|MaxSubGroupDepth|RemoteUserAttribute|RemoteUserIsDN|SearchAsUser|SubGroupAttribute|SubGroupClass|Url)|Merging|Name|nCache(?:Context|Enable|ProvideFor|SOCache|Timeout)|nzFcgiCheckAuthnProvider|nzFcgiDefineProvider|Type|UserFile|zDBDLoginToReferer|zDBDQuery|zDBDRedirectQuery|zDBMType|zSendForbiddenOnFailure)|BalancerGrowth|BalancerInherit|BalancerMember|BalancerPersist|BrowserMatch|BrowserMatchNoCase|BufferedLogs|BufferSize|Cache(?:DefaultExpire|DetailHeader|DirLength|DirLevels|Disable|Enable|File|Header|IgnoreCacheControl|IgnoreHeaders|IgnoreNoLastMod|IgnoreQueryString|IgnoreURLSessionIdentifiers|KeyBaseURL|LastModifiedFactor|Lock|LockMaxAge|LockPath|MaxExpire|MaxFileSize|MinExpire|MinFileSize|NegotiatedDocs|QuickHandler|ReadSize|ReadTime|Root|Socache(?:MaxSize|MaxTime|MinTime|ReadSize|ReadTime)?|StaleOnError|StoreExpired|StoreNoStore|StorePrivate)|CGIDScriptTimeout|CGIMapExtension|CharsetDefault|CharsetOptions|CharsetSourceEnc|CheckCaseOnly|CheckSpelling|ChrootDir|ContentDigest|CookieDomain|CookieExpires|CookieName|CookieStyle|CookieTracking|CoreDumpDirectory|CustomLog|Dav|DavDepthInfinity|DavGenericLockDB|DavLockDB|DavMinTimeout|DBDExptime|DBDInitSQL|DBDKeep|DBDMax|DBDMin|DBDParams|DBDPersist|DBDPrepareSQL|DBDriver|DefaultIcon|DefaultLanguage|DefaultRuntimeDir|DefaultType|Define|Deflate(?:BufferSize|CompressionLevel|FilterNote|InflateLimitRequestBody|InflateRatio(?:Burst|Limit)|MemLevel|WindowSize)|Deny|DirectoryCheckHandler|DirectoryIndex|DirectoryIndexRedirect|DirectorySlash|DocumentRoot|DTracePrivileges|DumpIOInput|DumpIOOutput|EnableExceptionHook|EnableMMAP|EnableSendfile|Error|ErrorDocument|ErrorLog|ErrorLogFormat|Example|ExpiresActive|ExpiresByType|ExpiresDefault|ExtendedStatus|ExtFilterDefine|ExtFilterOptions|FallbackResource|FileETag|FilterChain|FilterDeclare|FilterProtocol|FilterProvider|FilterTrace|ForceLanguagePriority|ForceType|ForensicLog|GprofDir|GracefulShutdownTimeout|Group|Header|HeaderName|Heartbeat(?:Address|Listen|MaxServers|Storage)|HostnameLookups|IdentityCheck|IdentityCheckTimeout|ImapBase|ImapDefault|ImapMenu|Include|IncludeOptional|Index(?:HeadInsert|Ignore|IgnoreReset|Options|OrderDefault|StyleSheet)|InputSed|ISAPI(?:AppendLogToErrors|AppendLogToQuery|CacheFile|FakeAsync|LogNotSupported|ReadAheadBuffer)|KeepAlive|KeepAliveTimeout|KeptBodySize|LanguagePriority|LDAP(?:CacheEntries|CacheTTL|ConnectionPoolTTL|ConnectionTimeout|LibraryDebug|OpCacheEntries|OpCacheTTL|ReferralHopLimit|Referrals|Retries|RetryDelay|SharedCacheFile|SharedCacheSize|Timeout|TrustedClientCert|TrustedGlobalCert|TrustedMode|VerifyServerCert)|Limit(?:InternalRecursion|Request(?:Body|Fields|FieldSize|Line)|XMLRequestBody)|Listen|ListenBackLog|LoadFile|LoadModule|LogFormat|LogLevel|LogMessage|LuaAuthzProvider|LuaCodeCache|Lua(?:Hook(?:AccessChecker|AuthChecker|CheckUserID|Fixups|InsertFilter|Log|MapToStorage|TranslateName|TypeChecker)|Inherit|InputFilter|MapHandler|OutputFilter|PackageCPath|PackagePath|QuickHandler|Root|Scope)|Max(?:ConnectionsPerChild|KeepAliveRequests|MemFree|RangeOverlaps|RangeReversals|Ranges|RequestWorkers|SpareServers|SpareThreads|Threads)|MergeTrailers|MetaDir|MetaFiles|MetaSuffix|MimeMagicFile|MinSpareServers|MinSpareThreads|MMapFile|ModemStandard|ModMimeUsePathInfo|MultiviewsMatch|Mutex|NameVirtualHost|NoProxy|NWSSLTrustedCerts|NWSSLUpgradeable|Options|Order|OutputSed|PassEnv|PidFile|PrivilegesMode|Protocol|ProtocolEcho|Proxy(?:AddHeaders|BadHeader|Block|Domain|ErrorOverride|ExpressDBMFile|ExpressDBMType|ExpressEnable|FtpDirCharset|FtpEscapeWildcards|FtpListOnWildcard|HTML(?:BufSize|CharsetOut|DocType|Enable|Events|Extended|Fixups|Interp|Links|Meta|StripComments|URLMap)|IOBufferSize|MaxForwards|Pass(?:Inherit|InterpolateEnv|Match|Reverse|ReverseCookieDomain|ReverseCookiePath)?|PreserveHost|ReceiveBufferSize|Remote|RemoteMatch|Requests|SCGIInternalRedirect|SCGISendfile|Set|SourceAddress|Status|Timeout|Via)|ReadmeName|ReceiveBufferSize|Redirect|RedirectMatch|RedirectPermanent|RedirectTemp|ReflectorHeader|RemoteIP(?:Header|InternalProxy|InternalProxyList|ProxiesHeader|TrustedProxy|TrustedProxyList)|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|RequestHeader|RequestReadTimeout|Require|Rewrite(?:Base|Cond|Engine|Map|Options|Rule)|RLimitCPU|RLimitMEM|RLimitNPROC|Satisfy|ScoreBoardFile|Script(?:Alias|AliasMatch|InterpreterSource|Log|LogBuffer|LogLength|Sock)?|SecureListen|SeeRequestTail|SendBufferSize|Server(?:Admin|Alias|Limit|Name|Path|Root|Signature|Tokens)|Session(?:Cookie(?:Name|Name2|Remove)|Crypto(?:Cipher|Driver|Passphrase|PassphraseFile)|DBD(?:CookieName|CookieName2|CookieRemove|DeleteLabel|InsertLabel|PerUser|SelectLabel|UpdateLabel)|Env|Exclude|Header|Include|MaxAge)?|SetEnv|SetEnvIf|SetEnvIfExpr|SetEnvIfNoCase|SetHandler|SetInputFilter|SetOutputFilter|SSIEndTag|SSIErrorMsg|SSIETag|SSILastModified|SSILegacyExprParser|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|SSL(?:CACertificateFile|CACertificatePath|CADNRequestFile|CADNRequestPath|CARevocationCheck|CARevocationFile|CARevocationPath|CertificateChainFile|CertificateFile|CertificateKeyFile|CipherSuite|Compression|CryptoDevice|Engine|FIPS|HonorCipherOrder|InsecureRenegotiation|OCSP(?:DefaultResponder|Enable|OverrideResponder|ResponderTimeout|ResponseMaxAge|ResponseTimeSkew|UseRequestNonce)|OpenSSLConfCmd|Options|PassPhraseDialog|Protocol|Proxy(?:CACertificateFile|CACertificatePath|CARevocation(?:Check|File|Path)|CheckPeer(?:CN|Expire|Name)|CipherSuite|Engine|MachineCertificate(?:ChainFile|File|Path)|Protocol|Verify|VerifyDepth)|RandomSeed|RenegBufferSize|Require|RequireSSL|Session(?:Cache|CacheTimeout|TicketKeyFile|Tickets)|SRPUnknownUserSeed|SRPVerifierFile|Stapling(?:Cache|ErrorCacheTimeout|FakeTryLater|ForceURL|ResponderTimeout|ResponseMaxAge|ResponseTimeSkew|ReturnResponderErrors|StandardCacheTimeout)|StrictSNIVHostCheck|UserName|UseStapling|VerifyClient|VerifyDepth)|StartServers|StartThreads|Substitute|Suexec|SuexecUserGroup|ThreadLimit|ThreadsPerChild|ThreadStackSize|TimeOut|TraceEnable|TransferLog|TypesConfig|UnDefine|UndefMacro|UnsetEnv|Use|UseCanonicalName|UseCanonicalPhysicalPort|User|UserDir|VHostCGIMode|VHostCGIPrivs|VHostGroup|VHostPrivs|VHostSecure|VHostUser|Virtual(?:DocumentRoot|ScriptAlias)(?:IP)?|WatchdogInterval|XBitHack|xml2EncAlias|xml2EncDefault|xml2StartParse)\b/im,lookbehind:!0,alias:"property"},"directive-block":{pattern:/<\/?\b(?:Auth[nz]ProviderAlias|Directory|DirectoryMatch|Else|ElseIf|Files|FilesMatch|If|IfDefine|IfModule|IfVersion|Limit|LimitExcept|Location|LocationMatch|Macro|Proxy|Require(?:All|Any|None)|VirtualHost)\b.*>/i,inside:{"directive-block":{pattern:/^<\/?\w+/,inside:{punctuation:/^<\/?/},alias:"tag"},"directive-block-parameter":{pattern:/.*[^>]/,inside:{punctuation:/:/,string:{pattern:/("|').*\1/,inside:{variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/}}},alias:"attr-value"},punctuation:/>/},alias:"tag"},"directive-flags":{pattern:/\[(?:[\w=],?)+\]/,alias:"keyword"},string:{pattern:/("|').*\1/,inside:{variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/}},variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/,regex:/\^?.*\$|\^.*\$?/}}return Zs}var Qs,Uy;function Bm(){if(Uy)return Qs;Uy=1,Qs=e,e.displayName="sql",e.aliases=[];function e(t){t.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}}return Qs}var Js,By;function j$(){if(By)return Js;By=1;var e=Bm();Js=t,t.displayName="apex",t.aliases=[];function t(n){n.register(e),function(r){var a=/\b(?:(?:after|before)(?=\s+[a-z])|abstract|activate|and|any|array|as|asc|autonomous|begin|bigdecimal|blob|boolean|break|bulk|by|byte|case|cast|catch|char|class|collect|commit|const|continue|currency|date|datetime|decimal|default|delete|desc|do|double|else|end|enum|exception|exit|export|extends|final|finally|float|for|from|get(?=\s*[{};])|global|goto|group|having|hint|if|implements|import|in|inner|insert|instanceof|int|integer|interface|into|join|like|limit|list|long|loop|map|merge|new|not|null|nulls|number|object|of|on|or|outer|override|package|parallel|pragma|private|protected|public|retrieve|return|rollback|select|set|short|sObject|sort|static|string|super|switch|synchronized|system|testmethod|then|this|throw|time|transaction|transient|trigger|try|undelete|update|upsert|using|virtual|void|webservice|when|where|while|(?:inherited|with|without)\s+sharing)\b/i,i=/\b(?:(?=[a-z_]\w*\s*[<\[])|(?!))[A-Z_]\w*(?:\s*\.\s*[A-Z_]\w*)*\b(?:\s*(?:\[\s*\]|<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>))*/.source.replace(//g,function(){return a.source});function o(l){return RegExp(l.replace(//g,function(){return i}),"i")}var s={keyword:a,punctuation:/[()\[\]{};,:.<>]/};r.languages.apex={comment:r.languages.clike.comment,string:r.languages.clike.string,sql:{pattern:/((?:[=,({:]|\breturn)\s*)\[[^\[\]]*\]/i,lookbehind:!0,greedy:!0,alias:"language-sql",inside:r.languages.sql},annotation:{pattern:/@\w+\b/,alias:"punctuation"},"class-name":[{pattern:o(/(\b(?:class|enum|extends|implements|instanceof|interface|new|trigger\s+\w+\s+on)\s+)/.source),lookbehind:!0,inside:s},{pattern:o(/(\(\s*)(?=\s*\)\s*[\w(])/.source),lookbehind:!0,inside:s},{pattern:o(/(?=\s*\w+\s*[;=,(){:])/.source),inside:s}],trigger:{pattern:/(\btrigger\s+)\w+\b/i,lookbehind:!0,alias:"class-name"},keyword:a,function:/\b[a-z_]\w*(?=\s*\()/i,boolean:/\b(?:false|true)\b/i,number:/(?:\B\.\d+|\b\d+(?:\.\d+|L)?)\b/i,operator:/[!=](?:==?)?|\?\.?|&&|\|\||--|\+\+|[-+*/^&|]=?|:|<{1,3}=?/,punctuation:/[()\[\]{};,.]/}}(n)}return Js}var el,$y;function H$(){if($y)return el;$y=1,el=e,e.displayName="apl",e.aliases=[];function e(t){t.languages.apl={comment:/(?:⍝|#[! ]).*$/m,string:{pattern:/'(?:[^'\r\n]|'')*'/,greedy:!0},number:/¯?(?:\d*\.?\b\d+(?:e[+¯]?\d+)?|¯|∞)(?:j¯?(?:(?:\d+(?:\.\d+)?|\.\d+)(?:e[+¯]?\d+)?|¯|∞))?/i,statement:/:[A-Z][a-z][A-Za-z]*\b/,"system-function":{pattern:/⎕[A-Z]+/i,alias:"function"},constant:/[⍬⌾#⎕⍞]/,function:/[-+×÷⌈⌊∣|⍳⍸?*⍟○!⌹<≤=>≥≠≡≢∊⍷∪∩~∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⊆⊇⌷⍋⍒⊤⊥⍕⍎⊣⊢⍁⍂≈⍯↗¤→]/,"monadic-operator":{pattern:/[\\\/⌿⍀¨⍨⌶&∥]/,alias:"operator"},"dyadic-operator":{pattern:/[.⍣⍠⍤∘⌸@⌺⍥]/,alias:"operator"},assignment:{pattern:/←/,alias:"keyword"},punctuation:/[\[;\]()◇⋄]/,dfn:{pattern:/[{}⍺⍵⍶⍹∇⍫:]/,alias:"builtin"}}}return el}var tl,zy;function V$(){if(zy)return tl;zy=1,tl=e,e.displayName="applescript",e.aliases=[];function e(t){t.languages.applescript={comment:[/\(\*(?:\(\*(?:[^*]|\*(?!\)))*\*\)|(?!\(\*)[\s\S])*?\*\)/,/--.+/,/#.+/],string:/"(?:\\.|[^"\\\r\n])*"/,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e-?\d+)?\b/i,operator:[/[&=≠≤≥*+\-\/÷^]|[<>]=?/,/\b(?:(?:begin|end|start)s? with|(?:contains?|(?:does not|doesn't) contain)|(?:is|isn't|is not) (?:contained by|in)|(?:(?:is|isn't|is not) )?(?:greater|less) than(?: or equal)?(?: to)?|(?:comes|(?:does not|doesn't) come) (?:after|before)|(?:is|isn't|is not) equal(?: to)?|(?:(?:does not|doesn't) equal|equal to|equals|is not|isn't)|(?:a )?(?:ref(?: to)?|reference to)|(?:and|as|div|mod|not|or))\b/],keyword:/\b(?:about|above|after|against|apart from|around|aside from|at|back|before|beginning|behind|below|beneath|beside|between|but|by|considering|continue|copy|does|eighth|else|end|equal|error|every|exit|false|fifth|first|for|fourth|from|front|get|given|global|if|ignoring|in|instead of|into|is|it|its|last|local|me|middle|my|ninth|of|on|onto|out of|over|prop|property|put|repeat|return|returning|second|set|seventh|since|sixth|some|tell|tenth|that|the|then|third|through|thru|timeout|times|to|transaction|true|try|until|where|while|whose|with|without)\b/,"class-name":/\b(?:POSIX file|RGB color|alias|application|boolean|centimeters|centimetres|class|constant|cubic centimeters|cubic centimetres|cubic feet|cubic inches|cubic meters|cubic metres|cubic yards|date|degrees Celsius|degrees Fahrenheit|degrees Kelvin|feet|file|gallons|grams|inches|integer|kilograms|kilometers|kilometres|list|liters|litres|meters|metres|miles|number|ounces|pounds|quarts|real|record|reference|script|square feet|square kilometers|square kilometres|square meters|square metres|square miles|square yards|text|yards)\b/,punctuation:/[{}():,¬«»《》]/}}return tl}var nl,Gy;function W$(){if(Gy)return nl;Gy=1,nl=e,e.displayName="aql",e.aliases=[];function e(t){t.languages.aql={comment:/\/\/.*|\/\*[\s\S]*?\*\//,property:{pattern:/([{,]\s*)(?:(?!\d)\w+|(["'´`])(?:(?!\2)[^\\\r\n]|\\.)*\2)(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\.)*\1/,greedy:!0},identifier:{pattern:/([´`])(?:(?!\1)[^\\\r\n]|\\.)*\1/,greedy:!0},variable:/@@?\w+/,keyword:[{pattern:/(\bWITH\s+)COUNT(?=\s+INTO\b)/i,lookbehind:!0},/\b(?:AGGREGATE|ALL|AND|ANY|ASC|COLLECT|DESC|DISTINCT|FILTER|FOR|GRAPH|IN|INBOUND|INSERT|INTO|K_PATHS|K_SHORTEST_PATHS|LET|LIKE|LIMIT|NONE|NOT|NULL|OR|OUTBOUND|REMOVE|REPLACE|RETURN|SHORTEST_PATH|SORT|UPDATE|UPSERT|WINDOW|WITH)\b/i,{pattern:/(^|[^\w.[])(?:KEEP|PRUNE|SEARCH|TO)\b/i,lookbehind:!0},{pattern:/(^|[^\w.[])(?:CURRENT|NEW|OLD)\b/,lookbehind:!0},{pattern:/\bOPTIONS(?=\s*\{)/i}],function:/\b(?!\d)\w+(?=\s*\()/,boolean:/\b(?:false|true)\b/i,range:{pattern:/\.\./,alias:"operator"},number:[/\b0b[01]+/i,/\b0x[0-9a-f]+/i,/(?:\B\.\d+|\b(?:0|[1-9]\d*)(?:\.\d+)?)(?:e[+-]?\d+)?/i],operator:/\*{2,}|[=!]~|[!=<>]=?|&&|\|\||[-+*/%]/,punctuation:/::|[?.:,;()[\]{}]/}}return nl}var rl,qy;function tr(){if(qy)return rl;qy=1,rl=e,e.displayName="c",e.aliases=[];function e(t){t.languages.c=t.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),t.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),t.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},t.languages.c.string],char:t.languages.c.char,comment:t.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:t.languages.c}}}}),t.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete t.languages.c.boolean}return rl}var al,jy;function $m(){if(jy)return al;jy=1;var e=tr();al=t,t.displayName="cpp",t.aliases=[];function t(n){n.register(e),function(r){var a=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,i=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,function(){return a.source});r.languages.cpp=r.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,function(){return a.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:a,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),r.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,function(){return i})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),r.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:r.languages.cpp}}}}),r.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),r.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:r.languages.extend("cpp",{})}}),r.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},r.languages.cpp["base-clause"])}(n)}return al}var il,Hy;function Y$(){if(Hy)return il;Hy=1;var e=$m();il=t,t.displayName="arduino",t.aliases=["ino"];function t(n){n.register(e),n.languages.arduino=n.languages.extend("cpp",{keyword:/\b(?:String|array|bool|boolean|break|byte|case|catch|continue|default|do|double|else|finally|for|function|goto|if|in|instanceof|int|integer|long|loop|new|null|return|setup|string|switch|throw|try|void|while|word)\b/,constant:/\b(?:ANALOG_MESSAGE|DEFAULT|DIGITAL_MESSAGE|EXTERNAL|FIRMATA_STRING|HIGH|INPUT|INPUT_PULLUP|INTERNAL|INTERNAL1V1|INTERNAL2V56|LED_BUILTIN|LOW|OUTPUT|REPORT_ANALOG|REPORT_DIGITAL|SET_PIN_MODE|SYSEX_START|SYSTEM_RESET)\b/,builtin:/\b(?:Audio|BSSID|Bridge|Client|Console|EEPROM|Esplora|EsploraTFT|Ethernet|EthernetClient|EthernetServer|EthernetUDP|File|FileIO|FileSystem|Firmata|GPRS|GSM|GSMBand|GSMClient|GSMModem|GSMPIN|GSMScanner|GSMServer|GSMVoiceCall|GSM_SMS|HttpClient|IPAddress|IRread|Keyboard|KeyboardController|LiquidCrystal|LiquidCrystal_I2C|Mailbox|Mouse|MouseController|PImage|Process|RSSI|RobotControl|RobotMotor|SD|SPI|SSID|Scheduler|Serial|Server|Servo|SoftwareSerial|Stepper|Stream|TFT|Task|USBHost|WiFi|WiFiClient|WiFiServer|WiFiUDP|Wire|YunClient|YunServer|abs|addParameter|analogRead|analogReadResolution|analogReference|analogWrite|analogWriteResolution|answerCall|attach|attachGPRS|attachInterrupt|attached|autoscroll|available|background|beep|begin|beginPacket|beginSD|beginSMS|beginSpeaker|beginTFT|beginTransmission|beginWrite|bit|bitClear|bitRead|bitSet|bitWrite|blink|blinkVersion|buffer|changePIN|checkPIN|checkPUK|checkReg|circle|cityNameRead|cityNameWrite|clear|clearScreen|click|close|compassRead|config|connect|connected|constrain|cos|countryNameRead|countryNameWrite|createChar|cursor|debugPrint|delay|delayMicroseconds|detach|detachInterrupt|digitalRead|digitalWrite|disconnect|display|displayLogos|drawBMP|drawCompass|encryptionType|end|endPacket|endSMS|endTransmission|endWrite|exists|exitValue|fill|find|findUntil|flush|gatewayIP|get|getAsynchronously|getBand|getButton|getCurrentCarrier|getIMEI|getKey|getModifiers|getOemKey|getPINUsed|getResult|getSignalStrength|getSocket|getVoiceCallStatus|getXChange|getYChange|hangCall|height|highByte|home|image|interrupts|isActionDone|isDirectory|isListening|isPIN|isPressed|isValid|keyPressed|keyReleased|keyboardRead|knobRead|leftToRight|line|lineFollowConfig|listen|listenOnLocalhost|loadImage|localIP|lowByte|macAddress|maintain|map|max|messageAvailable|micros|millis|min|mkdir|motorsStop|motorsWrite|mouseDragged|mouseMoved|mousePressed|mouseReleased|move|noAutoscroll|noBlink|noBuffer|noCursor|noDisplay|noFill|noInterrupts|noListenOnLocalhost|noStroke|noTone|onReceive|onRequest|open|openNextFile|overflow|parseCommand|parseFloat|parseInt|parsePacket|pauseMode|peek|pinMode|playFile|playMelody|point|pointTo|position|pow|prepare|press|print|printFirmwareVersion|printVersion|println|process|processInput|pulseIn|put|random|randomSeed|read|readAccelerometer|readBlue|readButton|readBytes|readBytesUntil|readGreen|readJoystickButton|readJoystickSwitch|readJoystickX|readJoystickY|readLightSensor|readMessage|readMicrophone|readNetworks|readRed|readSlider|readString|readStringUntil|readTemperature|ready|rect|release|releaseAll|remoteIP|remoteNumber|remotePort|remove|requestFrom|retrieveCallingNumber|rewindDirectory|rightToLeft|rmdir|robotNameRead|robotNameWrite|run|runAsynchronously|runShellCommand|runShellCommandAsynchronously|running|scanNetworks|scrollDisplayLeft|scrollDisplayRight|seek|sendAnalog|sendDigitalPortPair|sendDigitalPorts|sendString|sendSysex|serialEvent|setBand|setBitOrder|setClockDivider|setCursor|setDNS|setDataMode|setFirmwareVersion|setMode|setPINUsed|setSpeed|setTextSize|setTimeout|shiftIn|shiftOut|shutdown|sin|size|sqrt|startLoop|step|stop|stroke|subnetMask|switchPIN|tan|tempoWrite|text|tone|transfer|tuneWrite|turn|updateIR|userNameRead|userNameWrite|voiceCall|waitContinue|width|write|writeBlue|writeGreen|writeJSON|writeMessage|writeMicroseconds|writeRGB|writeRed|yield)\b/}),n.languages.ino=n.languages.arduino}return il}var ol,Vy;function K$(){if(Vy)return ol;Vy=1,ol=e,e.displayName="arff",e.aliases=[];function e(t){t.languages.arff={comment:/%.*/,string:{pattern:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/@(?:attribute|data|end|relation)\b/i,number:/\b\d+(?:\.\d+)?\b/,punctuation:/[{},]/}}return ol}var sl,Wy;function X$(){if(Wy)return sl;Wy=1,sl=e,e.displayName="asciidoc",e.aliases=["adoc"];function e(t){(function(n){var r={pattern:/(^[ \t]*)\[(?!\[)(?:(["'$`])(?:(?!\2)[^\\]|\\.)*\2|\[(?:[^\[\]\\]|\\.)*\]|[^\[\]\\"'$`]|\\.)*\]/m,lookbehind:!0,inside:{quoted:{pattern:/([$`])(?:(?!\1)[^\\]|\\.)*\1/,inside:{punctuation:/^[$`]|[$`]$/}},interpreted:{pattern:/'(?:[^'\\]|\\.)*'/,inside:{punctuation:/^'|'$/}},string:/"(?:[^"\\]|\\.)*"/,variable:/\w+(?==)/,punctuation:/^\[|\]$|,/,operator:/=/,"attr-value":/(?!^\s+$).+/}},a=n.languages.asciidoc={"comment-block":{pattern:/^(\/{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1/m,alias:"comment"},table:{pattern:/^\|={3,}(?:(?:\r?\n|\r(?!\n)).*)*?(?:\r?\n|\r)\|={3,}$/m,inside:{specifiers:{pattern:/(?:(?:(?:\d+(?:\.\d+)?|\.\d+)[+*](?:[<^>](?:\.[<^>])?|\.[<^>])?|[<^>](?:\.[<^>])?|\.[<^>])[a-z]*|[a-z]+)(?=\|)/,alias:"attr-value"},punctuation:{pattern:/(^|[^\\])[|!]=*/,lookbehind:!0}}},"passthrough-block":{pattern:/^(\+{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^\++|\++$/}},"literal-block":{pattern:/^(-{4,}|\.{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^(?:-+|\.+)|(?:-+|\.+)$/}},"other-block":{pattern:/^(--|\*{4,}|_{4,}|={4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^(?:-+|\*+|_+|=+)|(?:-+|\*+|_+|=+)$/}},"list-punctuation":{pattern:/(^[ \t]*)(?:-|\*{1,5}|\.{1,5}|(?:[a-z]|\d+)\.|[xvi]+\))(?= )/im,lookbehind:!0,alias:"punctuation"},"list-label":{pattern:/(^[ \t]*)[a-z\d].+(?::{2,4}|;;)(?=\s)/im,lookbehind:!0,alias:"symbol"},"indented-block":{pattern:/((\r?\n|\r)\2)([ \t]+)\S.*(?:(?:\r?\n|\r)\3.+)*(?=\2{2}|$)/,lookbehind:!0},comment:/^\/\/.*/m,title:{pattern:/^.+(?:\r?\n|\r)(?:={3,}|-{3,}|~{3,}|\^{3,}|\+{3,})$|^={1,5} .+|^\.(?![\s.]).*/m,alias:"important",inside:{punctuation:/^(?:\.|=+)|(?:=+|-+|~+|\^+|\++)$/}},"attribute-entry":{pattern:/^:[^:\r\n]+:(?: .*?(?: \+(?:\r?\n|\r).*?)*)?$/m,alias:"tag"},attributes:r,hr:{pattern:/^'{3,}$/m,alias:"punctuation"},"page-break":{pattern:/^<{3,}$/m,alias:"punctuation"},admonition:{pattern:/^(?:CAUTION|IMPORTANT|NOTE|TIP|WARNING):/m,alias:"keyword"},callout:[{pattern:/(^[ \t]*)/m,lookbehind:!0,alias:"symbol"},{pattern:/<\d+>/,alias:"symbol"}],macro:{pattern:/\b[a-z\d][a-z\d-]*::?(?:[^\s\[\]]*\[(?:[^\]\\"']|(["'])(?:(?!\1)[^\\]|\\.)*\1|\\.)*\])/,inside:{function:/^[a-z\d-]+(?=:)/,punctuation:/^::?/,attributes:{pattern:/(?:\[(?:[^\]\\"']|(["'])(?:(?!\1)[^\\]|\\.)*\1|\\.)*\])/,inside:r.inside}}},inline:{pattern:/(^|[^\\])(?:(?:\B\[(?:[^\]\\"']|(["'])(?:(?!\2)[^\\]|\\.)*\2|\\.)*\])?(?:\b_(?!\s)(?: _|[^_\\\r\n]|\\.)+(?:(?:\r?\n|\r)(?: _|[^_\\\r\n]|\\.)+)*_\b|\B``(?!\s).+?(?:(?:\r?\n|\r).+?)*''\B|\B`(?!\s)(?:[^`'\s]|\s+\S)+['`]\B|\B(['*+#])(?!\s)(?: \3|(?!\3)[^\\\r\n]|\\.)+(?:(?:\r?\n|\r)(?: \3|(?!\3)[^\\\r\n]|\\.)+)*\3\B)|(?:\[(?:[^\]\\"']|(["'])(?:(?!\4)[^\\]|\\.)*\4|\\.)*\])?(?:(__|\*\*|\+\+\+?|##|\$\$|[~^]).+?(?:(?:\r?\n|\r).+?)*\5|\{[^}\r\n]+\}|\[\[\[?.+?(?:(?:\r?\n|\r).+?)*\]?\]\]|<<.+?(?:(?:\r?\n|\r).+?)*>>|\(\(\(?.+?(?:(?:\r?\n|\r).+?)*\)?\)\)))/m,lookbehind:!0,inside:{attributes:r,url:{pattern:/^(?:\[\[\[?.+?\]?\]\]|<<.+?>>)$/,inside:{punctuation:/^(?:\[\[\[?|<<)|(?:\]\]\]?|>>)$/}},"attribute-ref":{pattern:/^\{.+\}$/,inside:{variable:{pattern:/(^\{)[a-z\d,+_-]+/,lookbehind:!0},operator:/^[=?!#%@$]|!(?=[:}])/,punctuation:/^\{|\}$|::?/}},italic:{pattern:/^(['_])[\s\S]+\1$/,inside:{punctuation:/^(?:''?|__?)|(?:''?|__?)$/}},bold:{pattern:/^\*[\s\S]+\*$/,inside:{punctuation:/^\*\*?|\*\*?$/}},punctuation:/^(?:``?|\+{1,3}|##?|\$\$|[~^]|\(\(\(?)|(?:''?|\+{1,3}|##?|\$\$|[~^`]|\)?\)\))$/}},replacement:{pattern:/\((?:C|R|TM)\)/,alias:"builtin"},entity:/&#?[\da-z]{1,8};/i,"line-continuation":{pattern:/(^| )\+$/m,lookbehind:!0,alias:"punctuation"}};function i(o){o=o.split(" ");for(var s={},l=0,u=o.length;l>=?|<<=?|&&?|\|\|?|[-+*/%&|^!=<>?]=?/,punctuation:/[(),:]/}}return ul}var cl,Xy;function Xo(){if(Xy)return cl;Xy=1,cl=e,e.displayName="csharp",e.aliases=["dotnet","cs"];function e(t){(function(n){function r(P,G){return P.replace(/<<(\d+)>>/g,function(A,Q){return"(?:"+G[+Q]+")"})}function a(P,G,A){return RegExp(r(P,G),"")}function i(P,G){for(var A=0;A>/g,function(){return"(?:"+P+")"});return P.replace(/<>/g,"[^\\s\\S]")}var o={type:"bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",typeDeclaration:"class enum interface record struct",contextual:"add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",other:"abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield"};function s(P){return"\\b(?:"+P.trim().replace(/ /g,"|")+")\\b"}var l=s(o.typeDeclaration),u=RegExp(s(o.type+" "+o.typeDeclaration+" "+o.contextual+" "+o.other)),d=s(o.typeDeclaration+" "+o.contextual+" "+o.other),c=s(o.type+" "+o.typeDeclaration+" "+o.other),f=i(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),p=i(/\((?:[^()]|<>)*\)/.source,2),h=/@?\b[A-Za-z_]\w*\b/.source,y=r(/<<0>>(?:\s*<<1>>)?/.source,[h,f]),T=r(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[d,y]),b=/\[\s*(?:,\s*)*\]/.source,g=r(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[T,b]),m=r(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[f,p,b]),v=r(/\(<<0>>+(?:,<<0>>+)+\)/.source,[m]),_=r(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[v,T,b]),E={keyword:u,punctuation:/[<>()?,.:[\]]/},R=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,C=/"(?:\\.|[^\\"\r\n])*"/.source,N=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;n.languages.csharp=n.languages.extend("clike",{string:[{pattern:a(/(^|[^$\\])<<0>>/.source,[N]),lookbehind:!0,greedy:!0},{pattern:a(/(^|[^@$\\])<<0>>/.source,[C]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:a(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[T]),lookbehind:!0,inside:E},{pattern:a(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[h,_]),lookbehind:!0,inside:E},{pattern:a(/(\busing\s+)<<0>>(?=\s*=)/.source,[h]),lookbehind:!0},{pattern:a(/(\b<<0>>\s+)<<1>>/.source,[l,y]),lookbehind:!0,inside:E},{pattern:a(/(\bcatch\s*\(\s*)<<0>>/.source,[T]),lookbehind:!0,inside:E},{pattern:a(/(\bwhere\s+)<<0>>/.source,[h]),lookbehind:!0},{pattern:a(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[g]),lookbehind:!0,inside:E},{pattern:a(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[_,c,h]),inside:E}],keyword:u,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),n.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),n.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:a(/([(,]\s*)<<0>>(?=\s*:)/.source,[h]),lookbehind:!0,alias:"punctuation"}}),n.languages.insertBefore("csharp","class-name",{namespace:{pattern:a(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:a(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[p]),lookbehind:!0,alias:"class-name",inside:E},"return-type":{pattern:a(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[_,T]),inside:E,alias:"class-name"},"constructor-invocation":{pattern:a(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[_]),lookbehind:!0,inside:E,alias:"class-name"},"generic-method":{pattern:a(/<<0>>\s*<<1>>(?=\s*\()/.source,[h,f]),inside:{function:a(/^<<0>>/.source,[h]),generic:{pattern:RegExp(f),alias:"class-name",inside:E}}},"type-list":{pattern:a(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[l,y,h,_,u.source,p,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:a(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[y,p]),lookbehind:!0,greedy:!0,inside:n.languages.csharp},keyword:u,"class-name":{pattern:RegExp(_),greedy:!0,inside:E},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var k=C+"|"+R,I=r(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[k]),D=i(r(/[^"'/()]|<<0>>|\(<>*\)/.source,[I]),2),q=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,$=r(/<<0>>(?:\s*\(<<1>>*\))?/.source,[T,D]);n.languages.insertBefore("csharp","class-name",{attribute:{pattern:a(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[q,$]),lookbehind:!0,greedy:!0,inside:{target:{pattern:a(/^<<0>>(?=\s*:)/.source,[q]),alias:"keyword"},"attribute-arguments":{pattern:a(/\(<<0>>*\)/.source,[D]),inside:n.languages.csharp},"class-name":{pattern:RegExp(T),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var z=/:[^}\r\n]+/.source,H=i(r(/[^"'/()]|<<0>>|\(<>*\)/.source,[I]),2),Y=r(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[H,z]),x=i(r(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[k]),2),M=r(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[x,z]);function S(P,G){return{interpolation:{pattern:a(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[P]),lookbehind:!0,inside:{"format-string":{pattern:a(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[G,z]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:n.languages.csharp}}},string:/[\s\S]+/}}n.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:a(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[Y]),lookbehind:!0,greedy:!0,inside:S(Y,H)},{pattern:a(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[M]),lookbehind:!0,greedy:!0,inside:S(M,x)}],char:{pattern:RegExp(R),greedy:!0}}),n.languages.dotnet=n.languages.cs=n.languages.csharp})(t)}return cl}var dl,Zy;function J$(){if(Zy)return dl;Zy=1;var e=Xo();dl=t,t.displayName="aspnet",t.aliases=[];function t(n){n.register(e),n.languages.aspnet=n.languages.extend("markup",{"page-directive":{pattern:/<%\s*@.*%>/,alias:"tag",inside:{"page-directive":{pattern:/<%\s*@\s*(?:Assembly|Control|Implements|Import|Master(?:Type)?|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/i,alias:"tag"},rest:n.languages.markup.tag.inside}},directive:{pattern:/<%.*%>/,alias:"tag",inside:{directive:{pattern:/<%\s*?[$=%#:]{0,2}|%>/,alias:"tag"},rest:n.languages.csharp}}}),n.languages.aspnet.tag.pattern=/<(?!%)\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/,n.languages.insertBefore("inside","punctuation",{directive:n.languages.aspnet.directive},n.languages.aspnet.tag.inside["attr-value"]),n.languages.insertBefore("aspnet","comment",{"asp-comment":{pattern:/<%--[\s\S]*?--%>/,alias:["asp","comment"]}}),n.languages.insertBefore("aspnet",n.languages.javascript?"script":"tag",{"asp-script":{pattern:/(]*>)[\s\S]*?(?=<\/script>)/i,lookbehind:!0,alias:["asp","script"],inside:n.languages.csharp||{}}})}return dl}var pl,Qy;function ez(){if(Qy)return pl;Qy=1,pl=e,e.displayName="autohotkey",e.aliases=[];function e(t){t.languages.autohotkey={comment:[{pattern:/(^|\s);.*/,lookbehind:!0},{pattern:/(^[\t ]*)\/\*(?:[\r\n](?![ \t]*\*\/)|[^\r\n])*(?:[\r\n][ \t]*\*\/)?/m,lookbehind:!0,greedy:!0}],tag:{pattern:/^([ \t]*)[^\s,`":]+(?=:[ \t]*$)/m,lookbehind:!0},string:/"(?:[^"\n\r]|"")*"/,variable:/%\w+%/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/\?|\/\/?=?|:=|\|[=|]?|&[=&]?|\+[=+]?|-[=-]?|\*[=*]?|<(?:<=?|>|=)?|>>?=?|[.^!=~]=?|\b(?:AND|NOT|OR)\b/,boolean:/\b(?:false|true)\b/,selector:/\b(?:AutoTrim|BlockInput|Break|Click|ClipWait|Continue|Control|ControlClick|ControlFocus|ControlGet|ControlGetFocus|ControlGetPos|ControlGetText|ControlMove|ControlSend|ControlSendRaw|ControlSetText|CoordMode|Critical|DetectHiddenText|DetectHiddenWindows|Drive|DriveGet|DriveSpaceFree|EnvAdd|EnvDiv|EnvGet|EnvMult|EnvSet|EnvSub|EnvUpdate|Exit|ExitApp|FileAppend|FileCopy|FileCopyDir|FileCreateDir|FileCreateShortcut|FileDelete|FileEncoding|FileGetAttrib|FileGetShortcut|FileGetSize|FileGetTime|FileGetVersion|FileInstall|FileMove|FileMoveDir|FileRead|FileReadLine|FileRecycle|FileRecycleEmpty|FileRemoveDir|FileSelectFile|FileSelectFolder|FileSetAttrib|FileSetTime|FormatTime|GetKeyState|Gosub|Goto|GroupActivate|GroupAdd|GroupClose|GroupDeactivate|Gui|GuiControl|GuiControlGet|Hotkey|ImageSearch|IniDelete|IniRead|IniWrite|Input|InputBox|KeyWait|ListHotkeys|ListLines|ListVars|Loop|Menu|MouseClick|MouseClickDrag|MouseGetPos|MouseMove|MsgBox|OnExit|OutputDebug|Pause|PixelGetColor|PixelSearch|PostMessage|Process|Progress|Random|RegDelete|RegRead|RegWrite|Reload|Repeat|Return|Run|RunAs|RunWait|Send|SendEvent|SendInput|SendMessage|SendMode|SendPlay|SendRaw|SetBatchLines|SetCapslockState|SetControlDelay|SetDefaultMouseSpeed|SetEnv|SetFormat|SetKeyDelay|SetMouseDelay|SetNumlockState|SetRegView|SetScrollLockState|SetStoreCapslockMode|SetTimer|SetTitleMatchMode|SetWinDelay|SetWorkingDir|Shutdown|Sleep|Sort|SoundBeep|SoundGet|SoundGetWaveVolume|SoundPlay|SoundSet|SoundSetWaveVolume|SplashImage|SplashTextOff|SplashTextOn|SplitPath|StatusBarGetText|StatusBarWait|StringCaseSense|StringGetPos|StringLeft|StringLen|StringLower|StringMid|StringReplace|StringRight|StringSplit|StringTrimLeft|StringTrimRight|StringUpper|Suspend|SysGet|Thread|ToolTip|Transform|TrayTip|URLDownloadToFile|WinActivate|WinActivateBottom|WinClose|WinGet|WinGetActiveStats|WinGetActiveTitle|WinGetClass|WinGetPos|WinGetText|WinGetTitle|WinHide|WinKill|WinMaximize|WinMenuSelectItem|WinMinimize|WinMinimizeAll|WinMinimizeAllUndo|WinMove|WinRestore|WinSet|WinSetTitle|WinShow|WinWait|WinWaitActive|WinWaitClose|WinWaitNotActive)\b/i,constant:/\b(?:a_ahkpath|a_ahkversion|a_appdata|a_appdatacommon|a_autotrim|a_batchlines|a_caretx|a_carety|a_computername|a_controldelay|a_cursor|a_dd|a_ddd|a_dddd|a_defaultmousespeed|a_desktop|a_desktopcommon|a_detecthiddentext|a_detecthiddenwindows|a_endchar|a_eventinfo|a_exitreason|a_fileencoding|a_formatfloat|a_formatinteger|a_gui|a_guicontrol|a_guicontrolevent|a_guievent|a_guiheight|a_guiwidth|a_guix|a_guiy|a_hour|a_iconfile|a_iconhidden|a_iconnumber|a_icontip|a_index|a_ipaddress1|a_ipaddress2|a_ipaddress3|a_ipaddress4|a_is64bitos|a_isadmin|a_iscompiled|a_iscritical|a_ispaused|a_issuspended|a_isunicode|a_keydelay|a_language|a_lasterror|a_linefile|a_linenumber|a_loopfield|a_loopfileattrib|a_loopfiledir|a_loopfileext|a_loopfilefullpath|a_loopfilelongpath|a_loopfilename|a_loopfileshortname|a_loopfileshortpath|a_loopfilesize|a_loopfilesizekb|a_loopfilesizemb|a_loopfiletimeaccessed|a_loopfiletimecreated|a_loopfiletimemodified|a_loopreadline|a_loopregkey|a_loopregname|a_loopregsubkey|a_loopregtimemodified|a_loopregtype|a_mday|a_min|a_mm|a_mmm|a_mmmm|a_mon|a_mousedelay|a_msec|a_mydocuments|a_now|a_nowutc|a_numbatchlines|a_ostype|a_osversion|a_priorhotkey|a_priorkey|a_programfiles|a_programs|a_programscommon|a_ptrsize|a_regview|a_screendpi|a_screenheight|a_screenwidth|a_scriptdir|a_scriptfullpath|a_scripthwnd|a_scriptname|a_sec|a_space|a_startmenu|a_startmenucommon|a_startup|a_startupcommon|a_stringcasesense|a_tab|a_temp|a_thisfunc|a_thishotkey|a_thislabel|a_thismenu|a_thismenuitem|a_thismenuitempos|a_tickcount|a_timeidle|a_timeidlephysical|a_timesincepriorhotkey|a_timesincethishotkey|a_titlematchmode|a_titlematchmodespeed|a_username|a_wday|a_windelay|a_windir|a_workingdir|a_yday|a_year|a_yweek|a_yyyy|clipboard|clipboardall|comspec|errorlevel|programfiles)\b/i,builtin:/\b(?:abs|acos|asc|asin|atan|ceil|chr|class|comobjactive|comobjarray|comobjconnect|comobjcreate|comobjerror|comobjflags|comobjget|comobjquery|comobjtype|comobjvalue|cos|dllcall|exp|fileexist|Fileopen|floor|format|il_add|il_create|il_destroy|instr|isfunc|islabel|IsObject|ln|log|ltrim|lv_add|lv_delete|lv_deletecol|lv_getcount|lv_getnext|lv_gettext|lv_insert|lv_insertcol|lv_modify|lv_modifycol|lv_setimagelist|mod|numget|numput|onmessage|regexmatch|regexreplace|registercallback|round|rtrim|sb_seticon|sb_setparts|sb_settext|sin|sqrt|strlen|strreplace|strsplit|substr|tan|tv_add|tv_delete|tv_get|tv_getchild|tv_getcount|tv_getnext|tv_getparent|tv_getprev|tv_getselection|tv_gettext|tv_modify|varsetcapacity|winactive|winexist|__Call|__Get|__New|__Set)\b/i,symbol:/\b(?:alt|altdown|altup|appskey|backspace|browser_back|browser_favorites|browser_forward|browser_home|browser_refresh|browser_search|browser_stop|bs|capslock|ctrl|ctrlbreak|ctrldown|ctrlup|del|delete|down|end|enter|esc|escape|f1|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f2|f20|f21|f22|f23|f24|f3|f4|f5|f6|f7|f8|f9|home|ins|insert|joy1|joy10|joy11|joy12|joy13|joy14|joy15|joy16|joy17|joy18|joy19|joy2|joy20|joy21|joy22|joy23|joy24|joy25|joy26|joy27|joy28|joy29|joy3|joy30|joy31|joy32|joy4|joy5|joy6|joy7|joy8|joy9|joyaxes|joybuttons|joyinfo|joyname|joypov|joyr|joyu|joyv|joyx|joyy|joyz|lalt|launch_app1|launch_app2|launch_mail|launch_media|lbutton|lcontrol|lctrl|left|lshift|lwin|lwindown|lwinup|mbutton|media_next|media_play_pause|media_prev|media_stop|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadadd|numpadclear|numpaddel|numpaddiv|numpaddot|numpaddown|numpadend|numpadenter|numpadhome|numpadins|numpadleft|numpadmult|numpadpgdn|numpadpgup|numpadright|numpadsub|numpadup|pgdn|pgup|printscreen|ralt|rbutton|rcontrol|rctrl|right|rshift|rwin|rwindown|rwinup|scrolllock|shift|shiftdown|shiftup|space|tab|up|volume_down|volume_mute|volume_up|wheeldown|wheelleft|wheelright|wheelup|xbutton1|xbutton2)\b/i,important:/#\b(?:AllowSameLineComments|ClipboardTimeout|CommentFlag|DerefChar|ErrorStdOut|EscapeChar|HotkeyInterval|HotkeyModifierTimeout|Hotstring|If|IfTimeout|IfWinActive|IfWinExist|IfWinNotActive|IfWinNotExist|Include|IncludeAgain|InputLevel|InstallKeybdHook|InstallMouseHook|KeyHistory|MaxHotkeysPerInterval|MaxMem|MaxThreads|MaxThreadsBuffer|MaxThreadsPerHotkey|MenuMaskKey|NoEnv|NoTrayIcon|Persistent|SingleInstance|UseHook|Warn|WinActivateForce)\b/i,keyword:/\b(?:Abort|AboveNormal|Add|ahk_class|ahk_exe|ahk_group|ahk_id|ahk_pid|All|Alnum|Alpha|AltSubmit|AltTab|AltTabAndMenu|AltTabMenu|AltTabMenuDismiss|AlwaysOnTop|AutoSize|Background|BackgroundTrans|BelowNormal|between|BitAnd|BitNot|BitOr|BitShiftLeft|BitShiftRight|BitXOr|Bold|Border|Button|ByRef|Catch|Checkbox|Checked|CheckedGray|Choose|ChooseString|Close|Color|ComboBox|Contains|ControlList|Count|Date|DateTime|Days|DDL|Default|DeleteAll|Delimiter|Deref|Destroy|Digit|Disable|Disabled|DropDownList|Edit|Eject|Else|Enable|Enabled|Error|Exist|Expand|ExStyle|FileSystem|Finally|First|Flash|Float|FloatFast|Focus|Font|for|global|Grid|Group|GroupBox|GuiClose|GuiContextMenu|GuiDropFiles|GuiEscape|GuiSize|Hdr|Hidden|Hide|High|HKCC|HKCR|HKCU|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_LOCAL_MACHINE|HKEY_USERS|HKLM|HKU|Hours|HScroll|Icon|IconSmall|ID|IDLast|If|IfEqual|IfExist|IfGreater|IfGreaterOrEqual|IfInString|IfLess|IfLessOrEqual|IfMsgBox|IfNotEqual|IfNotExist|IfNotInString|IfWinActive|IfWinExist|IfWinNotActive|IfWinNotExist|Ignore|ImageList|in|Integer|IntegerFast|Interrupt|is|italic|Join|Label|LastFound|LastFoundExist|Limit|Lines|List|ListBox|ListView|local|Lock|Logoff|Low|Lower|Lowercase|MainWindow|Margin|Maximize|MaximizeBox|MaxSize|Minimize|MinimizeBox|MinMax|MinSize|Minutes|MonthCal|Mouse|Move|Multi|NA|No|NoActivate|NoDefault|NoHide|NoIcon|NoMainWindow|norm|Normal|NoSort|NoSortHdr|NoStandard|Not|NoTab|NoTimers|Number|Off|Ok|On|OwnDialogs|Owner|Parse|Password|Picture|Pixel|Pos|Pow|Priority|ProcessName|Radio|Range|Read|ReadOnly|Realtime|Redraw|Region|REG_BINARY|REG_DWORD|REG_EXPAND_SZ|REG_MULTI_SZ|REG_SZ|Relative|Rename|Report|Resize|Restore|Retry|RGB|Screen|Seconds|Section|Serial|SetLabel|ShiftAltTab|Show|Single|Slider|SortDesc|Standard|static|Status|StatusBar|StatusCD|strike|Style|Submit|SysMenu|Tab2|TabStop|Text|Theme|Throw|Tile|ToggleCheck|ToggleEnable|ToolWindow|Top|Topmost|TransColor|Transparent|Tray|TreeView|Try|TryAgain|Type|UnCheck|underline|Unicode|Unlock|Until|UpDown|Upper|Uppercase|UseErrorLevel|Vis|VisFirst|Visible|VScroll|Wait|WaitClose|WantCtrlA|WantF2|WantReturn|While|Wrap|Xdigit|xm|xp|xs|Yes|ym|yp|ys)\b/i,function:/[^(); \t,\n+*\-=?>:\\\/<&%\[\]]+(?=\()/,punctuation:/[{}[\]():,]/}}return pl}var fl,Jy;function tz(){if(Jy)return fl;Jy=1,fl=e,e.displayName="autoit",e.aliases=[];function e(t){t.languages.autoit={comment:[/;.*/,{pattern:/(^[\t ]*)#(?:comments-start|cs)[\s\S]*?^[ \t]*#(?:ce|comments-end)/m,lookbehind:!0}],url:{pattern:/(^[\t ]*#include\s+)(?:<[^\r\n>]+>|"[^\r\n"]+")/m,lookbehind:!0},string:{pattern:/(["'])(?:\1\1|(?!\1)[^\r\n])*\1/,greedy:!0,inside:{variable:/([%$@])\w+\1/}},directive:{pattern:/(^[\t ]*)#[\w-]+/m,lookbehind:!0,alias:"keyword"},function:/\b\w+(?=\()/,variable:/[$@]\w+/,keyword:/\b(?:Case|Const|Continue(?:Case|Loop)|Default|Dim|Do|Else(?:If)?|End(?:Func|If|Select|Switch|With)|Enum|Exit(?:Loop)?|For|Func|Global|If|In|Local|Next|Null|ReDim|Select|Static|Step|Switch|Then|To|Until|Volatile|WEnd|While|With)\b/i,number:/\b(?:0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/i,boolean:/\b(?:False|True)\b/i,operator:/<[=>]?|[-+*\/=&>]=?|[?^]|\b(?:And|Not|Or)\b/i,punctuation:/[\[\]().,:]/}}return fl}var gl,eE;function nz(){if(eE)return gl;eE=1,gl=e,e.displayName="avisynth",e.aliases=["avs"];function e(t){(function(n){function r(d,c){return d.replace(/<<(\d+)>>/g,function(f,p){return c[+p]})}function a(d,c,f){return RegExp(r(d,c),f)}var i=/bool|clip|float|int|string|val/.source,o=[/is(?:bool|clip|float|int|string)|defined|(?:(?:internal)?function|var)?exists?/.source,/apply|assert|default|eval|import|nop|select|undefined/.source,/opt_(?:allowfloataudio|avipadscanlines|dwchannelmask|enable_(?:b64a|planartopackedrgb|v210|y3_10_10|y3_10_16)|usewaveextensible|vdubplanarhack)|set(?:cachemode|maxcpu|memorymax|planarlegacyalignment|workingdir)/.source,/hex(?:value)?|value/.source,/abs|ceil|continued(?:denominator|numerator)?|exp|floor|fmod|frac|log(?:10)?|max|min|muldiv|pi|pow|rand|round|sign|spline|sqrt/.source,/a?sinh?|a?cosh?|a?tan[2h]?/.source,/(?:bit(?:and|not|x?or|[lr]?shift[aslu]?|sh[lr]|sa[lr]|[lr]rotatel?|ro[rl]|te?st|set(?:count)?|cl(?:ea)?r|ch(?:an)?ge?))/.source,/average(?:[bgr]|chroma[uv]|luma)|(?:[rgb]|chroma[uv]|luma|rgb|[yuv](?=difference(?:fromprevious|tonext)))difference(?:fromprevious|tonext)?|[yuvrgb]plane(?:median|min|max|minmaxdifference)/.source,/getprocessinfo|logmsg|script(?:dir(?:utf8)?|file(?:utf8)?|name(?:utf8)?)|setlogparams/.source,/chr|(?:fill|find|left|mid|replace|rev|right)str|format|[lu]case|ord|str(?:cmpi?|fromutf8|len|toutf8)|time|trim(?:all|left|right)/.source,/isversionorgreater|version(?:number|string)/.source,/buildpixeltype|colorspacenametopixeltype/.source,/addautoloaddir|on(?:cpu|cuda)|prefetch|setfiltermtmode/.source].join("|"),s=[/has(?:audio|video)/.source,/height|width/.source,/frame(?:count|rate)|framerate(?:denominator|numerator)/.source,/getparity|is(?:field|frame)based/.source,/bitspercomponent|componentsize|hasalpha|is(?:planar(?:rgba?)?|interleaved|rgb(?:24|32|48|64)?|y(?:8|u(?:va?|y2))?|yv(?:12|16|24|411)|420|422|444|packedrgb)|numcomponents|pixeltype/.source,/audio(?:bits|channels|duration|length(?:[fs]|hi|lo)?|rate)|isaudio(?:float|int)/.source].join("|"),l=[/avi(?:file)?source|directshowsource|image(?:reader|source|sourceanim)|opendmlsource|segmented(?:avisource|directshowsource)|wavsource/.source,/coloryuv|convertbacktoyuy2|convertto(?:RGB(?:24|32|48|64)|(?:planar)?RGBA?|Y8?|YV(?:12|16|24|411)|YUVA?(?:411|420|422|444)|YUY2)|fixluminance|gr[ae]yscale|invert|levels|limiter|mergea?rgb|merge(?:chroma|luma)|rgbadjust|show(?:alpha|blue|green|red)|swapuv|tweak|[uv]toy8?|ytouv/.source,/(?:colorkey|reset)mask|layer|mask(?:hs)?|merge|overlay|subtract/.source,/addborders|(?:bicubic|bilinear|blackman|gauss|lanczos4|lanczos|point|sinc|spline(?:16|36|64))resize|crop(?:bottom)?|flip(?:horizontal|vertical)|(?:horizontal|vertical)?reduceby2|letterbox|skewrows|turn(?:180|left|right)/.source,/blur|fixbrokenchromaupsampling|generalconvolution|(?:spatial|temporal)soften|sharpen/.source,/trim|(?:un)?alignedsplice|(?:assume|assumescaled|change|convert)FPS|(?:delete|duplicate)frame|dissolve|fade(?:in|io|out)[02]?|freezeframe|interleave|loop|reverse|select(?:even|odd|(?:range)?every)/.source,/assume[bt]ff|assume(?:field|frame)based|bob|complementparity|doubleweave|peculiarblend|pulldown|separate(?:columns|fields|rows)|swapfields|weave(?:columns|rows)?/.source,/amplify(?:db)?|assumesamplerate|audiodub(?:ex)?|audiotrim|convertaudioto(?:(?:8|16|24|32)bit|float)|converttomono|delayaudio|ensurevbrmp3sync|get(?:left|right)?channel|kill(?:audio|video)|mergechannels|mixaudio|monotostereo|normalize|resampleaudio|ssrc|supereq|timestretch/.source,/animate|applyrange|conditional(?:filter|reader|select)|frameevaluate|scriptclip|tcp(?:server|source)|writefile(?:end|if|start)?/.source,/imagewriter/.source,/blackness|blankclip|colorbars(?:hd)?|compare|dumpfiltergraph|echo|histogram|info|messageclip|preroll|setgraphanalysis|show(?:framenumber|smpte|time)|showfiveversions|stack(?:horizontal|vertical)|subtitle|tone|version/.source].join("|"),u=[o,s,l].join("|");n.languages.avisynth={comment:[{pattern:/(^|[^\\])\[\*(?:[^\[*]|\[(?!\*)|\*(?!\])|\[\*(?:[^\[*]|\[(?!\*)|\*(?!\]))*\*\])*\*\]/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0,greedy:!0}],argument:{pattern:a(/\b(?:<<0>>)\s+("?)\w+\1/.source,[i],"i"),inside:{keyword:/^\w+/}},"argument-label":{pattern:/([,(][\s\\]*)\w+\s*=(?!=)/,lookbehind:!0,inside:{"argument-name":{pattern:/^\w+/,alias:"punctuation"},punctuation:/=$/}},string:[{pattern:/"""[\s\S]*?"""/,greedy:!0},{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0,inside:{constant:{pattern:/\b(?:DEFAULT_MT_MODE|(?:MAINSCRIPT|PROGRAM|SCRIPT)DIR|(?:MACHINE|USER)_(?:CLASSIC|PLUS)_PLUGINS)\b/}}}],variable:/\b(?:last)\b/i,boolean:/\b(?:false|no|true|yes)\b/i,keyword:/\b(?:catch|else|for|function|global|if|return|try|while|__END__)\b/i,constant:/\bMT_(?:MULTI_INSTANCE|NICE_FILTER|SERIALIZED|SPECIAL_MT)\b/,"builtin-function":{pattern:a(/\b(?:<<0>>)\b/.source,[u],"i"),alias:"function"},"type-cast":{pattern:a(/\b(?:<<0>>)(?=\s*\()/.source,[i],"i"),alias:"keyword"},function:{pattern:/\b[a-z_]\w*(?=\s*\()|(\.)[a-z_]\w*\b/i,lookbehind:!0},"line-continuation":{pattern:/(^[ \t]*)\\|\\(?=[ \t]*$)/m,lookbehind:!0,alias:"punctuation"},number:/\B\$(?:[\da-f]{6}|[\da-f]{8})\b|(?:(?:\b|\B-)\d+(?:\.\d*)?\b|\B\.\d+\b)/i,operator:/\+\+?|[!=<>]=?|&&|\|\||[?:*/%-]/,punctuation:/[{}\[\]();,.]/},n.languages.avs=n.languages.avisynth})(t)}return gl}var ml,tE;function rz(){if(tE)return ml;tE=1,ml=e,e.displayName="avroIdl",e.aliases=[];function e(t){t.languages["avro-idl"]={comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\//,greedy:!0},string:{pattern:/(^|[^\\])"(?:[^\r\n"\\]|\\.)*"/,lookbehind:!0,greedy:!0},annotation:{pattern:/@(?:[$\w.-]|`[^\r\n`]+`)+/,greedy:!0,alias:"function"},"function-identifier":{pattern:/`[^\r\n`]+`(?=\s*\()/,greedy:!0,alias:"function"},identifier:{pattern:/`[^\r\n`]+`/,greedy:!0},"class-name":{pattern:/(\b(?:enum|error|protocol|record|throws)\b\s+)[$\w]+/,lookbehind:!0,greedy:!0},keyword:/\b(?:array|boolean|bytes|date|decimal|double|enum|error|false|fixed|float|idl|import|int|local_timestamp_ms|long|map|null|oneway|protocol|record|schema|string|throws|time_ms|timestamp_ms|true|union|uuid|void)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:[{pattern:/(^|[^\w.])-?(?:(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|0x(?:[a-f0-9]+(?:\.[a-f0-9]*)?|\.[a-f0-9]+)(?:p[+-]?\d+)?)[dfl]?(?![\w.])/i,lookbehind:!0},/-?\b(?:Infinity|NaN)\b/],operator:/=/,punctuation:/[()\[\]{}<>.:,;-]/},t.languages.avdl=t.languages["avro-idl"]}return ml}var hl,nE;function GR(){if(nE)return hl;nE=1,hl=e,e.displayName="bash",e.aliases=["shell"];function e(t){(function(n){var r="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",a={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},i={bash:a,environment:{pattern:RegExp("\\$"+r),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+r),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};n.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+r),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:i},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:a}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:i},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:i.entity}}],environment:{pattern:RegExp("\\$?"+r),alias:"constant"},variable:i.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},a.inside=n.languages.bash;for(var o=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],s=i.variable[1].inside,l=0;l?^\w +\-.])*"/,greedy:!0},number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?/i,keyword:/\b(?:AS|BEEP|BLOAD|BSAVE|CALL(?: ABSOLUTE)?|CASE|CHAIN|CHDIR|CLEAR|CLOSE|CLS|COM|COMMON|CONST|DATA|DECLARE|DEF(?: FN| SEG|DBL|INT|LNG|SNG|STR)|DIM|DO|DOUBLE|ELSE|ELSEIF|END|ENVIRON|ERASE|ERROR|EXIT|FIELD|FILES|FOR|FUNCTION|GET|GOSUB|GOTO|IF|INPUT|INTEGER|IOCTL|KEY|KILL|LINE INPUT|LOCATE|LOCK|LONG|LOOP|LSET|MKDIR|NAME|NEXT|OFF|ON(?: COM| ERROR| KEY| TIMER)?|OPEN|OPTION BASE|OUT|POKE|PUT|READ|REDIM|REM|RESTORE|RESUME|RETURN|RMDIR|RSET|RUN|SELECT CASE|SHARED|SHELL|SINGLE|SLEEP|STATIC|STEP|STOP|STRING|SUB|SWAP|SYSTEM|THEN|TIMER|TO|TROFF|TRON|TYPE|UNLOCK|UNTIL|USING|VIEW PRINT|WAIT|WEND|WHILE|WRITE)(?:\$|\b)/i,function:/\b(?:ABS|ACCESS|ACOS|ANGLE|AREA|ARITHMETIC|ARRAY|ASIN|ASK|AT|ATN|BASE|BEGIN|BREAK|CAUSE|CEIL|CHR|CLIP|COLLATE|COLOR|CON|COS|COSH|COT|CSC|DATE|DATUM|DEBUG|DECIMAL|DEF|DEG|DEGREES|DELETE|DET|DEVICE|DISPLAY|DOT|ELAPSED|EPS|ERASABLE|EXLINE|EXP|EXTERNAL|EXTYPE|FILETYPE|FIXED|FP|GO|GRAPH|HANDLER|IDN|IMAGE|IN|INT|INTERNAL|IP|IS|KEYED|LBOUND|LCASE|LEFT|LEN|LENGTH|LET|LINE|LINES|LOG|LOG10|LOG2|LTRIM|MARGIN|MAT|MAX|MAXNUM|MID|MIN|MISSING|MOD|NATIVE|NUL|NUMERIC|OF|OPTION|ORD|ORGANIZATION|OUTIN|OUTPUT|PI|POINT|POINTER|POINTS|POS|PRINT|PROGRAM|PROMPT|RAD|RADIANS|RANDOMIZE|RECORD|RECSIZE|RECTYPE|RELATIVE|REMAINDER|REPEAT|REST|RETRY|REWRITE|RIGHT|RND|ROUND|RTRIM|SAME|SEC|SELECT|SEQUENTIAL|SET|SETTER|SGN|SIN|SINH|SIZE|SKIP|SQR|STANDARD|STATUS|STR|STREAM|STYLE|TAB|TAN|TANH|TEMPLATE|TEXT|THERE|TIME|TIMEOUT|TRACE|TRANSFORM|TRUNCATE|UBOUND|UCASE|USE|VAL|VARIABLE|VIEWPORT|WHEN|WINDOW|WITH|ZER|ZONEWIDTH)(?:\$|\b)/i,operator:/<[=>]?|>=?|[+\-*\/^=&]|\b(?:AND|EQV|IMP|NOT|OR|XOR)\b/i,punctuation:/[,;:()]/}}return bl}var yl,aE;function az(){if(aE)return yl;aE=1,yl=e,e.displayName="batch",e.aliases=[];function e(t){(function(n){var r=/%%?[~:\w]+%?|!\S+!/,a={pattern:/\/[a-z?]+(?=[ :]|$):?|-[a-z]\b|--[a-z-]+\b/im,alias:"attr-name",inside:{punctuation:/:/}},i=/"(?:[\\"]"|[^"])*"(?!")/,o=/(?:\b|-)\d+\b/;n.languages.batch={comment:[/^::.*/m,{pattern:/((?:^|[&(])[ \t]*)rem\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0}],label:{pattern:/^:.*/m,alias:"property"},command:[{pattern:/((?:^|[&(])[ \t]*)for(?: \/[a-z?](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* \S+ in \([^)]+\) do/im,lookbehind:!0,inside:{keyword:/\b(?:do|in)\b|^for\b/i,string:i,parameter:a,variable:r,number:o,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*)if(?: \/[a-z?](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* (?:not )?(?:cmdextversion \d+|defined \w+|errorlevel \d+|exist \S+|(?:"[^"]*"|(?!")(?:(?!==)\S)+)?(?:==| (?:equ|geq|gtr|leq|lss|neq) )(?:"[^"]*"|[^\s"]\S*))/im,lookbehind:!0,inside:{keyword:/\b(?:cmdextversion|defined|errorlevel|exist|not)\b|^if\b/i,string:i,parameter:a,variable:r,number:o,operator:/\^|==|\b(?:equ|geq|gtr|leq|lss|neq)\b/i}},{pattern:/((?:^|[&()])[ \t]*)else\b/im,lookbehind:!0,inside:{keyword:/^else\b/i}},{pattern:/((?:^|[&(])[ \t]*)set(?: \/[a-z](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* (?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^set\b/i,string:i,parameter:a,variable:[r,/\w+(?=(?:[*\/%+\-&^|]|<<|>>)?=)/],number:o,operator:/[*\/%+\-&^|]=?|<<=?|>>=?|[!~_=]/,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*@?)\w+\b(?:"(?:[\\"]"|[^"])*"(?!")|[^"^&)\r\n]|\^(?:\r\n|[\s\S]))*/m,lookbehind:!0,inside:{keyword:/^\w+\b/,string:i,parameter:a,label:{pattern:/(^\s*):\S+/m,lookbehind:!0,alias:"property"},variable:r,number:o,operator:/\^/}}],operator:/[&@]/,punctuation:/[()']/}})(t)}return yl}var El,iE;function iz(){if(iE)return El;iE=1,El=e,e.displayName="bbcode",e.aliases=["shortcode"];function e(t){t.languages.bbcode={tag:{pattern:/\[\/?[^\s=\]]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'"\]=]+))?(?:\s+[^\s=\]]+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'"\]=]+))*\s*\]/,inside:{tag:{pattern:/^\[\/?[^\s=\]]+/,inside:{punctuation:/^\[\/?/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'"\]=]+)/,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\]/,"attr-name":/[^\s=\]]+/}}},t.languages.shortcode=t.languages.bbcode}return El}var Sl,oE;function oz(){if(oE)return Sl;oE=1,Sl=e,e.displayName="bicep",e.aliases=[];function e(t){t.languages.bicep={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],property:[{pattern:/([\r\n][ \t]*)[a-z_]\w*(?=[ \t]*:)/i,lookbehind:!0},{pattern:/([\r\n][ \t]*)'(?:\\.|\$(?!\{)|[^'\\\r\n$])*'(?=[ \t]*:)/,lookbehind:!0,greedy:!0}],string:[{pattern:/'''[^'][\s\S]*?'''/,greedy:!0},{pattern:/(^|[^\\'])'(?:\\.|\$(?!\{)|[^'\\\r\n$])*'/,lookbehind:!0,greedy:!0}],"interpolated-string":{pattern:/(^|[^\\'])'(?:\\.|\$(?:(?!\{)|\{[^{}\r\n]*\})|[^'\\\r\n$])*'/,lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/\$\{[^{}\r\n]*\}/,inside:{expression:{pattern:/(^\$\{)[\s\S]+(?=\}$)/,lookbehind:!0},punctuation:/^\$\{|\}$/}},string:/[\s\S]+/}},datatype:{pattern:/(\b(?:output|param)\b[ \t]+\w+[ \t]+)\w+\b/,lookbehind:!0,alias:"class-name"},boolean:/\b(?:false|true)\b/,keyword:/\b(?:existing|for|if|in|module|null|output|param|resource|targetScope|var)\b/,decorator:/@\w+\b/,function:/\b[a-z_]\w*(?=[ \t]*\()/i,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?/i,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/,punctuation:/[{}[\];(),.:]/},t.languages.bicep["interpolated-string"].inside.interpolation.inside.expression.inside=t.languages.bicep}return Sl}var vl,sE;function sz(){if(sE)return vl;sE=1,vl=e,e.displayName="birb",e.aliases=[];function e(t){t.languages.birb=t.languages.extend("clike",{string:{pattern:/r?("|')(?:\\.|(?!\1)[^\\])*\1/,greedy:!0},"class-name":[/\b[A-Z](?:[\d_]*[a-zA-Z]\w*)?\b/,/\b(?:[A-Z]\w*|(?!(?:var|void)\b)[a-z]\w*)(?=\s+\w+\s*[;,=()])/],keyword:/\b(?:assert|break|case|class|const|default|else|enum|final|follows|for|grab|if|nest|new|next|noSeeb|return|static|switch|throw|var|void|while)\b/,operator:/\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?|:/,variable:/\b[a-z_]\w*\b/}),t.languages.insertBefore("birb","function",{metadata:{pattern:/<\w+>/,greedy:!0,alias:"symbol"}})}return vl}var kl,lE;function lz(){if(lE)return kl;lE=1;var e=tr();kl=t,t.displayName="bison",t.aliases=[];function t(n){n.register(e),n.languages.bison=n.languages.extend("c",{}),n.languages.insertBefore("bison","comment",{bison:{pattern:/^(?:[^%]|%(?!%))*%%[\s\S]*?%%/,inside:{c:{pattern:/%\{[\s\S]*?%\}|\{(?:\{[^}]*\}|[^{}])*\}/,inside:{delimiter:{pattern:/^%?\{|%?\}$/,alias:"punctuation"},"bison-variable":{pattern:/[$@](?:<[^\s>]+>)?[\w$]+/,alias:"variable",inside:{punctuation:/<|>/}},rest:n.languages.c}},comment:n.languages.c.comment,string:n.languages.c.string,property:/\S+(?=:)/,keyword:/%\w+/,number:{pattern:/(^|[^@])\b(?:0x[\da-f]+|\d+)/i,lookbehind:!0},punctuation:/%[%?]|[|:;\[\]<>]/}}})}return kl}var wl,uE;function uz(){if(uE)return wl;uE=1,wl=e,e.displayName="bnf",e.aliases=["rbnf"];function e(t){t.languages.bnf={string:{pattern:/"[^\r\n"]*"|'[^\r\n']*'/},definition:{pattern:/<[^<>\r\n\t]+>(?=\s*::=)/,alias:["rule","keyword"],inside:{punctuation:/^<|>$/}},rule:{pattern:/<[^<>\r\n\t]+>/,inside:{punctuation:/^<|>$/}},operator:/::=|[|()[\]{}*+?]|\.{3}/},t.languages.rbnf=t.languages.bnf}return wl}var _l,cE;function cz(){if(cE)return _l;cE=1,_l=e,e.displayName="brainfuck",e.aliases=[];function e(t){t.languages.brainfuck={pointer:{pattern:/<|>/,alias:"keyword"},increment:{pattern:/\+/,alias:"inserted"},decrement:{pattern:/-/,alias:"deleted"},branching:{pattern:/\[|\]/,alias:"important"},operator:/[.,]/,comment:/\S+/}}return _l}var Tl,dE;function dz(){if(dE)return Tl;dE=1,Tl=e,e.displayName="brightscript",e.aliases=[];function e(t){t.languages.brightscript={comment:/(?:\brem|').*/i,"directive-statement":{pattern:/(^[\t ]*)#(?:const|else(?:[\t ]+if)?|end[\t ]+if|error|if).*/im,lookbehind:!0,alias:"property",inside:{"error-message":{pattern:/(^#error).+/,lookbehind:!0},directive:{pattern:/^#(?:const|else(?:[\t ]+if)?|end[\t ]+if|error|if)/,alias:"keyword"},expression:{pattern:/[\s\S]+/,inside:null}}},property:{pattern:/([\r\n{,][\t ]*)(?:(?!\d)\w+|"(?:[^"\r\n]|"")*"(?!"))(?=[ \t]*:)/,lookbehind:!0,greedy:!0},string:{pattern:/"(?:[^"\r\n]|"")*"(?!")/,greedy:!0},"class-name":{pattern:/(\bAs[\t ]+)\w+/i,lookbehind:!0},keyword:/\b(?:As|Dim|Each|Else|Elseif|End|Exit|For|Function|Goto|If|In|Print|Return|Step|Stop|Sub|Then|To|While)\b/i,boolean:/\b(?:false|true)\b/i,function:/\b(?!\d)\w+(?=[\t ]*\()/,number:/(?:\b\d+(?:\.\d+)?(?:[ed][+-]\d+)?|&h[a-f\d]+)\b[%&!#]?/i,operator:/--|\+\+|>>=?|<<=?|<>|[-+*/\\<>]=?|[:^=?]|\b(?:and|mod|not|or)\b/i,punctuation:/[.,;()[\]{}]/,constant:/\b(?:LINE_NUM)\b/i},t.languages.brightscript["directive-statement"].inside.expression.inside=t.languages.brightscript}return Tl}var Al,pE;function pz(){if(pE)return Al;pE=1,Al=e,e.displayName="bro",e.aliases=[];function e(t){t.languages.bro={comment:{pattern:/(^|[^\\$])#.*/,lookbehind:!0,inside:{italic:/\b(?:FIXME|TODO|XXX)\b/}},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},boolean:/\b[TF]\b/,function:{pattern:/(\b(?:event|function|hook)[ \t]+)\w+(?:::\w+)?/,lookbehind:!0},builtin:/(?:@(?:load(?:-(?:plugin|sigs))?|unload|prefixes|ifn?def|else|(?:end)?if|DIR|FILENAME))|(?:&?(?:add_func|create_expire|default|delete_func|encrypt|error_handler|expire_func|group|log|mergeable|optional|persistent|priority|raw_output|read_expire|redef|rotate_interval|rotate_size|synchronized|type_column|write_expire))/,constant:{pattern:/(\bconst[ \t]+)\w+/i,lookbehind:!0},keyword:/\b(?:add|addr|alarm|any|bool|break|const|continue|count|delete|double|else|enum|event|export|file|for|function|global|hook|if|in|int|interval|local|module|next|of|opaque|pattern|port|print|record|return|schedule|set|string|subnet|table|time|timeout|using|vector|when)\b/,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&|\|\|?|\?|\*|\/|~|\^|%/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,punctuation:/[{}[\];(),.:]/}}return Al}var Rl,fE;function fz(){if(fE)return Rl;fE=1,Rl=e,e.displayName="bsl",e.aliases=[];function e(t){t.languages.bsl={comment:/\/\/.*/,string:[{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},{pattern:/'(?:[^'\r\n\\]|\\.)*'/}],keyword:[{pattern:/(^|[^\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])(?:пока|для|новый|прервать|попытка|исключение|вызватьисключение|иначе|конецпопытки|неопределено|функция|перем|возврат|конецфункции|если|иначеесли|процедура|конецпроцедуры|тогда|знач|экспорт|конецесли|из|каждого|истина|ложь|по|цикл|конеццикла|выполнить)(?![\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])/i,lookbehind:!0},{pattern:/\b(?:break|do|each|else|elseif|enddo|endfunction|endif|endprocedure|endtry|except|execute|export|false|for|function|if|in|new|null|procedure|raise|return|then|to|true|try|undefined|val|var|while)\b/i}],number:{pattern:/(^(?=\d)|[^\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])(?:\d+(?:\.\d*)?|\.\d+)(?:E[+-]?\d+)?/i,lookbehind:!0},operator:[/[<>+\-*/]=?|[%=]/,{pattern:/(^|[^\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])(?:и|или|не)(?![\w\u0400-\u0484\u0487-\u052f\u1d2b\u1d78\u2de0-\u2dff\ua640-\ua69f\ufe2e\ufe2f])/i,lookbehind:!0},{pattern:/\b(?:and|not|or)\b/i}],punctuation:/\(\.|\.\)|[()\[\]:;,.]/,directive:[{pattern:/^([ \t]*)&.*/m,lookbehind:!0,greedy:!0,alias:"important"},{pattern:/^([ \t]*)#.*/gm,lookbehind:!0,greedy:!0,alias:"important"}]},t.languages.oscript=t.languages.bsl}return Rl}var Il,gE;function gz(){if(gE)return Il;gE=1,Il=e,e.displayName="cfscript",e.aliases=[];function e(t){t.languages.cfscript=t.languages.extend("clike",{comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,inside:{annotation:{pattern:/(?:^|[^.])@[\w\.]+/,alias:"punctuation"}}},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],keyword:/\b(?:abstract|break|catch|component|continue|default|do|else|extends|final|finally|for|function|if|in|include|package|private|property|public|remote|required|rethrow|return|static|switch|throw|try|var|while|xml)\b(?!\s*=)/,operator:[/\+\+|--|&&|\|\||::|=>|[!=]==|<=?|>=?|[-+*/%&|^!=<>]=?|\?(?:\.|:)?|[?:]/,/\b(?:and|contains|eq|equal|eqv|gt|gte|imp|is|lt|lte|mod|not|or|xor)\b/],scope:{pattern:/\b(?:application|arguments|cgi|client|cookie|local|session|super|this|variables)\b/,alias:"global"},type:{pattern:/\b(?:any|array|binary|boolean|date|guid|numeric|query|string|struct|uuid|void|xml)\b/,alias:"builtin"}}),t.languages.insertBefore("cfscript","keyword",{"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"}}),delete t.languages.cfscript["class-name"],t.languages.cfc=t.languages.cfscript}return Il}var Cl,mE;function mz(){if(mE)return Cl;mE=1;var e=$m();Cl=t,t.displayName="chaiscript",t.aliases=[];function t(n){n.register(e),n.languages.chaiscript=n.languages.extend("clike",{string:{pattern:/(^|[^\\])'(?:[^'\\]|\\[\s\S])*'/,lookbehind:!0,greedy:!0},"class-name":[{pattern:/(\bclass\s+)\w+/,lookbehind:!0},{pattern:/(\b(?:attr|def)\s+)\w+(?=\s*::)/,lookbehind:!0}],keyword:/\b(?:attr|auto|break|case|catch|class|continue|def|default|else|finally|for|fun|global|if|return|switch|this|try|var|while)\b/,number:[n.languages.cpp.number,/\b(?:Infinity|NaN)\b/],operator:/>>=?|<<=?|\|\||&&|:[:=]?|--|\+\+|[=!<>+\-*/%|&^]=?|[?~]|`[^`\r\n]{1,4}`/}),n.languages.insertBefore("chaiscript","operator",{"parameter-type":{pattern:/([,(]\s*)\w+(?=\s+\w)/,lookbehind:!0,alias:"class-name"}}),n.languages.insertBefore("chaiscript","string",{"string-interpolation":{pattern:/(^|[^\\])"(?:[^"$\\]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*"/,lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}/,lookbehind:!0,inside:{"interpolation-expression":{pattern:/(^\$\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:n.languages.chaiscript},"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"}}},string:/[\s\S]+/}}})}return Cl}var Nl,hE;function hz(){if(hE)return Nl;hE=1,Nl=e,e.displayName="cil",e.aliases=[];function e(t){t.languages.cil={comment:/\/\/.*/,string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},directive:{pattern:/(^|\W)\.[a-z]+(?=\s)/,lookbehind:!0,alias:"class-name"},variable:/\[[\w\.]+\]/,keyword:/\b(?:abstract|ansi|assembly|auto|autochar|beforefieldinit|bool|bstr|byvalstr|catch|char|cil|class|currency|date|decimal|default|enum|error|explicit|extends|extern|famandassem|family|famorassem|final(?:ly)?|float32|float64|hidebysig|u?int(?:8|16|32|64)?|iant|idispatch|implements|import|initonly|instance|interface|iunknown|literal|lpstr|lpstruct|lptstr|lpwstr|managed|method|native(?:Type)?|nested|newslot|object(?:ref)?|pinvokeimpl|private|privatescope|public|reqsecobj|rtspecialname|runtime|sealed|sequential|serializable|specialname|static|string|struct|syschar|tbstr|unicode|unmanagedexp|unsigned|value(?:type)?|variant|virtual|void)\b/,function:/\b(?:(?:constrained|no|readonly|tail|unaligned|volatile)\.)?(?:conv\.(?:[iu][1248]?|ovf\.[iu][1248]?(?:\.un)?|r\.un|r4|r8)|ldc\.(?:i4(?:\.\d+|\.[mM]1|\.s)?|i8|r4|r8)|ldelem(?:\.[iu][1248]?|\.r[48]|\.ref|a)?|ldind\.(?:[iu][1248]?|r[48]|ref)|stelem\.?(?:i[1248]?|r[48]|ref)?|stind\.(?:i[1248]?|r[48]|ref)?|end(?:fault|filter|finally)|ldarg(?:\.[0-3s]|a(?:\.s)?)?|ldloc(?:\.\d+|\.s)?|sub(?:\.ovf(?:\.un)?)?|mul(?:\.ovf(?:\.un)?)?|add(?:\.ovf(?:\.un)?)?|stloc(?:\.[0-3s])?|refany(?:type|val)|blt(?:\.un)?(?:\.s)?|ble(?:\.un)?(?:\.s)?|bgt(?:\.un)?(?:\.s)?|bge(?:\.un)?(?:\.s)?|unbox(?:\.any)?|init(?:blk|obj)|call(?:i|virt)?|brfalse(?:\.s)?|bne\.un(?:\.s)?|ldloca(?:\.s)?|brzero(?:\.s)?|brtrue(?:\.s)?|brnull(?:\.s)?|brinst(?:\.s)?|starg(?:\.s)?|leave(?:\.s)?|shr(?:\.un)?|rem(?:\.un)?|div(?:\.un)?|clt(?:\.un)?|alignment|castclass|ldvirtftn|beq(?:\.s)?|ckfinite|ldsflda|ldtoken|localloc|mkrefany|rethrow|cgt\.un|arglist|switch|stsfld|sizeof|newobj|newarr|ldsfld|ldnull|ldflda|isinst|throw|stobj|stfld|ldstr|ldobj|ldlen|ldftn|ldfld|cpobj|cpblk|break|br\.s|xor|shl|ret|pop|not|nop|neg|jmp|dup|cgt|ceq|box|and|or|br)\b/,boolean:/\b(?:false|true)\b/,number:/\b-?(?:0x[0-9a-f]+|\d+)(?:\.[0-9a-f]+)?\b/i,punctuation:/[{}[\];(),:=]|IL_[0-9A-Za-z]+/}}return Nl}var xl,bE;function bz(){if(bE)return xl;bE=1,xl=e,e.displayName="clojure",e.aliases=[];function e(t){t.languages.clojure={comment:{pattern:/;.*/,greedy:!0},string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0},char:/\\\w+/,symbol:{pattern:/(^|[\s()\[\]{},])::?[\w*+!?'<>=/.-]+/,lookbehind:!0},keyword:{pattern:/(\()(?:-|->|->>|\.|\.\.|\*|\/|\+|<|<=|=|==|>|>=|accessor|agent|agent-errors|aget|alength|all-ns|alter|and|append-child|apply|array-map|aset|aset-boolean|aset-byte|aset-char|aset-double|aset-float|aset-int|aset-long|aset-short|assert|assoc|await|await-for|bean|binding|bit-and|bit-not|bit-or|bit-shift-left|bit-shift-right|bit-xor|boolean|branch\?|butlast|byte|cast|char|children|class|clear-agent-errors|comment|commute|comp|comparator|complement|concat|cond|conj|cons|constantly|construct-proxy|contains\?|count|create-ns|create-struct|cycle|dec|declare|def|def-|definline|definterface|defmacro|defmethod|defmulti|defn|defn-|defonce|defproject|defprotocol|defrecord|defstruct|deftype|deref|difference|disj|dissoc|distinct|do|doall|doc|dorun|doseq|dosync|dotimes|doto|double|down|drop|drop-while|edit|end\?|ensure|eval|every\?|false\?|ffirst|file-seq|filter|find|find-doc|find-ns|find-var|first|float|flush|fn|fnseq|for|frest|gensym|get|get-proxy-class|hash-map|hash-set|identical\?|identity|if|if-let|if-not|import|in-ns|inc|index|insert-child|insert-left|insert-right|inspect-table|inspect-tree|instance\?|int|interleave|intersection|into|into-array|iterate|join|key|keys|keyword|keyword\?|last|lazy-cat|lazy-cons|left|lefts|let|line-seq|list|list\*|load|load-file|locking|long|loop|macroexpand|macroexpand-1|make-array|make-node|map|map-invert|map\?|mapcat|max|max-key|memfn|merge|merge-with|meta|min|min-key|monitor-enter|name|namespace|neg\?|new|newline|next|nil\?|node|not|not-any\?|not-every\?|not=|ns|ns-imports|ns-interns|ns-map|ns-name|ns-publics|ns-refers|ns-resolve|ns-unmap|nth|nthrest|or|parse|partial|path|peek|pop|pos\?|pr|pr-str|print|print-str|println|println-str|prn|prn-str|project|proxy|proxy-mappings|quot|quote|rand|rand-int|range|re-find|re-groups|re-matcher|re-matches|re-pattern|re-seq|read|read-line|recur|reduce|ref|ref-set|refer|rem|remove|remove-method|remove-ns|rename|rename-keys|repeat|replace|replicate|resolve|rest|resultset-seq|reverse|rfirst|right|rights|root|rrest|rseq|second|select|select-keys|send|send-off|seq|seq-zip|seq\?|set|set!|short|slurp|some|sort|sort-by|sorted-map|sorted-map-by|sorted-set|special-symbol\?|split-at|split-with|str|string\?|struct|struct-map|subs|subvec|symbol|symbol\?|sync|take|take-nth|take-while|test|throw|time|to-array|to-array-2d|tree-seq|true\?|try|union|up|update-proxy|val|vals|var|var-get|var-set|var\?|vector|vector-zip|vector\?|when|when-first|when-let|when-not|with-local-vars|with-meta|with-open|with-out-str|xml-seq|xml-zip|zero\?|zipmap|zipper)(?=[\s)]|$)/,lookbehind:!0},boolean:/\b(?:false|nil|true)\b/,number:{pattern:/(^|[^\w$@])(?:\d+(?:[/.]\d+)?(?:e[+-]?\d+)?|0x[a-f0-9]+|[1-9]\d?r[a-z0-9]+)[lmn]?(?![\w$@])/i,lookbehind:!0},function:{pattern:/((?:^|[^'])\()[\w*+!?'<>=/.-]+(?=[\s)]|$)/,lookbehind:!0},operator:/[#@^`~]/,punctuation:/[{}\[\](),]/}}return xl}var Ol,yE;function yz(){if(yE)return Ol;yE=1,Ol=e,e.displayName="cmake",e.aliases=[];function e(t){t.languages.cmake={comment:/#.*/,string:{pattern:/"(?:[^\\"]|\\.)*"/,greedy:!0,inside:{interpolation:{pattern:/\$\{(?:[^{}$]|\$\{[^{}$]*\})*\}/,inside:{punctuation:/\$\{|\}/,variable:/\w+/}}}},variable:/\b(?:CMAKE_\w+|\w+_(?:(?:BINARY|SOURCE)_DIR|DESCRIPTION|HOMEPAGE_URL|ROOT|VERSION(?:_MAJOR|_MINOR|_PATCH|_TWEAK)?)|(?:ANDROID|APPLE|BORLAND|BUILD_SHARED_LIBS|CACHE|CPACK_(?:ABSOLUTE_DESTINATION_FILES|COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY|ERROR_ON_ABSOLUTE_INSTALL_DESTINATION|INCLUDE_TOPLEVEL_DIRECTORY|INSTALL_DEFAULT_DIRECTORY_PERMISSIONS|INSTALL_SCRIPT|PACKAGING_INSTALL_PREFIX|SET_DESTDIR|WARN_ON_ABSOLUTE_INSTALL_DESTINATION)|CTEST_(?:BINARY_DIRECTORY|BUILD_COMMAND|BUILD_NAME|BZR_COMMAND|BZR_UPDATE_OPTIONS|CHANGE_ID|CHECKOUT_COMMAND|CONFIGURATION_TYPE|CONFIGURE_COMMAND|COVERAGE_COMMAND|COVERAGE_EXTRA_FLAGS|CURL_OPTIONS|CUSTOM_(?:COVERAGE_EXCLUDE|ERROR_EXCEPTION|ERROR_MATCH|ERROR_POST_CONTEXT|ERROR_PRE_CONTEXT|MAXIMUM_FAILED_TEST_OUTPUT_SIZE|MAXIMUM_NUMBER_OF_(?:ERRORS|WARNINGS)|MAXIMUM_PASSED_TEST_OUTPUT_SIZE|MEMCHECK_IGNORE|POST_MEMCHECK|POST_TEST|PRE_MEMCHECK|PRE_TEST|TESTS_IGNORE|WARNING_EXCEPTION|WARNING_MATCH)|CVS_CHECKOUT|CVS_COMMAND|CVS_UPDATE_OPTIONS|DROP_LOCATION|DROP_METHOD|DROP_SITE|DROP_SITE_CDASH|DROP_SITE_PASSWORD|DROP_SITE_USER|EXTRA_COVERAGE_GLOB|GIT_COMMAND|GIT_INIT_SUBMODULES|GIT_UPDATE_CUSTOM|GIT_UPDATE_OPTIONS|HG_COMMAND|HG_UPDATE_OPTIONS|LABELS_FOR_SUBPROJECTS|MEMORYCHECK_(?:COMMAND|COMMAND_OPTIONS|SANITIZER_OPTIONS|SUPPRESSIONS_FILE|TYPE)|NIGHTLY_START_TIME|P4_CLIENT|P4_COMMAND|P4_OPTIONS|P4_UPDATE_OPTIONS|RUN_CURRENT_SCRIPT|SCP_COMMAND|SITE|SOURCE_DIRECTORY|SUBMIT_URL|SVN_COMMAND|SVN_OPTIONS|SVN_UPDATE_OPTIONS|TEST_LOAD|TEST_TIMEOUT|TRIGGER_SITE|UPDATE_COMMAND|UPDATE_OPTIONS|UPDATE_VERSION_ONLY|USE_LAUNCHERS)|CYGWIN|ENV|EXECUTABLE_OUTPUT_PATH|GHS-MULTI|IOS|LIBRARY_OUTPUT_PATH|MINGW|MSVC(?:10|11|12|14|60|70|71|80|90|_IDE|_TOOLSET_VERSION|_VERSION)?|MSYS|PROJECT_(?:BINARY_DIR|DESCRIPTION|HOMEPAGE_URL|NAME|SOURCE_DIR|VERSION|VERSION_(?:MAJOR|MINOR|PATCH|TWEAK))|UNIX|WIN32|WINCE|WINDOWS_PHONE|WINDOWS_STORE|XCODE|XCODE_VERSION))\b/,property:/\b(?:cxx_\w+|(?:ARCHIVE_OUTPUT_(?:DIRECTORY|NAME)|COMPILE_DEFINITIONS|COMPILE_PDB_NAME|COMPILE_PDB_OUTPUT_DIRECTORY|EXCLUDE_FROM_DEFAULT_BUILD|IMPORTED_(?:IMPLIB|LIBNAME|LINK_DEPENDENT_LIBRARIES|LINK_INTERFACE_LANGUAGES|LINK_INTERFACE_LIBRARIES|LINK_INTERFACE_MULTIPLICITY|LOCATION|NO_SONAME|OBJECTS|SONAME)|INTERPROCEDURAL_OPTIMIZATION|LIBRARY_OUTPUT_DIRECTORY|LIBRARY_OUTPUT_NAME|LINK_FLAGS|LINK_INTERFACE_LIBRARIES|LINK_INTERFACE_MULTIPLICITY|LOCATION|MAP_IMPORTED_CONFIG|OSX_ARCHITECTURES|OUTPUT_NAME|PDB_NAME|PDB_OUTPUT_DIRECTORY|RUNTIME_OUTPUT_DIRECTORY|RUNTIME_OUTPUT_NAME|STATIC_LIBRARY_FLAGS|VS_CSHARP|VS_DOTNET_REFERENCEPROP|VS_DOTNET_REFERENCE|VS_GLOBAL_SECTION_POST|VS_GLOBAL_SECTION_PRE|VS_GLOBAL|XCODE_ATTRIBUTE)_\w+|\w+_(?:CLANG_TIDY|COMPILER_LAUNCHER|CPPCHECK|CPPLINT|INCLUDE_WHAT_YOU_USE|OUTPUT_NAME|POSTFIX|VISIBILITY_PRESET)|ABSTRACT|ADDITIONAL_MAKE_CLEAN_FILES|ADVANCED|ALIASED_TARGET|ALLOW_DUPLICATE_CUSTOM_TARGETS|ANDROID_(?:ANT_ADDITIONAL_OPTIONS|API|API_MIN|ARCH|ASSETS_DIRECTORIES|GUI|JAR_DEPENDENCIES|NATIVE_LIB_DEPENDENCIES|NATIVE_LIB_DIRECTORIES|PROCESS_MAX|PROGUARD|PROGUARD_CONFIG_PATH|SECURE_PROPS_PATH|SKIP_ANT_STEP|STL_TYPE)|ARCHIVE_OUTPUT_DIRECTORY|ATTACHED_FILES|ATTACHED_FILES_ON_FAIL|AUTOGEN_(?:BUILD_DIR|ORIGIN_DEPENDS|PARALLEL|SOURCE_GROUP|TARGETS_FOLDER|TARGET_DEPENDS)|AUTOMOC|AUTOMOC_(?:COMPILER_PREDEFINES|DEPEND_FILTERS|EXECUTABLE|MACRO_NAMES|MOC_OPTIONS|SOURCE_GROUP|TARGETS_FOLDER)|AUTORCC|AUTORCC_EXECUTABLE|AUTORCC_OPTIONS|AUTORCC_SOURCE_GROUP|AUTOUIC|AUTOUIC_EXECUTABLE|AUTOUIC_OPTIONS|AUTOUIC_SEARCH_PATHS|BINARY_DIR|BUILDSYSTEM_TARGETS|BUILD_RPATH|BUILD_RPATH_USE_ORIGIN|BUILD_WITH_INSTALL_NAME_DIR|BUILD_WITH_INSTALL_RPATH|BUNDLE|BUNDLE_EXTENSION|CACHE_VARIABLES|CLEAN_NO_CUSTOM|COMMON_LANGUAGE_RUNTIME|COMPATIBLE_INTERFACE_(?:BOOL|NUMBER_MAX|NUMBER_MIN|STRING)|COMPILE_(?:DEFINITIONS|FEATURES|FLAGS|OPTIONS|PDB_NAME|PDB_OUTPUT_DIRECTORY)|COST|CPACK_DESKTOP_SHORTCUTS|CPACK_NEVER_OVERWRITE|CPACK_PERMANENT|CPACK_STARTUP_SHORTCUTS|CPACK_START_MENU_SHORTCUTS|CPACK_WIX_ACL|CROSSCOMPILING_EMULATOR|CUDA_EXTENSIONS|CUDA_PTX_COMPILATION|CUDA_RESOLVE_DEVICE_SYMBOLS|CUDA_SEPARABLE_COMPILATION|CUDA_STANDARD|CUDA_STANDARD_REQUIRED|CXX_EXTENSIONS|CXX_STANDARD|CXX_STANDARD_REQUIRED|C_EXTENSIONS|C_STANDARD|C_STANDARD_REQUIRED|DEBUG_CONFIGURATIONS|DEFINE_SYMBOL|DEFINITIONS|DEPENDS|DEPLOYMENT_ADDITIONAL_FILES|DEPLOYMENT_REMOTE_DIRECTORY|DISABLED|DISABLED_FEATURES|ECLIPSE_EXTRA_CPROJECT_CONTENTS|ECLIPSE_EXTRA_NATURES|ENABLED_FEATURES|ENABLED_LANGUAGES|ENABLE_EXPORTS|ENVIRONMENT|EXCLUDE_FROM_ALL|EXCLUDE_FROM_DEFAULT_BUILD|EXPORT_NAME|EXPORT_PROPERTIES|EXTERNAL_OBJECT|EchoString|FAIL_REGULAR_EXPRESSION|FIND_LIBRARY_USE_LIB32_PATHS|FIND_LIBRARY_USE_LIB64_PATHS|FIND_LIBRARY_USE_LIBX32_PATHS|FIND_LIBRARY_USE_OPENBSD_VERSIONING|FIXTURES_CLEANUP|FIXTURES_REQUIRED|FIXTURES_SETUP|FOLDER|FRAMEWORK|Fortran_FORMAT|Fortran_MODULE_DIRECTORY|GENERATED|GENERATOR_FILE_NAME|GENERATOR_IS_MULTI_CONFIG|GHS_INTEGRITY_APP|GHS_NO_SOURCE_GROUP_FILE|GLOBAL_DEPENDS_DEBUG_MODE|GLOBAL_DEPENDS_NO_CYCLES|GNUtoMS|HAS_CXX|HEADER_FILE_ONLY|HELPSTRING|IMPLICIT_DEPENDS_INCLUDE_TRANSFORM|IMPORTED|IMPORTED_(?:COMMON_LANGUAGE_RUNTIME|CONFIGURATIONS|GLOBAL|IMPLIB|LIBNAME|LINK_DEPENDENT_LIBRARIES|LINK_INTERFACE_(?:LANGUAGES|LIBRARIES|MULTIPLICITY)|LOCATION|NO_SONAME|OBJECTS|SONAME)|IMPORT_PREFIX|IMPORT_SUFFIX|INCLUDE_DIRECTORIES|INCLUDE_REGULAR_EXPRESSION|INSTALL_NAME_DIR|INSTALL_RPATH|INSTALL_RPATH_USE_LINK_PATH|INTERFACE_(?:AUTOUIC_OPTIONS|COMPILE_DEFINITIONS|COMPILE_FEATURES|COMPILE_OPTIONS|INCLUDE_DIRECTORIES|LINK_DEPENDS|LINK_DIRECTORIES|LINK_LIBRARIES|LINK_OPTIONS|POSITION_INDEPENDENT_CODE|SOURCES|SYSTEM_INCLUDE_DIRECTORIES)|INTERPROCEDURAL_OPTIMIZATION|IN_TRY_COMPILE|IOS_INSTALL_COMBINED|JOB_POOLS|JOB_POOL_COMPILE|JOB_POOL_LINK|KEEP_EXTENSION|LABELS|LANGUAGE|LIBRARY_OUTPUT_DIRECTORY|LINKER_LANGUAGE|LINK_(?:DEPENDS|DEPENDS_NO_SHARED|DIRECTORIES|FLAGS|INTERFACE_LIBRARIES|INTERFACE_MULTIPLICITY|LIBRARIES|OPTIONS|SEARCH_END_STATIC|SEARCH_START_STATIC|WHAT_YOU_USE)|LISTFILE_STACK|LOCATION|MACOSX_BUNDLE|MACOSX_BUNDLE_INFO_PLIST|MACOSX_FRAMEWORK_INFO_PLIST|MACOSX_PACKAGE_LOCATION|MACOSX_RPATH|MACROS|MANUALLY_ADDED_DEPENDENCIES|MEASUREMENT|MODIFIED|NAME|NO_SONAME|NO_SYSTEM_FROM_IMPORTED|OBJECT_DEPENDS|OBJECT_OUTPUTS|OSX_ARCHITECTURES|OUTPUT_NAME|PACKAGES_FOUND|PACKAGES_NOT_FOUND|PARENT_DIRECTORY|PASS_REGULAR_EXPRESSION|PDB_NAME|PDB_OUTPUT_DIRECTORY|POSITION_INDEPENDENT_CODE|POST_INSTALL_SCRIPT|PREDEFINED_TARGETS_FOLDER|PREFIX|PRE_INSTALL_SCRIPT|PRIVATE_HEADER|PROCESSORS|PROCESSOR_AFFINITY|PROJECT_LABEL|PUBLIC_HEADER|REPORT_UNDEFINED_PROPERTIES|REQUIRED_FILES|RESOURCE|RESOURCE_LOCK|RULE_LAUNCH_COMPILE|RULE_LAUNCH_CUSTOM|RULE_LAUNCH_LINK|RULE_MESSAGES|RUNTIME_OUTPUT_DIRECTORY|RUN_SERIAL|SKIP_AUTOGEN|SKIP_AUTOMOC|SKIP_AUTORCC|SKIP_AUTOUIC|SKIP_BUILD_RPATH|SKIP_RETURN_CODE|SOURCES|SOURCE_DIR|SOVERSION|STATIC_LIBRARY_FLAGS|STATIC_LIBRARY_OPTIONS|STRINGS|SUBDIRECTORIES|SUFFIX|SYMBOLIC|TARGET_ARCHIVES_MAY_BE_SHARED_LIBS|TARGET_MESSAGES|TARGET_SUPPORTS_SHARED_LIBS|TESTS|TEST_INCLUDE_FILE|TEST_INCLUDE_FILES|TIMEOUT|TIMEOUT_AFTER_MATCH|TYPE|USE_FOLDERS|VALUE|VARIABLES|VERSION|VISIBILITY_INLINES_HIDDEN|VS_(?:CONFIGURATION_TYPE|COPY_TO_OUT_DIR|DEBUGGER_(?:COMMAND|COMMAND_ARGUMENTS|ENVIRONMENT|WORKING_DIRECTORY)|DEPLOYMENT_CONTENT|DEPLOYMENT_LOCATION|DOTNET_REFERENCES|DOTNET_REFERENCES_COPY_LOCAL|GLOBAL_KEYWORD|GLOBAL_PROJECT_TYPES|GLOBAL_ROOTNAMESPACE|INCLUDE_IN_VSIX|IOT_STARTUP_TASK|KEYWORD|RESOURCE_GENERATOR|SCC_AUXPATH|SCC_LOCALPATH|SCC_PROJECTNAME|SCC_PROVIDER|SDK_REFERENCES|SHADER_(?:DISABLE_OPTIMIZATIONS|ENABLE_DEBUG|ENTRYPOINT|FLAGS|MODEL|OBJECT_FILE_NAME|OUTPUT_HEADER_FILE|TYPE|VARIABLE_NAME)|STARTUP_PROJECT|TOOL_OVERRIDE|USER_PROPS|WINRT_COMPONENT|WINRT_EXTENSIONS|WINRT_REFERENCES|XAML_TYPE)|WILL_FAIL|WIN32_EXECUTABLE|WINDOWS_EXPORT_ALL_SYMBOLS|WORKING_DIRECTORY|WRAP_EXCLUDE|XCODE_(?:EMIT_EFFECTIVE_PLATFORM_NAME|EXPLICIT_FILE_TYPE|FILE_ATTRIBUTES|LAST_KNOWN_FILE_TYPE|PRODUCT_TYPE|SCHEME_(?:ADDRESS_SANITIZER|ADDRESS_SANITIZER_USE_AFTER_RETURN|ARGUMENTS|DISABLE_MAIN_THREAD_CHECKER|DYNAMIC_LIBRARY_LOADS|DYNAMIC_LINKER_API_USAGE|ENVIRONMENT|EXECUTABLE|GUARD_MALLOC|MAIN_THREAD_CHECKER_STOP|MALLOC_GUARD_EDGES|MALLOC_SCRIBBLE|MALLOC_STACK|THREAD_SANITIZER(?:_STOP)?|UNDEFINED_BEHAVIOUR_SANITIZER(?:_STOP)?|ZOMBIE_OBJECTS))|XCTEST)\b/,keyword:/\b(?:add_compile_definitions|add_compile_options|add_custom_command|add_custom_target|add_definitions|add_dependencies|add_executable|add_library|add_link_options|add_subdirectory|add_test|aux_source_directory|break|build_command|build_name|cmake_host_system_information|cmake_minimum_required|cmake_parse_arguments|cmake_policy|configure_file|continue|create_test_sourcelist|ctest_build|ctest_configure|ctest_coverage|ctest_empty_binary_directory|ctest_memcheck|ctest_read_custom_files|ctest_run_script|ctest_sleep|ctest_start|ctest_submit|ctest_test|ctest_update|ctest_upload|define_property|else|elseif|enable_language|enable_testing|endforeach|endfunction|endif|endmacro|endwhile|exec_program|execute_process|export|export_library_dependencies|file|find_file|find_library|find_package|find_path|find_program|fltk_wrap_ui|foreach|function|get_cmake_property|get_directory_property|get_filename_component|get_property|get_source_file_property|get_target_property|get_test_property|if|include|include_directories|include_external_msproject|include_guard|include_regular_expression|install|install_files|install_programs|install_targets|link_directories|link_libraries|list|load_cache|load_command|macro|make_directory|mark_as_advanced|math|message|option|output_required_files|project|qt_wrap_cpp|qt_wrap_ui|remove|remove_definitions|return|separate_arguments|set|set_directory_properties|set_property|set_source_files_properties|set_target_properties|set_tests_properties|site_name|source_group|string|subdir_depends|subdirs|target_compile_definitions|target_compile_features|target_compile_options|target_include_directories|target_link_directories|target_link_libraries|target_link_options|target_sources|try_compile|try_run|unset|use_mangled_mesa|utility_source|variable_requires|variable_watch|while|write_file)(?=\s*\()\b/,boolean:/\b(?:FALSE|OFF|ON|TRUE)\b/,namespace:/\b(?:INTERFACE|PRIVATE|PROPERTIES|PUBLIC|SHARED|STATIC|TARGET_OBJECTS)\b/,operator:/\b(?:AND|DEFINED|EQUAL|GREATER|LESS|MATCHES|NOT|OR|STREQUAL|STRGREATER|STRLESS|VERSION_EQUAL|VERSION_GREATER|VERSION_LESS)\b/,inserted:{pattern:/\b\w+::\w+\b/,alias:"class-name"},number:/\b\d+(?:\.\d+)*\b/,function:/\b[a-z_]\w*(?=\s*\()\b/i,punctuation:/[()>}]|\$[<{]/}}return Ol}var Ll,EE;function Ez(){if(EE)return Ll;EE=1,Ll=e,e.displayName="cobol",e.aliases=[];function e(t){t.languages.cobol={comment:{pattern:/\*>.*|(^[ \t]*)\*.*/m,lookbehind:!0,greedy:!0},string:{pattern:/[xzgn]?(?:"(?:[^\r\n"]|"")*"(?!")|'(?:[^\r\n']|'')*'(?!'))/i,greedy:!0},level:{pattern:/(^[ \t]*)\d+\b/m,lookbehind:!0,greedy:!0,alias:"number"},"class-name":{pattern:/(\bpic(?:ture)?\s+)(?:(?:[-\w$/,:*+<>]|\.(?!\s|$))(?:\(\d+\))?)+/i,lookbehind:!0,inside:{number:{pattern:/(\()\d+/,lookbehind:!0},punctuation:/[()]/}},keyword:{pattern:/(^|[^\w-])(?:ABORT|ACCEPT|ACCESS|ADD|ADDRESS|ADVANCING|AFTER|ALIGNED|ALL|ALPHABET|ALPHABETIC|ALPHABETIC-LOWER|ALPHABETIC-UPPER|ALPHANUMERIC|ALPHANUMERIC-EDITED|ALSO|ALTER|ALTERNATE|ANY|ARE|AREA|AREAS|AS|ASCENDING|ASCII|ASSIGN|ASSOCIATED-DATA|ASSOCIATED-DATA-LENGTH|AT|ATTRIBUTE|AUTHOR|AUTO|AUTO-SKIP|BACKGROUND-COLOR|BACKGROUND-COLOUR|BASIS|BEEP|BEFORE|BEGINNING|BELL|BINARY|BIT|BLANK|BLINK|BLOCK|BOTTOM|BOUNDS|BY|BYFUNCTION|BYTITLE|CALL|CANCEL|CAPABLE|CCSVERSION|CD|CF|CH|CHAINING|CHANGED|CHANNEL|CHARACTER|CHARACTERS|CLASS|CLASS-ID|CLOCK-UNITS|CLOSE|CLOSE-DISPOSITION|COBOL|CODE|CODE-SET|COL|COLLATING|COLUMN|COM-REG|COMMA|COMMITMENT|COMMON|COMMUNICATION|COMP|COMP-1|COMP-2|COMP-3|COMP-4|COMP-5|COMPUTATIONAL|COMPUTATIONAL-1|COMPUTATIONAL-2|COMPUTATIONAL-3|COMPUTATIONAL-4|COMPUTATIONAL-5|COMPUTE|CONFIGURATION|CONTAINS|CONTENT|CONTINUE|CONTROL|CONTROL-POINT|CONTROLS|CONVENTION|CONVERTING|COPY|CORR|CORRESPONDING|COUNT|CRUNCH|CURRENCY|CURSOR|DATA|DATA-BASE|DATE|DATE-COMPILED|DATE-WRITTEN|DAY|DAY-OF-WEEK|DBCS|DE|DEBUG-CONTENTS|DEBUG-ITEM|DEBUG-LINE|DEBUG-NAME|DEBUG-SUB-1|DEBUG-SUB-2|DEBUG-SUB-3|DEBUGGING|DECIMAL-POINT|DECLARATIVES|DEFAULT|DEFAULT-DISPLAY|DEFINITION|DELETE|DELIMITED|DELIMITER|DEPENDING|DESCENDING|DESTINATION|DETAIL|DFHRESP|DFHVALUE|DISABLE|DISK|DISPLAY|DISPLAY-1|DIVIDE|DIVISION|DONTCARE|DOUBLE|DOWN|DUPLICATES|DYNAMIC|EBCDIC|EGCS|EGI|ELSE|EMI|EMPTY-CHECK|ENABLE|END|END-ACCEPT|END-ADD|END-CALL|END-COMPUTE|END-DELETE|END-DIVIDE|END-EVALUATE|END-IF|END-MULTIPLY|END-OF-PAGE|END-PERFORM|END-READ|END-RECEIVE|END-RETURN|END-REWRITE|END-SEARCH|END-START|END-STRING|END-SUBTRACT|END-UNSTRING|END-WRITE|ENDING|ENTER|ENTRY|ENTRY-PROCEDURE|ENVIRONMENT|EOL|EOP|EOS|ERASE|ERROR|ESCAPE|ESI|EVALUATE|EVENT|EVERY|EXCEPTION|EXCLUSIVE|EXHIBIT|EXIT|EXPORT|EXTEND|EXTENDED|EXTERNAL|FD|FILE|FILE-CONTROL|FILLER|FINAL|FIRST|FOOTING|FOR|FOREGROUND-COLOR|FOREGROUND-COLOUR|FROM|FULL|FUNCTION|FUNCTION-POINTER|FUNCTIONNAME|GENERATE|GIVING|GLOBAL|GO|GOBACK|GRID|GROUP|HEADING|HIGH-VALUE|HIGH-VALUES|HIGHLIGHT|I-O|I-O-CONTROL|ID|IDENTIFICATION|IF|IMPLICIT|IMPORT|IN|INDEX|INDEXED|INDICATE|INITIAL|INITIALIZE|INITIATE|INPUT|INPUT-OUTPUT|INSPECT|INSTALLATION|INTEGER|INTO|INVALID|INVOKE|IS|JUST|JUSTIFIED|KANJI|KEPT|KEY|KEYBOARD|LABEL|LANGUAGE|LAST|LB|LD|LEADING|LEFT|LEFTLINE|LENGTH|LENGTH-CHECK|LIBACCESS|LIBPARAMETER|LIBRARY|LIMIT|LIMITS|LINAGE|LINAGE-COUNTER|LINE|LINE-COUNTER|LINES|LINKAGE|LIST|LOCAL|LOCAL-STORAGE|LOCK|LONG-DATE|LONG-TIME|LOW-VALUE|LOW-VALUES|LOWER|LOWLIGHT|MEMORY|MERGE|MESSAGE|MMDDYYYY|MODE|MODULES|MORE-LABELS|MOVE|MULTIPLE|MULTIPLY|NAMED|NATIONAL|NATIONAL-EDITED|NATIVE|NEGATIVE|NETWORK|NEXT|NO|NO-ECHO|NULL|NULLS|NUMBER|NUMERIC|NUMERIC-DATE|NUMERIC-EDITED|NUMERIC-TIME|OBJECT-COMPUTER|OCCURS|ODT|OF|OFF|OMITTED|ON|OPEN|OPTIONAL|ORDER|ORDERLY|ORGANIZATION|OTHER|OUTPUT|OVERFLOW|OVERLINE|OWN|PACKED-DECIMAL|PADDING|PAGE|PAGE-COUNTER|PASSWORD|PERFORM|PF|PH|PIC|PICTURE|PLUS|POINTER|PORT|POSITION|POSITIVE|PRINTER|PRINTING|PRIVATE|PROCEDURE|PROCEDURE-POINTER|PROCEDURES|PROCEED|PROCESS|PROGRAM|PROGRAM-ID|PROGRAM-LIBRARY|PROMPT|PURGE|QUEUE|QUOTE|QUOTES|RANDOM|RD|READ|READER|REAL|RECEIVE|RECEIVED|RECORD|RECORDING|RECORDS|RECURSIVE|REDEFINES|REEL|REF|REFERENCE|REFERENCES|RELATIVE|RELEASE|REMAINDER|REMARKS|REMOTE|REMOVAL|REMOVE|RENAMES|REPLACE|REPLACING|REPORT|REPORTING|REPORTS|REQUIRED|RERUN|RESERVE|RESET|RETURN|RETURN-CODE|RETURNING|REVERSE-VIDEO|REVERSED|REWIND|REWRITE|RF|RH|RIGHT|ROUNDED|RUN|SAME|SAVE|SCREEN|SD|SEARCH|SECTION|SECURE|SECURITY|SEGMENT|SEGMENT-LIMIT|SELECT|SEND|SENTENCE|SEPARATE|SEQUENCE|SEQUENTIAL|SET|SHARED|SHAREDBYALL|SHAREDBYRUNUNIT|SHARING|SHIFT-IN|SHIFT-OUT|SHORT-DATE|SIGN|SIZE|SORT|SORT-CONTROL|SORT-CORE-SIZE|SORT-FILE-SIZE|SORT-MERGE|SORT-MESSAGE|SORT-MODE-SIZE|SORT-RETURN|SOURCE|SOURCE-COMPUTER|SPACE|SPACES|SPECIAL-NAMES|STANDARD|STANDARD-1|STANDARD-2|START|STATUS|STOP|STRING|SUB-QUEUE-1|SUB-QUEUE-2|SUB-QUEUE-3|SUBTRACT|SUM|SUPPRESS|SYMBOL|SYMBOLIC|SYNC|SYNCHRONIZED|TABLE|TALLY|TALLYING|TAPE|TASK|TERMINAL|TERMINATE|TEST|TEXT|THEN|THREAD|THREAD-LOCAL|THROUGH|THRU|TIME|TIMER|TIMES|TITLE|TO|TODAYS-DATE|TODAYS-NAME|TOP|TRAILING|TRUNCATED|TYPE|TYPEDEF|UNDERLINE|UNIT|UNSTRING|UNTIL|UP|UPON|USAGE|USE|USING|VALUE|VALUES|VARYING|VIRTUAL|WAIT|WHEN|WHEN-COMPILED|WITH|WORDS|WORKING-STORAGE|WRITE|YEAR|YYYYDDD|YYYYMMDD|ZERO-FILL|ZEROES|ZEROS)(?![\w-])/i,lookbehind:!0},boolean:{pattern:/(^|[^\w-])(?:false|true)(?![\w-])/i,lookbehind:!0},number:{pattern:/(^|[^\w-])(?:[+-]?(?:(?:\d+(?:[.,]\d+)?|[.,]\d+)(?:e[+-]?\d+)?|zero))(?![\w-])/i,lookbehind:!0},operator:[/<>|[<>]=?|[=+*/&]/,{pattern:/(^|[^\w-])(?:-|and|equal|greater|less|not|or|than)(?![\w-])/i,lookbehind:!0}],punctuation:/[.:,()]/}}return Ll}var Dl,SE;function Sz(){if(SE)return Dl;SE=1,Dl=e,e.displayName="coffeescript",e.aliases=["coffee"];function e(t){(function(n){var r=/#(?!\{).+/,a={pattern:/#\{[^}]+\}/,alias:"variable"};n.languages.coffeescript=n.languages.extend("javascript",{comment:r,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:a}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),n.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:r,interpolation:a}}}),n.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:n.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:a}}]}),n.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete n.languages.coffeescript["template-string"],n.languages.coffee=n.languages.coffeescript})(t)}return Dl}var Ml,vE;function vz(){if(vE)return Ml;vE=1,Ml=e,e.displayName="concurnas",e.aliases=["conc"];function e(t){t.languages.concurnas={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?(?:\*\/|$)|\/\/.*)/,lookbehind:!0,greedy:!0},langext:{pattern:/\b\w+\s*\|\|[\s\S]+?\|\|/,greedy:!0,inside:{"class-name":/^\w+/,string:{pattern:/(^\s*\|\|)[\s\S]+(?=\|\|$)/,lookbehind:!0},punctuation:/\|\|/}},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/,lookbehind:!0},keyword:/\b(?:abstract|actor|also|annotation|assert|async|await|bool|boolean|break|byte|case|catch|changed|char|class|closed|constant|continue|def|default|del|double|elif|else|enum|every|extends|false|finally|float|for|from|global|gpudef|gpukernel|if|import|in|init|inject|int|lambda|local|long|loop|match|new|nodefault|null|of|onchange|open|out|override|package|parfor|parforsync|post|pre|private|protected|provide|provider|public|return|shared|short|single|size_t|sizeof|super|sync|this|throw|trait|trans|transient|true|try|typedef|unchecked|using|val|var|void|while|with)\b/,boolean:/\b(?:false|true)\b/,number:/\b0b[01][01_]*L?\b|\b0x(?:[\da-f_]*\.)?[\da-f_p+-]+\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfls]?/i,punctuation:/[{}[\];(),.:]/,operator:/<==|>==|=>|->|<-|<>|&==|&<>|\?:?|\.\?|\+\+|--|[-+*/=<>]=?|[!^~]|\b(?:and|as|band|bor|bxor|comp|is|isnot|mod|or)\b=?/,annotation:{pattern:/@(?:\w+:)?(?:\w+|\[[^\]]+\])?/,alias:"builtin"}},t.languages.insertBefore("concurnas","langext",{"regex-literal":{pattern:/\br("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:t.languages.concurnas},regex:/[\s\S]+/}},"string-literal":{pattern:/(?:\B|\bs)("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:t.languages.concurnas},string:/[\s\S]+/}}}),t.languages.conc=t.languages.concurnas}return Ml}var Fl,kE;function kz(){if(kE)return Fl;kE=1,Fl=e,e.displayName="coq",e.aliases=[];function e(t){(function(n){for(var r=/\(\*(?:[^(*]|\((?!\*)|\*(?!\))|)*\*\)/.source,a=0;a<2;a++)r=r.replace(//g,function(){return r});r=r.replace(//g,"[]"),n.languages.coq={comment:RegExp(r),string:{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},attribute:[{pattern:RegExp(/#\[(?:[^\[\]("]|"(?:[^"]|"")*"(?!")|\((?!\*)|)*\]/.source.replace(//g,function(){return r})),greedy:!0,alias:"attr-name",inside:{comment:RegExp(r),string:{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},operator:/=/,punctuation:/^#\[|\]$|[,()]/}},{pattern:/\b(?:Cumulative|Global|Local|Monomorphic|NonCumulative|Polymorphic|Private|Program)\b/,alias:"attr-name"}],keyword:/\b(?:Abort|About|Add|Admit|Admitted|All|Arguments|As|Assumptions|Axiom|Axioms|Back|BackTo|Backtrace|BinOp|BinOpSpec|BinRel|Bind|Blacklist|Canonical|Case|Cd|Check|Class|Classes|Close|CoFixpoint|CoInductive|Coercion|Coercions|Collection|Combined|Compute|Conjecture|Conjectures|Constant|Constants|Constraint|Constructors|Context|Corollary|Create|CstOp|Custom|Cut|Debug|Declare|Defined|Definition|Delimit|Dependencies|Dependent|Derive|Diffs|Drop|Elimination|End|Entry|Equality|Eval|Example|Existential|Existentials|Existing|Export|Extern|Extraction|Fact|Fail|Field|File|Firstorder|Fixpoint|Flags|Focus|From|Funclass|Function|Functional|GC|Generalizable|Goal|Grab|Grammar|Graph|Guarded|Haskell|Heap|Hide|Hint|HintDb|Hints|Hypotheses|Hypothesis|IF|Identity|Immediate|Implicit|Implicits|Import|Include|Induction|Inductive|Infix|Info|Initial|InjTyp|Inline|Inspect|Instance|Instances|Intro|Intros|Inversion|Inversion_clear|JSON|Language|Left|Lemma|Let|Lia|Libraries|Library|Load|LoadPath|Locate|Ltac|Ltac2|ML|Match|Method|Minimality|Module|Modules|Morphism|Next|NoInline|Notation|Number|OCaml|Obligation|Obligations|Opaque|Open|Optimize|Parameter|Parameters|Parametric|Path|Paths|Prenex|Preterm|Primitive|Print|Profile|Projections|Proof|Prop|PropBinOp|PropOp|PropUOp|Property|Proposition|Pwd|Qed|Quit|Rec|Record|Recursive|Redirect|Reduction|Register|Relation|Remark|Remove|Require|Reserved|Reset|Resolve|Restart|Rewrite|Right|Ring|Rings|SProp|Saturate|Save|Scheme|Scope|Scopes|Search|SearchHead|SearchPattern|SearchRewrite|Section|Separate|Set|Setoid|Show|Signatures|Solve|Solver|Sort|Sortclass|Sorted|Spec|Step|Strategies|Strategy|String|Structure|SubClass|Subgraph|SuchThat|Tactic|Term|TestCompile|Theorem|Time|Timeout|To|Transparent|Type|Typeclasses|Types|Typing|UnOp|UnOpSpec|Undelimit|Undo|Unfocus|Unfocused|Unfold|Universe|Universes|Unshelve|Variable|Variables|Variant|Verbose|View|Visibility|Zify|_|apply|as|at|by|cofix|else|end|exists|exists2|fix|for|forall|fun|if|in|let|match|measure|move|removed|return|struct|then|using|wf|where|with)\b/,number:/\b(?:0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]+)?(?:p[+-]?\d[\d_]*)?|\d[\d_]*(?:\.[\d_]+)?(?:e[+-]?\d[\d_]*)?)\b/i,punct:{pattern:/@\{|\{\||\[=|:>/,alias:"punctuation"},operator:/\/\\|\\\/|\.{2,3}|:{1,2}=|\*\*|[-=]>|<(?:->?|[+:=>]|<:)|>(?:=|->)|\|[-|]?|[-!%&*+/<=>?@^~']/,punctuation:/\.\(|`\(|@\{|`\{|\{\||\[=|:>|[:.,;(){}\[\]]/}})(t)}return Fl}var Pl,wE;function Zo(){if(wE)return Pl;wE=1,Pl=e,e.displayName="ruby",e.aliases=["rb"];function e(t){(function(n){n.languages.ruby=n.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===||[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),n.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var r={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:n.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete n.languages.ruby.function;var a="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",i=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;n.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+a+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+i),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+i+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),n.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+a),greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+a),greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete n.languages.ruby.string,n.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),n.languages.rb=n.languages.ruby})(t)}return Pl}var Ul,_E;function wz(){if(_E)return Ul;_E=1;var e=Zo();Ul=t,t.displayName="crystal",t.aliases=[];function t(n){n.register(e),function(r){r.languages.crystal=r.languages.extend("ruby",{keyword:[/\b(?:__DIR__|__END_LINE__|__FILE__|__LINE__|abstract|alias|annotation|as|asm|begin|break|case|class|def|do|else|elsif|end|ensure|enum|extend|for|fun|if|ifdef|include|instance_sizeof|lib|macro|module|next|of|out|pointerof|private|protected|ptr|require|rescue|return|select|self|sizeof|struct|super|then|type|typeof|undef|uninitialized|union|unless|until|when|while|with|yield)\b/,{pattern:/(\.\s*)(?:is_a|responds_to)\?/,lookbehind:!0}],number:/\b(?:0b[01_]*[01]|0o[0-7_]*[0-7]|0x[\da-fA-F_]*[\da-fA-F]|(?:\d(?:[\d_]*\d)?)(?:\.[\d_]*\d)?(?:[eE][+-]?[\d_]*\d)?)(?:_(?:[uif](?:8|16|32|64))?)?\b/,operator:[/->/,r.languages.ruby.operator],punctuation:/[(){}[\].,;\\]/}),r.languages.insertBefore("crystal","string-literal",{attribute:{pattern:/@\[.*?\]/,inside:{delimiter:{pattern:/^@\[|\]$/,alias:"punctuation"},attribute:{pattern:/^(\s*)\w+/,lookbehind:!0,alias:"class-name"},args:{pattern:/\S(?:[\s\S]*\S)?/,inside:r.languages.crystal}}},expansion:{pattern:/\{(?:\{.*?\}|%.*?%)\}/,inside:{content:{pattern:/^(\{.)[\s\S]+(?=.\}$)/,lookbehind:!0,inside:r.languages.crystal},delimiter:{pattern:/^\{[\{%]|[\}%]\}$/,alias:"operator"}}},char:{pattern:/'(?:[^\\\r\n]{1,2}|\\(?:.|u(?:[A-Fa-f0-9]{1,4}|\{[A-Fa-f0-9]{1,6}\})))'/,greedy:!0}})}(n)}return Ul}var Bl,TE;function _z(){if(TE)return Bl;TE=1;var e=Xo();Bl=t,t.displayName="cshtml",t.aliases=["razor"];function t(n){n.register(e),function(r){var a=/\/(?![/*])|\/\/.*[\r\n]|\/\*[^*]*(?:\*(?!\/)[^*]*)*\*\//.source,i=/@(?!")|"(?:[^\r\n\\"]|\\.)*"|@"(?:[^\\"]|""|\\[\s\S])*"(?!")/.source+"|"+/'(?:(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'|(?=[^\\](?!')))/.source;function o(T,b){for(var g=0;g/g,function(){return"(?:"+T+")"});return T.replace(//g,"[^\\s\\S]").replace(//g,"(?:"+i+")").replace(//g,"(?:"+a+")")}var s=o(/\((?:[^()'"@/]|||)*\)/.source,2),l=o(/\[(?:[^\[\]'"@/]|||)*\]/.source,2),u=o(/\{(?:[^{}'"@/]|||)*\}/.source,2),d=o(/<(?:[^<>'"@/]|||)*>/.source,2),c=/(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?/.source,f=/(?!\d)[^\s>\/=$<%]+/.source+c+/\s*\/?>/.source,p=/\B@?/.source+"(?:"+/<([a-zA-Z][\w:]*)/.source+c+/\s*>/.source+"(?:"+(/[^<]/.source+"|"+/<\/?(?!\1\b)/.source+f+"|"+o(/<\1/.source+c+/\s*>/.source+"(?:"+(/[^<]/.source+"|"+/<\/?(?!\1\b)/.source+f+"|")+")*"+/<\/\1\s*>/.source,2))+")*"+/<\/\1\s*>/.source+"|"+/|\+|~|\|\|/,punctuation:/[(),]/}},n.languages.css.atrule.inside["selector-function-argument"].inside=a,n.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var i={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},o={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};n.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:i,number:o,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:i,number:o})})(t)}return zl}var Gl,IE;function Rz(){if(IE)return Gl;IE=1,Gl=e,e.displayName="csv",e.aliases=[];function e(t){t.languages.csv={value:/[^\r\n,"]+|"(?:[^"]|"")*"(?!")/,punctuation:/,/}}return Gl}var ql,CE;function Iz(){if(CE)return ql;CE=1,ql=e,e.displayName="cypher",e.aliases=[];function e(t){t.languages.cypher={comment:/\/\/.*/,string:{pattern:/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/,greedy:!0},"class-name":{pattern:/(:\s*)(?:\w+|`(?:[^`\\\r\n])*`)(?=\s*[{):])/,lookbehind:!0,greedy:!0},relationship:{pattern:/(-\[\s*(?:\w+\s*|`(?:[^`\\\r\n])*`\s*)?:\s*|\|\s*:\s*)(?:\w+|`(?:[^`\\\r\n])*`)/,lookbehind:!0,greedy:!0,alias:"property"},identifier:{pattern:/`(?:[^`\\\r\n])*`/,greedy:!0},variable:/\$\w+/,keyword:/\b(?:ADD|ALL|AND|AS|ASC|ASCENDING|ASSERT|BY|CALL|CASE|COMMIT|CONSTRAINT|CONTAINS|CREATE|CSV|DELETE|DESC|DESCENDING|DETACH|DISTINCT|DO|DROP|ELSE|END|ENDS|EXISTS|FOR|FOREACH|IN|INDEX|IS|JOIN|KEY|LIMIT|LOAD|MANDATORY|MATCH|MERGE|NODE|NOT|OF|ON|OPTIONAL|OR|ORDER(?=\s+BY)|PERIODIC|REMOVE|REQUIRE|RETURN|SCALAR|SCAN|SET|SKIP|START|STARTS|THEN|UNION|UNIQUE|UNWIND|USING|WHEN|WHERE|WITH|XOR|YIELD)\b/i,function:/\b\w+\b(?=\s*\()/,boolean:/\b(?:false|null|true)\b/i,number:/\b(?:0x[\da-fA-F]+|\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\b/,operator:/:|<--?|--?>?|<>|=~?|[<>]=?|[+*/%^|]|\.\.\.?/,punctuation:/[()[\]{},;.]/}}return ql}var jl,NE;function Cz(){if(NE)return jl;NE=1,jl=e,e.displayName="d",e.aliases=[];function e(t){t.languages.d=t.languages.extend("clike",{comment:[{pattern:/^\s*#!.+/,greedy:!0},{pattern:RegExp(/(^|[^\\])/.source+"(?:"+[/\/\+(?:\/\+(?:[^+]|\+(?!\/))*\+\/|(?!\/\+)[\s\S])*?\+\//.source,/\/\/.*/.source,/\/\*[\s\S]*?\*\//.source].join("|")+")"),lookbehind:!0,greedy:!0}],string:[{pattern:RegExp([/\b[rx]"(?:\\[\s\S]|[^\\"])*"[cwd]?/.source,/\bq"(?:\[[\s\S]*?\]|\([\s\S]*?\)|<[\s\S]*?>|\{[\s\S]*?\})"/.source,/\bq"((?!\d)\w+)$[\s\S]*?^\1"/.source,/\bq"(.)[\s\S]*?\2"/.source,/(["`])(?:\\[\s\S]|(?!\3)[^\\])*\3[cwd]?/.source].join("|"),"m"),greedy:!0},{pattern:/\bq\{(?:\{[^{}]*\}|[^{}])*\}/,greedy:!0,alias:"token-string"}],keyword:/\$|\b(?:__(?:(?:DATE|EOF|FILE|FUNCTION|LINE|MODULE|PRETTY_FUNCTION|TIMESTAMP|TIME|VENDOR|VERSION)__|gshared|parameters|traits|vector)|abstract|alias|align|asm|assert|auto|body|bool|break|byte|case|cast|catch|cdouble|cent|cfloat|char|class|const|continue|creal|dchar|debug|default|delegate|delete|deprecated|do|double|dstring|else|enum|export|extern|false|final|finally|float|for|foreach|foreach_reverse|function|goto|idouble|if|ifloat|immutable|import|inout|int|interface|invariant|ireal|lazy|long|macro|mixin|module|new|nothrow|null|out|override|package|pragma|private|protected|ptrdiff_t|public|pure|real|ref|return|scope|shared|short|size_t|static|string|struct|super|switch|synchronized|template|this|throw|true|try|typedef|typeid|typeof|ubyte|ucent|uint|ulong|union|unittest|ushort|version|void|volatile|wchar|while|with|wstring)\b/,number:[/\b0x\.?[a-f\d_]+(?:(?!\.\.)\.[a-f\d_]*)?(?:p[+-]?[a-f\d_]+)?[ulfi]{0,4}/i,{pattern:/((?:\.\.)?)(?:\b0b\.?|\b|\.)\d[\d_]*(?:(?!\.\.)\.[\d_]*)?(?:e[+-]?\d[\d_]*)?[ulfi]{0,4}/i,lookbehind:!0}],operator:/\|[|=]?|&[&=]?|\+[+=]?|-[-=]?|\.?\.\.|=[>=]?|!(?:i[ns]\b|<>?=?|>=?|=)?|\bi[ns]\b|(?:<[<>]?|>>?>?|\^\^|[*\/%^~])=?/}),t.languages.insertBefore("d","string",{char:/'(?:\\(?:\W|\w+)|[^\\])'/}),t.languages.insertBefore("d","keyword",{property:/\B@\w*/}),t.languages.insertBefore("d","function",{register:{pattern:/\b(?:[ABCD][LHX]|E?(?:BP|DI|SI|SP)|[BS]PL|[ECSDGF]S|CR[0234]|[DS]IL|DR[012367]|E[ABCD]X|X?MM[0-7]|R(?:1[0-5]|[89])[BWD]?|R[ABCD]X|R[BS]P|R[DS]I|TR[3-7]|XMM(?:1[0-5]|[89])|YMM(?:1[0-5]|\d))\b|\bST(?:\([0-7]\)|\b)/,alias:"variable"}})}return jl}var Hl,xE;function Nz(){if(xE)return Hl;xE=1,Hl=e,e.displayName="dart",e.aliases=[];function e(t){(function(n){var r=[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extends|extension|external|factory|final|finally|for|get|hide|if|implements|import|in|interface|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/],a=/(^|[^\w.])(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,i={pattern:RegExp(a+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}}}};n.languages.dart=n.languages.extend("clike",{"class-name":[i,{pattern:RegExp(a+/[A-Z]\w*(?=\s+\w+\s*[;,=()])/.source),lookbehind:!0,inside:i.inside}],keyword:r,operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),n.languages.insertBefore("dart","string",{"string-literal":{pattern:/r?(?:("""|''')[\s\S]*?\1|(["'])(?:\\.|(?!\2)[^\\\r\n])*\2(?!\2))/,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,lookbehind:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:n.languages.dart}}},string:/[\s\S]+/}},string:void 0}),n.languages.insertBefore("dart","class-name",{metadata:{pattern:/@\w+/,alias:"function"}}),n.languages.insertBefore("dart","class-name",{generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":i,keyword:r,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})})(t)}return Hl}var Vl,OE;function xz(){if(OE)return Vl;OE=1,Vl=e,e.displayName="dataweave",e.aliases=[];function e(t){(function(n){n.languages.dataweave={url:/\b[A-Za-z]+:\/\/[\w/:.?=&-]+|\burn:[\w:.?=&-]+/,property:{pattern:/(?:\b\w+#)?(?:"(?:\\.|[^\\"\r\n])*"|\b\w+)(?=\s*[:@])/,greedy:!0},string:{pattern:/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},"mime-type":/\b(?:application|audio|image|multipart|text|video)\/[\w+-]+/,date:{pattern:/\|[\w:+-]+\|/,greedy:!0},comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],regex:{pattern:/\/(?:[^\\\/\r\n]|\\[^\r\n])+\//,greedy:!0},keyword:/\b(?:and|as|at|case|do|else|fun|if|input|is|match|not|ns|null|or|output|type|unless|update|using|var)\b/,function:/\b[A-Z_]\w*(?=\s*\()/i,number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\];(),.:@]/,operator:/<<|>>|->|[<>~=]=?|!=|--?-?|\+\+?|!|\?/,boolean:/\b(?:false|true)\b/}})(t)}return Vl}var Wl,LE;function Oz(){if(LE)return Wl;LE=1,Wl=e,e.displayName="dax",e.aliases=[];function e(t){t.languages.dax={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/).*)/,lookbehind:!0},"data-field":{pattern:/'(?:[^']|'')*'(?!')(?:\[[ \w\xA0-\uFFFF]+\])?|\w+\[[ \w\xA0-\uFFFF]+\]/,alias:"symbol"},measure:{pattern:/\[[ \w\xA0-\uFFFF]+\]/,alias:"constant"},string:{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},function:/\b(?:ABS|ACOS|ACOSH|ACOT|ACOTH|ADDCOLUMNS|ADDMISSINGITEMS|ALL|ALLCROSSFILTERED|ALLEXCEPT|ALLNOBLANKROW|ALLSELECTED|AND|APPROXIMATEDISTINCTCOUNT|ASIN|ASINH|ATAN|ATANH|AVERAGE|AVERAGEA|AVERAGEX|BETA\.DIST|BETA\.INV|BLANK|CALCULATE|CALCULATETABLE|CALENDAR|CALENDARAUTO|CEILING|CHISQ\.DIST|CHISQ\.DIST\.RT|CHISQ\.INV|CHISQ\.INV\.RT|CLOSINGBALANCEMONTH|CLOSINGBALANCEQUARTER|CLOSINGBALANCEYEAR|COALESCE|COMBIN|COMBINA|COMBINEVALUES|CONCATENATE|CONCATENATEX|CONFIDENCE\.NORM|CONFIDENCE\.T|CONTAINS|CONTAINSROW|CONTAINSSTRING|CONTAINSSTRINGEXACT|CONVERT|COS|COSH|COT|COTH|COUNT|COUNTA|COUNTAX|COUNTBLANK|COUNTROWS|COUNTX|CROSSFILTER|CROSSJOIN|CURRENCY|CURRENTGROUP|CUSTOMDATA|DATATABLE|DATE|DATEADD|DATEDIFF|DATESBETWEEN|DATESINPERIOD|DATESMTD|DATESQTD|DATESYTD|DATEVALUE|DAY|DEGREES|DETAILROWS|DISTINCT|DISTINCTCOUNT|DISTINCTCOUNTNOBLANK|DIVIDE|EARLIER|EARLIEST|EDATE|ENDOFMONTH|ENDOFQUARTER|ENDOFYEAR|EOMONTH|ERROR|EVEN|EXACT|EXCEPT|EXP|EXPON\.DIST|FACT|FALSE|FILTER|FILTERS|FIND|FIRSTDATE|FIRSTNONBLANK|FIRSTNONBLANKVALUE|FIXED|FLOOR|FORMAT|GCD|GENERATE|GENERATEALL|GENERATESERIES|GEOMEAN|GEOMEANX|GROUPBY|HASONEFILTER|HASONEVALUE|HOUR|IF|IF\.EAGER|IFERROR|IGNORE|INT|INTERSECT|ISBLANK|ISCROSSFILTERED|ISEMPTY|ISERROR|ISEVEN|ISFILTERED|ISINSCOPE|ISLOGICAL|ISNONTEXT|ISNUMBER|ISO\.CEILING|ISODD|ISONORAFTER|ISSELECTEDMEASURE|ISSUBTOTAL|ISTEXT|KEEPFILTERS|KEYWORDMATCH|LASTDATE|LASTNONBLANK|LASTNONBLANKVALUE|LCM|LEFT|LEN|LN|LOG|LOG10|LOOKUPVALUE|LOWER|MAX|MAXA|MAXX|MEDIAN|MEDIANX|MID|MIN|MINA|MINUTE|MINX|MOD|MONTH|MROUND|NATURALINNERJOIN|NATURALLEFTOUTERJOIN|NEXTDAY|NEXTMONTH|NEXTQUARTER|NEXTYEAR|NONVISUAL|NORM\.DIST|NORM\.INV|NORM\.S\.DIST|NORM\.S\.INV|NOT|NOW|ODD|OPENINGBALANCEMONTH|OPENINGBALANCEQUARTER|OPENINGBALANCEYEAR|OR|PARALLELPERIOD|PATH|PATHCONTAINS|PATHITEM|PATHITEMREVERSE|PATHLENGTH|PERCENTILE\.EXC|PERCENTILE\.INC|PERCENTILEX\.EXC|PERCENTILEX\.INC|PERMUT|PI|POISSON\.DIST|POWER|PREVIOUSDAY|PREVIOUSMONTH|PREVIOUSQUARTER|PREVIOUSYEAR|PRODUCT|PRODUCTX|QUARTER|QUOTIENT|RADIANS|RAND|RANDBETWEEN|RANK\.EQ|RANKX|RELATED|RELATEDTABLE|REMOVEFILTERS|REPLACE|REPT|RIGHT|ROLLUP|ROLLUPADDISSUBTOTAL|ROLLUPGROUP|ROLLUPISSUBTOTAL|ROUND|ROUNDDOWN|ROUNDUP|ROW|SAMEPERIODLASTYEAR|SAMPLE|SEARCH|SECOND|SELECTCOLUMNS|SELECTEDMEASURE|SELECTEDMEASUREFORMATSTRING|SELECTEDMEASURENAME|SELECTEDVALUE|SIGN|SIN|SINH|SQRT|SQRTPI|STARTOFMONTH|STARTOFQUARTER|STARTOFYEAR|STDEV\.P|STDEV\.S|STDEVX\.P|STDEVX\.S|SUBSTITUTE|SUBSTITUTEWITHINDEX|SUM|SUMMARIZE|SUMMARIZECOLUMNS|SUMX|SWITCH|T\.DIST|T\.DIST\.2T|T\.DIST\.RT|T\.INV|T\.INV\.2T|TAN|TANH|TIME|TIMEVALUE|TODAY|TOPN|TOPNPERLEVEL|TOPNSKIP|TOTALMTD|TOTALQTD|TOTALYTD|TREATAS|TRIM|TRUE|TRUNC|UNICHAR|UNICODE|UNION|UPPER|USERELATIONSHIP|USERNAME|USEROBJECTID|USERPRINCIPALNAME|UTCNOW|UTCTODAY|VALUE|VALUES|VAR\.P|VAR\.S|VARX\.P|VARX\.S|WEEKDAY|WEEKNUM|XIRR|XNPV|YEAR|YEARFRAC)(?=\s*\()/i,keyword:/\b(?:DEFINE|EVALUATE|MEASURE|ORDER\s+BY|RETURN|VAR|START\s+AT|ASC|DESC)\b/i,boolean:{pattern:/\b(?:FALSE|NULL|TRUE)\b/i,alias:"constant"},number:/\b\d+(?:\.\d*)?|\B\.\d+\b/,operator:/:=|[-+*\/=^]|&&?|\|\||<(?:=>?|<|>)?|>[>=]?|\b(?:IN|NOT)\b/i,punctuation:/[;\[\](){}`,.]/}}return Wl}var Yl,DE;function Lz(){if(DE)return Yl;DE=1,Yl=e,e.displayName="dhall",e.aliases=[];function e(t){t.languages.dhall={comment:/--.*|\{-(?:[^-{]|-(?!\})|\{(?!-)|\{-(?:[^-{]|-(?!\})|\{(?!-))*-\})*-\}/,string:{pattern:/"(?:[^"\\]|\\.)*"|''(?:[^']|'(?!')|'''|''\$\{)*''(?!'|\$)/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^{}]*\}/,inside:{expression:{pattern:/(^\$\{)[\s\S]+(?=\}$)/,lookbehind:!0,alias:"language-dhall",inside:null},punctuation:/\$\{|\}/}}}},label:{pattern:/`[^`]*`/,greedy:!0},url:{pattern:/\bhttps?:\/\/[\w.:%!$&'*+;=@~-]+(?:\/[\w.:%!$&'*+;=@~-]*)*(?:\?[/?\w.:%!$&'*+;=@~-]*)?/,greedy:!0},env:{pattern:/\benv:(?:(?!\d)\w+|"(?:[^"\\=]|\\.)*")/,greedy:!0,inside:{function:/^env/,operator:/^:/,variable:/[\s\S]+/}},hash:{pattern:/\bsha256:[\da-fA-F]{64}\b/,inside:{function:/sha256/,operator:/:/,number:/[\da-fA-F]{64}/}},keyword:/\b(?:as|assert|else|forall|if|in|let|merge|missing|then|toMap|using|with)\b|\u2200/,builtin:/\b(?:None|Some)\b/,boolean:/\b(?:False|True)\b/,number:/\bNaN\b|-?\bInfinity\b|[+-]?\b(?:0x[\da-fA-F]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/,operator:/\/\\|\/\/\\\\|&&|\|\||===|[!=]=|\/\/|->|\+\+|::|[+*#@=:?<>|\\\u2227\u2a53\u2261\u2afd\u03bb\u2192]/,punctuation:/\.\.|[{}\[\](),./]/,"class-name":/\b[A-Z]\w*\b/},t.languages.dhall.string.inside.interpolation.inside.expression.inside=t.languages.dhall}return Yl}var Kl,ME;function Dz(){if(ME)return Kl;ME=1,Kl=e,e.displayName="diff",e.aliases=[];function e(t){(function(n){n.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var r={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(r).forEach(function(a){var i=r[a],o=[];/^\w+$/.test(a)||o.push(/\w+/.exec(a)[0]),a==="diff"&&o.push("bold"),n.languages.diff[a]={pattern:RegExp("^(?:["+i+`].*(?:\r +?| +|(?![\\s\\S])))+`,"m"),alias:o,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(a)[0]}}}}),Object.defineProperty(n.languages.diff,"PREFIXES",{value:r})})(t)}return Kl}var Xl,FE;function nt(){if(FE)return Xl;FE=1,Xl=e,e.displayName="markupTemplating",e.aliases=[];function e(t){(function(n){function r(a,i){return"___"+a.toUpperCase()+i+"___"}Object.defineProperties(n.languages["markup-templating"]={},{buildPlaceholders:{value:function(a,i,o,s){if(a.language===i){var l=a.tokenStack=[];a.code=a.code.replace(o,function(u){if(typeof s=="function"&&!s(u))return u;for(var d=l.length,c;a.code.indexOf(c=r(i,d))!==-1;)++d;return l[d]=u,c}),a.grammar=n.languages.markup}}},tokenizePlaceholders:{value:function(a,i){if(a.language!==i||!a.tokenStack)return;a.grammar=n.languages[i];var o=0,s=Object.keys(a.tokenStack);function l(u){for(var d=0;d=s.length);d++){var c=u[d];if(typeof c=="string"||c.content&&typeof c.content=="string"){var f=s[o],p=a.tokenStack[f],h=typeof c=="string"?c:c.content,y=r(i,f),T=h.indexOf(y);if(T>-1){++o;var b=h.substring(0,T),g=new n.Token(i,n.tokenize(p,a.grammar),"language-"+i,p),m=h.substring(T+y.length),v=[];b&&v.push.apply(v,l([b])),v.push(g),m&&v.push.apply(v,l([m])),typeof c=="string"?u.splice.apply(u,[d,1].concat(v)):c.content=v}}else c.content&&l(c.content)}return u}l(a.tokens)}}})})(t)}return Xl}var Zl,PE;function Mz(){if(PE)return Zl;PE=1;var e=nt();Zl=t,t.displayName="django",t.aliases=["jinja2"];function t(n){n.register(e),function(r){r.languages.django={comment:/^\{#[\s\S]*?#\}$/,tag:{pattern:/(^\{%[+-]?\s*)\w+/,lookbehind:!0,alias:"keyword"},delimiter:{pattern:/^\{[{%][+-]?|[+-]?[}%]\}$/,alias:"punctuation"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},filter:{pattern:/(\|)\w+/,lookbehind:!0,alias:"function"},test:{pattern:/(\bis\s+(?:not\s+)?)(?!not\b)\w+/,lookbehind:!0,alias:"function"},function:/\b[a-z_]\w+(?=\s*\()/i,keyword:/\b(?:and|as|by|else|for|if|import|in|is|loop|not|or|recursive|with|without)\b/,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,number:/\b\d+(?:\.\d+)?\b/,boolean:/[Ff]alse|[Nn]one|[Tt]rue/,variable:/\b\w+\b/,punctuation:/[{}[\](),.:;]/};var a=/\{\{[\s\S]*?\}\}|\{%[\s\S]*?%\}|\{#[\s\S]*?#\}/g,i=r.languages["markup-templating"];r.hooks.add("before-tokenize",function(o){i.buildPlaceholders(o,"django",a)}),r.hooks.add("after-tokenize",function(o){i.tokenizePlaceholders(o,"django")}),r.languages.jinja2=r.languages.django,r.hooks.add("before-tokenize",function(o){i.buildPlaceholders(o,"jinja2",a)}),r.hooks.add("after-tokenize",function(o){i.tokenizePlaceholders(o,"jinja2")})}(n)}return Zl}var Ql,UE;function Fz(){if(UE)return Ql;UE=1,Ql=e,e.displayName="dnsZoneFile",e.aliases=[];function e(t){t.languages["dns-zone-file"]={comment:/;.*/,string:{pattern:/"(?:\\.|[^"\\\r\n])*"/,greedy:!0},variable:[{pattern:/(^\$ORIGIN[ \t]+)\S+/m,lookbehind:!0},{pattern:/(^|\s)@(?=\s|$)/,lookbehind:!0}],keyword:/^\$(?:INCLUDE|ORIGIN|TTL)(?=\s|$)/m,class:{pattern:/(^|\s)(?:CH|CS|HS|IN)(?=\s|$)/,lookbehind:!0,alias:"keyword"},type:{pattern:/(^|\s)(?:A|A6|AAAA|AFSDB|APL|ATMA|CAA|CDNSKEY|CDS|CERT|CNAME|DHCID|DLV|DNAME|DNSKEY|DS|EID|GID|GPOS|HINFO|HIP|IPSECKEY|ISDN|KEY|KX|LOC|MAILA|MAILB|MB|MD|MF|MG|MINFO|MR|MX|NAPTR|NB|NBSTAT|NIMLOC|NINFO|NS|NSAP|NSAP-PTR|NSEC|NSEC3|NSEC3PARAM|NULL|NXT|OPENPGPKEY|PTR|PX|RKEY|RP|RRSIG|RT|SIG|SINK|SMIMEA|SOA|SPF|SRV|SSHFP|TA|TKEY|TLSA|TSIG|TXT|UID|UINFO|UNSPEC|URI|WKS|X25)(?=\s|$)/,lookbehind:!0,alias:"keyword"},punctuation:/[()]/},t.languages["dns-zone"]=t.languages["dns-zone-file"]}return Ql}var Jl,BE;function Pz(){if(BE)return Jl;BE=1,Jl=e,e.displayName="docker",e.aliases=["dockerfile"];function e(t){(function(n){var r=/\\[\r\n](?:\s|\\[\r\n]|#.*(?!.))*(?![\s#]|\\[\r\n])/.source,a=/(?:[ \t]+(?![ \t])(?:)?|)/.source.replace(//g,function(){return r}),i=/"(?:[^"\\\r\n]|\\(?:\r\n|[\s\S]))*"|'(?:[^'\\\r\n]|\\(?:\r\n|[\s\S]))*'/.source,o=/--[\w-]+=(?:|(?!["'])(?:[^\s\\]|\\.)+)/.source.replace(//g,function(){return i}),s={pattern:RegExp(i),greedy:!0},l={pattern:/(^[ \t]*)#.*/m,lookbehind:!0,greedy:!0};function u(d,c){return d=d.replace(//g,function(){return o}).replace(//g,function(){return a}),RegExp(d,c)}n.languages.docker={instruction:{pattern:/(^[ \t]*)(?:ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|ONBUILD|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR)(?=\s)(?:\\.|[^\r\n\\])*(?:\\$(?:\s|#.*$)*(?![\s#])(?:\\.|[^\r\n\\])*)*/im,lookbehind:!0,greedy:!0,inside:{options:{pattern:u(/(^(?:ONBUILD)?\w+)(?:)*/.source,"i"),lookbehind:!0,greedy:!0,inside:{property:{pattern:/(^|\s)--[\w-]+/,lookbehind:!0},string:[s,{pattern:/(=)(?!["'])(?:[^\s\\]|\\.)+/,lookbehind:!0}],operator:/\\$/m,punctuation:/=/}},keyword:[{pattern:u(/(^(?:ONBUILD)?HEALTHCHECK(?:)*)(?:CMD|NONE)\b/.source,"i"),lookbehind:!0,greedy:!0},{pattern:u(/(^(?:ONBUILD)?FROM(?:)*(?!--)[^ \t\\]+)AS/.source,"i"),lookbehind:!0,greedy:!0},{pattern:u(/(^ONBUILD)\w+/.source,"i"),lookbehind:!0,greedy:!0},{pattern:/^\w+/,greedy:!0}],comment:l,string:s,variable:/\$(?:\w+|\{[^{}"'\\]*\})/,operator:/\\$/m}},comment:l},n.languages.dockerfile=n.languages.docker})(t)}return Jl}var eu,$E;function Uz(){if($E)return eu;$E=1,eu=e,e.displayName="dot",e.aliases=["gv"];function e(t){(function(n){var r="(?:"+[/[a-zA-Z_\x80-\uFFFF][\w\x80-\uFFFF]*/.source,/-?(?:\.\d+|\d+(?:\.\d*)?)/.source,/"[^"\\]*(?:\\[\s\S][^"\\]*)*"/.source,/<(?:[^<>]|(?!)*>/.source].join("|")+")",a={markup:{pattern:/(^<)[\s\S]+(?=>$)/,lookbehind:!0,alias:["language-markup","language-html","language-xml"],inside:n.languages.markup}};function i(o,s){return RegExp(o.replace(//g,function(){return r}),s)}n.languages.dot={comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\/|^#.*/m,greedy:!0},"graph-name":{pattern:i(/(\b(?:digraph|graph|subgraph)[ \t\r\n]+)/.source,"i"),lookbehind:!0,greedy:!0,alias:"class-name",inside:a},"attr-value":{pattern:i(/(=[ \t\r\n]*)/.source),lookbehind:!0,greedy:!0,inside:a},"attr-name":{pattern:i(/([\[;, \t\r\n])(?=[ \t\r\n]*=)/.source),lookbehind:!0,greedy:!0,inside:a},keyword:/\b(?:digraph|edge|graph|node|strict|subgraph)\b/i,"compass-point":{pattern:/(:[ \t\r\n]*)(?:[ewc_]|[ns][ew]?)(?![\w\x80-\uFFFF])/,lookbehind:!0,alias:"builtin"},node:{pattern:i(/(^|[^-.\w\x80-\uFFFF\\])/.source),lookbehind:!0,greedy:!0,inside:a},operator:/[=:]|-[->]/,punctuation:/[\[\]{};,]/},n.languages.gv=n.languages.dot})(t)}return eu}var tu,zE;function Bz(){if(zE)return tu;zE=1,tu=e,e.displayName="ebnf",e.aliases=[];function e(t){t.languages.ebnf={comment:/\(\*[\s\S]*?\*\)/,string:{pattern:/"[^"\r\n]*"|'[^'\r\n]*'/,greedy:!0},special:{pattern:/\?[^?\r\n]*\?/,greedy:!0,alias:"class-name"},definition:{pattern:/^([\t ]*)[a-z]\w*(?:[ \t]+[a-z]\w*)*(?=\s*=)/im,lookbehind:!0,alias:["rule","keyword"]},rule:/\b[a-z]\w*(?:[ \t]+[a-z]\w*)*\b/i,punctuation:/\([:/]|[:/]\)|[.,;()[\]{}]/,operator:/[-=|*/!]/}}return tu}var nu,GE;function $z(){if(GE)return nu;GE=1,nu=e,e.displayName="editorconfig",e.aliases=[];function e(t){t.languages.editorconfig={comment:/[;#].*/,section:{pattern:/(^[ \t]*)\[.+\]/m,lookbehind:!0,alias:"selector",inside:{regex:/\\\\[\[\]{},!?.*]/,operator:/[!?]|\.\.|\*{1,2}/,punctuation:/[\[\]{},]/}},key:{pattern:/(^[ \t]*)[^\s=]+(?=[ \t]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/=.*/,alias:"attr-value",inside:{punctuation:/^=/}}}}return nu}var ru,qE;function zz(){if(qE)return ru;qE=1,ru=e,e.displayName="eiffel",e.aliases=[];function e(t){t.languages.eiffel={comment:/--.*/,string:[{pattern:/"([^[]*)\[[\s\S]*?\]\1"/,greedy:!0},{pattern:/"([^{]*)\{[\s\S]*?\}\1"/,greedy:!0},{pattern:/"(?:%(?:(?!\n)\s)*\n\s*%|%\S|[^%"\r\n])*"/,greedy:!0}],char:/'(?:%.|[^%'\r\n])+'/,keyword:/\b(?:across|agent|alias|all|and|as|assign|attached|attribute|check|class|convert|create|Current|debug|deferred|detachable|do|else|elseif|end|ensure|expanded|export|external|feature|from|frozen|if|implies|inherit|inspect|invariant|like|local|loop|not|note|obsolete|old|once|or|Precursor|redefine|rename|require|rescue|Result|retry|select|separate|some|then|undefine|until|variant|Void|when|xor)\b/i,boolean:/\b(?:False|True)\b/i,"class-name":/\b[A-Z][\dA-Z_]*\b/,number:[/\b0[xcb][\da-f](?:_*[\da-f])*\b/i,/(?:\b\d(?:_*\d)*)?\.(?:(?:\d(?:_*\d)*)?e[+-]?)?\d(?:_*\d)*\b|\b\d(?:_*\d)*\b\.?/i],punctuation:/:=|<<|>>|\(\||\|\)|->|\.(?=\w)|[{}[\];(),:?]/,operator:/\\\\|\|\.\.\||\.\.|\/[~\/=]?|[><]=?|[-+*^=~]/}}return ru}var au,jE;function Gz(){if(jE)return au;jE=1;var e=nt();au=t,t.displayName="ejs",t.aliases=["eta"];function t(n){n.register(e),function(r){r.languages.ejs={delimiter:{pattern:/^<%[-_=]?|[-_]?%>$/,alias:"punctuation"},comment:/^#[\s\S]*/,"language-javascript":{pattern:/[\s\S]+/,inside:r.languages.javascript}},r.hooks.add("before-tokenize",function(a){var i=/<%(?!%)[\s\S]+?%>/g;r.languages["markup-templating"].buildPlaceholders(a,"ejs",i)}),r.hooks.add("after-tokenize",function(a){r.languages["markup-templating"].tokenizePlaceholders(a,"ejs")}),r.languages.eta=r.languages.ejs}(n)}return au}var iu,HE;function qz(){if(HE)return iu;HE=1,iu=e,e.displayName="elixir",e.aliases=[];function e(t){t.languages.elixir={doc:{pattern:/@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/,inside:{attribute:/^@\w+/,string:/['"][\s\S]+/}},comment:{pattern:/#.*/,greedy:!0},regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|#(?!\{)|[^#\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},module:{pattern:/\b[A-Z]\w*\b/,alias:"class-name"},"attr-name":/\b\w+\??:(?!:)/,argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},function:/\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d))/,number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|delegate|exception|impl|macro|module|n|np|p|protocol|struct)?|do|else|end|fn|for|if|import|not|or|quote|raise|require|rescue|try|unless|unquote|use|when)\b/,boolean:/\b(?:false|nil|true)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},t.languages.elixir.string.forEach(function(n){n.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:t.languages.elixir}}}})}return iu}var ou,VE;function jz(){if(VE)return ou;VE=1,ou=e,e.displayName="elm",e.aliases=[];function e(t){t.languages.elm={comment:/--.*|\{-[\s\S]*?-\}/,char:{pattern:/'(?:[^\\'\r\n]|\\(?:[abfnrtv\\']|\d+|x[0-9a-fA-F]+|u\{[0-9a-fA-F]+\}))'/,greedy:!0},string:[{pattern:/"""[\s\S]*?"""/,greedy:!0},{pattern:/"(?:[^\\"\r\n]|\\.)*"/,greedy:!0}],"import-statement":{pattern:/(^[\t ]*)import\s+[A-Z]\w*(?:\.[A-Z]\w*)*(?:\s+as\s+(?:[A-Z]\w*)(?:\.[A-Z]\w*)*)?(?:\s+exposing\s+)?/m,lookbehind:!0,inside:{keyword:/\b(?:as|exposing|import)\b/}},keyword:/\b(?:alias|as|case|else|exposing|if|in|infixl|infixr|let|module|of|then|type)\b/,builtin:/\b(?:abs|acos|always|asin|atan|atan2|ceiling|clamp|compare|cos|curry|degrees|e|flip|floor|fromPolar|identity|isInfinite|isNaN|logBase|max|min|negate|never|not|pi|radians|rem|round|sin|sqrt|tan|toFloat|toPolar|toString|truncate|turns|uncurry|xor)\b/,number:/\b(?:\d+(?:\.\d+)?(?:e[+-]?\d+)?|0x[0-9a-f]+)\b/i,operator:/\s\.\s|[+\-/*=.$<>:&|^?%#@~!]{2,}|[+\-/*=$<>:&|^?%#@~!]/,hvariable:/\b(?:[A-Z]\w*\.)*[a-z]\w*\b/,constant:/\b(?:[A-Z]\w*\.)*[A-Z]\w*\b/,punctuation:/[{}[\]|(),.:]/}}return ou}var su,WE;function Hz(){if(WE)return su;WE=1;var e=Zo(),t=nt();su=n,n.displayName="erb",n.aliases=[];function n(r){r.register(e),r.register(t),function(a){a.languages.erb={delimiter:{pattern:/^(\s*)<%=?|%>(?=\s*$)/,lookbehind:!0,alias:"punctuation"},ruby:{pattern:/\s*\S[\s\S]*/,alias:"language-ruby",inside:a.languages.ruby}},a.hooks.add("before-tokenize",function(i){var o=/<%=?(?:[^\r\n]|[\r\n](?!=begin)|[\r\n]=begin\s(?:[^\r\n]|[\r\n](?!=end))*[\r\n]=end)+?%>/g;a.languages["markup-templating"].buildPlaceholders(i,"erb",o)}),a.hooks.add("after-tokenize",function(i){a.languages["markup-templating"].tokenizePlaceholders(i,"erb")})}(r)}return su}var lu,YE;function Vz(){if(YE)return lu;YE=1,lu=e,e.displayName="erlang",e.aliases=[];function e(t){t.languages.erlang={comment:/%.+/,string:{pattern:/"(?:\\.|[^\\"\r\n])*"/,greedy:!0},"quoted-function":{pattern:/'(?:\\.|[^\\'\r\n])+'(?=\()/,alias:"function"},"quoted-atom":{pattern:/'(?:\\.|[^\\'\r\n])+'/,alias:"atom"},boolean:/\b(?:false|true)\b/,keyword:/\b(?:after|case|catch|end|fun|if|of|receive|try|when)\b/,number:[/\$\\?./,/\b\d+#[a-z0-9]+/i,/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i],function:/\b[a-z][\w@]*(?=\()/,variable:{pattern:/(^|[^@])(?:\b|\?)[A-Z_][\w@]*/,lookbehind:!0},operator:[/[=\/<>:]=|=[:\/]=|\+\+?|--?|[=*\/!]|\b(?:and|andalso|band|bnot|bor|bsl|bsr|bxor|div|not|or|orelse|rem|xor)\b/,{pattern:/(^|[^<])<(?!<)/,lookbehind:!0},{pattern:/(^|[^>])>(?!>)/,lookbehind:!0}],atom:/\b[a-z][\w@]*/,punctuation:/[()[\]{}:;,.#|]|<<|>>/}}return lu}var uu,KE;function jR(){if(KE)return uu;KE=1,uu=e,e.displayName="lua",e.aliases=[];function e(t){t.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[^z]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+(?:\.[a-f\d]*)?(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|(?:\.\d*)?(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}}return uu}var cu,XE;function Wz(){if(XE)return cu;XE=1;var e=jR(),t=nt();cu=n,n.displayName="etlua",n.aliases=[];function n(r){r.register(e),r.register(t),function(a){a.languages.etlua={delimiter:{pattern:/^<%[-=]?|-?%>$/,alias:"punctuation"},"language-lua":{pattern:/[\s\S]+/,inside:a.languages.lua}},a.hooks.add("before-tokenize",function(i){var o=/<%[\s\S]+?%>/g;a.languages["markup-templating"].buildPlaceholders(i,"etlua",o)}),a.hooks.add("after-tokenize",function(i){a.languages["markup-templating"].tokenizePlaceholders(i,"etlua")})}(r)}return cu}var du,ZE;function Yz(){if(ZE)return du;ZE=1,du=e,e.displayName="excelFormula",e.aliases=[];function e(t){t.languages["excel-formula"]={comment:{pattern:/(\bN\(\s*)"(?:[^"]|"")*"(?=\s*\))/i,lookbehind:!0,greedy:!0},string:{pattern:/"(?:[^"]|"")*"(?!")/,greedy:!0},reference:{pattern:/(?:'[^']*'|(?:[^\s()[\]{}<>*?"';,$&]*\[[^^\s()[\]{}<>*?"']+\])?\w+)!/,greedy:!0,alias:"string",inside:{operator:/!$/,punctuation:/'/,sheet:{pattern:/[^[\]]+$/,alias:"function"},file:{pattern:/\[[^[\]]+\]$/,inside:{punctuation:/[[\]]/}},path:/[\s\S]+/}},"function-name":{pattern:/\b[A-Z]\w*(?=\()/i,alias:"keyword"},range:{pattern:/\$?\b(?:[A-Z]+\$?\d+:\$?[A-Z]+\$?\d+|[A-Z]+:\$?[A-Z]+|\d+:\$?\d+)\b/i,alias:"property",inside:{operator:/:/,cell:/\$?[A-Z]+\$?\d+/i,column:/\$?[A-Z]+/i,row:/\$?\d+/}},cell:{pattern:/\b[A-Z]+\d+\b|\$[A-Za-z]+\$?\d+\b|\b[A-Za-z]+\$\d+\b/,alias:"property"},number:/(?:\b\d+(?:\.\d+)?|\B\.\d+)(?:e[+-]?\d+)?\b/i,boolean:/\b(?:FALSE|TRUE)\b/i,operator:/[-+*/^%=&,]|<[=>]?|>=?/,punctuation:/[[\]();{}|]/},t.languages.xlsx=t.languages.xls=t.languages["excel-formula"]}return du}var pu,QE;function Kz(){if(QE)return pu;QE=1,pu=e,e.displayName="factor",e.aliases=[];function e(t){(function(n){var r={function:/\b(?:BUGS?|FIX(?:MES?)?|NOTES?|TODOS?|XX+|HACKS?|WARN(?:ING)?|\?{2,}|!{2,})\b/},a={number:/\\[^\s']|%\w/},i={comment:[{pattern:/(^|\s)(?:! .*|!$)/,lookbehind:!0,inside:r},{pattern:/(^|\s)\/\*\s[\s\S]*?\*\/(?=\s|$)/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|\s)!\[(={0,6})\[\s[\s\S]*?\]\2\](?=\s|$)/,lookbehind:!0,greedy:!0,inside:r}],number:[{pattern:/(^|\s)[+-]?\d+(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)[+-]?0(?:b[01]+|o[0-7]+|d\d+|x[\dA-F]+)(?=\s|$)/i,lookbehind:!0},{pattern:/(^|\s)[+-]?\d+\/\d+\.?(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)\+?\d+\+\d+\/\d+(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)-\d+-\d+\/\d+(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)[+-]?(?:\d*\.\d+|\d+\.\d*|\d+)(?:e[+-]?\d+)?(?=\s|$)/i,lookbehind:!0},{pattern:/(^|\s)NAN:\s+[\da-fA-F]+(?=\s|$)/,lookbehind:!0},{pattern:/(^|\s)[+-]?0(?:b1\.[01]*|o1\.[0-7]*|d1\.\d*|x1\.[\dA-F]*)p\d+(?=\s|$)/i,lookbehind:!0}],regexp:{pattern:/(^|\s)R\/\s(?:\\\S|[^\\/])*\/(?:[idmsr]*|[idmsr]+-[idmsr]+)(?=\s|$)/,lookbehind:!0,alias:"number",inside:{variable:/\\\S/,keyword:/[+?*\[\]^$(){}.|]/,operator:{pattern:/(\/)[idmsr]+(?:-[idmsr]+)?/,lookbehind:!0}}},boolean:{pattern:/(^|\s)[tf](?=\s|$)/,lookbehind:!0},"custom-string":{pattern:/(^|\s)[A-Z0-9\-]+"\s(?:\\\S|[^"\\])*"/,lookbehind:!0,greedy:!0,alias:"string",inside:{number:/\\\S|%\w|\//}},"multiline-string":[{pattern:/(^|\s)STRING:\s+\S+(?:\n|\r\n).*(?:\n|\r\n)\s*;(?=\s|$)/,lookbehind:!0,greedy:!0,alias:"string",inside:{number:a.number,"semicolon-or-setlocal":{pattern:/([\r\n][ \t]*);(?=\s|$)/,lookbehind:!0,alias:"function"}}},{pattern:/(^|\s)HEREDOC:\s+\S+(?:\n|\r\n).*(?:\n|\r\n)\s*\S+(?=\s|$)/,lookbehind:!0,greedy:!0,alias:"string",inside:a},{pattern:/(^|\s)\[(={0,6})\[\s[\s\S]*?\]\2\](?=\s|$)/,lookbehind:!0,greedy:!0,alias:"string",inside:a}],"special-using":{pattern:/(^|\s)USING:(?:\s\S+)*(?=\s+;(?:\s|$))/,lookbehind:!0,alias:"function",inside:{string:{pattern:/(\s)[^:\s]+/,lookbehind:!0}}},"stack-effect-delimiter":[{pattern:/(^|\s)(?:call|eval|execute)?\((?=\s)/,lookbehind:!0,alias:"operator"},{pattern:/(\s)--(?=\s)/,lookbehind:!0,alias:"operator"},{pattern:/(\s)\)(?=\s|$)/,lookbehind:!0,alias:"operator"}],combinators:{pattern:null,lookbehind:!0,alias:"keyword"},"kernel-builtin":{pattern:null,lookbehind:!0,alias:"variable"},"sequences-builtin":{pattern:null,lookbehind:!0,alias:"variable"},"math-builtin":{pattern:null,lookbehind:!0,alias:"variable"},"constructor-word":{pattern:/(^|\s)<(?!=+>|-+>)\S+>(?=\s|$)/,lookbehind:!0,alias:"keyword"},"other-builtin-syntax":{pattern:null,lookbehind:!0,alias:"operator"},"conventionally-named-word":{pattern:/(^|\s)(?!")(?:(?:change|new|set|with)-\S+|\$\S+|>[^>\s]+|[^:>\s]+>|[^>\s]+>[^>\s]+|\+[^+\s]+\+|[^?\s]+\?|\?[^?\s]+|[^>\s]+>>|>>[^>\s]+|[^<\s]+<<|\([^()\s]+\)|[^!\s]+!|[^*\s]\S*\*|[^.\s]\S*\.)(?=\s|$)/,lookbehind:!0,alias:"keyword"},"colon-syntax":{pattern:/(^|\s)(?:[A-Z0-9\-]+#?)?:{1,2}\s+(?:;\S+|(?!;)\S+)(?=\s|$)/,lookbehind:!0,greedy:!0,alias:"function"},"semicolon-or-setlocal":{pattern:/(\s)(?:;|:>)(?=\s|$)/,lookbehind:!0,alias:"function"},"curly-brace-literal-delimiter":[{pattern:/(^|\s)[a-z]*\{(?=\s)/i,lookbehind:!0,alias:"operator"},{pattern:/(\s)\}(?=\s|$)/,lookbehind:!0,alias:"operator"}],"quotation-delimiter":[{pattern:/(^|\s)\[(?=\s)/,lookbehind:!0,alias:"operator"},{pattern:/(\s)\](?=\s|$)/,lookbehind:!0,alias:"operator"}],"normal-word":{pattern:/(^|\s)[^"\s]\S*(?=\s|$)/,lookbehind:!0},string:{pattern:/"(?:\\\S|[^"\\])*"/,greedy:!0,inside:a}},o=function(d){return(d+"").replace(/([.?*+\^$\[\]\\(){}|\-])/g,"\\$1")},s=function(d){return new RegExp("(^|\\s)(?:"+d.map(o).join("|")+")(?=\\s|$)")},l={"kernel-builtin":["or","2nipd","4drop","tuck","wrapper","nip","wrapper?","callstack>array","die","dupd","callstack","callstack?","3dup","hashcode","pick","4nip","build",">boolean","nipd","clone","5nip","eq?","?","=","swapd","2over","clear","2dup","get-retainstack","not","tuple?","dup","3nipd","call","-rotd","object","drop","assert=","assert?","-rot","execute","boa","get-callstack","curried?","3drop","pickd","overd","over","roll","3nip","swap","and","2nip","rotd","throw","(clone)","hashcode*","spin","reach","4dup","equal?","get-datastack","assert","2drop","","boolean?","identity-hashcode","identity-tuple?","null","composed?","new","5drop","rot","-roll","xor","identity-tuple","boolean"],"other-builtin-syntax":["=======","recursive","flushable",">>","<<<<<<","M\\","B","PRIVATE>","\\","======","final","inline","delimiter","deprecated",">>>>>","<<<<<<<","parse-complex","malformed-complex","read-only",">>>>>>>","call-next-method","<<","foldable","$","$[","${"],"sequences-builtin":["member-eq?","mismatch","append","assert-sequence=","longer","repetition","clone-like","3sequence","assert-sequence?","last-index-from","reversed","index-from","cut*","pad-tail","join-as","remove-eq!","concat-as","but-last","snip","nths","nth","sequence","longest","slice?","","remove-nth","tail-slice","empty?","tail*","member?","virtual-sequence?","set-length","drop-prefix","iota","unclip","bounds-error?","unclip-last-slice","non-negative-integer-expected","non-negative-integer-expected?","midpoint@","longer?","?set-nth","?first","rest-slice","prepend-as","prepend","fourth","sift","subseq-start","new-sequence","?last","like","first4","1sequence","reverse","slice","virtual@","repetition?","set-last","index","4sequence","max-length","set-second","immutable-sequence","first2","first3","supremum","unclip-slice","suffix!","insert-nth","tail","3append","short","suffix","concat","flip","immutable?","reverse!","2sequence","sum","delete-all","indices","snip-slice","","check-slice","sequence?","head","append-as","halves","sequence=","collapse-slice","?second","slice-error?","product","bounds-check?","bounds-check","immutable","virtual-exemplar","harvest","remove","pad-head","last","set-fourth","cartesian-product","remove-eq","shorten","shorter","reversed?","shorter?","shortest","head-slice","pop*","tail-slice*","but-last-slice","iota?","append!","cut-slice","new-resizable","head-slice*","sequence-hashcode","pop","set-nth","?nth","second","join","immutable-sequence?","","3append-as","virtual-sequence","subseq?","remove-nth!","length","last-index","lengthen","assert-sequence","copy","move","third","first","tail?","set-first","prefix","bounds-error","","exchange","surround","cut","min-length","set-third","push-all","head?","subseq-start-from","delete-slice","rest","sum-lengths","head*","infimum","remove!","glue","slice-error","subseq","push","replace-slice","subseq-as","unclip-last"],"math-builtin":["number=","next-power-of-2","?1+","fp-special?","imaginary-part","float>bits","number?","fp-infinity?","bignum?","fp-snan?","denominator","gcd","*","+","fp-bitwise=","-","u>=","/",">=","bitand","power-of-2?","log2-expects-positive","neg?","<","log2",">","integer?","number","bits>double","2/","zero?","bits>float","float?","shift","ratio?","rect>","even?","ratio","fp-sign","bitnot",">fixnum","complex?","/i","integer>fixnum","/f","sgn",">bignum","next-float","u<","u>","mod","recip","rational",">float","2^","integer","fixnum?","neg","fixnum","sq","bignum",">rect","bit?","fp-qnan?","simple-gcd","complex","","real",">fraction","double>bits","bitor","rem","fp-nan-payload","real-part","log2-expects-positive?","prev-float","align","unordered?","float","fp-nan?","abs","bitxor","integer>fixnum-strict","u<=","odd?","<=","/mod",">integer","real?","rational?","numerator"]};Object.keys(l).forEach(function(d){i[d].pattern=s(l[d])});var u=["2bi","while","2tri","bi*","4dip","both?","same?","tri@","curry","prepose","3bi","?if","tri*","2keep","3keep","curried","2keepd","when","2bi*","2tri*","4keep","bi@","keepdd","do","unless*","tri-curry","if*","loop","bi-curry*","when*","2bi@","2tri@","with","2with","either?","bi","until","3dip","3curry","tri-curry*","tri-curry@","bi-curry","keepd","compose","2dip","if","3tri","unless","tuple","keep","2curry","tri","most","while*","dip","composed","bi-curry@","find-last-from","trim-head-slice","map-as","each-from","none?","trim-tail","partition","if-empty","accumulate*","reject!","find-from","accumulate-as","collector-for-as","reject","map","map-sum","accumulate!","2each-from","follow","supremum-by","map!","unless-empty","collector","padding","reduce-index","replicate-as","infimum-by","trim-tail-slice","count","find-index","filter","accumulate*!","reject-as","map-integers","map-find","reduce","selector","interleave","2map","filter-as","binary-reduce","map-index-as","find","produce","filter!","replicate","cartesian-map","cartesian-each","find-index-from","map-find-last","3map-as","3map","find-last","selector-as","2map-as","2map-reduce","accumulate","each","each-index","accumulate*-as","when-empty","all?","collector-as","push-either","new-like","collector-for","2selector","push-if","2all?","map-reduce","3each","any?","trim-slice","2reduce","change-nth","produce-as","2each","trim","trim-head","cartesian-find","map-index","if-zero","each-integer","unless-zero","(find-integer)","when-zero","find-last-integer","(all-integers?)","times","(each-integer)","find-integer","all-integers?","unless-negative","if-positive","when-positive","when-negative","unless-positive","if-negative","case","2cleave","cond>quot","case>quot","3cleave","wrong-values","to-fixed-point","alist>quot","cond","cleave","call-effect","recursive-hashcode","spread","deep-spread>quot","2||","0||","n||","0&&","2&&","3||","1||","1&&","n&&","3&&","smart-unless*","keep-inputs","reduce-outputs","smart-when*","cleave>array","smart-with","smart-apply","smart-if","inputs/outputs","output>sequence-n","map-outputs","map-reduce-outputs","dropping","output>array","smart-map-reduce","smart-2map-reduce","output>array-n","nullary","inputsequence"];i.combinators.pattern=s(u),n.languages.factor=i})(t)}return pu}var fu,JE;function Xz(){if(JE)return fu;JE=1,fu=e,e.displayName="$false",e.aliases=[];function e(t){(function(n){n.languages.false={comment:{pattern:/\{[^}]*\}/},string:{pattern:/"[^"]*"/,greedy:!0},"character-code":{pattern:/'(?:[^\r]|\r\n?)/,alias:"number"},"assembler-code":{pattern:/\d+`/,alias:"important"},number:/\d+/,operator:/[-!#$%&'*+,./:;=>?@\\^_`|~ßø]/,punctuation:/\[|\]/,variable:/[a-z]/,"non-standard":{pattern:/[()!=]=?|[-+*/%]|\b(?:in|is)\b/}),delete t.languages["firestore-security-rules"]["class-name"],t.languages.insertBefore("firestore-security-rules","keyword",{path:{pattern:/(^|[\s(),])(?:\/(?:[\w\xA0-\uFFFF]+|\{[\w\xA0-\uFFFF]+(?:=\*\*)?\}|\$\([\w\xA0-\uFFFF.]+\)))+/,lookbehind:!0,greedy:!0,inside:{variable:{pattern:/\{[\w\xA0-\uFFFF]+(?:=\*\*)?\}|\$\([\w\xA0-\uFFFF.]+\)/,inside:{operator:/=/,keyword:/\*\*/,punctuation:/[.$(){}]/}},punctuation:/\//}},method:{pattern:/(\ballow\s+)[a-z]+(?:\s*,\s*[a-z]+)*(?=\s*[:;])/,lookbehind:!0,alias:"builtin",inside:{punctuation:/,/}}})}return gu}var mu,tS;function Qz(){if(tS)return mu;tS=1,mu=e,e.displayName="flow",e.aliases=[];function e(t){(function(n){n.languages.flow=n.languages.extend("javascript",{}),n.languages.insertBefore("flow","keyword",{type:[{pattern:/\b(?:[Bb]oolean|Function|[Nn]umber|[Ss]tring|any|mixed|null|void)\b/,alias:"tag"}]}),n.languages.flow["function-variable"].pattern=/(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=\s*(?:function\b|(?:\([^()]*\)(?:\s*:\s*\w+)?|(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/i,delete n.languages.flow.parameter,n.languages.insertBefore("flow","operator",{"flow-punctuation":{pattern:/\{\||\|\}/,alias:"punctuation"}}),Array.isArray(n.languages.flow.keyword)||(n.languages.flow.keyword=[n.languages.flow.keyword]),n.languages.flow.keyword.unshift({pattern:/(^|[^$]\b)(?:Class|declare|opaque|type)\b(?!\$)/,lookbehind:!0},{pattern:/(^|[^$]\B)\$(?:Diff|Enum|Exact|Keys|ObjMap|PropertyType|Record|Shape|Subtype|Supertype|await)\b(?!\$)/,lookbehind:!0})})(t)}return mu}var hu,nS;function Jz(){if(nS)return hu;nS=1,hu=e,e.displayName="fortran",e.aliases=[];function e(t){t.languages.fortran={"quoted-number":{pattern:/[BOZ](['"])[A-F0-9]+\1/i,alias:"number"},string:{pattern:/(?:\b\w+_)?(['"])(?:\1\1|&(?:\r\n?|\n)(?:[ \t]*!.*(?:\r\n?|\n)|(?![ \t]*!))|(?!\1).)*(?:\1|&)/,inside:{comment:{pattern:/(&(?:\r\n?|\n)\s*)!.*/,lookbehind:!0}}},comment:{pattern:/!.*/,greedy:!0},boolean:/\.(?:FALSE|TRUE)\.(?:_\w+)?/i,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[ED][+-]?\d+)?(?:_\w+)?/i,keyword:[/\b(?:CHARACTER|COMPLEX|DOUBLE ?PRECISION|INTEGER|LOGICAL|REAL)\b/i,/\b(?:END ?)?(?:BLOCK ?DATA|DO|FILE|FORALL|FUNCTION|IF|INTERFACE|MODULE(?! PROCEDURE)|PROGRAM|SELECT|SUBROUTINE|TYPE|WHERE)\b/i,/\b(?:ALLOCATABLE|ALLOCATE|BACKSPACE|CALL|CASE|CLOSE|COMMON|CONTAINS|CONTINUE|CYCLE|DATA|DEALLOCATE|DIMENSION|DO|END|EQUIVALENCE|EXIT|EXTERNAL|FORMAT|GO ?TO|IMPLICIT(?: NONE)?|INQUIRE|INTENT|INTRINSIC|MODULE PROCEDURE|NAMELIST|NULLIFY|OPEN|OPTIONAL|PARAMETER|POINTER|PRINT|PRIVATE|PUBLIC|READ|RETURN|REWIND|SAVE|SELECT|STOP|TARGET|WHILE|WRITE)\b/i,/\b(?:ASSIGNMENT|DEFAULT|ELEMENTAL|ELSE|ELSEIF|ELSEWHERE|ENTRY|IN|INCLUDE|INOUT|KIND|NULL|ONLY|OPERATOR|OUT|PURE|RECURSIVE|RESULT|SEQUENCE|STAT|THEN|USE)\b/i],operator:[/\*\*|\/\/|=>|[=\/]=|[<>]=?|::|[+\-*=%]|\.[A-Z]+\./i,{pattern:/(^|(?!\().)\/(?!\))/,lookbehind:!0}],punctuation:/\(\/|\/\)|[(),;:&]/}}return hu}var bu,rS;function eG(){if(rS)return bu;rS=1,bu=e,e.displayName="fsharp",e.aliases=[];function e(t){t.languages.fsharp=t.languages.extend("clike",{comment:[{pattern:/(^|[^\\])\(\*(?!\))[\s\S]*?\*\)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(?:"""[\s\S]*?"""|@"(?:""|[^"])*"|"(?:\\[\s\S]|[^\\"])*")B?/,greedy:!0},"class-name":{pattern:/(\b(?:exception|inherit|interface|new|of|type)\s+|\w\s*:\s*|\s:\??>\s*)[.\w]+\b(?:\s*(?:->|\*)\s*[.\w]+\b)*(?!\s*[:.])/,lookbehind:!0,inside:{operator:/->|\*/,punctuation:/\./}},keyword:/\b(?:let|return|use|yield)(?:!\B|\b)|\b(?:abstract|and|as|asr|assert|atomic|base|begin|break|checked|class|component|const|constraint|constructor|continue|default|delegate|do|done|downcast|downto|eager|elif|else|end|event|exception|extern|external|false|finally|fixed|for|fun|function|functor|global|if|in|include|inherit|inline|interface|internal|land|lazy|lor|lsl|lsr|lxor|match|member|method|mixin|mod|module|mutable|namespace|new|not|null|object|of|open|or|override|parallel|private|process|protected|public|pure|rec|sealed|select|sig|static|struct|tailcall|then|to|trait|true|try|type|upcast|val|virtual|void|volatile|when|while|with)\b/,number:[/\b0x[\da-fA-F]+(?:LF|lf|un)?\b/,/\b0b[01]+(?:uy|y)?\b/,/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[fm]|e[+-]?\d+)?\b/i,/\b\d+(?:[IlLsy]|UL|u[lsy]?)?\b/],operator:/([<>~&^])\1\1|([*.:<>&])\2|<-|->|[!=:]=|?|\??(?:<=|>=|<>|[-+*/%=<>])\??|[!?^&]|~[+~-]|:>|:\?>?/}),t.languages.insertBefore("fsharp","keyword",{preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(^#)\b(?:else|endif|if|light|line|nowarn)\b/,lookbehind:!0,alias:"keyword"}}}}),t.languages.insertBefore("fsharp","punctuation",{"computation-expression":{pattern:/\b[_a-z]\w*(?=\s*\{)/i,alias:"keyword"}}),t.languages.insertBefore("fsharp","string",{annotation:{pattern:/\[<.+?>\]/,greedy:!0,inside:{punctuation:/^\[<|>\]$/,"class-name":{pattern:/^\w+$|(^|;\s*)[A-Z]\w*(?=\()/,lookbehind:!0},"annotation-content":{pattern:/[\s\S]+/,inside:t.languages.fsharp}}},char:{pattern:/'(?:[^\\']|\\(?:.|\d{3}|x[a-fA-F\d]{2}|u[a-fA-F\d]{4}|U[a-fA-F\d]{8}))'B?/,greedy:!0}})}return bu}var yu,aS;function tG(){if(aS)return yu;aS=1;var e=nt();yu=t,t.displayName="ftl",t.aliases=[];function t(n){n.register(e),function(r){for(var a=/[^<()"']|\((?:)*\)|<(?!#--)|<#--(?:[^-]|-(?!->))*-->|"(?:[^\\"]|\\.)*"|'(?:[^\\']|\\.)*'/.source,i=0;i<2;i++)a=a.replace(//g,function(){return a});a=a.replace(//g,/[^\s\S]/.source);var o={comment:/<#--[\s\S]*?-->/,string:[{pattern:/\br("|')(?:(?!\1)[^\\]|\\.)*\1/,greedy:!0},{pattern:RegExp(/("|')(?:(?!\1|\$\{)[^\\]|\\.|\$\{(?:(?!\})(?:))*\})*\1/.source.replace(//g,function(){return a})),greedy:!0,inside:{interpolation:{pattern:RegExp(/((?:^|[^\\])(?:\\\\)*)\$\{(?:(?!\})(?:))*\}/.source.replace(//g,function(){return a})),lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:null}}}}],keyword:/\b(?:as)\b/,boolean:/\b(?:false|true)\b/,"builtin-function":{pattern:/((?:^|[^?])\?\s*)\w+/,lookbehind:!0,alias:"function"},function:/\b\w+(?=\s*\()/,number:/\b\d+(?:\.\d+)?\b/,operator:/\.\.[<*!]?|->|--|\+\+|&&|\|\||\?{1,2}|[-+*/%!=<>]=?|\b(?:gt|gte|lt|lte)\b/,punctuation:/[,;.:()[\]{}]/};o.string[1].inside.interpolation.inside.rest=o,r.languages.ftl={"ftl-comment":{pattern:/^<#--[\s\S]*/,alias:"comment"},"ftl-directive":{pattern:/^<[\s\S]+>$/,inside:{directive:{pattern:/(^<\/?)[#@][a-z]\w*/i,lookbehind:!0,alias:"keyword"},punctuation:/^<\/?|\/?>$/,content:{pattern:/\s*\S[\s\S]*/,alias:"ftl",inside:o}}},"ftl-interpolation":{pattern:/^\$\{[\s\S]*\}$/,inside:{punctuation:/^\$\{|\}$/,content:{pattern:/\s*\S[\s\S]*/,alias:"ftl",inside:o}}}},r.hooks.add("before-tokenize",function(s){var l=RegExp(/<#--[\s\S]*?-->|<\/?[#@][a-zA-Z](?:)*?>|\$\{(?:)*?\}/.source.replace(//g,function(){return a}),"gi");r.languages["markup-templating"].buildPlaceholders(s,"ftl",l)}),r.hooks.add("after-tokenize",function(s){r.languages["markup-templating"].tokenizePlaceholders(s,"ftl")})}(n)}return yu}var Eu,iS;function nG(){if(iS)return Eu;iS=1,Eu=e,e.displayName="gap",e.aliases=[];function e(t){t.languages.gap={shell:{pattern:/^gap>[\s\S]*?(?=^gap>|$(?![\s\S]))/m,greedy:!0,inside:{gap:{pattern:/^(gap>).+(?:(?:\r(?:\n|(?!\n))|\n)>.*)*/,lookbehind:!0,inside:null},punctuation:/^gap>/}},comment:{pattern:/#.*/,greedy:!0},string:{pattern:/(^|[^\\'"])(?:'(?:[^\r\n\\']|\\.){1,10}'|"(?:[^\r\n\\"]|\\.)*"(?!")|"""[\s\S]*?""")/,lookbehind:!0,greedy:!0,inside:{continuation:{pattern:/([\r\n])>/,lookbehind:!0,alias:"punctuation"}}},keyword:/\b(?:Assert|Info|IsBound|QUIT|TryNextMethod|Unbind|and|atomic|break|continue|do|elif|else|end|fi|for|function|if|in|local|mod|not|od|or|quit|readonly|readwrite|rec|repeat|return|then|until|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:{pattern:/(^|[^\w.]|\.\.)(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?(?:_[a-z]?)?(?=$|[^\w.]|\.\.)/,lookbehind:!0},continuation:{pattern:/([\r\n])>/,lookbehind:!0,alias:"punctuation"},operator:/->|[-+*/^~=!]|<>|[<>]=?|:=|\.\./,punctuation:/[()[\]{},;.:]/},t.languages.gap.shell.inside.gap.inside=t.languages.gap}return Eu}var Su,oS;function rG(){if(oS)return Su;oS=1,Su=e,e.displayName="gcode",e.aliases=[];function e(t){t.languages.gcode={comment:/;.*|\B\(.*?\)\B/,string:{pattern:/"(?:""|[^"])*"/,greedy:!0},keyword:/\b[GM]\d+(?:\.\d+)?\b/,property:/\b[A-Z]/,checksum:{pattern:/(\*)\d+/,lookbehind:!0,alias:"number"},punctuation:/[:*]/}}return Su}var vu,sS;function aG(){if(sS)return vu;sS=1,vu=e,e.displayName="gdscript",e.aliases=[];function e(t){t.languages.gdscript={comment:/#.*/,string:{pattern:/@?(?:("|')(?:(?!\1)[^\n\\]|\\[\s\S])*\1(?!"|')|"""(?:[^\\]|\\[\s\S])*?""")/,greedy:!0},"class-name":{pattern:/(^(?:class|class_name|extends)[ \t]+|^export\([ \t]*|\bas[ \t]+|(?:\b(?:const|var)[ \t]|[,(])[ \t]*\w+[ \t]*:[ \t]*|->[ \t]*)[a-zA-Z_]\w*/m,lookbehind:!0},keyword:/\b(?:and|as|assert|break|breakpoint|class|class_name|const|continue|elif|else|enum|export|extends|for|func|if|in|is|master|mastersync|match|not|null|onready|or|pass|preload|puppet|puppetsync|remote|remotesync|return|self|setget|signal|static|tool|var|while|yield)\b/,function:/\b[a-z_]\w*(?=[ \t]*\()/i,variable:/\$\w+/,number:[/\b0b[01_]+\b|\b0x[\da-fA-F_]+\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.[\d_]+)(?:e[+-]?[\d_]+)?\b/,/\b(?:INF|NAN|PI|TAU)\b/],constant:/\b[A-Z][A-Z_\d]*\b/,boolean:/\b(?:false|true)\b/,operator:/->|:=|&&|\|\||<<|>>|[-+*/%&|!<>=]=?|[~^]/,punctuation:/[.:,;()[\]{}]/}}return vu}var ku,lS;function iG(){if(lS)return ku;lS=1,ku=e,e.displayName="gedcom",e.aliases=[];function e(t){t.languages.gedcom={"line-value":{pattern:/(^[\t ]*\d+ +(?:@\w[\w!"$%&'()*+,\-./:;<=>?[\\\]^`{|}~\x80-\xfe #]*@ +)?\w+ ).+/m,lookbehind:!0,inside:{pointer:{pattern:/^@\w[\w!"$%&'()*+,\-./:;<=>?[\\\]^`{|}~\x80-\xfe #]*@$/,alias:"variable"}}},tag:{pattern:/(^[\t ]*\d+ +(?:@\w[\w!"$%&'()*+,\-./:;<=>?[\\\]^`{|}~\x80-\xfe #]*@ +)?)\w+/m,lookbehind:!0,alias:"string"},level:{pattern:/(^[\t ]*)\d+/m,lookbehind:!0,alias:"number"},pointer:{pattern:/@\w[\w!"$%&'()*+,\-./:;<=>?[\\\]^`{|}~\x80-\xfe #]*@/,alias:"variable"}}}return ku}var wu,uS;function oG(){if(uS)return wu;uS=1,wu=e,e.displayName="gherkin",e.aliases=[];function e(t){(function(n){var r=/(?:\r?\n|\r)[ \t]*\|.+\|(?:(?!\|).)*/.source;n.languages.gherkin={pystring:{pattern:/("""|''')[\s\S]+?\1/,alias:"string"},comment:{pattern:/(^[ \t]*)#.*/m,lookbehind:!0},tag:{pattern:/(^[ \t]*)@\S*/m,lookbehind:!0},feature:{pattern:/((?:^|\r?\n|\r)[ \t]*)(?:Ability|Ahoy matey!|Arwedd|Aspekt|Besigheid Behoefte|Business Need|Caracteristica|Característica|Egenskab|Egenskap|Eiginleiki|Feature|Fīča|Fitur|Fonctionnalité|Fonksyonalite|Funcionalidade|Funcionalitat|Functionalitate|Funcţionalitate|Funcționalitate|Functionaliteit|Fungsi|Funkcia|Funkcija|Funkcionalitāte|Funkcionalnost|Funkcja|Funksie|Funktionalität|Funktionalitéit|Funzionalità|Hwaet|Hwæt|Jellemző|Karakteristik|Lastnost|Mak|Mogucnost|laH|Mogućnost|Moznosti|Možnosti|OH HAI|Omadus|Ominaisuus|Osobina|Özellik|Potrzeba biznesowa|perbogh|poQbogh malja'|Požadavek|Požiadavka|Pretty much|Qap|Qu'meH 'ut|Savybė|Tính năng|Trajto|Vermoë|Vlastnosť|Właściwość|Značilnost|Δυνατότητα|Λειτουργία|Могућност|Мөмкинлек|Особина|Свойство|Үзенчәлеклелек|Функционал|Функционалност|Функция|Функціонал|תכונה|خاصية|خصوصیت|صلاحیت|کاروبار کی ضرورت|وِیژگی|रूप लेख|ਖਾਸੀਅਤ|ਨਕਸ਼ ਨੁਹਾਰ|ਮੁਹਾਂਦਰਾ|గుణము|ಹೆಚ್ಚಳ|ความต้องการทางธุรกิจ|ความสามารถ|โครงหลัก|기능|フィーチャ|功能|機能):(?:[^:\r\n]+(?:\r?\n|\r|$))*/,lookbehind:!0,inside:{important:{pattern:/(:)[^\r\n]+/,lookbehind:!0},keyword:/[^:\r\n]+:/}},scenario:{pattern:/(^[ \t]*)(?:Abstract Scenario|Abstrakt Scenario|Achtergrond|Aer|Ær|Agtergrond|All y'all|Antecedentes|Antecedents|Atburðarás|Atburðarásir|Awww, look mate|B4|Background|Baggrund|Bakgrund|Bakgrunn|Bakgrunnur|Beispiele|Beispiller|Bối cảnh|Cefndir|Cenario|Cenário|Cenario de Fundo|Cenário de Fundo|Cenarios|Cenários|Contesto|Context|Contexte|Contexto|Conto|Contoh|Contone|Dæmi|Dasar|Dead men tell no tales|Delineacao do Cenario|Delineação do Cenário|Dis is what went down|Dữ liệu|Dyagram Senaryo|Dyagram senaryo|Egzanp|Ejemplos|Eksempler|Ekzemploj|Enghreifftiau|Esbozo do escenario|Escenari|Escenario|Esempi|Esquema de l'escenari|Esquema del escenario|Esquema do Cenario|Esquema do Cenário|EXAMPLZ|Examples|Exempel|Exemple|Exemples|Exemplos|First off|Fono|Forgatókönyv|Forgatókönyv vázlat|Fundo|Geçmiş|Grundlage|Hannergrond|ghantoH|Háttér|Heave to|Istorik|Juhtumid|Keadaan|Khung kịch bản|Khung tình huống|Kịch bản|Koncept|Konsep skenario|Kontèks|Kontekst|Kontekstas|Konteksts|Kontext|Konturo de la scenaro|Latar Belakang|lut chovnatlh|lut|lutmey|Lýsing Atburðarásar|Lýsing Dæma|MISHUN SRSLY|MISHUN|Menggariskan Senario|mo'|Náčrt Scenára|Náčrt Scénáře|Náčrt Scenáru|Oris scenarija|Örnekler|Osnova|Osnova Scenára|Osnova scénáře|Osnutek|Ozadje|Paraugs|Pavyzdžiai|Példák|Piemēri|Plan du scénario|Plan du Scénario|Plan Senaryo|Plan senaryo|Plang vum Szenario|Pozadí|Pozadie|Pozadina|Príklady|Příklady|Primer|Primeri|Primjeri|Przykłady|Raamstsenaarium|Reckon it's like|Rerefons|Scenár|Scénář|Scenarie|Scenarij|Scenarijai|Scenarijaus šablonas|Scenariji|Scenārijs|Scenārijs pēc parauga|Scenarijus|Scenario|Scénario|Scenario Amlinellol|Scenario Outline|Scenario Template|Scenariomal|Scenariomall|Scenarios|Scenariu|Scenariusz|Scenaro|Schema dello scenario|Se ðe|Se the|Se þe|Senario|Senaryo Deskripsyon|Senaryo deskripsyon|Senaryo|Senaryo taslağı|Shiver me timbers|Situācija|Situai|Situasie Uiteensetting|Situasie|Skenario konsep|Skenario|Skica|Structura scenariu|Structură scenariu|Struktura scenarija|Stsenaarium|Swa hwaer swa|Swa|Swa hwær swa|Szablon scenariusza|Szenario|Szenariogrundriss|Tapaukset|Tapaus|Tapausaihio|Taust|Tausta|Template Keadaan|Template Senario|Template Situai|The thing of it is|Tình huống|Variantai|Voorbeelde|Voorbeelden|Wharrimean is|Yo-ho-ho|You'll wanna|Założenia|Παραδείγματα|Περιγραφή Σεναρίου|Σενάρια|Σενάριο|Υπόβαθρο|Кереш|Контекст|Концепт|Мисаллар|Мисоллар|Основа|Передумова|Позадина|Предистория|Предыстория|Приклади|Пример|Примери|Примеры|Рамка на сценарий|Скица|Структура сценарија|Структура сценария|Структура сценарію|Сценарий|Сценарий структураси|Сценарийның төзелеше|Сценарији|Сценарио|Сценарій|Тарих|Үрнәкләр|דוגמאות|רקע|תבנית תרחיש|תרחיש|الخلفية|الگوی سناریو|امثلة|پس منظر|زمینه|سناریو|سيناريو|سيناريو مخطط|مثالیں|منظر نامے کا خاکہ|منظرنامہ|نمونه ها|उदाहरण|परिदृश्य|परिदृश्य रूपरेखा|पृष्ठभूमि|ਉਦਾਹਰਨਾਂ|ਪਟਕਥਾ|ਪਟਕਥਾ ਢਾਂਚਾ|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਿਛੋਕੜ|ఉదాహరణలు|కథనం|నేపథ్యం|సన్నివేశం|ಉದಾಹರಣೆಗಳು|ಕಥಾಸಾರಾಂಶ|ವಿವರಣೆ|ಹಿನ್ನೆಲೆ|โครงสร้างของเหตุการณ์|ชุดของตัวอย่าง|ชุดของเหตุการณ์|แนวคิด|สรุปเหตุการณ์|เหตุการณ์|배경|시나리오|시나리오 개요|예|サンプル|シナリオ|シナリオアウトライン|シナリオテンプレ|シナリオテンプレート|テンプレ|例|例子|剧本|剧本大纲|劇本|劇本大綱|场景|场景大纲|場景|場景大綱|背景):[^:\r\n]*/m,lookbehind:!0,inside:{important:{pattern:/(:)[^\r\n]*/,lookbehind:!0},keyword:/[^:\r\n]+:/}},"table-body":{pattern:RegExp("("+r+")(?:"+r+")+"),lookbehind:!0,inside:{outline:{pattern:/<[^>]+>/,alias:"variable"},td:{pattern:/\s*[^\s|][^|]*/,alias:"string"},punctuation:/\|/}},"table-head":{pattern:RegExp(r),inside:{th:{pattern:/\s*[^\s|][^|]*/,alias:"variable"},punctuation:/\|/}},atrule:{pattern:/(^[ \t]+)(?:'a|'ach|'ej|7|a|A také|A taktiež|A tiež|A zároveň|Aber|Ac|Adott|Akkor|Ak|Aleshores|Ale|Ali|Allora|Alors|Als|Ama|Amennyiben|Amikor|Ampak|an|AN|Ananging|And y'all|And|Angenommen|Anrhegedig a|An|Apabila|Atès|Atesa|Atunci|Avast!|Aye|A|awer|Bagi|Banjur|Bet|Biết|Blimey!|Buh|But at the end of the day I reckon|But y'all|But|BUT|Cal|Când|Cand|Cando|Ce|Cuando|Če|Ða ðe|Ða|Dadas|Dada|Dados|Dado|DaH ghu' bejlu'|dann|Dann|Dano|Dan|Dar|Dat fiind|Data|Date fiind|Date|Dati fiind|Dati|Daţi fiind|Dați fiind|DEN|Dato|De|Den youse gotta|Dengan|Diberi|Diyelim ki|Donada|Donat|Donitaĵo|Do|Dun|Duota|Ðurh|Eeldades|Ef|Eğer ki|Entao|Então|Entón|E|En|Entonces|Epi|És|Etant donnée|Etant donné|Et|Étant données|Étant donnée|Étant donné|Etant données|Etant donnés|Étant donnés|Fakat|Gangway!|Gdy|Gegeben seien|Gegeben sei|Gegeven|Gegewe|ghu' noblu'|Gitt|Given y'all|Given|Givet|Givun|Ha|Cho|I CAN HAZ|In|Ir|It's just unbelievable|I|Ja|Jeśli|Jeżeli|Kad|Kada|Kadar|Kai|Kaj|Když|Keď|Kemudian|Ketika|Khi|Kiedy|Ko|Kuid|Kui|Kun|Lan|latlh|Le sa a|Let go and haul|Le|Lè sa a|Lè|Logo|Lorsqu'<|Lorsque|mä|Maar|Mais|Mając|Ma|Majd|Maka|Manawa|Mas|Men|Menawa|Mutta|Nalika|Nalikaning|Nanging|Når|När|Nato|Nhưng|Niin|Njuk|O zaman|Och|Og|Oletetaan|Ond|Onda|Oraz|Pak|Pero|Però|Podano|Pokiaľ|Pokud|Potem|Potom|Privzeto|Pryd|Quan|Quand|Quando|qaSDI'|Så|Sed|Se|Siis|Sipoze ke|Sipoze Ke|Sipoze|Si|Şi|Și|Soit|Stel|Tada|Tad|Takrat|Tak|Tapi|Ter|Tetapi|Tha the|Tha|Then y'all|Then|Thì|Thurh|Toda|Too right|Un|Und|ugeholl|Và|vaj|Vendar|Ve|wann|Wanneer|WEN|Wenn|When y'all|When|Wtedy|Wun|Y'know|Yeah nah|Yna|Youse know like when|Youse know when youse got|Y|Za predpokladu|Za předpokladu|Zadan|Zadani|Zadano|Zadate|Zadato|Zakładając|Zaradi|Zatati|Þa þe|Þa|Þá|Þegar|Þurh|Αλλά|Δεδομένου|Και|Όταν|Τότε|А також|Агар|Але|Али|Аммо|А|Әгәр|Әйтик|Әмма|Бирок|Ва|Вә|Дадено|Дано|Допустим|Если|Задате|Задати|Задато|И|І|К тому же|Када|Кад|Когато|Когда|Коли|Ләкин|Лекин|Нәтиҗәдә|Нехай|Но|Онда|Припустимо, що|Припустимо|Пусть|Также|Та|Тогда|Тоді|То|Унда|Һәм|Якщо|אבל|אזי|אז|בהינתן|וגם|כאשר|آنگاه|اذاً|اگر|اما|اور|با فرض|بالفرض|بفرض|پھر|تب|ثم|جب|عندما|فرض کیا|لكن|لیکن|متى|هنگامی|و|अगर|और|कदा|किन्तु|चूंकि|जब|तथा|तदा|तब|परन्तु|पर|यदि|ਅਤੇ|ਜਦੋਂ|ਜਿਵੇਂ ਕਿ|ਜੇਕਰ|ਤਦ|ਪਰ|అప్పుడు|ఈ పరిస్థితిలో|కాని|చెప్పబడినది|మరియు|ಆದರೆ|ನಂತರ|ನೀಡಿದ|ಮತ್ತು|ಸ್ಥಿತಿಯನ್ನು|กำหนดให้|ดังนั้น|แต่|เมื่อ|และ|그러면<|그리고<|단<|만약<|만일<|먼저<|조건<|하지만<|かつ<|しかし<|ただし<|ならば<|もし<|並且<|但し<|但是<|假如<|假定<|假設<|假设<|前提<|同时<|同時<|并且<|当<|當<|而且<|那么<|那麼<)(?=[ \t])/m,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*'/,inside:{outline:{pattern:/<[^>]+>/,alias:"variable"}}},outline:{pattern:/<[^>]+>/,alias:"variable"}}})(t)}return wu}var _u,cS;function sG(){if(cS)return _u;cS=1,_u=e,e.displayName="git",e.aliases=[];function e(t){t.languages.git={comment:/^#.*/m,deleted:/^[-–].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m}}return _u}var Tu,dS;function lG(){if(dS)return Tu;dS=1;var e=tr();Tu=t,t.displayName="glsl",t.aliases=[];function t(n){n.register(e),n.languages.glsl=n.languages.extend("c",{keyword:/\b(?:active|asm|atomic_uint|attribute|[ibdu]?vec[234]|bool|break|buffer|case|cast|centroid|class|coherent|common|const|continue|d?mat[234](?:x[234])?|default|discard|do|double|else|enum|extern|external|false|filter|fixed|flat|float|for|fvec[234]|goto|half|highp|hvec[234]|[iu]?sampler2DMS(?:Array)?|[iu]?sampler2DRect|[iu]?samplerBuffer|[iu]?samplerCube|[iu]?samplerCubeArray|[iu]?sampler[123]D|[iu]?sampler[12]DArray|[iu]?image2DMS(?:Array)?|[iu]?image2DRect|[iu]?imageBuffer|[iu]?imageCube|[iu]?imageCubeArray|[iu]?image[123]D|[iu]?image[12]DArray|if|in|inline|inout|input|int|interface|invariant|layout|long|lowp|mediump|namespace|noinline|noperspective|out|output|partition|patch|precise|precision|public|readonly|resource|restrict|return|sample|sampler[12]DArrayShadow|sampler[12]DShadow|sampler2DRectShadow|sampler3DRect|samplerCubeArrayShadow|samplerCubeShadow|shared|short|sizeof|smooth|static|struct|subroutine|superp|switch|template|this|true|typedef|uint|uniform|union|unsigned|using|varying|void|volatile|while|writeonly)\b/})}return Tu}var Au,pS;function uG(){if(pS)return Au;pS=1,Au=e,e.displayName="gml",e.aliases=[];function e(t){t.languages.gamemakerlanguage=t.languages.gml=t.languages.extend("clike",{keyword:/\b(?:break|case|continue|default|do|else|enum|exit|for|globalvar|if|repeat|return|switch|until|var|while)\b/,number:/(?:\b0x[\da-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ulf]{0,4}/i,operator:/--|\+\+|[-+%/=]=?|!=|\*\*?=?|<[<=>]?|>[=>]?|&&?|\^\^?|\|\|?|~|\b(?:and|at|not|or|with|xor)\b/,constant:/\b(?:GM_build_date|GM_version|action_(?:continue|restart|reverse|stop)|all|gamespeed_(?:fps|microseconds)|global|local|noone|other|pi|pointer_(?:invalid|null)|self|timezone_(?:local|utc)|undefined|ev_(?:create|destroy|step|alarm|keyboard|mouse|collision|other|draw|draw_(?:begin|end|post|pre)|keypress|keyrelease|trigger|(?:left|middle|no|right)_button|(?:left|middle|right)_press|(?:left|middle|right)_release|mouse_(?:enter|leave|wheel_down|wheel_up)|global_(?:left|middle|right)_button|global_(?:left|middle|right)_press|global_(?:left|middle|right)_release|joystick(?:1|2)_(?:button1|button2|button3|button4|button5|button6|button7|button8|down|left|right|up)|outside|boundary|game_start|game_end|room_start|room_end|no_more_lives|animation_end|end_of_path|no_more_health|user\d|gui|gui_begin|gui_end|step_(?:begin|end|normal))|vk_(?:alt|anykey|backspace|control|delete|down|end|enter|escape|home|insert|left|nokey|pagedown|pageup|pause|printscreen|return|right|shift|space|tab|up|f\d|numpad\d|add|decimal|divide|lalt|lcontrol|lshift|multiply|ralt|rcontrol|rshift|subtract)|achievement_(?:filter_(?:all_players|favorites_only|friends_only)|friends_info|info|leaderboard_info|our_info|pic_loaded|show_(?:achievement|bank|friend_picker|leaderboard|profile|purchase_prompt|ui)|type_challenge|type_score_challenge)|asset_(?:font|object|path|room|script|shader|sound|sprite|tiles|timeline|unknown)|audio_(?:3d|falloff_(?:exponent_distance|exponent_distance_clamped|inverse_distance|inverse_distance_clamped|linear_distance|linear_distance_clamped|none)|mono|new_system|old_system|stereo)|bm_(?:add|complex|dest_alpha|dest_color|dest_colour|inv_dest_alpha|inv_dest_color|inv_dest_colour|inv_src_alpha|inv_src_color|inv_src_colour|max|normal|one|src_alpha|src_alpha_sat|src_color|src_colour|subtract|zero)|browser_(?:chrome|firefox|ie|ie_mobile|not_a_browser|opera|safari|safari_mobile|tizen|unknown|windows_store)|buffer_(?:bool|f16|f32|f64|fast|fixed|generalerror|grow|invalidtype|network|outofbounds|outofspace|s16|s32|s8|seek_end|seek_relative|seek_start|string|text|u16|u32|u64|u8|vbuffer|wrap)|c_(?:aqua|black|blue|dkgray|fuchsia|gray|green|lime|ltgray|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow)|cmpfunc_(?:always|equal|greater|greaterequal|less|lessequal|never|notequal)|cr_(?:appstart|arrow|beam|cross|default|drag|handpoint|hourglass|none|size_all|size_nesw|size_ns|size_nwse|size_we|uparrow)|cull_(?:clockwise|counterclockwise|noculling)|device_(?:emulator|tablet)|device_ios_(?:ipad|ipad_retina|iphone|iphone5|iphone6|iphone6plus|iphone_retina|unknown)|display_(?:landscape|landscape_flipped|portrait|portrait_flipped)|dll_(?:cdecl|cdel|stdcall)|ds_type_(?:grid|list|map|priority|queue|stack)|ef_(?:cloud|ellipse|explosion|firework|flare|rain|ring|smoke|smokeup|snow|spark|star)|fa_(?:archive|bottom|center|directory|hidden|left|middle|readonly|right|sysfile|top|volumeid)|fb_login_(?:default|fallback_to_webview|forcing_safari|forcing_webview|no_fallback_to_webview|use_system_account)|iap_(?:available|canceled|ev_consume|ev_product|ev_purchase|ev_restore|ev_storeload|failed|purchased|refunded|status_available|status_loading|status_processing|status_restoring|status_unavailable|status_uninitialised|storeload_failed|storeload_ok|unavailable)|leaderboard_type_(?:number|time_mins_secs)|lighttype_(?:dir|point)|matrix_(?:projection|view|world)|mb_(?:any|left|middle|none|right)|network_(?:config_(?:connect_timeout|disable_reliable_udp|enable_reliable_udp|use_non_blocking_socket)|socket_(?:bluetooth|tcp|udp)|type_(?:connect|data|disconnect|non_blocking_connect))|of_challenge_(?:lose|tie|win)|os_(?:android|ios|linux|macosx|ps3|ps4|psvita|unknown|uwp|win32|win8native|windows|winphone|xboxone)|phy_debug_render_(?:aabb|collision_pairs|coms|core_shapes|joints|obb|shapes)|phy_joint_(?:anchor_1_x|anchor_1_y|anchor_2_x|anchor_2_y|angle|angle_limits|damping_ratio|frequency|length_1|length_2|lower_angle_limit|max_force|max_length|max_motor_force|max_motor_torque|max_torque|motor_force|motor_speed|motor_torque|reaction_force_x|reaction_force_y|reaction_torque|speed|translation|upper_angle_limit)|phy_particle_data_flag_(?:category|color|colour|position|typeflags|velocity)|phy_particle_flag_(?:colormixing|colourmixing|elastic|powder|spring|tensile|viscous|wall|water|zombie)|phy_particle_group_flag_(?:rigid|solid)|pr_(?:linelist|linestrip|pointlist|trianglefan|trianglelist|trianglestrip)|ps_(?:distr|shape)_(?:diamond|ellipse|gaussian|invgaussian|line|linear|rectangle)|pt_shape_(?:circle|cloud|disk|explosion|flare|line|pixel|ring|smoke|snow|spark|sphere|square|star)|ty_(?:real|string)|gp_(?:face\d|axislh|axislv|axisrh|axisrv|padd|padl|padr|padu|select|shoulderl|shoulderlb|shoulderr|shoulderrb|start|stickl|stickr)|lb_disp_(?:none|numeric|time_ms|time_sec)|lb_sort_(?:ascending|descending|none)|ov_(?:achievements|community|friends|gamegroup|players|settings)|ugc_(?:filetype_(?:community|microtrans)|list_(?:Favorited|Followed|Published|Subscribed|UsedOrPlayed|VotedDown|VotedOn|VotedUp|WillVoteLater)|match_(?:AllGuides|Artwork|Collections|ControllerBindings|IntegratedGuides|Items|Items_Mtx|Items_ReadyToUse|Screenshots|UsableInGame|Videos|WebGuides)|query_(?:AcceptedForGameRankedByAcceptanceDate|CreatedByFriendsRankedByPublicationDate|FavoritedByFriendsRankedByPublicationDate|NotYetRated)|query_RankedBy(?:NumTimesReported|PublicationDate|TextSearch|TotalVotesAsc|Trend|Vote|VotesUp)|result_success|sortorder_CreationOrder(?:Asc|Desc)|sortorder_(?:ForModeration|LastUpdatedDesc|SubscriptionDateDesc|TitleAsc|VoteScoreDesc)|visibility_(?:friends_only|private|public))|vertex_usage_(?:binormal|blendindices|blendweight|color|colour|depth|fog|normal|position|psize|sample|tangent|texcoord|textcoord)|vertex_type_(?:float\d|color|colour|ubyte4)|input_type|layerelementtype_(?:background|instance|oldtilemap|particlesystem|sprite|tile|tilemap|undefined)|se_(?:chorus|compressor|echo|equalizer|flanger|gargle|none|reverb)|text_type|tile_(?:flip|index_mask|mirror|rotate)|(?:obj|rm|scr|spr)\w+)\b/,variable:/\b(?:alarm|application_surface|async_load|background_(?:alpha|blend|color|colour|foreground|height|hspeed|htiled|index|showcolor|showcolour|visible|vspeed|vtiled|width|x|xscale|y|yscale)|bbox_(?:bottom|left|right|top)|browser_(?:height|width)|caption_(?:health|lives|score)|current_(?:day|hour|minute|month|second|time|weekday|year)|cursor_sprite|debug_mode|delta_time|direction|display_aa|error_(?:last|occurred)|event_(?:action|number|object|type)|fps|fps_real|friction|game_(?:display|project|save)_(?:id|name)|gamemaker_(?:pro|registered|version)|gravity|gravity_direction|(?:h|v)speed|health|iap_data|id|image_(?:alpha|angle|blend|depth|index|number|speed|xscale|yscale)|instance_(?:count|id)|keyboard_(?:key|lastchar|lastkey|string)|layer|lives|mask_index|mouse_(?:button|lastbutton|x|y)|object_index|os_(?:browser|device|type|version)|path_(?:endaction|index|orientation|position|positionprevious|scale|speed)|persistent|phy_(?:rotation|(?:col_normal|collision|com|linear_velocity|position|speed)_(?:x|y)|angular_(?:damping|velocity)|position_(?:x|y)previous|speed|linear_damping|bullet|fixed_rotation|active|mass|inertia|dynamic|kinematic|sleeping|collision_points)|pointer_(?:invalid|null)|room|room_(?:caption|first|height|last|persistent|speed|width)|score|secure_mode|show_(?:health|lives|score)|solid|speed|sprite_(?:height|index|width|xoffset|yoffset)|temp_directory|timeline_(?:index|loop|position|running|speed)|transition_(?:color|kind|steps)|undefined|view_(?:angle|current|enabled|(?:h|v)(?:border|speed)|(?:h|w|x|y)port|(?:h|w|x|y)view|object|surface_id|visible)|visible|webgl_enabled|working_directory|(?:x|y)(?:previous|start)|x|y|argument(?:_relitive|_count|\d)|argument|global|local|other|self)\b/})}return Au}var Ru,fS;function cG(){if(fS)return Ru;fS=1,Ru=e,e.displayName="gn",e.aliases=["gni"];function e(t){t.languages.gn={comment:{pattern:/#.*/,greedy:!0},"string-literal":{pattern:/(^|[^\\"])"(?:[^\r\n"\\]|\\.)*"/,lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\{[\s\S]*?\}|[a-zA-Z_]\w*|0x[a-fA-F0-9]{2})/,lookbehind:!0,inside:{number:/^\$0x[\s\S]{2}$/,variable:/^\$\w+$/,"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:null}}},string:/[\s\S]+/}},keyword:/\b(?:else|if)\b/,boolean:/\b(?:false|true)\b/,"builtin-function":{pattern:/\b(?:assert|defined|foreach|import|pool|print|template|tool|toolchain)(?=\s*\()/i,alias:"keyword"},function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:current_cpu|current_os|current_toolchain|default_toolchain|host_cpu|host_os|root_build_dir|root_gen_dir|root_out_dir|target_cpu|target_gen_dir|target_os|target_out_dir)\b/,number:/-?\b\d+\b/,operator:/[-+!=<>]=?|&&|\|\|/,punctuation:/[(){}[\],.]/},t.languages.gn["string-literal"].inside.interpolation.inside.expression.inside=t.languages.gn,t.languages.gni=t.languages.gn}return Ru}var Iu,gS;function dG(){if(gS)return Iu;gS=1,Iu=e,e.displayName="goModule",e.aliases=[];function e(t){t.languages["go-mod"]=t.languages["go-module"]={comment:{pattern:/\/\/.*/,greedy:!0},version:{pattern:/(^|[\s()[\],])v\d+\.\d+\.\d+(?:[+-][-+.\w]*)?(?![^\s()[\],])/,lookbehind:!0,alias:"number"},"go-version":{pattern:/((?:^|\s)go\s+)\d+(?:\.\d+){1,2}/,lookbehind:!0,alias:"number"},keyword:{pattern:/^([ \t]*)(?:exclude|go|module|replace|require|retract)\b/m,lookbehind:!0},operator:/=>/,punctuation:/[()[\],]/}}return Iu}var Cu,mS;function pG(){if(mS)return Cu;mS=1,Cu=e,e.displayName="go",e.aliases=[];function e(t){t.languages.go=t.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),t.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete t.languages.go["class-name"]}return Cu}var Nu,hS;function fG(){if(hS)return Nu;hS=1,Nu=e,e.displayName="graphql",e.aliases=[];function e(t){t.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:t.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},t.hooks.add("after-tokenize",function(r){if(r.language!=="graphql")return;var a=r.tokens.filter(function(b){return typeof b!="string"&&b.type!=="comment"&&b.type!=="scalar"}),i=0;function o(b){return a[i+b]}function s(b,g){g=g||0;for(var m=0;m0)){var h=l(/^\{$/,/^\}$/);if(h===-1)continue;for(var y=i;y=0&&u(T,"variable-input")}}}}})}return Nu}var xu,bS;function gG(){if(bS)return xu;bS=1,xu=e,e.displayName="groovy",e.aliases=[];function e(t){t.languages.groovy=t.languages.extend("clike",{string:[{pattern:/("""|''')(?:[^\\]|\\[\s\S])*?\1|\$\/(?:[^/$]|\$(?:[/$]|(?![/$]))|\/(?!\$))*\/\$/,greedy:!0},{pattern:/(["'/])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0}],keyword:/\b(?:abstract|as|assert|boolean|break|byte|case|catch|char|class|const|continue|def|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|in|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\b/,number:/\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?\d+)?)[glidf]?\b/i,operator:{pattern:/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.\.(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),t.languages.insertBefore("groovy","string",{shebang:{pattern:/#!.+/,alias:"comment"}}),t.languages.insertBefore("groovy","punctuation",{"spock-block":/\b(?:and|cleanup|expect|given|setup|then|when|where):/}),t.languages.insertBefore("groovy","function",{annotation:{pattern:/(^|[^.])@\w+/,lookbehind:!0,alias:"punctuation"}}),t.hooks.add("wrap",function(n){if(n.language==="groovy"&&n.type==="string"){var r=n.content.value[0];if(r!="'"){var a=/([^\\])(?:\$(?:\{.*?\}|[\w.]+))/;r==="$"&&(a=/([^\$])(?:\$(?:\{.*?\}|[\w.]+))/),n.content.value=n.content.value.replace(/</g,"<").replace(/&/g,"&"),n.content=t.highlight(n.content.value,{expression:{pattern:a,lookbehind:!0,inside:t.languages.groovy}}),n.classes.push(r==="/"?"regex":"gstring")}}})}return xu}var Ou,yS;function mG(){if(yS)return Ou;yS=1;var e=Zo();Ou=t,t.displayName="haml",t.aliases=[];function t(n){n.register(e),function(r){r.languages.haml={"multiline-comment":{pattern:/((?:^|\r?\n|\r)([\t ]*))(?:\/|-#).*(?:(?:\r?\n|\r)\2[\t ].+)*/,lookbehind:!0,alias:"comment"},"multiline-code":[{pattern:/((?:^|\r?\n|\r)([\t ]*)(?:[~-]|[&!]?=)).*,[\t ]*(?:(?:\r?\n|\r)\2[\t ].*,[\t ]*)*(?:(?:\r?\n|\r)\2[\t ].+)/,lookbehind:!0,inside:r.languages.ruby},{pattern:/((?:^|\r?\n|\r)([\t ]*)(?:[~-]|[&!]?=)).*\|[\t ]*(?:(?:\r?\n|\r)\2[\t ].*\|[\t ]*)*/,lookbehind:!0,inside:r.languages.ruby}],filter:{pattern:/((?:^|\r?\n|\r)([\t ]*)):[\w-]+(?:(?:\r?\n|\r)(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/,lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"symbol"}}},markup:{pattern:/((?:^|\r?\n|\r)[\t ]*)<.+/,lookbehind:!0,inside:r.languages.markup},doctype:{pattern:/((?:^|\r?\n|\r)[\t ]*)!!!(?: .+)?/,lookbehind:!0},tag:{pattern:/((?:^|\r?\n|\r)[\t ]*)[%.#][\w\-#.]*[\w\-](?:\([^)]+\)|\{(?:\{[^}]+\}|[^{}])+\}|\[[^\]]+\])*[\/<>]*/,lookbehind:!0,inside:{attributes:[{pattern:/(^|[^#])\{(?:\{[^}]+\}|[^{}])+\}/,lookbehind:!0,inside:r.languages.ruby},{pattern:/\([^)]+\)/,inside:{"attr-value":{pattern:/(=\s*)(?:"(?:\\.|[^\\"\r\n])*"|[^)\s]+)/,lookbehind:!0},"attr-name":/[\w:-]+(?=\s*!?=|\s*[,)])/,punctuation:/[=(),]/}},{pattern:/\[[^\]]+\]/,inside:r.languages.ruby}],punctuation:/[<>]/}},code:{pattern:/((?:^|\r?\n|\r)[\t ]*(?:[~-]|[&!]?=)).+/,lookbehind:!0,inside:r.languages.ruby},interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},ruby:{pattern:/[\s\S]+/,inside:r.languages.ruby}}},punctuation:{pattern:/((?:^|\r?\n|\r)[\t ]*)[~=\-&!]+/,lookbehind:!0}};for(var a="((?:^|\\r?\\n|\\r)([\\t ]*)):{{filter_name}}(?:(?:\\r?\\n|\\r)(?:\\2[\\t ].+|\\s*?(?=\\r?\\n|\\r)))+",i=["css",{filter:"coffee",language:"coffeescript"},"erb","javascript","less","markdown","ruby","scss","textile"],o={},s=0,l=i.length;s@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},r.hooks.add("before-tokenize",function(a){var i=/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g;r.languages["markup-templating"].buildPlaceholders(a,"handlebars",i)}),r.hooks.add("after-tokenize",function(a){r.languages["markup-templating"].tokenizePlaceholders(a,"handlebars")}),r.languages.hbs=r.languages.handlebars}(n)}return Lu}var Du,SS;function zm(){if(SS)return Du;SS=1,Du=e,e.displayName="haskell",e.aliases=["hs"];function e(t){t.languages.haskell={comment:{pattern:/(^|[^-!#$%*+=?&@|~.:<>^\\\/])(?:--(?:(?=.)[^-!#$%*+=?&@|~.:<>^\\\/].*|$)|\{-[\s\S]*?-\})/m,lookbehind:!0},char:{pattern:/'(?:[^\\']|\\(?:[abfnrtv\\"'&]|\^[A-Z@[\]^_]|ACK|BEL|BS|CAN|CR|DC1|DC2|DC3|DC4|DEL|DLE|EM|ENQ|EOT|ESC|ETB|ETX|FF|FS|GS|HT|LF|NAK|NUL|RS|SI|SO|SOH|SP|STX|SUB|SYN|US|VT|\d+|o[0-7]+|x[0-9a-fA-F]+))'/,alias:"string"},string:{pattern:/"(?:[^\\"]|\\(?:\S|\s+\\))*"/,greedy:!0},keyword:/\b(?:case|class|data|deriving|do|else|if|in|infixl|infixr|instance|let|module|newtype|of|primitive|then|type|where)\b/,"import-statement":{pattern:/(^[\t ]*)import\s+(?:qualified\s+)?(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*(?:\s+as\s+(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*)?(?:\s+hiding\b)?/m,lookbehind:!0,inside:{keyword:/\b(?:as|hiding|import|qualified)\b/,punctuation:/\./}},builtin:/\b(?:abs|acos|acosh|all|and|any|appendFile|approxRational|asTypeOf|asin|asinh|atan|atan2|atanh|basicIORun|break|catch|ceiling|chr|compare|concat|concatMap|const|cos|cosh|curry|cycle|decodeFloat|denominator|digitToInt|div|divMod|drop|dropWhile|either|elem|encodeFloat|enumFrom|enumFromThen|enumFromThenTo|enumFromTo|error|even|exp|exponent|fail|filter|flip|floatDigits|floatRadix|floatRange|floor|fmap|foldl|foldl1|foldr|foldr1|fromDouble|fromEnum|fromInt|fromInteger|fromIntegral|fromRational|fst|gcd|getChar|getContents|getLine|group|head|id|inRange|index|init|intToDigit|interact|ioError|isAlpha|isAlphaNum|isAscii|isControl|isDenormalized|isDigit|isHexDigit|isIEEE|isInfinite|isLower|isNaN|isNegativeZero|isOctDigit|isPrint|isSpace|isUpper|iterate|last|lcm|length|lex|lexDigits|lexLitChar|lines|log|logBase|lookup|map|mapM|mapM_|max|maxBound|maximum|maybe|min|minBound|minimum|mod|negate|not|notElem|null|numerator|odd|or|ord|otherwise|pack|pi|pred|primExitWith|print|product|properFraction|putChar|putStr|putStrLn|quot|quotRem|range|rangeSize|read|readDec|readFile|readFloat|readHex|readIO|readInt|readList|readLitChar|readLn|readOct|readParen|readSigned|reads|readsPrec|realToFrac|recip|rem|repeat|replicate|return|reverse|round|scaleFloat|scanl|scanl1|scanr|scanr1|seq|sequence|sequence_|show|showChar|showInt|showList|showLitChar|showParen|showSigned|showString|shows|showsPrec|significand|signum|sin|sinh|snd|sort|span|splitAt|sqrt|subtract|succ|sum|tail|take|takeWhile|tan|tanh|threadToIOResult|toEnum|toInt|toInteger|toLower|toRational|toUpper|truncate|uncurry|undefined|unlines|until|unwords|unzip|unzip3|userError|words|writeFile|zip|zip3|zipWith|zipWith3)\b/,number:/\b(?:\d+(?:\.\d+)?(?:e[+-]?\d+)?|0o[0-7]+|0x[0-9a-f]+)\b/i,operator:[{pattern:/`(?:[A-Z][\w']*\.)*[_a-z][\w']*`/,greedy:!0},{pattern:/(\s)\.(?=\s)/,lookbehind:!0},/[-!#$%*+=?&@|~:<>^\\\/][-!#$%*+=?&@|~.:<>^\\\/]*|\.[-!#$%*+=?&@|~.:<>^\\\/]+/],hvariable:{pattern:/\b(?:[A-Z][\w']*\.)*[_a-z][\w']*/,inside:{punctuation:/\./}},constant:{pattern:/\b(?:[A-Z][\w']*\.)*[A-Z][\w']*/,inside:{punctuation:/\./}},punctuation:/[{}[\];(),.:]/},t.languages.hs=t.languages.haskell}return Du}var Mu,vS;function bG(){if(vS)return Mu;vS=1,Mu=e,e.displayName="haxe",e.aliases=[];function e(t){t.languages.haxe=t.languages.extend("clike",{string:{pattern:/"(?:[^"\\]|\\[\s\S])*"/,greedy:!0},"class-name":[{pattern:/(\b(?:abstract|class|enum|extends|implements|interface|new|typedef)\s+)[A-Z_]\w*/,lookbehind:!0},/\b[A-Z]\w*/],keyword:/\bthis\b|\b(?:abstract|as|break|case|cast|catch|class|continue|default|do|dynamic|else|enum|extends|extern|final|for|from|function|if|implements|import|in|inline|interface|macro|new|null|operator|overload|override|package|private|public|return|static|super|switch|throw|to|try|typedef|untyped|using|var|while)(?!\.)\b/,function:{pattern:/\b[a-z_]\w*(?=\s*(?:<[^<>]*>\s*)?\()/i,greedy:!0},operator:/\.{3}|\+\+|--|&&|\|\||->|=>|(?:<{1,3}|[-+*/%!=&|^])=?|[?:~]/}),t.languages.insertBefore("haxe","string",{"string-interpolation":{pattern:/'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{interpolation:{pattern:/(^|[^\\])\$(?:\w+|\{[^{}]+\})/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:t.languages.haxe}}},string:/[\s\S]+/}}}),t.languages.insertBefore("haxe","class-name",{regex:{pattern:/~\/(?:[^\/\\\r\n]|\\.)+\/[a-z]*/,greedy:!0,inside:{"regex-flags":/\b[a-z]+$/,"regex-source":{pattern:/^(~\/)[\s\S]+(?=\/$)/,lookbehind:!0,alias:"language-regex",inside:t.languages.regex},"regex-delimiter":/^~\/|\/$/}}}),t.languages.insertBefore("haxe","keyword",{preprocessor:{pattern:/#(?:else|elseif|end|if)\b.*/,alias:"property"},metadata:{pattern:/@:?[\w.]+/,alias:"symbol"},reification:{pattern:/\$(?:\w+|(?=\{))/,alias:"important"}})}return Mu}var Fu,kS;function yG(){if(kS)return Fu;kS=1,Fu=e,e.displayName="hcl",e.aliases=[];function e(t){t.languages.hcl={comment:/(?:\/\/|#).*|\/\*[\s\S]*?(?:\*\/|$)/,heredoc:{pattern:/<<-?(\w+\b)[\s\S]*?^[ \t]*\1/m,greedy:!0,alias:"string"},keyword:[{pattern:/(?:data|resource)\s+(?:"(?:\\[\s\S]|[^\\"])*")(?=\s+"[\w-]+"\s+\{)/i,inside:{type:{pattern:/(resource|data|\s+)(?:"(?:\\[\s\S]|[^\\"])*")/i,lookbehind:!0,alias:"variable"}}},{pattern:/(?:backend|module|output|provider|provisioner|variable)\s+(?:[\w-]+|"(?:\\[\s\S]|[^\\"])*")\s+(?=\{)/i,inside:{type:{pattern:/(backend|module|output|provider|provisioner|variable)\s+(?:[\w-]+|"(?:\\[\s\S]|[^\\"])*")\s+/i,lookbehind:!0,alias:"variable"}}},/[\w-]+(?=\s+\{)/],property:[/[-\w\.]+(?=\s*=(?!=))/,/"(?:\\[\s\S]|[^\\"])+"(?=\s*[:=])/],string:{pattern:/"(?:[^\\$"]|\\[\s\S]|\$(?:(?=")|\$+(?!\$)|[^"${])|\$\{(?:[^{}"]|"(?:[^\\"]|\\[\s\S])*")*\})*"/,greedy:!0,inside:{interpolation:{pattern:/(^|[^$])\$\{(?:[^{}"]|"(?:[^\\"]|\\[\s\S])*")*\}/,lookbehind:!0,inside:{type:{pattern:/(\b(?:count|data|local|module|path|self|terraform|var)\b\.)[\w\*]+/i,lookbehind:!0,alias:"variable"},keyword:/\b(?:count|data|local|module|path|self|terraform|var)\b/i,function:/\w+(?=\()/,string:{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0},number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i,punctuation:/[!\$#%&'()*+,.\/;<=>@\[\\\]^`{|}~?:]/}}}},number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i,boolean:/\b(?:false|true)\b/i,punctuation:/[=\[\]{}]/}}return Fu}var Pu,wS;function EG(){if(wS)return Pu;wS=1;var e=tr();Pu=t,t.displayName="hlsl",t.aliases=[];function t(n){n.register(e),n.languages.hlsl=n.languages.extend("c",{"class-name":[n.languages.c["class-name"],/\b(?:AppendStructuredBuffer|BlendState|Buffer|ByteAddressBuffer|CompileShader|ComputeShader|ConsumeStructuredBuffer|DepthStencilState|DepthStencilView|DomainShader|GeometryShader|Hullshader|InputPatch|LineStream|OutputPatch|PixelShader|PointStream|RWBuffer|RWByteAddressBuffer|RWStructuredBuffer|RWTexture(?:1D|1DArray|2D|2DArray|3D)|RasterizerState|RenderTargetView|SamplerComparisonState|SamplerState|StructuredBuffer|Texture(?:1D|1DArray|2D|2DArray|2DMS|2DMSArray|3D|Cube|CubeArray)|TriangleStream|VertexShader)\b/],keyword:[/\b(?:asm|asm_fragment|auto|break|case|catch|cbuffer|centroid|char|class|column_major|compile|compile_fragment|const|const_cast|continue|default|delete|discard|do|dynamic_cast|else|enum|explicit|export|extern|for|friend|fxgroup|goto|groupshared|if|in|inline|inout|interface|line|lineadj|linear|long|matrix|mutable|namespace|new|nointerpolation|noperspective|operator|out|packoffset|pass|pixelfragment|point|precise|private|protected|public|register|reinterpret_cast|return|row_major|sample|sampler|shared|short|signed|sizeof|snorm|stateblock|stateblock_state|static|static_cast|string|struct|switch|tbuffer|technique|technique10|technique11|template|texture|this|throw|triangle|triangleadj|try|typedef|typename|uniform|union|unorm|unsigned|using|vector|vertexfragment|virtual|void|volatile|while)\b/,/\b(?:bool|double|dword|float|half|int|min(?:10float|12int|16(?:float|int|uint))|uint)(?:[1-4](?:x[1-4])?)?\b/],number:/(?:(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[eE][+-]?\d+)?|\b0x[\da-fA-F]+)[fFhHlLuU]?\b/,boolean:/\b(?:false|true)\b/})}return Pu}var Uu,_S;function SG(){if(_S)return Uu;_S=1,Uu=e,e.displayName="hoon",e.aliases=[];function e(t){t.languages.hoon={comment:{pattern:/::.*/,greedy:!0},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},constant:/%(?:\.[ny]|[\w-]+)/,"class-name":/@(?:[a-z0-9-]*[a-z0-9])?|\*/i,function:/(?:\+[-+] {2})?(?:[a-z](?:[a-z0-9-]*[a-z0-9])?)/,keyword:/\.[\^\+\*=\?]|![><:\.=\?!]|=[>|:,\.\-\^<+;/~\*\?]|\?[>|:\.\-\^<\+&~=@!]|\|[\$_%:\.\-\^~\*=@\?]|\+[|\$\+\*]|:[_\-\^\+~\*]|%[_:\.\-\^\+~\*=]|\^[|:\.\-\+&~\*=\?]|\$[|_%:<>\-\^&~@=\?]|;[:<\+;\/~\*=]|~[>|\$_%<\+\/&=\?!]|--|==/}}return Uu}var Bu,TS;function vG(){if(TS)return Bu;TS=1,Bu=e,e.displayName="hpkp",e.aliases=[];function e(t){t.languages.hpkp={directive:{pattern:/\b(?:includeSubDomains|max-age|pin-sha256|preload|report-to|report-uri|strict)(?=[\s;=]|$)/i,alias:"property"},operator:/=/,punctuation:/;/}}return Bu}var $u,AS;function kG(){if(AS)return $u;AS=1,$u=e,e.displayName="hsts",e.aliases=[];function e(t){t.languages.hsts={directive:{pattern:/\b(?:includeSubDomains|max-age|preload)(?=[\s;=]|$)/i,alias:"property"},operator:/=/,punctuation:/;/}}return $u}var zu,RS;function wG(){if(RS)return zu;RS=1,zu=e,e.displayName="http",e.aliases=[];function e(t){(function(n){function r(c){return RegExp("(^(?:"+c+"):[ ]*(?![ ]))[^]+","i")}n.languages.http={"request-line":{pattern:/^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PRI|PUT|SEARCH|TRACE)\s(?:https?:\/\/|\/)\S*\sHTTP\/[\d.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:n.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[\d.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[\d.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[\d.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},header:{pattern:/^[\w-]+:.+(?:(?:\r\n?|\n)[ \t].+)*/m,inside:{"header-value":[{pattern:r(/Content-Security-Policy/.source),lookbehind:!0,alias:["csp","languages-csp"],inside:n.languages.csp},{pattern:r(/Public-Key-Pins(?:-Report-Only)?/.source),lookbehind:!0,alias:["hpkp","languages-hpkp"],inside:n.languages.hpkp},{pattern:r(/Strict-Transport-Security/.source),lookbehind:!0,alias:["hsts","languages-hsts"],inside:n.languages.hsts},{pattern:r(/[^:]+/.source),lookbehind:!0}],"header-name":{pattern:/^[^:]+/,alias:"keyword"},punctuation:/^:/}}};var a=n.languages,i={"application/javascript":a.javascript,"application/json":a.json||a.javascript,"application/xml":a.xml,"text/xml":a.xml,"text/html":a.html,"text/css":a.css,"text/plain":a.plain},o={"application/json":!0,"application/xml":!0};function s(c){var f=c.replace(/^[a-z]+\//,""),p="\\w+/(?:[\\w.-]+\\+)+"+f+"(?![+\\w.-])";return"(?:"+c+"|"+p+")"}var l;for(var u in i)if(i[u]){l=l||{};var d=o[u]?s(u):u;l[u.replace(/\//g,"-")]={pattern:RegExp("("+/content-type:\s*/.source+d+/(?:(?:\r\n?|\n)[\w-].*)*(?:\r(?:\n|(?!\n))|\n)/.source+")"+/[^ \t\w-][\s\S]*/.source,"i"),lookbehind:!0,inside:i[u]}}l&&n.languages.insertBefore("http","header",l)})(t)}return zu}var Gu,IS;function _G(){if(IS)return Gu;IS=1,Gu=e,e.displayName="ichigojam",e.aliases=[];function e(t){t.languages.ichigojam={comment:/(?:\B'|REM)(?:[^\n\r]*)/i,string:{pattern:/"(?:""|[!#$%&'()*,\/:;<=>?^\w +\-.])*"/,greedy:!0},number:/\B#[0-9A-F]+|\B`[01]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?/i,keyword:/\b(?:BEEP|BPS|CASE|CLEAR|CLK|CLO|CLP|CLS|CLT|CLV|CONT|COPY|ELSE|END|FILE|FILES|FOR|GOSUB|GOTO|GSB|IF|INPUT|KBD|LED|LET|LIST|LOAD|LOCATE|LRUN|NEW|NEXT|OUT|PLAY|POKE|PRINT|PWM|REM|RENUM|RESET|RETURN|RIGHT|RTN|RUN|SAVE|SCROLL|SLEEP|SRND|STEP|STOP|SUB|TEMPO|THEN|TO|UART|VIDEO|WAIT)(?:\$|\b)/i,function:/\b(?:ABS|ANA|ASC|BIN|BTN|DEC|END|FREE|HELP|HEX|I2CR|I2CW|IN|INKEY|LEN|LINE|PEEK|RND|SCR|SOUND|STR|TICK|USR|VER|VPEEK|ZER)(?:\$|\b)/i,label:/(?:\B@\S+)/,operator:/<[=>]?|>=?|\|\||&&|[+\-*\/=|&^~!]|\b(?:AND|NOT|OR)\b/i,punctuation:/[\[,;:()\]]/}}return Gu}var qu,CS;function TG(){if(CS)return qu;CS=1,qu=e,e.displayName="icon",e.aliases=[];function e(t){t.languages.icon={comment:/#.*/,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n_]|\\.|_(?!\1)(?:\r\n|[\s\S]))*\1/,greedy:!0},number:/\b(?:\d+r[a-z\d]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b|\.\d+\b/i,"builtin-keyword":{pattern:/&(?:allocated|ascii|clock|collections|cset|current|date|dateline|digits|dump|e|error(?:number|text|value)?|errout|fail|features|file|host|input|lcase|letters|level|line|main|null|output|phi|pi|pos|progname|random|regions|source|storage|subject|time|trace|ucase|version)\b/,alias:"variable"},directive:{pattern:/\$\w+/,alias:"builtin"},keyword:/\b(?:break|by|case|create|default|do|else|end|every|fail|global|if|initial|invocable|link|local|next|not|of|procedure|record|repeat|return|static|suspend|then|to|until|while)\b/,function:/\b(?!\d)\w+(?=\s*[({]|\s*!\s*\[)/,operator:/[+-]:(?!=)|(?:[\/?@^%&]|\+\+?|--?|==?=?|~==?=?|\*\*?|\|\|\|?|<(?:->?|>?=?)(?::=)?|:(?:=:?)?|[!.\\|~]/,punctuation:/[\[\](){},;]/}}return qu}var ju,NS;function AG(){if(NS)return ju;NS=1,ju=e,e.displayName="icuMessageFormat",e.aliases=[];function e(t){(function(n){function r(u,d){return d<=0?/[]/.source:u.replace(//g,function(){return r(u,d-1)})}var a=/'[{}:=,](?:[^']|'')*'(?!')/,i={pattern:/''/,greedy:!0,alias:"operator"},o={pattern:a,greedy:!0,inside:{escape:i}},s=r(/\{(?:[^{}']|'(?![{},'])|''||)*\}/.source.replace(//g,function(){return a.source}),8),l={pattern:RegExp(s),inside:{message:{pattern:/^(\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:null},"message-delimiter":{pattern:/./,alias:"punctuation"}}};n.languages["icu-message-format"]={argument:{pattern:RegExp(s),greedy:!0,inside:{content:{pattern:/^(\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:{"argument-name":{pattern:/^(\s*)[^{}:=,\s]+/,lookbehind:!0},"choice-style":{pattern:/^(\s*,\s*choice\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{punctuation:/\|/,range:{pattern:/^(\s*)[+-]?(?:\d+(?:\.\d*)?|\u221e)\s*[<#\u2264]/,lookbehind:!0,inside:{operator:/[<#\u2264]/,number:/\S+/}},rest:null}},"plural-style":{pattern:/^(\s*,\s*(?:plural|selectordinal)\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{offset:/^offset:\s*\d+/,"nested-message":l,selector:{pattern:/=\d+|[^{}:=,\s]+/,inside:{keyword:/^(?:few|many|one|other|two|zero)$/}}}},"select-style":{pattern:/^(\s*,\s*select\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{"nested-message":l,selector:{pattern:/[^{}:=,\s]+/,inside:{keyword:/^other$/}}}},keyword:/\b(?:choice|plural|select|selectordinal)\b/,"arg-type":{pattern:/\b(?:date|duration|number|ordinal|spellout|time)\b/,alias:"keyword"},"arg-skeleton":{pattern:/(,\s*)::[^{}:=,\s]+/,lookbehind:!0},"arg-style":{pattern:/(,\s*)(?:currency|full|integer|long|medium|percent|short)(?=\s*$)/,lookbehind:!0},"arg-style-text":{pattern:RegExp(/(^\s*,\s*(?=\S))/.source+r(/(?:[^{}']|'[^']*'|\{(?:)?\})+/.source,8)+"$"),lookbehind:!0,alias:"string"},punctuation:/,/}},"argument-delimiter":{pattern:/./,alias:"operator"}}},escape:i,string:o},l.inside.message.inside=n.languages["icu-message-format"],n.languages["icu-message-format"].argument.inside.content.inside["choice-style"].inside.rest=n.languages["icu-message-format"]})(t)}return ju}var Hu,xS;function RG(){if(xS)return Hu;xS=1;var e=zm();Hu=t,t.displayName="idris",t.aliases=["idr"];function t(n){n.register(e),n.languages.idris=n.languages.extend("haskell",{comment:{pattern:/(?:(?:--|\|\|\|).*$|\{-[\s\S]*?-\})/m},keyword:/\b(?:Type|case|class|codata|constructor|corecord|data|do|dsl|else|export|if|implementation|implicit|import|impossible|in|infix|infixl|infixr|instance|interface|let|module|mutual|namespace|of|parameters|partial|postulate|private|proof|public|quoteGoal|record|rewrite|syntax|then|total|using|where|with)\b/,builtin:void 0}),n.languages.insertBefore("idris","keyword",{"import-statement":{pattern:/(^\s*import\s+)(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*/m,lookbehind:!0,inside:{punctuation:/\./}}}),n.languages.idr=n.languages.idris}return Hu}var Vu,OS;function IG(){if(OS)return Vu;OS=1,Vu=e,e.displayName="iecst",e.aliases=[];function e(t){t.languages.iecst={comment:[{pattern:/(^|[^\\])(?:\/\*[\s\S]*?(?:\*\/|$)|\(\*[\s\S]*?(?:\*\)|$)|\{[\s\S]*?(?:\}|$))/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:[/\b(?:END_)?(?:PROGRAM|CONFIGURATION|INTERFACE|FUNCTION_BLOCK|FUNCTION|ACTION|TRANSITION|TYPE|STRUCT|(?:INITIAL_)?STEP|NAMESPACE|LIBRARY|CHANNEL|FOLDER|RESOURCE|VAR_(?:ACCESS|CONFIG|EXTERNAL|GLOBAL|INPUT|IN_OUT|OUTPUT|TEMP)|VAR|METHOD|PROPERTY)\b/i,/\b(?:AT|BY|(?:END_)?(?:CASE|FOR|IF|REPEAT|WHILE)|CONSTANT|CONTINUE|DO|ELSE|ELSIF|EXIT|EXTENDS|FROM|GET|GOTO|IMPLEMENTS|JMP|NON_RETAIN|OF|PRIVATE|PROTECTED|PUBLIC|RETAIN|RETURN|SET|TASK|THEN|TO|UNTIL|USING|WITH|__CATCH|__ENDTRY|__FINALLY|__TRY)\b/],"class-name":/\b(?:ANY|ARRAY|BOOL|BYTE|U?(?:D|L|S)?INT|(?:D|L)?WORD|DATE(?:_AND_TIME)?|DT|L?REAL|POINTER|STRING|TIME(?:_OF_DAY)?|TOD)\b/,address:{pattern:/%[IQM][XBWDL][\d.]*|%[IQ][\d.]*/,alias:"symbol"},number:/\b(?:16#[\da-f]+|2#[01_]+|0x[\da-f]+)\b|\b(?:D|DT|T|TOD)#[\d_shmd:]*|\b[A-Z]*#[\d.,_]*|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/,operator:/S?R?:?=>?|&&?|\*\*?|<[=>]?|>=?|[-:^/+#]|\b(?:AND|EQ|EXPT|GE|GT|LE|LT|MOD|NE|NOT|OR|XOR)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,punctuation:/[()[\].,;]/}}return Vu}var Wu,LS;function CG(){if(LS)return Wu;LS=1,Wu=e,e.displayName="ignore",e.aliases=["gitignore","hgignore","npmignore"];function e(t){(function(n){n.languages.ignore={comment:/^#.*/m,entry:{pattern:/\S(?:.*(?:(?:\\ )|\S))?/,alias:"string",inside:{operator:/^!|\*\*?|\?/,regex:{pattern:/(^|[^\\])\[[^\[\]]*\]/,lookbehind:!0},punctuation:/\//}}},n.languages.gitignore=n.languages.ignore,n.languages.hgignore=n.languages.ignore,n.languages.npmignore=n.languages.ignore})(t)}return Wu}var Yu,DS;function NG(){if(DS)return Yu;DS=1,Yu=e,e.displayName="inform7",e.aliases=[];function e(t){t.languages.inform7={string:{pattern:/"[^"]*"/,inside:{substitution:{pattern:/\[[^\[\]]+\]/,inside:{delimiter:{pattern:/\[|\]/,alias:"punctuation"}}}}},comment:{pattern:/\[[^\[\]]+\]/,greedy:!0},title:{pattern:/^[ \t]*(?:book|chapter|part(?! of)|section|table|volume)\b.+/im,alias:"important"},number:{pattern:/(^|[^-])(?:\b\d+(?:\.\d+)?(?:\^\d+)?(?:(?!\d)\w+)?|\b(?:eight|eleven|five|four|nine|one|seven|six|ten|three|twelve|two))\b(?!-)/i,lookbehind:!0},verb:{pattern:/(^|[^-])\b(?:answering|applying to|are|asking|attacking|be(?:ing)?|burning|buying|called|carries|carry(?! out)|carrying|climbing|closing|conceal(?:ing|s)?|consulting|contain(?:ing|s)?|cutting|drinking|dropping|eating|enclos(?:es?|ing)|entering|examining|exiting|getting|giving|going|ha(?:s|ve|ving)|hold(?:ing|s)?|impl(?:ies|y)|incorporat(?:es?|ing)|inserting|is|jumping|kissing|listening|locking|looking|mean(?:ing|s)?|opening|provid(?:es?|ing)|pulling|pushing|putting|relat(?:es?|ing)|removing|searching|see(?:ing|s)?|setting|showing|singing|sleeping|smelling|squeezing|support(?:ing|s)?|swearing|switching|taking|tasting|telling|thinking|throwing|touching|turning|tying|unlock(?:ing|s)?|var(?:ies|y|ying)|waiting|waking|waving|wear(?:ing|s)?)\b(?!-)/i,lookbehind:!0,alias:"operator"},keyword:{pattern:/(^|[^-])\b(?:after|before|carry out|check|continue the action|definition(?= *:)|do nothing|else|end (?:if|the story|unless)|every turn|if|include|instead(?: of)?|let|move|no|now|otherwise|repeat|report|resume the story|rule for|running through|say(?:ing)?|stop the action|test|try(?:ing)?|understand|unless|use|when|while|yes)\b(?!-)/i,lookbehind:!0},property:{pattern:/(^|[^-])\b(?:adjacent(?! to)|carried|closed|concealed|contained|dark|described|edible|empty|enclosed|enterable|even|female|fixed in place|full|handled|held|improper-named|incorporated|inedible|invisible|lighted|lit|lock(?:able|ed)|male|marked for listing|mentioned|negative|neuter|non-(?:empty|full|recurring)|odd|opaque|open(?:able)?|plural-named|portable|positive|privately-named|proper-named|provided|publically-named|pushable between rooms|recurring|related|rubbing|scenery|seen|singular-named|supported|swinging|switch(?:able|ed(?: off| on)?)|touch(?:able|ed)|transparent|unconcealed|undescribed|unlit|unlocked|unmarked for listing|unmentioned|unopenable|untouchable|unvisited|variable|visible|visited|wearable|worn)\b(?!-)/i,lookbehind:!0,alias:"symbol"},position:{pattern:/(^|[^-])\b(?:above|adjacent to|back side of|below|between|down|east|everywhere|front side|here|in|inside(?: from)?|north(?:east|west)?|nowhere|on(?: top of)?|other side|outside(?: from)?|parts? of|regionally in|south(?:east|west)?|through|up|west|within)\b(?!-)/i,lookbehind:!0,alias:"keyword"},type:{pattern:/(^|[^-])\b(?:actions?|activit(?:ies|y)|actors?|animals?|backdrops?|containers?|devices?|directions?|doors?|holders?|kinds?|lists?|m[ae]n|nobody|nothing|nouns?|numbers?|objects?|people|persons?|player(?:'s holdall)?|regions?|relations?|rooms?|rule(?:book)?s?|scenes?|someone|something|supporters?|tables?|texts?|things?|time|vehicles?|wom[ae]n)\b(?!-)/i,lookbehind:!0,alias:"variable"},punctuation:/[.,:;(){}]/},t.languages.inform7.string.inside.substitution.inside.rest=t.languages.inform7,t.languages.inform7.string.inside.substitution.inside.rest.text={pattern:/\S(?:\s*\S)*/,alias:"comment"}}return Yu}var Ku,MS;function xG(){if(MS)return Ku;MS=1,Ku=e,e.displayName="ini",e.aliases=[];function e(t){t.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},section:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/}}return Ku}var Xu,FS;function OG(){if(FS)return Xu;FS=1,Xu=e,e.displayName="io",e.aliases=[];function e(t){t.languages.io={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?(?:\*\/|$)|\/\/.*|#.*)/,lookbehind:!0,greedy:!0},"triple-quoted-string":{pattern:/"""(?:\\[\s\S]|(?!""")[^\\])*"""/,greedy:!0,alias:"string"},string:{pattern:/"(?:\\.|[^\\\r\n"])*"/,greedy:!0},keyword:/\b(?:activate|activeCoroCount|asString|block|break|call|catch|clone|collectGarbage|compileString|continue|do|doFile|doMessage|doString|else|elseif|exit|for|foreach|forward|getEnvironmentVariable|getSlot|hasSlot|if|ifFalse|ifNil|ifNilEval|ifTrue|isActive|isNil|isResumable|list|message|method|parent|pass|pause|perform|performWithArgList|print|println|proto|raise|raiseResumable|removeSlot|resend|resume|schedulerSleepSeconds|self|sender|setSchedulerSleepSeconds|setSlot|shallowCopy|slotNames|super|system|then|thisBlock|thisContext|try|type|uniqueId|updateSlot|wait|while|write|yield)\b/,builtin:/\b(?:Array|AudioDevice|AudioMixer|BigNum|Block|Box|Buffer|CFunction|CGI|Color|Curses|DBM|DNSResolver|DOConnection|DOProxy|DOServer|Date|Directory|Duration|DynLib|Error|Exception|FFT|File|Fnmatch|Font|Future|GL|GLE|GLScissor|GLU|GLUCylinder|GLUQuadric|GLUSphere|GLUT|Host|Image|Importer|LinkList|List|Lobby|Locals|MD5|MP3Decoder|MP3Encoder|Map|Message|Movie|Notification|Number|Object|OpenGL|Point|Protos|Random|Regex|SGML|SGMLElement|SGMLParser|SQLite|Sequence|Server|ShowMessage|SleepyCat|SleepyCatCursor|Socket|SocketManager|Sound|Soup|Store|String|Tree|UDPSender|UPDReceiver|URL|User|Warning|WeakLink)\b/,boolean:/\b(?:false|nil|true)\b/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e-?\d+)?/i,operator:/[=!*/%+\-^&|]=|>>?=?|<+*\-%$|,#][.:]?|[?^]\.?|[;\[]:?|[~}"i][.:]|[ACeEIjLor]\.|(?:[_\/\\qsux]|_?\d):)/,alias:"keyword"},number:/\b_?(?:(?!\d:)\d+(?:\.\d+)?(?:(?:ad|ar|[ejpx])_?\d+(?:\.\d+)?)*(?:b_?[\da-z]+(?:\.[\da-z]+)?)?|_\b(?!\.))/,adverb:{pattern:/[~}]|[\/\\]\.?|[bfM]\.|t[.:]/,alias:"builtin"},operator:/[=a][.:]|_\./,conjunction:{pattern:/&(?:\.:?|:)?|[.:@][.:]?|[!D][.:]|[;dHT]\.|`:?|[\^LS]:|"/,alias:"variable"},punctuation:/[()]/}}return Zu}var Qu,US;function Gm(){if(US)return Qu;US=1,Qu=e,e.displayName="java",e.aliases=[];function e(t){(function(n){var r=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,a=/(^|[^\w.])(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,i={pattern:RegExp(a+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};n.languages.java=n.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[i,{pattern:RegExp(a+/[A-Z]\w*(?=\s+\w+\s*[;,=()])/.source),lookbehind:!0,inside:i.inside}],keyword:r,function:[n.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),n.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),n.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":i,keyword:r,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,function(){return r.source})),lookbehind:!0,inside:{punctuation:/\./}}})})(t)}return Qu}var Ju,BS;function Qo(){if(BS)return Ju;BS=1,Ju=e,e.displayName="javadoclike",e.aliases=[];function e(t){(function(n){var r=n.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};function a(o,s){var l="doc-comment",u=n.languages[o];if(u){var d=u[l];if(!d){var c={};c[l]={pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"},u=n.languages.insertBefore(o,"comment",c),d=u[l]}if(d instanceof RegExp&&(d=u[l]={pattern:d}),Array.isArray(d))for(var f=0,p=d.length;f)?|/.source.replace(//g,function(){return o});a.languages.javadoc=a.languages.extend("javadoclike",{}),a.languages.insertBefore("javadoc","keyword",{reference:{pattern:RegExp(/(@(?:exception|link|linkplain|see|throws|value)\s+(?:\*\s*)?)/.source+"(?:"+s+")"),lookbehind:!0,inside:{function:{pattern:/(#\s*)\w+(?=\s*\()/,lookbehind:!0},field:{pattern:/(#\s*)\w+/,lookbehind:!0},namespace:{pattern:/\b(?:[a-z]\w*\s*\.\s*)+/,inside:{punctuation:/\./}},"class-name":/\b[A-Z]\w*/,keyword:a.languages.java.keyword,punctuation:/[#()[\],.]/}},"class-name":{pattern:/(@param\s+)<[A-Z]\w*>/,lookbehind:!0,inside:{punctuation:/[.<>]/}},"code-section":[{pattern:/(\{@code\s+(?!\s))(?:[^\s{}]|\s+(?![\s}])|\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*\})+(?=\s*\})/,lookbehind:!0,inside:{code:{pattern:i,lookbehind:!0,inside:a.languages.java,alias:"language-java"}}},{pattern:/(<(code|pre|tt)>(?!)\s*)\S(?:\S|\s+\S)*?(?=\s*<\/\2>)/,lookbehind:!0,inside:{line:{pattern:i,lookbehind:!0,inside:{tag:a.languages.markup.tag,entity:a.languages.markup.entity,code:{pattern:/.+/,inside:a.languages.java,alias:"language-java"}}}}}],tag:a.languages.markup.tag,entity:a.languages.markup.entity}),a.languages.javadoclike.addSupport("java",a.languages.javadoc)}(r)}return ec}var tc,zS;function MG(){if(zS)return tc;zS=1,tc=e,e.displayName="javastacktrace",e.aliases=[];function e(t){t.languages.javastacktrace={summary:{pattern:/^([\t ]*)(?:(?:Caused by:|Suppressed:|Exception in thread "[^"]*")[\t ]+)?[\w$.]+(?::.*)?$/m,lookbehind:!0,inside:{keyword:{pattern:/^([\t ]*)(?:(?:Caused by|Suppressed)(?=:)|Exception in thread)/m,lookbehind:!0},string:{pattern:/^(\s*)"[^"]*"/,lookbehind:!0},exceptions:{pattern:/^(:?\s*)[\w$.]+(?=:|$)/,lookbehind:!0,inside:{"class-name":/[\w$]+$/,namespace:/\b[a-z]\w*\b/,punctuation:/\./}},message:{pattern:/(:\s*)\S.*/,lookbehind:!0,alias:"string"},punctuation:/:/}},"stack-frame":{pattern:/^([\t ]*)at (?:[\w$./]|@[\w$.+-]*\/)+(?:)?\([^()]*\)/m,lookbehind:!0,inside:{keyword:{pattern:/^(\s*)at(?= )/,lookbehind:!0},source:[{pattern:/(\()\w+\.\w+:\d+(?=\))/,lookbehind:!0,inside:{file:/^\w+\.\w+/,punctuation:/:/,"line-number":{pattern:/\b\d+\b/,alias:"number"}}},{pattern:/(\()[^()]*(?=\))/,lookbehind:!0,inside:{keyword:/^(?:Native Method|Unknown Source)$/}}],"class-name":/[\w$]+(?=\.(?:|[\w$]+)\()/,function:/(?:|[\w$]+)(?=\()/,"class-loader":{pattern:/(\s)[a-z]\w*(?:\.[a-z]\w*)*(?=\/[\w@$.]*\/)/,lookbehind:!0,alias:"namespace",inside:{punctuation:/\./}},module:{pattern:/([\s/])[a-z]\w*(?:\.[a-z]\w*)*(?:@[\w$.+-]*)?(?=\/)/,lookbehind:!0,inside:{version:{pattern:/(@)[\s\S]+/,lookbehind:!0,alias:"number"},punctuation:/[@.]/}},namespace:{pattern:/(?:\b[a-z]\w*\.)+/,inside:{punctuation:/\./}},punctuation:/[()/.]/}},more:{pattern:/^([\t ]*)\.{3} \d+ [a-z]+(?: [a-z]+)*/m,lookbehind:!0,inside:{punctuation:/\.{3}/,number:/\d+/,keyword:/\b[a-z]+(?: [a-z]+)*\b/}}}}return tc}var nc,GS;function FG(){if(GS)return nc;GS=1,nc=e,e.displayName="jexl",e.aliases=[];function e(t){t.languages.jexl={string:/(["'])(?:\\[\s\S]|(?!\1)[^\\])*\1/,transform:{pattern:/(\|\s*)[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$][\wа-яА-Я\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$]*/,alias:"function",lookbehind:!0},function:/[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$][\wа-яА-Я\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$]*\s*(?=\()/,number:/\b\d+(?:\.\d+)?\b|\B\.\d+\b/,operator:/[<>!]=?|-|\+|&&|==|\|\|?|\/\/?|[?:*^%]/,boolean:/\b(?:false|true)\b/,keyword:/\bin\b/,punctuation:/[{}[\](),.]/}}return nc}var rc,qS;function PG(){if(qS)return rc;qS=1,rc=e,e.displayName="jolie",e.aliases=[];function e(t){t.languages.jolie=t.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\[\s\S]|[^"\\])*"/,lookbehind:!0,greedy:!0},"class-name":{pattern:/((?:\b(?:as|courier|embed|in|inputPort|outputPort|service)\b|@)[ \t]*)\w+/,lookbehind:!0},keyword:/\b(?:as|cH|comp|concurrent|constants|courier|cset|csets|default|define|else|embed|embedded|execution|exit|extender|for|foreach|forward|from|global|if|import|in|include|init|inputPort|install|instanceof|interface|is_defined|linkIn|linkOut|main|new|nullProcess|outputPort|over|private|provide|public|scope|sequential|service|single|spawn|synchronized|this|throw|throws|type|undef|until|while|with)\b/,function:/\b[a-z_]\w*(?=[ \t]*[@(])/i,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?l?/i,operator:/-[-=>]?|\+[+=]?|<[<=]?|[>=*!]=?|&&|\|\||[?\/%^@|]/,punctuation:/[()[\]{},;.:]/,builtin:/\b(?:Byte|any|bool|char|double|enum|float|int|length|long|ranges|regex|string|undefined|void)\b/}),t.languages.insertBefore("jolie","keyword",{aggregates:{pattern:/(\bAggregates\s*:\s*)(?:\w+(?:\s+with\s+\w+)?\s*,\s*)*\w+(?:\s+with\s+\w+)?/,lookbehind:!0,inside:{keyword:/\bwith\b/,"class-name":/\w+/,punctuation:/,/}},redirects:{pattern:/(\bRedirects\s*:\s*)(?:\w+\s*=>\s*\w+\s*,\s*)*(?:\w+\s*=>\s*\w+)/,lookbehind:!0,inside:{punctuation:/,/,"class-name":/\w+/,operator:/=>/}},property:{pattern:/\b(?:Aggregates|[Ii]nterfaces|Java|Javascript|Jolie|[Ll]ocation|OneWay|[Pp]rotocol|Redirects|RequestResponse)\b(?=[ \t]*:)/}})}return rc}var ac,jS;function UG(){if(jS)return ac;jS=1,ac=e,e.displayName="jq",e.aliases=[];function e(t){(function(n){var r=/\\\((?:[^()]|\([^()]*\))*\)/.source,a=RegExp(/(^|[^\\])"(?:[^"\r\n\\]|\\[^\r\n(]|__)*"/.source.replace(/__/g,function(){return r})),i={interpolation:{pattern:RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+r),lookbehind:!0,inside:{content:{pattern:/^(\\\()[\s\S]+(?=\)$)/,lookbehind:!0,inside:null},punctuation:/^\\\(|\)$/}}},o=n.languages.jq={comment:/#.*/,property:{pattern:RegExp(a.source+/(?=\s*:(?!:))/.source),lookbehind:!0,greedy:!0,inside:i},string:{pattern:a,lookbehind:!0,greedy:!0,inside:i},function:{pattern:/(\bdef\s+)[a-z_]\w+/i,lookbehind:!0},variable:/\B\$\w+/,"property-literal":{pattern:/\b[a-z_]\w*(?=\s*:(?!:))/i,alias:"property"},keyword:/\b(?:as|break|catch|def|elif|else|end|foreach|if|import|include|label|module|modulemeta|null|reduce|then|try|while)\b/,boolean:/\b(?:false|true)\b/,number:/(?:\b\d+\.|\B\.)?\b\d+(?:[eE][+-]?\d+)?\b/,operator:[{pattern:/\|=?/,alias:"pipe"},/\.\.|[!=<>]?=|\?\/\/|\/\/=?|[-+*/%]=?|[<>?]|\b(?:and|not|or)\b/],"c-style-function":{pattern:/\b[a-z_]\w*(?=\s*\()/i,alias:"function"},punctuation:/::|[()\[\]{},:;]|\.(?=\s*[\[\w$])/,dot:{pattern:/\./,alias:"important"}};i.interpolation.inside.content.inside=o})(t)}return ac}var ic,HS;function BG(){if(HS)return ic;HS=1,ic=e,e.displayName="jsExtras",e.aliases=[];function e(t){(function(n){n.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+n.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),n.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+n.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),n.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]});function r(u,d){return RegExp(u.replace(//g,function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source}),d)}n.languages.insertBefore("javascript","keyword",{imports:{pattern:r(/(\bimport\b\s*)(?:(?:\s*,\s*(?:\*\s*as\s+|\{[^{}]*\}))?|\*\s*as\s+|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:n.languages.javascript},exports:{pattern:r(/(\bexport\b\s*)(?:\*(?:\s*as\s+)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:n.languages.javascript}}),n.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),n.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),n.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:r(/(\.\s*)#?/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var a=["function","function-variable","method","method-variable","property-access"],i=0;i=R.length)return;var I=N[k];if(typeof I=="string"||typeof I.content=="string"){var D=R[m],q=typeof I=="string"?I:I.content,$=q.indexOf(D);if($!==-1){++m;var z=q.substring(0,$),H=c(v[D]),Y=q.substring($+D.length),x=[];if(z&&x.push(z),x.push(H),Y){var M=[Y];C(M),x.push.apply(x,M)}typeof I=="string"?(N.splice.apply(N,[k,1].concat(x)),k+=x.length-1):I.content=x}}else{var S=I.content;Array.isArray(S)?C(S):C([S])}}}return C(E),new n.Token(b,E,"language-"+b,y)}var p={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};n.hooks.add("after-tokenize",function(y){if(!(y.language in p))return;function T(b){for(var g=0,m=b.length;g]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),n.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete n.languages.typescript.parameter,delete n.languages.typescript["literal-property"];var r=n.languages.extend("typescript",{});delete r["class-name"],n.languages.typescript["class-name"].inside=r,n.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:r}}}}),n.languages.ts=n.languages.typescript})(t)}return sc}var lc,YS;function zG(){if(YS)return lc;YS=1;var e=Qo(),t=qm();lc=n,n.displayName="jsdoc",n.aliases=[];function n(r){r.register(e),r.register(t),function(a){var i=a.languages.javascript,o=/\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})+\}/.source,s="(@(?:arg|argument|param|property)\\s+(?:"+o+"\\s+)?)";a.languages.jsdoc=a.languages.extend("javadoclike",{parameter:{pattern:RegExp(s+/(?:(?!\s)[$\w\xA0-\uFFFF.])+(?=\s|$)/.source),lookbehind:!0,inside:{punctuation:/\./}}}),a.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(s+/\[(?:(?!\s)[$\w\xA0-\uFFFF.])+(?:=[^[\]]+)?\](?=\s|$)/.source),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:i,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp(/(@(?:augments|class|extends|interface|memberof!?|template|this|typedef)\s+(?:\s+)?)[A-Z]\w*(?:\.[A-Z]\w*)*/.source.replace(//g,function(){return o})),lookbehind:!0,inside:{punctuation:/\./}},{pattern:RegExp("(@[a-z]+\\s+)"+o),lookbehind:!0,inside:{string:i.string,number:i.number,boolean:i.boolean,keyword:a.languages.typescript.keyword,operator:/=>|\.\.\.|[&|?:*]/,punctuation:/[.,;=<>{}()[\]]/}}],example:{pattern:/(@example\s+(?!\s))(?:[^@\s]|\s+(?!\s))+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^([\t ]*(?:\*\s*)?)\S.*$/m,lookbehind:!0,inside:i,alias:"language-javascript"}}}}),a.languages.javadoclike.addSupport("javascript",a.languages.jsdoc)}(r)}return lc}var uc,KS;function jm(){if(KS)return uc;KS=1,uc=e,e.displayName="json",e.aliases=["webmanifest"];function e(t){t.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},t.languages.webmanifest=t.languages.json}return uc}var cc,XS;function GG(){if(XS)return cc;XS=1;var e=jm();cc=t,t.displayName="json5",t.aliases=[];function t(n){n.register(e),function(r){var a=/("|')(?:\\(?:\r\n?|\n|.)|(?!\1)[^\\\r\n])*\1/;r.languages.json5=r.languages.extend("json",{property:[{pattern:RegExp(a.source+"(?=\\s*:)"),greedy:!0},{pattern:/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/,alias:"unquoted"}],string:{pattern:a,greedy:!0},number:/[+-]?\b(?:NaN|Infinity|0x[a-fA-F\d]+)\b|[+-]?(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[eE][+-]?\d+\b)?/})}(n)}return cc}var dc,ZS;function qG(){if(ZS)return dc;ZS=1;var e=jm();dc=t,t.displayName="jsonp",t.aliases=[];function t(n){n.register(e),n.languages.jsonp=n.languages.extend("json",{punctuation:/[{}[\]();,.]/}),n.languages.insertBefore("jsonp","punctuation",{function:/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*\()/})}return dc}var pc,QS;function jG(){if(QS)return pc;QS=1,pc=e,e.displayName="jsstacktrace",e.aliases=[];function e(t){t.languages.jsstacktrace={"error-message":{pattern:/^\S.*/m,alias:"string"},"stack-frame":{pattern:/(^[ \t]+)at[ \t].*/m,lookbehind:!0,inside:{"not-my-code":{pattern:/^at[ \t]+(?!\s)(?:node\.js||.*(?:node_modules|\(\)|\(|$|\(internal\/|\(node\.js)).*/m,alias:"comment"},filename:{pattern:/(\bat\s+(?!\s)|\()(?:[a-zA-Z]:)?[^():]+(?=:)/,lookbehind:!0,alias:"url"},function:{pattern:/(\bat\s+(?:new\s+)?)(?!\s)[_$a-zA-Z\xA0-\uFFFF<][.$\w\xA0-\uFFFF<>]*/,lookbehind:!0,inside:{punctuation:/\./}},punctuation:/[()]/,keyword:/\b(?:at|new)\b/,alias:{pattern:/\[(?:as\s+)?(?!\s)[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\]/,alias:"variable"},"line-number":{pattern:/:\d+(?::\d+)?\b/,alias:"number",inside:{punctuation:/:/}}}}}}return pc}var fc,JS;function HR(){if(JS)return fc;JS=1,fc=e,e.displayName="jsx",e.aliases=[];function e(t){(function(n){var r=n.util.clone(n.languages.javascript),a=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,i=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,o=/(?:\{*\.{3}(?:[^{}]|)*\})/.source;function s(d,c){return d=d.replace(//g,function(){return a}).replace(//g,function(){return i}).replace(//g,function(){return o}),RegExp(d,c)}o=s(o).source,n.languages.jsx=n.languages.extend("markup",r),n.languages.jsx.tag.pattern=s(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),n.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,n.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,n.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,n.languages.jsx.tag.inside.comment=r.comment,n.languages.insertBefore("inside","attr-name",{spread:{pattern:s(//.source),inside:n.languages.jsx}},n.languages.jsx.tag),n.languages.insertBefore("inside","special-attr",{script:{pattern:s(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:n.languages.jsx}}},n.languages.jsx.tag);var l=function(d){return d?typeof d=="string"?d:typeof d.content=="string"?d.content:d.content.map(l).join(""):""},u=function(d){for(var c=[],f=0;f0&&c[c.length-1].tagName===l(p.content[0].content[1])&&c.pop():p.content[p.content.length-1].content==="/>"||c.push({tagName:l(p.content[0].content[1]),openedBraces:0}):c.length>0&&p.type==="punctuation"&&p.content==="{"?c[c.length-1].openedBraces++:c.length>0&&c[c.length-1].openedBraces>0&&p.type==="punctuation"&&p.content==="}"?c[c.length-1].openedBraces--:h=!0),(h||typeof p=="string")&&c.length>0&&c[c.length-1].openedBraces===0){var y=l(p);f0&&(typeof d[f-1]=="string"||d[f-1].type==="plain-text")&&(y=l(d[f-1])+y,d.splice(f-1,1),f--),d[f]=new n.Token("plain-text",y,null,y)}p.content&&typeof p.content!="string"&&u(p.content)}};n.hooks.add("after-tokenize",function(d){d.language!=="jsx"&&d.language!=="tsx"||u(d.tokens)})})(t)}return fc}var gc,ev;function HG(){if(ev)return gc;ev=1,gc=e,e.displayName="julia",e.aliases=[];function e(t){t.languages.julia={comment:{pattern:/(^|[^\\])(?:#=(?:[^#=]|=(?!#)|#(?!=)|#=(?:[^#=]|=(?!#)|#(?!=))*=#)*=#|#.*)/,lookbehind:!0},regex:{pattern:/r"(?:\\.|[^"\\\r\n])*"[imsx]{0,4}/,greedy:!0},string:{pattern:/"""[\s\S]+?"""|(?:\b\w+)?"(?:\\.|[^"\\\r\n])*"|`(?:[^\\`\r\n]|\\.)*`/,greedy:!0},char:{pattern:/(^|[^\w'])'(?:\\[^\r\n][^'\r\n]*|[^\\\r\n])'/,lookbehind:!0,greedy:!0},keyword:/\b(?:abstract|baremodule|begin|bitstype|break|catch|ccall|const|continue|do|else|elseif|end|export|finally|for|function|global|if|immutable|import|importall|in|let|local|macro|module|print|println|quote|return|struct|try|type|typealias|using|while)\b/,boolean:/\b(?:false|true)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[box])?(?:[\da-f]+(?:_[\da-f]+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[efp][+-]?\d+(?:_\d+)*)?j?/i,operator:/&&|\|\||[-+*^%÷⊻&$\\]=?|\/[\/=]?|!=?=?|\|[=>]?|<(?:<=?|[=:|])?|>(?:=|>>?=?)?|==?=?|[~≠≤≥'√∛]/,punctuation:/::?|[{}[\]();,.?]/,constant:/\b(?:(?:Inf|NaN)(?:16|32|64)?|im|pi)\b|[πℯ]/}}return gc}var mc,tv;function VG(){if(tv)return mc;tv=1,mc=e,e.displayName="keepalived",e.aliases=[];function e(t){t.languages.keepalived={comment:{pattern:/[#!].*/,greedy:!0},string:{pattern:/(^|[^\\])(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/,lookbehind:!0,greedy:!0},ip:{pattern:RegExp(/\b(?:(?:(?:[\da-f]{1,4}:){7}[\da-f]{1,4}|(?:[\da-f]{1,4}:){6}:[\da-f]{1,4}|(?:[\da-f]{1,4}:){5}:(?:[\da-f]{1,4}:)?[\da-f]{1,4}|(?:[\da-f]{1,4}:){4}:(?:[\da-f]{1,4}:){0,2}[\da-f]{1,4}|(?:[\da-f]{1,4}:){3}:(?:[\da-f]{1,4}:){0,3}[\da-f]{1,4}|(?:[\da-f]{1,4}:){2}:(?:[\da-f]{1,4}:){0,4}[\da-f]{1,4}|(?:[\da-f]{1,4}:){6}|(?:[\da-f]{1,4}:){0,5}:|::(?:[\da-f]{1,4}:){0,5}|[\da-f]{1,4}::(?:[\da-f]{1,4}:){0,5}[\da-f]{1,4}|::(?:[\da-f]{1,4}:){0,6}[\da-f]{1,4}|(?:[\da-f]{1,4}:){1,7}:)(?:\/\d{1,3})?|(?:\/\d{1,2})?)\b/.source.replace(//g,function(){return/(?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d))/.source}),"i"),alias:"number"},path:{pattern:/(\s)\/(?:[^\/\s]+\/)*[^\/\s]*|\b[a-zA-Z]:\\(?:[^\\\s]+\\)*[^\\\s]*/,lookbehind:!0,alias:"string"},variable:/\$\{?\w+\}?/,email:{pattern:/[\w-]+@[\w-]+(?:\.[\w-]{2,3}){1,2}/,alias:"string"},"conditional-configuration":{pattern:/@\^?[\w-]+/,alias:"variable"},operator:/=/,property:/\b(?:BFD_CHECK|DNS_CHECK|FILE_CHECK|HTTP_GET|MISC_CHECK|NAME|PING_CHECK|SCRIPTS|SMTP_CHECK|SSL|SSL_GET|TCP_CHECK|UDP_CHECK|accept|advert_int|alpha|auth_pass|auth_type|authentication|bfd_cpu_affinity|bfd_instance|bfd_no_swap|bfd_priority|bfd_process_name|bfd_rlimit_rttime|bfd_rt_priority|bind_if|bind_port|bindto|ca|certificate|check_unicast_src|checker|checker_cpu_affinity|checker_log_all_failures|checker_no_swap|checker_priority|checker_rlimit_rttime|checker_rt_priority|child_wait_time|connect_ip|connect_port|connect_timeout|dbus_service_name|debug|default_interface|delay|delay_before_retry|delay_loop|digest|dont_track_primary|dynamic|dynamic_interfaces|enable_(?:dbus|script_security|sni|snmp_checker|snmp_rfc|snmp_rfcv2|snmp_rfcv3|snmp_vrrp|traps)|end|fall|fast_recovery|file|flag-[123]|fork_delay|full_command|fwmark|garp_group|garp_interval|garp_lower_prio_delay|garp_lower_prio_repeat|garp_master_delay|garp_master_refresh|garp_master_refresh_repeat|garp_master_repeat|global_defs|global_tracking|gna_interval|group|ha_suspend|hashed|helo_name|higher_prio_send_advert|hoplimit|http_protocol|hysteresis|idle_tx|include|inhibit_on_failure|init_fail|init_file|instance|interface|interfaces|interval|ip_family|ipvs_process_name|keepalived.conf|kernel_rx_buf_size|key|linkbeat_interfaces|linkbeat_use_polling|log_all_failures|log_unknown_vrids|lower_prio_no_advert|lthreshold|lvs_flush|lvs_flush_onstop|lvs_method|lvs_netlink_cmd_rcv_bufs|lvs_netlink_cmd_rcv_bufs_force|lvs_netlink_monitor_rcv_bufs|lvs_netlink_monitor_rcv_bufs_force|lvs_notify_fifo|lvs_notify_fifo_script|lvs_sched|lvs_sync_daemon|max_auto_priority|max_hops|mcast_src_ip|mh-fallback|mh-port|min_auto_priority_delay|min_rx|min_tx|misc_dynamic|misc_path|misc_timeout|multiplier|name|namespace_with_ipsets|native_ipv6|neighbor_ip|net_namespace|net_namespace_ipvs|nftables|nftables_counters|nftables_ifindex|nftables_priority|no_accept|no_checker_emails|no_email_faults|nopreempt|notification_email|notification_email_from|notify|notify_backup|notify_deleted|notify_down|notify_fault|notify_fifo|notify_fifo_script|notify_master|notify_master_rx_lower_pri|notify_priority_changes|notify_stop|notify_up|old_unicast_checksum|omega|ops|param_match|passive|password|path|persistence_engine|persistence_granularity|persistence_timeout|preempt|preempt_delay|priority|process|process_monitor_rcv_bufs|process_monitor_rcv_bufs_force|process_name|process_names|promote_secondaries|protocol|proxy_arp|proxy_arp_pvlan|quorum|quorum_down|quorum_max|quorum_up|random_seed|real_server|regex|regex_max_offset|regex_min_offset|regex_no_match|regex_options|regex_stack|reload_repeat|reload_time_file|require_reply|retry|rise|router_id|rs_init_notifies|script|script_user|sh-fallback|sh-port|shutdown_script|shutdown_script_timeout|skip_check_adv_addr|smtp_alert|smtp_alert_checker|smtp_alert_vrrp|smtp_connect_timeout|smtp_helo_name|smtp_server|snmp_socket|sorry_server|sorry_server_inhibit|sorry_server_lvs_method|source_ip|start|startup_script|startup_script_timeout|state|static_ipaddress|static_routes|static_rules|status_code|step|strict_mode|sync_group_tracking_weight|terminate_delay|timeout|track_bfd|track_file|track_group|track_interface|track_process|track_script|track_src_ip|ttl|type|umask|unicast_peer|unicast_src_ip|unicast_ttl|url|use_ipvlan|use_pid_dir|use_vmac|user|uthreshold|val[123]|version|virtual_ipaddress|virtual_ipaddress_excluded|virtual_router_id|virtual_routes|virtual_rules|virtual_server|virtual_server_group|virtualhost|vmac_xmit_base|vrrp|vrrp_(?:check_unicast_src|cpu_affinity|garp_interval|garp_lower_prio_delay|garp_lower_prio_repeat|garp_master_delay|garp_master_refresh|garp_master_refresh_repeat|garp_master_repeat|gna_interval|higher_prio_send_advert|instance|ipsets|iptables|lower_prio_no_advert|mcast_group4|mcast_group6|min_garp|netlink_cmd_rcv_bufs|netlink_cmd_rcv_bufs_force|netlink_monitor_rcv_bufs|netlink_monitor_rcv_bufs_force|no_swap|notify_fifo|notify_fifo_script|notify_priority_changes|priority|process_name|rlimit_rttime|rt_priority|rx_bufs_multiplier|rx_bufs_policy|script|skip_check_adv_addr|startup_delay|strict|sync_group|track_process|version)|warmup|weight)\b/,constant:/\b(?:A|AAAA|AH|BACKUP|CNAME|DR|MASTER|MX|NAT|NS|PASS|SCTP|SOA|TCP|TUN|TXT|UDP|dh|fo|lblc|lblcr|lc|mh|nq|ovf|rr|sed|sh|wlc|wrr)\b/,number:{pattern:/(^|[^\w.-])-?\d+(?:\.\d+)?/,lookbehind:!0},boolean:/\b(?:false|no|off|on|true|yes)\b/,punctuation:/[\{\}]/}}return mc}var hc,nv;function WG(){if(nv)return hc;nv=1,hc=e,e.displayName="keyman",e.aliases=[];function e(t){t.languages.keyman={comment:{pattern:/\bc .*/i,greedy:!0},string:{pattern:/"[^"\r\n]*"|'[^'\r\n]*'/,greedy:!0},"virtual-key":{pattern:/\[\s*(?:(?:ALT|CAPS|CTRL|LALT|LCTRL|NCAPS|RALT|RCTRL|SHIFT)\s+)*(?:[TKU]_[\w?]+|[A-E]\d\d?|"[^"\r\n]*"|'[^'\r\n]*')\s*\]/i,greedy:!0,alias:"function"},"header-keyword":{pattern:/&\w+/,alias:"bold"},"header-statement":{pattern:/\b(?:bitmap|bitmaps|caps always off|caps on only|copyright|hotkey|language|layout|message|name|shift frees caps|version)\b/i,alias:"bold"},"rule-keyword":{pattern:/\b(?:any|baselayout|beep|call|context|deadkey|dk|if|index|layer|notany|nul|outs|platform|reset|return|save|set|store|use)\b/i,alias:"keyword"},"structural-keyword":{pattern:/\b(?:ansi|begin|group|match|nomatch|unicode|using keys)\b/i,alias:"keyword"},"compile-target":{pattern:/\$(?:keyman|keymanonly|keymanweb|kmfl|weaver):/i,alias:"property"},number:/\b(?:U\+[\dA-F]+|d\d+|x[\da-f]+|\d+)\b/i,operator:/[+>\\$]|\.\./,punctuation:/[()=,]/}}return hc}var bc,rv;function YG(){if(rv)return bc;rv=1,bc=e,e.displayName="kotlin",e.aliases=["kt","kts"];function e(t){(function(n){n.languages.kotlin=n.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var r={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:r},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:r},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin})(t)}return bc}var yc,av;function KG(){if(av)return yc;av=1,yc=e,e.displayName="kumir",e.aliases=["kum"];function e(t){(function(n){var r=/\s\x00-\x1f\x22-\x2f\x3a-\x3f\x5b-\x5e\x60\x7b-\x7e/.source;function a(i,o){return RegExp(i.replace(//g,r),o)}n.languages.kumir={comment:{pattern:/\|.*/},prolog:{pattern:/#.*/,greedy:!0},string:{pattern:/"[^\n\r"]*"|'[^\n\r']*'/,greedy:!0},boolean:{pattern:a(/(^|[])(?:да|нет)(?=[]|$)/.source),lookbehind:!0},"operator-word":{pattern:a(/(^|[])(?:и|или|не)(?=[]|$)/.source),lookbehind:!0,alias:"keyword"},"system-variable":{pattern:a(/(^|[])знач(?=[]|$)/.source),lookbehind:!0,alias:"keyword"},type:[{pattern:a(/(^|[])(?:вещ|лит|лог|сим|цел)(?:\x20*таб)?(?=[]|$)/.source),lookbehind:!0,alias:"builtin"},{pattern:a(/(^|[])(?:компл|сканкод|файл|цвет)(?=[]|$)/.source),lookbehind:!0,alias:"important"}],keyword:{pattern:a(/(^|[])(?:алг|арг(?:\x20*рез)?|ввод|ВКЛЮЧИТЬ|вс[её]|выбор|вывод|выход|дано|для|до|дс|если|иначе|исп|использовать|кон(?:(?:\x20+|_)исп)?|кц(?:(?:\x20+|_)при)?|надо|нач|нс|нц|от|пауза|пока|при|раза?|рез|стоп|таб|то|утв|шаг)(?=[]|$)/.source),lookbehind:!0},name:{pattern:a(/(^|[])[^\d][^]*(?:\x20+[^]+)*(?=[]|$)/.source),lookbehind:!0},number:{pattern:a(/(^|[])(?:\B\$[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)(?=[]|$)/.source,"i"),lookbehind:!0},punctuation:/:=|[(),:;\[\]]/,"operator-char":{pattern:/\*\*?|<[=>]?|>=?|[-+/=]/,alias:"operator"}},n.languages.kum=n.languages.kumir})(t)}return yc}var Ec,iv;function XG(){if(iv)return Ec;iv=1,Ec=e,e.displayName="kusto",e.aliases=[];function e(t){t.languages.kusto={comment:{pattern:/\/\/.*/,greedy:!0},string:{pattern:/```[\s\S]*?```|[hH]?(?:"(?:[^\r\n\\"]|\\.)*"|'(?:[^\r\n\\']|\\.)*'|@(?:"[^\r\n"]*"|'[^\r\n']*'))/,greedy:!0},verb:{pattern:/(\|\s*)[a-z][\w-]*/i,lookbehind:!0,alias:"keyword"},command:{pattern:/\.[a-z][a-z\d-]*\b/,alias:"keyword"},"class-name":/\b(?:bool|datetime|decimal|dynamic|guid|int|long|real|string|timespan)\b/,keyword:/\b(?:access|alias|and|anti|as|asc|auto|between|by|(?:contains|(?:ends|starts)with|has(?:perfix|suffix)?)(?:_cs)?|database|declare|desc|external|from|fullouter|has_all|in|ingestion|inline|inner|innerunique|into|(?:left|right)(?:anti(?:semi)?|inner|outer|semi)?|let|like|local|not|of|on|or|pattern|print|query_parameters|range|restrict|schema|set|step|table|tables|to|view|where|with|matches\s+regex|nulls\s+(?:first|last))(?![\w-])/,boolean:/\b(?:false|null|true)\b/,function:/\b[a-z_]\w*(?=\s*\()/,datetime:[{pattern:/\b(?:(?:Fri|Friday|Mon|Monday|Sat|Saturday|Sun|Sunday|Thu|Thursday|Tue|Tuesday|Wed|Wednesday)\s*,\s*)?\d{1,2}(?:\s+|-)(?:Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)(?:\s+|-)\d{2}\s+\d{2}:\d{2}(?::\d{2})?(?:\s*(?:\b(?:[A-Z]|(?:[ECMT][DS]|GM|U)T)|[+-]\d{4}))?\b/,alias:"number"},{pattern:/[+-]?\b(?:\d{4}-\d{2}-\d{2}(?:[ T]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?)?|\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?)Z?/,alias:"number"}],number:/\b(?:0x[0-9A-Fa-f]+|\d+(?:\.\d+)?(?:[Ee][+-]?\d+)?)(?:(?:min|sec|[mnµ]s|[dhms]|microsecond|tick)\b)?|[+-]?\binf\b/,operator:/=>|[!=]~|[!=<>]=?|[-+*/%|]|\.\./,punctuation:/[()\[\]{},;.:]/}}return Ec}var Sc,ov;function ZG(){if(ov)return Sc;ov=1,Sc=e,e.displayName="latex",e.aliases=["tex","context"];function e(t){(function(n){var r=/\\(?:[^a-z()[\]]|[a-z*]+)/i,a={"equation-command":{pattern:r,alias:"regex"}};n.languages.latex={comment:/%.*/,cdata:{pattern:/(\\begin\{((?:lstlisting|verbatim)\*?)\})[\s\S]*?(?=\\end\{\2\})/,lookbehind:!0},equation:[{pattern:/\$\$(?:\\[\s\S]|[^\\$])+\$\$|\$(?:\\[\s\S]|[^\\$])+\$|\\\([\s\S]*?\\\)|\\\[[\s\S]*?\\\]/,inside:a,alias:"string"},{pattern:/(\\begin\{((?:align|eqnarray|equation|gather|math|multline)\*?)\})[\s\S]*?(?=\\end\{\2\})/,lookbehind:!0,inside:a,alias:"string"}],keyword:{pattern:/(\\(?:begin|cite|documentclass|end|label|ref|usepackage)(?:\[[^\]]+\])?\{)[^}]+(?=\})/,lookbehind:!0},url:{pattern:/(\\url\{)[^}]+(?=\})/,lookbehind:!0},headline:{pattern:/(\\(?:chapter|frametitle|paragraph|part|section|subparagraph|subsection|subsubparagraph|subsubsection|subsubsubparagraph)\*?(?:\[[^\]]+\])?\{)[^}]+(?=\})/,lookbehind:!0,alias:"class-name"},function:{pattern:r,alias:"selector"},punctuation:/[[\]{}&]/},n.languages.tex=n.languages.latex,n.languages.context=n.languages.latex})(t)}return Sc}var vc,sv;function Jo(){if(sv)return vc;sv=1;var e=nt();vc=t,t.displayName="php",t.aliases=[];function t(n){n.register(e),function(r){var a=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,i=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],o=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,s=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,l=/[{}\[\](),:;]/;r.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:a,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s+)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:i,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:o,operator:s,punctuation:l};var u={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:r.languages.php},d=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:u}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:u}}];r.languages.insertBefore("php","variable",{string:d,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:a,string:d,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:i,number:o,operator:s,punctuation:l}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),r.hooks.add("before-tokenize",function(c){if(/<\?/.test(c.code)){var f=/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g;r.languages["markup-templating"].buildPlaceholders(c,"php",f)}}),r.hooks.add("after-tokenize",function(c){r.languages["markup-templating"].tokenizePlaceholders(c,"php")})}(n)}return vc}var kc,lv;function QG(){if(lv)return kc;lv=1;var e=nt(),t=Jo();kc=n,n.displayName="latte",n.aliases=[];function n(r){r.register(e),r.register(t),function(a){a.languages.latte={comment:/^\{\*[\s\S]*/,"latte-tag":{pattern:/(^\{(?:\/(?=[a-z]))?)(?:[=_]|[a-z]\w*\b(?!\())/i,lookbehind:!0,alias:"important"},delimiter:{pattern:/^\{\/?|\}$/,alias:"punctuation"},php:{pattern:/\S(?:[\s\S]*\S)?/,alias:"language-php",inside:a.languages.php}};var i=a.languages.extend("markup",{});a.languages.insertBefore("inside","attr-value",{"n-attr":{pattern:/n:[\w-]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+))?/,inside:{"attr-name":{pattern:/^[^\s=]+/,alias:"important"},"attr-value":{pattern:/=[\s\S]+/,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}],php:{pattern:/\S(?:[\s\S]*\S)?/,inside:a.languages.php}}}}}},i.tag),a.hooks.add("before-tokenize",function(o){if(o.language==="latte"){var s=/\{\*[\s\S]*?\*\}|\{[^'"\s{}*](?:[^"'/{}]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|\/\*(?:[^*]|\*(?!\/))*\*\/)*\}/g;a.languages["markup-templating"].buildPlaceholders(o,"latte",s),o.grammar=i}}),a.hooks.add("after-tokenize",function(o){a.languages["markup-templating"].tokenizePlaceholders(o,"latte")})}(r)}return kc}var wc,uv;function JG(){if(uv)return wc;uv=1,wc=e,e.displayName="less",e.aliases=[];function e(t){t.languages.less=t.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),t.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}})}return wc}var _c,cv;function Hm(){if(cv)return _c;cv=1,_c=e,e.displayName="scheme",e.aliases=[];function e(t){(function(n){n.languages.scheme={comment:/;.*|#;\s*(?:\((?:[^()]|\([^()]*\))*\)|\[(?:[^\[\]]|\[[^\[\]]*\])*\])|#\|(?:[^#|]|#(?!\|)|\|(?!#)|#\|(?:[^#|]|#(?!\|)|\|(?!#))*\|#)*\|#/,string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0},symbol:{pattern:/'[^()\[\]#'\s]+/,greedy:!0},char:{pattern:/#\\(?:[ux][a-fA-F\d]+\b|[-a-zA-Z]+\b|[\uD800-\uDBFF][\uDC00-\uDFFF]|\S)/,greedy:!0},"lambda-parameter":[{pattern:/((?:^|[^'`#])[(\[]lambda\s+)(?:[^|()\[\]'\s]+|\|(?:[^\\|]|\\.)*\|)/,lookbehind:!0},{pattern:/((?:^|[^'`#])[(\[]lambda\s+[(\[])[^()\[\]']+/,lookbehind:!0}],keyword:{pattern:/((?:^|[^'`#])[(\[])(?:begin|case(?:-lambda)?|cond(?:-expand)?|define(?:-library|-macro|-record-type|-syntax|-values)?|defmacro|delay(?:-force)?|do|else|except|export|guard|if|import|include(?:-ci|-library-declarations)?|lambda|let(?:rec)?(?:-syntax|-values|\*)?|let\*-values|only|parameterize|prefix|(?:quasi-?)?quote|rename|set!|syntax-(?:case|rules)|unless|unquote(?:-splicing)?|when)(?=[()\[\]\s]|$)/,lookbehind:!0},builtin:{pattern:/((?:^|[^'`#])[(\[])(?:abs|and|append|apply|assoc|ass[qv]|binary-port\?|boolean=?\?|bytevector(?:-append|-copy|-copy!|-length|-u8-ref|-u8-set!|\?)?|caar|cadr|call-with-(?:current-continuation|port|values)|call\/cc|car|cdar|cddr|cdr|ceiling|char(?:->integer|-ready\?|\?|<\?|<=\?|=\?|>\?|>=\?)|close-(?:input-port|output-port|port)|complex\?|cons|current-(?:error|input|output)-port|denominator|dynamic-wind|eof-object\??|eq\?|equal\?|eqv\?|error|error-object(?:-irritants|-message|\?)|eval|even\?|exact(?:-integer-sqrt|-integer\?|\?)?|expt|features|file-error\?|floor(?:-quotient|-remainder|\/)?|flush-output-port|for-each|gcd|get-output-(?:bytevector|string)|inexact\??|input-port(?:-open\?|\?)|integer(?:->char|\?)|lcm|length|list(?:->string|->vector|-copy|-ref|-set!|-tail|\?)?|make-(?:bytevector|list|parameter|string|vector)|map|max|member|memq|memv|min|modulo|negative\?|newline|not|null\?|number(?:->string|\?)|numerator|odd\?|open-(?:input|output)-(?:bytevector|string)|or|output-port(?:-open\?|\?)|pair\?|peek-char|peek-u8|port\?|positive\?|procedure\?|quotient|raise|raise-continuable|rational\?|rationalize|read-(?:bytevector|bytevector!|char|error\?|line|string|u8)|real\?|remainder|reverse|round|set-c[ad]r!|square|string(?:->list|->number|->symbol|->utf8|->vector|-append|-copy|-copy!|-fill!|-for-each|-length|-map|-ref|-set!|\?|<\?|<=\?|=\?|>\?|>=\?)?|substring|symbol(?:->string|\?|=\?)|syntax-error|textual-port\?|truncate(?:-quotient|-remainder|\/)?|u8-ready\?|utf8->string|values|vector(?:->list|->string|-append|-copy|-copy!|-fill!|-for-each|-length|-map|-ref|-set!|\?)?|with-exception-handler|write-(?:bytevector|char|string|u8)|zero\?)(?=[()\[\]\s]|$)/,lookbehind:!0},operator:{pattern:/((?:^|[^'`#])[(\[])(?:[-+*%/]|[<>]=?|=>?)(?=[()\[\]\s]|$)/,lookbehind:!0},number:{pattern:RegExp(r({"":/\d+(?:\/\d+)|(?:\d+(?:\.\d*)?|\.\d+)(?:[esfdl][+-]?\d+)?/.source,"":/[+-]?|[+-](?:inf|nan)\.0/.source,"":/[+-](?:|(?:inf|nan)\.0)?i/.source,"":/(?:@|)?|/.source,"":/(?:#d(?:#[ei])?|#[ei](?:#d)?)?/.source,"":/[0-9a-f]+(?:\/[0-9a-f]+)?/.source,"":/[+-]?|[+-](?:inf|nan)\.0/.source,"":/[+-](?:|(?:inf|nan)\.0)?i/.source,"":/(?:@|)?|/.source,"":/#[box](?:#[ei])?|(?:#[ei])?#[box]/.source,"":/(^|[()\[\]\s])(?:|)(?=[()\[\]\s]|$)/.source}),"i"),lookbehind:!0},boolean:{pattern:/(^|[()\[\]\s])#(?:[ft]|false|true)(?=[()\[\]\s]|$)/,lookbehind:!0},function:{pattern:/((?:^|[^'`#])[(\[])(?:[^|()\[\]'\s]+|\|(?:[^\\|]|\\.)*\|)(?=[()\[\]\s]|$)/,lookbehind:!0},identifier:{pattern:/(^|[()\[\]\s])\|(?:[^\\|]|\\.)*\|(?=[()\[\]\s]|$)/,lookbehind:!0,greedy:!0},punctuation:/[()\[\]']/};function r(a){for(var i in a)a[i]=a[i].replace(/<[\w\s]+>/g,function(o){return"(?:"+a[o].trim()+")"});return a[i]}})(t)}return _c}var Tc,dv;function eq(){if(dv)return Tc;dv=1;var e=Hm();Tc=t,t.displayName="lilypond",t.aliases=[];function t(n){n.register(e),function(r){for(var a=/\((?:[^();"#\\]|\\[\s\S]|;.*(?!.)|"(?:[^"\\]|\\.)*"|#(?:\{(?:(?!#\})[\s\S])*#\}|[^{])|)*\)/.source,i=5,o=0;o/g,function(){return a});a=a.replace(//g,/[^\s\S]/.source);var s=r.languages.lilypond={comment:/%(?:(?!\{).*|\{[\s\S]*?%\})/,"embedded-scheme":{pattern:RegExp(/(^|[=\s])#(?:"(?:[^"\\]|\\.)*"|[^\s()"]*(?:[^\s()]|))/.source.replace(//g,function(){return a}),"m"),lookbehind:!0,greedy:!0,inside:{scheme:{pattern:/^(#)[\s\S]+$/,lookbehind:!0,alias:"language-scheme",inside:{"embedded-lilypond":{pattern:/#\{[\s\S]*?#\}/,greedy:!0,inside:{punctuation:/^#\{|#\}$/,lilypond:{pattern:/[\s\S]+/,alias:"language-lilypond",inside:null}}},rest:r.languages.scheme}},punctuation:/#/}},string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0},"class-name":{pattern:/(\\new\s+)[\w-]+/,lookbehind:!0},keyword:{pattern:/\\[a-z][-\w]*/i,inside:{punctuation:/^\\/}},operator:/[=|]|<<|>>/,punctuation:{pattern:/(^|[a-z\d])(?:'+|,+|[_^]?-[_^]?(?:[-+^!>._]|(?=\d))|[_^]\.?|[.!])|[{}()[\]<>^~]|\\[()[\]<>\\!]|--|__/,lookbehind:!0},number:/\b\d+(?:\/\d+)?\b/};s["embedded-scheme"].inside.scheme.inside["embedded-lilypond"].inside.lilypond.inside=s,r.languages.ly=s}(n)}return Tc}var Ac,pv;function tq(){if(pv)return Ac;pv=1;var e=nt();Ac=t,t.displayName="liquid",t.aliases=[];function t(n){n.register(e),n.languages.liquid={comment:{pattern:/(^\{%\s*comment\s*%\})[\s\S]+(?=\{%\s*endcomment\s*%\}$)/,lookbehind:!0},delimiter:{pattern:/^\{(?:\{\{|[%\{])-?|-?(?:\}\}|[%\}])\}$/,alias:"punctuation"},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},keyword:/\b(?:as|assign|break|(?:end)?(?:capture|case|comment|for|form|if|paginate|raw|style|tablerow|unless)|continue|cycle|decrement|echo|else|elsif|in|include|increment|limit|liquid|offset|range|render|reversed|section|when|with)\b/,object:/\b(?:address|all_country_option_tags|article|block|blog|cart|checkout|collection|color|country|country_option_tags|currency|current_page|current_tags|customer|customer_address|date|discount_allocation|discount_application|external_video|filter|filter_value|font|forloop|fulfillment|generic_file|gift_card|group|handle|image|line_item|link|linklist|localization|location|measurement|media|metafield|model|model_source|order|page|page_description|page_image|page_title|part|policy|product|product_option|recommendations|request|robots|routes|rule|script|search|selling_plan|selling_plan_allocation|selling_plan_group|shipping_method|shop|shop_locale|sitemap|store_availability|tax_line|template|theme|transaction|unit_price_measurement|user_agent|variant|video|video_source)\b/,function:[{pattern:/(\|\s*)\w+/,lookbehind:!0,alias:"filter"},{pattern:/(\.\s*)(?:first|last|size)/,lookbehind:!0}],boolean:/\b(?:false|nil|true)\b/,range:{pattern:/\.\./,alias:"operator"},number:/\b\d+(?:\.\d+)?\b/,operator:/[!=]=|<>|[<>]=?|[|?:=-]|\b(?:and|contains(?=\s)|or)\b/,punctuation:/[.,\[\]()]/,empty:{pattern:/\bempty\b/,alias:"keyword"}},n.hooks.add("before-tokenize",function(r){var a=/\{%\s*comment\s*%\}[\s\S]*?\{%\s*endcomment\s*%\}|\{(?:%[\s\S]*?%|\{\{[\s\S]*?\}\}|\{[\s\S]*?\})\}/g,i=!1;n.languages["markup-templating"].buildPlaceholders(r,"liquid",a,function(o){var s=/^\{%-?\s*(\w+)/.exec(o);if(s){var l=s[1];if(l==="raw"&&!i)return i=!0,!0;if(l==="endraw")return i=!1,!0}return!i})}),n.hooks.add("after-tokenize",function(r){n.languages["markup-templating"].tokenizePlaceholders(r,"liquid")})}return Ac}var Rc,fv;function nq(){if(fv)return Rc;fv=1,Rc=e,e.displayName="lisp",e.aliases=[];function e(t){(function(n){function r(y){return RegExp(/(\()/.source+"(?:"+y+")"+/(?=[\s\)])/.source)}function a(y){return RegExp(/([\s([])/.source+"(?:"+y+")"+/(?=[\s)])/.source)}var i=/(?!\d)[-+*/~!@$%^=<>{}\w]+/.source,o="&"+i,s="(\\()",l="(?=\\))",u="(?=\\s)",d=/(?:[^()]|\((?:[^()]|\((?:[^()]|\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\))*\))*\))*/.source,c={heading:{pattern:/;;;.*/,alias:["comment","title"]},comment:/;.*/,string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0,inside:{argument:/[-A-Z]+(?=[.,\s])/,symbol:RegExp("`"+i+"'")}},"quoted-symbol":{pattern:RegExp("#?'"+i),alias:["variable","symbol"]},"lisp-property":{pattern:RegExp(":"+i),alias:"property"},splice:{pattern:RegExp(",@?"+i),alias:["symbol","variable"]},keyword:[{pattern:RegExp(s+"(?:and|(?:cl-)?letf|cl-loop|cond|cons|error|if|(?:lexical-)?let\\*?|message|not|null|or|provide|require|setq|unless|use-package|when|while)"+u),lookbehind:!0},{pattern:RegExp(s+"(?:append|by|collect|concat|do|finally|for|in|return)"+u),lookbehind:!0}],declare:{pattern:r(/declare/.source),lookbehind:!0,alias:"keyword"},interactive:{pattern:r(/interactive/.source),lookbehind:!0,alias:"keyword"},boolean:{pattern:a(/nil|t/.source),lookbehind:!0},number:{pattern:a(/[-+]?\d+(?:\.\d*)?/.source),lookbehind:!0},defvar:{pattern:RegExp(s+"def(?:const|custom|group|var)\\s+"+i),lookbehind:!0,inside:{keyword:/^def[a-z]+/,variable:RegExp(i)}},defun:{pattern:RegExp(s+/(?:cl-)?(?:defmacro|defun\*?)\s+/.source+i+/\s+\(/.source+d+/\)/.source),lookbehind:!0,greedy:!0,inside:{keyword:/^(?:cl-)?def\S+/,arguments:null,function:{pattern:RegExp("(^\\s)"+i),lookbehind:!0},punctuation:/[()]/}},lambda:{pattern:RegExp(s+"lambda\\s+\\(\\s*(?:&?"+i+"(?:\\s+&?"+i+")*\\s*)?\\)"),lookbehind:!0,greedy:!0,inside:{keyword:/^lambda/,arguments:null,punctuation:/[()]/}},car:{pattern:RegExp(s+i),lookbehind:!0},punctuation:[/(?:['`,]?\(|[)\[\]])/,{pattern:/(\s)\.(?=\s)/,lookbehind:!0}]},f={"lisp-marker":RegExp(o),varform:{pattern:RegExp(/\(/.source+i+/\s+(?=\S)/.source+d+/\)/.source),inside:c},argument:{pattern:RegExp(/(^|[\s(])/.source+i),lookbehind:!0,alias:"variable"},rest:c},p="\\S+(?:\\s+\\S+)*",h={pattern:RegExp(s+d+l),lookbehind:!0,inside:{"rest-vars":{pattern:RegExp("&(?:body|rest)\\s+"+p),inside:f},"other-marker-vars":{pattern:RegExp("&(?:aux|optional)\\s+"+p),inside:f},keys:{pattern:RegExp("&key\\s+"+p+"(?:\\s+&allow-other-keys)?"),inside:f},argument:{pattern:RegExp(i),alias:"variable"},punctuation:/[()]/}};c.lambda.inside.arguments=h,c.defun.inside.arguments=n.util.clone(h),c.defun.inside.arguments.inside.sublist=h,n.languages.lisp=c,n.languages.elisp=c,n.languages.emacs=c,n.languages["emacs-lisp"]=c})(t)}return Rc}var Ic,gv;function rq(){if(gv)return Ic;gv=1,Ic=e,e.displayName="livescript",e.aliases=[];function e(t){t.languages.livescript={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\])#.*/,lookbehind:!0}],"interpolated-string":{pattern:/(^|[^"])("""|")(?:\\[\s\S]|(?!\2)[^\\])*\2(?!")/,lookbehind:!0,greedy:!0,inside:{variable:{pattern:/(^|[^\\])#[a-z_](?:-?[a-z]|[\d_])*/m,lookbehind:!0},interpolation:{pattern:/(^|[^\\])#\{[^}]+\}/m,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^#\{|\}$/,alias:"variable"}}},string:/[\s\S]+/}},string:[{pattern:/('''|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/<\[[\s\S]*?\]>/,greedy:!0},/\\[^\s,;\])}]+/],regex:[{pattern:/\/\/(?:\[[^\r\n\]]*\]|\\.|(?!\/\/)[^\\\[])+\/\/[gimyu]{0,5}/,greedy:!0,inside:{comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0}}},{pattern:/\/(?:\[[^\r\n\]]*\]|\\.|[^/\\\r\n\[])+\/[gimyu]{0,5}/,greedy:!0}],keyword:{pattern:/(^|(?!-).)\b(?:break|case|catch|class|const|continue|default|do|else|extends|fallthrough|finally|for(?: ever)?|function|if|implements|it|let|loop|new|null|otherwise|own|return|super|switch|that|then|this|throw|try|unless|until|var|void|when|while|yield)(?!-)\b/m,lookbehind:!0},"keyword-operator":{pattern:/(^|[^-])\b(?:(?:delete|require|typeof)!|(?:and|by|delete|export|from|import(?: all)?|in|instanceof|is(?: not|nt)?|not|of|or|til|to|typeof|with|xor)(?!-)\b)/m,lookbehind:!0,alias:"operator"},boolean:{pattern:/(^|[^-])\b(?:false|no|off|on|true|yes)(?!-)\b/m,lookbehind:!0},argument:{pattern:/(^|(?!\.&\.)[^&])&(?!&)\d*/m,lookbehind:!0,alias:"variable"},number:/\b(?:\d+~[\da-z]+|\d[\d_]*(?:\.\d[\d_]*)?(?:[a-z]\w*)?)/i,identifier:/[a-z_](?:-?[a-z]|[\d_])*/i,operator:[{pattern:/( )\.(?= )/,lookbehind:!0},/\.(?:[=~]|\.\.?)|\.(?:[&|^]|<<|>>>?)\.|:(?:=|:=?)|&&|\|[|>]|<(?:<[>=?]?|-(?:->?|>)?|\+\+?|@@?|%%?|\*\*?|!(?:~?=|--?>|~?~>)?|~(?:~?>|=)?|==?|\^\^?|[\/?]/],punctuation:/[(){}\[\]|.,:;`]/},t.languages.livescript["interpolated-string"].inside.interpolation.inside.rest=t.languages.livescript}return Ic}var Cc,mv;function aq(){if(mv)return Cc;mv=1,Cc=e,e.displayName="llvm",e.aliases=[];function e(t){(function(n){n.languages.llvm={comment:/;.*/,string:{pattern:/"[^"]*"/,greedy:!0},boolean:/\b(?:false|true)\b/,variable:/[%@!#](?:(?!\d)(?:[-$.\w]|\\[a-f\d]{2})+|\d+)/i,label:/(?!\d)(?:[-$.\w]|\\[a-f\d]{2})+:/i,type:{pattern:/\b(?:double|float|fp128|half|i[1-9]\d*|label|metadata|ppc_fp128|token|void|x86_fp80|x86_mmx)\b/,alias:"class-name"},keyword:/\b[a-z_][a-z_0-9]*\b/,number:/[+-]?\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b|\b0x[\dA-Fa-f]+\b|\b0xK[\dA-Fa-f]{20}\b|\b0x[ML][\dA-Fa-f]{32}\b|\b0xH[\dA-Fa-f]{4}\b/,punctuation:/[{}[\];(),.!*=<>]/}})(t)}return Cc}var Nc,hv;function iq(){if(hv)return Nc;hv=1,Nc=e,e.displayName="log",e.aliases=[];function e(t){t.languages.log={string:{pattern:/"(?:[^"\\\r\n]|\\.)*"|'(?![st] | \w)(?:[^'\\\r\n]|\\.)*'/,greedy:!0},exception:{pattern:/(^|[^\w.])[a-z][\w.]*(?:Error|Exception):.*(?:(?:\r\n?|\n)[ \t]*(?:at[ \t].+|\.{3}.*|Caused by:.*))+(?:(?:\r\n?|\n)[ \t]*\.\.\. .*)?/,lookbehind:!0,greedy:!0,alias:["javastacktrace","language-javastacktrace"],inside:t.languages.javastacktrace||{keyword:/\bat\b/,function:/[a-z_][\w$]*(?=\()/,punctuation:/[.:()]/}},level:[{pattern:/\b(?:ALERT|CRIT|CRITICAL|EMERG|EMERGENCY|ERR|ERROR|FAILURE|FATAL|SEVERE)\b/,alias:["error","important"]},{pattern:/\b(?:WARN|WARNING|WRN)\b/,alias:["warning","important"]},{pattern:/\b(?:DISPLAY|INF|INFO|NOTICE|STATUS)\b/,alias:["info","keyword"]},{pattern:/\b(?:DBG|DEBUG|FINE)\b/,alias:["debug","keyword"]},{pattern:/\b(?:FINER|FINEST|TRACE|TRC|VERBOSE|VRB)\b/,alias:["trace","comment"]}],property:{pattern:/((?:^|[\]|])[ \t]*)[a-z_](?:[\w-]|\b\/\b)*(?:[. ]\(?\w(?:[\w-]|\b\/\b)*\)?)*:(?=\s)/im,lookbehind:!0},separator:{pattern:/(^|[^-+])-{3,}|={3,}|\*{3,}|- - /m,lookbehind:!0,alias:"comment"},url:/\b(?:file|ftp|https?):\/\/[^\s|,;'"]*[^\s|,;'">.]/,email:{pattern:/(^|\s)[-\w+.]+@[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+(?=\s)/,lookbehind:!0,alias:"url"},"ip-address":{pattern:/\b(?:\d{1,3}(?:\.\d{1,3}){3})\b/,alias:"constant"},"mac-address":{pattern:/\b[a-f0-9]{2}(?::[a-f0-9]{2}){5}\b/i,alias:"constant"},domain:{pattern:/(^|\s)[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)*\.[a-z][a-z0-9-]+(?=\s)/,lookbehind:!0,alias:"constant"},uuid:{pattern:/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i,alias:"constant"},hash:{pattern:/\b(?:[a-f0-9]{32}){1,2}\b/i,alias:"constant"},"file-path":{pattern:/\b[a-z]:[\\/][^\s|,;:(){}\[\]"']+|(^|[\s:\[\](>|])\.{0,2}\/\w[^\s|,;:(){}\[\]"']*/i,lookbehind:!0,greedy:!0,alias:"string"},date:{pattern:RegExp(/\b\d{4}[-/]\d{2}[-/]\d{2}(?:T(?=\d{1,2}:)|(?=\s\d{1,2}:))/.source+"|"+/\b\d{1,4}[-/ ](?:\d{1,2}|Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)[-/ ]\d{2,4}T?\b/.source+"|"+/\b(?:(?:Fri|Mon|Sat|Sun|Thu|Tue|Wed)(?:\s{1,2}(?:Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep))?|Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)\s{1,2}\d{1,2}\b/.source,"i"),alias:"number"},time:{pattern:/\b\d{1,2}:\d{1,2}:\d{1,2}(?:[.,:]\d+)?(?:\s?[+-]\d{2}:?\d{2}|Z)?\b/,alias:"number"},boolean:/\b(?:false|null|true)\b/i,number:{pattern:/(^|[^.\w])(?:0x[a-f0-9]+|0o[0-7]+|0b[01]+|v?\d[\da-f]*(?:\.\d+)*(?:e[+-]?\d+)?[a-z]{0,3}\b)\b(?!\.\w)/i,lookbehind:!0},operator:/[;:?<=>~/@!$%&+\-|^(){}*#]/,punctuation:/[\[\].,]/}}return Nc}var xc,bv;function oq(){if(bv)return xc;bv=1,xc=e,e.displayName="lolcode",e.aliases=[];function e(t){t.languages.lolcode={comment:[/\bOBTW\s[\s\S]*?\sTLDR\b/,/\bBTW.+/],string:{pattern:/"(?::.|[^":])*"/,inside:{variable:/:\{[^}]+\}/,symbol:[/:\([a-f\d]+\)/i,/:\[[^\]]+\]/,/:[)>o":]/]},greedy:!0},number:/(?:\B-)?(?:\b\d+(?:\.\d*)?|\B\.\d+)/,symbol:{pattern:/(^|\s)(?:A )?(?:BUKKIT|NOOB|NUMBAR|NUMBR|TROOF|YARN)(?=\s|,|$)/,lookbehind:!0,inside:{keyword:/A(?=\s)/}},label:{pattern:/((?:^|\s)(?:IM IN YR|IM OUTTA YR) )[a-zA-Z]\w*/,lookbehind:!0,alias:"string"},function:{pattern:/((?:^|\s)(?:HOW IZ I|I IZ|IZ) )[a-zA-Z]\w*/,lookbehind:!0},keyword:[{pattern:/(^|\s)(?:AN|FOUND YR|GIMMEH|GTFO|HAI|HAS A|HOW IZ I|I HAS A|I IZ|IF U SAY SO|IM IN YR|IM OUTTA YR|IS NOW(?: A)?|ITZ(?: A)?|IZ|KTHX|KTHXBYE|LIEK(?: A)?|MAEK|MEBBE|MKAY|NERFIN|NO WAI|O HAI IM|O RLY\?|OIC|OMG|OMGWTF|R|SMOOSH|SRS|TIL|UPPIN|VISIBLE|WILE|WTF\?|YA RLY|YR)(?=\s|,|$)/,lookbehind:!0},/'Z(?=\s|,|$)/],boolean:{pattern:/(^|\s)(?:FAIL|WIN)(?=\s|,|$)/,lookbehind:!0},variable:{pattern:/(^|\s)IT(?=\s|,|$)/,lookbehind:!0},operator:{pattern:/(^|\s)(?:NOT|BOTH SAEM|DIFFRINT|(?:ALL|ANY|BIGGR|BOTH|DIFF|EITHER|MOD|PRODUKT|QUOSHUNT|SMALLR|SUM|WON) OF)(?=\s|,|$)/,lookbehind:!0},punctuation:/\.{3}|…|,|!/}}return xc}var Oc,yv;function sq(){if(yv)return Oc;yv=1,Oc=e,e.displayName="magma",e.aliases=[];function e(t){t.languages.magma={output:{pattern:/^(>.*(?:\r(?:\n|(?!\n))|\n))(?!>)(?:.+|(?:\r(?:\n|(?!\n))|\n)(?!>).*)(?:(?:\r(?:\n|(?!\n))|\n)(?!>).*)*/m,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\//,greedy:!0},string:{pattern:/(^|[^\\"])"(?:[^\r\n\\"]|\\.)*"/,lookbehind:!0,greedy:!0},keyword:/\b(?:_|adj|and|assert|assert2|assert3|assigned|break|by|case|cat|catch|clear|cmpeq|cmpne|continue|declare|default|delete|diff|div|do|elif|else|end|eq|error|eval|exists|exit|for|forall|forward|fprintf|freeze|function|ge|gt|if|iload|import|in|intrinsic|is|join|le|load|local|lt|meet|mod|ne|not|notadj|notin|notsubset|or|print|printf|procedure|quit|random|read|readi|repeat|require|requirege|requirerange|restore|return|save|sdiff|select|subset|then|time|to|try|until|vprint|vprintf|vtime|when|where|while|xor)\b/,boolean:/\b(?:false|true)\b/,generator:{pattern:/\b[a-z_]\w*(?=\s*<)/i,alias:"class-name"},function:/\b[a-z_]\w*(?=\s*\()/i,number:{pattern:/(^|[^\w.]|\.\.)(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?(?:_[a-z]?)?(?=$|[^\w.]|\.\.)/,lookbehind:!0},operator:/->|[-+*/^~!|#=]|:=|\.\./,punctuation:/[()[\]{}<>,;.:]/}}return Oc}var Lc,Ev;function lq(){if(Ev)return Lc;Ev=1,Lc=e,e.displayName="makefile",e.aliases=[];function e(t){t.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/}}return Lc}var Dc,Sv;function uq(){if(Sv)return Dc;Sv=1,Dc=e,e.displayName="markdown",e.aliases=["md"];function e(t){(function(n){var r=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function a(f){return f=f.replace(//g,function(){return r}),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+f+")")}var i=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,o=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,function(){return i}),s=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;n.languages.markdown=n.languages.extend("markup",{}),n.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:n.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+o+s+"(?:"+o+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+o+s+")(?:"+o+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(i),inside:n.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+o+")"+s+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+o+"$"),inside:{"table-header":{pattern:RegExp(i),alias:"important",inside:n.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:a(/\b__(?:(?!_)|_(?:(?!_))+_)+__\b|\*\*(?:(?!\*)|\*(?:(?!\*))+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:a(/\b_(?:(?!_)|__(?:(?!_))+__)+_\b|\*(?:(?!\*)|\*\*(?:(?!\*))+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:a(/(~~?)(?:(?!~))+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:a(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]))+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach(function(f){["url","bold","italic","strike","code-snippet"].forEach(function(p){f!==p&&(n.languages.markdown[f].inside.content.inside[p]=n.languages.markdown[p])})}),n.hooks.add("after-tokenize",function(f){if(f.language!=="markdown"&&f.language!=="md")return;function p(h){if(!(!h||typeof h=="string"))for(var y=0,T=h.length;y",quot:'"'},d=String.fromCodePoint||String.fromCharCode;function c(f){var p=f.replace(l,"");return p=p.replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,function(h,y){if(y=y.toLowerCase(),y[0]==="#"){var T;return y[1]==="x"?T=parseInt(y.slice(2),16):T=Number(y.slice(1)),d(T)}else{var b=u[y];return b||h}}),p}n.languages.md=n.languages.markdown})(t)}return Dc}var Mc,vv;function cq(){if(vv)return Mc;vv=1,Mc=e,e.displayName="matlab",e.aliases=[];function e(t){t.languages.matlab={comment:[/%\{[\s\S]*?\}%/,/%.+/],string:{pattern:/\B'(?:''|[^'\r\n])*'/,greedy:!0},number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[eE][+-]?\d+)?(?:[ij])?|\b[ij]\b/,keyword:/\b(?:NaN|break|case|catch|continue|else|elseif|end|for|function|if|inf|otherwise|parfor|pause|pi|return|switch|try|while)\b/,function:/\b(?!\d)\w+(?=\s*\()/,operator:/\.?[*^\/\\']|[+\-:@]|[<>=~]=?|&&?|\|\|?/,punctuation:/\.{3}|[.,;\[\](){}!]/}}return Mc}var Fc,kv;function dq(){if(kv)return Fc;kv=1,Fc=e,e.displayName="maxscript",e.aliases=[];function e(t){(function(n){var r=/\b(?:about|and|animate|as|at|attributes|by|case|catch|collect|continue|coordsys|do|else|exit|fn|for|from|function|global|if|in|local|macroscript|mapped|max|not|of|off|on|or|parameters|persistent|plugin|rcmenu|return|rollout|set|struct|then|throw|to|tool|try|undo|utility|when|where|while|with)\b/i;n.languages.maxscript={comment:{pattern:/\/\*[\s\S]*?(?:\*\/|$)|--.*/,greedy:!0},string:{pattern:/(^|[^"\\@])(?:"(?:[^"\\]|\\[\s\S])*"|@"[^"]*")/,lookbehind:!0,greedy:!0},path:{pattern:/\$(?:[\w/\\.*?]|'[^']*')*/,greedy:!0,alias:"string"},"function-call":{pattern:RegExp("((?:"+(/^/.source+"|"+/[;=<>+\-*/^({\[]/.source+"|"+/\b(?:and|by|case|catch|collect|do|else|if|in|not|or|return|then|to|try|where|while|with)\b/.source)+")[ ]*)(?!"+r.source+")"+/[a-z_]\w*\b/.source+"(?=[ ]*(?:"+("(?!"+r.source+")"+/[a-z_]/.source+"|"+/\d|-\.?\d/.source+"|"+/[({'"$@#?]/.source)+"))","im"),lookbehind:!0,greedy:!0,alias:"function"},"function-definition":{pattern:/(\b(?:fn|function)\s+)\w+\b/i,lookbehind:!0,alias:"function"},argument:{pattern:/\b[a-z_]\w*(?=:)/i,alias:"attr-name"},keyword:r,boolean:/\b(?:false|true)\b/,time:{pattern:/(^|[^\w.])(?:(?:(?:\d+(?:\.\d*)?|\.\d+)(?:[eEdD][+-]\d+|[LP])?[msft])+|\d+:\d+(?:\.\d*)?)(?![\w.:])/,lookbehind:!0,alias:"number"},number:[{pattern:/(^|[^\w.])(?:(?:\d+(?:\.\d*)?|\.\d+)(?:[eEdD][+-]\d+|[LP])?|0x[a-fA-F0-9]+)(?![\w.:])/,lookbehind:!0},/\b(?:e|pi)\b/],constant:/\b(?:dontcollect|ok|silentValue|undefined|unsupplied)\b/,color:{pattern:/\b(?:black|blue|brown|gray|green|orange|red|white|yellow)\b/i,alias:"constant"},operator:/[-+*/<>=!]=?|[&^?]|#(?!\()/,punctuation:/[()\[\]{}.:,;]|#(?=\()|\\$/m}})(t)}return Fc}var Pc,wv;function pq(){if(wv)return Pc;wv=1,Pc=e,e.displayName="mel",e.aliases=[];function e(t){t.languages.mel={comment:/\/\/.*/,code:{pattern:/`(?:\\.|[^\\`\r\n])*`/,greedy:!0,alias:"italic",inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"}}},string:{pattern:/"(?:\\.|[^\\"\r\n])*"/,greedy:!0},variable:/\$\w+/,number:/\b0x[\da-fA-F]+\b|\b\d+(?:\.\d*)?|\B\.\d+/,flag:{pattern:/-[^\d\W]\w*/,alias:"operator"},keyword:/\b(?:break|case|continue|default|do|else|float|for|global|if|in|int|matrix|proc|return|string|switch|vector|while)\b/,function:/\b\w+(?=\()|\b(?:CBG|HfAddAttractorToAS|HfAssignAS|HfBuildEqualMap|HfBuildFurFiles|HfBuildFurImages|HfCancelAFR|HfConnectASToHF|HfCreateAttractor|HfDeleteAS|HfEditAS|HfPerformCreateAS|HfRemoveAttractorFromAS|HfSelectAttached|HfSelectAttractors|HfUnAssignAS|Mayatomr|about|abs|addAttr|addAttributeEditorNodeHelp|addDynamic|addNewShelfTab|addPP|addPanelCategory|addPrefixToName|advanceToNextDrivenKey|affectedNet|affects|aimConstraint|air|alias|aliasAttr|align|alignCtx|alignCurve|alignSurface|allViewFit|ambientLight|angle|angleBetween|animCone|animCurveEditor|animDisplay|animView|annotate|appendStringArray|applicationName|applyAttrPreset|applyTake|arcLenDimContext|arcLengthDimension|arclen|arrayMapper|art3dPaintCtx|artAttrCtx|artAttrPaintVertexCtx|artAttrSkinPaintCtx|artAttrTool|artBuildPaintMenu|artFluidAttrCtx|artPuttyCtx|artSelectCtx|artSetPaintCtx|artUserPaintCtx|assignCommand|assignInputDevice|assignViewportFactories|attachCurve|attachDeviceAttr|attachSurface|attrColorSliderGrp|attrCompatibility|attrControlGrp|attrEnumOptionMenu|attrEnumOptionMenuGrp|attrFieldGrp|attrFieldSliderGrp|attrNavigationControlGrp|attrPresetEditWin|attributeExists|attributeInfo|attributeMenu|attributeQuery|autoKeyframe|autoPlace|bakeClip|bakeFluidShading|bakePartialHistory|bakeResults|bakeSimulation|basename|basenameEx|batchRender|bessel|bevel|bevelPlus|binMembership|bindSkin|blend2|blendShape|blendShapeEditor|blendShapePanel|blendTwoAttr|blindDataType|boneLattice|boundary|boxDollyCtx|boxZoomCtx|bufferCurve|buildBookmarkMenu|buildKeyframeMenu|button|buttonManip|cacheFile|cacheFileCombine|cacheFileMerge|cacheFileTrack|camera|cameraView|canCreateManip|canvas|capitalizeString|catch|catchQuiet|ceil|changeSubdivComponentDisplayLevel|changeSubdivRegion|channelBox|character|characterMap|characterOutlineEditor|characterize|chdir|checkBox|checkBoxGrp|checkDefaultRenderGlobals|choice|circle|circularFillet|clamp|clear|clearCache|clip|clipEditor|clipEditorCurrentTimeCtx|clipSchedule|clipSchedulerOutliner|clipTrimBefore|closeCurve|closeSurface|cluster|cmdFileOutput|cmdScrollFieldExecuter|cmdScrollFieldReporter|cmdShell|coarsenSubdivSelectionList|collision|color|colorAtPoint|colorEditor|colorIndex|colorIndexSliderGrp|colorSliderButtonGrp|colorSliderGrp|columnLayout|commandEcho|commandLine|commandPort|compactHairSystem|componentEditor|compositingInterop|computePolysetVolume|condition|cone|confirmDialog|connectAttr|connectControl|connectDynamic|connectJoint|connectionInfo|constrain|constrainValue|constructionHistory|container|containsMultibyte|contextInfo|control|convertFromOldLayers|convertIffToPsd|convertLightmap|convertSolidTx|convertTessellation|convertUnit|copyArray|copyFlexor|copyKey|copySkinWeights|cos|cpButton|cpCache|cpClothSet|cpCollision|cpConstraint|cpConvClothToMesh|cpForces|cpGetSolverAttr|cpPanel|cpProperty|cpRigidCollisionFilter|cpSeam|cpSetEdit|cpSetSolverAttr|cpSolver|cpSolverTypes|cpTool|cpUpdateClothUVs|createDisplayLayer|createDrawCtx|createEditor|createLayeredPsdFile|createMotionField|createNewShelf|createNode|createRenderLayer|createSubdivRegion|cross|crossProduct|ctxAbort|ctxCompletion|ctxEditMode|ctxTraverse|currentCtx|currentTime|currentTimeCtx|currentUnit|curve|curveAddPtCtx|curveCVCtx|curveEPCtx|curveEditorCtx|curveIntersect|curveMoveEPCtx|curveOnSurface|curveSketchCtx|cutKey|cycleCheck|cylinder|dagPose|date|defaultLightListCheckBox|defaultNavigation|defineDataServer|defineVirtualDevice|deformer|deg_to_rad|delete|deleteAttr|deleteShadingGroupsAndMaterials|deleteShelfTab|deleteUI|deleteUnusedBrushes|delrandstr|detachCurve|detachDeviceAttr|detachSurface|deviceEditor|devicePanel|dgInfo|dgdirty|dgeval|dgtimer|dimWhen|directKeyCtx|directionalLight|dirmap|dirname|disable|disconnectAttr|disconnectJoint|diskCache|displacementToPoly|displayAffected|displayColor|displayCull|displayLevelOfDetail|displayPref|displayRGBColor|displaySmoothness|displayStats|displayString|displaySurface|distanceDimContext|distanceDimension|doBlur|dolly|dollyCtx|dopeSheetEditor|dot|dotProduct|doubleProfileBirailSurface|drag|dragAttrContext|draggerContext|dropoffLocator|duplicate|duplicateCurve|duplicateSurface|dynCache|dynControl|dynExport|dynExpression|dynGlobals|dynPaintEditor|dynParticleCtx|dynPref|dynRelEdPanel|dynRelEditor|dynamicLoad|editAttrLimits|editDisplayLayerGlobals|editDisplayLayerMembers|editRenderLayerAdjustment|editRenderLayerGlobals|editRenderLayerMembers|editor|editorTemplate|effector|emit|emitter|enableDevice|encodeString|endString|endsWith|env|equivalent|equivalentTol|erf|error|eval|evalDeferred|evalEcho|event|exactWorldBoundingBox|exclusiveLightCheckBox|exec|executeForEachObject|exists|exp|expression|expressionEditorListen|extendCurve|extendSurface|extrude|fcheck|fclose|feof|fflush|fgetline|fgetword|file|fileBrowserDialog|fileDialog|fileExtension|fileInfo|filetest|filletCurve|filter|filterCurve|filterExpand|filterStudioImport|findAllIntersections|findAnimCurves|findKeyframe|findMenuItem|findRelatedSkinCluster|finder|firstParentOf|fitBspline|flexor|floatEq|floatField|floatFieldGrp|floatScrollBar|floatSlider|floatSlider2|floatSliderButtonGrp|floatSliderGrp|floor|flow|fluidCacheInfo|fluidEmitter|fluidVoxelInfo|flushUndo|fmod|fontDialog|fopen|formLayout|format|fprint|frameLayout|fread|freeFormFillet|frewind|fromNativePath|fwrite|gamma|gauss|geometryConstraint|getApplicationVersionAsFloat|getAttr|getClassification|getDefaultBrush|getFileList|getFluidAttr|getInputDeviceRange|getMayaPanelTypes|getModifiers|getPanel|getParticleAttr|getPluginResource|getenv|getpid|glRender|glRenderEditor|globalStitch|gmatch|goal|gotoBindPose|grabColor|gradientControl|gradientControlNoAttr|graphDollyCtx|graphSelectContext|graphTrackCtx|gravity|grid|gridLayout|group|groupObjectsByName|hardenPointCurve|hardware|hardwareRenderPanel|headsUpDisplay|headsUpMessage|help|helpLine|hermite|hide|hilite|hitTest|hotBox|hotkey|hotkeyCheck|hsv_to_rgb|hudButton|hudSlider|hudSliderButton|hwReflectionMap|hwRender|hwRenderLoad|hyperGraph|hyperPanel|hyperShade|hypot|iconTextButton|iconTextCheckBox|iconTextRadioButton|iconTextRadioCollection|iconTextScrollList|iconTextStaticLabel|ikHandle|ikHandleCtx|ikHandleDisplayScale|ikSolver|ikSplineHandleCtx|ikSystem|ikSystemInfo|ikfkDisplayMethod|illustratorCurves|image|imfPlugins|inheritTransform|insertJoint|insertJointCtx|insertKeyCtx|insertKnotCurve|insertKnotSurface|instance|instanceable|instancer|intField|intFieldGrp|intScrollBar|intSlider|intSliderGrp|interToUI|internalVar|intersect|iprEngine|isAnimCurve|isConnected|isDirty|isParentOf|isSameObject|isTrue|isValidObjectName|isValidString|isValidUiName|isolateSelect|itemFilter|itemFilterAttr|itemFilterRender|itemFilterType|joint|jointCluster|jointCtx|jointDisplayScale|jointLattice|keyTangent|keyframe|keyframeOutliner|keyframeRegionCurrentTimeCtx|keyframeRegionDirectKeyCtx|keyframeRegionDollyCtx|keyframeRegionInsertKeyCtx|keyframeRegionMoveKeyCtx|keyframeRegionScaleKeyCtx|keyframeRegionSelectKeyCtx|keyframeRegionSetKeyCtx|keyframeRegionTrackCtx|keyframeStats|lassoContext|lattice|latticeDeformKeyCtx|launch|launchImageEditor|layerButton|layeredShaderPort|layeredTexturePort|layout|layoutDialog|lightList|lightListEditor|lightListPanel|lightlink|lineIntersection|linearPrecision|linstep|listAnimatable|listAttr|listCameras|listConnections|listDeviceAttachments|listHistory|listInputDeviceAxes|listInputDeviceButtons|listInputDevices|listMenuAnnotation|listNodeTypes|listPanelCategories|listRelatives|listSets|listTransforms|listUnselected|listerEditor|loadFluid|loadNewShelf|loadPlugin|loadPluginLanguageResources|loadPrefObjects|localizedPanelLabel|lockNode|loft|log|longNameOf|lookThru|ls|lsThroughFilter|lsType|lsUI|mag|makeIdentity|makeLive|makePaintable|makeRoll|makeSingleSurface|makeTubeOn|makebot|manipMoveContext|manipMoveLimitsCtx|manipOptions|manipRotateContext|manipRotateLimitsCtx|manipScaleContext|manipScaleLimitsCtx|marker|match|max|memory|menu|menuBarLayout|menuEditor|menuItem|menuItemToShelf|menuSet|menuSetPref|messageLine|min|minimizeApp|mirrorJoint|modelCurrentTimeCtx|modelEditor|modelPanel|mouse|movIn|movOut|move|moveIKtoFK|moveKeyCtx|moveVertexAlongDirection|multiProfileBirailSurface|mute|nParticle|nameCommand|nameField|namespace|namespaceInfo|newPanelItems|newton|nodeCast|nodeIconButton|nodeOutliner|nodePreset|nodeType|noise|nonLinear|normalConstraint|normalize|nurbsBoolean|nurbsCopyUVSet|nurbsCube|nurbsEditUV|nurbsPlane|nurbsSelect|nurbsSquare|nurbsToPoly|nurbsToPolygonsPref|nurbsToSubdiv|nurbsToSubdivPref|nurbsUVSet|nurbsViewDirectionVector|objExists|objectCenter|objectLayer|objectType|objectTypeUI|obsoleteProc|oceanNurbsPreviewPlane|offsetCurve|offsetCurveOnSurface|offsetSurface|openGLExtension|openMayaPref|optionMenu|optionMenuGrp|optionVar|orbit|orbitCtx|orientConstraint|outlinerEditor|outlinerPanel|overrideModifier|paintEffectsDisplay|pairBlend|palettePort|paneLayout|panel|panelConfiguration|panelHistory|paramDimContext|paramDimension|paramLocator|parent|parentConstraint|particle|particleExists|particleInstancer|particleRenderInfo|partition|pasteKey|pathAnimation|pause|pclose|percent|performanceOptions|pfxstrokes|pickWalk|picture|pixelMove|planarSrf|plane|play|playbackOptions|playblast|plugAttr|plugNode|pluginInfo|pluginResourceUtil|pointConstraint|pointCurveConstraint|pointLight|pointMatrixMult|pointOnCurve|pointOnSurface|pointPosition|poleVectorConstraint|polyAppend|polyAppendFacetCtx|polyAppendVertex|polyAutoProjection|polyAverageNormal|polyAverageVertex|polyBevel|polyBlendColor|polyBlindData|polyBoolOp|polyBridgeEdge|polyCacheMonitor|polyCheck|polyChipOff|polyClipboard|polyCloseBorder|polyCollapseEdge|polyCollapseFacet|polyColorBlindData|polyColorDel|polyColorPerVertex|polyColorSet|polyCompare|polyCone|polyCopyUV|polyCrease|polyCreaseCtx|polyCreateFacet|polyCreateFacetCtx|polyCube|polyCut|polyCutCtx|polyCylinder|polyCylindricalProjection|polyDelEdge|polyDelFacet|polyDelVertex|polyDuplicateAndConnect|polyDuplicateEdge|polyEditUV|polyEditUVShell|polyEvaluate|polyExtrudeEdge|polyExtrudeFacet|polyExtrudeVertex|polyFlipEdge|polyFlipUV|polyForceUV|polyGeoSampler|polyHelix|polyInfo|polyInstallAction|polyLayoutUV|polyListComponentConversion|polyMapCut|polyMapDel|polyMapSew|polyMapSewMove|polyMergeEdge|polyMergeEdgeCtx|polyMergeFacet|polyMergeFacetCtx|polyMergeUV|polyMergeVertex|polyMirrorFace|polyMoveEdge|polyMoveFacet|polyMoveFacetUV|polyMoveUV|polyMoveVertex|polyNormal|polyNormalPerVertex|polyNormalizeUV|polyOptUvs|polyOptions|polyOutput|polyPipe|polyPlanarProjection|polyPlane|polyPlatonicSolid|polyPoke|polyPrimitive|polyPrism|polyProjection|polyPyramid|polyQuad|polyQueryBlindData|polyReduce|polySelect|polySelectConstraint|polySelectConstraintMonitor|polySelectCtx|polySelectEditCtx|polySeparate|polySetToFaceNormal|polySewEdge|polyShortestPathCtx|polySmooth|polySoftEdge|polySphere|polySphericalProjection|polySplit|polySplitCtx|polySplitEdge|polySplitRing|polySplitVertex|polyStraightenUVBorder|polySubdivideEdge|polySubdivideFacet|polyToSubdiv|polyTorus|polyTransfer|polyTriangulate|polyUVSet|polyUnite|polyWedgeFace|popen|popupMenu|pose|pow|preloadRefEd|print|progressBar|progressWindow|projFileViewer|projectCurve|projectTangent|projectionContext|projectionManip|promptDialog|propModCtx|propMove|psdChannelOutliner|psdEditTextureFile|psdExport|psdTextureFile|putenv|pwd|python|querySubdiv|quit|rad_to_deg|radial|radioButton|radioButtonGrp|radioCollection|radioMenuItemCollection|rampColorPort|rand|randomizeFollicles|randstate|rangeControl|readTake|rebuildCurve|rebuildSurface|recordAttr|recordDevice|redo|reference|referenceEdit|referenceQuery|refineSubdivSelectionList|refresh|refreshAE|registerPluginResource|rehash|reloadImage|removeJoint|removeMultiInstance|removePanelCategory|rename|renameAttr|renameSelectionList|renameUI|render|renderGlobalsNode|renderInfo|renderLayerButton|renderLayerParent|renderLayerPostProcess|renderLayerUnparent|renderManip|renderPartition|renderQualityNode|renderSettings|renderThumbnailUpdate|renderWindowEditor|renderWindowSelectContext|renderer|reorder|reorderDeformers|requires|reroot|resampleFluid|resetAE|resetPfxToPolyCamera|resetTool|resolutionNode|retarget|reverseCurve|reverseSurface|revolve|rgb_to_hsv|rigidBody|rigidSolver|roll|rollCtx|rootOf|rot|rotate|rotationInterpolation|roundConstantRadius|rowColumnLayout|rowLayout|runTimeCommand|runup|sampleImage|saveAllShelves|saveAttrPreset|saveFluid|saveImage|saveInitialState|saveMenu|savePrefObjects|savePrefs|saveShelf|saveToolSettings|scale|scaleBrushBrightness|scaleComponents|scaleConstraint|scaleKey|scaleKeyCtx|sceneEditor|sceneUIReplacement|scmh|scriptCtx|scriptEditorInfo|scriptJob|scriptNode|scriptTable|scriptToShelf|scriptedPanel|scriptedPanelType|scrollField|scrollLayout|sculpt|searchPathArray|seed|selLoadSettings|select|selectContext|selectCurveCV|selectKey|selectKeyCtx|selectKeyframeRegionCtx|selectMode|selectPref|selectPriority|selectType|selectedNodes|selectionConnection|separator|setAttr|setAttrEnumResource|setAttrMapping|setAttrNiceNameResource|setConstraintRestPosition|setDefaultShadingGroup|setDrivenKeyframe|setDynamic|setEditCtx|setEditor|setFluidAttr|setFocus|setInfinity|setInputDeviceMapping|setKeyCtx|setKeyPath|setKeyframe|setKeyframeBlendshapeTargetWts|setMenuMode|setNodeNiceNameResource|setNodeTypeFlag|setParent|setParticleAttr|setPfxToPolyCamera|setPluginResource|setProject|setStampDensity|setStartupMessage|setState|setToolTo|setUITemplate|setXformManip|sets|shadingConnection|shadingGeometryRelCtx|shadingLightRelCtx|shadingNetworkCompare|shadingNode|shapeCompare|shelfButton|shelfLayout|shelfTabLayout|shellField|shortNameOf|showHelp|showHidden|showManipCtx|showSelectionInTitle|showShadingGroupAttrEditor|showWindow|sign|simplify|sin|singleProfileBirailSurface|size|sizeBytes|skinCluster|skinPercent|smoothCurve|smoothTangentSurface|smoothstep|snap2to2|snapKey|snapMode|snapTogetherCtx|snapshot|soft|softMod|softModCtx|sort|sound|soundControl|source|spaceLocator|sphere|sphrand|spotLight|spotLightPreviewPort|spreadSheetEditor|spring|sqrt|squareSurface|srtContext|stackTrace|startString|startsWith|stitchAndExplodeShell|stitchSurface|stitchSurfacePoints|strcmp|stringArrayCatenate|stringArrayContains|stringArrayCount|stringArrayInsertAtIndex|stringArrayIntersector|stringArrayRemove|stringArrayRemoveAtIndex|stringArrayRemoveDuplicates|stringArrayRemoveExact|stringArrayToString|stringToStringArray|strip|stripPrefixFromName|stroke|subdAutoProjection|subdCleanTopology|subdCollapse|subdDuplicateAndConnect|subdEditUV|subdListComponentConversion|subdMapCut|subdMapSewMove|subdMatchTopology|subdMirror|subdToBlind|subdToPoly|subdTransferUVsToCache|subdiv|subdivCrease|subdivDisplaySmoothness|substitute|substituteAllString|substituteGeometry|substring|surface|surfaceSampler|surfaceShaderList|swatchDisplayPort|switchTable|symbolButton|symbolCheckBox|sysFile|system|tabLayout|tan|tangentConstraint|texLatticeDeformContext|texManipContext|texMoveContext|texMoveUVShellContext|texRotateContext|texScaleContext|texSelectContext|texSelectShortestPathCtx|texSmudgeUVContext|texWinToolCtx|text|textCurves|textField|textFieldButtonGrp|textFieldGrp|textManip|textScrollList|textToShelf|textureDisplacePlane|textureHairColor|texturePlacementContext|textureWindow|threadCount|threePointArcCtx|timeControl|timePort|timerX|toNativePath|toggle|toggleAxis|toggleWindowVisibility|tokenize|tokenizeList|tolerance|tolower|toolButton|toolCollection|toolDropped|toolHasOptions|toolPropertyWindow|torus|toupper|trace|track|trackCtx|transferAttributes|transformCompare|transformLimits|translator|trim|trunc|truncateFluidCache|truncateHairCache|tumble|tumbleCtx|turbulence|twoPointArcCtx|uiRes|uiTemplate|unassignInputDevice|undo|undoInfo|ungroup|uniform|unit|unloadPlugin|untangleUV|untitledFileName|untrim|upAxis|updateAE|userCtx|uvLink|uvSnapshot|validateShelfName|vectorize|view2dToolCtx|viewCamera|viewClipPlane|viewFit|viewHeadOn|viewLookAt|viewManip|viewPlace|viewSet|visor|volumeAxis|vortex|waitCursor|warning|webBrowser|webBrowserPrefs|whatIs|window|windowPref|wire|wireContext|workspace|wrinkle|wrinkleContext|writeTake|xbmLangPathList|xform)\b/,operator:[/\+[+=]?|-[-=]?|&&|\|\||[<>]=|[*\/!=]=?|[%^]/,{pattern:/(^|[^<])<(?!<)/,lookbehind:!0},{pattern:/(^|[^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,:;?\[\](){}]/},t.languages.mel.code.inside.rest=t.languages.mel}return Pc}var Uc,_v;function fq(){if(_v)return Uc;_v=1,Uc=e,e.displayName="mermaid",e.aliases=[];function e(t){t.languages.mermaid={comment:{pattern:/%%.*/,greedy:!0},style:{pattern:/^([ \t]*(?:classDef|linkStyle|style)[ \t]+[\w$-]+[ \t]+)\w.*[^\s;]/m,lookbehind:!0,inside:{property:/\b\w[\w-]*(?=[ \t]*:)/,operator:/:/,punctuation:/,/}},"inter-arrow-label":{pattern:/([^<>ox.=-])(?:-[-.]|==)(?![<>ox.=-])[ \t]*(?:"[^"\r\n]*"|[^\s".=-](?:[^\r\n.=-]*[^\s.=-])?)[ \t]*(?:\.+->?|--+[->]|==+[=>])(?![<>ox.=-])/,lookbehind:!0,greedy:!0,inside:{arrow:{pattern:/(?:\.+->?|--+[->]|==+[=>])$/,alias:"operator"},label:{pattern:/^([\s\S]{2}[ \t]*)\S(?:[\s\S]*\S)?/,lookbehind:!0,alias:"property"},"arrow-head":{pattern:/^\S+/,alias:["arrow","operator"]}}},arrow:[{pattern:/(^|[^{}|o.-])[|}][|o](?:--|\.\.)[|o][|{](?![{}|o.-])/,lookbehind:!0,alias:"operator"},{pattern:/(^|[^<>ox.=-])(?:[ox]?|(?:==+|--+|-\.*-)[>ox]|===+|---+|-\.+-)(?![<>ox.=-])/,lookbehind:!0,alias:"operator"},{pattern:/(^|[^<>()x-])(?:--?(?:>>|[x>)])(?![<>()x])|(?:<<|[x<(])--?(?!-))/,lookbehind:!0,alias:"operator"},{pattern:/(^|[^<>|*o.-])(?:[*o]--|--[*o]|<\|?(?:--|\.\.)|(?:--|\.\.)\|?>|--|\.\.)(?![<>|*o.-])/,lookbehind:!0,alias:"operator"}],label:{pattern:/(^|[^|<])\|(?:[^\r\n"|]|"[^"\r\n]*")+\|/,lookbehind:!0,greedy:!0,alias:"property"},text:{pattern:/(?:[(\[{]+|\b>)(?:[^\r\n"()\[\]{}]|"[^"\r\n]*")+(?:[)\]}]+|>)/,alias:"string"},string:{pattern:/"[^"\r\n]*"/,greedy:!0},annotation:{pattern:/<<(?:abstract|choice|enumeration|fork|interface|join|service)>>|\[\[(?:choice|fork|join)\]\]/i,alias:"important"},keyword:[{pattern:/(^[ \t]*)(?:action|callback|class|classDef|classDiagram|click|direction|erDiagram|flowchart|gantt|gitGraph|graph|journey|link|linkStyle|pie|requirementDiagram|sequenceDiagram|stateDiagram|stateDiagram-v2|style|subgraph)(?![\w$-])/m,lookbehind:!0,greedy:!0},{pattern:/(^[ \t]*)(?:activate|alt|and|as|autonumber|deactivate|else|end(?:[ \t]+note)?|loop|opt|par|participant|rect|state|note[ \t]+(?:over|(?:left|right)[ \t]+of))(?![\w$-])/im,lookbehind:!0,greedy:!0}],entity:/#[a-z0-9]+;/,operator:{pattern:/(\w[ \t]*)&(?=[ \t]*\w)|:::|:/,lookbehind:!0},punctuation:/[(){};]/}}return Uc}var Bc,Tv;function gq(){if(Tv)return Bc;Tv=1,Bc=e,e.displayName="mizar",e.aliases=[];function e(t){t.languages.mizar={comment:/::.+/,keyword:/@proof\b|\b(?:according|aggregate|all|and|antonym|are|as|associativity|assume|asymmetry|attr|be|begin|being|by|canceled|case|cases|clusters?|coherence|commutativity|compatibility|connectedness|consider|consistency|constructors|contradiction|correctness|def|deffunc|define|definitions?|defpred|do|does|end|environ|equals|ex|exactly|existence|for|from|func|given|hence|hereby|holds|idempotence|identity|iff?|implies|involutiveness|irreflexivity|is|it|let|means|mode|non|not|notations?|now|of|or|otherwise|over|per|pred|prefix|projectivity|proof|provided|qua|reconsider|redefine|reduce|reducibility|reflexivity|registrations?|requirements|reserve|sch|schemes?|section|selector|set|sethood|st|struct|such|suppose|symmetry|synonym|take|that|the|then|theorems?|thesis|thus|to|transitivity|uniqueness|vocabular(?:ies|y)|when|where|with|wrt)\b/,parameter:{pattern:/\$(?:10|\d)/,alias:"variable"},variable:/\b\w+(?=:)/,number:/(?:\b|-)\d+\b/,operator:/\.\.\.|->|&|\.?=/,punctuation:/\(#|#\)|[,:;\[\](){}]/}}return Bc}var $c,Av;function mq(){if(Av)return $c;Av=1,$c=e,e.displayName="mongodb",e.aliases=[];function e(t){(function(n){var r=["$eq","$gt","$gte","$in","$lt","$lte","$ne","$nin","$and","$not","$nor","$or","$exists","$type","$expr","$jsonSchema","$mod","$regex","$text","$where","$geoIntersects","$geoWithin","$near","$nearSphere","$all","$elemMatch","$size","$bitsAllClear","$bitsAllSet","$bitsAnyClear","$bitsAnySet","$comment","$elemMatch","$meta","$slice","$currentDate","$inc","$min","$max","$mul","$rename","$set","$setOnInsert","$unset","$addToSet","$pop","$pull","$push","$pullAll","$each","$position","$slice","$sort","$bit","$addFields","$bucket","$bucketAuto","$collStats","$count","$currentOp","$facet","$geoNear","$graphLookup","$group","$indexStats","$limit","$listLocalSessions","$listSessions","$lookup","$match","$merge","$out","$planCacheStats","$project","$redact","$replaceRoot","$replaceWith","$sample","$set","$skip","$sort","$sortByCount","$unionWith","$unset","$unwind","$setWindowFields","$abs","$accumulator","$acos","$acosh","$add","$addToSet","$allElementsTrue","$and","$anyElementTrue","$arrayElemAt","$arrayToObject","$asin","$asinh","$atan","$atan2","$atanh","$avg","$binarySize","$bsonSize","$ceil","$cmp","$concat","$concatArrays","$cond","$convert","$cos","$dateFromParts","$dateToParts","$dateFromString","$dateToString","$dayOfMonth","$dayOfWeek","$dayOfYear","$degreesToRadians","$divide","$eq","$exp","$filter","$first","$floor","$function","$gt","$gte","$hour","$ifNull","$in","$indexOfArray","$indexOfBytes","$indexOfCP","$isArray","$isNumber","$isoDayOfWeek","$isoWeek","$isoWeekYear","$last","$last","$let","$literal","$ln","$log","$log10","$lt","$lte","$ltrim","$map","$max","$mergeObjects","$meta","$min","$millisecond","$minute","$mod","$month","$multiply","$ne","$not","$objectToArray","$or","$pow","$push","$radiansToDegrees","$range","$reduce","$regexFind","$regexFindAll","$regexMatch","$replaceOne","$replaceAll","$reverseArray","$round","$rtrim","$second","$setDifference","$setEquals","$setIntersection","$setIsSubset","$setUnion","$size","$sin","$slice","$split","$sqrt","$stdDevPop","$stdDevSamp","$strcasecmp","$strLenBytes","$strLenCP","$substr","$substrBytes","$substrCP","$subtract","$sum","$switch","$tan","$toBool","$toDate","$toDecimal","$toDouble","$toInt","$toLong","$toObjectId","$toString","$toLower","$toUpper","$trim","$trunc","$type","$week","$year","$zip","$count","$dateAdd","$dateDiff","$dateSubtract","$dateTrunc","$getField","$rand","$sampleRate","$setField","$unsetField","$comment","$explain","$hint","$max","$maxTimeMS","$min","$orderby","$query","$returnKey","$showDiskLoc","$natural"],a=["ObjectId","Code","BinData","DBRef","Timestamp","NumberLong","NumberDecimal","MaxKey","MinKey","RegExp","ISODate","UUID"];r=r.map(function(o){return o.replace("$","\\$")});var i="(?:"+r.join("|")+")\\b";n.languages.mongodb=n.languages.extend("javascript",{}),n.languages.insertBefore("mongodb","string",{property:{pattern:/(?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)(?=\s*:)/,greedy:!0,inside:{keyword:RegExp(`^(['"])?`+i+"(?:\\1)?$")}}}),n.languages.mongodb.string.inside={url:{pattern:/https?:\/\/[-\w@:%.+~#=]{1,256}\.[a-z0-9()]{1,6}\b[-\w()@:%+.~#?&/=]*/i,greedy:!0},entity:{pattern:/\b(?:(?:[01]?\d\d?|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d\d?|2[0-4]\d|25[0-5])\b/,greedy:!0}},n.languages.insertBefore("mongodb","constant",{builtin:{pattern:RegExp("\\b(?:"+a.join("|")+")\\b"),alias:"keyword"}})})(t)}return $c}var zc,Rv;function hq(){if(Rv)return zc;Rv=1,zc=e,e.displayName="monkey",e.aliases=[];function e(t){t.languages.monkey={comment:{pattern:/^#Rem\s[\s\S]*?^#End|'.+/im,greedy:!0},string:{pattern:/"[^"\r\n]*"/,greedy:!0},preprocessor:{pattern:/(^[ \t]*)#.+/m,lookbehind:!0,greedy:!0,alias:"property"},function:/\b\w+(?=\()/,"type-char":{pattern:/\b[?%#$]/,alias:"class-name"},number:{pattern:/((?:\.\.)?)(?:(?:\b|\B-\.?|\B\.)\d+(?:(?!\.\.)\.\d*)?|\$[\da-f]+)/i,lookbehind:!0},keyword:/\b(?:Abstract|Array|Bool|Case|Catch|Class|Const|Continue|Default|Eachin|Else|ElseIf|End|EndIf|Exit|Extends|Extern|False|Field|Final|Float|For|Forever|Function|Global|If|Implements|Import|Inline|Int|Interface|Local|Method|Module|New|Next|Null|Object|Private|Property|Public|Repeat|Return|Select|Self|Step|Strict|String|Super|Then|Throw|To|True|Try|Until|Void|Wend|While)\b/i,operator:/\.\.|<[=>]?|>=?|:?=|(?:[+\-*\/&~|]|\b(?:Mod|Shl|Shr)\b)=?|\b(?:And|Not|Or)\b/i,punctuation:/[.,:;()\[\]]/}}return zc}var Gc,Iv;function bq(){if(Iv)return Gc;Iv=1,Gc=e,e.displayName="moonscript",e.aliases=["moon"];function e(t){t.languages.moonscript={comment:/--.*/,string:[{pattern:/'[^']*'|\[(=*)\[[\s\S]*?\]\1\]/,greedy:!0},{pattern:/"[^"]*"/,greedy:!0,inside:{interpolation:{pattern:/#\{[^{}]*\}/,inside:{moonscript:{pattern:/(^#\{)[\s\S]+(?=\})/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/#\{|\}/,alias:"punctuation"}}}}}],"class-name":[{pattern:/(\b(?:class|extends)[ \t]+)\w+/,lookbehind:!0},/\b[A-Z]\w*/],keyword:/\b(?:class|continue|do|else|elseif|export|extends|for|from|if|import|in|local|nil|return|self|super|switch|then|unless|using|when|while|with)\b/,variable:/@@?\w*/,property:{pattern:/\b(?!\d)\w+(?=:)|(:)(?!\d)\w+/,lookbehind:!0},function:{pattern:/\b(?:_G|_VERSION|assert|collectgarbage|coroutine\.(?:create|resume|running|status|wrap|yield)|debug\.(?:debug|getfenv|gethook|getinfo|getlocal|getmetatable|getregistry|getupvalue|setfenv|sethook|setlocal|setmetatable|setupvalue|traceback)|dofile|error|getfenv|getmetatable|io\.(?:close|flush|input|lines|open|output|popen|read|stderr|stdin|stdout|tmpfile|type|write)|ipairs|load|loadfile|loadstring|math\.(?:abs|acos|asin|atan|atan2|ceil|cos|cosh|deg|exp|floor|fmod|frexp|ldexp|log|log10|max|min|modf|pi|pow|rad|random|randomseed|sin|sinh|sqrt|tan|tanh)|module|next|os\.(?:clock|date|difftime|execute|exit|getenv|remove|rename|setlocale|time|tmpname)|package\.(?:cpath|loaded|loadlib|path|preload|seeall)|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|string\.(?:byte|char|dump|find|format|gmatch|gsub|len|lower|match|rep|reverse|sub|upper)|table\.(?:concat|insert|maxn|remove|sort)|tonumber|tostring|type|unpack|xpcall)\b/,inside:{punctuation:/\./}},boolean:/\b(?:false|true)\b/,number:/(?:\B\.\d+|\b\d+\.\d+|\b\d+(?=[eE]))(?:[eE][-+]?\d+)?\b|\b(?:0x[a-fA-F\d]+|\d+)(?:U?LL)?\b/,operator:/\.{3}|[-=]>|~=|(?:[-+*/%<>!=]|\.\.)=?|[:#^]|\b(?:and|or)\b=?|\b(?:not)\b/,punctuation:/[.,()[\]{}\\]/},t.languages.moonscript.string[1].inside.interpolation.inside.moonscript.inside=t.languages.moonscript,t.languages.moon=t.languages.moonscript}return Gc}var qc,Cv;function yq(){if(Cv)return qc;Cv=1,qc=e,e.displayName="n1ql",e.aliases=[];function e(t){t.languages.n1ql={comment:{pattern:/\/\*[\s\S]*?(?:$|\*\/)|--.*/,greedy:!0},string:{pattern:/(["'])(?:\\[\s\S]|(?!\1)[^\\]|\1\1)*\1/,greedy:!0},identifier:{pattern:/`(?:\\[\s\S]|[^\\`]|``)*`/,greedy:!0},parameter:/\$[\w.]+/,keyword:/\b(?:ADVISE|ALL|ALTER|ANALYZE|AS|ASC|AT|BEGIN|BINARY|BOOLEAN|BREAK|BUCKET|BUILD|BY|CALL|CAST|CLUSTER|COLLATE|COLLECTION|COMMIT|COMMITTED|CONNECT|CONTINUE|CORRELATE|CORRELATED|COVER|CREATE|CURRENT|DATABASE|DATASET|DATASTORE|DECLARE|DECREMENT|DELETE|DERIVED|DESC|DESCRIBE|DISTINCT|DO|DROP|EACH|ELEMENT|EXCEPT|EXCLUDE|EXECUTE|EXPLAIN|FETCH|FILTER|FLATTEN|FLUSH|FOLLOWING|FOR|FORCE|FROM|FTS|FUNCTION|GOLANG|GRANT|GROUP|GROUPS|GSI|HASH|HAVING|IF|IGNORE|ILIKE|INCLUDE|INCREMENT|INDEX|INFER|INLINE|INNER|INSERT|INTERSECT|INTO|IS|ISOLATION|JAVASCRIPT|JOIN|KEY|KEYS|KEYSPACE|KNOWN|LANGUAGE|LAST|LEFT|LET|LETTING|LEVEL|LIMIT|LSM|MAP|MAPPING|MATCHED|MATERIALIZED|MERGE|MINUS|MISSING|NAMESPACE|NEST|NL|NO|NTH_VALUE|NULL|NULLS|NUMBER|OBJECT|OFFSET|ON|OPTION|OPTIONS|ORDER|OTHERS|OUTER|OVER|PARSE|PARTITION|PASSWORD|PATH|POOL|PRECEDING|PREPARE|PRIMARY|PRIVATE|PRIVILEGE|PROBE|PROCEDURE|PUBLIC|RANGE|RAW|REALM|REDUCE|RENAME|RESPECT|RETURN|RETURNING|REVOKE|RIGHT|ROLE|ROLLBACK|ROW|ROWS|SATISFIES|SAVEPOINT|SCHEMA|SCOPE|SELECT|SELF|SEMI|SET|SHOW|SOME|START|STATISTICS|STRING|SYSTEM|TIES|TO|TRAN|TRANSACTION|TRIGGER|TRUNCATE|UNBOUNDED|UNDER|UNION|UNIQUE|UNKNOWN|UNNEST|UNSET|UPDATE|UPSERT|USE|USER|USING|VALIDATE|VALUE|VALUES|VIA|VIEW|WHERE|WHILE|WINDOW|WITH|WORK|XOR)\b/i,function:/\b[a-z_]\w*(?=\s*\()/i,boolean:/\b(?:FALSE|TRUE)\b/i,number:/(?:\b\d+\.|\B\.)\d+e[+\-]?\d+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/%]|!=|==?|\|\||<[>=]?|>=?|\b(?:AND|ANY|ARRAY|BETWEEN|CASE|ELSE|END|EVERY|EXISTS|FIRST|IN|LIKE|NOT|OR|THEN|VALUED|WHEN|WITHIN)\b/i,punctuation:/[;[\](),.{}:]/}}return qc}var jc,Nv;function Eq(){if(Nv)return jc;Nv=1,jc=e,e.displayName="n4js",e.aliases=["n4jsd"];function e(t){t.languages.n4js=t.languages.extend("javascript",{keyword:/\b(?:Array|any|boolean|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|module|new|null|number|package|private|protected|public|return|set|static|string|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/}),t.languages.insertBefore("n4js","constant",{annotation:{pattern:/@+\w+/,alias:"operator"}}),t.languages.n4jsd=t.languages.n4js}return jc}var Hc,xv;function Sq(){if(xv)return Hc;xv=1,Hc=e,e.displayName="nand2tetrisHdl",e.aliases=[];function e(t){t.languages["nand2tetris-hdl"]={comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,keyword:/\b(?:BUILTIN|CHIP|CLOCKED|IN|OUT|PARTS)\b/,boolean:/\b(?:false|true)\b/,function:/\b[A-Za-z][A-Za-z0-9]*(?=\()/,number:/\b\d+\b/,operator:/=|\.\./,punctuation:/[{}[\];(),:]/}}return Hc}var Vc,Ov;function vq(){if(Ov)return Vc;Ov=1,Vc=e,e.displayName="naniscript",e.aliases=[];function e(t){(function(n){var r=/\{[^\r\n\[\]{}]*\}/,a={"quoted-string":{pattern:/"(?:[^"\\]|\\.)*"/,alias:"operator"},"command-param-id":{pattern:/(\s)\w+:/,lookbehind:!0,alias:"property"},"command-param-value":[{pattern:r,alias:"selector"},{pattern:/([\t ])\S+/,lookbehind:!0,greedy:!0,alias:"operator"},{pattern:/\S(?:.*\S)?/,alias:"operator"}]};n.languages.naniscript={comment:{pattern:/^([\t ]*);.*/m,lookbehind:!0},define:{pattern:/^>.+/m,alias:"tag",inside:{value:{pattern:/(^>\w+[\t ]+)(?!\s)[^{}\r\n]+/,lookbehind:!0,alias:"operator"},key:{pattern:/(^>)\w+/,lookbehind:!0}}},label:{pattern:/^([\t ]*)#[\t ]*\w+[\t ]*$/m,lookbehind:!0,alias:"regex"},command:{pattern:/^([\t ]*)@\w+(?=[\t ]|$).*/m,lookbehind:!0,alias:"function",inside:{"command-name":/^@\w+/,expression:{pattern:r,greedy:!0,alias:"selector"},"command-params":{pattern:/\s*\S[\s\S]*/,inside:a}}},"generic-text":{pattern:/(^[ \t]*)[^#@>;\s].*/m,lookbehind:!0,alias:"punctuation",inside:{"escaped-char":/\\[{}\[\]"]/,expression:{pattern:r,greedy:!0,alias:"selector"},"inline-command":{pattern:/\[[\t ]*\w[^\r\n\[\]]*\]/,greedy:!0,alias:"function",inside:{"command-params":{pattern:/(^\[[\t ]*\w+\b)[\s\S]+(?=\]$)/,lookbehind:!0,inside:a},"command-param-name":{pattern:/^(\[[\t ]*)\w+/,lookbehind:!0,alias:"name"},"start-stop-char":/[\[\]]/}}}}},n.languages.nani=n.languages.naniscript,n.hooks.add("after-tokenize",function(s){var l=s.tokens;l.forEach(function(u){if(typeof u!="string"&&u.type==="generic-text"){var d=o(u);i(d)||(u.type="bad-line",u.content=d)}})});function i(s){for(var l="[]{}",u=[],d=0;d=&|$!]/}}return Wc}var Yc,Dv;function wq(){if(Dv)return Yc;Dv=1,Yc=e,e.displayName="neon",e.aliases=[];function e(t){t.languages.neon={comment:{pattern:/#.*/,greedy:!0},datetime:{pattern:/(^|[[{(=:,\s])\d\d\d\d-\d\d?-\d\d?(?:(?:[Tt]| +)\d\d?:\d\d:\d\d(?:\.\d*)? *(?:Z|[-+]\d\d?(?::?\d\d)?)?)?(?=$|[\]}),\s])/,lookbehind:!0,alias:"number"},key:{pattern:/(^|[[{(,\s])[^,:=[\]{}()'"\s]+(?=\s*:(?:$|[\]}),\s])|\s*=)/,lookbehind:!0,alias:"atrule"},number:{pattern:/(^|[[{(=:,\s])[+-]?(?:0x[\da-fA-F]+|0o[0-7]+|0b[01]+|(?:\d+(?:\.\d*)?|\.?\d+)(?:[eE][+-]?\d+)?)(?=$|[\]}),:=\s])/,lookbehind:!0},boolean:{pattern:/(^|[[{(=:,\s])(?:false|no|true|yes)(?=$|[\]}),:=\s])/i,lookbehind:!0},null:{pattern:/(^|[[{(=:,\s])(?:null)(?=$|[\]}),:=\s])/i,lookbehind:!0,alias:"keyword"},string:{pattern:/(^|[[{(=:,\s])(?:('''|""")\r?\n(?:(?:[^\r\n]|\r?\n(?![\t ]*\2))*\r?\n)?[\t ]*\2|'[^'\r\n]*'|"(?:\\.|[^\\"\r\n])*")/,lookbehind:!0,greedy:!0},literal:{pattern:/(^|[[{(=:,\s])(?:[^#"',:=[\]{}()\s`-]|[:-][^"',=[\]{}()\s])(?:[^,:=\]})(\s]|:(?![\s,\]})]|$)|[ \t]+[^#,:=\]})(\s])*/,lookbehind:!0,alias:"string"},punctuation:/[,:=[\]{}()-]/}}return Yc}var Kc,Mv;function _q(){if(Mv)return Kc;Mv=1,Kc=e,e.displayName="nevod",e.aliases=[];function e(t){t.languages.nevod={comment:/\/\/.*|(?:\/\*[\s\S]*?(?:\*\/|$))/,string:{pattern:/(?:"(?:""|[^"])*"(?!")|'(?:''|[^'])*'(?!'))!?\*?/,greedy:!0,inside:{"string-attrs":/!$|!\*$|\*$/}},namespace:{pattern:/(@namespace\s+)[a-zA-Z0-9\-.]+(?=\s*\{)/,lookbehind:!0},pattern:{pattern:/(@pattern\s+)?#?[a-zA-Z0-9\-.]+(?:\s*\(\s*(?:~\s*)?[a-zA-Z0-9\-.]+\s*(?:,\s*(?:~\s*)?[a-zA-Z0-9\-.]*)*\))?(?=\s*=)/,lookbehind:!0,inside:{"pattern-name":{pattern:/^#?[a-zA-Z0-9\-.]+/,alias:"class-name"},fields:{pattern:/\(.*\)/,inside:{"field-name":{pattern:/[a-zA-Z0-9\-.]+/,alias:"variable"},punctuation:/[,()]/,operator:{pattern:/~/,alias:"field-hidden-mark"}}}}},search:{pattern:/(@search\s+|#)[a-zA-Z0-9\-.]+(?:\.\*)?(?=\s*;)/,alias:"function",lookbehind:!0},keyword:/@(?:having|inside|namespace|outside|pattern|require|search|where)\b/,"standard-pattern":{pattern:/\b(?:Alpha|AlphaNum|Any|Blank|End|LineBreak|Num|NumAlpha|Punct|Space|Start|Symbol|Word|WordBreak)\b(?:\([a-zA-Z0-9\-.,\s+]*\))?/,inside:{"standard-pattern-name":{pattern:/^[a-zA-Z0-9\-.]+/,alias:"builtin"},quantifier:{pattern:/\b\d+(?:\s*\+|\s*-\s*\d+)?(?!\w)/,alias:"number"},"standard-pattern-attr":{pattern:/[a-zA-Z0-9\-.]+/,alias:"builtin"},punctuation:/[,()]/}},quantifier:{pattern:/\b\d+(?:\s*\+|\s*-\s*\d+)?(?!\w)/,alias:"number"},operator:[{pattern:/=/,alias:"pattern-def"},{pattern:/&/,alias:"conjunction"},{pattern:/~/,alias:"exception"},{pattern:/\?/,alias:"optionality"},{pattern:/[[\]]/,alias:"repetition"},{pattern:/[{}]/,alias:"variation"},{pattern:/[+_]/,alias:"sequence"},{pattern:/\.{2,3}/,alias:"span"}],"field-capture":[{pattern:/([a-zA-Z0-9\-.]+\s*\()\s*[a-zA-Z0-9\-.]+\s*:\s*[a-zA-Z0-9\-.]+(?:\s*,\s*[a-zA-Z0-9\-.]+\s*:\s*[a-zA-Z0-9\-.]+)*(?=\s*\))/,lookbehind:!0,inside:{"field-name":{pattern:/[a-zA-Z0-9\-.]+/,alias:"variable"},colon:/:/}},{pattern:/[a-zA-Z0-9\-.]+\s*:/,inside:{"field-name":{pattern:/[a-zA-Z0-9\-.]+/,alias:"variable"},colon:/:/}}],punctuation:/[:;,()]/,name:/[a-zA-Z0-9\-.]+/}}return Kc}var Xc,Fv;function Tq(){if(Fv)return Xc;Fv=1,Xc=e,e.displayName="nginx",e.aliases=[];function e(t){(function(n){var r=/\$(?:\w[a-z\d]*(?:_[^\x00-\x1F\s"'\\()$]*)?|\{[^}\s"'\\]+\})/i;n.languages.nginx={comment:{pattern:/(^|[\s{};])#.*/,lookbehind:!0,greedy:!0},directive:{pattern:/(^|\s)\w(?:[^;{}"'\\\s]|\\.|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\s+(?:#.*(?!.)|(?![#\s])))*?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:{string:{pattern:/((?:^|[^\\])(?:\\\\)*)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,lookbehind:!0,greedy:!0,inside:{escape:{pattern:/\\["'\\nrt]/,alias:"entity"},variable:r}},comment:{pattern:/(\s)#.*/,lookbehind:!0,greedy:!0},keyword:{pattern:/^\S+/,greedy:!0},boolean:{pattern:/(\s)(?:off|on)(?!\S)/,lookbehind:!0},number:{pattern:/(\s)\d+[a-z]*(?!\S)/i,lookbehind:!0},variable:r}},punctuation:/[{};]/}})(t)}return Xc}var Zc,Pv;function Aq(){if(Pv)return Zc;Pv=1,Zc=e,e.displayName="nim",e.aliases=[];function e(t){t.languages.nim={comment:{pattern:/#.*/,greedy:!0},string:{pattern:/(?:\b(?!\d)(?:\w|\\x[89a-fA-F][0-9a-fA-F])+)?(?:"""[\s\S]*?"""(?!")|"(?:\\[\s\S]|""|[^"\\])*")/,greedy:!0},char:{pattern:/'(?:\\(?:\d+|x[\da-fA-F]{0,2}|.)|[^'])'/,greedy:!0},function:{pattern:/(?:(?!\d)(?:\w|\\x[89a-fA-F][0-9a-fA-F])+|`[^`\r\n]+`)\*?(?:\[[^\]]+\])?(?=\s*\()/,greedy:!0,inside:{operator:/\*$/}},identifier:{pattern:/`[^`\r\n]+`/,greedy:!0,inside:{punctuation:/`/}},number:/\b(?:0[xXoObB][\da-fA-F_]+|\d[\d_]*(?:(?!\.\.)\.[\d_]*)?(?:[eE][+-]?\d[\d_]*)?)(?:'?[iuf]\d*)?/,keyword:/\b(?:addr|as|asm|atomic|bind|block|break|case|cast|concept|const|continue|converter|defer|discard|distinct|do|elif|else|end|enum|except|export|finally|for|from|func|generic|if|import|include|interface|iterator|let|macro|method|mixin|nil|object|out|proc|ptr|raise|ref|return|static|template|try|tuple|type|using|var|when|while|with|without|yield)\b/,operator:{pattern:/(^|[({\[](?=\.\.)|(?![({\[]\.).)(?:(?:[=+\-*\/<>@$~&%|!?^:\\]|\.\.|\.(?![)}\]]))+|\b(?:and|div|in|is|isnot|mod|not|notin|of|or|shl|shr|xor)\b)/m,lookbehind:!0},punctuation:/[({\[]\.|\.[)}\]]|[`(){}\[\],:]/}}return Zc}var Qc,Uv;function Rq(){if(Uv)return Qc;Uv=1,Qc=e,e.displayName="nix",e.aliases=[];function e(t){t.languages.nix={comment:{pattern:/\/\*[\s\S]*?\*\/|#.*/,greedy:!0},string:{pattern:/"(?:[^"\\]|\\[\s\S])*"|''(?:(?!'')[\s\S]|''(?:'|\\|\$\{))*''/,greedy:!0,inside:{interpolation:{pattern:/(^|(?:^|(?!'').)[^\\])\$\{(?:[^{}]|\{[^}]*\})*\}/,lookbehind:!0,inside:null}}},url:[/\b(?:[a-z]{3,7}:\/\/)[\w\-+%~\/.:#=?&]+/,{pattern:/([^\/])(?:[\w\-+%~.:#=?&]*(?!\/\/)[\w\-+%~\/.:#=?&])?(?!\/\/)\/[\w\-+%~\/.:#=?&]*/,lookbehind:!0}],antiquotation:{pattern:/\$(?=\{)/,alias:"important"},number:/\b\d+\b/,keyword:/\b(?:assert|builtins|else|if|in|inherit|let|null|or|then|with)\b/,function:/\b(?:abort|add|all|any|attrNames|attrValues|baseNameOf|compareVersions|concatLists|currentSystem|deepSeq|derivation|dirOf|div|elem(?:At)?|fetch(?:Tarball|url)|filter(?:Source)?|fromJSON|genList|getAttr|getEnv|hasAttr|hashString|head|import|intersectAttrs|is(?:Attrs|Bool|Function|Int|List|Null|String)|length|lessThan|listToAttrs|map|mul|parseDrvName|pathExists|read(?:Dir|File)|removeAttrs|replaceStrings|seq|sort|stringLength|sub(?:string)?|tail|throw|to(?:File|JSON|Path|String|XML)|trace|typeOf)\b|\bfoldl'\B/,boolean:/\b(?:false|true)\b/,operator:/[=!<>]=?|\+\+?|\|\||&&|\/\/|->?|[?@]/,punctuation:/[{}()[\].,:;]/},t.languages.nix.string.inside.interpolation.inside=t.languages.nix}return Qc}var Jc,Bv;function Iq(){if(Bv)return Jc;Bv=1,Jc=e,e.displayName="nsis",e.aliases=[];function e(t){t.languages.nsis={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|[#;].*)/,lookbehind:!0,greedy:!0},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:{pattern:/(^[\t ]*)(?:Abort|Add(?:BrandingImage|Size)|AdvSplash|Allow(?:RootDirInstall|SkipFiles)|AutoCloseWindow|BG(?:Font|Gradient|Image)|Banner|BrandingText|BringToFront|CRCCheck|Call(?:InstDLL)?|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|Create(?:Directory|Font|ShortCut)|Delete(?:INISec|INIStr|RegKey|RegValue)?|Detail(?:Print|sButtonText)|Dialer|Dir(?:Text|Var|Verify)|EnableWindow|Enum(?:RegKey|RegValue)|Exch|Exec(?:Shell(?:Wait)?|Wait)?|ExpandEnvStrings|File(?:BufSize|Close|ErrorText|Open|Read|ReadByte|ReadUTF16LE|ReadWord|Seek|Write|WriteByte|WriteUTF16LE|WriteWord)?|Find(?:Close|First|Next|Window)|FlushINI|Get(?:CurInstType|CurrentAddress|DLLVersion(?:Local)?|DlgItem|ErrorLevel|FileTime(?:Local)?|FullPathName|Function(?:Address|End)?|InstDirError|LabelAddress|TempFileName)|Goto|HideWindow|Icon|If(?:Abort|Errors|FileExists|RebootFlag|Silent)|InitPluginsDir|InstProgressFlags|Inst(?:Type(?:GetText|SetText)?)|Install(?:ButtonText|Colors|Dir(?:RegKey)?)|Int(?:64|Ptr)?CmpU?|Int(?:64)?Fmt|Int(?:Ptr)?Op|IsWindow|Lang(?:DLL|String)|License(?:BkColor|Data|ForceSelection|LangString|Text)|LoadLanguageFile|LockWindow|Log(?:Set|Text)|Manifest(?:DPIAware|SupportedOS)|Math|MessageBox|MiscButtonText|NSISdl|Name|Nop|OutFile|PE(?:DllCharacteristics|SubsysVer)|Page(?:Callbacks)?|Pop|Push|Quit|RMDir|Read(?:EnvStr|INIStr|RegDWORD|RegStr)|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|SearchPath|Section(?:End|GetFlags|GetInstTypes|GetSize|GetText|Group|In|SetFlags|SetInstTypes|SetSize|SetText)?|SendMessage|Set(?:AutoClose|BrandingImage|Compress|Compressor(?:DictSize)?|CtlColors|CurInstType|DatablockOptimize|DateSave|Details(?:Print|View)|ErrorLevel|Errors|FileAttributes|Font|OutPath|Overwrite|PluginUnload|RebootFlag|RegView|ShellVarContext|Silent)|Show(?:InstDetails|UninstDetails|Window)|Silent(?:Install|UnInstall)|Sleep|SpaceTexts|Splash|StartMenu|Str(?:CmpS?|Cpy|Len)|SubCaption|System|UnRegDLL|Unicode|UninstPage|Uninstall(?:ButtonText|Caption|Icon|SubCaption|Text)|UserInfo|VI(?:AddVersionKey|FileVersion|ProductVersion)|VPatch|Var|WindowIcon|Write(?:INIStr|Reg(?:Bin|DWORD|ExpandStr|MultiStr|None|Str)|Uninstaller)|XPStyle|ns(?:Dialogs|Exec))\b/m,lookbehind:!0},property:/\b(?:ARCHIVE|FILE_(?:ATTRIBUTE_ARCHIVE|ATTRIBUTE_NORMAL|ATTRIBUTE_OFFLINE|ATTRIBUTE_READONLY|ATTRIBUTE_SYSTEM|ATTRIBUTE_TEMPORARY)|HK(?:(?:CR|CU|LM)(?:32|64)?|DD|PD|U)|HKEY_(?:CLASSES_ROOT|CURRENT_CONFIG|CURRENT_USER|DYN_DATA|LOCAL_MACHINE|PERFORMANCE_DATA|USERS)|ID(?:ABORT|CANCEL|IGNORE|NO|OK|RETRY|YES)|MB_(?:ABORTRETRYIGNORE|DEFBUTTON1|DEFBUTTON2|DEFBUTTON3|DEFBUTTON4|ICONEXCLAMATION|ICONINFORMATION|ICONQUESTION|ICONSTOP|OK|OKCANCEL|RETRYCANCEL|RIGHT|RTLREADING|SETFOREGROUND|TOPMOST|USERICON|YESNO)|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY|admin|all|auto|both|colored|false|force|hide|highest|lastused|leave|listonly|none|normal|notset|off|on|open|print|show|silent|silentlog|smooth|textonly|true|user)\b/,constant:/\$\{[!\w\.:\^-]+\}|\$\([!\w\.:\^-]+\)/,variable:/\$\w[\w\.]*/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|\+\+?|<=?|>=?|==?=?|&&?|\|\|?|[?*\/~^%]/,punctuation:/[{}[\];(),.:]/,important:{pattern:/(^[\t ]*)!(?:addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversion|gettlbversion|if|ifdef|ifmacrodef|ifmacrondef|ifndef|include|insertmacro|macro|macroend|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|verbose|warning)\b/im,lookbehind:!0}}}return Jc}var ed,$v;function Cq(){if($v)return ed;$v=1;var e=tr();ed=t,t.displayName="objectivec",t.aliases=["objc"];function t(n){n.register(e),n.languages.objectivec=n.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete n.languages.objectivec["class-name"],n.languages.objc=n.languages.objectivec}return ed}var td,zv;function Nq(){if(zv)return td;zv=1,td=e,e.displayName="ocaml",e.aliases=[];function e(t){t.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/}}return td}var nd,Gv;function xq(){if(Gv)return nd;Gv=1;var e=tr();nd=t,t.displayName="opencl",t.aliases=[];function t(n){n.register(e),function(r){r.languages.opencl=r.languages.extend("c",{keyword:/\b(?:(?:__)?(?:constant|global|kernel|local|private|read_only|read_write|write_only)|__attribute__|auto|(?:bool|u?(?:char|int|long|short)|half|quad)(?:2|3|4|8|16)?|break|case|complex|const|continue|(?:double|float)(?:16(?:x(?:1|2|4|8|16))?|1x(?:1|2|4|8|16)|2(?:x(?:1|2|4|8|16))?|3|4(?:x(?:1|2|4|8|16))?|8(?:x(?:1|2|4|8|16))?)?|default|do|else|enum|extern|for|goto|if|imaginary|inline|packed|pipe|register|restrict|return|signed|sizeof|static|struct|switch|typedef|uniform|union|unsigned|void|volatile|while)\b/,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[fuhl]{0,4}/i,boolean:/\b(?:false|true)\b/,"constant-opencl-kernel":{pattern:/\b(?:CHAR_(?:BIT|MAX|MIN)|CLK_(?:ADDRESS_(?:CLAMP(?:_TO_EDGE)?|NONE|REPEAT)|FILTER_(?:LINEAR|NEAREST)|(?:GLOBAL|LOCAL)_MEM_FENCE|NORMALIZED_COORDS_(?:FALSE|TRUE))|CL_(?:BGRA|(?:HALF_)?FLOAT|INTENSITY|LUMINANCE|A?R?G?B?[Ax]?|(?:(?:UN)?SIGNED|[US]NORM)_(?:INT(?:8|16|32))|UNORM_(?:INT_101010|SHORT_(?:555|565)))|(?:DBL|FLT|HALF)_(?:DIG|EPSILON|(?:MAX|MIN)(?:(?:_10)?_EXP)?|MANT_DIG)|FLT_RADIX|HUGE_VALF?|(?:INT|LONG|SCHAR|SHRT)_(?:MAX|MIN)|INFINITY|MAXFLOAT|M_(?:[12]_PI|2_SQRTPI|E|LN(?:2|10)|LOG(?:2|10)E?|PI(?:_[24])?|SQRT(?:1_2|2))(?:_F|_H)?|NAN|(?:UCHAR|UINT|ULONG|USHRT)_MAX)\b/,alias:"constant"}}),r.languages.insertBefore("opencl","class-name",{"builtin-type":{pattern:/\b(?:_cl_(?:command_queue|context|device_id|event|kernel|mem|platform_id|program|sampler)|cl_(?:image_format|mem_fence_flags)|clk_event_t|event_t|image(?:1d_(?:array_|buffer_)?t|2d_(?:array_(?:depth_|msaa_depth_|msaa_)?|depth_|msaa_depth_|msaa_)?t|3d_t)|intptr_t|ndrange_t|ptrdiff_t|queue_t|reserve_id_t|sampler_t|size_t|uintptr_t)\b/,alias:"keyword"}});var a={"type-opencl-host":{pattern:/\b(?:cl_(?:GLenum|GLint|GLuin|addressing_mode|bitfield|bool|buffer_create_type|build_status|channel_(?:order|type)|(?:u?(?:char|int|long|short)|double|float)(?:2|3|4|8|16)?|command_(?:queue(?:_info|_properties)?|type)|context(?:_info|_properties)?|device_(?:exec_capabilities|fp_config|id|info|local_mem_type|mem_cache_type|type)|(?:event|sampler)(?:_info)?|filter_mode|half|image_info|kernel(?:_info|_work_group_info)?|map_flags|mem(?:_flags|_info|_object_type)?|platform_(?:id|info)|profiling_info|program(?:_build_info|_info)?))\b/,alias:"keyword"},"boolean-opencl-host":{pattern:/\bCL_(?:FALSE|TRUE)\b/,alias:"boolean"},"constant-opencl-host":{pattern:/\bCL_(?:A|ABGR|ADDRESS_(?:CLAMP(?:_TO_EDGE)?|MIRRORED_REPEAT|NONE|REPEAT)|ARGB|BGRA|BLOCKING|BUFFER_CREATE_TYPE_REGION|BUILD_(?:ERROR|IN_PROGRESS|NONE|PROGRAM_FAILURE|SUCCESS)|COMMAND_(?:ACQUIRE_GL_OBJECTS|BARRIER|COPY_(?:BUFFER(?:_RECT|_TO_IMAGE)?|IMAGE(?:_TO_BUFFER)?)|FILL_(?:BUFFER|IMAGE)|MAP(?:_BUFFER|_IMAGE)|MARKER|MIGRATE(?:_SVM)?_MEM_OBJECTS|NATIVE_KERNEL|NDRANGE_KERNEL|READ_(?:BUFFER(?:_RECT)?|IMAGE)|RELEASE_GL_OBJECTS|SVM_(?:FREE|MAP|MEMCPY|MEMFILL|UNMAP)|TASK|UNMAP_MEM_OBJECT|USER|WRITE_(?:BUFFER(?:_RECT)?|IMAGE))|COMPILER_NOT_AVAILABLE|COMPILE_PROGRAM_FAILURE|COMPLETE|CONTEXT_(?:DEVICES|INTEROP_USER_SYNC|NUM_DEVICES|PLATFORM|PROPERTIES|REFERENCE_COUNT)|DEPTH(?:_STENCIL)?|DEVICE_(?:ADDRESS_BITS|AFFINITY_DOMAIN_(?:L[1-4]_CACHE|NEXT_PARTITIONABLE|NUMA)|AVAILABLE|BUILT_IN_KERNELS|COMPILER_AVAILABLE|DOUBLE_FP_CONFIG|ENDIAN_LITTLE|ERROR_CORRECTION_SUPPORT|EXECUTION_CAPABILITIES|EXTENSIONS|GLOBAL_(?:MEM_(?:CACHELINE_SIZE|CACHE_SIZE|CACHE_TYPE|SIZE)|VARIABLE_PREFERRED_TOTAL_SIZE)|HOST_UNIFIED_MEMORY|IL_VERSION|IMAGE(?:2D_MAX_(?:HEIGHT|WIDTH)|3D_MAX_(?:DEPTH|HEIGHT|WIDTH)|_BASE_ADDRESS_ALIGNMENT|_MAX_ARRAY_SIZE|_MAX_BUFFER_SIZE|_PITCH_ALIGNMENT|_SUPPORT)|LINKER_AVAILABLE|LOCAL_MEM_SIZE|LOCAL_MEM_TYPE|MAX_(?:CLOCK_FREQUENCY|COMPUTE_UNITS|CONSTANT_ARGS|CONSTANT_BUFFER_SIZE|GLOBAL_VARIABLE_SIZE|MEM_ALLOC_SIZE|NUM_SUB_GROUPS|ON_DEVICE_(?:EVENTS|QUEUES)|PARAMETER_SIZE|PIPE_ARGS|READ_IMAGE_ARGS|READ_WRITE_IMAGE_ARGS|SAMPLERS|WORK_GROUP_SIZE|WORK_ITEM_DIMENSIONS|WORK_ITEM_SIZES|WRITE_IMAGE_ARGS)|MEM_BASE_ADDR_ALIGN|MIN_DATA_TYPE_ALIGN_SIZE|NAME|NATIVE_VECTOR_WIDTH_(?:CHAR|DOUBLE|FLOAT|HALF|INT|LONG|SHORT)|NOT_(?:AVAILABLE|FOUND)|OPENCL_C_VERSION|PARENT_DEVICE|PARTITION_(?:AFFINITY_DOMAIN|BY_AFFINITY_DOMAIN|BY_COUNTS|BY_COUNTS_LIST_END|EQUALLY|FAILED|MAX_SUB_DEVICES|PROPERTIES|TYPE)|PIPE_MAX_(?:ACTIVE_RESERVATIONS|PACKET_SIZE)|PLATFORM|PREFERRED_(?:GLOBAL_ATOMIC_ALIGNMENT|INTEROP_USER_SYNC|LOCAL_ATOMIC_ALIGNMENT|PLATFORM_ATOMIC_ALIGNMENT|VECTOR_WIDTH_(?:CHAR|DOUBLE|FLOAT|HALF|INT|LONG|SHORT))|PRINTF_BUFFER_SIZE|PROFILE|PROFILING_TIMER_RESOLUTION|QUEUE_(?:ON_(?:DEVICE_(?:MAX_SIZE|PREFERRED_SIZE|PROPERTIES)|HOST_PROPERTIES)|PROPERTIES)|REFERENCE_COUNT|SINGLE_FP_CONFIG|SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS|SVM_(?:ATOMICS|CAPABILITIES|COARSE_GRAIN_BUFFER|FINE_GRAIN_BUFFER|FINE_GRAIN_SYSTEM)|TYPE(?:_ACCELERATOR|_ALL|_CPU|_CUSTOM|_DEFAULT|_GPU)?|VENDOR(?:_ID)?|VERSION)|DRIVER_VERSION|EVENT_(?:COMMAND_(?:EXECUTION_STATUS|QUEUE|TYPE)|CONTEXT|REFERENCE_COUNT)|EXEC_(?:KERNEL|NATIVE_KERNEL|STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST)|FILTER_(?:LINEAR|NEAREST)|FLOAT|FP_(?:CORRECTLY_ROUNDED_DIVIDE_SQRT|DENORM|FMA|INF_NAN|ROUND_TO_INF|ROUND_TO_NEAREST|ROUND_TO_ZERO|SOFT_FLOAT)|GLOBAL|HALF_FLOAT|IMAGE_(?:ARRAY_SIZE|BUFFER|DEPTH|ELEMENT_SIZE|FORMAT|FORMAT_MISMATCH|FORMAT_NOT_SUPPORTED|HEIGHT|NUM_MIP_LEVELS|NUM_SAMPLES|ROW_PITCH|SLICE_PITCH|WIDTH)|INTENSITY|INVALID_(?:ARG_INDEX|ARG_SIZE|ARG_VALUE|BINARY|BUFFER_SIZE|BUILD_OPTIONS|COMMAND_QUEUE|COMPILER_OPTIONS|CONTEXT|DEVICE|DEVICE_PARTITION_COUNT|DEVICE_QUEUE|DEVICE_TYPE|EVENT|EVENT_WAIT_LIST|GLOBAL_OFFSET|GLOBAL_WORK_SIZE|GL_OBJECT|HOST_PTR|IMAGE_DESCRIPTOR|IMAGE_FORMAT_DESCRIPTOR|IMAGE_SIZE|KERNEL|KERNEL_ARGS|KERNEL_DEFINITION|KERNEL_NAME|LINKER_OPTIONS|MEM_OBJECT|MIP_LEVEL|OPERATION|PIPE_SIZE|PLATFORM|PROGRAM|PROGRAM_EXECUTABLE|PROPERTY|QUEUE_PROPERTIES|SAMPLER|VALUE|WORK_DIMENSION|WORK_GROUP_SIZE|WORK_ITEM_SIZE)|KERNEL_(?:ARG_(?:ACCESS_(?:NONE|QUALIFIER|READ_ONLY|READ_WRITE|WRITE_ONLY)|ADDRESS_(?:CONSTANT|GLOBAL|LOCAL|PRIVATE|QUALIFIER)|INFO_NOT_AVAILABLE|NAME|TYPE_(?:CONST|NAME|NONE|PIPE|QUALIFIER|RESTRICT|VOLATILE))|ATTRIBUTES|COMPILE_NUM_SUB_GROUPS|COMPILE_WORK_GROUP_SIZE|CONTEXT|EXEC_INFO_SVM_FINE_GRAIN_SYSTEM|EXEC_INFO_SVM_PTRS|FUNCTION_NAME|GLOBAL_WORK_SIZE|LOCAL_MEM_SIZE|LOCAL_SIZE_FOR_SUB_GROUP_COUNT|MAX_NUM_SUB_GROUPS|MAX_SUB_GROUP_SIZE_FOR_NDRANGE|NUM_ARGS|PREFERRED_WORK_GROUP_SIZE_MULTIPLE|PRIVATE_MEM_SIZE|PROGRAM|REFERENCE_COUNT|SUB_GROUP_COUNT_FOR_NDRANGE|WORK_GROUP_SIZE)|LINKER_NOT_AVAILABLE|LINK_PROGRAM_FAILURE|LOCAL|LUMINANCE|MAP_(?:FAILURE|READ|WRITE|WRITE_INVALIDATE_REGION)|MEM_(?:ALLOC_HOST_PTR|ASSOCIATED_MEMOBJECT|CONTEXT|COPY_HOST_PTR|COPY_OVERLAP|FLAGS|HOST_NO_ACCESS|HOST_PTR|HOST_READ_ONLY|HOST_WRITE_ONLY|KERNEL_READ_AND_WRITE|MAP_COUNT|OBJECT_(?:ALLOCATION_FAILURE|BUFFER|IMAGE1D|IMAGE1D_ARRAY|IMAGE1D_BUFFER|IMAGE2D|IMAGE2D_ARRAY|IMAGE3D|PIPE)|OFFSET|READ_ONLY|READ_WRITE|REFERENCE_COUNT|SIZE|SVM_ATOMICS|SVM_FINE_GRAIN_BUFFER|TYPE|USES_SVM_POINTER|USE_HOST_PTR|WRITE_ONLY)|MIGRATE_MEM_OBJECT_(?:CONTENT_UNDEFINED|HOST)|MISALIGNED_SUB_BUFFER_OFFSET|NONE|NON_BLOCKING|OUT_OF_(?:HOST_MEMORY|RESOURCES)|PIPE_(?:MAX_PACKETS|PACKET_SIZE)|PLATFORM_(?:EXTENSIONS|HOST_TIMER_RESOLUTION|NAME|PROFILE|VENDOR|VERSION)|PROFILING_(?:COMMAND_(?:COMPLETE|END|QUEUED|START|SUBMIT)|INFO_NOT_AVAILABLE)|PROGRAM_(?:BINARIES|BINARY_SIZES|BINARY_TYPE(?:_COMPILED_OBJECT|_EXECUTABLE|_LIBRARY|_NONE)?|BUILD_(?:GLOBAL_VARIABLE_TOTAL_SIZE|LOG|OPTIONS|STATUS)|CONTEXT|DEVICES|IL|KERNEL_NAMES|NUM_DEVICES|NUM_KERNELS|REFERENCE_COUNT|SOURCE)|QUEUED|QUEUE_(?:CONTEXT|DEVICE|DEVICE_DEFAULT|ON_DEVICE|ON_DEVICE_DEFAULT|OUT_OF_ORDER_EXEC_MODE_ENABLE|PROFILING_ENABLE|PROPERTIES|REFERENCE_COUNT|SIZE)|R|RA|READ_(?:ONLY|WRITE)_CACHE|RG|RGB|RGBA|RGBx|RGx|RUNNING|Rx|SAMPLER_(?:ADDRESSING_MODE|CONTEXT|FILTER_MODE|LOD_MAX|LOD_MIN|MIP_FILTER_MODE|NORMALIZED_COORDS|REFERENCE_COUNT)|(?:UN)?SIGNED_INT(?:8|16|32)|SNORM_INT(?:8|16)|SUBMITTED|SUCCESS|UNORM_INT(?:8|16|24|_101010|_101010_2)|UNORM_SHORT_(?:555|565)|VERSION_(?:1_0|1_1|1_2|2_0|2_1)|sBGRA|sRGB|sRGBA|sRGBx)\b/,alias:"constant"},"function-opencl-host":{pattern:/\bcl(?:BuildProgram|CloneKernel|CompileProgram|Create(?:Buffer|CommandQueue(?:WithProperties)?|Context|ContextFromType|Image|Image2D|Image3D|Kernel|KernelsInProgram|Pipe|ProgramWith(?:Binary|BuiltInKernels|IL|Source)|Sampler|SamplerWithProperties|SubBuffer|SubDevices|UserEvent)|Enqueue(?:(?:Barrier|Marker)(?:WithWaitList)?|Copy(?:Buffer(?:Rect|ToImage)?|Image(?:ToBuffer)?)|(?:Fill|Map)(?:Buffer|Image)|MigrateMemObjects|NDRangeKernel|NativeKernel|(?:Read|Write)(?:Buffer(?:Rect)?|Image)|SVM(?:Free|Map|MemFill|Memcpy|MigrateMem|Unmap)|Task|UnmapMemObject|WaitForEvents)|Finish|Flush|Get(?:CommandQueueInfo|ContextInfo|Device(?:AndHostTimer|IDs|Info)|Event(?:Profiling)?Info|ExtensionFunctionAddress(?:ForPlatform)?|HostTimer|ImageInfo|Kernel(?:ArgInfo|Info|SubGroupInfo|WorkGroupInfo)|MemObjectInfo|PipeInfo|Platform(?:IDs|Info)|Program(?:Build)?Info|SamplerInfo|SupportedImageFormats)|LinkProgram|(?:Release|Retain)(?:CommandQueue|Context|Device|Event|Kernel|MemObject|Program|Sampler)|SVM(?:Alloc|Free)|Set(?:CommandQueueProperty|DefaultDeviceCommandQueue|EventCallback|Kernel|Kernel(?:Arg(?:SVMPointer)?|ExecInfo)|MemObjectDestructorCallback|UserEventStatus)|Unload(?:Platform)?Compiler|WaitForEvents)\b/,alias:"function"}};r.languages.insertBefore("c","keyword",a),r.languages.cpp&&(a["type-opencl-host-cpp"]={pattern:/\b(?:Buffer|BufferGL|BufferRenderGL|CommandQueue|Context|Device|DeviceCommandQueue|EnqueueArgs|Event|Image|Image1D|Image1DArray|Image1DBuffer|Image2D|Image2DArray|Image2DGL|Image3D|Image3DGL|ImageFormat|ImageGL|Kernel|KernelFunctor|LocalSpaceArg|Memory|NDRange|Pipe|Platform|Program|SVMAllocator|SVMTraitAtomic|SVMTraitCoarse|SVMTraitFine|SVMTraitReadOnly|SVMTraitReadWrite|SVMTraitWriteOnly|Sampler|UserEvent)\b/,alias:"keyword"},r.languages.insertBefore("cpp","keyword",a))}(n)}return nd}var rd,qv;function Oq(){if(qv)return rd;qv=1,rd=e,e.displayName="openqasm",e.aliases=["qasm"];function e(t){t.languages.openqasm={comment:/\/\*[\s\S]*?\*\/|\/\/.*/,string:{pattern:/"[^"\r\n\t]*"|'[^'\r\n\t]*'/,greedy:!0},keyword:/\b(?:CX|OPENQASM|U|barrier|boxas|boxto|break|const|continue|ctrl|def|defcal|defcalgrammar|delay|else|end|for|gate|gphase|if|in|include|inv|kernel|lengthof|let|measure|pow|reset|return|rotary|stretchinf|while)\b|#pragma\b/,"class-name":/\b(?:angle|bit|bool|creg|fixed|float|int|length|qreg|qubit|stretch|uint)\b/,function:/\b(?:cos|exp|ln|popcount|rotl|rotr|sin|sqrt|tan)\b(?=\s*\()/,constant:/\b(?:euler|pi|tau)\b|π|𝜏|ℇ/,number:{pattern:/(^|[^.\w$])(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?(?:dt|ns|us|µs|ms|s)?/i,lookbehind:!0},operator:/->|>>=?|<<=?|&&|\|\||\+\+|--|[!=<>&|~^+\-*/%]=?|@/,punctuation:/[(){}\[\];,:.]/},t.languages.qasm=t.languages.openqasm}return rd}var ad,jv;function Lq(){if(jv)return ad;jv=1,ad=e,e.displayName="oz",e.aliases=[];function e(t){t.languages.oz={comment:{pattern:/\/\*[\s\S]*?\*\/|%.*/,greedy:!0},string:{pattern:/"(?:[^"\\]|\\[\s\S])*"/,greedy:!0},atom:{pattern:/'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,alias:"builtin"},keyword:/\$|\[\]|\b(?:_|at|attr|case|catch|choice|class|cond|declare|define|dis|else(?:case|if)?|end|export|fail|false|feat|finally|from|fun|functor|if|import|in|local|lock|meth|nil|not|of|or|prepare|proc|prop|raise|require|self|skip|then|thread|true|try|unit)\b/,function:[/\b[a-z][A-Za-z\d]*(?=\()/,{pattern:/(\{)[A-Z][A-Za-z\d]*\b/,lookbehind:!0}],number:/\b(?:0[bx][\da-f]+|\d+(?:\.\d*)?(?:e~?\d+)?)\b|&(?:[^\\]|\\(?:\d{3}|.))/i,variable:/`(?:[^`\\]|\\.)+`/,"attr-name":/\b\w+(?=[ \t]*:(?![:=]))/,operator:/:(?:=|::?)|<[-:=]?|=(?:=|=?:?|\\=:?|!!?|[|#+\-*\/,~^@]|\b(?:andthen|div|mod|orelse)\b/,punctuation:/[\[\](){}.:;?]/}}return ad}var id,Hv;function Dq(){if(Hv)return id;Hv=1,id=e,e.displayName="parigp",e.aliases=[];function e(t){t.languages.parigp={comment:/\/\*[\s\S]*?\*\/|\\\\.*/,string:{pattern:/"(?:[^"\\\r\n]|\\.)*"/,greedy:!0},keyword:function(){var n=["breakpoint","break","dbg_down","dbg_err","dbg_up","dbg_x","forcomposite","fordiv","forell","forpart","forprime","forstep","forsubgroup","forvec","for","iferr","if","local","my","next","return","until","while"];return n=n.map(function(r){return r.split("").join(" *")}).join("|"),RegExp("\\b(?:"+n+")\\b")}(),function:/\b\w(?:[\w ]*\w)?(?= *\()/,number:{pattern:/((?:\. *\. *)?)(?:\b\d(?: *\d)*(?: *(?!\. *\.)\.(?: *\d)*)?|\. *\d(?: *\d)*)(?: *e *(?:[+-] *)?\d(?: *\d)*)?/i,lookbehind:!0},operator:/\. *\.|[*\/!](?: *=)?|%(?: *=|(?: *#)?(?: *')*)?|\+(?: *[+=])?|-(?: *[-=>])?|<(?: *>|(?: *<)?(?: *=)?)?|>(?: *>)?(?: *=)?|=(?: *=){0,2}|\\(?: *\/)?(?: *=)?|&(?: *&)?|\| *\||['#~^]/,punctuation:/[\[\]{}().,:;|]/}}return id}var od,Vv;function Mq(){if(Vv)return od;Vv=1,od=e,e.displayName="parser",e.aliases=[];function e(t){(function(n){var r=n.languages.parser=n.languages.extend("markup",{keyword:{pattern:/(^|[^^])(?:\^(?:case|eval|for|if|switch|throw)\b|@(?:BASE|CLASS|GET(?:_DEFAULT)?|OPTIONS|SET_DEFAULT|USE)\b)/,lookbehind:!0},variable:{pattern:/(^|[^^])\B\$(?:\w+|(?=[.{]))(?:(?:\.|::?)\w+)*(?:\.|::?)?/,lookbehind:!0,inside:{punctuation:/\.|:+/}},function:{pattern:/(^|[^^])\B[@^]\w+(?:(?:\.|::?)\w+)*(?:\.|::?)?/,lookbehind:!0,inside:{keyword:{pattern:/(^@)(?:GET_|SET_)/,lookbehind:!0},punctuation:/\.|:+/}},escape:{pattern:/\^(?:[$^;@()\[\]{}"':]|#[a-f\d]*)/i,alias:"builtin"},punctuation:/[\[\](){};]/});r=n.languages.insertBefore("parser","keyword",{"parser-comment":{pattern:/(\s)#.*/,lookbehind:!0,alias:"comment"},expression:{pattern:/(^|[^^])\((?:[^()]|\((?:[^()]|\((?:[^()])*\))*\))*\)/,greedy:!0,lookbehind:!0,inside:{string:{pattern:/(^|[^^])(["'])(?:(?!\2)[^^]|\^[\s\S])*\2/,lookbehind:!0},keyword:r.keyword,variable:r.variable,function:r.function,boolean:/\b(?:false|true)\b/,number:/\b(?:0x[a-f\d]+|\d+(?:\.\d*)?(?:e[+-]?\d+)?)\b/i,escape:r.escape,operator:/[~+*\/\\%]|!(?:\|\|?|=)?|&&?|\|\|?|==|<[<=]?|>[>=]?|-[fd]?|\b(?:def|eq|ge|gt|in|is|le|lt|ne)\b/,punctuation:r.punctuation}}}),n.languages.insertBefore("inside","punctuation",{expression:r.expression,keyword:r.keyword,variable:r.variable,function:r.function,escape:r.escape,"parser-punctuation":{pattern:r.punctuation,alias:"punctuation"}},r.tag.inside["attr-value"])})(t)}return od}var sd,Wv;function Fq(){if(Wv)return sd;Wv=1,sd=e,e.displayName="pascal",e.aliases=["objectpascal"];function e(t){t.languages.pascal={directive:{pattern:/\{\$[\s\S]*?\}/,greedy:!0,alias:["marco","property"]},comment:{pattern:/\(\*[\s\S]*?\*\)|\{[\s\S]*?\}|\/\/.*/,greedy:!0},string:{pattern:/(?:'(?:''|[^'\r\n])*'(?!')|#[&$%]?[a-f\d]+)+|\^[a-z]/i,greedy:!0},asm:{pattern:/(\basm\b)[\s\S]+?(?=\bend\s*[;[])/i,lookbehind:!0,greedy:!0,inside:null},keyword:[{pattern:/(^|[^&])\b(?:absolute|array|asm|begin|case|const|constructor|destructor|do|downto|else|end|file|for|function|goto|if|implementation|inherited|inline|interface|label|nil|object|of|operator|packed|procedure|program|record|reintroduce|repeat|self|set|string|then|to|type|unit|until|uses|var|while|with)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:dispose|exit|false|new|true)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:class|dispinterface|except|exports|finalization|finally|initialization|inline|library|on|out|packed|property|raise|resourcestring|threadvar|try)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:absolute|abstract|alias|assembler|bitpacked|break|cdecl|continue|cppdecl|cvar|default|deprecated|dynamic|enumerator|experimental|export|external|far|far16|forward|generic|helper|implements|index|interrupt|iochecks|local|message|name|near|nodefault|noreturn|nostackframe|oldfpccall|otherwise|overload|override|pascal|platform|private|protected|public|published|read|register|reintroduce|result|safecall|saveregisters|softfloat|specialize|static|stdcall|stored|strict|unaligned|unimplemented|varargs|virtual|write)\b/i,lookbehind:!0}],number:[/(?:[&%]\d+|\$[a-f\d]+)/i,/\b\d+(?:\.\d+)?(?:e[+-]?\d+)?/i],operator:[/\.\.|\*\*|:=|<[<=>]?|>[>=]?|[+\-*\/]=?|[@^=]/,{pattern:/(^|[^&])\b(?:and|as|div|exclude|in|include|is|mod|not|or|shl|shr|xor)\b/,lookbehind:!0}],punctuation:/\(\.|\.\)|[()\[\]:;,.]/},t.languages.pascal.asm.inside=t.languages.extend("pascal",{asm:void 0,keyword:void 0,operator:void 0}),t.languages.objectpascal=t.languages.pascal}return sd}var ld,Yv;function Pq(){if(Yv)return ld;Yv=1,ld=e,e.displayName="pascaligo",e.aliases=[];function e(t){(function(n){var r=/\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\)/.source,a=/(?:\b\w+(?:)?|)/.source.replace(//g,function(){return r}),i=n.languages.pascaligo={comment:/\(\*[\s\S]+?\*\)|\/\/.*/,string:{pattern:/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1|\^[a-z]/i,greedy:!0},"class-name":[{pattern:RegExp(/(\btype\s+\w+\s+is\s+)/.source.replace(//g,function(){return a}),"i"),lookbehind:!0,inside:null},{pattern:RegExp(/(?=\s+is\b)/.source.replace(//g,function(){return a}),"i"),inside:null},{pattern:RegExp(/(:\s*)/.source.replace(//g,function(){return a})),lookbehind:!0,inside:null}],keyword:{pattern:/(^|[^&])\b(?:begin|block|case|const|else|end|fail|for|from|function|if|is|nil|of|remove|return|skip|then|type|var|while|with)\b/i,lookbehind:!0},boolean:{pattern:/(^|[^&])\b(?:False|True)\b/i,lookbehind:!0},builtin:{pattern:/(^|[^&])\b(?:bool|int|list|map|nat|record|string|unit)\b/i,lookbehind:!0},function:/\b\w+(?=\s*\()/,number:[/%[01]+|&[0-7]+|\$[a-f\d]+/i,/\b\d+(?:\.\d+)?(?:e[+-]?\d+)?(?:mtz|n)?/i],operator:/->|=\/=|\.\.|\*\*|:=|<[<=>]?|>[>=]?|[+\-*\/]=?|[@^=|]|\b(?:and|mod|or)\b/,punctuation:/\(\.|\.\)|[()\[\]:;,.{}]/},o=["comment","keyword","builtin","operator","punctuation"].reduce(function(s,l){return s[l]=i[l],s},{});i["class-name"].forEach(function(s){s.inside=o})})(t)}return ld}var ud,Kv;function Uq(){if(Kv)return ud;Kv=1,ud=e,e.displayName="pcaxis",e.aliases=["px"];function e(t){t.languages.pcaxis={string:/"[^"]*"/,keyword:{pattern:/((?:^|;)\s*)[-A-Z\d]+(?:\s*\[[-\w]+\])?(?:\s*\("[^"]*"(?:,\s*"[^"]*")*\))?(?=\s*=)/,lookbehind:!0,greedy:!0,inside:{keyword:/^[-A-Z\d]+/,language:{pattern:/^(\s*)\[[-\w]+\]/,lookbehind:!0,inside:{punctuation:/^\[|\]$/,property:/[-\w]+/}},"sub-key":{pattern:/^(\s*)\S[\s\S]*/,lookbehind:!0,inside:{parameter:{pattern:/"[^"]*"/,alias:"property"},punctuation:/^\(|\)$|,/}}}},operator:/=/,tlist:{pattern:/TLIST\s*\(\s*\w+(?:(?:\s*,\s*"[^"]*")+|\s*,\s*"[^"]*"-"[^"]*")?\s*\)/,greedy:!0,inside:{function:/^TLIST/,property:{pattern:/^(\s*\(\s*)\w+/,lookbehind:!0},string:/"[^"]*"/,punctuation:/[(),]/,operator:/-/}},punctuation:/[;,]/,number:{pattern:/(^|\s)\d+(?:\.\d+)?(?!\S)/,lookbehind:!0},boolean:/NO|YES/},t.languages.px=t.languages.pcaxis}return ud}var cd,Xv;function Bq(){if(Xv)return cd;Xv=1,cd=e,e.displayName="peoplecode",e.aliases=["pcode"];function e(t){t.languages.peoplecode={comment:RegExp([/\/\*[\s\S]*?\*\//.source,/\bREM[^;]*;/.source,/<\*(?:[^<*]|\*(?!>)|<(?!\*)|<\*(?:(?!\*>)[\s\S])*\*>)*\*>/.source,/\/\+[\s\S]*?\+\//.source].join("|")),string:{pattern:/'(?:''|[^'\r\n])*'(?!')|"(?:""|[^"\r\n])*"(?!")/,greedy:!0},variable:/%\w+/,"function-definition":{pattern:/((?:^|[^\w-])(?:function|method)\s+)\w+/i,lookbehind:!0,alias:"function"},"class-name":{pattern:/((?:^|[^-\w])(?:as|catch|class|component|create|extends|global|implements|instance|local|of|property|returns)\s+)\w+(?::\w+)*/i,lookbehind:!0,inside:{punctuation:/:/}},keyword:/\b(?:abstract|alias|as|catch|class|component|constant|create|declare|else|end-(?:class|evaluate|for|function|get|if|method|set|try|while)|evaluate|extends|for|function|get|global|if|implements|import|instance|library|local|method|null|of|out|peopleCode|private|program|property|protected|readonly|ref|repeat|returns?|set|step|then|throw|to|try|until|value|when(?:-other)?|while)\b/i,"operator-keyword":{pattern:/\b(?:and|not|or)\b/i,alias:"operator"},function:/[_a-z]\w*(?=\s*\()/i,boolean:/\b(?:false|true)\b/i,number:/\b\d+(?:\.\d+)?\b/,operator:/<>|[<>]=?|!=|\*\*|[-+*/|=@]/,punctuation:/[:.;,()[\]]/},t.languages.pcode=t.languages.peoplecode}return cd}var dd,Zv;function $q(){if(Zv)return dd;Zv=1,dd=e,e.displayName="perl",e.aliases=[];function e(t){(function(n){var r=/(?:\((?:[^()\\]|\\[\s\S])*\)|\{(?:[^{}\\]|\\[\s\S])*\}|\[(?:[^[\]\\]|\\[\s\S])*\]|<(?:[^<>\\]|\\[\s\S])*>)/.source;n.languages.perl={comment:[{pattern:/(^\s*)=\w[\s\S]*?=cut.*/m,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0,greedy:!0}],string:[{pattern:RegExp(/\b(?:q|qq|qw|qx)(?![a-zA-Z0-9])\s*/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2/.source,r].join("|")+")"),greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:RegExp(/\b(?:m|qr)(?![a-zA-Z0-9])\s*/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2/.source,r].join("|")+")"+/[msixpodualngc]*/.source),greedy:!0},{pattern:RegExp(/(^|[^-])\b(?:s|tr|y)(?![a-zA-Z0-9])\s*/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2/.source,/([a-zA-Z0-9])(?:(?!\3)[^\\]|\\[\s\S])*\3(?:(?!\3)[^\\]|\\[\s\S])*\3/.source,r+/\s*/.source+r].join("|")+")"+/[msixpodualngcer]*/.source),lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|x|xor)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+(?![\w$]))+(?:::)*/,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*?>|\b_\b/,alias:"symbol"},"v-string":{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},function:{pattern:/(\bsub[ \t]+)\w+/,lookbehind:!0},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|return|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)\b/,punctuation:/[{}[\];(),:]/}})(t)}return dd}var pd,Qv;function zq(){if(Qv)return pd;Qv=1;var e=Jo();pd=t,t.displayName="phpExtras",t.aliases=[];function t(n){n.register(e),n.languages.insertBefore("php","variable",{this:{pattern:/\$this\b/,alias:"keyword"},global:/\$(?:GLOBALS|HTTP_RAW_POST_DATA|_(?:COOKIE|ENV|FILES|GET|POST|REQUEST|SERVER|SESSION)|argc|argv|http_response_header|php_errormsg)\b/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/\b(?:parent|self|static)\b/,punctuation:/::|\\/}}})}return pd}var fd,Jv;function Gq(){if(Jv)return fd;Jv=1;var e=Jo(),t=Qo();fd=n,n.displayName="phpdoc",n.aliases=[];function n(r){r.register(e),r.register(t),function(a){var i=/(?:\b[a-zA-Z]\w*|[|\\[\]])+/.source;a.languages.phpdoc=a.languages.extend("javadoclike",{parameter:{pattern:RegExp("(@(?:global|param|property(?:-read|-write)?|var)\\s+(?:"+i+"\\s+)?)\\$\\w+"),lookbehind:!0}}),a.languages.insertBefore("phpdoc","keyword",{"class-name":[{pattern:RegExp("(@(?:global|package|param|property(?:-read|-write)?|return|subpackage|throws|var)\\s+)"+i),lookbehind:!0,inside:{keyword:/\b(?:array|bool|boolean|callback|double|false|float|int|integer|mixed|null|object|resource|self|string|true|void)\b/,punctuation:/[|\\[\]()]/}}]}),a.languages.javadoclike.addSupport("php",a.languages.phpdoc)}(r)}return fd}var gd,ek;function qq(){if(ek)return gd;ek=1;var e=Bm();gd=t,t.displayName="plsql",t.aliases=[];function t(n){n.register(e),n.languages.plsql=n.languages.extend("sql",{comment:{pattern:/\/\*[\s\S]*?\*\/|--.*/,greedy:!0},keyword:/\b(?:A|ACCESSIBLE|ADD|AGENT|AGGREGATE|ALL|ALTER|AND|ANY|ARRAY|AS|ASC|AT|ATTRIBUTE|AUTHID|AVG|BEGIN|BETWEEN|BFILE_BASE|BINARY|BLOB_BASE|BLOCK|BODY|BOTH|BOUND|BULK|BY|BYTE|C|CALL|CALLING|CASCADE|CASE|CHAR|CHARACTER|CHARSET|CHARSETFORM|CHARSETID|CHAR_BASE|CHECK|CLOB_BASE|CLONE|CLOSE|CLUSTER|CLUSTERS|COLAUTH|COLLECT|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPILED|COMPRESS|CONNECT|CONSTANT|CONSTRUCTOR|CONTEXT|CONTINUE|CONVERT|COUNT|CRASH|CREATE|CREDENTIAL|CURRENT|CURSOR|CUSTOMDATUM|DANGLING|DATA|DATE|DATE_BASE|DAY|DECLARE|DEFAULT|DEFINE|DELETE|DESC|DETERMINISTIC|DIRECTORY|DISTINCT|DOUBLE|DROP|DURATION|ELEMENT|ELSE|ELSIF|EMPTY|END|ESCAPE|EXCEPT|EXCEPTION|EXCEPTIONS|EXCLUSIVE|EXECUTE|EXISTS|EXIT|EXTERNAL|FETCH|FINAL|FIRST|FIXED|FLOAT|FOR|FORALL|FORCE|FROM|FUNCTION|GENERAL|GOTO|GRANT|GROUP|HASH|HAVING|HEAP|HIDDEN|HOUR|IDENTIFIED|IF|IMMEDIATE|IMMUTABLE|IN|INCLUDING|INDEX|INDEXES|INDICATOR|INDICES|INFINITE|INSERT|INSTANTIABLE|INT|INTERFACE|INTERSECT|INTERVAL|INTO|INVALIDATE|IS|ISOLATION|JAVA|LANGUAGE|LARGE|LEADING|LENGTH|LEVEL|LIBRARY|LIKE|LIKE2|LIKE4|LIKEC|LIMIT|LIMITED|LOCAL|LOCK|LONG|LOOP|MAP|MAX|MAXLEN|MEMBER|MERGE|MIN|MINUS|MINUTE|MOD|MODE|MODIFY|MONTH|MULTISET|MUTABLE|NAME|NAN|NATIONAL|NATIVE|NCHAR|NEW|NOCOMPRESS|NOCOPY|NOT|NOWAIT|NULL|NUMBER_BASE|OBJECT|OCICOLL|OCIDATE|OCIDATETIME|OCIDURATION|OCIINTERVAL|OCILOBLOCATOR|OCINUMBER|OCIRAW|OCIREF|OCIREFCURSOR|OCIROWID|OCISTRING|OCITYPE|OF|OLD|ON|ONLY|OPAQUE|OPEN|OPERATOR|OPTION|OR|ORACLE|ORADATA|ORDER|ORGANIZATION|ORLANY|ORLVARY|OTHERS|OUT|OVERLAPS|OVERRIDING|PACKAGE|PARALLEL_ENABLE|PARAMETER|PARAMETERS|PARENT|PARTITION|PASCAL|PERSISTABLE|PIPE|PIPELINED|PLUGGABLE|POLYMORPHIC|PRAGMA|PRECISION|PRIOR|PRIVATE|PROCEDURE|PUBLIC|RAISE|RANGE|RAW|READ|RECORD|REF|REFERENCE|RELIES_ON|REM|REMAINDER|RENAME|RESOURCE|RESULT|RESULT_CACHE|RETURN|RETURNING|REVERSE|REVOKE|ROLLBACK|ROW|SAMPLE|SAVE|SAVEPOINT|SB1|SB2|SB4|SECOND|SEGMENT|SELECT|SELF|SEPARATE|SEQUENCE|SERIALIZABLE|SET|SHARE|SHORT|SIZE|SIZE_T|SOME|SPARSE|SQL|SQLCODE|SQLDATA|SQLNAME|SQLSTATE|STANDARD|START|STATIC|STDDEV|STORED|STRING|STRUCT|STYLE|SUBMULTISET|SUBPARTITION|SUBSTITUTABLE|SUBTYPE|SUM|SYNONYM|TABAUTH|TABLE|TDO|THE|THEN|TIME|TIMESTAMP|TIMEZONE_ABBR|TIMEZONE_HOUR|TIMEZONE_MINUTE|TIMEZONE_REGION|TO|TRAILING|TRANSACTION|TRANSACTIONAL|TRUSTED|TYPE|UB1|UB2|UB4|UNDER|UNION|UNIQUE|UNPLUG|UNSIGNED|UNTRUSTED|UPDATE|USE|USING|VALIST|VALUE|VALUES|VARIABLE|VARIANCE|VARRAY|VARYING|VIEW|VIEWS|VOID|WHEN|WHERE|WHILE|WITH|WORK|WRAPPED|WRITE|YEAR|ZONE)\b/i,operator:/:=?|=>|[<>^~!]=|\.\.|\|\||\*\*|[-+*/%<>=@]/}),n.languages.insertBefore("plsql","operator",{label:{pattern:/<<\s*\w+\s*>>/,alias:"symbol"}})}return gd}var md,tk;function jq(){if(tk)return md;tk=1,md=e,e.displayName="powerquery",e.aliases=[];function e(t){t.languages.powerquery={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},"quoted-identifier":{pattern:/#"(?:[^"\r\n]|"")*"(?!")/,greedy:!0},string:{pattern:/(?:#!)?"(?:[^"\r\n]|"")*"(?!")/,greedy:!0},constant:[/\bDay\.(?:Friday|Monday|Saturday|Sunday|Thursday|Tuesday|Wednesday)\b/,/\bTraceLevel\.(?:Critical|Error|Information|Verbose|Warning)\b/,/\bOccurrence\.(?:All|First|Last)\b/,/\bOrder\.(?:Ascending|Descending)\b/,/\bRoundingMode\.(?:AwayFromZero|Down|ToEven|TowardZero|Up)\b/,/\bMissingField\.(?:Error|Ignore|UseNull)\b/,/\bQuoteStyle\.(?:Csv|None)\b/,/\bJoinKind\.(?:FullOuter|Inner|LeftAnti|LeftOuter|RightAnti|RightOuter)\b/,/\bGroupKind\.(?:Global|Local)\b/,/\bExtraValues\.(?:Error|Ignore|List)\b/,/\bJoinAlgorithm\.(?:Dynamic|LeftHash|LeftIndex|PairwiseHash|RightHash|RightIndex|SortMerge)\b/,/\bJoinSide\.(?:Left|Right)\b/,/\bPrecision\.(?:Decimal|Double)\b/,/\bRelativePosition\.From(?:End|Start)\b/,/\bTextEncoding\.(?:Ascii|BigEndianUnicode|Unicode|Utf16|Utf8|Windows)\b/,/\b(?:Any|Binary|Date|DateTime|DateTimeZone|Duration|Function|Int16|Int32|Int64|Int8|List|Logical|None|Number|Record|Table|Text|Time)\.Type\b/,/\bnull\b/],boolean:/\b(?:false|true)\b/,keyword:/\b(?:and|as|each|else|error|if|in|is|let|meta|not|nullable|optional|or|otherwise|section|shared|then|try|type)\b|#(?:binary|date|datetime|datetimezone|duration|infinity|nan|sections|shared|table|time)\b/,function:{pattern:/(^|[^#\w.])[a-z_][\w.]*(?=\s*\()/i,lookbehind:!0},"data-type":{pattern:/\b(?:any|anynonnull|binary|date|datetime|datetimezone|duration|function|list|logical|none|number|record|table|text|time)\b/,alias:"class-name"},number:{pattern:/\b0x[\da-f]+\b|(?:[+-]?(?:\b\d+\.)?\b\d+|[+-]\.\d+|(^|[^.])\B\.\d+)(?:e[+-]?\d+)?\b/i,lookbehind:!0},operator:/[-+*\/&?@^]|<(?:=>?|>)?|>=?|=>?|\.\.\.?/,punctuation:/[,;\[\](){}]/},t.languages.pq=t.languages.powerquery,t.languages.mscript=t.languages.powerquery}return md}var hd,nk;function Hq(){if(nk)return hd;nk=1,hd=e,e.displayName="powershell",e.aliases=[];function e(t){(function(n){var r=n.languages.powershell={comment:[{pattern:/(^|[^`])<#[\s\S]*?#>/,lookbehind:!0},{pattern:/(^|[^`])#.*/,lookbehind:!0}],string:[{pattern:/"(?:`[\s\S]|[^`"])*"/,greedy:!0,inside:null},{pattern:/'(?:[^']|'')*'/,greedy:!0}],namespace:/\[[a-z](?:\[(?:\[[^\]]*\]|[^\[\]])*\]|[^\[\]])*\]/i,boolean:/\$(?:false|true)\b/i,variable:/\$\w+\b/,function:[/\b(?:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|ForEach|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Sort|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Tee|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Where|Write)-[a-z]+\b/i,/\b(?:ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i],keyword:/\b(?:Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,operator:{pattern:/(^|\W)(?:!|-(?:b?(?:and|x?or)|as|(?:Not)?(?:Contains|In|Like|Match)|eq|ge|gt|is(?:Not)?|Join|le|lt|ne|not|Replace|sh[lr])\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,lookbehind:!0},punctuation:/[|{}[\];(),.]/};r.string[0].inside={function:{pattern:/(^|[^`])\$\((?:\$\([^\r\n()]*\)|(?!\$\()[^\r\n)])*\)/,lookbehind:!0,inside:r},boolean:r.boolean,variable:r.variable}})(t)}return hd}var bd,rk;function Vq(){if(rk)return bd;rk=1,bd=e,e.displayName="processing",e.aliases=[];function e(t){t.languages.processing=t.languages.extend("clike",{keyword:/\b(?:break|case|catch|class|continue|default|else|extends|final|for|if|implements|import|new|null|private|public|return|static|super|switch|this|try|void|while)\b/,function:/\b\w+(?=\s*\()/,operator:/<[<=]?|>[>=]?|&&?|\|\|?|[%?]|[!=+\-*\/]=?/}),t.languages.insertBefore("processing","number",{constant:/\b(?!XML\b)[A-Z][A-Z\d_]+\b/,type:{pattern:/\b(?:boolean|byte|char|color|double|float|int|[A-Z]\w*)\b/,alias:"class-name"}})}return bd}var yd,ak;function Wq(){if(ak)return yd;ak=1,yd=e,e.displayName="prolog",e.aliases=[];function e(t){t.languages.prolog={comment:{pattern:/\/\*[\s\S]*?\*\/|%.*/,greedy:!0},string:{pattern:/(["'])(?:\1\1|\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1(?!\1)/,greedy:!0},builtin:/\b(?:fx|fy|xf[xy]?|yfx?)\b/,function:/\b[a-z]\w*(?:(?=\()|\/\d+)/,number:/\b\d+(?:\.\d*)?/,operator:/[:\\=><\-?*@\/;+^|!$.]+|\b(?:is|mod|not|xor)\b/,punctuation:/[(){}\[\],]/}}return yd}var Ed,ik;function Yq(){if(ik)return Ed;ik=1,Ed=e,e.displayName="promql",e.aliases=[];function e(t){(function(n){var r=["sum","min","max","avg","group","stddev","stdvar","count","count_values","bottomk","topk","quantile"],a=["on","ignoring","group_right","group_left","by","without"],i=["offset"],o=r.concat(a,i);n.languages.promql={comment:{pattern:/(^[ \t]*)#.*/m,lookbehind:!0},"vector-match":{pattern:new RegExp("((?:"+a.join("|")+")\\s*)\\([^)]*\\)"),lookbehind:!0,inside:{"label-key":{pattern:/\b[^,]+\b/,alias:"attr-name"},punctuation:/[(),]/}},"context-labels":{pattern:/\{[^{}]*\}/,inside:{"label-key":{pattern:/\b[a-z_]\w*(?=\s*(?:=|![=~]))/,alias:"attr-name"},"label-value":{pattern:/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0,alias:"attr-value"},punctuation:/\{|\}|=~?|![=~]|,/}},"context-range":[{pattern:/\[[\w\s:]+\]/,inside:{punctuation:/\[|\]|:/,"range-duration":{pattern:/\b(?:\d+(?:[smhdwy]|ms))+\b/i,alias:"number"}}},{pattern:/(\boffset\s+)\w+/,lookbehind:!0,inside:{"range-duration":{pattern:/\b(?:\d+(?:[smhdwy]|ms))+\b/i,alias:"number"}}}],keyword:new RegExp("\\b(?:"+o.join("|")+")\\b","i"),function:/\b[a-z_]\w*(?=\s*\()/i,number:/[-+]?(?:(?:\b\d+(?:\.\d+)?|\B\.\d+)(?:e[-+]?\d+)?\b|\b(?:0x[0-9a-f]+|nan|inf)\b)/i,operator:/[\^*/%+-]|==|!=|<=|<|>=|>|\b(?:and|or|unless)\b/i,punctuation:/[{};()`,.[\]]/}})(t)}return Ed}var Sd,ok;function Kq(){if(ok)return Sd;ok=1,Sd=e,e.displayName="properties",e.aliases=[];function e(t){t.languages.properties={comment:/^[ \t]*[#!].*$/m,"attr-value":{pattern:/(^[ \t]*(?:\\(?:\r\n|[\s\S])|[^\\\s:=])+(?: *[=:] *(?! )| ))(?:\\(?:\r\n|[\s\S])|[^\\\r\n])+/m,lookbehind:!0},"attr-name":/^[ \t]*(?:\\(?:\r\n|[\s\S])|[^\\\s:=])+(?= *[=:]| )/m,punctuation:/[=:]/}}return Sd}var vd,sk;function Xq(){if(sk)return vd;sk=1,vd=e,e.displayName="protobuf",e.aliases=[];function e(t){(function(n){var r=/\b(?:bool|bytes|double|s?fixed(?:32|64)|float|[su]?int(?:32|64)|string)\b/;n.languages.protobuf=n.languages.extend("clike",{"class-name":[{pattern:/(\b(?:enum|extend|message|service)\s+)[A-Za-z_]\w*(?=\s*\{)/,lookbehind:!0},{pattern:/(\b(?:rpc\s+\w+|returns)\s*\(\s*(?:stream\s+)?)\.?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?=\s*\))/,lookbehind:!0}],keyword:/\b(?:enum|extend|extensions|import|message|oneof|option|optional|package|public|repeated|required|reserved|returns|rpc(?=\s+\w)|service|stream|syntax|to)\b(?!\s*=\s*\d)/,function:/\b[a-z_]\w*(?=\s*\()/i}),n.languages.insertBefore("protobuf","operator",{map:{pattern:/\bmap<\s*[\w.]+\s*,\s*[\w.]+\s*>(?=\s+[a-z_]\w*\s*[=;])/i,alias:"class-name",inside:{punctuation:/[<>.,]/,builtin:r}},builtin:r,"positional-class-name":{pattern:/(?:\b|\B\.)[a-z_]\w*(?:\.[a-z_]\w*)*(?=\s+[a-z_]\w*\s*[=;])/i,alias:"class-name",inside:{punctuation:/\./}},annotation:{pattern:/(\[\s*)[a-z_]\w*(?=\s*=)/i,lookbehind:!0}})})(t)}return vd}var kd,lk;function Zq(){if(lk)return kd;lk=1,kd=e,e.displayName="psl",e.aliases=[];function e(t){t.languages.psl={comment:{pattern:/#.*/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"])*"/,greedy:!0,inside:{symbol:/\\[ntrbA-Z"\\]/}},"heredoc-string":{pattern:/<<<([a-zA-Z_]\w*)[\r\n](?:.*[\r\n])*?\1\b/,alias:"string",greedy:!0},keyword:/\b(?:__multi|__single|case|default|do|else|elsif|exit|export|for|foreach|function|if|last|line|local|next|requires|return|switch|until|while|word)\b/,constant:/\b(?:ALARM|CHART_ADD_GRAPH|CHART_DELETE_GRAPH|CHART_DESTROY|CHART_LOAD|CHART_PRINT|EOF|OFFLINE|OK|PSL_PROF_LOG|R_CHECK_HORIZ|R_CHECK_VERT|R_CLICKER|R_COLUMN|R_FRAME|R_ICON|R_LABEL|R_LABEL_CENTER|R_LIST_MULTIPLE|R_LIST_MULTIPLE_ND|R_LIST_SINGLE|R_LIST_SINGLE_ND|R_MENU|R_POPUP|R_POPUP_SCROLLED|R_RADIO_HORIZ|R_RADIO_VERT|R_ROW|R_SCALE_HORIZ|R_SCALE_VERT|R_SEP_HORIZ|R_SEP_VERT|R_SPINNER|R_TEXT_FIELD|R_TEXT_FIELD_LABEL|R_TOGGLE|TRIM_LEADING|TRIM_LEADING_AND_TRAILING|TRIM_REDUNDANT|TRIM_TRAILING|VOID|WARN)\b/,boolean:/\b(?:FALSE|False|NO|No|TRUE|True|YES|Yes|false|no|true|yes)\b/,variable:/\b(?:PslDebug|errno|exit_status)\b/,builtin:{pattern:/\b(?:PslExecute|PslFunctionCall|PslFunctionExists|PslSetOptions|_snmp_debug|acos|add_diary|annotate|annotate_get|ascii_to_ebcdic|asctime|asin|atan|atexit|batch_set|blackout|cat|ceil|chan_exists|change_state|close|code_cvt|cond_signal|cond_wait|console_type|convert_base|convert_date|convert_locale_date|cos|cosh|create|date|dcget_text|destroy|destroy_lock|dget_text|difference|dump_hist|ebcdic_to_ascii|encrypt|event_archive|event_catalog_get|event_check|event_query|event_range_manage|event_range_query|event_report|event_schedule|event_trigger|event_trigger2|execute|exists|exp|fabs|file|floor|fmod|fopen|fseek|ftell|full_discovery|get|get_chan_info|get_ranges|get_text|get_vars|getenv|gethostinfo|getpid|getpname|grep|history|history_get_retention|in_transition|index|int|internal|intersection|is_var|isnumber|join|kill|length|lines|lock|lock_info|log|log10|loge|matchline|msg_check|msg_get_format|msg_get_severity|msg_printf|msg_sprintf|ntharg|nthargf|nthline|nthlinef|num_bytes|num_consoles|pconfig|popen|poplines|pow|print|printf|proc_exists|process|random|read|readln|refresh_parameters|remote_check|remote_close|remote_event_query|remote_event_trigger|remote_file_send|remote_open|remove|replace|rindex|sec_check_priv|sec_store_get|sec_store_set|set|set_alarm_ranges|set_locale|share|sin|sinh|sleep|snmp_agent_config|snmp_agent_start|snmp_agent_stop|snmp_close|snmp_config|snmp_get|snmp_get_next|snmp_h_get|snmp_h_get_next|snmp_h_set|snmp_open|snmp_set|snmp_trap_ignore|snmp_trap_listen|snmp_trap_raise_std_trap|snmp_trap_receive|snmp_trap_register_im|snmp_trap_send|snmp_walk|sopen|sort|splitline|sprintf|sqrt|srandom|str_repeat|strcasecmp|subset|substr|system|tail|tan|tanh|text_domain|time|tmpnam|tolower|toupper|trace_psl_process|trim|union|unique|unlock|unset|va_arg|va_start|write)\b/,alias:"builtin-function"},"foreach-variable":{pattern:/(\bforeach\s+(?:(?:\w+\b|"(?:\\.|[^\\"])*")\s+){0,2})[_a-zA-Z]\w*(?=\s*\()/,lookbehind:!0,greedy:!0},function:/\b[_a-z]\w*\b(?=\s*\()/i,number:/\b(?:0x[0-9a-f]+|\d+(?:\.\d+)?)\b/i,operator:/--|\+\+|&&=?|\|\|=?|<<=?|>>=?|[=!]~|[-+*/%&|^!=<>]=?|\.|[:?]/,punctuation:/[(){}\[\];,]/}}return kd}var wd,uk;function Qq(){if(uk)return wd;uk=1,wd=e,e.displayName="pug",e.aliases=[];function e(t){(function(n){n.languages.pug={comment:{pattern:/(^([\t ]*))\/\/.*(?:(?:\r?\n|\r)\2[\t ].+)*/m,lookbehind:!0},"multiline-script":{pattern:/(^([\t ]*)script\b.*\.[\t ]*)(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0,inside:n.languages.javascript},filter:{pattern:/(^([\t ]*)):.+(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"variable"},text:/\S[\s\S]*/}},"multiline-plain-text":{pattern:/(^([\t ]*)[\w\-#.]+\.[\t ]*)(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/m,lookbehind:!0},markup:{pattern:/(^[\t ]*)<.+/m,lookbehind:!0,inside:n.languages.markup},doctype:{pattern:/((?:^|\n)[\t ]*)doctype(?: .+)?/,lookbehind:!0},"flow-control":{pattern:/(^[\t ]*)(?:case|default|each|else|if|unless|when|while)\b(?: .+)?/m,lookbehind:!0,inside:{each:{pattern:/^each .+? in\b/,inside:{keyword:/\b(?:each|in)\b/,punctuation:/,/}},branch:{pattern:/^(?:case|default|else|if|unless|when|while)\b/,alias:"keyword"},rest:n.languages.javascript}},keyword:{pattern:/(^[\t ]*)(?:append|block|extends|include|prepend)\b.+/m,lookbehind:!0},mixin:[{pattern:/(^[\t ]*)mixin .+/m,lookbehind:!0,inside:{keyword:/^mixin/,function:/\w+(?=\s*\(|\s*$)/,punctuation:/[(),.]/}},{pattern:/(^[\t ]*)\+.+/m,lookbehind:!0,inside:{name:{pattern:/^\+\w+/,alias:"function"},rest:n.languages.javascript}}],script:{pattern:/(^[\t ]*script(?:(?:&[^(]+)?\([^)]+\))*[\t ]).+/m,lookbehind:!0,inside:n.languages.javascript},"plain-text":{pattern:/(^[\t ]*(?!-)[\w\-#.]*[\w\-](?:(?:&[^(]+)?\([^)]+\))*\/?[\t ]).+/m,lookbehind:!0},tag:{pattern:/(^[\t ]*)(?!-)[\w\-#.]*[\w\-](?:(?:&[^(]+)?\([^)]+\))*\/?:?/m,lookbehind:!0,inside:{attributes:[{pattern:/&[^(]+\([^)]+\)/,inside:n.languages.javascript},{pattern:/\([^)]+\)/,inside:{"attr-value":{pattern:/(=\s*(?!\s))(?:\{[^}]*\}|[^,)\r\n]+)/,lookbehind:!0,inside:n.languages.javascript},"attr-name":/[\w-]+(?=\s*!?=|\s*[,)])/,punctuation:/[!=(),]+/}}],punctuation:/:/,"attr-id":/#[\w\-]+/,"attr-class":/\.[\w\-]+/}},code:[{pattern:/(^[\t ]*(?:-|!?=)).+/m,lookbehind:!0,inside:n.languages.javascript}],punctuation:/[.\-!=|]+/};for(var r=/(^([\t ]*)):(?:(?:\r?\n|\r(?!\n))(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/.source,a=[{filter:"atpl",language:"twig"},{filter:"coffee",language:"coffeescript"},"ejs","handlebars","less","livescript","markdown",{filter:"sass",language:"scss"},"stylus"],i={},o=0,s=a.length;o",function(){return l.filter}),"m"),lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"variable"},text:{pattern:/\S[\s\S]*/,alias:[l.language,"language-"+l.language],inside:n.languages[l.language]}}})}n.languages.insertBefore("pug","filter",i)})(t)}return wd}var _d,ck;function Jq(){if(ck)return _d;ck=1,_d=e,e.displayName="puppet",e.aliases=[];function e(t){(function(n){n.languages.puppet={heredoc:[{pattern:/(@\("([^"\r\n\/):]+)"(?:\/[nrts$uL]*)?\).*(?:\r?\n|\r))(?:.*(?:\r?\n|\r(?!\n)))*?[ \t]*(?:\|[ \t]*)?(?:-[ \t]*)?\2/,lookbehind:!0,alias:"string",inside:{punctuation:/(?=\S).*\S(?= *$)/}},{pattern:/(@\(([^"\r\n\/):]+)(?:\/[nrts$uL]*)?\).*(?:\r?\n|\r))(?:.*(?:\r?\n|\r(?!\n)))*?[ \t]*(?:\|[ \t]*)?(?:-[ \t]*)?\2/,lookbehind:!0,greedy:!0,alias:"string",inside:{punctuation:/(?=\S).*\S(?= *$)/}},{pattern:/@\("?(?:[^"\r\n\/):]+)"?(?:\/[nrts$uL]*)?\)/,alias:"string",inside:{punctuation:{pattern:/(\().+?(?=\))/,lookbehind:!0}}}],"multiline-comment":{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0,greedy:!0,alias:"comment"},regex:{pattern:/((?:\bnode\s+|[~=\(\[\{,]\s*|[=+]>\s*|^\s*))\/(?:[^\/\\]|\\[\s\S])+\/(?:[imx]+\b|\B)/,lookbehind:!0,greedy:!0,inside:{"extended-regex":{pattern:/^\/(?:[^\/\\]|\\[\s\S])+\/[im]*x[im]*$/,inside:{comment:/#.*/}}}},comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},string:{pattern:/(["'])(?:\$\{(?:[^'"}]|(["'])(?:(?!\2)[^\\]|\\[\s\S])*\2)+\}|\$(?!\{)|(?!\1)[^\\$]|\\[\s\S])*\1/,greedy:!0,inside:{"double-quoted":{pattern:/^"[\s\S]*"$/,inside:{}}}},variable:{pattern:/\$(?:::)?\w+(?:::\w+)*/,inside:{punctuation:/::/}},"attr-name":/(?:\b\w+|\*)(?=\s*=>)/,function:[{pattern:/(\.)(?!\d)\w+/,lookbehind:!0},/\b(?:contain|debug|err|fail|include|info|notice|realize|require|tag|warning)\b|\b(?!\d)\w+(?=\()/],number:/\b(?:0x[a-f\d]+|\d+(?:\.\d+)?(?:e-?\d+)?)\b/i,boolean:/\b(?:false|true)\b/,keyword:/\b(?:application|attr|case|class|consumes|default|define|else|elsif|function|if|import|inherits|node|private|produces|type|undef|unless)\b/,datatype:{pattern:/\b(?:Any|Array|Boolean|Callable|Catalogentry|Class|Collection|Data|Default|Enum|Float|Hash|Integer|NotUndef|Numeric|Optional|Pattern|Regexp|Resource|Runtime|Scalar|String|Struct|Tuple|Type|Undef|Variant)\b/,alias:"symbol"},operator:/=[=~>]?|![=~]?|<(?:<\|?|[=~|-])?|>[>=]?|->?|~>|\|>?>?|[*\/%+?]|\b(?:and|in|or)\b/,punctuation:/[\[\]{}().,;]|:+/};var r=[{pattern:/(^|[^\\])\$\{(?:[^'"{}]|\{[^}]*\}|(["'])(?:(?!\2)[^\\]|\\[\s\S])*\2)+\}/,lookbehind:!0,inside:{"short-variable":{pattern:/(^\$\{)(?!\w+\()(?:::)?\w+(?:::\w+)*/,lookbehind:!0,alias:"variable",inside:{punctuation:/::/}},delimiter:{pattern:/^\$/,alias:"variable"},rest:n.languages.puppet}},{pattern:/(^|[^\\])\$(?:::)?\w+(?:::\w+)*/,lookbehind:!0,alias:"variable",inside:{punctuation:/::/}}];n.languages.puppet.heredoc[0].inside.interpolation=r,n.languages.puppet.string.inside["double-quoted"].inside.interpolation=r})(t)}return _d}var Td,dk;function ej(){if(dk)return Td;dk=1,Td=e,e.displayName="pure",e.aliases=[];function e(t){(function(n){n.languages.pure={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0},/#!.+/],"inline-lang":{pattern:/%<[\s\S]+?%>/,greedy:!0,inside:{lang:{pattern:/(^%< *)-\*-.+?-\*-/,lookbehind:!0,alias:"comment"},delimiter:{pattern:/^%<.*|%>$/,alias:"punctuation"}}},string:{pattern:/"(?:\\.|[^"\\\r\n])*"/,greedy:!0},number:{pattern:/((?:\.\.)?)(?:\b(?:inf|nan)\b|\b0x[\da-f]+|(?:\b(?:0b)?\d+(?:\.\d+)?|\B\.\d+)(?:e[+-]?\d+)?L?)/i,lookbehind:!0},keyword:/\b(?:NULL|ans|break|bt|case|catch|cd|clear|const|def|del|dump|else|end|exit|extern|false|force|help|if|infix[lr]?|interface|let|ls|mem|namespace|nonfix|of|otherwise|outfix|override|postfix|prefix|private|public|pwd|quit|run|save|show|stats|then|throw|trace|true|type|underride|using|when|with)\b/,function:/\b(?:abs|add_(?:addr|constdef|(?:fundef|interface|macdef|typedef)(?:_at)?|vardef)|all|any|applp?|arity|bigintp?|blob(?:_crc|_size|p)?|boolp?|byte_c?string(?:_pointer)?|byte_(?:matrix|pointer)|calloc|cat|catmap|ceil|char[ps]?|check_ptrtag|chr|clear_sentry|clearsym|closurep?|cmatrixp?|cols?|colcat(?:map)?|colmap|colrev|colvector(?:p|seq)?|complex(?:_float_(?:matrix|pointer)|_matrix(?:_view)?|_pointer|p)?|conj|cookedp?|cst|cstring(?:_(?:dup|list|vector))?|curry3?|cyclen?|del_(?:constdef|fundef|interface|macdef|typedef|vardef)|delete|diag(?:mat)?|dim|dmatrixp?|do|double(?:_matrix(?:_view)?|_pointer|p)?|dowith3?|drop|dropwhile|eval(?:cmd)?|exactp|filter|fix|fixity|flip|float(?:_matrix|_pointer)|floor|fold[lr]1?|frac|free|funp?|functionp?|gcd|get(?:_(?:byte|constdef|double|float|fundef|int(?:64)?|interface(?:_typedef)?|long|macdef|pointer|ptrtag|sentry|short|string|typedef|vardef))?|globsym|hash|head|id|im|imatrixp?|index|inexactp|infp|init|insert|int(?:_matrix(?:_view)?|_pointer|p)?|int64_(?:matrix|pointer)|integerp?|iteraten?|iterwhile|join|keys?|lambdap?|last(?:err(?:pos)?)?|lcd|list[2p]?|listmap|make_ptrtag|malloc|map|matcat|matrixp?|max|member|min|nanp|nargs|nmatrixp?|null|numberp?|ord|pack(?:ed)?|pointer(?:_cast|_tag|_type|p)?|pow|pred|ptrtag|put(?:_(?:byte|double|float|int(?:64)?|long|pointer|short|string))?|rationalp?|re|realp?|realloc|recordp?|redim|reduce(?:_with)?|refp?|repeatn?|reverse|rlistp?|round|rows?|rowcat(?:map)?|rowmap|rowrev|rowvector(?:p|seq)?|same|scan[lr]1?|sentry|sgn|short_(?:matrix|pointer)|slice|smatrixp?|sort|split|str|strcat|stream|stride|string(?:_(?:dup|list|vector)|p)?|subdiag(?:mat)?|submat|subseq2?|substr|succ|supdiag(?:mat)?|symbolp?|tail|take|takewhile|thunkp?|transpose|trunc|tuplep?|typep|ubyte|uint(?:64)?|ulong|uncurry3?|unref|unzip3?|update|ushort|vals?|varp?|vector(?:p|seq)?|void|zip3?|zipwith3?)\b/,special:{pattern:/\b__[a-z]+__\b/i,alias:"builtin"},operator:/(?:[!"#$%&'*+,\-.\/:<=>?@\\^`|~\u00a1-\u00bf\u00d7-\u00f7\u20d0-\u2bff]|\b_+\b)+|\b(?:and|div|mod|not|or)\b/,punctuation:/[(){}\[\];,|]/};var r=["c",{lang:"c++",alias:"cpp"},"fortran"],a=/%< *-\*- *\d* *-\*-[\s\S]+?%>/.source;r.forEach(function(i){var o=i;if(typeof i!="string"&&(o=i.alias,i=i.lang),n.languages[o]){var s={};s["inline-lang-"+o]={pattern:RegExp(a.replace("",i.replace(/([.+*?\/\\(){}\[\]])/g,"\\$1")),"i"),inside:n.util.clone(n.languages.pure["inline-lang"].inside)},s["inline-lang-"+o].inside.rest=n.util.clone(n.languages[o]),n.languages.insertBefore("pure","inline-lang",s)}}),n.languages.c&&(n.languages.pure["inline-lang"].inside.rest=n.util.clone(n.languages.c))})(t)}return Td}var Ad,pk;function tj(){if(pk)return Ad;pk=1,Ad=e,e.displayName="purebasic",e.aliases=[];function e(t){t.languages.purebasic=t.languages.extend("clike",{comment:/;.*/,keyword:/\b(?:align|and|as|break|calldebugger|case|compilercase|compilerdefault|compilerelse|compilerelseif|compilerendif|compilerendselect|compilererror|compilerif|compilerselect|continue|data|datasection|debug|debuglevel|declare|declarec|declarecdll|declaredll|declaremodule|default|define|dim|disableasm|disabledebugger|disableexplicit|else|elseif|enableasm|enabledebugger|enableexplicit|end|enddatasection|enddeclaremodule|endenumeration|endif|endimport|endinterface|endmacro|endmodule|endprocedure|endselect|endstructure|endstructureunion|endwith|enumeration|extends|fakereturn|for|foreach|forever|global|gosub|goto|if|import|importc|includebinary|includefile|includepath|interface|macro|module|newlist|newmap|next|not|or|procedure|procedurec|procedurecdll|proceduredll|procedurereturn|protected|prototype|prototypec|read|redim|repeat|restore|return|runtime|select|shared|static|step|structure|structureunion|swap|threaded|to|until|wend|while|with|xincludefile|xor)\b/i,function:/\b\w+(?:\.\w+)?\s*(?=\()/,number:/(?:\$[\da-f]+|\b-?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)\b/i,operator:/(?:@\*?|\?|\*)\w+|-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|?\||[~^%?*/@]/}),t.languages.insertBefore("purebasic","keyword",{tag:/#\w+\$?/,asm:{pattern:/(^[\t ]*)!.*/m,lookbehind:!0,alias:"tag",inside:{comment:/;.*/,string:{pattern:/(["'`])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"label-reference-anonymous":{pattern:/(!\s*j[a-z]+\s+)@[fb]/i,lookbehind:!0,alias:"fasm-label"},"label-reference-addressed":{pattern:/(!\s*j[a-z]+\s+)[A-Z._?$@][\w.?$@~#]*/i,lookbehind:!0,alias:"fasm-label"},keyword:[/\b(?:extern|global)\b[^;\r\n]*/i,/\b(?:CPU|DEFAULT|FLOAT)\b.*/],function:{pattern:/^([\t ]*!\s*)[\da-z]+(?=\s|$)/im,lookbehind:!0},"function-inline":{pattern:/(:\s*)[\da-z]+(?=\s)/i,lookbehind:!0,alias:"function"},label:{pattern:/^([\t ]*!\s*)[A-Za-z._?$@][\w.?$@~#]*(?=:)/m,lookbehind:!0,alias:"fasm-label"},register:/\b(?:st\d|[xyz]mm\d\d?|[cdt]r\d|r\d\d?[bwd]?|[er]?[abcd]x|[abcd][hl]|[er]?(?:bp|di|si|sp)|[cdefgs]s|mm\d+)\b/i,number:/(?:\b|-|(?=\$))(?:0[hx](?:[\da-f]*\.)?[\da-f]+(?:p[+-]?\d+)?|\d[\da-f]+[hx]|\$\d[\da-f]*|0[oq][0-7]+|[0-7]+[oq]|0[by][01]+|[01]+[by]|0[dt]\d+|(?:\d+(?:\.\d+)?|\.\d+)(?:\.?e[+-]?\d+)?[dt]?)\b/i,operator:/[\[\]*+\-/%<>=&|$!,.:]/}}}),delete t.languages.purebasic["class-name"],delete t.languages.purebasic.boolean,t.languages.pbfasm=t.languages.purebasic}return Ad}var Rd,fk;function nj(){if(fk)return Rd;fk=1;var e=zm();Rd=t,t.displayName="purescript",t.aliases=["purs"];function t(n){n.register(e),n.languages.purescript=n.languages.extend("haskell",{keyword:/\b(?:ado|case|class|data|derive|do|else|forall|if|in|infixl|infixr|instance|let|module|newtype|of|primitive|then|type|where)\b|∀/,"import-statement":{pattern:/(^[\t ]*)import\s+[A-Z][\w']*(?:\.[A-Z][\w']*)*(?:\s+as\s+[A-Z][\w']*(?:\.[A-Z][\w']*)*)?(?:\s+hiding\b)?/m,lookbehind:!0,inside:{keyword:/\b(?:as|hiding|import)\b/,punctuation:/\./}},builtin:/\b(?:absurd|add|ap|append|apply|between|bind|bottom|clamp|compare|comparing|compose|conj|const|degree|discard|disj|div|eq|flap|flip|gcd|identity|ifM|join|lcm|liftA1|liftM1|map|max|mempty|min|mod|mul|negate|not|notEq|one|otherwise|recip|show|sub|top|unit|unless|unlessM|void|when|whenM|zero)\b/,operator:[n.languages.haskell.operator[0],n.languages.haskell.operator[2],/[\xa2-\xa6\xa8\xa9\xac\xae-\xb1\xb4\xb8\xd7\xf7\u02c2-\u02c5\u02d2-\u02df\u02e5-\u02eb\u02ed\u02ef-\u02ff\u0375\u0384\u0385\u03f6\u0482\u058d-\u058f\u0606-\u0608\u060b\u060e\u060f\u06de\u06e9\u06fd\u06fe\u07f6\u07fe\u07ff\u09f2\u09f3\u09fa\u09fb\u0af1\u0b70\u0bf3-\u0bfa\u0c7f\u0d4f\u0d79\u0e3f\u0f01-\u0f03\u0f13\u0f15-\u0f17\u0f1a-\u0f1f\u0f34\u0f36\u0f38\u0fbe-\u0fc5\u0fc7-\u0fcc\u0fce\u0fcf\u0fd5-\u0fd8\u109e\u109f\u1390-\u1399\u166d\u17db\u1940\u19de-\u19ff\u1b61-\u1b6a\u1b74-\u1b7c\u1fbd\u1fbf-\u1fc1\u1fcd-\u1fcf\u1fdd-\u1fdf\u1fed-\u1fef\u1ffd\u1ffe\u2044\u2052\u207a-\u207c\u208a-\u208c\u20a0-\u20bf\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211e-\u2123\u2125\u2127\u2129\u212e\u213a\u213b\u2140-\u2144\u214a-\u214d\u214f\u218a\u218b\u2190-\u2307\u230c-\u2328\u232b-\u2426\u2440-\u244a\u249c-\u24e9\u2500-\u2767\u2794-\u27c4\u27c7-\u27e5\u27f0-\u2982\u2999-\u29d7\u29dc-\u29fb\u29fe-\u2b73\u2b76-\u2b95\u2b97-\u2bff\u2ce5-\u2cea\u2e50\u2e51\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u2ff0-\u2ffb\u3004\u3012\u3013\u3020\u3036\u3037\u303e\u303f\u309b\u309c\u3190\u3191\u3196-\u319f\u31c0-\u31e3\u3200-\u321e\u322a-\u3247\u3250\u3260-\u327f\u328a-\u32b0\u32c0-\u33ff\u4dc0-\u4dff\ua490-\ua4c6\ua700-\ua716\ua720\ua721\ua789\ua78a\ua828-\ua82b\ua836-\ua839\uaa77-\uaa79\uab5b\uab6a\uab6b\ufb29\ufbb2-\ufbc1\ufdfc\ufdfd\ufe62\ufe64-\ufe66\ufe69\uff04\uff0b\uff1c-\uff1e\uff3e\uff40\uff5c\uff5e\uffe0-\uffe6\uffe8-\uffee\ufffc\ufffd]/]}),n.languages.purs=n.languages.purescript}return Rd}var Id,gk;function rj(){if(gk)return Id;gk=1,Id=e,e.displayName="python",e.aliases=["py"];function e(t){t.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},t.languages.python["string-interpolation"].inside.interpolation.inside.rest=t.languages.python,t.languages.py=t.languages.python}return Id}var Cd,mk;function aj(){if(mk)return Cd;mk=1,Cd=e,e.displayName="q",e.aliases=[];function e(t){t.languages.q={string:/"(?:\\.|[^"\\\r\n])*"/,comment:[{pattern:/([\t )\]}])\/.*/,lookbehind:!0,greedy:!0},{pattern:/(^|\r?\n|\r)\/[\t ]*(?:(?:\r?\n|\r)(?:.*(?:\r?\n|\r(?!\n)))*?(?:\\(?=[\t ]*(?:\r?\n|\r))|$)|\S.*)/,lookbehind:!0,greedy:!0},{pattern:/^\\[\t ]*(?:\r?\n|\r)[\s\S]+/m,greedy:!0},{pattern:/^#!.+/m,greedy:!0}],symbol:/`(?::\S+|[\w.]*)/,datetime:{pattern:/0N[mdzuvt]|0W[dtz]|\d{4}\.\d\d(?:m|\.\d\d(?:T(?:\d\d(?::\d\d(?::\d\d(?:[.:]\d\d\d)?)?)?)?)?[dz]?)|\d\d:\d\d(?::\d\d(?:[.:]\d\d\d)?)?[uvt]?/,alias:"number"},number:/\b(?![01]:)(?:0N[hje]?|0W[hj]?|0[wn]|0x[\da-fA-F]+|\d+(?:\.\d*)?(?:e[+-]?\d+)?[hjfeb]?)/,keyword:/\\\w+\b|\b(?:abs|acos|aj0?|all|and|any|asc|asin|asof|atan|attr|avgs?|binr?|by|ceiling|cols|cor|cos|count|cov|cross|csv|cut|delete|deltas|desc|dev|differ|distinct|div|do|dsave|ej|enlist|eval|except|exec|exit|exp|fby|fills|first|fkeys|flip|floor|from|get|getenv|group|gtime|hclose|hcount|hdel|hopen|hsym|iasc|identity|idesc|if|ij|in|insert|inter|inv|keys?|last|like|list|ljf?|load|log|lower|lsq|ltime|ltrim|mavg|maxs?|mcount|md5|mdev|med|meta|mins?|mmax|mmin|mmu|mod|msum|neg|next|not|null|or|over|parse|peach|pj|plist|prds?|prev|prior|rand|rank|ratios|raze|read0|read1|reciprocal|reval|reverse|rload|rotate|rsave|rtrim|save|scan|scov|sdev|select|set|setenv|show|signum|sin|sqrt|ssr?|string|sublist|sums?|sv|svar|system|tables|tan|til|trim|txf|type|uj|ungroup|union|update|upper|upsert|value|var|views?|vs|wavg|where|while|within|wj1?|wsum|ww|xasc|xbar|xcols?|xdesc|xexp|xgroup|xkey|xlog|xprev|xrank)\b/,adverb:{pattern:/['\/\\]:?|\beach\b/,alias:"function"},verb:{pattern:/(?:\B\.\B|\b[01]:|<[=>]?|>=?|[:+\-*%,!?~=|$&#@^]):?|\b_\b:?/,alias:"operator"},punctuation:/[(){}\[\];.]/}}return Cd}var Nd,hk;function ij(){if(hk)return Nd;hk=1,Nd=e,e.displayName="qml",e.aliases=[];function e(t){(function(n){for(var r=/"(?:\\.|[^\\"\r\n])*"|'(?:\\.|[^\\'\r\n])*'/.source,a=/\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))*\*\//.source,i=/(?:[^\\()[\]{}"'/]||\/(?![*/])||\(*\)|\[*\]|\{*\}|\\[\s\S])/.source.replace(//g,function(){return r}).replace(//g,function(){return a}),o=0;o<2;o++)i=i.replace(//g,function(){return i});i=i.replace(//g,"[^\\s\\S]"),n.languages.qml={comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\//,greedy:!0},"javascript-function":{pattern:RegExp(/((?:^|;)[ \t]*)function\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*\(*\)\s*\{*\}/.source.replace(//g,function(){return i}),"m"),lookbehind:!0,greedy:!0,alias:"language-javascript",inside:n.languages.javascript},"class-name":{pattern:/((?:^|[:;])[ \t]*)(?!\d)\w+(?=[ \t]*\{|[ \t]+on\b)/m,lookbehind:!0},property:[{pattern:/((?:^|[;{])[ \t]*)(?!\d)\w+(?:\.\w+)*(?=[ \t]*:)/m,lookbehind:!0},{pattern:/((?:^|[;{])[ \t]*)property[ \t]+(?!\d)\w+(?:\.\w+)*[ \t]+(?!\d)\w+(?:\.\w+)*(?=[ \t]*:)/m,lookbehind:!0,inside:{keyword:/^property/,property:/\w+(?:\.\w+)*/}}],"javascript-expression":{pattern:RegExp(/(:[ \t]*)(?![\s;}[])(?:(?!$|[;}]))+/.source.replace(//g,function(){return i}),"m"),lookbehind:!0,greedy:!0,alias:"language-javascript",inside:n.languages.javascript},string:{pattern:/"(?:\\.|[^\\"\r\n])*"/,greedy:!0},keyword:/\b(?:as|import|on)\b/,punctuation:/[{}[\]:;,]/}})(t)}return Nd}var xd,bk;function oj(){if(bk)return xd;bk=1,xd=e,e.displayName="qore",e.aliases=[];function e(t){t.languages.qore=t.languages.extend("clike",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:\/\/|#).*)/,lookbehind:!0},string:{pattern:/("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},keyword:/\b(?:abstract|any|assert|binary|bool|boolean|break|byte|case|catch|char|class|code|const|continue|data|default|do|double|else|enum|extends|final|finally|float|for|goto|hash|if|implements|import|inherits|instanceof|int|interface|long|my|native|new|nothing|null|object|our|own|private|reference|rethrow|return|short|soft(?:bool|date|float|int|list|number|string)|static|strictfp|string|sub|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while)\b/,boolean:/\b(?:false|true)\b/i,function:/\$?\b(?!\d)\w+(?=\()/,number:/\b(?:0b[01]+|0x(?:[\da-f]*\.)?[\da-fp\-]+|(?:\d+(?:\.\d+)?|\.\d+)(?:e\d+)?[df]|(?:\d+(?:\.\d+)?|\.\d+))\b/i,operator:{pattern:/(^|[^.])(?:\+[+=]?|-[-=]?|[!=](?:==?|~)?|>>?=?|<(?:=>?|<=?)?|&[&=]?|\|[|=]?|[*\/%^]=?|[~?])/,lookbehind:!0},variable:/\$(?!\d)\w+\b/})}return xd}var Od,yk;function sj(){if(yk)return Od;yk=1,Od=e,e.displayName="qsharp",e.aliases=["qs"];function e(t){(function(n){function r(h,y){return h.replace(/<<(\d+)>>/g,function(T,b){return"(?:"+y[+b]+")"})}function a(h,y,T){return RegExp(r(h,y),"")}function i(h,y){for(var T=0;T>/g,function(){return"(?:"+h+")"});return h.replace(/<>/g,"[^\\s\\S]")}var o={type:"Adj BigInt Bool Ctl Double false Int One Pauli PauliI PauliX PauliY PauliZ Qubit Range Result String true Unit Zero",other:"Adjoint adjoint apply as auto body borrow borrowing Controlled controlled distribute elif else fail fixup for function if in internal intrinsic invert is let mutable namespace new newtype open operation repeat return self set until use using while within"};function s(h){return"\\b(?:"+h.trim().replace(/ /g,"|")+")\\b"}var l=RegExp(s(o.type+" "+o.other)),u=/\b[A-Za-z_]\w*\b/.source,d=r(/<<0>>(?:\s*\.\s*<<0>>)*/.source,[u]),c={keyword:l,punctuation:/[<>()?,.:[\]]/},f=/"(?:\\.|[^\\"])*"/.source;n.languages.qsharp=n.languages.extend("clike",{comment:/\/\/.*/,string:[{pattern:a(/(^|[^$\\])<<0>>/.source,[f]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:a(/(\b(?:as|open)\s+)<<0>>(?=\s*(?:;|as\b))/.source,[d]),lookbehind:!0,inside:c},{pattern:a(/(\bnamespace\s+)<<0>>(?=\s*\{)/.source,[d]),lookbehind:!0,inside:c}],keyword:l,number:/(?:\b0(?:x[\da-f]+|b[01]+|o[0-7]+)|(?:\B\.\d+|\b\d+(?:\.\d*)?)(?:e[-+]?\d+)?)l?\b/i,operator:/\band=|\bor=|\band\b|\bnot\b|\bor\b|<[-=]|[-=]>|>>>=?|<<<=?|\^\^\^=?|\|\|\|=?|&&&=?|w\/=?|~~~|[*\/+\-^=!%]=?/,punctuation:/::|[{}[\];(),.:]/}),n.languages.insertBefore("qsharp","number",{range:{pattern:/\.\./,alias:"operator"}});var p=i(r(/\{(?:[^"{}]|<<0>>|<>)*\}/.source,[f]),2);n.languages.insertBefore("qsharp","string",{"interpolation-string":{pattern:a(/\$"(?:\\.|<<0>>|[^\\"{])*"/.source,[p]),greedy:!0,inside:{interpolation:{pattern:a(/((?:^|[^\\])(?:\\\\)*)<<0>>/.source,[p]),lookbehind:!0,inside:{punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-qsharp",inside:n.languages.qsharp}}},string:/[\s\S]+/}}})})(t),t.languages.qs=t.languages.qsharp}return Od}var Ld,Ek;function lj(){if(Ek)return Ld;Ek=1,Ld=e,e.displayName="r",e.aliases=[];function e(t){t.languages.r={comment:/#.*/,string:{pattern:/(['"])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"percent-operator":{pattern:/%[^%\s]*%/,alias:"operator"},boolean:/\b(?:FALSE|TRUE)\b/,ellipsis:/\.\.(?:\.|\d+)/,number:[/\b(?:Inf|NaN)\b/,/(?:\b0x[\dA-Fa-f]+(?:\.\d*)?|\b\d+(?:\.\d*)?|\B\.\d+)(?:[EePp][+-]?\d+)?[iL]?/],keyword:/\b(?:NA|NA_character_|NA_complex_|NA_integer_|NA_real_|NULL|break|else|for|function|if|in|next|repeat|while)\b/,operator:/->?>?|<(?:=|=!]=?|::?|&&?|\|\|?|[+*\/^$@~]/,punctuation:/[(){}\[\],;]/}}return Ld}var Dd,Sk;function uj(){if(Sk)return Dd;Sk=1;var e=Hm();Dd=t,t.displayName="racket",t.aliases=["rkt"];function t(n){n.register(e),n.languages.racket=n.languages.extend("scheme",{"lambda-parameter":{pattern:/([(\[]lambda\s+[(\[])[^()\[\]'\s]+/,lookbehind:!0}}),n.languages.insertBefore("racket","string",{lang:{pattern:/^#lang.+/m,greedy:!0,alias:"keyword"}}),n.languages.rkt=n.languages.racket}return Dd}var Md,vk;function cj(){if(vk)return Md;vk=1,Md=e,e.displayName="reason",e.aliases=[];function e(t){t.languages.reason=t.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),t.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete t.languages.reason.function}return Md}var Fd,kk;function dj(){if(kk)return Fd;kk=1,Fd=e,e.displayName="regex",e.aliases=[];function e(t){(function(n){var r={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},a=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/,i={pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},o={pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},s="(?:[^\\\\-]|"+a.source+")",l=RegExp(s+"-"+s),u={pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"};n.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:l,inside:{escape:a,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":r,"char-set":o,escape:a}},"special-escape":r,"char-set":i,backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":u}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:a,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|:=]=?|!=|\b_\b/,punctuation:/[,;.\[\]{}()]/}}return Pd}var Ud,_k;function fj(){if(_k)return Ud;_k=1,Ud=e,e.displayName="renpy",e.aliases=["rpy"];function e(t){t.languages.renpy={comment:{pattern:/(^|[^\\])#.+/,lookbehind:!0},string:{pattern:/("""|''')[\s\S]+?\1|("|')(?:\\.|(?!\2)[^\\])*\2|(?:^#?(?:(?:[0-9a-fA-F]){3}|[0-9a-fA-F]{6})$)/m,greedy:!0},function:/\b[a-z_]\w*(?=\()/i,property:/\b(?:Update|UpdateVersion|action|activate_sound|adv_nvl_transition|after_load_transition|align|alpha|alt|anchor|antialias|area|auto|background|bar_invert|bar_resizing|bar_vertical|black_color|bold|bottom_bar|bottom_gutter|bottom_margin|bottom_padding|box_reverse|box_wrap|can_update|caret|child|color|crop|default_afm_enable|default_afm_time|default_fullscreen|default_text_cps|developer|directory_name|drag_handle|drag_joined|drag_name|drag_raise|draggable|dragged|drop_shadow|drop_shadow_color|droppable|dropped|easein|easeout|edgescroll|end_game_transition|end_splash_transition|enter_replay_transition|enter_sound|enter_transition|enter_yesno_transition|executable_name|exit_replay_transition|exit_sound|exit_transition|exit_yesno_transition|fadein|fadeout|first_indent|first_spacing|fit_first|focus|focus_mask|font|foreground|game_main_transition|get_installed_packages|google_play_key|google_play_salt|ground|has_music|has_sound|has_voice|height|help|hinting|hover|hover_background|hover_color|hover_sound|hovered|hyperlink_functions|idle|idle_color|image_style|include_update|insensitive|insensitive_background|insensitive_color|inside|intra_transition|italic|justify|kerning|keyboard_focus|language|layer_clipping|layers|layout|left_bar|left_gutter|left_margin|left_padding|length|line_leading|line_overlap_split|line_spacing|linear|main_game_transition|main_menu_music|maximum|min_width|minimum|minwidth|modal|mouse|mousewheel|name|narrator_menu|newline_indent|nvl_adv_transition|offset|order_reverse|outlines|overlay_functions|pos|position|prefix|radius|range|rest_indent|right_bar|right_gutter|right_margin|right_padding|rotate|rotate_pad|ruby_style|sample_sound|save_directory|say_attribute_transition|screen_height|screen_width|scrollbars|selected_hover|selected_hover_color|selected_idle|selected_idle_color|selected_insensitive|show_side_image|show_two_window|side_spacing|side_xpos|side_ypos|size|size_group|slow_cps|slow_cps_multiplier|spacing|strikethrough|subpixel|text_align|text_style|text_xpos|text_y_fudge|text_ypos|thumb|thumb_offset|thumb_shadow|thumbnail_height|thumbnail_width|time|top_bar|top_gutter|top_margin|top_padding|translations|underline|unscrollable|update|value|version|version_name|version_tuple|vertical|width|window_hide_transition|window_icon|window_left_padding|window_show_transition|window_title|windows_icon|xadjustment|xalign|xanchor|xanchoraround|xaround|xcenter|xfill|xinitial|xmargin|xmaximum|xminimum|xoffset|xofsset|xpadding|xpos|xsize|xzoom|yadjustment|yalign|yanchor|yanchoraround|yaround|ycenter|yfill|yinitial|ymargin|ymaximum|yminimum|yoffset|ypadding|ypos|ysize|ysizexysize|yzoom|zoom|zorder)\b/,tag:/\b(?:bar|block|button|buttoscreenn|drag|draggroup|fixed|frame|grid|[hv]box|hotbar|hotspot|image|imagebutton|imagemap|input|key|label|menu|mm_menu_frame|mousearea|nvl|parallel|screen|self|side|tag|text|textbutton|timer|vbar|viewport|window)\b|\$/,keyword:/\b(?:None|add|adjustment|alignaround|allow|angle|animation|around|as|assert|behind|box_layout|break|build|cache|call|center|changed|child_size|choice|circles|class|clear|clicked|clipping|clockwise|config|contains|continue|corner1|corner2|counterclockwise|def|default|define|del|delay|disabled|disabled_text|dissolve|elif|else|event|except|exclude|exec|expression|fade|finally|for|from|function|global|gm_root|has|hide|id|if|import|in|init|is|jump|knot|lambda|left|less_rounded|mm_root|movie|music|null|on|onlayer|pass|pause|persistent|play|print|python|queue|raise|random|renpy|repeat|return|right|rounded_window|scene|scope|set|show|slow|slow_abortable|slow_done|sound|stop|store|style|style_group|substitute|suffix|theme|transform|transform_anchor|transpose|try|ui|unhovered|updater|use|voice|while|widget|widget_hover|widget_selected|widget_text|yield)\b/,boolean:/\b(?:[Ff]alse|[Tt]rue)\b/,number:/(?:\b(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*(?:\.\d*)?)|\B\.\d+)(?:e[+-]?\d+)?j?/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:and|at|not|or|with)\b/,punctuation:/[{}[\];(),.:]/},t.languages.rpy=t.languages.renpy}return Ud}var Bd,Tk;function gj(){if(Tk)return Bd;Tk=1,Bd=e,e.displayName="rest",e.aliases=[];function e(t){t.languages.rest={table:[{pattern:/(^[\t ]*)(?:\+[=-]+)+\+(?:\r?\n|\r)(?:\1[+|].+[+|](?:\r?\n|\r))+\1(?:\+[=-]+)+\+/m,lookbehind:!0,inside:{punctuation:/\||(?:\+[=-]+)+\+/}},{pattern:/(^[\t ]*)=+ [ =]*=(?:(?:\r?\n|\r)\1.+)+(?:\r?\n|\r)\1=+ [ =]*=(?=(?:\r?\n|\r){2}|\s*$)/m,lookbehind:!0,inside:{punctuation:/[=-]+/}}],"substitution-def":{pattern:/(^[\t ]*\.\. )\|(?:[^|\s](?:[^|]*[^|\s])?)\| [^:]+::/m,lookbehind:!0,inside:{substitution:{pattern:/^\|(?:[^|\s]|[^|\s][^|]*[^|\s])\|/,alias:"attr-value",inside:{punctuation:/^\||\|$/}},directive:{pattern:/( )(?! )[^:]+::/,lookbehind:!0,alias:"function",inside:{punctuation:/::$/}}}},"link-target":[{pattern:/(^[\t ]*\.\. )\[[^\]]+\]/m,lookbehind:!0,alias:"string",inside:{punctuation:/^\[|\]$/}},{pattern:/(^[\t ]*\.\. )_(?:`[^`]+`|(?:[^:\\]|\\.)+):/m,lookbehind:!0,alias:"string",inside:{punctuation:/^_|:$/}}],directive:{pattern:/(^[\t ]*\.\. )[^:]+::/m,lookbehind:!0,alias:"function",inside:{punctuation:/::$/}},comment:{pattern:/(^[\t ]*\.\.)(?:(?: .+)?(?:(?:\r?\n|\r).+)+| .+)(?=(?:\r?\n|\r){2}|$)/m,lookbehind:!0},title:[{pattern:/^(([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~])\2+)(?:\r?\n|\r).+(?:\r?\n|\r)\1$/m,inside:{punctuation:/^[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]+|[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]+$/,important:/.+/}},{pattern:/(^|(?:\r?\n|\r){2}).+(?:\r?\n|\r)([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~])\2+(?=\r?\n|\r|$)/,lookbehind:!0,inside:{punctuation:/[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]+$/,important:/.+/}}],hr:{pattern:/((?:\r?\n|\r){2})([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~])\2{3,}(?=(?:\r?\n|\r){2})/,lookbehind:!0,alias:"punctuation"},field:{pattern:/(^[\t ]*):[^:\r\n]+:(?= )/m,lookbehind:!0,alias:"attr-name"},"command-line-option":{pattern:/(^[\t ]*)(?:[+-][a-z\d]|(?:--|\/)[a-z\d-]+)(?:[ =](?:[a-z][\w-]*|<[^<>]+>))?(?:, (?:[+-][a-z\d]|(?:--|\/)[a-z\d-]+)(?:[ =](?:[a-z][\w-]*|<[^<>]+>))?)*(?=(?:\r?\n|\r)? {2,}\S)/im,lookbehind:!0,alias:"symbol"},"literal-block":{pattern:/::(?:\r?\n|\r){2}([ \t]+)(?![ \t]).+(?:(?:\r?\n|\r)\1.+)*/,inside:{"literal-block-punctuation":{pattern:/^::/,alias:"punctuation"}}},"quoted-literal-block":{pattern:/::(?:\r?\n|\r){2}([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]).*(?:(?:\r?\n|\r)\1.*)*/,inside:{"literal-block-punctuation":{pattern:/^(?:::|([!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~])\1*)/m,alias:"punctuation"}}},"list-bullet":{pattern:/(^[\t ]*)(?:[*+\-•‣⁃]|\(?(?:\d+|[a-z]|[ivxdclm]+)\)|(?:\d+|[a-z]|[ivxdclm]+)\.)(?= )/im,lookbehind:!0,alias:"punctuation"},"doctest-block":{pattern:/(^[\t ]*)>>> .+(?:(?:\r?\n|\r).+)*/m,lookbehind:!0,inside:{punctuation:/^>>>/}},inline:[{pattern:/(^|[\s\-:\/'"<(\[{])(?::[^:]+:`.*?`|`.*?`:[^:]+:|(\*\*?|``?|\|)(?!\s)(?:(?!\2).)*\S\2(?=[\s\-.,:;!?\\\/'")\]}]|$))/m,lookbehind:!0,inside:{bold:{pattern:/(^\*\*).+(?=\*\*$)/,lookbehind:!0},italic:{pattern:/(^\*).+(?=\*$)/,lookbehind:!0},"inline-literal":{pattern:/(^``).+(?=``$)/,lookbehind:!0,alias:"symbol"},role:{pattern:/^:[^:]+:|:[^:]+:$/,alias:"function",inside:{punctuation:/^:|:$/}},"interpreted-text":{pattern:/(^`).+(?=`$)/,lookbehind:!0,alias:"attr-value"},substitution:{pattern:/(^\|).+(?=\|$)/,lookbehind:!0,alias:"attr-value"},punctuation:/\*\*?|``?|\|/}}],link:[{pattern:/\[[^\[\]]+\]_(?=[\s\-.,:;!?\\\/'")\]}]|$)/,alias:"string",inside:{punctuation:/^\[|\]_$/}},{pattern:/(?:\b[a-z\d]+(?:[_.:+][a-z\d]+)*_?_|`[^`]+`_?_|_`[^`]+`)(?=[\s\-.,:;!?\\\/'")\]}]|$)/i,alias:"string",inside:{punctuation:/^_?`|`$|`?_?_$/}}],punctuation:{pattern:/(^[\t ]*)(?:\|(?= |$)|(?:---?|—|\.\.|__)(?= )|\.\.$)/m,lookbehind:!0}}}return Bd}var $d,Ak;function mj(){if(Ak)return $d;Ak=1,$d=e,e.displayName="rip",e.aliases=[];function e(t){t.languages.rip={comment:{pattern:/#.*/,greedy:!0},char:{pattern:/\B`[^\s`'",.:;#\/\\()<>\[\]{}]\b/,greedy:!0},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},regex:{pattern:/(^|[^/])\/(?!\/)(?:\[[^\n\r\]]*\]|\\.|[^/\\\r\n\[])+\/(?=\s*(?:$|[\r\n,.;})]))/,lookbehind:!0,greedy:!0},keyword:/(?:=>|->)|\b(?:case|catch|class|else|exit|finally|if|raise|return|switch|try)\b/,builtin:/@|\bSystem\b/,boolean:/\b(?:false|true)\b/,date:/\b\d{4}-\d{2}-\d{2}\b/,time:/\b\d{2}:\d{2}:\d{2}\b/,datetime:/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\b/,symbol:/:[^\d\s`'",.:;#\/\\()<>\[\]{}][^\s`'",.:;#\/\\()<>\[\]{}]*/,number:/[+-]?\b(?:\d+\.\d+|\d+)\b/,punctuation:/(?:\.{2,3})|[`,.:;=\/\\()<>\[\]{}]/,reference:/[^\d\s`'",.:;#\/\\()<>\[\]{}][^\s`'",.:;#\/\\()<>\[\]{}]*/}}return $d}var zd,Rk;function hj(){if(Rk)return zd;Rk=1,zd=e,e.displayName="roboconf",e.aliases=[];function e(t){t.languages.roboconf={comment:/#.*/,keyword:{pattern:/(^|\s)(?:(?:external|import)\b|(?:facet|instance of)(?=[ \t]+[\w-]+[ \t]*\{))/,lookbehind:!0},component:{pattern:/[\w-]+(?=[ \t]*\{)/,alias:"variable"},property:/[\w.-]+(?=[ \t]*:)/,value:{pattern:/(=[ \t]*(?![ \t]))[^,;]+/,lookbehind:!0,alias:"attr-value"},optional:{pattern:/\(optional\)/,alias:"builtin"},wildcard:{pattern:/(\.)\*/,lookbehind:!0,alias:"operator"},punctuation:/[{},.;:=]/}}return zd}var Gd,Ik;function bj(){if(Ik)return Gd;Ik=1,Gd=e,e.displayName="robotframework",e.aliases=[];function e(t){(function(n){var r={pattern:/(^[ \t]*| {2}|\t)#.*/m,lookbehind:!0,greedy:!0},a={pattern:/((?:^|[^\\])(?:\\{2})*)[$@&%]\{(?:[^{}\r\n]|\{[^{}\r\n]*\})*\}/,lookbehind:!0,inside:{punctuation:/^[$@&%]\{|\}$/}};function i(u,d){var c={};c["section-header"]={pattern:/^ ?\*{3}.+?\*{3}/,alias:"keyword"};for(var f in d)c[f]=d[f];return c.tag={pattern:/([\r\n](?: {2}|\t)[ \t]*)\[[-\w]+\]/,lookbehind:!0,inside:{punctuation:/\[|\]/}},c.variable=a,c.comment=r,{pattern:RegExp(/^ ?\*{3}[ \t]*[ \t]*\*{3}(?:.|[\r\n](?!\*{3}))*/.source.replace(//g,function(){return u}),"im"),alias:"section",inside:c}}var o={pattern:/(\[Documentation\](?: {2}|\t)[ \t]*)(?![ \t]|#)(?:.|(?:\r\n?|\n)[ \t]*\.{3})+/,lookbehind:!0,alias:"string"},s={pattern:/([\r\n] ?)(?!#)(?:\S(?:[ \t]\S)*)+/,lookbehind:!0,alias:"function",inside:{variable:a}},l={pattern:/([\r\n](?: {2}|\t)[ \t]*)(?!\[|\.{3}|#)(?:\S(?:[ \t]\S)*)+/,lookbehind:!0,inside:{variable:a}};n.languages.robotframework={settings:i("Settings",{documentation:{pattern:/([\r\n] ?Documentation(?: {2}|\t)[ \t]*)(?![ \t]|#)(?:.|(?:\r\n?|\n)[ \t]*\.{3})+/,lookbehind:!0,alias:"string"},property:{pattern:/([\r\n] ?)(?!\.{3}|#)(?:\S(?:[ \t]\S)*)+/,lookbehind:!0}}),variables:i("Variables"),"test-cases":i("Test Cases",{"test-name":s,documentation:o,property:l}),keywords:i("Keywords",{"keyword-name":s,documentation:o,property:l}),tasks:i("Tasks",{"task-name":s,documentation:o,property:l}),comment:r},n.languages.robot=n.languages.robotframework})(t)}return Gd}var qd,Ck;function yj(){if(Ck)return qd;Ck=1,qd=e,e.displayName="rust",e.aliases=[];function e(t){(function(n){for(var r=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|)*\*\//.source,a=0;a<2;a++)r=r.replace(//g,function(){return r});r=r.replace(//g,function(){return/[^\s\S]/.source}),n.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+r),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},n.languages.rust["closure-params"].inside.rest=n.languages.rust,n.languages.rust.attribute.inside.string=n.languages.rust.string})(t)}return qd}var jd,Nk;function Ej(){if(Nk)return jd;Nk=1,jd=e,e.displayName="sas",e.aliases=[];function e(t){(function(n){var r=/(?:"(?:""|[^"])*"(?!")|'(?:''|[^'])*'(?!'))/.source,a=/\b(?:\d[\da-f]*x|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/i,i={pattern:RegExp(r+"[bx]"),alias:"number"},o={pattern:/&[a-z_]\w*/i},s={pattern:/((?:^|\s|=|\())%(?:ABORT|BY|CMS|COPY|DISPLAY|DO|ELSE|END|EVAL|GLOBAL|GO|GOTO|IF|INC|INCLUDE|INDEX|INPUT|KTRIM|LENGTH|LET|LIST|LOCAL|PUT|QKTRIM|QSCAN|QSUBSTR|QSYSFUNC|QUPCASE|RETURN|RUN|SCAN|SUBSTR|SUPERQ|SYMDEL|SYMEXIST|SYMGLOBL|SYMLOCAL|SYSCALL|SYSEVALF|SYSEXEC|SYSFUNC|SYSGET|SYSRPUT|THEN|TO|TSO|UNQUOTE|UNTIL|UPCASE|WHILE|WINDOW)\b/i,lookbehind:!0,alias:"keyword"},l={pattern:/(^|\s)(?:proc\s+\w+|data(?!=)|quit|run)\b/i,alias:"keyword",lookbehind:!0},u=[/\/\*[\s\S]*?\*\//,{pattern:/(^[ \t]*|;\s*)\*[^;]*;/m,lookbehind:!0}],d={pattern:RegExp(r),greedy:!0},c=/[$%@.(){}\[\];,\\]/,f={pattern:/%?\b\w+(?=\()/,alias:"keyword"},p={function:f,"arg-value":{pattern:/(=\s*)[A-Z\.]+/i,lookbehind:!0},operator:/=/,"macro-variable":o,arg:{pattern:/[A-Z]+/i,alias:"keyword"},number:a,"numeric-constant":i,punctuation:c,string:d},h={pattern:/\b(?:format|put)\b=?[\w'$.]+/i,inside:{keyword:/^(?:format|put)(?==)/i,equals:/=/,format:{pattern:/(?:\w|\$\d)+\.\d?/,alias:"number"}}},y={pattern:/\b(?:format|put)\s+[\w']+(?:\s+[$.\w]+)+(?=;)/i,inside:{keyword:/^(?:format|put)/i,format:{pattern:/[\w$]+\.\d?/,alias:"number"}}},T={pattern:/((?:^|\s)=?)(?:catname|checkpoint execute_always|dm|endsas|filename|footnote|%include|libname|%list|lock|missing|options|page|resetline|%run|sasfile|skip|sysecho|title\d?)\b/i,lookbehind:!0,alias:"keyword"},b={pattern:/(^|\s)(?:submit(?:\s+(?:load|norun|parseonly))?|endsubmit)\b/i,lookbehind:!0,alias:"keyword"},g=/aStore|accessControl|aggregation|audio|autotune|bayesianNetClassifier|bioMedImage|boolRule|builtins|cardinality|cdm|clustering|conditionalRandomFields|configuration|copula|countreg|dataDiscovery|dataPreprocess|dataSciencePilot|dataStep|decisionTree|deduplication|deepLearn|deepNeural|deepRnn|ds2|ecm|entityRes|espCluster|explainModel|factmac|fastKnn|fcmpact|fedSql|freqTab|gVarCluster|gam|gleam|graphSemiSupLearn|hiddenMarkovModel|hyperGroup|ica|image|iml|kernalPca|langModel|ldaTopic|loadStreams|mbc|mixed|mlTools|modelPublishing|network|neuralNet|nmf|nonParametricBayes|nonlinear|optNetwork|optimization|panel|pca|percentile|phreg|pls|qkb|qlim|quantreg|recommend|regression|reinforcementLearn|robustPca|ruleMining|sampling|sandwich|sccasl|search(?:Analytics)?|sentimentAnalysis|sequence|session(?:Prop)?|severity|simSystem|simple|smartData|sparkEmbeddedProcess|sparseML|spatialreg|spc|stabilityMonitoring|svDataDescription|svm|table|text(?:Filters|Frequency|Mining|Parse|Rule(?:Develop|Score)|Topic|Util)|timeData|transpose|tsInfo|tsReconcile|uniTimeSeries|varReduce/.source,m={pattern:RegExp(/(^|\s)(?:action\s+)?(?:)\.[a-z]+\b[^;]+/.source.replace(//g,function(){return g}),"i"),lookbehind:!0,inside:{keyword:RegExp(/(?:)\.[a-z]+\b/.source.replace(//g,function(){return g}),"i"),action:{pattern:/(?:action)/i,alias:"keyword"},comment:u,function:f,"arg-value":p["arg-value"],operator:p.operator,argument:p.arg,number:a,"numeric-constant":i,punctuation:c,string:d}},v={pattern:/((?:^|\s)=?)(?:after|analysis|and|array|barchart|barwidth|begingraph|by|call|cas|cbarline|cfill|class(?:lev)?|close|column|computed?|contains|continue|data(?==)|define|delete|describe|document|do\s+over|do|dol|drop|dul|else|end(?:comp|source)?|entryTitle|eval(?:uate)?|exec(?:ute)?|exit|file(?:name)?|fill(?:attrs)?|flist|fnc|function(?:list)?|global|goto|group(?:by)?|headline|headskip|histogram|if|infile|keep|keylabel|keyword|label|layout|leave|legendlabel|length|libname|loadactionset|merge|midpoints|_?null_|name|noobs|nowd|ods|options|or|otherwise|out(?:put)?|over(?:lay)?|plot|print|put|raise|ranexp|rannor|rbreak|retain|return|select|session|sessref|set|source|statgraph|sum|summarize|table|temp|terminate|then\s+do|then|title\d?|to|var|when|where|xaxisopts|y2axisopts|yaxisopts)\b/i,lookbehind:!0};n.languages.sas={datalines:{pattern:/^([ \t]*)(?:cards|(?:data)?lines);[\s\S]+?^[ \t]*;/im,lookbehind:!0,alias:"string",inside:{keyword:{pattern:/^(?:cards|(?:data)?lines)/i},punctuation:/;/}},"proc-sql":{pattern:/(^proc\s+(?:fed)?sql(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|data|quit|run);|(?![\s\S]))/im,lookbehind:!0,inside:{sql:{pattern:RegExp(/^[ \t]*(?:select|alter\s+table|(?:create|describe|drop)\s+(?:index|table(?:\s+constraints)?|view)|create\s+unique\s+index|insert\s+into|update)(?:|[^;"'])+;/.source.replace(//g,function(){return r}),"im"),alias:"language-sql",inside:n.languages.sql},"global-statements":T,"sql-statements":{pattern:/(^|\s)(?:disconnect\s+from|begin|commit|exec(?:ute)?|reset|rollback|validate)\b/i,lookbehind:!0,alias:"keyword"},number:a,"numeric-constant":i,punctuation:c,string:d}},"proc-groovy":{pattern:/(^proc\s+groovy(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|data|quit|run);|(?![\s\S]))/im,lookbehind:!0,inside:{comment:u,groovy:{pattern:RegExp(/(^[ \t]*submit(?:\s+(?:load|norun|parseonly))?)(?:|[^"'])+?(?=endsubmit;)/.source.replace(//g,function(){return r}),"im"),lookbehind:!0,alias:"language-groovy",inside:n.languages.groovy},keyword:v,"submit-statement":b,"global-statements":T,number:a,"numeric-constant":i,punctuation:c,string:d}},"proc-lua":{pattern:/(^proc\s+lua(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|data|quit|run);|(?![\s\S]))/im,lookbehind:!0,inside:{comment:u,lua:{pattern:RegExp(/(^[ \t]*submit(?:\s+(?:load|norun|parseonly))?)(?:|[^"'])+?(?=endsubmit;)/.source.replace(//g,function(){return r}),"im"),lookbehind:!0,alias:"language-lua",inside:n.languages.lua},keyword:v,"submit-statement":b,"global-statements":T,number:a,"numeric-constant":i,punctuation:c,string:d}},"proc-cas":{pattern:/(^proc\s+cas(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|data);|(?![\s\S]))/im,lookbehind:!0,inside:{comment:u,"statement-var":{pattern:/((?:^|\s)=?)saveresult\s[^;]+/im,lookbehind:!0,inside:{statement:{pattern:/^saveresult\s+\S+/i,inside:{keyword:/^(?:saveresult)/i}},rest:p}},"cas-actions":m,statement:{pattern:/((?:^|\s)=?)(?:default|(?:un)?set|on|output|upload)[^;]+/im,lookbehind:!0,inside:p},step:l,keyword:v,function:f,format:h,altformat:y,"global-statements":T,number:a,"numeric-constant":i,punctuation:c,string:d}},"proc-args":{pattern:RegExp(/(^proc\s+\w+\s+)(?!\s)(?:[^;"']|)+;/.source.replace(//g,function(){return r}),"im"),lookbehind:!0,inside:p},"macro-keyword":s,"macro-variable":o,"macro-string-functions":{pattern:/((?:^|\s|=))%(?:BQUOTE|NRBQUOTE|NRQUOTE|NRSTR|QUOTE|STR)\(.*?(?:[^%]\))/i,lookbehind:!0,inside:{function:{pattern:/%(?:BQUOTE|NRBQUOTE|NRQUOTE|NRSTR|QUOTE|STR)/i,alias:"keyword"},"macro-keyword":s,"macro-variable":o,"escaped-char":{pattern:/%['"()<>=¬^~;,#]/},punctuation:c}},"macro-declaration":{pattern:/^%macro[^;]+(?=;)/im,inside:{keyword:/%macro/i}},"macro-end":{pattern:/^%mend[^;]+(?=;)/im,inside:{keyword:/%mend/i}},macro:{pattern:/%_\w+(?=\()/,alias:"keyword"},input:{pattern:/\binput\s[-\w\s/*.$&]+;/i,inside:{input:{alias:"keyword",pattern:/^input/i},comment:u,number:a,"numeric-constant":i}},"options-args":{pattern:/(^options)[-'"|/\\<>*+=:()\w\s]*(?=;)/im,lookbehind:!0,inside:p},"cas-actions":m,comment:u,function:f,format:h,altformat:y,"numeric-constant":i,datetime:{pattern:RegExp(r+"(?:dt?|t)"),alias:"number"},string:d,step:l,keyword:v,"operator-keyword":{pattern:/\b(?:eq|ge|gt|in|le|lt|ne|not)\b/i,alias:"operator"},number:a,operator:/\*\*?|\|\|?|!!?|¦¦?|<[>=]?|>[<=]?|[-+\/=&]|[~¬^]=?/,punctuation:c}})(t)}return jd}var Hd,xk;function Sj(){if(xk)return Hd;xk=1,Hd=e,e.displayName="sass",e.aliases=[];function e(t){(function(n){n.languages.sass=n.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),n.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete n.languages.sass.atrule;var r=/\$[-\w]+|#\{\$[-\w]+\}/,a=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];n.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:r,operator:a}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:r,operator:a,important:n.languages.sass.important}}}),delete n.languages.sass.property,delete n.languages.sass.important,n.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})})(t)}return Hd}var Vd,Ok;function vj(){if(Ok)return Vd;Ok=1;var e=Gm();Vd=t,t.displayName="scala",t.aliases=[];function t(n){n.register(e),n.languages.scala=n.languages.extend("java",{"triple-quoted-string":{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/<-|=>|\b(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|null|object|override|package|private|protected|return|sealed|self|super|this|throw|trait|try|type|val|var|while|with|yield)\b/,number:/\b0x(?:[\da-f]*\.)?[\da-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e\d+)?[dfl]?/i,builtin:/\b(?:Any|AnyRef|AnyVal|Boolean|Byte|Char|Double|Float|Int|Long|Nothing|Short|String|Unit)\b/,symbol:/'[^\d\s\\]\w*/}),n.languages.insertBefore("scala","triple-quoted-string",{"string-interpolation":{pattern:/\b[a-z]\w*(?:"""(?:[^$]|\$(?:[^{]|\{(?:[^{}]|\{[^{}]*\})*\}))*?"""|"(?:[^$"\r\n]|\$(?:[^{]|\{(?:[^{}]|\{[^{}]*\})*\}))*")/i,greedy:!0,inside:{id:{pattern:/^\w+/,greedy:!0,alias:"function"},escape:{pattern:/\\\$"|\$[$"]/,greedy:!0,alias:"symbol"},interpolation:{pattern:/\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,greedy:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:n.languages.scala}}},string:/[\s\S]+/}}}),delete n.languages.scala["class-name"],delete n.languages.scala.function}return Vd}var Wd,Lk;function kj(){if(Lk)return Wd;Lk=1,Wd=e,e.displayName="scss",e.aliases=[];function e(t){t.languages.scss=t.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),t.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),t.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),t.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),t.languages.scss.atrule.inside.rest=t.languages.scss}return Wd}var Yd,Dk;function wj(){if(Dk)return Yd;Dk=1;var e=GR();Yd=t,t.displayName="shellSession",t.aliases=[];function t(n){n.register(e),function(r){var a=[/"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/.source,/'[^']*'/.source,/\$'(?:[^'\\]|\\[\s\S])*'/.source,/<<-?\s*(["']?)(\w+)\1\s[\s\S]*?[\r\n]\2/.source].join("|");r.languages["shell-session"]={command:{pattern:RegExp(/^/.source+"(?:"+(/[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+(?::[^\0-\x1F$#%*?"<>:;|]+)?/.source+"|"+/[/~.][^\0-\x1F$#%*?"<>@:;|]*/.source)+")?"+/[$#%](?=\s)/.source+/(?:[^\\\r\n \t'"<$]|[ \t](?:(?!#)|#.*$)|\\(?:[^\r]|\r\n?)|\$(?!')|<(?!<)|<>)+/.source.replace(/<>/g,function(){return a}),"m"),greedy:!0,inside:{info:{pattern:/^[^#$%]+/,alias:"punctuation",inside:{user:/^[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+/,punctuation:/:/,path:/[\s\S]+/}},bash:{pattern:/(^[$#%]\s*)\S[\s\S]*/,lookbehind:!0,alias:"language-bash",inside:r.languages.bash},"shell-symbol":{pattern:/^[$#%]/,alias:"important"}}},output:/.(?:.*(?:[\r\n]|.$))*/},r.languages["sh-session"]=r.languages.shellsession=r.languages["shell-session"]}(n)}return Yd}var Kd,Mk;function _j(){if(Mk)return Kd;Mk=1,Kd=e,e.displayName="smali",e.aliases=[];function e(t){t.languages.smali={comment:/#.*/,string:{pattern:/"(?:[^\r\n\\"]|\\.)*"|'(?:[^\r\n\\']|\\(?:.|u[\da-fA-F]{4}))'/,greedy:!0},"class-name":{pattern:/(^|[^L])L(?:(?:\w+|`[^`\r\n]*`)\/)*(?:[\w$]+|`[^`\r\n]*`)(?=\s*;)/,lookbehind:!0,inside:{"class-name":{pattern:/(^L|\/)(?:[\w$]+|`[^`\r\n]*`)$/,lookbehind:!0},namespace:{pattern:/^(L)(?:(?:\w+|`[^`\r\n]*`)\/)+/,lookbehind:!0,inside:{punctuation:/\//}},builtin:/^L/}},builtin:[{pattern:/([();\[])[BCDFIJSVZ]+/,lookbehind:!0},{pattern:/([\w$>]:)[BCDFIJSVZ]/,lookbehind:!0}],keyword:[{pattern:/(\.end\s+)[\w-]+/,lookbehind:!0},{pattern:/(^|[^\w.-])\.(?!\d)[\w-]+/,lookbehind:!0},{pattern:/(^|[^\w.-])(?:abstract|annotation|bridge|constructor|enum|final|interface|private|protected|public|runtime|static|synthetic|system|transient)(?![\w.-])/,lookbehind:!0}],function:{pattern:/(^|[^\w.-])(?:\w+|<[\w$-]+>)(?=\()/,lookbehind:!0},field:{pattern:/[\w$]+(?=:)/,alias:"variable"},register:{pattern:/(^|[^\w.-])[vp]\d(?![\w.-])/,lookbehind:!0,alias:"variable"},boolean:{pattern:/(^|[^\w.-])(?:false|true)(?![\w.-])/,lookbehind:!0},number:{pattern:/(^|[^/\w.-])-?(?:NAN|INFINITY|0x(?:[\dA-F]+(?:\.[\dA-F]*)?|\.[\dA-F]+)(?:p[+-]?[\dA-F]+)?|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)[dflst]?(?![\w.-])/i,lookbehind:!0},label:{pattern:/(:)\w+/,lookbehind:!0,alias:"property"},operator:/->|\.\.|[\[=]/,punctuation:/[{}(),;:]/}}return Kd}var Xd,Fk;function Tj(){if(Fk)return Xd;Fk=1,Xd=e,e.displayName="smalltalk",e.aliases=[];function e(t){t.languages.smalltalk={comment:{pattern:/"(?:""|[^"])*"/,greedy:!0},char:{pattern:/\$./,greedy:!0},string:{pattern:/'(?:''|[^'])*'/,greedy:!0},symbol:/#[\da-z]+|#(?:-|([+\/\\*~<>=@%|&?!])\1?)|#(?=\()/i,"block-arguments":{pattern:/(\[\s*):[^\[|]*\|/,lookbehind:!0,inside:{variable:/:[\da-z]+/i,punctuation:/\|/}},"temporary-variables":{pattern:/\|[^|]+\|/,inside:{variable:/[\da-z]+/i,punctuation:/\|/}},keyword:/\b(?:new|nil|self|super)\b/,boolean:/\b(?:false|true)\b/,number:[/\d+r-?[\dA-Z]+(?:\.[\dA-Z]+)?(?:e-?\d+)?/,/\b\d+(?:\.\d+)?(?:e-?\d+)?/],operator:/[<=]=?|:=|~[~=]|\/\/?|\\\\|>[>=]?|[!^+\-*&|,@]/,punctuation:/[.;:?\[\](){}]/}}return Xd}var Zd,Pk;function Aj(){if(Pk)return Zd;Pk=1;var e=nt();Zd=t,t.displayName="smarty",t.aliases=[];function t(n){n.register(e),function(r){r.languages.smarty={comment:{pattern:/^\{\*[\s\S]*?\*\}/,greedy:!0},"embedded-php":{pattern:/^\{php\}[\s\S]*?\{\/php\}/,greedy:!0,inside:{smarty:{pattern:/^\{php\}|\{\/php\}$/,inside:null},php:{pattern:/[\s\S]+/,alias:"language-php",inside:r.languages.php}}},string:[{pattern:/"(?:\\.|[^"\\\r\n])*"/,greedy:!0,inside:{interpolation:{pattern:/\{[^{}]*\}|`[^`]*`/,inside:{"interpolation-punctuation":{pattern:/^[{`]|[`}]$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:null}}},variable:/\$\w+/}},{pattern:/'(?:\\.|[^'\\\r\n])*'/,greedy:!0}],keyword:{pattern:/(^\{\/?)[a-z_]\w*\b(?!\()/i,lookbehind:!0,greedy:!0},delimiter:{pattern:/^\{\/?|\}$/,greedy:!0,alias:"punctuation"},number:/\b0x[\dA-Fa-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][-+]?\d+)?/,variable:[/\$(?!\d)\w+/,/#(?!\d)\w+#/,{pattern:/(\.|->|\w\s*=)(?!\d)\w+\b(?!\()/,lookbehind:!0},{pattern:/(\[)(?!\d)\w+(?=\])/,lookbehind:!0}],function:{pattern:/(\|\s*)@?[a-z_]\w*|\b[a-z_]\w*(?=\()/i,lookbehind:!0},"attr-name":/\b[a-z_]\w*(?=\s*=)/i,boolean:/\b(?:false|no|off|on|true|yes)\b/,punctuation:/[\[\](){}.,:`]|->/,operator:[/[+\-*\/%]|==?=?|[!<>]=?|&&|\|\|?/,/\bis\s+(?:not\s+)?(?:div|even|odd)(?:\s+by)?\b/,/\b(?:and|eq|gt?e|gt|lt?e|lt|mod|neq?|not|or)\b/]},r.languages.smarty["embedded-php"].inside.smarty.inside=r.languages.smarty,r.languages.smarty.string[0].inside.interpolation.inside.expression.inside=r.languages.smarty;var a=/"(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*'/,i=RegExp(/\{\*[\s\S]*?\*\}/.source+"|"+/\{php\}[\s\S]*?\{\/php\}/.source+"|"+/\{(?:[^{}"']||\{(?:[^{}"']||\{(?:[^{}"']|)*\})*\})*\}/.source.replace(//g,function(){return a.source}),"g");r.hooks.add("before-tokenize",function(o){var s="{literal}",l="{/literal}",u=!1;r.languages["markup-templating"].buildPlaceholders(o,"smarty",i,function(d){return d===l&&(u=!1),u?!1:(d===s&&(u=!0),!0)})}),r.hooks.add("after-tokenize",function(o){r.languages["markup-templating"].tokenizePlaceholders(o,"smarty")})}(n)}return Zd}var Qd,Uk;function Rj(){if(Uk)return Qd;Uk=1,Qd=e,e.displayName="sml",e.aliases=["smlnj"];function e(t){(function(n){var r=/\b(?:abstype|and|andalso|as|case|datatype|do|else|end|eqtype|exception|fn|fun|functor|handle|if|in|include|infix|infixr|let|local|nonfix|of|op|open|orelse|raise|rec|sharing|sig|signature|struct|structure|then|type|val|where|while|with|withtype)\b/i;n.languages.sml={comment:/\(\*(?:[^*(]|\*(?!\))|\((?!\*)|\(\*(?:[^*(]|\*(?!\))|\((?!\*))*\*\))*\*\)/,string:{pattern:/#?"(?:[^"\\]|\\.)*"/,greedy:!0},"class-name":[{pattern:RegExp(/((?:^|[^:]):\s*)(?:\s*(?:(?:\*|->)\s*|,\s*(?:(?=)|(?!)\s+)))*/.source.replace(//g,function(){return/\s*(?:[*,]|->)/.source}).replace(//g,function(){return/(?:'[\w']*||\((?:[^()]|\([^()]*\))*\)|\{(?:[^{}]|\{[^{}]*\})*\})(?:\s+)*/.source}).replace(//g,function(){return/(?!)[a-z\d_][\w'.]*/.source}).replace(//g,function(){return r.source}),"i"),lookbehind:!0,greedy:!0,inside:null},{pattern:/((?:^|[^\w'])(?:datatype|exception|functor|signature|structure|type)\s+)[a-z_][\w'.]*/i,lookbehind:!0}],function:{pattern:/((?:^|[^\w'])fun\s+)[a-z_][\w'.]*/i,lookbehind:!0},keyword:r,variable:{pattern:/(^|[^\w'])'[\w']*/,lookbehind:!0},number:/~?\b(?:\d+(?:\.\d+)?(?:e~?\d+)?|0x[\da-f]+)\b/i,word:{pattern:/\b0w(?:\d+|x[\da-f]+)\b/i,alias:"constant"},boolean:/\b(?:false|true)\b/i,operator:/\.\.\.|:[>=:]|=>?|->|[<>]=?|[!+\-*/^#|@~]/,punctuation:/[(){}\[\].:,;]/},n.languages.sml["class-name"][0].inside=n.languages.sml,n.languages.smlnj=n.languages.sml})(t)}return Qd}var Jd,Bk;function Ij(){if(Bk)return Jd;Bk=1,Jd=e,e.displayName="solidity",e.aliases=["sol"];function e(t){t.languages.solidity=t.languages.extend("clike",{"class-name":{pattern:/(\b(?:contract|enum|interface|library|new|struct|using)\s+)(?!\d)[\w$]+/,lookbehind:!0},keyword:/\b(?:_|anonymous|as|assembly|assert|break|calldata|case|constant|constructor|continue|contract|default|delete|do|else|emit|enum|event|external|for|from|function|if|import|indexed|inherited|interface|internal|is|let|library|mapping|memory|modifier|new|payable|pragma|private|public|pure|require|returns?|revert|selfdestruct|solidity|storage|struct|suicide|switch|this|throw|using|var|view|while)\b/,operator:/=>|->|:=|=:|\*\*|\+\+|--|\|\||&&|<<=?|>>=?|[-+*/%^&|<>!=]=?|[~?]/}),t.languages.insertBefore("solidity","keyword",{builtin:/\b(?:address|bool|byte|u?int(?:8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?|string|bytes(?:[1-9]|[12]\d|3[0-2])?)\b/}),t.languages.insertBefore("solidity","number",{version:{pattern:/([<>]=?|\^)\d+\.\d+\.\d+\b/,lookbehind:!0,alias:"number"}}),t.languages.sol=t.languages.solidity}return Jd}var ep,$k;function Cj(){if($k)return ep;$k=1,ep=e,e.displayName="solutionFile",e.aliases=[];function e(t){(function(n){var r={pattern:/\{[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\}/i,alias:"constant",inside:{punctuation:/[{}]/}};n.languages["solution-file"]={comment:{pattern:/#.*/,greedy:!0},string:{pattern:/"[^"\r\n]*"|'[^'\r\n]*'/,greedy:!0,inside:{guid:r}},object:{pattern:/^([ \t]*)(?:([A-Z]\w*)\b(?=.*(?:\r\n?|\n)(?:\1[ \t].*(?:\r\n?|\n))*\1End\2(?=[ \t]*$))|End[A-Z]\w*(?=[ \t]*$))/m,lookbehind:!0,greedy:!0,alias:"keyword"},property:{pattern:/^([ \t]*)(?!\s)[^\r\n"#=()]*[^\s"#=()](?=\s*=)/m,lookbehind:!0,inside:{guid:r}},guid:r,number:/\b\d+(?:\.\d+)*\b/,boolean:/\b(?:FALSE|TRUE)\b/,operator:/=/,punctuation:/[(),]/},n.languages.sln=n.languages["solution-file"]})(t)}return ep}var tp,zk;function Nj(){if(zk)return tp;zk=1;var e=nt();tp=t,t.displayName="soy",t.aliases=[];function t(n){n.register(e),function(r){var a=/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,i=/\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b|\b0x[\dA-F]+\b/;r.languages.soy={comment:[/\/\*[\s\S]*?\*\//,{pattern:/(\s)\/\/.*/,lookbehind:!0,greedy:!0}],"command-arg":{pattern:/(\{+\/?\s*(?:alias|call|delcall|delpackage|deltemplate|namespace|template)\s+)\.?[\w.]+/,lookbehind:!0,alias:"string",inside:{punctuation:/\./}},parameter:{pattern:/(\{+\/?\s*@?param\??\s+)\.?[\w.]+/,lookbehind:!0,alias:"variable"},keyword:[{pattern:/(\{+\/?[^\S\r\n]*)(?:\\[nrt]|alias|call|case|css|default|delcall|delpackage|deltemplate|else(?:if)?|fallbackmsg|for(?:each)?|if(?:empty)?|lb|let|literal|msg|namespace|nil|@?param\??|rb|sp|switch|template|xid)/,lookbehind:!0},/\b(?:any|as|attributes|bool|css|float|html|in|int|js|list|map|null|number|string|uri)\b/],delimiter:{pattern:/^\{+\/?|\/?\}+$/,alias:"punctuation"},property:/\w+(?==)/,variable:{pattern:/\$[^\W\d]\w*(?:\??(?:\.\w+|\[[^\]]+\]))*/,inside:{string:{pattern:a,greedy:!0},number:i,punctuation:/[\[\].?]/}},string:{pattern:a,greedy:!0},function:[/\w+(?=\()/,{pattern:/(\|[^\S\r\n]*)\w+/,lookbehind:!0}],boolean:/\b(?:false|true)\b/,number:i,operator:/\?:?|<=?|>=?|==?|!=|[+*/%-]|\b(?:and|not|or)\b/,punctuation:/[{}()\[\]|.,:]/},r.hooks.add("before-tokenize",function(o){var s=/\{\{.+?\}\}|\{.+?\}|\s\/\/.*|\/\*[\s\S]*?\*\//g,l="{literal}",u="{/literal}",d=!1;r.languages["markup-templating"].buildPlaceholders(o,"soy",s,function(c){return c===u&&(d=!1),d?!1:(c===l&&(d=!0),!0)})}),r.hooks.add("after-tokenize",function(o){r.languages["markup-templating"].tokenizePlaceholders(o,"soy")})}(n)}return tp}var np,Gk;function VR(){if(Gk)return np;Gk=1,np=e,e.displayName="turtle",e.aliases=[];function e(t){t.languages.turtle={comment:{pattern:/#.*/,greedy:!0},"multiline-string":{pattern:/"""(?:(?:""?)?(?:[^"\\]|\\.))*"""|'''(?:(?:''?)?(?:[^'\\]|\\.))*'''/,greedy:!0,alias:"string",inside:{comment:/#.*/}},string:{pattern:/"(?:[^\\"\r\n]|\\.)*"|'(?:[^\\'\r\n]|\\.)*'/,greedy:!0},url:{pattern:/<(?:[^\x00-\x20<>"{}|^`\\]|\\(?:u[\da-fA-F]{4}|U[\da-fA-F]{8}))*>/,greedy:!0,inside:{punctuation:/[<>]/}},function:{pattern:/(?:(?![-.\d\xB7])[-.\w\xB7\xC0-\uFFFD]+)?:(?:(?![-.])(?:[-.:\w\xC0-\uFFFD]|%[\da-f]{2}|\\.)+)?/i,inside:{"local-name":{pattern:/([^:]*:)[\s\S]+/,lookbehind:!0},prefix:{pattern:/[\s\S]+/,inside:{punctuation:/:/}}}},number:/[+-]?\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i,punctuation:/[{}.,;()[\]]|\^\^/,boolean:/\b(?:false|true)\b/,keyword:[/(?:\ba|@prefix|@base)\b|=/,/\b(?:base|graph|prefix)\b/i],tag:{pattern:/@[a-z]+(?:-[a-z\d]+)*/i,inside:{punctuation:/@/}}},t.languages.trig=t.languages.turtle}return np}var rp,qk;function xj(){if(qk)return rp;qk=1;var e=VR();rp=t,t.displayName="sparql",t.aliases=["rq"];function t(n){n.register(e),n.languages.sparql=n.languages.extend("turtle",{boolean:/\b(?:false|true)\b/i,variable:{pattern:/[?$]\w+/,greedy:!0}}),n.languages.insertBefore("sparql","punctuation",{keyword:[/\b(?:A|ADD|ALL|AS|ASC|ASK|BNODE|BY|CLEAR|CONSTRUCT|COPY|CREATE|DATA|DEFAULT|DELETE|DESC|DESCRIBE|DISTINCT|DROP|EXISTS|FILTER|FROM|GROUP|HAVING|INSERT|INTO|LIMIT|LOAD|MINUS|MOVE|NAMED|NOT|NOW|OFFSET|OPTIONAL|ORDER|RAND|REDUCED|SELECT|SEPARATOR|SERVICE|SILENT|STRUUID|UNION|USING|UUID|VALUES|WHERE)\b/i,/\b(?:ABS|AVG|BIND|BOUND|CEIL|COALESCE|CONCAT|CONTAINS|COUNT|DATATYPE|DAY|ENCODE_FOR_URI|FLOOR|GROUP_CONCAT|HOURS|IF|IRI|isBLANK|isIRI|isLITERAL|isNUMERIC|isURI|LANG|LANGMATCHES|LCASE|MAX|MD5|MIN|MINUTES|MONTH|REGEX|REPLACE|ROUND|sameTerm|SAMPLE|SECONDS|SHA1|SHA256|SHA384|SHA512|STR|STRAFTER|STRBEFORE|STRDT|STRENDS|STRLANG|STRLEN|STRSTARTS|SUBSTR|SUM|TIMEZONE|TZ|UCASE|URI|YEAR)\b(?=\s*\()/i,/\b(?:BASE|GRAPH|PREFIX)\b/i]}),n.languages.rq=n.languages.sparql}return rp}var ap,jk;function Oj(){if(jk)return ap;jk=1,ap=e,e.displayName="splunkSpl",e.aliases=[];function e(t){t.languages["splunk-spl"]={comment:/`comment\("(?:\\.|[^\\"])*"\)`/,string:{pattern:/"(?:\\.|[^\\"])*"/,greedy:!0},keyword:/\b(?:abstract|accum|addcoltotals|addinfo|addtotals|analyzefields|anomalies|anomalousvalue|anomalydetection|append|appendcols|appendcsv|appendlookup|appendpipe|arules|associate|audit|autoregress|bin|bucket|bucketdir|chart|cluster|cofilter|collect|concurrency|contingency|convert|correlate|datamodel|dbinspect|dedup|delete|delta|diff|erex|eval|eventcount|eventstats|extract|fieldformat|fields|fieldsummary|filldown|fillnull|findtypes|folderize|foreach|format|from|gauge|gentimes|geom|geomfilter|geostats|head|highlight|history|iconify|input|inputcsv|inputlookup|iplocation|join|kmeans|kv|kvform|loadjob|localize|localop|lookup|makecontinuous|makemv|makeresults|map|mcollect|metadata|metasearch|meventcollect|mstats|multikv|multisearch|mvcombine|mvexpand|nomv|outlier|outputcsv|outputlookup|outputtext|overlap|pivot|predict|rangemap|rare|regex|relevancy|reltime|rename|replace|rest|return|reverse|rex|rtorder|run|savedsearch|script|scrub|search|searchtxn|selfjoin|sendemail|set|setfields|sichart|sirare|sistats|sitimechart|sitop|sort|spath|stats|strcat|streamstats|table|tags|tail|timechart|timewrap|top|transaction|transpose|trendline|tscollect|tstats|typeahead|typelearner|typer|union|uniq|untable|where|x11|xmlkv|xmlunescape|xpath|xyseries)\b/i,"operator-word":{pattern:/\b(?:and|as|by|not|or|xor)\b/i,alias:"operator"},function:/\b\w+(?=\s*\()/,property:/\b\w+(?=\s*=(?!=))/,date:{pattern:/\b\d{1,2}\/\d{1,2}\/\d{1,4}(?:(?::\d{1,2}){3})?\b/,alias:"number"},number:/\b\d+(?:\.\d+)?\b/,boolean:/\b(?:f|false|t|true)\b/i,operator:/[<>=]=?|[-+*/%|]/,punctuation:/[()[\],]/}}return ap}var ip,Hk;function Lj(){if(Hk)return ip;Hk=1,ip=e,e.displayName="sqf",e.aliases=[];function e(t){t.languages.sqf=t.languages.extend("clike",{string:{pattern:/"(?:(?:"")?[^"])*"(?!")|'(?:[^'])*'/,greedy:!0},keyword:/\b(?:breakOut|breakTo|call|case|catch|default|do|echo|else|execFSM|execVM|exitWith|for|forEach|forEachMember|forEachMemberAgent|forEachMemberTeam|from|goto|if|nil|preprocessFile|preprocessFileLineNumbers|private|scopeName|spawn|step|switch|then|throw|to|try|while|with)\b/i,boolean:/\b(?:false|true)\b/i,function:/\b(?:abs|accTime|acos|action|actionIDs|actionKeys|actionKeysImages|actionKeysNames|actionKeysNamesArray|actionName|actionParams|activateAddons|activatedAddons|activateKey|add3DENConnection|add3DENEventHandler|add3DENLayer|addAction|addBackpack|addBackpackCargo|addBackpackCargoGlobal|addBackpackGlobal|addCamShake|addCuratorAddons|addCuratorCameraArea|addCuratorEditableObjects|addCuratorEditingArea|addCuratorPoints|addEditorObject|addEventHandler|addForce|addForceGeneratorRTD|addGoggles|addGroupIcon|addHandgunItem|addHeadgear|addItem|addItemCargo|addItemCargoGlobal|addItemPool|addItemToBackpack|addItemToUniform|addItemToVest|addLiveStats|addMagazine|addMagazineAmmoCargo|addMagazineCargo|addMagazineCargoGlobal|addMagazineGlobal|addMagazinePool|addMagazines|addMagazineTurret|addMenu|addMenuItem|addMissionEventHandler|addMPEventHandler|addMusicEventHandler|addOwnedMine|addPlayerScores|addPrimaryWeaponItem|addPublicVariableEventHandler|addRating|addResources|addScore|addScoreSide|addSecondaryWeaponItem|addSwitchableUnit|addTeamMember|addToRemainsCollector|addTorque|addUniform|addVehicle|addVest|addWaypoint|addWeapon|addWeaponCargo|addWeaponCargoGlobal|addWeaponGlobal|addWeaponItem|addWeaponPool|addWeaponTurret|admin|agent|agents|AGLToASL|aimedAtTarget|aimPos|airDensityCurveRTD|airDensityRTD|airplaneThrottle|airportSide|AISFinishHeal|alive|all3DENEntities|allAirports|allControls|allCurators|allCutLayers|allDead|allDeadMen|allDisplays|allGroups|allMapMarkers|allMines|allMissionObjects|allow3DMode|allowCrewInImmobile|allowCuratorLogicIgnoreAreas|allowDamage|allowDammage|allowFileOperations|allowFleeing|allowGetIn|allowSprint|allPlayers|allSimpleObjects|allSites|allTurrets|allUnits|allUnitsUAV|allVariables|ammo|ammoOnPylon|animate|animateBay|animateDoor|animatePylon|animateSource|animationNames|animationPhase|animationSourcePhase|animationState|append|apply|armoryPoints|arrayIntersect|asin|ASLToAGL|ASLToATL|assert|assignAsCargo|assignAsCargoIndex|assignAsCommander|assignAsDriver|assignAsGunner|assignAsTurret|assignCurator|assignedCargo|assignedCommander|assignedDriver|assignedGunner|assignedItems|assignedTarget|assignedTeam|assignedVehicle|assignedVehicleRole|assignItem|assignTeam|assignToAirport|atan|atan2|atg|ATLToASL|attachedObject|attachedObjects|attachedTo|attachObject|attachTo|attackEnabled|backpack|backpackCargo|backpackContainer|backpackItems|backpackMagazines|backpackSpaceFor|behaviour|benchmark|binocular|blufor|boundingBox|boundingBoxReal|boundingCenter|briefingName|buildingExit|buildingPos|buldozer_EnableRoadDiag|buldozer_IsEnabledRoadDiag|buldozer_LoadNewRoads|buldozer_reloadOperMap|buttonAction|buttonSetAction|cadetMode|callExtension|camCommand|camCommit|camCommitPrepared|camCommitted|camConstuctionSetParams|camCreate|camDestroy|cameraEffect|cameraEffectEnableHUD|cameraInterest|cameraOn|cameraView|campaignConfigFile|camPreload|camPreloaded|camPrepareBank|camPrepareDir|camPrepareDive|camPrepareFocus|camPrepareFov|camPrepareFovRange|camPreparePos|camPrepareRelPos|camPrepareTarget|camSetBank|camSetDir|camSetDive|camSetFocus|camSetFov|camSetFovRange|camSetPos|camSetRelPos|camSetTarget|camTarget|camUseNVG|canAdd|canAddItemToBackpack|canAddItemToUniform|canAddItemToVest|cancelSimpleTaskDestination|canFire|canMove|canSlingLoad|canStand|canSuspend|canTriggerDynamicSimulation|canUnloadInCombat|canVehicleCargo|captive|captiveNum|cbChecked|cbSetChecked|ceil|channelEnabled|cheatsEnabled|checkAIFeature|checkVisibility|civilian|className|clear3DENAttribute|clear3DENInventory|clearAllItemsFromBackpack|clearBackpackCargo|clearBackpackCargoGlobal|clearForcesRTD|clearGroupIcons|clearItemCargo|clearItemCargoGlobal|clearItemPool|clearMagazineCargo|clearMagazineCargoGlobal|clearMagazinePool|clearOverlay|clearRadio|clearVehicleInit|clearWeaponCargo|clearWeaponCargoGlobal|clearWeaponPool|clientOwner|closeDialog|closeDisplay|closeOverlay|collapseObjectTree|collect3DENHistory|collectiveRTD|combatMode|commandArtilleryFire|commandChat|commander|commandFire|commandFollow|commandFSM|commandGetOut|commandingMenu|commandMove|commandRadio|commandStop|commandSuppressiveFire|commandTarget|commandWatch|comment|commitOverlay|compile|compileFinal|completedFSM|composeText|configClasses|configFile|configHierarchy|configName|configNull|configProperties|configSourceAddonList|configSourceMod|configSourceModList|confirmSensorTarget|connectTerminalToUAV|controlNull|controlsGroupCtrl|copyFromClipboard|copyToClipboard|copyWaypoints|cos|count|countEnemy|countFriendly|countSide|countType|countUnknown|create3DENComposition|create3DENEntity|createAgent|createCenter|createDialog|createDiaryLink|createDiaryRecord|createDiarySubject|createDisplay|createGearDialog|createGroup|createGuardedPoint|createLocation|createMarker|createMarkerLocal|createMenu|createMine|createMissionDisplay|createMPCampaignDisplay|createSimpleObject|createSimpleTask|createSite|createSoundSource|createTask|createTeam|createTrigger|createUnit|createVehicle|createVehicleCrew|createVehicleLocal|crew|ctAddHeader|ctAddRow|ctClear|ctCurSel|ctData|ctFindHeaderRows|ctFindRowHeader|ctHeaderControls|ctHeaderCount|ctRemoveHeaders|ctRemoveRows|ctrlActivate|ctrlAddEventHandler|ctrlAngle|ctrlAutoScrollDelay|ctrlAutoScrollRewind|ctrlAutoScrollSpeed|ctrlChecked|ctrlClassName|ctrlCommit|ctrlCommitted|ctrlCreate|ctrlDelete|ctrlEnable|ctrlEnabled|ctrlFade|ctrlHTMLLoaded|ctrlIDC|ctrlIDD|ctrlMapAnimAdd|ctrlMapAnimClear|ctrlMapAnimCommit|ctrlMapAnimDone|ctrlMapCursor|ctrlMapMouseOver|ctrlMapScale|ctrlMapScreenToWorld|ctrlMapWorldToScreen|ctrlModel|ctrlModelDirAndUp|ctrlModelScale|ctrlParent|ctrlParentControlsGroup|ctrlPosition|ctrlRemoveAllEventHandlers|ctrlRemoveEventHandler|ctrlScale|ctrlSetActiveColor|ctrlSetAngle|ctrlSetAutoScrollDelay|ctrlSetAutoScrollRewind|ctrlSetAutoScrollSpeed|ctrlSetBackgroundColor|ctrlSetChecked|ctrlSetDisabledColor|ctrlSetEventHandler|ctrlSetFade|ctrlSetFocus|ctrlSetFont|ctrlSetFontH1|ctrlSetFontH1B|ctrlSetFontH2|ctrlSetFontH2B|ctrlSetFontH3|ctrlSetFontH3B|ctrlSetFontH4|ctrlSetFontH4B|ctrlSetFontH5|ctrlSetFontH5B|ctrlSetFontH6|ctrlSetFontH6B|ctrlSetFontHeight|ctrlSetFontHeightH1|ctrlSetFontHeightH2|ctrlSetFontHeightH3|ctrlSetFontHeightH4|ctrlSetFontHeightH5|ctrlSetFontHeightH6|ctrlSetFontHeightSecondary|ctrlSetFontP|ctrlSetFontPB|ctrlSetFontSecondary|ctrlSetForegroundColor|ctrlSetModel|ctrlSetModelDirAndUp|ctrlSetModelScale|ctrlSetPixelPrecision|ctrlSetPosition|ctrlSetScale|ctrlSetStructuredText|ctrlSetText|ctrlSetTextColor|ctrlSetTextColorSecondary|ctrlSetTextSecondary|ctrlSetTooltip|ctrlSetTooltipColorBox|ctrlSetTooltipColorShade|ctrlSetTooltipColorText|ctrlShow|ctrlShown|ctrlText|ctrlTextHeight|ctrlTextSecondary|ctrlTextWidth|ctrlType|ctrlVisible|ctRowControls|ctRowCount|ctSetCurSel|ctSetData|ctSetHeaderTemplate|ctSetRowTemplate|ctSetValue|ctValue|curatorAddons|curatorCamera|curatorCameraArea|curatorCameraAreaCeiling|curatorCoef|curatorEditableObjects|curatorEditingArea|curatorEditingAreaType|curatorMouseOver|curatorPoints|curatorRegisteredObjects|curatorSelected|curatorWaypointCost|current3DENOperation|currentChannel|currentCommand|currentMagazine|currentMagazineDetail|currentMagazineDetailTurret|currentMagazineTurret|currentMuzzle|currentNamespace|currentTask|currentTasks|currentThrowable|currentVisionMode|currentWaypoint|currentWeapon|currentWeaponMode|currentWeaponTurret|currentZeroing|cursorObject|cursorTarget|customChat|customRadio|cutFadeOut|cutObj|cutRsc|cutText|damage|date|dateToNumber|daytime|deActivateKey|debriefingText|debugFSM|debugLog|deg|delete3DENEntities|deleteAt|deleteCenter|deleteCollection|deleteEditorObject|deleteGroup|deleteGroupWhenEmpty|deleteIdentity|deleteLocation|deleteMarker|deleteMarkerLocal|deleteRange|deleteResources|deleteSite|deleteStatus|deleteTeam|deleteVehicle|deleteVehicleCrew|deleteWaypoint|detach|detectedMines|diag_activeMissionFSMs|diag_activeScripts|diag_activeSQFScripts|diag_activeSQSScripts|diag_captureFrame|diag_captureFrameToFile|diag_captureSlowFrame|diag_codePerformance|diag_drawMode|diag_dynamicSimulationEnd|diag_enable|diag_enabled|diag_fps|diag_fpsMin|diag_frameNo|diag_lightNewLoad|diag_list|diag_log|diag_logSlowFrame|diag_mergeConfigFile|diag_recordTurretLimits|diag_setLightNew|diag_tickTime|diag_toggle|dialog|diarySubjectExists|didJIP|didJIPOwner|difficulty|difficultyEnabled|difficultyEnabledRTD|difficultyOption|direction|directSay|disableAI|disableCollisionWith|disableConversation|disableDebriefingStats|disableMapIndicators|disableNVGEquipment|disableRemoteSensors|disableSerialization|disableTIEquipment|disableUAVConnectability|disableUserInput|displayAddEventHandler|displayCtrl|displayNull|displayParent|displayRemoveAllEventHandlers|displayRemoveEventHandler|displaySetEventHandler|dissolveTeam|distance|distance2D|distanceSqr|distributionRegion|do3DENAction|doArtilleryFire|doFire|doFollow|doFSM|doGetOut|doMove|doorPhase|doStop|doSuppressiveFire|doTarget|doWatch|drawArrow|drawEllipse|drawIcon|drawIcon3D|drawLine|drawLine3D|drawLink|drawLocation|drawPolygon|drawRectangle|drawTriangle|driver|drop|dynamicSimulationDistance|dynamicSimulationDistanceCoef|dynamicSimulationEnabled|dynamicSimulationSystemEnabled|east|edit3DENMissionAttributes|editObject|editorSetEventHandler|effectiveCommander|emptyPositions|enableAI|enableAIFeature|enableAimPrecision|enableAttack|enableAudioFeature|enableAutoStartUpRTD|enableAutoTrimRTD|enableCamShake|enableCaustics|enableChannel|enableCollisionWith|enableCopilot|enableDebriefingStats|enableDiagLegend|enableDynamicSimulation|enableDynamicSimulationSystem|enableEndDialog|enableEngineArtillery|enableEnvironment|enableFatigue|enableGunLights|enableInfoPanelComponent|enableIRLasers|enableMimics|enablePersonTurret|enableRadio|enableReload|enableRopeAttach|enableSatNormalOnDetail|enableSaving|enableSentences|enableSimulation|enableSimulationGlobal|enableStamina|enableStressDamage|enableTeamSwitch|enableTraffic|enableUAVConnectability|enableUAVWaypoints|enableVehicleCargo|enableVehicleSensor|enableWeaponDisassembly|endl|endLoadingScreen|endMission|engineOn|enginesIsOnRTD|enginesPowerRTD|enginesRpmRTD|enginesTorqueRTD|entities|environmentEnabled|estimatedEndServerTime|estimatedTimeLeft|evalObjectArgument|everyBackpack|everyContainer|exec|execEditorScript|exp|expectedDestination|exportJIPMessages|eyeDirection|eyePos|face|faction|fadeMusic|fadeRadio|fadeSound|fadeSpeech|failMission|fillWeaponsFromPool|find|findCover|findDisplay|findEditorObject|findEmptyPosition|findEmptyPositionReady|findIf|findNearestEnemy|finishMissionInit|finite|fire|fireAtTarget|firstBackpack|flag|flagAnimationPhase|flagOwner|flagSide|flagTexture|fleeing|floor|flyInHeight|flyInHeightASL|fog|fogForecast|fogParams|forceAddUniform|forceAtPositionRTD|forcedMap|forceEnd|forceFlagTexture|forceFollowRoad|forceGeneratorRTD|forceMap|forceRespawn|forceSpeed|forceWalk|forceWeaponFire|forceWeatherChange|forgetTarget|format|formation|formationDirection|formationLeader|formationMembers|formationPosition|formationTask|formatText|formLeader|freeLook|fromEditor|fuel|fullCrew|gearIDCAmmoCount|gearSlotAmmoCount|gearSlotData|get3DENActionState|get3DENAttribute|get3DENCamera|get3DENConnections|get3DENEntity|get3DENEntityID|get3DENGrid|get3DENIconsVisible|get3DENLayerEntities|get3DENLinesVisible|get3DENMissionAttribute|get3DENMouseOver|get3DENSelected|getAimingCoef|getAllEnvSoundControllers|getAllHitPointsDamage|getAllOwnedMines|getAllSoundControllers|getAmmoCargo|getAnimAimPrecision|getAnimSpeedCoef|getArray|getArtilleryAmmo|getArtilleryComputerSettings|getArtilleryETA|getAssignedCuratorLogic|getAssignedCuratorUnit|getBackpackCargo|getBleedingRemaining|getBurningValue|getCameraViewDirection|getCargoIndex|getCenterOfMass|getClientState|getClientStateNumber|getCompatiblePylonMagazines|getConnectedUAV|getContainerMaxLoad|getCursorObjectParams|getCustomAimCoef|getDammage|getDescription|getDir|getDirVisual|getDLCAssetsUsage|getDLCAssetsUsageByName|getDLCs|getDLCUsageTime|getEditorCamera|getEditorMode|getEditorObjectScope|getElevationOffset|getEngineTargetRpmRTD|getEnvSoundController|getFatigue|getFieldManualStartPage|getForcedFlagTexture|getFriend|getFSMVariable|getFuelCargo|getGroupIcon|getGroupIconParams|getGroupIcons|getHideFrom|getHit|getHitIndex|getHitPointDamage|getItemCargo|getMagazineCargo|getMarkerColor|getMarkerPos|getMarkerSize|getMarkerType|getMass|getMissionConfig|getMissionConfigValue|getMissionDLCs|getMissionLayerEntities|getMissionLayers|getModelInfo|getMousePosition|getMusicPlayedTime|getNumber|getObjectArgument|getObjectChildren|getObjectDLC|getObjectMaterials|getObjectProxy|getObjectTextures|getObjectType|getObjectViewDistance|getOxygenRemaining|getPersonUsedDLCs|getPilotCameraDirection|getPilotCameraPosition|getPilotCameraRotation|getPilotCameraTarget|getPlateNumber|getPlayerChannel|getPlayerScores|getPlayerUID|getPlayerUIDOld|getPos|getPosASL|getPosASLVisual|getPosASLW|getPosATL|getPosATLVisual|getPosVisual|getPosWorld|getPylonMagazines|getRelDir|getRelPos|getRemoteSensorsDisabled|getRepairCargo|getResolution|getRotorBrakeRTD|getShadowDistance|getShotParents|getSlingLoad|getSoundController|getSoundControllerResult|getSpeed|getStamina|getStatValue|getSuppression|getTerrainGrid|getTerrainHeightASL|getText|getTotalDLCUsageTime|getTrimOffsetRTD|getUnitLoadout|getUnitTrait|getUserMFDText|getUserMFDValue|getVariable|getVehicleCargo|getWeaponCargo|getWeaponSway|getWingsOrientationRTD|getWingsPositionRTD|getWPPos|glanceAt|globalChat|globalRadio|goggles|group|groupChat|groupFromNetId|groupIconSelectable|groupIconsVisible|groupId|groupOwner|groupRadio|groupSelectedUnits|groupSelectUnit|grpNull|gunner|gusts|halt|handgunItems|handgunMagazine|handgunWeapon|handsHit|hasInterface|hasPilotCamera|hasWeapon|hcAllGroups|hcGroupParams|hcLeader|hcRemoveAllGroups|hcRemoveGroup|hcSelected|hcSelectGroup|hcSetGroup|hcShowBar|hcShownBar|headgear|hideBody|hideObject|hideObjectGlobal|hideSelection|hint|hintC|hintCadet|hintSilent|hmd|hostMission|htmlLoad|HUDMovementLevels|humidity|image|importAllGroups|importance|in|inArea|inAreaArray|incapacitatedState|independent|inflame|inflamed|infoPanel|infoPanelComponentEnabled|infoPanelComponents|infoPanels|inGameUISetEventHandler|inheritsFrom|initAmbientLife|inPolygon|inputAction|inRangeOfArtillery|insertEditorObject|intersect|is3DEN|is3DENMultiplayer|isAbleToBreathe|isAgent|isAimPrecisionEnabled|isArray|isAutoHoverOn|isAutonomous|isAutoStartUpEnabledRTD|isAutotest|isAutoTrimOnRTD|isBleeding|isBurning|isClass|isCollisionLightOn|isCopilotEnabled|isDamageAllowed|isDedicated|isDLCAvailable|isEngineOn|isEqualTo|isEqualType|isEqualTypeAll|isEqualTypeAny|isEqualTypeArray|isEqualTypeParams|isFilePatchingEnabled|isFlashlightOn|isFlatEmpty|isForcedWalk|isFormationLeader|isGroupDeletedWhenEmpty|isHidden|isInRemainsCollector|isInstructorFigureEnabled|isIRLaserOn|isKeyActive|isKindOf|isLaserOn|isLightOn|isLocalized|isManualFire|isMarkedForCollection|isMultiplayer|isMultiplayerSolo|isNil|isNull|isNumber|isObjectHidden|isObjectRTD|isOnRoad|isPipEnabled|isPlayer|isRealTime|isRemoteExecuted|isRemoteExecutedJIP|isServer|isShowing3DIcons|isSimpleObject|isSprintAllowed|isStaminaEnabled|isSteamMission|isStreamFriendlyUIEnabled|isStressDamageEnabled|isText|isTouchingGround|isTurnedOut|isTutHintsEnabled|isUAVConnectable|isUAVConnected|isUIContext|isUniformAllowed|isVehicleCargo|isVehicleRadarOn|isVehicleSensorEnabled|isWalking|isWeaponDeployed|isWeaponRested|itemCargo|items|itemsWithMagazines|join|joinAs|joinAsSilent|joinSilent|joinString|kbAddDatabase|kbAddDatabaseTargets|kbAddTopic|kbHasTopic|kbReact|kbRemoveTopic|kbTell|kbWasSaid|keyImage|keyName|knowsAbout|land|landAt|landResult|language|laserTarget|lbAdd|lbClear|lbColor|lbColorRight|lbCurSel|lbData|lbDelete|lbIsSelected|lbPicture|lbPictureRight|lbSelection|lbSetColor|lbSetColorRight|lbSetCurSel|lbSetData|lbSetPicture|lbSetPictureColor|lbSetPictureColorDisabled|lbSetPictureColorSelected|lbSetPictureRight|lbSetPictureRightColor|lbSetPictureRightColorDisabled|lbSetPictureRightColorSelected|lbSetSelectColor|lbSetSelectColorRight|lbSetSelected|lbSetText|lbSetTextRight|lbSetTooltip|lbSetValue|lbSize|lbSort|lbSortByValue|lbText|lbTextRight|lbValue|leader|leaderboardDeInit|leaderboardGetRows|leaderboardInit|leaderboardRequestRowsFriends|leaderboardRequestRowsGlobal|leaderboardRequestRowsGlobalAroundUser|leaderboardsRequestUploadScore|leaderboardsRequestUploadScoreKeepBest|leaderboardState|leaveVehicle|libraryCredits|libraryDisclaimers|lifeState|lightAttachObject|lightDetachObject|lightIsOn|lightnings|limitSpeed|linearConversion|lineBreak|lineIntersects|lineIntersectsObjs|lineIntersectsSurfaces|lineIntersectsWith|linkItem|list|listObjects|listRemoteTargets|listVehicleSensors|ln|lnbAddArray|lnbAddColumn|lnbAddRow|lnbClear|lnbColor|lnbColorRight|lnbCurSelRow|lnbData|lnbDeleteColumn|lnbDeleteRow|lnbGetColumnsPosition|lnbPicture|lnbPictureRight|lnbSetColor|lnbSetColorRight|lnbSetColumnsPos|lnbSetCurSelRow|lnbSetData|lnbSetPicture|lnbSetPictureColor|lnbSetPictureColorRight|lnbSetPictureColorSelected|lnbSetPictureColorSelectedRight|lnbSetPictureRight|lnbSetText|lnbSetTextRight|lnbSetValue|lnbSize|lnbSort|lnbSortByValue|lnbText|lnbTextRight|lnbValue|load|loadAbs|loadBackpack|loadFile|loadGame|loadIdentity|loadMagazine|loadOverlay|loadStatus|loadUniform|loadVest|local|localize|locationNull|locationPosition|lock|lockCameraTo|lockCargo|lockDriver|locked|lockedCargo|lockedDriver|lockedTurret|lockIdentity|lockTurret|lockWP|log|logEntities|logNetwork|logNetworkTerminate|lookAt|lookAtPos|magazineCargo|magazines|magazinesAllTurrets|magazinesAmmo|magazinesAmmoCargo|magazinesAmmoFull|magazinesDetail|magazinesDetailBackpack|magazinesDetailUniform|magazinesDetailVest|magazinesTurret|magazineTurretAmmo|mapAnimAdd|mapAnimClear|mapAnimCommit|mapAnimDone|mapCenterOnCamera|mapGridPosition|markAsFinishedOnSteam|markerAlpha|markerBrush|markerColor|markerDir|markerPos|markerShape|markerSize|markerText|markerType|max|members|menuAction|menuAdd|menuChecked|menuClear|menuCollapse|menuData|menuDelete|menuEnable|menuEnabled|menuExpand|menuHover|menuPicture|menuSetAction|menuSetCheck|menuSetData|menuSetPicture|menuSetValue|menuShortcut|menuShortcutText|menuSize|menuSort|menuText|menuURL|menuValue|min|mineActive|mineDetectedBy|missionConfigFile|missionDifficulty|missionName|missionNamespace|missionStart|missionVersion|modelToWorld|modelToWorldVisual|modelToWorldVisualWorld|modelToWorldWorld|modParams|moonIntensity|moonPhase|morale|move|move3DENCamera|moveInAny|moveInCargo|moveInCommander|moveInDriver|moveInGunner|moveInTurret|moveObjectToEnd|moveOut|moveTime|moveTo|moveToCompleted|moveToFailed|musicVolume|name|nameSound|nearEntities|nearestBuilding|nearestLocation|nearestLocations|nearestLocationWithDubbing|nearestObject|nearestObjects|nearestTerrainObjects|nearObjects|nearObjectsReady|nearRoads|nearSupplies|nearTargets|needReload|netId|netObjNull|newOverlay|nextMenuItemIndex|nextWeatherChange|nMenuItems|numberOfEnginesRTD|numberToDate|objectCurators|objectFromNetId|objectParent|objNull|objStatus|onBriefingGear|onBriefingGroup|onBriefingNotes|onBriefingPlan|onBriefingTeamSwitch|onCommandModeChanged|onDoubleClick|onEachFrame|onGroupIconClick|onGroupIconOverEnter|onGroupIconOverLeave|onHCGroupSelectionChanged|onMapSingleClick|onPlayerConnected|onPlayerDisconnected|onPreloadFinished|onPreloadStarted|onShowNewObject|onTeamSwitch|openCuratorInterface|openDLCPage|openDSInterface|openMap|openSteamApp|openYoutubeVideo|opfor|orderGetIn|overcast|overcastForecast|owner|param|params|parseNumber|parseSimpleArray|parseText|parsingNamespace|particlesQuality|pi|pickWeaponPool|pitch|pixelGrid|pixelGridBase|pixelGridNoUIScale|pixelH|pixelW|playableSlotsNumber|playableUnits|playAction|playActionNow|player|playerRespawnTime|playerSide|playersNumber|playGesture|playMission|playMove|playMoveNow|playMusic|playScriptedMission|playSound|playSound3D|position|positionCameraToWorld|posScreenToWorld|posWorldToScreen|ppEffectAdjust|ppEffectCommit|ppEffectCommitted|ppEffectCreate|ppEffectDestroy|ppEffectEnable|ppEffectEnabled|ppEffectForceInNVG|precision|preloadCamera|preloadObject|preloadSound|preloadTitleObj|preloadTitleRsc|primaryWeapon|primaryWeaponItems|primaryWeaponMagazine|priority|processDiaryLink|processInitCommands|productVersion|profileName|profileNamespace|profileNameSteam|progressLoadingScreen|progressPosition|progressSetPosition|publicVariable|publicVariableClient|publicVariableServer|pushBack|pushBackUnique|putWeaponPool|queryItemsPool|queryMagazinePool|queryWeaponPool|rad|radioChannelAdd|radioChannelCreate|radioChannelRemove|radioChannelSetCallSign|radioChannelSetLabel|radioVolume|rain|rainbow|random|rank|rankId|rating|rectangular|registeredTasks|registerTask|reload|reloadEnabled|remoteControl|remoteExec|remoteExecCall|remoteExecutedOwner|remove3DENConnection|remove3DENEventHandler|remove3DENLayer|removeAction|removeAll3DENEventHandlers|removeAllActions|removeAllAssignedItems|removeAllContainers|removeAllCuratorAddons|removeAllCuratorCameraAreas|removeAllCuratorEditingAreas|removeAllEventHandlers|removeAllHandgunItems|removeAllItems|removeAllItemsWithMagazines|removeAllMissionEventHandlers|removeAllMPEventHandlers|removeAllMusicEventHandlers|removeAllOwnedMines|removeAllPrimaryWeaponItems|removeAllWeapons|removeBackpack|removeBackpackGlobal|removeCuratorAddons|removeCuratorCameraArea|removeCuratorEditableObjects|removeCuratorEditingArea|removeDrawIcon|removeDrawLinks|removeEventHandler|removeFromRemainsCollector|removeGoggles|removeGroupIcon|removeHandgunItem|removeHeadgear|removeItem|removeItemFromBackpack|removeItemFromUniform|removeItemFromVest|removeItems|removeMagazine|removeMagazineGlobal|removeMagazines|removeMagazinesTurret|removeMagazineTurret|removeMenuItem|removeMissionEventHandler|removeMPEventHandler|removeMusicEventHandler|removeOwnedMine|removePrimaryWeaponItem|removeSecondaryWeaponItem|removeSimpleTask|removeSwitchableUnit|removeTeamMember|removeUniform|removeVest|removeWeapon|removeWeaponAttachmentCargo|removeWeaponCargo|removeWeaponGlobal|removeWeaponTurret|reportRemoteTarget|requiredVersion|resetCamShake|resetSubgroupDirection|resistance|resize|resources|respawnVehicle|restartEditorCamera|reveal|revealMine|reverse|reversedMouseY|roadAt|roadsConnectedTo|roleDescription|ropeAttachedObjects|ropeAttachedTo|ropeAttachEnabled|ropeAttachTo|ropeCreate|ropeCut|ropeDestroy|ropeDetach|ropeEndPosition|ropeLength|ropes|ropeUnwind|ropeUnwound|rotorsForcesRTD|rotorsRpmRTD|round|runInitScript|safeZoneH|safeZoneW|safeZoneWAbs|safeZoneX|safeZoneXAbs|safeZoneY|save3DENInventory|saveGame|saveIdentity|saveJoysticks|saveOverlay|saveProfileNamespace|saveStatus|saveVar|savingEnabled|say|say2D|say3D|score|scoreSide|screenshot|screenToWorld|scriptDone|scriptName|scriptNull|scudState|secondaryWeapon|secondaryWeaponItems|secondaryWeaponMagazine|select|selectBestPlaces|selectDiarySubject|selectedEditorObjects|selectEditorObject|selectionNames|selectionPosition|selectLeader|selectMax|selectMin|selectNoPlayer|selectPlayer|selectRandom|selectRandomWeighted|selectWeapon|selectWeaponTurret|sendAUMessage|sendSimpleCommand|sendTask|sendTaskResult|sendUDPMessage|serverCommand|serverCommandAvailable|serverCommandExecutable|serverName|serverTime|set|set3DENAttribute|set3DENAttributes|set3DENGrid|set3DENIconsVisible|set3DENLayer|set3DENLinesVisible|set3DENLogicType|set3DENMissionAttribute|set3DENMissionAttributes|set3DENModelsVisible|set3DENObjectType|set3DENSelected|setAccTime|setActualCollectiveRTD|setAirplaneThrottle|setAirportSide|setAmmo|setAmmoCargo|setAmmoOnPylon|setAnimSpeedCoef|setAperture|setApertureNew|setArmoryPoints|setAttributes|setAutonomous|setBehaviour|setBleedingRemaining|setBrakesRTD|setCameraInterest|setCamShakeDefParams|setCamShakeParams|setCamUseTI|setCaptive|setCenterOfMass|setCollisionLight|setCombatMode|setCompassOscillation|setConvoySeparation|setCuratorCameraAreaCeiling|setCuratorCoef|setCuratorEditingAreaType|setCuratorWaypointCost|setCurrentChannel|setCurrentTask|setCurrentWaypoint|setCustomAimCoef|setCustomWeightRTD|setDamage|setDammage|setDate|setDebriefingText|setDefaultCamera|setDestination|setDetailMapBlendPars|setDir|setDirection|setDrawIcon|setDriveOnPath|setDropInterval|setDynamicSimulationDistance|setDynamicSimulationDistanceCoef|setEditorMode|setEditorObjectScope|setEffectCondition|setEngineRpmRTD|setFace|setFaceAnimation|setFatigue|setFeatureType|setFlagAnimationPhase|setFlagOwner|setFlagSide|setFlagTexture|setFog|setForceGeneratorRTD|setFormation|setFormationTask|setFormDir|setFriend|setFromEditor|setFSMVariable|setFuel|setFuelCargo|setGroupIcon|setGroupIconParams|setGroupIconsSelectable|setGroupIconsVisible|setGroupId|setGroupIdGlobal|setGroupOwner|setGusts|setHideBehind|setHit|setHitIndex|setHitPointDamage|setHorizonParallaxCoef|setHUDMovementLevels|setIdentity|setImportance|setInfoPanel|setLeader|setLightAmbient|setLightAttenuation|setLightBrightness|setLightColor|setLightDayLight|setLightFlareMaxDistance|setLightFlareSize|setLightIntensity|setLightnings|setLightUseFlare|setLocalWindParams|setMagazineTurretAmmo|setMarkerAlpha|setMarkerAlphaLocal|setMarkerBrush|setMarkerBrushLocal|setMarkerColor|setMarkerColorLocal|setMarkerDir|setMarkerDirLocal|setMarkerPos|setMarkerPosLocal|setMarkerShape|setMarkerShapeLocal|setMarkerSize|setMarkerSizeLocal|setMarkerText|setMarkerTextLocal|setMarkerType|setMarkerTypeLocal|setMass|setMimic|setMousePosition|setMusicEffect|setMusicEventHandler|setName|setNameSound|setObjectArguments|setObjectMaterial|setObjectMaterialGlobal|setObjectProxy|setObjectTexture|setObjectTextureGlobal|setObjectViewDistance|setOvercast|setOwner|setOxygenRemaining|setParticleCircle|setParticleClass|setParticleFire|setParticleParams|setParticleRandom|setPilotCameraDirection|setPilotCameraRotation|setPilotCameraTarget|setPilotLight|setPiPEffect|setPitch|setPlateNumber|setPlayable|setPlayerRespawnTime|setPos|setPosASL|setPosASL2|setPosASLW|setPosATL|setPosition|setPosWorld|setPylonLoadOut|setPylonsPriority|setRadioMsg|setRain|setRainbow|setRandomLip|setRank|setRectangular|setRepairCargo|setRotorBrakeRTD|setShadowDistance|setShotParents|setSide|setSimpleTaskAlwaysVisible|setSimpleTaskCustomData|setSimpleTaskDescription|setSimpleTaskDestination|setSimpleTaskTarget|setSimpleTaskType|setSimulWeatherLayers|setSize|setSkill|setSlingLoad|setSoundEffect|setSpeaker|setSpeech|setSpeedMode|setStamina|setStaminaScheme|setStatValue|setSuppression|setSystemOfUnits|setTargetAge|setTaskMarkerOffset|setTaskResult|setTaskState|setTerrainGrid|setText|setTimeMultiplier|setTitleEffect|setToneMapping|setToneMappingParams|setTrafficDensity|setTrafficDistance|setTrafficGap|setTrafficSpeed|setTriggerActivation|setTriggerArea|setTriggerStatements|setTriggerText|setTriggerTimeout|setTriggerType|setType|setUnconscious|setUnitAbility|setUnitLoadout|setUnitPos|setUnitPosWeak|setUnitRank|setUnitRecoilCoefficient|setUnitTrait|setUnloadInCombat|setUserActionText|setUserMFDText|setUserMFDValue|setVariable|setVectorDir|setVectorDirAndUp|setVectorUp|setVehicleAmmo|setVehicleAmmoDef|setVehicleArmor|setVehicleCargo|setVehicleId|setVehicleInit|setVehicleLock|setVehiclePosition|setVehicleRadar|setVehicleReceiveRemoteTargets|setVehicleReportOwnPosition|setVehicleReportRemoteTargets|setVehicleTIPars|setVehicleVarName|setVelocity|setVelocityModelSpace|setVelocityTransformation|setViewDistance|setVisibleIfTreeCollapsed|setWantedRpmRTD|setWaves|setWaypointBehaviour|setWaypointCombatMode|setWaypointCompletionRadius|setWaypointDescription|setWaypointForceBehaviour|setWaypointFormation|setWaypointHousePosition|setWaypointLoiterRadius|setWaypointLoiterType|setWaypointName|setWaypointPosition|setWaypointScript|setWaypointSpeed|setWaypointStatements|setWaypointTimeout|setWaypointType|setWaypointVisible|setWeaponReloadingTime|setWind|setWindDir|setWindForce|setWindStr|setWingForceScaleRTD|setWPPos|show3DIcons|showChat|showCinemaBorder|showCommandingMenu|showCompass|showCuratorCompass|showGPS|showHUD|showLegend|showMap|shownArtilleryComputer|shownChat|shownCompass|shownCuratorCompass|showNewEditorObject|shownGPS|shownHUD|shownMap|shownPad|shownRadio|shownScoretable|shownUAVFeed|shownWarrant|shownWatch|showPad|showRadio|showScoretable|showSubtitles|showUAVFeed|showWarrant|showWatch|showWaypoint|showWaypoints|side|sideAmbientLife|sideChat|sideEmpty|sideEnemy|sideFriendly|sideLogic|sideRadio|sideUnknown|simpleTasks|simulationEnabled|simulCloudDensity|simulCloudOcclusion|simulInClouds|simulWeatherSync|sin|size|sizeOf|skill|skillFinal|skipTime|sleep|sliderPosition|sliderRange|sliderSetPosition|sliderSetRange|sliderSetSpeed|sliderSpeed|slingLoadAssistantShown|soldierMagazines|someAmmo|sort|soundVolume|speaker|speed|speedMode|splitString|sqrt|squadParams|stance|startLoadingScreen|stop|stopEngineRTD|stopped|str|sunOrMoon|supportInfo|suppressFor|surfaceIsWater|surfaceNormal|surfaceType|swimInDepth|switchableUnits|switchAction|switchCamera|switchGesture|switchLight|switchMove|synchronizedObjects|synchronizedTriggers|synchronizedWaypoints|synchronizeObjectsAdd|synchronizeObjectsRemove|synchronizeTrigger|synchronizeWaypoint|systemChat|systemOfUnits|tan|targetKnowledge|targets|targetsAggregate|targetsQuery|taskAlwaysVisible|taskChildren|taskCompleted|taskCustomData|taskDescription|taskDestination|taskHint|taskMarkerOffset|taskNull|taskParent|taskResult|taskState|taskType|teamMember|teamMemberNull|teamName|teams|teamSwitch|teamSwitchEnabled|teamType|terminate|terrainIntersect|terrainIntersectASL|terrainIntersectAtASL|text|textLog|textLogFormat|tg|time|timeMultiplier|titleCut|titleFadeOut|titleObj|titleRsc|titleText|toArray|toFixed|toLower|toString|toUpper|triggerActivated|triggerActivation|triggerArea|triggerAttachedVehicle|triggerAttachObject|triggerAttachVehicle|triggerDynamicSimulation|triggerStatements|triggerText|triggerTimeout|triggerTimeoutCurrent|triggerType|turretLocal|turretOwner|turretUnit|tvAdd|tvClear|tvCollapse|tvCollapseAll|tvCount|tvCurSel|tvData|tvDelete|tvExpand|tvExpandAll|tvPicture|tvPictureRight|tvSetColor|tvSetCurSel|tvSetData|tvSetPicture|tvSetPictureColor|tvSetPictureColorDisabled|tvSetPictureColorSelected|tvSetPictureRight|tvSetPictureRightColor|tvSetPictureRightColorDisabled|tvSetPictureRightColorSelected|tvSetSelectColor|tvSetText|tvSetTooltip|tvSetValue|tvSort|tvSortByValue|tvText|tvTooltip|tvValue|type|typeName|typeOf|UAVControl|uiNamespace|uiSleep|unassignCurator|unassignItem|unassignTeam|unassignVehicle|underwater|uniform|uniformContainer|uniformItems|uniformMagazines|unitAddons|unitAimPosition|unitAimPositionVisual|unitBackpack|unitIsUAV|unitPos|unitReady|unitRecoilCoefficient|units|unitsBelowHeight|unlinkItem|unlockAchievement|unregisterTask|updateDrawIcon|updateMenuItem|updateObjectTree|useAIOperMapObstructionTest|useAISteeringComponent|useAudioTimeForMoves|userInputDisabled|vectorAdd|vectorCos|vectorCrossProduct|vectorDiff|vectorDir|vectorDirVisual|vectorDistance|vectorDistanceSqr|vectorDotProduct|vectorFromTo|vectorMagnitude|vectorMagnitudeSqr|vectorModelToWorld|vectorModelToWorldVisual|vectorMultiply|vectorNormalized|vectorUp|vectorUpVisual|vectorWorldToModel|vectorWorldToModelVisual|vehicle|vehicleCargoEnabled|vehicleChat|vehicleRadio|vehicleReceiveRemoteTargets|vehicleReportOwnPosition|vehicleReportRemoteTargets|vehicles|vehicleVarName|velocity|velocityModelSpace|verifySignature|vest|vestContainer|vestItems|vestMagazines|viewDistance|visibleCompass|visibleGPS|visibleMap|visiblePosition|visiblePositionASL|visibleScoretable|visibleWatch|waitUntil|waves|waypointAttachedObject|waypointAttachedVehicle|waypointAttachObject|waypointAttachVehicle|waypointBehaviour|waypointCombatMode|waypointCompletionRadius|waypointDescription|waypointForceBehaviour|waypointFormation|waypointHousePosition|waypointLoiterRadius|waypointLoiterType|waypointName|waypointPosition|waypoints|waypointScript|waypointsEnabledUAV|waypointShow|waypointSpeed|waypointStatements|waypointTimeout|waypointTimeoutCurrent|waypointType|waypointVisible|weaponAccessories|weaponAccessoriesCargo|weaponCargo|weaponDirection|weaponInertia|weaponLowered|weapons|weaponsItems|weaponsItemsCargo|weaponState|weaponsTurret|weightRTD|west|WFSideText|wind|windDir|windRTD|windStr|wingsForcesRTD|worldName|worldSize|worldToModel|worldToModelVisual|worldToScreen)\b/i,number:/(?:\$|\b0x)[\da-f]+\b|(?:\B\.\d+|\b\d+(?:\.\d+)?)(?:e[+-]?\d+)?\b/i,operator:/##|>>|&&|\|\||[!=<>]=?|[-+*/%#^]|\b(?:and|mod|not|or)\b/i,"magic-variable":{pattern:/\b(?:this|thisList|thisTrigger|_exception|_fnc_scriptName|_fnc_scriptNameParent|_forEachIndex|_this|_thisEventHandler|_thisFSM|_thisScript|_x)\b/i,alias:"keyword"},constant:/\bDIK(?:_[a-z\d]+)+\b/i}),t.languages.insertBefore("sqf","string",{macro:{pattern:/(^[ \t]*)#[a-z](?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{directive:{pattern:/#[a-z]+\b/i,alias:"keyword"},comment:t.languages.sqf.comment}}}),delete t.languages.sqf["class-name"]}return ip}var op,Vk;function Dj(){if(Vk)return op;Vk=1,op=e,e.displayName="squirrel",e.aliases=[];function e(t){t.languages.squirrel=t.languages.extend("clike",{comment:[t.languages.clike.comment[0],{pattern:/(^|[^\\:])(?:\/\/|#).*/,lookbehind:!0,greedy:!0}],string:{pattern:/(^|[^\\"'@])(?:@"(?:[^"]|"")*"(?!")|"(?:[^\\\r\n"]|\\.)*")/,lookbehind:!0,greedy:!0},"class-name":{pattern:/(\b(?:class|enum|extends|instanceof)\s+)\w+(?:\.\w+)*/,lookbehind:!0,inside:{punctuation:/\./}},keyword:/\b(?:__FILE__|__LINE__|base|break|case|catch|class|clone|const|constructor|continue|default|delete|else|enum|extends|for|foreach|function|if|in|instanceof|local|null|resume|return|static|switch|this|throw|try|typeof|while|yield)\b/,number:/\b(?:0x[0-9a-fA-F]+|\d+(?:\.(?:\d+|[eE][+-]?\d+))?)\b/,operator:/\+\+|--|<=>|<[-<]|>>>?|&&?|\|\|?|[-+*/%!=<>]=?|[~^]|::?/,punctuation:/[(){}\[\],;.]/}),t.languages.insertBefore("squirrel","string",{char:{pattern:/(^|[^\\"'])'(?:[^\\']|\\(?:[xuU][0-9a-fA-F]{0,8}|[\s\S]))'/,lookbehind:!0,greedy:!0}}),t.languages.insertBefore("squirrel","operator",{"attribute-punctuation":{pattern:/<\/|\/>/,alias:"important"},lambda:{pattern:/@(?=\()/,alias:"operator"}})}return op}var sp,Wk;function Mj(){if(Wk)return sp;Wk=1,sp=e,e.displayName="stan",e.aliases=[];function e(t){(function(n){var r=/\b(?:algebra_solver|algebra_solver_newton|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect|ode_(?:adams|bdf|ckrk|rk45)(?:_tol)?|ode_adjoint_tol_ctl|reduce_sum|reduce_sum_static)\b/;n.languages.stan={comment:/\/\/.*|\/\*[\s\S]*?\*\/|#(?!include).*/,string:{pattern:/"[\x20\x21\x23-\x5B\x5D-\x7E]*"/,greedy:!0},directive:{pattern:/^([ \t]*)#include\b.*/m,lookbehind:!0,alias:"property"},"function-arg":{pattern:RegExp("("+r.source+/\s*\(\s*/.source+")"+/[a-zA-Z]\w*/.source),lookbehind:!0,alias:"function"},constraint:{pattern:/(\b(?:int|matrix|real|row_vector|vector)\s*)<[^<>]*>/,lookbehind:!0,inside:{expression:{pattern:/(=\s*)\S(?:\S|\s+(?!\s))*?(?=\s*(?:>$|,\s*\w+\s*=))/,lookbehind:!0,inside:null},property:/\b[a-z]\w*(?=\s*=)/i,operator:/=/,punctuation:/^<|>$|,/}},keyword:[{pattern:/\bdata(?=\s*\{)|\b(?:functions|generated|model|parameters|quantities|transformed)\b/,alias:"program-block"},/\b(?:array|break|cholesky_factor_corr|cholesky_factor_cov|complex|continue|corr_matrix|cov_matrix|data|else|for|if|in|increment_log_prob|int|matrix|ordered|positive_ordered|print|real|reject|return|row_vector|simplex|target|unit_vector|vector|void|while)\b/,r],function:/\b[a-z]\w*(?=\s*\()/i,number:/(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:E[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,boolean:/\b(?:false|true)\b/,operator:/<-|\.[*/]=?|\|\|?|&&|[!=<>+\-*/]=?|['^%~?:]/,punctuation:/[()\[\]{},;]/},n.languages.stan.constraint.inside.expression.inside=n.languages.stan})(t)}return sp}var lp,Yk;function Fj(){if(Yk)return lp;Yk=1,lp=e,e.displayName="stylus",e.aliases=[];function e(t){(function(n){var r={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},a={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},i={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:a,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:a,punctuation:/[{}()\[\];:,]/};i.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:i}},i.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:i}},n.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:i}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:i}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:i}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:i.interpolation}},rest:i}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:i.interpolation,comment:i.comment,punctuation:/[{},]/}},func:i.func,string:i.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:i.interpolation,punctuation:/[{}()\[\];:.]/}})(t)}return lp}var up,Kk;function Pj(){if(Kk)return up;Kk=1,up=e,e.displayName="swift",e.aliases=[];function e(t){t.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp(/(^|[^"#])/.source+"(?:"+/"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source+"|"+/"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source+")"+/(?!["#])/.source),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp(/(^|[^"#])(#+)/.source+"(?:"+/"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source+"|"+/"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source+")\\2"),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp(/#/.source+"(?:"+(/(?:elseif|if)\b/.source+"(?:[ ]*"+/(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source+")+")+"|"+/(?:else|endif)\b/.source+")"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},t.languages.swift["string-literal"].forEach(function(n){n.inside.interpolation.inside=t.languages.swift})}return up}var cp,Xk;function Uj(){if(Xk)return cp;Xk=1,cp=e,e.displayName="systemd",e.aliases=[];function e(t){(function(n){var r={pattern:/^[;#].*/m,greedy:!0},a=/"(?:[^\r\n"\\]|\\(?:[^\r]|\r\n?))*"(?!\S)/.source;n.languages.systemd={comment:r,section:{pattern:/^\[[^\n\r\[\]]*\](?=[ \t]*$)/m,greedy:!0,inside:{punctuation:/^\[|\]$/,"section-name":{pattern:/[\s\S]+/,alias:"selector"}}},key:{pattern:/^[^\s=]+(?=[ \t]*=)/m,greedy:!0,alias:"attr-name"},value:{pattern:RegExp(/(=[ \t]*(?!\s))/.source+"(?:"+a+`|(?=[^"\r +]))(?:`+(/[^\s\\]/.source+'|[ ]+(?:(?![ "])|'+a+")|"+/\\[\r\n]+(?:[#;].*[\r\n]+)*(?![#;])/.source)+")*"),lookbehind:!0,greedy:!0,alias:"attr-value",inside:{comment:r,quoted:{pattern:RegExp(/(^|\s)/.source+a),lookbehind:!0,greedy:!0},punctuation:/\\$/m,boolean:{pattern:/^(?:false|no|off|on|true|yes)$/,greedy:!0}}},punctuation:/=/}})(t)}return cp}var dp,Zk;function Vm(){if(Zk)return dp;Zk=1,dp=e,e.displayName="t4Templating",e.aliases=[];function e(t){(function(n){function r(i,o,s){return{pattern:RegExp("<#"+i+"[\\s\\S]*?#>"),alias:"block",inside:{delimiter:{pattern:RegExp("^<#"+i+"|#>$"),alias:"important"},content:{pattern:/[\s\S]+/,inside:o,alias:s}}}}function a(i){var o=n.languages[i],s="language-"+i;return{block:{pattern:/<#[\s\S]+?#>/,inside:{directive:r("@",{"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/,inside:{punctuation:/^=|^["']|["']$/}},keyword:/\b\w+(?=\s)/,"attr-name":/\b\w+/}),expression:r("=",o,s),"class-feature":r("\\+",o,s),standard:r("",o,s)}}}}n.languages["t4-templating"]=Object.defineProperty({},"createT4",{value:a})})(t)}return dp}var pp,Qk;function Bj(){if(Qk)return pp;Qk=1;var e=Vm(),t=Xo();pp=n,n.displayName="t4Cs",n.aliases=[];function n(r){r.register(e),r.register(t),r.languages.t4=r.languages["t4-cs"]=r.languages["t4-templating"].createT4("csharp")}return pp}var fp,Jk;function WR(){if(Jk)return fp;Jk=1;var e=qR();fp=t,t.displayName="vbnet",t.aliases=[];function t(n){n.register(e),n.languages.vbnet=n.languages.extend("basic",{comment:[{pattern:/(?:!|REM\b).+/i,inside:{keyword:/^REM/i}},{pattern:/(^|[^\\:])'.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(^|[^"])"(?:""|[^"])*"(?!")/,lookbehind:!0,greedy:!0},keyword:/(?:\b(?:ADDHANDLER|ADDRESSOF|ALIAS|AND|ANDALSO|AS|BEEP|BLOAD|BOOLEAN|BSAVE|BYREF|BYTE|BYVAL|CALL(?: ABSOLUTE)?|CASE|CATCH|CBOOL|CBYTE|CCHAR|CDATE|CDBL|CDEC|CHAIN|CHAR|CHDIR|CINT|CLASS|CLEAR|CLNG|CLOSE|CLS|COBJ|COM|COMMON|CONST|CONTINUE|CSBYTE|CSHORT|CSNG|CSTR|CTYPE|CUINT|CULNG|CUSHORT|DATA|DATE|DECIMAL|DECLARE|DEF(?: FN| SEG|DBL|INT|LNG|SNG|STR)|DEFAULT|DELEGATE|DIM|DIRECTCAST|DO|DOUBLE|ELSE|ELSEIF|END|ENUM|ENVIRON|ERASE|ERROR|EVENT|EXIT|FALSE|FIELD|FILES|FINALLY|FOR(?: EACH)?|FRIEND|FUNCTION|GET|GETTYPE|GETXMLNAMESPACE|GLOBAL|GOSUB|GOTO|HANDLES|IF|IMPLEMENTS|IMPORTS|IN|INHERITS|INPUT|INTEGER|INTERFACE|IOCTL|IS|ISNOT|KEY|KILL|LET|LIB|LIKE|LINE INPUT|LOCATE|LOCK|LONG|LOOP|LSET|ME|MKDIR|MOD|MODULE|MUSTINHERIT|MUSTOVERRIDE|MYBASE|MYCLASS|NAME|NAMESPACE|NARROWING|NEW|NEXT|NOT|NOTHING|NOTINHERITABLE|NOTOVERRIDABLE|OBJECT|OF|OFF|ON(?: COM| ERROR| KEY| TIMER)?|OPEN|OPERATOR|OPTION(?: BASE)?|OPTIONAL|OR|ORELSE|OUT|OVERLOADS|OVERRIDABLE|OVERRIDES|PARAMARRAY|PARTIAL|POKE|PRIVATE|PROPERTY|PROTECTED|PUBLIC|PUT|RAISEEVENT|READ|READONLY|REDIM|REM|REMOVEHANDLER|RESTORE|RESUME|RETURN|RMDIR|RSET|RUN|SBYTE|SELECT(?: CASE)?|SET|SHADOWS|SHARED|SHELL|SHORT|SINGLE|SLEEP|STATIC|STEP|STOP|STRING|STRUCTURE|SUB|SWAP|SYNCLOCK|SYSTEM|THEN|THROW|TIMER|TO|TROFF|TRON|TRUE|TRY|TRYCAST|TYPE|TYPEOF|UINTEGER|ULONG|UNLOCK|UNTIL|USHORT|USING|VIEW PRINT|WAIT|WEND|WHEN|WHILE|WIDENING|WITH|WITHEVENTS|WRITE|WRITEONLY|XOR)|\B(?:#CONST|#ELSE|#ELSEIF|#END|#IF))(?:\$|\b)/i,punctuation:/[,;:(){}]/})}return fp}var gp,ew;function $j(){if(ew)return gp;ew=1;var e=Vm(),t=WR();gp=n,n.displayName="t4Vb",n.aliases=[];function n(r){r.register(e),r.register(t),r.languages["t4-vb"]=r.languages["t4-templating"].createT4("vbnet")}return gp}var mp,tw;function YR(){if(tw)return mp;tw=1,mp=e,e.displayName="yaml",e.aliases=["yml"];function e(t){(function(n){var r=/[*&][^\s[\]{},]+/,a=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,i="(?:"+a.source+"(?:[ ]+"+r.source+")?|"+r.source+"(?:[ ]+"+a.source+")?)",o=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source}),s=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function l(u,d){d=(d||"").replace(/m/g,"")+"m";var c=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,function(){return i}).replace(/<>/g,function(){return u});return RegExp(c,d)}n.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,function(){return i})),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,function(){return i}).replace(/<>/g,function(){return"(?:"+o+"|"+s+")"})),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:l(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:l(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:l(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:l(s),lookbehind:!0,greedy:!0},number:{pattern:l(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:a,important:r,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},n.languages.yml=n.languages.yaml})(t)}return mp}var hp,nw;function zj(){if(nw)return hp;nw=1;var e=YR();hp=t,t.displayName="tap",t.aliases=[];function t(n){n.register(e),n.languages.tap={fail:/not ok[^#{\n\r]*/,pass:/ok[^#{\n\r]*/,pragma:/pragma [+-][a-z]+/,bailout:/bail out!.*/i,version:/TAP version \d+/i,plan:/\b\d+\.\.\d+(?: +#.*)?/,subtest:{pattern:/# Subtest(?:: .*)?/,greedy:!0},punctuation:/[{}]/,directive:/#.*/,yamlish:{pattern:/(^[ \t]*)---[\s\S]*?[\r\n][ \t]*\.\.\.$/m,lookbehind:!0,inside:n.languages.yaml,alias:"language-yaml"}}}return hp}var bp,rw;function Gj(){if(rw)return bp;rw=1,bp=e,e.displayName="tcl",e.aliases=[];function e(t){t.languages.tcl={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:{pattern:/"(?:[^"\\\r\n]|\\(?:\r\n|[\s\S]))*"/,greedy:!0},variable:[{pattern:/(\$)(?:::)?(?:[a-zA-Z0-9]+::)*\w+/,lookbehind:!0},{pattern:/(\$)\{[^}]+\}/,lookbehind:!0},{pattern:/(^[\t ]*set[ \t]+)(?:::)?(?:[a-zA-Z0-9]+::)*\w+/m,lookbehind:!0}],function:{pattern:/(^[\t ]*proc[ \t]+)\S+/m,lookbehind:!0},builtin:[{pattern:/(^[\t ]*)(?:break|class|continue|error|eval|exit|for|foreach|if|proc|return|switch|while)\b/m,lookbehind:!0},/\b(?:else|elseif)\b/],scope:{pattern:/(^[\t ]*)(?:global|upvar|variable)\b/m,lookbehind:!0,alias:"constant"},keyword:{pattern:/(^[\t ]*|\[)(?:Safe_Base|Tcl|after|append|apply|array|auto_(?:execok|import|load|mkindex|qualify|reset)|automkindex_old|bgerror|binary|catch|cd|chan|clock|close|concat|dde|dict|encoding|eof|exec|expr|fblocked|fconfigure|fcopy|file(?:event|name)?|flush|gets|glob|history|http|incr|info|interp|join|lappend|lassign|lindex|linsert|list|llength|load|lrange|lrepeat|lreplace|lreverse|lsearch|lset|lsort|math(?:func|op)|memory|msgcat|namespace|open|package|parray|pid|pkg_mkIndex|platform|puts|pwd|re_syntax|read|refchan|regexp|registry|regsub|rename|scan|seek|set|socket|source|split|string|subst|tcl(?:_endOfWord|_findLibrary|startOf(?:Next|Previous)Word|test|vars|wordBreak(?:After|Before))|tell|time|tm|trace|unknown|unload|unset|update|uplevel|vwait)\b/m,lookbehind:!0},operator:/!=?|\*\*?|==|&&?|\|\|?|<[=<]?|>[=>]?|[-+~\/%?^]|\b(?:eq|in|ne|ni)\b/,punctuation:/[{}()\[\]]/}}return bp}var yp,aw;function qj(){if(aw)return yp;aw=1,yp=e,e.displayName="textile",e.aliases=[];function e(t){(function(n){var r=/\([^|()\n]+\)|\[[^\]\n]+\]|\{[^}\n]+\}/.source,a=/\)|\((?![^|()\n]+\))/.source;function i(f,p){return RegExp(f.replace(//g,function(){return"(?:"+r+")"}).replace(//g,function(){return"(?:"+a+")"}),p||"")}var o={css:{pattern:/\{[^{}]+\}/,inside:{rest:n.languages.css}},"class-id":{pattern:/(\()[^()]+(?=\))/,lookbehind:!0,alias:"attr-value"},lang:{pattern:/(\[)[^\[\]]+(?=\])/,lookbehind:!0,alias:"attr-value"},punctuation:/[\\\/]\d+|\S/},s=n.languages.textile=n.languages.extend("markup",{phrase:{pattern:/(^|\r|\n)\S[\s\S]*?(?=$|\r?\n\r?\n|\r\r)/,lookbehind:!0,inside:{"block-tag":{pattern:i(/^[a-z]\w*(?:||[<>=])*\./.source),inside:{modifier:{pattern:i(/(^[a-z]\w*)(?:||[<>=])+(?=\.)/.source),lookbehind:!0,inside:o},tag:/^[a-z]\w*/,punctuation:/\.$/}},list:{pattern:i(/^[*#]+*\s+\S.*/.source,"m"),inside:{modifier:{pattern:i(/(^[*#]+)+/.source),lookbehind:!0,inside:o},punctuation:/^[*#]+/}},table:{pattern:i(/^(?:(?:||[<>=^~])+\.\s*)?(?:\|(?:(?:||[<>=^~_]|[\\/]\d+)+\.|(?!(?:||[<>=^~_]|[\\/]\d+)+\.))[^|]*)+\|/.source,"m"),inside:{modifier:{pattern:i(/(^|\|(?:\r?\n|\r)?)(?:||[<>=^~_]|[\\/]\d+)+(?=\.)/.source),lookbehind:!0,inside:o},punctuation:/\||^\./}},inline:{pattern:i(/(^|[^a-zA-Z\d])(\*\*|__|\?\?|[*_%@+\-^~])*.+?\2(?![a-zA-Z\d])/.source),lookbehind:!0,inside:{bold:{pattern:i(/(^(\*\*?)*).+?(?=\2)/.source),lookbehind:!0},italic:{pattern:i(/(^(__?)*).+?(?=\2)/.source),lookbehind:!0},cite:{pattern:i(/(^\?\?*).+?(?=\?\?)/.source),lookbehind:!0,alias:"string"},code:{pattern:i(/(^@*).+?(?=@)/.source),lookbehind:!0,alias:"keyword"},inserted:{pattern:i(/(^\+*).+?(?=\+)/.source),lookbehind:!0},deleted:{pattern:i(/(^-*).+?(?=-)/.source),lookbehind:!0},span:{pattern:i(/(^%*).+?(?=%)/.source),lookbehind:!0},modifier:{pattern:i(/(^\*\*|__|\?\?|[*_%@+\-^~])+/.source),lookbehind:!0,inside:o},punctuation:/[*_%?@+\-^~]+/}},"link-ref":{pattern:/^\[[^\]]+\]\S+$/m,inside:{string:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0},url:{pattern:/(^\])\S+$/,lookbehind:!0},punctuation:/[\[\]]/}},link:{pattern:i(/"*[^"]+":.+?(?=[^\w/]?(?:\s|$))/.source),inside:{text:{pattern:i(/(^"*)[^"]+(?=")/.source),lookbehind:!0},modifier:{pattern:i(/(^")+/.source),lookbehind:!0,inside:o},url:{pattern:/(:).+/,lookbehind:!0},punctuation:/[":]/}},image:{pattern:i(/!(?:||[<>=])*(?![<>=])[^!\s()]+(?:\([^)]+\))?!(?::.+?(?=[^\w/]?(?:\s|$)))?/.source),inside:{source:{pattern:i(/(^!(?:||[<>=])*)(?![<>=])[^!\s()]+(?:\([^)]+\))?(?=!)/.source),lookbehind:!0,alias:"url"},modifier:{pattern:i(/(^!)(?:||[<>=])+/.source),lookbehind:!0,inside:o},url:{pattern:/(:).+/,lookbehind:!0},punctuation:/[!:]/}},footnote:{pattern:/\b\[\d+\]/,alias:"comment",inside:{punctuation:/\[|\]/}},acronym:{pattern:/\b[A-Z\d]+\([^)]+\)/,inside:{comment:{pattern:/(\()[^()]+(?=\))/,lookbehind:!0},punctuation:/[()]/}},mark:{pattern:/\b\((?:C|R|TM)\)/,alias:"comment",inside:{punctuation:/[()]/}}}}}),l=s.phrase.inside,u={inline:l.inline,link:l.link,image:l.image,footnote:l.footnote,acronym:l.acronym,mark:l.mark};s.tag.pattern=/<\/?(?!\d)[a-z0-9]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i;var d=l.inline.inside;d.bold.inside=u,d.italic.inside=u,d.inserted.inside=u,d.deleted.inside=u,d.span.inside=u;var c=l.table.inside;c.inline=u.inline,c.link=u.link,c.image=u.image,c.footnote=u.footnote,c.acronym=u.acronym,c.mark=u.mark})(t)}return yp}var Ep,iw;function jj(){if(iw)return Ep;iw=1,Ep=e,e.displayName="toml",e.aliases=[];function e(t){(function(n){var r=/(?:[\w-]+|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*")/.source;function a(i){return i.replace(/__/g,function(){return r})}n.languages.toml={comment:{pattern:/#.*/,greedy:!0},table:{pattern:RegExp(a(/(^[\t ]*\[\s*(?:\[\s*)?)__(?:\s*\.\s*__)*(?=\s*\])/.source),"m"),lookbehind:!0,greedy:!0,alias:"class-name"},key:{pattern:RegExp(a(/(^[\t ]*|[{,]\s*)__(?:\s*\.\s*__)*(?=\s*=)/.source),"m"),lookbehind:!0,greedy:!0,alias:"property"},string:{pattern:/"""(?:\\[\s\S]|[^\\])*?"""|'''[\s\S]*?'''|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},date:[{pattern:/\b\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)?\b/i,alias:"number"},{pattern:/\b\d{2}:\d{2}:\d{2}(?:\.\d+)?\b/,alias:"number"}],number:/(?:\b0(?:x[\da-zA-Z]+(?:_[\da-zA-Z]+)*|o[0-7]+(?:_[0-7]+)*|b[10]+(?:_[10]+)*))\b|[-+]?\b\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?\b|[-+]?\b(?:inf|nan)\b/,boolean:/\b(?:false|true)\b/,punctuation:/[.,=[\]{}]/}})(t)}return Ep}var Sp,ow;function Hj(){if(ow)return Sp;ow=1,Sp=e,e.displayName="tremor",e.aliases=[];function e(t){(function(n){n.languages.tremor={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},"interpolated-string":null,extractor:{pattern:/\b[a-z_]\w*\|(?:[^\r\n\\|]|\\(?:\r\n|[\s\S]))*\|/i,greedy:!0,inside:{regex:{pattern:/(^re)\|[\s\S]+/,lookbehind:!0},function:/^\w+/,value:/\|[\s\S]+/}},identifier:{pattern:/`[^`]*`/,greedy:!0},function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())\b/,keyword:/\b(?:args|as|by|case|config|connect|connector|const|copy|create|default|define|deploy|drop|each|emit|end|erase|event|flow|fn|for|from|group|having|insert|into|intrinsic|let|links|match|merge|mod|move|of|operator|patch|pipeline|recur|script|select|set|sliding|state|stream|to|tumbling|update|use|when|where|window|with)\b/,boolean:/\b(?:false|null|true)\b/i,number:/\b(?:0b[01_]*|0x[0-9a-fA-F_]*|\d[\d_]*(?:\.\d[\d_]*)?(?:[Ee][+-]?[\d_]+)?)\b/,"pattern-punctuation":{pattern:/%(?=[({[])/,alias:"punctuation"},operator:/[-+*\/%~!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?>?=?|(?:absent|and|not|or|present|xor)\b/,punctuation:/::|[;\[\]()\{\},.:]/};var r=/#\{(?:[^"{}]|\{[^{}]*\}|"(?:[^"\\\r\n]|\\(?:\r\n|[\s\S]))*")*\}/.source;n.languages.tremor["interpolated-string"]={pattern:RegExp(/(^|[^\\])/.source+'(?:"""(?:'+/[^"\\#]|\\[\s\S]|"(?!"")|#(?!\{)/.source+"|"+r+')*"""|"(?:'+/[^"\\\r\n#]|\\(?:\r\n|[\s\S])|#(?!\{)/.source+"|"+r+')*")'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:RegExp(r),inside:{punctuation:/^#\{|\}$/,expression:{pattern:/[\s\S]+/,inside:n.languages.tremor}}},string:/[\s\S]+/}},n.languages.troy=n.languages.tremor,n.languages.trickle=n.languages.tremor})(t)}return Sp}var vp,sw;function Vj(){if(sw)return vp;sw=1;var e=HR(),t=qm();vp=n,n.displayName="tsx",n.aliases=[];function n(r){r.register(e),r.register(t),function(a){var i=a.util.clone(a.languages.typescript);a.languages.tsx=a.languages.extend("jsx",i),delete a.languages.tsx.parameter,delete a.languages.tsx["literal-property"];var o=a.languages.tsx.tag;o.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+o.pattern.source+")",o.pattern.flags),o.lookbehind=!0}(r)}return vp}var kp,lw;function Wj(){if(lw)return kp;lw=1;var e=nt();kp=t,t.displayName="tt2",t.aliases=[];function t(n){n.register(e),function(r){r.languages.tt2=r.languages.extend("clike",{comment:/#.*|\[%#[\s\S]*?%\]/,keyword:/\b(?:BLOCK|CALL|CASE|CATCH|CLEAR|DEBUG|DEFAULT|ELSE|ELSIF|END|FILTER|FINAL|FOREACH|GET|IF|IN|INCLUDE|INSERT|LAST|MACRO|META|NEXT|PERL|PROCESS|RAWPERL|RETURN|SET|STOP|SWITCH|TAGS|THROW|TRY|UNLESS|USE|WHILE|WRAPPER)\b/,punctuation:/[[\]{},()]/}),r.languages.insertBefore("tt2","number",{operator:/=[>=]?|!=?|<=?|>=?|&&|\|\|?|\b(?:and|not|or)\b/,variable:{pattern:/\b[a-z]\w*(?:\s*\.\s*(?:\d+|\$?[a-z]\w*))*\b/i}}),r.languages.insertBefore("tt2","keyword",{delimiter:{pattern:/^(?:\[%|%%)-?|-?%\]$/,alias:"punctuation"}}),r.languages.insertBefore("tt2","string",{"single-quoted-string":{pattern:/'[^\\']*(?:\\[\s\S][^\\']*)*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"[^\\"]*(?:\\[\s\S][^\\"]*)*"/,greedy:!0,alias:"string",inside:{variable:{pattern:/\$(?:[a-z]\w*(?:\.(?:\d+|\$?[a-z]\w*))*)/i}}}}),delete r.languages.tt2.string,r.hooks.add("before-tokenize",function(a){var i=/\[%[\s\S]+?%\]/g;r.languages["markup-templating"].buildPlaceholders(a,"tt2",i)}),r.hooks.add("after-tokenize",function(a){r.languages["markup-templating"].tokenizePlaceholders(a,"tt2")})}(n)}return kp}var wp,uw;function Yj(){if(uw)return wp;uw=1;var e=nt();wp=t,t.displayName="twig",t.aliases=[];function t(n){n.register(e),n.languages.twig={comment:/^\{#[\s\S]*?#\}$/,"tag-name":{pattern:/(^\{%-?\s*)\w+/,lookbehind:!0,alias:"keyword"},delimiter:{pattern:/^\{[{%]-?|-?[%}]\}$/,alias:"punctuation"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,inside:{punctuation:/^['"]|['"]$/}},keyword:/\b(?:even|if|odd)\b/,boolean:/\b(?:false|null|true)\b/,number:/\b0x[\dA-Fa-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][-+]?\d+)?/,operator:[{pattern:/(\s)(?:and|b-and|b-or|b-xor|ends with|in|is|matches|not|or|same as|starts with)(?=\s)/,lookbehind:!0},/[=<>]=?|!=|\*\*?|\/\/?|\?:?|[-+~%|]/],punctuation:/[()\[\]{}:.,]/},n.hooks.add("before-tokenize",function(r){if(r.language==="twig"){var a=/\{(?:#[\s\S]*?#|%[\s\S]*?%|\{[\s\S]*?\})\}/g;n.languages["markup-templating"].buildPlaceholders(r,"twig",a)}}),n.hooks.add("after-tokenize",function(r){n.languages["markup-templating"].tokenizePlaceholders(r,"twig")})}return wp}var _p,cw;function Kj(){if(cw)return _p;cw=1,_p=e,e.displayName="typoscript",e.aliases=["tsconfig"];function e(t){(function(n){var r=/\b(?:ACT|ACTIFSUB|CARRAY|CASE|CLEARGIF|COA|COA_INT|CONSTANTS|CONTENT|CUR|EDITPANEL|EFFECT|EXT|FILE|FLUIDTEMPLATE|FORM|FRAME|FRAMESET|GIFBUILDER|GMENU|GMENU_FOLDOUT|GMENU_LAYERS|GP|HMENU|HRULER|HTML|IENV|IFSUB|IMAGE|IMGMENU|IMGMENUITEM|IMGTEXT|IMG_RESOURCE|INCLUDE_TYPOSCRIPT|JSMENU|JSMENUITEM|LLL|LOAD_REGISTER|NO|PAGE|RECORDS|RESTORE_REGISTER|TEMPLATE|TEXT|TMENU|TMENUITEM|TMENU_LAYERS|USER|USER_INT|_GIFBUILDER|global|globalString|globalVar)\b/;n.languages.typoscript={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:= \t]|(?:^|[^= \t])[ \t]+)\/\/.*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^"'])#.*/,lookbehind:!0,greedy:!0}],function:[{pattern://,inside:{string:{pattern:/"[^"\r\n]*"|'[^'\r\n]*'/,inside:{keyword:r}},keyword:{pattern:/INCLUDE_TYPOSCRIPT/}}},{pattern:/@import\s*(?:"[^"\r\n]*"|'[^'\r\n]*')/,inside:{string:/"[^"\r\n]*"|'[^'\r\n]*'/}}],string:{pattern:/^([^=]*=[< ]?)(?:(?!\]\n).)*/,lookbehind:!0,inside:{function:/\{\$.*\}/,keyword:r,number:/^\d+$/,punctuation:/[,|:]/}},keyword:r,number:{pattern:/\b\d+\s*[.{=]/,inside:{operator:/[.{=]/}},tag:{pattern:/\.?[-\w\\]+\.?/,inside:{punctuation:/\./}},punctuation:/[{}[\];(),.:|]/,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/},n.languages.tsconfig=n.languages.typoscript})(t)}return _p}var Tp,dw;function Xj(){if(dw)return Tp;dw=1,Tp=e,e.displayName="unrealscript",e.aliases=["uc","uscript"];function e(t){t.languages.unrealscript={comment:/\/\/.*|\/\*[\s\S]*?\*\//,string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},category:{pattern:/(\b(?:(?:autoexpand|hide|show)categories|var)\s*\()[^()]+(?=\))/,lookbehind:!0,greedy:!0,alias:"property"},metadata:{pattern:/(\w\s*)<\s*\w+\s*=[^<>|=\r\n]+(?:\|\s*\w+\s*=[^<>|=\r\n]+)*>/,lookbehind:!0,greedy:!0,inside:{property:/\b\w+(?=\s*=)/,operator:/=/,punctuation:/[<>|]/}},macro:{pattern:/`\w+/,alias:"property"},"class-name":{pattern:/(\b(?:class|enum|extends|interface|state(?:\(\))?|struct|within)\s+)\w+/,lookbehind:!0},keyword:/\b(?:abstract|actor|array|auto|autoexpandcategories|bool|break|byte|case|class|classgroup|client|coerce|collapsecategories|config|const|continue|default|defaultproperties|delegate|dependson|deprecated|do|dontcollapsecategories|editconst|editinlinenew|else|enum|event|exec|export|extends|final|float|for|forcescriptorder|foreach|function|goto|guid|hidecategories|hidedropdown|if|ignores|implements|inherits|input|int|interface|iterator|latent|local|material|name|native|nativereplication|noexport|nontransient|noteditinlinenew|notplaceable|operator|optional|out|pawn|perobjectconfig|perobjectlocalized|placeable|postoperator|preoperator|private|protected|reliable|replication|return|server|showcategories|simulated|singular|state|static|string|struct|structdefault|structdefaultproperties|switch|texture|transient|travel|unreliable|until|var|vector|while|within)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,boolean:/\b(?:false|true)\b/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/>>|<<|--|\+\+|\*\*|[-+*/~!=<>$@]=?|&&?|\|\|?|\^\^?|[?:%]|\b(?:ClockwiseFrom|Cross|Dot)\b/,punctuation:/[()[\]{};,.]/},t.languages.uc=t.languages.uscript=t.languages.unrealscript}return Tp}var Ap,pw;function Zj(){if(pw)return Ap;pw=1,Ap=e,e.displayName="uorazor",e.aliases=[];function e(t){t.languages.uorazor={"comment-hash":{pattern:/#.*/,alias:"comment",greedy:!0},"comment-slash":{pattern:/\/\/.*/,alias:"comment",greedy:!0},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,inside:{punctuation:/^['"]|['"]$/},greedy:!0},"source-layers":{pattern:/\b(?:arms|backpack|blue|bracelet|cancel|clear|cloak|criminal|earrings|enemy|facialhair|friend|friendly|gloves|gray|grey|ground|hair|head|innerlegs|innertorso|innocent|lefthand|middletorso|murderer|neck|nonfriendly|onehandedsecondary|outerlegs|outertorso|pants|red|righthand|ring|self|shirt|shoes|talisman|waist)\b/i,alias:"function"},"source-commands":{pattern:/\b(?:alliance|attack|cast|clearall|clearignore|clearjournal|clearlist|clearsysmsg|createlist|createtimer|dclick|dclicktype|dclickvar|dress|dressconfig|drop|droprelloc|emote|getlabel|guild|gumpclose|gumpresponse|hotkey|ignore|lasttarget|lift|lifttype|menu|menuresponse|msg|org|organize|organizer|overhead|pause|poplist|potion|promptresponse|pushlist|removelist|removetimer|rename|restock|say|scav|scavenger|script|setability|setlasttarget|setskill|settimer|setvar|sysmsg|target|targetloc|targetrelloc|targettype|undress|unignore|unsetvar|useobject|useonce|useskill|usetype|virtue|wait|waitforgump|waitformenu|waitforprompt|waitforstat|waitforsysmsg|waitfortarget|walk|wfsysmsg|wft|whisper|yell)\b/,alias:"function"},"tag-name":{pattern:/(^\{%-?\s*)\w+/,lookbehind:!0,alias:"keyword"},delimiter:{pattern:/^\{[{%]-?|-?[%}]\}$/,alias:"punctuation"},function:/\b(?:atlist|close|closest|count|counter|counttype|dead|dex|diffhits|diffmana|diffstam|diffweight|find|findbuff|finddebuff|findlayer|findtype|findtypelist|followers|gumpexists|hidden|hits|hp|hue|human|humanoid|ingump|inlist|insysmessage|insysmsg|int|invul|lhandempty|list|listexists|mana|maxhits|maxhp|maxmana|maxstam|maxweight|monster|mounted|name|next|noto|paralyzed|poisoned|position|prev|previous|queued|rand|random|rhandempty|skill|stam|str|targetexists|timer|timerexists|varexist|warmode|weight)\b/,keyword:/\b(?:and|as|break|continue|else|elseif|endfor|endif|endwhile|for|if|loop|not|or|replay|stop|while)\b/,boolean:/\b(?:false|null|true)\b/,number:/\b0x[\dA-Fa-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][-+]?\d+)?/,operator:[{pattern:/(\s)(?:and|b-and|b-or|b-xor|ends with|in|is|matches|not|or|same as|starts with)(?=\s)/,lookbehind:!0},/[=<>]=?|!=|\*\*?|\/\/?|\?:?|[-+~%|]/],punctuation:/[()\[\]{}:.,]/}}return Ap}var Rp,fw;function Qj(){if(fw)return Rp;fw=1,Rp=e,e.displayName="uri",e.aliases=["url"];function e(t){t.languages.uri={scheme:{pattern:/^[a-z][a-z0-9+.-]*:/im,greedy:!0,inside:{"scheme-delimiter":/:$/}},fragment:{pattern:/#[\w\-.~!$&'()*+,;=%:@/?]*/,inside:{"fragment-delimiter":/^#/}},query:{pattern:/\?[\w\-.~!$&'()*+,;=%:@/?]*/,inside:{"query-delimiter":{pattern:/^\?/,greedy:!0},"pair-delimiter":/[&;]/,pair:{pattern:/^[^=][\s\S]*/,inside:{key:/^[^=]+/,value:{pattern:/(^=)[\s\S]+/,lookbehind:!0}}}}},authority:{pattern:RegExp(/^\/\//.source+/(?:[\w\-.~!$&'()*+,;=%:]*@)?/.source+("(?:"+/\[(?:[0-9a-fA-F:.]{2,48}|v[0-9a-fA-F]+\.[\w\-.~!$&'()*+,;=]+)\]/.source+"|"+/[\w\-.~!$&'()*+,;=%]*/.source+")")+/(?::\d*)?/.source,"m"),inside:{"authority-delimiter":/^\/\//,"user-info-segment":{pattern:/^[\w\-.~!$&'()*+,;=%:]*@/,inside:{"user-info-delimiter":/@$/,"user-info":/^[\w\-.~!$&'()*+,;=%:]+/}},"port-segment":{pattern:/:\d*$/,inside:{"port-delimiter":/^:/,port:/^\d+/}},host:{pattern:/[\s\S]+/,inside:{"ip-literal":{pattern:/^\[[\s\S]+\]$/,inside:{"ip-literal-delimiter":/^\[|\]$/,"ipv-future":/^v[\s\S]+/,"ipv6-address":/^[\s\S]+/}},"ipv4-address":/^(?:(?:[03-9]\d?|[12]\d{0,2})\.){3}(?:[03-9]\d?|[12]\d{0,2})$/}}}},path:{pattern:/^[\w\-.~!$&'()*+,;=%:@/]+/m,inside:{"path-separator":/\//}}},t.languages.url=t.languages.uri}return Rp}var Ip,gw;function Jj(){if(gw)return Ip;gw=1,Ip=e,e.displayName="v",e.aliases=[];function e(t){(function(n){var r={pattern:/[\s\S]+/,inside:null};n.languages.v=n.languages.extend("clike",{string:{pattern:/r?(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,alias:"quoted-string",greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\{[^{}]*\}|\w+(?:\.\w+(?:\([^\(\)]*\))?|\[[^\[\]]+\])*)/,lookbehind:!0,inside:{"interpolation-variable":{pattern:/^\$\w[\s\S]*$/,alias:"variable"},"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},"interpolation-expression":r}}}},"class-name":{pattern:/(\b(?:enum|interface|struct|type)\s+)(?:C\.)?\w+/,lookbehind:!0},keyword:/(?:\b(?:__global|as|asm|assert|atomic|break|chan|const|continue|defer|else|embed|enum|fn|for|go(?:to)?|if|import|in|interface|is|lock|match|module|mut|none|or|pub|return|rlock|select|shared|sizeof|static|struct|type(?:of)?|union|unsafe)|\$(?:else|for|if)|#(?:flag|include))\b/,number:/\b(?:0x[a-f\d]+(?:_[a-f\d]+)*|0b[01]+(?:_[01]+)*|0o[0-7]+(?:_[0-7]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?)\b/i,operator:/~|\?|[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\.?/,builtin:/\b(?:any(?:_float|_int)?|bool|byte(?:ptr)?|charptr|f(?:32|64)|i(?:8|16|64|128|nt)|rune|size_t|string|u(?:16|32|64|128)|voidptr)\b/}),r.inside=n.languages.v,n.languages.insertBefore("v","string",{char:{pattern:/`(?:\\`|\\?[^`]{1,2})`/,alias:"rune"}}),n.languages.insertBefore("v","operator",{attribute:{pattern:/(^[\t ]*)\[(?:deprecated|direct_array_access|flag|inline|live|ref_only|typedef|unsafe_fn|windows_stdcall)\]/m,lookbehind:!0,alias:"annotation",inside:{punctuation:/[\[\]]/,keyword:/\w+/}},generic:{pattern:/<\w+>(?=\s*[\)\{])/,inside:{punctuation:/[<>]/,"class-name":/\w+/}}}),n.languages.insertBefore("v","function",{"generic-function":{pattern:/\b\w+\s*<\w+>(?=\()/,inside:{function:/^\w+/,generic:{pattern:/<\w+>/,inside:n.languages.v.generic.inside}}}})})(t)}return Ip}var Cp,mw;function eH(){if(mw)return Cp;mw=1,Cp=e,e.displayName="vala",e.aliases=[];function e(t){t.languages.vala=t.languages.extend("clike",{"class-name":[{pattern:/\b[A-Z]\w*(?:\.\w+)*\b(?=(?:\?\s+|\*?\s+\*?)\w)/,inside:{punctuation:/\./}},{pattern:/(\[)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/(\b(?:class|interface)\s+[A-Z]\w*(?:\.\w+)*\s*:\s*)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/((?:\b(?:class|enum|interface|new|struct)\s+)|(?:catch\s+\())[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}}],keyword:/\b(?:abstract|as|assert|async|base|bool|break|case|catch|char|class|const|construct|continue|default|delegate|delete|do|double|dynamic|else|ensures|enum|errordomain|extern|finally|float|for|foreach|get|if|in|inline|int|int16|int32|int64|int8|interface|internal|is|lock|long|namespace|new|null|out|override|owned|params|private|protected|public|ref|requires|return|set|short|signal|sizeof|size_t|ssize_t|static|string|struct|switch|this|throw|throws|try|typeof|uchar|uint|uint16|uint32|uint64|uint8|ulong|unichar|unowned|ushort|using|value|var|virtual|void|volatile|weak|while|yield)\b/i,function:/\b\w+(?=\s*\()/,number:/(?:\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)(?:f|u?l?)?/i,operator:/\+\+|--|&&|\|\||<<=?|>>=?|=>|->|~|[+\-*\/%&^|=!<>]=?|\?\??|\.\.\./,punctuation:/[{}[\];(),.:]/,constant:/\b[A-Z0-9_]+\b/}),t.languages.insertBefore("vala","string",{"raw-string":{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string"},"template-string":{pattern:/@"[\s\S]*?"/,greedy:!0,inside:{interpolation:{pattern:/\$(?:\([^)]*\)|[a-zA-Z]\w*)/,inside:{delimiter:{pattern:/^\$\(?|\)$/,alias:"punctuation"},rest:t.languages.vala}},string:/[\s\S]+/}}}),t.languages.insertBefore("vala","keyword",{regex:{pattern:/\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[imsx]{0,4}(?=\s*(?:$|[\r\n,.;})\]]))/,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:t.languages.regex},"regex-delimiter":/^\//,"regex-flags":/^[a-z]+$/}}})}return Cp}var Np,hw;function tH(){if(hw)return Np;hw=1,Np=e,e.displayName="velocity",e.aliases=[];function e(t){(function(n){n.languages.velocity=n.languages.extend("markup",{});var r={variable:{pattern:/(^|[^\\](?:\\\\)*)\$!?(?:[a-z][\w-]*(?:\([^)]*\))?(?:\.[a-z][\w-]*(?:\([^)]*\))?|\[[^\]]+\])*|\{[^}]+\})/i,lookbehind:!0,inside:{}},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},number:/\b\d+\b/,boolean:/\b(?:false|true)\b/,operator:/[=!<>]=?|[+*/%-]|&&|\|\||\.\.|\b(?:eq|g[et]|l[et]|n(?:e|ot))\b/,punctuation:/[(){}[\]:,.]/};r.variable.inside={string:r.string,function:{pattern:/([^\w-])[a-z][\w-]*(?=\()/,lookbehind:!0},number:r.number,boolean:r.boolean,punctuation:r.punctuation},n.languages.insertBefore("velocity","comment",{unparsed:{pattern:/(^|[^\\])#\[\[[\s\S]*?\]\]#/,lookbehind:!0,greedy:!0,inside:{punctuation:/^#\[\[|\]\]#$/}},"velocity-comment":[{pattern:/(^|[^\\])#\*[\s\S]*?\*#/,lookbehind:!0,greedy:!0,alias:"comment"},{pattern:/(^|[^\\])##.*/,lookbehind:!0,greedy:!0,alias:"comment"}],directive:{pattern:/(^|[^\\](?:\\\\)*)#@?(?:[a-z][\w-]*|\{[a-z][\w-]*\})(?:\s*\((?:[^()]|\([^()]*\))*\))?/i,lookbehind:!0,inside:{keyword:{pattern:/^#@?(?:[a-z][\w-]*|\{[a-z][\w-]*\})|\bin\b/,inside:{punctuation:/[{}]/}},rest:r}},variable:r.variable}),n.languages.velocity.tag.inside["attr-value"].inside.rest=n.languages.velocity})(t)}return Np}var xp,bw;function nH(){if(bw)return xp;bw=1,xp=e,e.displayName="verilog",e.aliases=[];function e(t){t.languages.verilog={comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\//,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"kernel-function":{pattern:/\B\$\w+\b/,alias:"property"},constant:/\B`\w+\b/,function:/\b\w+(?=\()/,keyword:/\b(?:alias|and|assert|assign|assume|automatic|before|begin|bind|bins|binsof|bit|break|buf|bufif0|bufif1|byte|case|casex|casez|cell|chandle|class|clocking|cmos|config|const|constraint|context|continue|cover|covergroup|coverpoint|cross|deassign|default|defparam|design|disable|dist|do|edge|else|end|endcase|endclass|endclocking|endconfig|endfunction|endgenerate|endgroup|endinterface|endmodule|endpackage|endprimitive|endprogram|endproperty|endsequence|endspecify|endtable|endtask|enum|event|expect|export|extends|extern|final|first_match|for|force|foreach|forever|fork|forkjoin|function|generate|genvar|highz0|highz1|if|iff|ifnone|ignore_bins|illegal_bins|import|incdir|include|initial|inout|input|inside|instance|int|integer|interface|intersect|join|join_any|join_none|large|liblist|library|local|localparam|logic|longint|macromodule|matches|medium|modport|module|nand|negedge|new|nmos|nor|noshowcancelled|not|notif0|notif1|null|or|output|package|packed|parameter|pmos|posedge|primitive|priority|program|property|protected|pull0|pull1|pulldown|pullup|pulsestyle_ondetect|pulsestyle_onevent|pure|rand|randc|randcase|randsequence|rcmos|real|realtime|ref|reg|release|repeat|return|rnmos|rpmos|rtran|rtranif0|rtranif1|scalared|sequence|shortint|shortreal|showcancelled|signed|small|solve|specify|specparam|static|string|strong0|strong1|struct|super|supply0|supply1|table|tagged|task|this|throughout|time|timeprecision|timeunit|tran|tranif0|tranif1|tri|tri0|tri1|triand|trior|trireg|type|typedef|union|unique|unsigned|use|uwire|var|vectored|virtual|void|wait|wait_order|wand|weak0|weak1|while|wildcard|wire|with|within|wor|xnor|xor)\b/,important:/\b(?:always|always_comb|always_ff|always_latch)\b(?: *@)?/,number:/\B##?\d+|(?:\b\d+)?'[odbh] ?[\da-fzx_?]+|\b(?:\d*[._])?\d+(?:e[-+]?\d+)?/i,operator:/[-+{}^~%*\/?=!<>&|]+/,punctuation:/[[\];(),.:]/}}return xp}var Op,yw;function rH(){if(yw)return Op;yw=1,Op=e,e.displayName="vhdl",e.aliases=[];function e(t){t.languages.vhdl={comment:/--.+/,"vhdl-vectors":{pattern:/\b[oxb]"[\da-f_]+"|"[01uxzwlh-]+"/i,alias:"number"},"quoted-function":{pattern:/"\S+?"(?=\()/,alias:"function"},string:/"(?:[^\\"\r\n]|\\(?:\r\n|[\s\S]))*"/,constant:/\b(?:library|use)\b/i,keyword:/\b(?:'active|'ascending|'base|'delayed|'driving|'driving_value|'event|'high|'image|'instance_name|'last_active|'last_event|'last_value|'left|'leftof|'length|'low|'path_name|'pos|'pred|'quiet|'range|'reverse_range|'right|'rightof|'simple_name|'stable|'succ|'transaction|'val|'value|access|after|alias|all|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|new|next|null|of|on|open|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|report|return|select|severity|shared|signal|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with)\b/i,boolean:/\b(?:false|true)\b/i,function:/\w+(?=\()/,number:/'[01uxzwlh-]'|\b(?:\d+#[\da-f_.]+#|\d[\d_.]*)(?:e[-+]?\d+)?/i,operator:/[<>]=?|:=|[-+*/&=]|\b(?:abs|and|mod|nand|nor|not|or|rem|rol|ror|sla|sll|sra|srl|xnor|xor)\b/i,punctuation:/[{}[\];(),.:]/}}return Op}var Lp,Ew;function aH(){if(Ew)return Lp;Ew=1,Lp=e,e.displayName="vim",e.aliases=[];function e(t){t.languages.vim={string:/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\r\n]|'')*'/,comment:/".*/,function:/\b\w+(?=\()/,keyword:/\b(?:N|Next|P|Print|X|XMLent|XMLns|ab|abbreviate|abc|abclear|abo|aboveleft|al|all|ar|arga|argadd|argd|argdelete|argdo|arge|argedit|argg|argglobal|argl|arglocal|args|argu|argument|as|ascii|b|bN|bNext|ba|bad|badd|ball|bd|bdelete|be|bel|belowright|bf|bfirst|bl|blast|bm|bmodified|bn|bnext|bo|botright|bp|bprevious|br|brea|break|breaka|breakadd|breakd|breakdel|breakl|breaklist|brewind|bro|browse|bufdo|buffer|buffers|bun|bunload|bw|bwipeout|c|cN|cNext|cNfcNfile|ca|cabbrev|cabc|cabclear|cad|caddb|caddbuffer|caddexpr|caddf|caddfile|cal|call|cat|catch|cb|cbuffer|cc|ccl|cclose|cd|ce|center|cex|cexpr|cf|cfile|cfir|cfirst|cg|cgetb|cgetbuffer|cgete|cgetexpr|cgetfile|change|changes|chd|chdir|che|checkpath|checkt|checktime|cl|cla|clast|clist|clo|close|cmapc|cmapclear|cn|cnew|cnewer|cnext|cnf|cnfile|cnorea|cnoreabbrev|co|col|colder|colo|colorscheme|comc|comclear|comp|compiler|con|conf|confirm|continue|cope|copen|copy|cp|cpf|cpfile|cprevious|cq|cquit|cr|crewind|cu|cuna|cunabbrev|cunmap|cw|cwindow|d|debugg|debuggreedy|delc|delcommand|delete|delf|delfunction|delm|delmarks|di|diffg|diffget|diffoff|diffpatch|diffpu|diffput|diffsplit|diffthis|diffu|diffupdate|dig|digraphs|display|dj|djump|dl|dlist|dr|drop|ds|dsearch|dsp|dsplit|e|earlier|echoe|echoerr|echom|echomsg|echon|edit|el|else|elsei|elseif|em|emenu|en|endf|endfo|endfor|endfun|endfunction|endif|endt|endtry|endw|endwhile|ene|enew|ex|exi|exit|exu|exusage|f|file|files|filetype|fin|fina|finally|find|fini|finish|fir|first|fix|fixdel|fo|fold|foldc|foldclose|foldd|folddoc|folddoclosed|folddoopen|foldo|foldopen|for|fu|fun|function|go|goto|gr|grep|grepa|grepadd|h|ha|hardcopy|help|helpf|helpfind|helpg|helpgrep|helpt|helptags|hid|hide|his|history|ia|iabbrev|iabc|iabclear|if|ij|ijump|il|ilist|imapc|imapclear|in|inorea|inoreabbrev|isearch|isp|isplit|iu|iuna|iunabbrev|iunmap|j|join|ju|jumps|k|kee|keepalt|keepj|keepjumps|keepmarks|l|lN|lNext|lNf|lNfile|la|lad|laddb|laddbuffer|laddexpr|laddf|laddfile|lan|language|last|later|lb|lbuffer|lc|lcd|lch|lchdir|lcl|lclose|left|lefta|leftabove|let|lex|lexpr|lf|lfile|lfir|lfirst|lg|lgetb|lgetbuffer|lgete|lgetexpr|lgetfile|lgr|lgrep|lgrepa|lgrepadd|lh|lhelpgrep|list|ll|lla|llast|lli|llist|lm|lmak|lmake|lmap|lmapc|lmapclear|ln|lne|lnew|lnewer|lnext|lnf|lnfile|lnoremap|lo|loadview|loc|lockmarks|lockv|lockvar|lol|lolder|lop|lopen|lp|lpf|lpfile|lprevious|lr|lrewind|ls|lt|ltag|lu|lunmap|lv|lvimgrep|lvimgrepa|lvimgrepadd|lw|lwindow|m|ma|mak|make|mark|marks|mat|match|menut|menutranslate|mk|mkexrc|mks|mksession|mksp|mkspell|mkv|mkvie|mkview|mkvimrc|mod|mode|move|mz|mzf|mzfile|mzscheme|n|nbkey|new|next|nmapc|nmapclear|noh|nohlsearch|norea|noreabbrev|nu|number|nun|nunmap|o|omapc|omapclear|on|only|open|opt|options|ou|ounmap|p|pc|pclose|pe|ped|pedit|perl|perld|perldo|po|pop|popu|popup|pp|ppop|pre|preserve|prev|previous|print|prof|profd|profdel|profile|promptf|promptfind|promptr|promptrepl|ps|psearch|ptN|ptNext|pta|ptag|ptf|ptfirst|ptj|ptjump|ptl|ptlast|ptn|ptnext|ptp|ptprevious|ptr|ptrewind|pts|ptselect|pu|put|pw|pwd|py|pyf|pyfile|python|q|qa|qall|quit|quita|quitall|r|read|rec|recover|red|redi|redir|redo|redr|redraw|redraws|redrawstatus|reg|registers|res|resize|ret|retab|retu|return|rew|rewind|ri|right|rightb|rightbelow|ru|rub|ruby|rubyd|rubydo|rubyf|rubyfile|runtime|rv|rviminfo|sN|sNext|sa|sal|sall|san|sandbox|sargument|sav|saveas|sb|sbN|sbNext|sba|sball|sbf|sbfirst|sbl|sblast|sbm|sbmodified|sbn|sbnext|sbp|sbprevious|sbr|sbrewind|sbuffer|scrip|scripte|scriptencoding|scriptnames|se|set|setf|setfiletype|setg|setglobal|setl|setlocal|sf|sfind|sfir|sfirst|sh|shell|sign|sil|silent|sim|simalt|sl|sla|slast|sleep|sm|smagic|smap|smapc|smapclear|sme|smenu|sn|snext|sni|sniff|sno|snomagic|snor|snoremap|snoreme|snoremenu|so|sor|sort|source|sp|spe|spelld|spelldump|spellgood|spelli|spellinfo|spellr|spellrepall|spellu|spellundo|spellw|spellwrong|split|spr|sprevious|sre|srewind|st|sta|stag|star|startg|startgreplace|startinsert|startr|startreplace|stj|stjump|stop|stopi|stopinsert|sts|stselect|sun|sunhide|sunm|sunmap|sus|suspend|sv|sview|syncbind|t|tN|tNext|ta|tab|tabN|tabNext|tabc|tabclose|tabd|tabdo|tabe|tabedit|tabf|tabfind|tabfir|tabfirst|tabl|tablast|tabm|tabmove|tabn|tabnew|tabnext|tabo|tabonly|tabp|tabprevious|tabr|tabrewind|tabs|tag|tags|tc|tcl|tcld|tcldo|tclf|tclfile|te|tearoff|tf|tfirst|th|throw|tj|tjump|tl|tlast|tm|tmenu|tn|tnext|to|topleft|tp|tprevious|tr|trewind|try|ts|tselect|tu|tunmenu|u|una|unabbreviate|undo|undoj|undojoin|undol|undolist|unh|unhide|unlet|unlo|unlockvar|unm|unmap|up|update|ve|verb|verbose|version|vert|vertical|vi|vie|view|vim|vimgrep|vimgrepa|vimgrepadd|visual|viu|viusage|vmapc|vmapclear|vne|vnew|vs|vsplit|vu|vunmap|w|wN|wNext|wa|wall|wh|while|win|winc|wincmd|windo|winp|winpos|winsize|wn|wnext|wp|wprevious|wq|wqa|wqall|write|ws|wsverb|wv|wviminfo|x|xa|xall|xit|xm|xmap|xmapc|xmapclear|xme|xmenu|xn|xnoremap|xnoreme|xnoremenu|xu|xunmap|y|yank)\b/,builtin:/\b(?:acd|ai|akm|aleph|allowrevins|altkeymap|ambiwidth|ambw|anti|antialias|arab|arabic|arabicshape|ari|arshape|autochdir|autocmd|autoindent|autoread|autowrite|autowriteall|aw|awa|background|backspace|backup|backupcopy|backupdir|backupext|backupskip|balloondelay|ballooneval|balloonexpr|bdir|bdlay|beval|bex|bexpr|bg|bh|bin|binary|biosk|bioskey|bk|bkc|bomb|breakat|brk|browsedir|bs|bsdir|bsk|bt|bufhidden|buflisted|buftype|casemap|ccv|cdpath|cedit|cfu|ch|charconvert|ci|cin|cindent|cink|cinkeys|cino|cinoptions|cinw|cinwords|clipboard|cmdheight|cmdwinheight|cmp|cms|columns|com|comments|commentstring|compatible|complete|completefunc|completeopt|consk|conskey|copyindent|cot|cpo|cpoptions|cpt|cscopepathcomp|cscopeprg|cscopequickfix|cscopetag|cscopetagorder|cscopeverbose|cspc|csprg|csqf|cst|csto|csverb|cuc|cul|cursorcolumn|cursorline|cwh|debug|deco|def|define|delcombine|dex|dg|dict|dictionary|diff|diffexpr|diffopt|digraph|dip|dir|directory|dy|ea|ead|eadirection|eb|ed|edcompatible|ef|efm|ei|ek|enc|encoding|endofline|eol|ep|equalalways|equalprg|errorbells|errorfile|errorformat|esckeys|et|eventignore|expandtab|exrc|fcl|fcs|fdc|fde|fdi|fdl|fdls|fdm|fdn|fdo|fdt|fen|fenc|fencs|fex|ff|ffs|fileencoding|fileencodings|fileformat|fileformats|fillchars|fk|fkmap|flp|fml|fmr|foldcolumn|foldenable|foldexpr|foldignore|foldlevel|foldlevelstart|foldmarker|foldmethod|foldminlines|foldnestmax|foldtext|formatexpr|formatlistpat|formatoptions|formatprg|fp|fs|fsync|ft|gcr|gd|gdefault|gfm|gfn|gfs|gfw|ghr|gp|grepformat|grepprg|gtl|gtt|guicursor|guifont|guifontset|guifontwide|guiheadroom|guioptions|guipty|guitablabel|guitabtooltip|helpfile|helpheight|helplang|hf|hh|hi|hidden|highlight|hk|hkmap|hkmapp|hkp|hl|hlg|hls|hlsearch|ic|icon|iconstring|ignorecase|im|imactivatekey|imak|imc|imcmdline|imd|imdisable|imi|iminsert|ims|imsearch|inc|include|includeexpr|incsearch|inde|indentexpr|indentkeys|indk|inex|inf|infercase|insertmode|invacd|invai|invakm|invallowrevins|invaltkeymap|invanti|invantialias|invar|invarab|invarabic|invarabicshape|invari|invarshape|invautochdir|invautoindent|invautoread|invautowrite|invautowriteall|invaw|invawa|invbackup|invballooneval|invbeval|invbin|invbinary|invbiosk|invbioskey|invbk|invbl|invbomb|invbuflisted|invcf|invci|invcin|invcindent|invcompatible|invconfirm|invconsk|invconskey|invcopyindent|invcp|invcscopetag|invcscopeverbose|invcst|invcsverb|invcuc|invcul|invcursorcolumn|invcursorline|invdeco|invdelcombine|invdg|invdiff|invdigraph|invdisable|invea|inveb|inved|invedcompatible|invek|invendofline|inveol|invequalalways|inverrorbells|invesckeys|invet|invex|invexpandtab|invexrc|invfen|invfk|invfkmap|invfoldenable|invgd|invgdefault|invguipty|invhid|invhidden|invhk|invhkmap|invhkmapp|invhkp|invhls|invhlsearch|invic|invicon|invignorecase|invim|invimc|invimcmdline|invimd|invincsearch|invinf|invinfercase|invinsertmode|invis|invjoinspaces|invjs|invlazyredraw|invlbr|invlinebreak|invlisp|invlist|invloadplugins|invlpl|invlz|invma|invmacatsui|invmagic|invmh|invml|invmod|invmodeline|invmodifiable|invmodified|invmore|invmousef|invmousefocus|invmousehide|invnu|invnumber|invodev|invopendevice|invpaste|invpi|invpreserveindent|invpreviewwindow|invprompt|invpvw|invreadonly|invremap|invrestorescreen|invrevins|invri|invrightleft|invrightleftcmd|invrl|invrlc|invro|invrs|invru|invruler|invsb|invsc|invscb|invscrollbind|invscs|invsecure|invsft|invshellslash|invshelltemp|invshiftround|invshortname|invshowcmd|invshowfulltag|invshowmatch|invshowmode|invsi|invsm|invsmartcase|invsmartindent|invsmarttab|invsmd|invsn|invsol|invspell|invsplitbelow|invsplitright|invspr|invsr|invssl|invsta|invstartofline|invstmp|invswapfile|invswf|invta|invtagbsearch|invtagrelative|invtagstack|invtbi|invtbidi|invtbs|invtermbidi|invterse|invtextauto|invtextmode|invtf|invtgst|invtildeop|invtimeout|invtitle|invto|invtop|invtr|invttimeout|invttybuiltin|invttyfast|invtx|invvb|invvisualbell|invwa|invwarn|invwb|invweirdinvert|invwfh|invwfw|invwildmenu|invwinfixheight|invwinfixwidth|invwiv|invwmnu|invwrap|invwrapscan|invwrite|invwriteany|invwritebackup|invws|isf|isfname|isi|isident|isk|iskeyword|isprint|joinspaces|js|key|keymap|keymodel|keywordprg|km|kmp|kp|langmap|langmenu|laststatus|lazyredraw|lbr|lcs|linebreak|lines|linespace|lisp|lispwords|listchars|loadplugins|lpl|lsp|lz|macatsui|magic|makeef|makeprg|matchpairs|matchtime|maxcombine|maxfuncdepth|maxmapdepth|maxmem|maxmempattern|maxmemtot|mco|mef|menuitems|mfd|mh|mis|mkspellmem|ml|mls|mm|mmd|mmp|mmt|modeline|modelines|modifiable|modified|more|mouse|mousef|mousefocus|mousehide|mousem|mousemodel|mouses|mouseshape|mouset|mousetime|mp|mps|msm|mzq|mzquantum|nf|noacd|noai|noakm|noallowrevins|noaltkeymap|noanti|noantialias|noar|noarab|noarabic|noarabicshape|noari|noarshape|noautochdir|noautoindent|noautoread|noautowrite|noautowriteall|noaw|noawa|nobackup|noballooneval|nobeval|nobin|nobinary|nobiosk|nobioskey|nobk|nobl|nobomb|nobuflisted|nocf|noci|nocin|nocindent|nocompatible|noconfirm|noconsk|noconskey|nocopyindent|nocp|nocscopetag|nocscopeverbose|nocst|nocsverb|nocuc|nocul|nocursorcolumn|nocursorline|nodeco|nodelcombine|nodg|nodiff|nodigraph|nodisable|noea|noeb|noed|noedcompatible|noek|noendofline|noeol|noequalalways|noerrorbells|noesckeys|noet|noex|noexpandtab|noexrc|nofen|nofk|nofkmap|nofoldenable|nogd|nogdefault|noguipty|nohid|nohidden|nohk|nohkmap|nohkmapp|nohkp|nohls|noic|noicon|noignorecase|noim|noimc|noimcmdline|noimd|noincsearch|noinf|noinfercase|noinsertmode|nois|nojoinspaces|nojs|nolazyredraw|nolbr|nolinebreak|nolisp|nolist|noloadplugins|nolpl|nolz|noma|nomacatsui|nomagic|nomh|noml|nomod|nomodeline|nomodifiable|nomodified|nomore|nomousef|nomousefocus|nomousehide|nonu|nonumber|noodev|noopendevice|nopaste|nopi|nopreserveindent|nopreviewwindow|noprompt|nopvw|noreadonly|noremap|norestorescreen|norevins|nori|norightleft|norightleftcmd|norl|norlc|noro|nors|noru|noruler|nosb|nosc|noscb|noscrollbind|noscs|nosecure|nosft|noshellslash|noshelltemp|noshiftround|noshortname|noshowcmd|noshowfulltag|noshowmatch|noshowmode|nosi|nosm|nosmartcase|nosmartindent|nosmarttab|nosmd|nosn|nosol|nospell|nosplitbelow|nosplitright|nospr|nosr|nossl|nosta|nostartofline|nostmp|noswapfile|noswf|nota|notagbsearch|notagrelative|notagstack|notbi|notbidi|notbs|notermbidi|noterse|notextauto|notextmode|notf|notgst|notildeop|notimeout|notitle|noto|notop|notr|nottimeout|nottybuiltin|nottyfast|notx|novb|novisualbell|nowa|nowarn|nowb|noweirdinvert|nowfh|nowfw|nowildmenu|nowinfixheight|nowinfixwidth|nowiv|nowmnu|nowrap|nowrapscan|nowrite|nowriteany|nowritebackup|nows|nrformats|numberwidth|nuw|odev|oft|ofu|omnifunc|opendevice|operatorfunc|opfunc|osfiletype|pa|para|paragraphs|paste|pastetoggle|patchexpr|patchmode|path|pdev|penc|pex|pexpr|pfn|ph|pheader|pi|pm|pmbcs|pmbfn|popt|preserveindent|previewheight|previewwindow|printdevice|printencoding|printexpr|printfont|printheader|printmbcharset|printmbfont|printoptions|prompt|pt|pumheight|pvh|pvw|qe|quoteescape|readonly|remap|report|restorescreen|revins|rightleft|rightleftcmd|rl|rlc|ro|rs|rtp|ruf|ruler|rulerformat|runtimepath|sbo|sc|scb|scr|scroll|scrollbind|scrolljump|scrolloff|scrollopt|scs|sect|sections|secure|sel|selection|selectmode|sessionoptions|sft|shcf|shellcmdflag|shellpipe|shellquote|shellredir|shellslash|shelltemp|shelltype|shellxquote|shiftround|shiftwidth|shm|shortmess|shortname|showbreak|showcmd|showfulltag|showmatch|showmode|showtabline|shq|si|sidescroll|sidescrolloff|siso|sj|slm|smartcase|smartindent|smarttab|smc|smd|softtabstop|sol|spc|spell|spellcapcheck|spellfile|spelllang|spellsuggest|spf|spl|splitbelow|splitright|sps|sr|srr|ss|ssl|ssop|stal|startofline|statusline|stl|stmp|su|sua|suffixes|suffixesadd|sw|swapfile|swapsync|swb|swf|switchbuf|sws|sxq|syn|synmaxcol|syntax|t_AB|t_AF|t_AL|t_CS|t_CV|t_Ce|t_Co|t_Cs|t_DL|t_EI|t_F1|t_F2|t_F3|t_F4|t_F5|t_F6|t_F7|t_F8|t_F9|t_IE|t_IS|t_K1|t_K3|t_K4|t_K5|t_K6|t_K7|t_K8|t_K9|t_KA|t_KB|t_KC|t_KD|t_KE|t_KF|t_KG|t_KH|t_KI|t_KJ|t_KK|t_KL|t_RI|t_RV|t_SI|t_Sb|t_Sf|t_WP|t_WS|t_ZH|t_ZR|t_al|t_bc|t_cd|t_ce|t_cl|t_cm|t_cs|t_da|t_db|t_dl|t_fs|t_k1|t_k2|t_k3|t_k4|t_k5|t_k6|t_k7|t_k8|t_k9|t_kB|t_kD|t_kI|t_kN|t_kP|t_kb|t_kd|t_ke|t_kh|t_kl|t_kr|t_ks|t_ku|t_le|t_mb|t_md|t_me|t_mr|t_ms|t_nd|t_op|t_se|t_so|t_sr|t_te|t_ti|t_ts|t_ue|t_us|t_ut|t_vb|t_ve|t_vi|t_vs|t_xs|tabline|tabpagemax|tabstop|tagbsearch|taglength|tagrelative|tagstack|tal|tb|tbi|tbidi|tbis|tbs|tenc|term|termbidi|termencoding|terse|textauto|textmode|textwidth|tgst|thesaurus|tildeop|timeout|timeoutlen|title|titlelen|titleold|titlestring|toolbar|toolbariconsize|top|tpm|tsl|tsr|ttimeout|ttimeoutlen|ttm|tty|ttybuiltin|ttyfast|ttym|ttymouse|ttyscroll|ttytype|tw|tx|uc|ul|undolevels|updatecount|updatetime|ut|vb|vbs|vdir|verbosefile|vfile|viewdir|viewoptions|viminfo|virtualedit|visualbell|vop|wak|warn|wb|wc|wcm|wd|weirdinvert|wfh|wfw|whichwrap|wi|wig|wildchar|wildcharm|wildignore|wildmenu|wildmode|wildoptions|wim|winaltkeys|window|winfixheight|winfixwidth|winheight|winminheight|winminwidth|winwidth|wiv|wiw|wm|wmh|wmnu|wmw|wop|wrap|wrapmargin|wrapscan|writeany|writebackup|writedelay|ww)\b/,number:/\b(?:0x[\da-f]+|\d+(?:\.\d+)?)\b/i,operator:/\|\||&&|[-+.]=?|[=!](?:[=~][#?]?)?|[<>]=?[#?]?|[*\/%?]|\b(?:is(?:not)?)\b/,punctuation:/[{}[\](),;:]/}}return Lp}var Dp,Sw;function iH(){if(Sw)return Dp;Sw=1,Dp=e,e.displayName="visualBasic",e.aliases=[];function e(t){t.languages["visual-basic"]={comment:{pattern:/(?:['‘’]|REM\b)(?:[^\r\n_]|_(?:\r\n?|\n)?)*/i,inside:{keyword:/^REM/i}},directive:{pattern:/#(?:Const|Else|ElseIf|End|ExternalChecksum|ExternalSource|If|Region)(?:\b_[ \t]*(?:\r\n?|\n)|.)+/i,alias:"property",greedy:!0},string:{pattern:/\$?["“”](?:["“”]{2}|[^"“”])*["“”]C?/i,greedy:!0},date:{pattern:/#[ \t]*(?:\d+([/-])\d+\1\d+(?:[ \t]+(?:\d+[ \t]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[ \t]*(?:AM|PM))?))?|\d+[ \t]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[ \t]*(?:AM|PM))?)[ \t]*#/i,alias:"number"},number:/(?:(?:\b\d+(?:\.\d+)?|\.\d+)(?:E[+-]?\d+)?|&[HO][\dA-F]+)(?:[FRD]|U?[ILS])?/i,boolean:/\b(?:False|Nothing|True)\b/i,keyword:/\b(?:AddHandler|AddressOf|Alias|And(?:Also)?|As|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|C(?:Bool|Byte|Char|Date|Dbl|Dec|Int|Lng|Obj|SByte|Short|Sng|Str|Type|UInt|ULng|UShort)|Char|Class|Const|Continue|Currency|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else(?:If)?|End(?:If)?|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get(?:Type|XMLNamespace)?|Global|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|IsNot|Let|Lib|Like|Long|Loop|Me|Mod|Module|Must(?:Inherit|Override)|My(?:Base|Class)|Namespace|Narrowing|New|Next|Not(?:Inheritable|Overridable)?|Object|Of|On|Operator|Option(?:al)?|Or(?:Else)?|Out|Overloads|Overridable|Overrides|ParamArray|Partial|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|SByte|Select|Set|Shadows|Shared|short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TryCast|Type|TypeOf|U(?:Integer|Long|Short)|Until|Using|Variant|Wend|When|While|Widening|With(?:Events)?|WriteOnly|Xor)\b/i,operator:/[+\-*/\\^<=>&#@$%!]|\b_(?=[ \t]*[\r\n])/,punctuation:/[{}().,:?]/},t.languages.vb=t.languages["visual-basic"],t.languages.vba=t.languages["visual-basic"]}return Dp}var Mp,vw;function oH(){if(vw)return Mp;vw=1,Mp=e,e.displayName="warpscript",e.aliases=[];function e(t){t.languages.warpscript={comment:/#.*|\/\/.*|\/\*[\s\S]*?\*\//,string:{pattern:/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'|<'(?:[^\\']|'(?!>)|\\.)*'>/,greedy:!0},variable:/\$\S+/,macro:{pattern:/@\S+/,alias:"property"},keyword:/\b(?:BREAK|CHECKMACRO|CONTINUE|CUDF|DEFINED|DEFINEDMACRO|EVAL|FAIL|FOR|FOREACH|FORSTEP|IFT|IFTE|MSGFAIL|NRETURN|RETHROW|RETURN|SWITCH|TRY|UDF|UNTIL|WHILE)\b/,number:/[+-]?\b(?:NaN|Infinity|\d+(?:\.\d*)?(?:[Ee][+-]?\d+)?|0x[\da-fA-F]+|0b[01]+)\b/,boolean:/\b(?:F|T|false|true)\b/,punctuation:/<%|%>|[{}[\]()]/,operator:/==|&&?|\|\|?|\*\*?|>>>?|<<|[<>!~]=?|[-/%^]|\+!?|\b(?:AND|NOT|OR)\b/}}return Mp}var Fp,kw;function sH(){if(kw)return Fp;kw=1,Fp=e,e.displayName="wasm",e.aliases=[];function e(t){t.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/}}return Fp}var Pp,ww;function lH(){if(ww)return Pp;ww=1,Pp=e,e.displayName="webIdl",e.aliases=[];function e(t){(function(n){var r=/(?:\B-|\b_|\b)[A-Za-z][\w-]*(?![\w-])/.source,a="(?:"+/\b(?:unsigned\s+)?long\s+long(?![\w-])/.source+"|"+/\b(?:unrestricted|unsigned)\s+[a-z]+(?![\w-])/.source+"|"+/(?!(?:unrestricted|unsigned)\b)/.source+r+/(?:\s*<(?:[^<>]|<[^<>]*>)*>)?/.source+")"+/(?:\s*\?)?/.source,i={};n.languages["web-idl"]={comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\//,greedy:!0},string:{pattern:/"[^"]*"/,greedy:!0},namespace:{pattern:RegExp(/(\bnamespace\s+)/.source+r),lookbehind:!0},"class-name":[{pattern:/(^|[^\w-])(?:iterable|maplike|setlike)\s*<(?:[^<>]|<[^<>]*>)*>/,lookbehind:!0,inside:i},{pattern:RegExp(/(\b(?:attribute|const|deleter|getter|optional|setter)\s+)/.source+a),lookbehind:!0,inside:i},{pattern:RegExp("("+/\bcallback\s+/.source+r+/\s*=\s*/.source+")"+a),lookbehind:!0,inside:i},{pattern:RegExp(/(\btypedef\b\s*)/.source+a),lookbehind:!0,inside:i},{pattern:RegExp(/(\b(?:callback|dictionary|enum|interface(?:\s+mixin)?)\s+)(?!(?:interface|mixin)\b)/.source+r),lookbehind:!0},{pattern:RegExp(/(:\s*)/.source+r),lookbehind:!0},RegExp(r+/(?=\s+(?:implements|includes)\b)/.source),{pattern:RegExp(/(\b(?:implements|includes)\s+)/.source+r),lookbehind:!0},{pattern:RegExp(a+"(?="+/\s*(?:\.{3}\s*)?/.source+r+/\s*[(),;=]/.source+")"),inside:i}],builtin:/\b(?:ArrayBuffer|BigInt64Array|BigUint64Array|ByteString|DOMString|DataView|Float32Array|Float64Array|FrozenArray|Int16Array|Int32Array|Int8Array|ObservableArray|Promise|USVString|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray)\b/,keyword:[/\b(?:async|attribute|callback|const|constructor|deleter|dictionary|enum|getter|implements|includes|inherit|interface|mixin|namespace|null|optional|or|partial|readonly|required|setter|static|stringifier|typedef|unrestricted)\b/,/\b(?:any|bigint|boolean|byte|double|float|iterable|long|maplike|object|octet|record|sequence|setlike|short|symbol|undefined|unsigned|void)\b/],boolean:/\b(?:false|true)\b/,number:{pattern:/(^|[^\w-])-?(?:0x[0-9a-f]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|NaN|Infinity)(?![\w-])/i,lookbehind:!0},operator:/\.{3}|[=:?<>-]/,punctuation:/[(){}[\].,;]/};for(var o in n.languages["web-idl"])o!=="class-name"&&(i[o]=n.languages["web-idl"][o]);n.languages.webidl=n.languages["web-idl"]})(t)}return Pp}var Up,_w;function uH(){if(_w)return Up;_w=1,Up=e,e.displayName="wiki",e.aliases=[];function e(t){t.languages.wiki=t.languages.extend("markup",{"block-comment":{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0,alias:"comment"},heading:{pattern:/^(=+)[^=\r\n].*?\1/m,inside:{punctuation:/^=+|=+$/,important:/.+/}},emphasis:{pattern:/('{2,5}).+?\1/,inside:{"bold-italic":{pattern:/(''''').+?(?=\1)/,lookbehind:!0,alias:["bold","italic"]},bold:{pattern:/(''')[^'](?:.*?[^'])?(?=\1)/,lookbehind:!0},italic:{pattern:/('')[^'](?:.*?[^'])?(?=\1)/,lookbehind:!0},punctuation:/^''+|''+$/}},hr:{pattern:/^-{4,}/m,alias:"punctuation"},url:[/ISBN +(?:97[89][ -]?)?(?:\d[ -]?){9}[\dx]\b|(?:PMID|RFC) +\d+/i,/\[\[.+?\]\]|\[.+?\]/],variable:[/__[A-Z]+__/,/\{{3}.+?\}{3}/,/\{\{.+?\}\}/],symbol:[/^#redirect/im,/~{3,5}/],"table-tag":{pattern:/((?:^|[|!])[|!])[^|\r\n]+\|(?!\|)/m,lookbehind:!0,inside:{"table-bar":{pattern:/\|$/,alias:"punctuation"},rest:t.languages.markup.tag.inside}},punctuation:/^(?:\{\||\|\}|\|-|[*#:;!|])|\|\||!!/m}),t.languages.insertBefore("wiki","tag",{nowiki:{pattern:/<(nowiki|pre|source)\b[^>]*>[\s\S]*?<\/\1>/i,inside:{tag:{pattern:/<(?:nowiki|pre|source)\b[^>]*>|<\/(?:nowiki|pre|source)>/i,inside:t.languages.markup.tag.inside}}}})}return Up}var Bp,Tw;function cH(){if(Tw)return Bp;Tw=1,Bp=e,e.displayName="wolfram",e.aliases=["mathematica","wl","nb"];function e(t){t.languages.wolfram={comment:/\(\*(?:\(\*(?:[^*]|\*(?!\)))*\*\)|(?!\(\*)[\s\S])*?\*\)/,string:{pattern:/"(?:\\.|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:Abs|AbsArg|Accuracy|Block|Do|For|Function|If|Manipulate|Module|Nest|NestList|None|Return|Switch|Table|Which|While)\b/,context:{pattern:/\b\w+`+\w*/,alias:"class-name"},blank:{pattern:/\b\w+_\b/,alias:"regex"},"global-variable":{pattern:/\$\w+/,alias:"variable"},boolean:/\b(?:False|True)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/\/\.|;|=\.|\^=|\^:=|:=|<<|>>|<\||\|>|:>|\|->|->|<-|@@@|@@|@|\/@|=!=|===|==|=|\+|-|\^|\[\/-+%=\]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},t.languages.mathematica=t.languages.wolfram,t.languages.wl=t.languages.wolfram,t.languages.nb=t.languages.wolfram}return Bp}var $p,Aw;function dH(){if(Aw)return $p;Aw=1,$p=e,e.displayName="wren",e.aliases=[];function e(t){t.languages.wren={comment:[{pattern:/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|\/\*(?:[^*/]|\*(?!\/)|\/(?!\*))*\*\/)*\*\/)*\*\//,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],"triple-quoted-string":{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string"},"string-literal":null,hashbang:{pattern:/^#!\/.+/,greedy:!0,alias:"comment"},attribute:{pattern:/#!?[ \t\u3000]*\w+/,alias:"keyword"},"class-name":[{pattern:/(\bclass\s+)\w+/,lookbehind:!0},/\b[A-Z][a-z\d_]*\b/],constant:/\b[A-Z][A-Z\d_]*\b/,null:{pattern:/\bnull\b/,alias:"keyword"},keyword:/\b(?:as|break|class|construct|continue|else|for|foreign|if|import|in|is|return|static|super|this|var|while)\b/,boolean:/\b(?:false|true)\b/,number:/\b(?:0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/i,function:/\b[a-z_]\w*(?=\s*[({])/i,operator:/<<|>>|[=!<>]=?|&&|\|\||[-+*/%~^&|?:]|\.{2,3}/,punctuation:/[\[\](){}.,;]/},t.languages.wren["string-literal"]={pattern:/(^|[^\\"])"(?:[^\\"%]|\\[\s\S]|%(?!\()|%\((?:[^()]|\((?:[^()]|\([^)]*\))*\))*\))*"/,lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)%\((?:[^()]|\((?:[^()]|\([^)]*\))*\))*\)/,lookbehind:!0,inside:{expression:{pattern:/^(%\()[\s\S]+(?=\)$)/,lookbehind:!0,inside:t.languages.wren},"interpolation-punctuation":{pattern:/^%\(|\)$/,alias:"punctuation"}}},string:/[\s\S]+/}}}return $p}var zp,Rw;function pH(){if(Rw)return zp;Rw=1,zp=e,e.displayName="xeora",e.aliases=["xeoracube"];function e(t){(function(n){n.languages.xeora=n.languages.extend("markup",{constant:{pattern:/\$(?:DomainContents|PageRenderDuration)\$/,inside:{punctuation:{pattern:/\$/}}},variable:{pattern:/\$@?(?:#+|[-+*~=^])?[\w.]+\$/,inside:{punctuation:{pattern:/[$.]/},operator:{pattern:/#+|[-+*~=^@]/}}},"function-inline":{pattern:/\$F:[-\w.]+\?[-\w.]+(?:,(?:(?:@[-#]*\w+\.[\w+.]\.*)*\|)*(?:(?:[\w+]|[-#*.~^]+[\w+]|=\S)(?:[^$=]|=+[^=])*=*|(?:@[-#]*\w+\.[\w+.]\.*)+(?:(?:[\w+]|[-#*~^][-#*.~^]*[\w+]|=\S)(?:[^$=]|=+[^=])*=*)?)?)?\$/,inside:{variable:{pattern:/(?:[,|])@?(?:#+|[-+*~=^])?[\w.]+/,inside:{punctuation:{pattern:/[,.|]/},operator:{pattern:/#+|[-+*~=^@]/}}},punctuation:{pattern:/\$\w:|[$:?.,|]/}},alias:"function"},"function-block":{pattern:/\$XF:\{[-\w.]+\?[-\w.]+(?:,(?:(?:@[-#]*\w+\.[\w+.]\.*)*\|)*(?:(?:[\w+]|[-#*.~^]+[\w+]|=\S)(?:[^$=]|=+[^=])*=*|(?:@[-#]*\w+\.[\w+.]\.*)+(?:(?:[\w+]|[-#*~^][-#*.~^]*[\w+]|=\S)(?:[^$=]|=+[^=])*=*)?)?)?\}:XF\$/,inside:{punctuation:{pattern:/[$:{}?.,|]/}},alias:"function"},"directive-inline":{pattern:/\$\w(?:#\d+\+?)?(?:\[[-\w.]+\])?:[-\/\w.]+\$/,inside:{punctuation:{pattern:/\$(?:\w:|C(?:\[|#\d))?|[:{[\]]/,inside:{tag:{pattern:/#\d/}}}},alias:"function"},"directive-block-open":{pattern:/\$\w+:\{|\$\w(?:#\d+\+?)?(?:\[[-\w.]+\])?:[-\w.]+:\{(?:![A-Z]+)?/,inside:{punctuation:{pattern:/\$(?:\w:|C(?:\[|#\d))?|[:{[\]]/,inside:{tag:{pattern:/#\d/}}},attribute:{pattern:/![A-Z]+$/,inside:{punctuation:{pattern:/!/}},alias:"keyword"}},alias:"function"},"directive-block-separator":{pattern:/\}:[-\w.]+:\{/,inside:{punctuation:{pattern:/[:{}]/}},alias:"function"},"directive-block-close":{pattern:/\}:[-\w.]+\$/,inside:{punctuation:{pattern:/[:{}$]/}},alias:"function"}}),n.languages.insertBefore("inside","punctuation",{variable:n.languages.xeora["function-inline"].inside.variable},n.languages.xeora["function-block"]),n.languages.xeoracube=n.languages.xeora})(t)}return zp}var Gp,Iw;function fH(){if(Iw)return Gp;Iw=1,Gp=e,e.displayName="xmlDoc",e.aliases=[];function e(t){(function(n){function r(s,l){n.languages[s]&&n.languages.insertBefore(s,"comment",{"doc-comment":l})}var a=n.languages.markup.tag,i={pattern:/\/\/\/.*/,greedy:!0,alias:"comment",inside:{tag:a}},o={pattern:/'''.*/,greedy:!0,alias:"comment",inside:{tag:a}};r("csharp",i),r("fsharp",i),r("vbnet",o)})(t)}return Gp}var qp,Cw;function gH(){if(Cw)return qp;Cw=1,qp=e,e.displayName="xojo",e.aliases=[];function e(t){t.languages.xojo={comment:{pattern:/(?:'|\/\/|Rem\b).+/i,greedy:!0},string:{pattern:/"(?:""|[^"])*"/,greedy:!0},number:[/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?/i,/&[bchou][a-z\d]+/i],directive:{pattern:/#(?:Else|ElseIf|Endif|If|Pragma)\b/i,alias:"property"},keyword:/\b(?:AddHandler|App|Array|As(?:signs)?|Auto|Boolean|Break|By(?:Ref|Val)|Byte|Call|Case|Catch|CFStringRef|CGFloat|Class|Color|Const|Continue|CString|Currency|CurrentMethodName|Declare|Delegate|Dim|Do(?:uble|wnTo)?|Each|Else(?:If)?|End|Enumeration|Event|Exception|Exit|Extends|False|Finally|For|Function|Get|GetTypeInfo|Global|GOTO|If|Implements|In|Inherits|Int(?:8|16|32|64|eger|erface)?|Lib|Loop|Me|Module|Next|Nil|Object|Optional|OSType|ParamArray|Private|Property|Protected|PString|Ptr|Raise(?:Event)?|ReDim|RemoveHandler|Return|Select(?:or)?|Self|Set|Shared|Short|Single|Soft|Static|Step|String|Sub|Super|Text|Then|To|True|Try|Ubound|UInt(?:8|16|32|64|eger)?|Until|Using|Var(?:iant)?|Wend|While|WindowPtr|WString)\b/i,operator:/<[=>]?|>=?|[+\-*\/\\^=]|\b(?:AddressOf|And|Ctype|IsA?|Mod|New|Not|Or|WeakAddressOf|Xor)\b/i,punctuation:/[.,;:()]/}}return qp}var jp,Nw;function mH(){if(Nw)return jp;Nw=1,jp=e,e.displayName="xquery",e.aliases=[];function e(t){(function(n){n.languages.xquery=n.languages.extend("markup",{"xquery-comment":{pattern:/\(:[\s\S]*?:\)/,greedy:!0,alias:"comment"},string:{pattern:/(["'])(?:\1\1|(?!\1)[\s\S])*\1/,greedy:!0},extension:{pattern:/\(#.+?#\)/,alias:"symbol"},variable:/\$[-\w:]+/,axis:{pattern:/(^|[^-])(?:ancestor(?:-or-self)?|attribute|child|descendant(?:-or-self)?|following(?:-sibling)?|parent|preceding(?:-sibling)?|self)(?=::)/,lookbehind:!0,alias:"operator"},"keyword-operator":{pattern:/(^|[^:-])\b(?:and|castable as|div|eq|except|ge|gt|idiv|instance of|intersect|is|le|lt|mod|ne|or|union)\b(?=$|[^:-])/,lookbehind:!0,alias:"operator"},keyword:{pattern:/(^|[^:-])\b(?:as|ascending|at|base-uri|boundary-space|case|cast as|collation|construction|copy-namespaces|declare|default|descending|else|empty (?:greatest|least)|encoding|every|external|for|function|if|import|in|inherit|lax|let|map|module|namespace|no-inherit|no-preserve|option|order(?: by|ed|ing)?|preserve|return|satisfies|schema|some|stable|strict|strip|then|to|treat as|typeswitch|unordered|validate|variable|version|where|xquery)\b(?=$|[^:-])/,lookbehind:!0},function:/[\w-]+(?::[\w-]+)*(?=\s*\()/,"xquery-element":{pattern:/(element\s+)[\w-]+(?::[\w-]+)*/,lookbehind:!0,alias:"tag"},"xquery-attribute":{pattern:/(attribute\s+)[\w-]+(?::[\w-]+)*/,lookbehind:!0,alias:"attr-name"},builtin:{pattern:/(^|[^:-])\b(?:attribute|comment|document|element|processing-instruction|text|xs:(?:ENTITIES|ENTITY|ID|IDREFS?|NCName|NMTOKENS?|NOTATION|Name|QName|anyAtomicType|anyType|anyURI|base64Binary|boolean|byte|date|dateTime|dayTimeDuration|decimal|double|duration|float|gDay|gMonth|gMonthDay|gYear|gYearMonth|hexBinary|int|integer|language|long|negativeInteger|nonNegativeInteger|nonPositiveInteger|normalizedString|positiveInteger|short|string|time|token|unsigned(?:Byte|Int|Long|Short)|untyped(?:Atomic)?|yearMonthDuration))\b(?=$|[^:-])/,lookbehind:!0},number:/\b\d+(?:\.\d+)?(?:E[+-]?\d+)?/,operator:[/[+*=?|@]|\.\.?|:=|!=|<[=<]?|>[=>]?/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}],punctuation:/[[\](){},;:/]/}),n.languages.xquery.tag.pattern=/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/,n.languages.xquery.tag.inside["attr-value"].pattern=/=(?:("|')(?:\\[\s\S]|\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}|(?!\1)[^\\])*\1|[^\s'">=]+)/,n.languages.xquery.tag.inside["attr-value"].inside.punctuation=/^="|"$/,n.languages.xquery.tag.inside["attr-value"].inside.expression={pattern:/\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}/,inside:n.languages.xquery,alias:"language-xquery"};var r=function(i){return typeof i=="string"?i:typeof i.content=="string"?i.content:i.content.map(r).join("")},a=function(i){for(var o=[],s=0;s0&&o[o.length-1].tagName===r(l.content[0].content[1])&&o.pop():l.content[l.content.length-1].content==="/>"||o.push({tagName:r(l.content[0].content[1]),openedBraces:0}):o.length>0&&l.type==="punctuation"&&l.content==="{"&&(!i[s+1]||i[s+1].type!=="punctuation"||i[s+1].content!=="{")&&(!i[s-1]||i[s-1].type!=="plain-text"||i[s-1].content!=="{")?o[o.length-1].openedBraces++:o.length>0&&o[o.length-1].openedBraces>0&&l.type==="punctuation"&&l.content==="}"?o[o.length-1].openedBraces--:l.type!=="comment"&&(u=!0)),(u||typeof l=="string")&&o.length>0&&o[o.length-1].openedBraces===0){var d=r(l);s0&&(typeof i[s-1]=="string"||i[s-1].type==="plain-text")&&(d=r(i[s-1])+d,i.splice(s-1,1),s--),/^\s+$/.test(d)?i[s]=d:i[s]=new n.Token("plain-text",d,null,d)}l.content&&typeof l.content!="string"&&a(l.content)}};n.hooks.add("after-tokenize",function(i){i.language==="xquery"&&a(i.tokens)})})(t)}return jp}var Hp,xw;function hH(){if(xw)return Hp;xw=1,Hp=e,e.displayName="yang",e.aliases=[];function e(t){t.languages.yang={comment:/\/\*[\s\S]*?\*\/|\/\/.*/,string:{pattern:/"(?:[^\\"]|\\.)*"|'[^']*'/,greedy:!0},keyword:{pattern:/(^|[{};\r\n][ \t]*)[a-z_][\w.-]*/i,lookbehind:!0},namespace:{pattern:/(\s)[a-z_][\w.-]*(?=:)/i,lookbehind:!0},boolean:/\b(?:false|true)\b/,operator:/\+/,punctuation:/[{};:]/}}return Hp}var Vp,Ow;function bH(){if(Ow)return Vp;Ow=1,Vp=e,e.displayName="zig",e.aliases=[];function e(t){(function(n){function r(d){return function(){return d}}var a=/\b(?:align|allowzero|and|anyframe|anytype|asm|async|await|break|cancel|catch|comptime|const|continue|defer|else|enum|errdefer|error|export|extern|fn|for|if|inline|linksection|nakedcc|noalias|nosuspend|null|or|orelse|packed|promise|pub|resume|return|stdcallcc|struct|suspend|switch|test|threadlocal|try|undefined|union|unreachable|usingnamespace|var|volatile|while)\b/,i="\\b(?!"+a.source+")(?!\\d)\\w+\\b",o=/align\s*\((?:[^()]|\([^()]*\))*\)/.source,s=/(?:\?|\bpromise->|(?:\[[^[\]]*\]|\*(?!\*)|\*\*)(?:\s*|\s*const\b|\s*volatile\b|\s*allowzero\b)*)/.source.replace(//g,r(o)),l=/(?:\bpromise\b|(?:\berror\.)?(?:\.)*(?!\s+))/.source.replace(//g,r(i)),u="(?!\\s)(?:!?\\s*(?:"+s+"\\s*)*"+l+")+";n.languages.zig={comment:[{pattern:/\/\/[/!].*/,alias:"doc-comment"},/\/{2}.*/],string:[{pattern:/(^|[^\\@])c?"(?:[^"\\\r\n]|\\.)*"/,lookbehind:!0,greedy:!0},{pattern:/([\r\n])([ \t]+c?\\{2}).*(?:(?:\r\n?|\n)\2.*)*/,lookbehind:!0,greedy:!0}],char:{pattern:/(^|[^\\])'(?:[^'\\\r\n]|[\uD800-\uDFFF]{2}|\\(?:.|x[a-fA-F\d]{2}|u\{[a-fA-F\d]{1,6}\}))'/,lookbehind:!0,greedy:!0},builtin:/\B@(?!\d)\w+(?=\s*\()/,label:{pattern:/(\b(?:break|continue)\s*:\s*)\w+\b|\b(?!\d)\w+\b(?=\s*:\s*(?:\{|while\b))/,lookbehind:!0},"class-name":[/\b(?!\d)\w+(?=\s*=\s*(?:(?:extern|packed)\s+)?(?:enum|struct|union)\s*[({])/,{pattern:RegExp(/(:\s*)(?=\s*(?:\s*)?[=;,)])|(?=\s*(?:\s*)?\{)/.source.replace(//g,r(u)).replace(//g,r(o))),lookbehind:!0,inside:null},{pattern:RegExp(/(\)\s*)(?=\s*(?:\s*)?;)/.source.replace(//g,r(u)).replace(//g,r(o))),lookbehind:!0,inside:null}],"builtin-type":{pattern:/\b(?:anyerror|bool|c_u?(?:int|long|longlong|short)|c_longdouble|c_void|comptime_(?:float|int)|f(?:16|32|64|128)|[iu](?:8|16|32|64|128|size)|noreturn|type|void)\b/,alias:"keyword"},keyword:a,function:/\b(?!\d)\w+(?=\s*\()/,number:/\b(?:0b[01]+|0o[0-7]+|0x[a-fA-F\d]+(?:\.[a-fA-F\d]*)?(?:[pP][+-]?[a-fA-F\d]+)?|\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)\b/,boolean:/\b(?:false|true)\b/,operator:/\.[*?]|\.{2,3}|[-=]>|\*\*|\+\+|\|\||(?:<<|>>|[-+*]%|[-+*/%^&|<>!=])=?|[?~]/,punctuation:/[.:,;(){}[\]]/},n.languages.zig["class-name"].forEach(function(d){d.inside===null&&(d.inside=n.languages.zig)})})(t)}return Vp}var w=T$,yH=w;w.register(F$());w.register(P$());w.register(U$());w.register(B$());w.register($$());w.register(z$());w.register(G$());w.register(q$());w.register(j$());w.register(H$());w.register(V$());w.register(W$());w.register(Y$());w.register(K$());w.register(X$());w.register(Z$());w.register(Q$());w.register(J$());w.register(ez());w.register(tz());w.register(nz());w.register(rz());w.register(GR());w.register(qR());w.register(az());w.register(iz());w.register(oz());w.register(sz());w.register(lz());w.register(uz());w.register(cz());w.register(dz());w.register(pz());w.register(fz());w.register(tr());w.register(gz());w.register(mz());w.register(hz());w.register(bz());w.register(yz());w.register(Ez());w.register(Sz());w.register(vz());w.register(kz());w.register($m());w.register(wz());w.register(Xo());w.register(_z());w.register(Tz());w.register(Az());w.register(Rz());w.register(Iz());w.register(Cz());w.register(Nz());w.register(xz());w.register(Oz());w.register(Lz());w.register(Dz());w.register(Mz());w.register(Fz());w.register(Pz());w.register(Uz());w.register(Bz());w.register($z());w.register(zz());w.register(Gz());w.register(qz());w.register(jz());w.register(Hz());w.register(Vz());w.register(Wz());w.register(Yz());w.register(Kz());w.register(Xz());w.register(Zz());w.register(Qz());w.register(Jz());w.register(eG());w.register(tG());w.register(nG());w.register(rG());w.register(aG());w.register(iG());w.register(oG());w.register(sG());w.register(lG());w.register(uG());w.register(cG());w.register(dG());w.register(pG());w.register(fG());w.register(gG());w.register(mG());w.register(hG());w.register(zm());w.register(bG());w.register(yG());w.register(EG());w.register(SG());w.register(vG());w.register(kG());w.register(wG());w.register(_G());w.register(TG());w.register(AG());w.register(RG());w.register(IG());w.register(CG());w.register(NG());w.register(xG());w.register(OG());w.register(LG());w.register(Gm());w.register(DG());w.register(Qo());w.register(MG());w.register(FG());w.register(PG());w.register(UG());w.register(BG());w.register($G());w.register(zG());w.register(jm());w.register(GG());w.register(qG());w.register(jG());w.register(HR());w.register(HG());w.register(VG());w.register(WG());w.register(YG());w.register(KG());w.register(XG());w.register(ZG());w.register(QG());w.register(JG());w.register(eq());w.register(tq());w.register(nq());w.register(rq());w.register(aq());w.register(iq());w.register(oq());w.register(jR());w.register(sq());w.register(lq());w.register(uq());w.register(nt());w.register(cq());w.register(dq());w.register(pq());w.register(fq());w.register(gq());w.register(mq());w.register(hq());w.register(bq());w.register(yq());w.register(Eq());w.register(Sq());w.register(vq());w.register(kq());w.register(wq());w.register(_q());w.register(Tq());w.register(Aq());w.register(Rq());w.register(Iq());w.register(Cq());w.register(Nq());w.register(xq());w.register(Oq());w.register(Lq());w.register(Dq());w.register(Mq());w.register(Fq());w.register(Pq());w.register(Uq());w.register(Bq());w.register($q());w.register(zq());w.register(Jo());w.register(Gq());w.register(qq());w.register(jq());w.register(Hq());w.register(Vq());w.register(Wq());w.register(Yq());w.register(Kq());w.register(Xq());w.register(Zq());w.register(Qq());w.register(Jq());w.register(ej());w.register(tj());w.register(nj());w.register(rj());w.register(aj());w.register(ij());w.register(oj());w.register(sj());w.register(lj());w.register(uj());w.register(cj());w.register(dj());w.register(pj());w.register(fj());w.register(gj());w.register(mj());w.register(hj());w.register(bj());w.register(Zo());w.register(yj());w.register(Ej());w.register(Sj());w.register(vj());w.register(Hm());w.register(kj());w.register(wj());w.register(_j());w.register(Tj());w.register(Aj());w.register(Rj());w.register(Ij());w.register(Cj());w.register(Nj());w.register(xj());w.register(Oj());w.register(Lj());w.register(Bm());w.register(Dj());w.register(Mj());w.register(Fj());w.register(Pj());w.register(Uj());w.register(Bj());w.register(Vm());w.register($j());w.register(zj());w.register(Gj());w.register(qj());w.register(jj());w.register(Hj());w.register(Vj());w.register(Wj());w.register(VR());w.register(Yj());w.register(qm());w.register(Kj());w.register(Xj());w.register(Zj());w.register(Qj());w.register(Jj());w.register(eH());w.register(WR());w.register(tH());w.register(nH());w.register(rH());w.register(aH());w.register(iH());w.register(oH());w.register(sH());w.register(lH());w.register(uH());w.register(cH());w.register(dH());w.register(pH());w.register(fH());w.register(gH());w.register(mH());w.register(YR());w.register(hH());w.register(bH());const EH=Wa(yH);var KR=mP(EH,M$);KR.supportedLanguages=hP;const SH={'code[class*="language-"]':{background:"hsl(220, 13%, 18%)",color:"hsl(220, 14%, 71%)",textShadow:"0 1px rgba(0, 0, 0, 0.3)",fontFamily:'"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",lineHeight:"1.5",MozTabSize:"2",OTabSize:"2",tabSize:"2",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none"},'pre[class*="language-"]':{background:"hsl(220, 13%, 18%)",color:"hsl(220, 14%, 71%)",textShadow:"0 1px rgba(0, 0, 0, 0.3)",fontFamily:'"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",lineHeight:"1.5",MozTabSize:"2",OTabSize:"2",tabSize:"2",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none",padding:"1em",margin:"0.5em 0",overflow:"auto",borderRadius:"0.3em"},'code[class*="language-"]::-moz-selection':{background:"hsl(220, 13%, 28%)",color:"inherit",textShadow:"none"},'code[class*="language-"] *::-moz-selection':{background:"hsl(220, 13%, 28%)",color:"inherit",textShadow:"none"},'pre[class*="language-"] *::-moz-selection':{background:"hsl(220, 13%, 28%)",color:"inherit",textShadow:"none"},'code[class*="language-"]::selection':{background:"hsl(220, 13%, 28%)",color:"inherit",textShadow:"none"},'code[class*="language-"] *::selection':{background:"hsl(220, 13%, 28%)",color:"inherit",textShadow:"none"},'pre[class*="language-"] *::selection':{background:"hsl(220, 13%, 28%)",color:"inherit",textShadow:"none"},':not(pre) > code[class*="language-"]':{padding:"0.2em 0.3em",borderRadius:"0.3em",whiteSpace:"normal"},comment:{color:"hsl(220, 10%, 40%)",fontStyle:"italic"},prolog:{color:"hsl(220, 10%, 40%)"},cdata:{color:"hsl(220, 10%, 40%)"},doctype:{color:"hsl(220, 14%, 71%)"},punctuation:{color:"hsl(220, 14%, 71%)"},entity:{color:"hsl(220, 14%, 71%)",cursor:"help"},"attr-name":{color:"hsl(29, 54%, 61%)"},"class-name":{color:"hsl(29, 54%, 61%)"},boolean:{color:"hsl(29, 54%, 61%)"},constant:{color:"hsl(29, 54%, 61%)"},number:{color:"hsl(29, 54%, 61%)"},atrule:{color:"hsl(29, 54%, 61%)"},keyword:{color:"hsl(286, 60%, 67%)"},property:{color:"hsl(355, 65%, 65%)"},tag:{color:"hsl(355, 65%, 65%)"},symbol:{color:"hsl(355, 65%, 65%)"},deleted:{color:"hsl(355, 65%, 65%)"},important:{color:"hsl(355, 65%, 65%)"},selector:{color:"hsl(95, 38%, 62%)"},string:{color:"hsl(95, 38%, 62%)"},char:{color:"hsl(95, 38%, 62%)"},builtin:{color:"hsl(95, 38%, 62%)"},inserted:{color:"hsl(95, 38%, 62%)"},regex:{color:"hsl(95, 38%, 62%)"},"attr-value":{color:"hsl(95, 38%, 62%)"},"attr-value > .token.punctuation":{color:"hsl(95, 38%, 62%)"},variable:{color:"hsl(207, 82%, 66%)"},operator:{color:"hsl(207, 82%, 66%)"},function:{color:"hsl(207, 82%, 66%)"},url:{color:"hsl(187, 47%, 55%)"},"attr-value > .token.punctuation.attr-equals":{color:"hsl(220, 14%, 71%)"},"special-attr > .token.attr-value > .token.value.css":{color:"hsl(220, 14%, 71%)"},".language-css .token.selector":{color:"hsl(355, 65%, 65%)"},".language-css .token.property":{color:"hsl(220, 14%, 71%)"},".language-css .token.function":{color:"hsl(187, 47%, 55%)"},".language-css .token.url > .token.function":{color:"hsl(187, 47%, 55%)"},".language-css .token.url > .token.string.url":{color:"hsl(95, 38%, 62%)"},".language-css .token.important":{color:"hsl(286, 60%, 67%)"},".language-css .token.atrule .token.rule":{color:"hsl(286, 60%, 67%)"},".language-javascript .token.operator":{color:"hsl(286, 60%, 67%)"},".language-javascript .token.template-string > .token.interpolation > .token.interpolation-punctuation.punctuation":{color:"hsl(5, 48%, 51%)"},".language-json .token.operator":{color:"hsl(220, 14%, 71%)"},".language-json .token.null.keyword":{color:"hsl(29, 54%, 61%)"},".language-markdown .token.url":{color:"hsl(220, 14%, 71%)"},".language-markdown .token.url > .token.operator":{color:"hsl(220, 14%, 71%)"},".language-markdown .token.url-reference.url > .token.string":{color:"hsl(220, 14%, 71%)"},".language-markdown .token.url > .token.content":{color:"hsl(207, 82%, 66%)"},".language-markdown .token.url > .token.url":{color:"hsl(187, 47%, 55%)"},".language-markdown .token.url-reference.url":{color:"hsl(187, 47%, 55%)"},".language-markdown .token.blockquote.punctuation":{color:"hsl(220, 10%, 40%)",fontStyle:"italic"},".language-markdown .token.hr.punctuation":{color:"hsl(220, 10%, 40%)",fontStyle:"italic"},".language-markdown .token.code-snippet":{color:"hsl(95, 38%, 62%)"},".language-markdown .token.bold .token.content":{color:"hsl(29, 54%, 61%)"},".language-markdown .token.italic .token.content":{color:"hsl(286, 60%, 67%)"},".language-markdown .token.strike .token.content":{color:"hsl(355, 65%, 65%)"},".language-markdown .token.strike .token.punctuation":{color:"hsl(355, 65%, 65%)"},".language-markdown .token.list.punctuation":{color:"hsl(355, 65%, 65%)"},".language-markdown .token.title.important > .token.punctuation":{color:"hsl(355, 65%, 65%)"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"},namespace:{Opacity:"0.8"},"token.tab:not(:empty):before":{color:"hsla(220, 14%, 71%, 0.15)",textShadow:"none"},"token.cr:before":{color:"hsla(220, 14%, 71%, 0.15)",textShadow:"none"},"token.lf:before":{color:"hsla(220, 14%, 71%, 0.15)",textShadow:"none"},"token.space:before":{color:"hsla(220, 14%, 71%, 0.15)",textShadow:"none"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item":{marginRight:"0.4em"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button":{background:"hsl(220, 13%, 26%)",color:"hsl(220, 9%, 55%)",padding:"0.1em 0.4em",borderRadius:"0.3em"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a":{background:"hsl(220, 13%, 26%)",color:"hsl(220, 9%, 55%)",padding:"0.1em 0.4em",borderRadius:"0.3em"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span":{background:"hsl(220, 13%, 26%)",color:"hsl(220, 9%, 55%)",padding:"0.1em 0.4em",borderRadius:"0.3em"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover":{background:"hsl(220, 13%, 28%)",color:"hsl(220, 14%, 71%)"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus":{background:"hsl(220, 13%, 28%)",color:"hsl(220, 14%, 71%)"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover":{background:"hsl(220, 13%, 28%)",color:"hsl(220, 14%, 71%)"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus":{background:"hsl(220, 13%, 28%)",color:"hsl(220, 14%, 71%)"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover":{background:"hsl(220, 13%, 28%)",color:"hsl(220, 14%, 71%)"},"div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus":{background:"hsl(220, 13%, 28%)",color:"hsl(220, 14%, 71%)"},".line-highlight.line-highlight":{background:"hsla(220, 100%, 80%, 0.04)"},".line-highlight.line-highlight:before":{background:"hsl(220, 13%, 26%)",color:"hsl(220, 14%, 71%)",padding:"0.1em 0.6em",borderRadius:"0.3em",boxShadow:"0 2px 0 0 rgba(0, 0, 0, 0.2)"},".line-highlight.line-highlight[data-end]:after":{background:"hsl(220, 13%, 26%)",color:"hsl(220, 14%, 71%)",padding:"0.1em 0.6em",borderRadius:"0.3em",boxShadow:"0 2px 0 0 rgba(0, 0, 0, 0.2)"},"pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before":{backgroundColor:"hsla(220, 100%, 80%, 0.04)"},".line-numbers.line-numbers .line-numbers-rows":{borderRightColor:"hsla(220, 14%, 71%, 0.15)"},".command-line .command-line-prompt":{borderRightColor:"hsla(220, 14%, 71%, 0.15)"},".line-numbers .line-numbers-rows > span:before":{color:"hsl(220, 14%, 45%)"},".command-line .command-line-prompt > span:before":{color:"hsl(220, 14%, 45%)"},".rainbow-braces .token.token.punctuation.brace-level-1":{color:"hsl(355, 65%, 65%)"},".rainbow-braces .token.token.punctuation.brace-level-5":{color:"hsl(355, 65%, 65%)"},".rainbow-braces .token.token.punctuation.brace-level-9":{color:"hsl(355, 65%, 65%)"},".rainbow-braces .token.token.punctuation.brace-level-2":{color:"hsl(95, 38%, 62%)"},".rainbow-braces .token.token.punctuation.brace-level-6":{color:"hsl(95, 38%, 62%)"},".rainbow-braces .token.token.punctuation.brace-level-10":{color:"hsl(95, 38%, 62%)"},".rainbow-braces .token.token.punctuation.brace-level-3":{color:"hsl(207, 82%, 66%)"},".rainbow-braces .token.token.punctuation.brace-level-7":{color:"hsl(207, 82%, 66%)"},".rainbow-braces .token.token.punctuation.brace-level-11":{color:"hsl(207, 82%, 66%)"},".rainbow-braces .token.token.punctuation.brace-level-4":{color:"hsl(286, 60%, 67%)"},".rainbow-braces .token.token.punctuation.brace-level-8":{color:"hsl(286, 60%, 67%)"},".rainbow-braces .token.token.punctuation.brace-level-12":{color:"hsl(286, 60%, 67%)"},"pre.diff-highlight > code .token.token.deleted:not(.prefix)":{backgroundColor:"hsla(353, 100%, 66%, 0.15)"},"pre > code.diff-highlight .token.token.deleted:not(.prefix)":{backgroundColor:"hsla(353, 100%, 66%, 0.15)"},"pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection":{backgroundColor:"hsla(353, 95%, 66%, 0.25)"},"pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection":{backgroundColor:"hsla(353, 95%, 66%, 0.25)"},"pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection":{backgroundColor:"hsla(353, 95%, 66%, 0.25)"},"pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection":{backgroundColor:"hsla(353, 95%, 66%, 0.25)"},"pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection":{backgroundColor:"hsla(353, 95%, 66%, 0.25)"},"pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection":{backgroundColor:"hsla(353, 95%, 66%, 0.25)"},"pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection":{backgroundColor:"hsla(353, 95%, 66%, 0.25)"},"pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection":{backgroundColor:"hsla(353, 95%, 66%, 0.25)"},"pre.diff-highlight > code .token.token.inserted:not(.prefix)":{backgroundColor:"hsla(137, 100%, 55%, 0.15)"},"pre > code.diff-highlight .token.token.inserted:not(.prefix)":{backgroundColor:"hsla(137, 100%, 55%, 0.15)"},"pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection":{backgroundColor:"hsla(135, 73%, 55%, 0.25)"},"pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection":{backgroundColor:"hsla(135, 73%, 55%, 0.25)"},"pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection":{backgroundColor:"hsla(135, 73%, 55%, 0.25)"},"pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection":{backgroundColor:"hsla(135, 73%, 55%, 0.25)"},"pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection":{backgroundColor:"hsla(135, 73%, 55%, 0.25)"},"pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection":{backgroundColor:"hsla(135, 73%, 55%, 0.25)"},"pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection":{backgroundColor:"hsla(135, 73%, 55%, 0.25)"},"pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection":{backgroundColor:"hsla(135, 73%, 55%, 0.25)"},".prism-previewer.prism-previewer:before":{borderColor:"hsl(224, 13%, 17%)"},".prism-previewer-gradient.prism-previewer-gradient div":{borderColor:"hsl(224, 13%, 17%)",borderRadius:"0.3em"},".prism-previewer-color.prism-previewer-color:before":{borderRadius:"0.3em"},".prism-previewer-easing.prism-previewer-easing:before":{borderRadius:"0.3em"},".prism-previewer.prism-previewer:after":{borderTopColor:"hsl(224, 13%, 17%)"},".prism-previewer-flipped.prism-previewer-flipped.after":{borderBottomColor:"hsl(224, 13%, 17%)"},".prism-previewer-angle.prism-previewer-angle:before":{background:"hsl(219, 13%, 22%)"},".prism-previewer-time.prism-previewer-time:before":{background:"hsl(219, 13%, 22%)"},".prism-previewer-easing.prism-previewer-easing":{background:"hsl(219, 13%, 22%)"},".prism-previewer-angle.prism-previewer-angle circle":{stroke:"hsl(220, 14%, 71%)",strokeOpacity:"1"},".prism-previewer-time.prism-previewer-time circle":{stroke:"hsl(220, 14%, 71%)",strokeOpacity:"1"},".prism-previewer-easing.prism-previewer-easing circle":{stroke:"hsl(220, 14%, 71%)",fill:"transparent"},".prism-previewer-easing.prism-previewer-easing path":{stroke:"hsl(220, 14%, 71%)"},".prism-previewer-easing.prism-previewer-easing line":{stroke:"hsl(220, 14%, 71%)"}},XR=({content:e})=>L.jsx(L0,{remarkPlugins:[VF],components:{code({className:t,children:n,...r}){const a=/language-(\w+)/.exec(t||""),i=String(n).replace(/\n$/,"");return a?L.jsx(KR,{style:SH,language:a[1],PreTag:"div",children:i}):L.jsx("code",{className:t,...r,children:n})}},children:e}),vH=({thinking:e})=>{const[t,n]=W.useState(!1);return e?L.jsxs("div",{className:"chat-msg__thinking",children:[L.jsxs("button",{className:"chat-msg__thinking-toggle",onClick:()=>n(r=>!r),children:[t?"▾":"▸"," Thinking..."]}),t&&L.jsx("div",{className:"chat-msg__thinking-content",children:L.jsx(XR,{content:e})})]}):null},kH=({toolCalls:e})=>!e||e.length===0?null:L.jsx("div",{className:"chat-msg__tools",children:e.map((t,n)=>L.jsxs("span",{className:`chat-msg__tool-badge chat-msg__tool-badge--${t.status}`,children:[t.status==="running"?"⚙ ":t.status==="done"?"✓ ":"✗ ",t.name]},n))}),wH=({sessionMgr:e,sessionId:t,onBack:n})=>{const{getMessages:r,setMessages:a,appendMessage:i,updateLastMessageFull:o,isStreaming:s,setIsStreaming:l,setError:u}=am(),d=r(t),[c,f]=W.useState(""),p=W.useRef(null),h=W.useRef({thinking:"",text:"",toolCalls:[]}),[y,T]=W.useState(!1),[b,g]=W.useState(!0),m=W.useRef(null),v=W.useRef(null),_=W.useCallback(async k=>{if(!(y||!b&&k))try{T(!0);const I=await e.getSessionMessages(t,50,k);if(k){const D=r(t);a(t,[...I.messages,...D])}else a(t,I.messages);g(I.has_more)}catch(I){u(I.message)}finally{T(!1)}},[e,t,a,u,r,y,b]),E=W.useCallback(()=>{const k=v.current;if(k&&k.scrollTop<100&&b&&!y){const I=r(t);I.length>0&&_(I[0].id)}},[b,y,r,t,_]);W.useEffect(()=>{e.subscribeSession(t).catch(console.error),_();const k=e.onStreamEvent(I=>{var q,$,z,H,Y;if(I.session_id!==t)return;const D=I.event_type;if(D==="stream_start"){h.current={thinking:"",text:"",toolCalls:[]},l(!0),i(t,{id:`stream-${Date.now()}`,role:"assistant",content:"",timestamp:new Date().toISOString(),metadata:{thinking:"",toolCalls:[]}});const x=(q=I.payload)==null?void 0:q.user_input;if(x&&x.trim()){const S=[...r(t)].reverse().find(P=>P.role==="user");if(!S||S.content!==x.trim()){const P=r(t),G={id:`user-remote-${Date.now()}`,role:"user",content:x.trim(),timestamp:new Date().toISOString()};a(t,[...P.slice(0,-1),G,P[P.length-1]])}}}else if(D==="text_chunk")h.current.text+=(($=I.payload)==null?void 0:$.text)||"",o(t,h.current.text,{thinking:h.current.thinking,toolCalls:h.current.toolCalls});else if(D==="thinking_chunk")h.current.thinking+=((z=I.payload)==null?void 0:z.content)||"",o(t,h.current.text,{thinking:h.current.thinking,toolCalls:h.current.toolCalls});else if(D==="tool_event"){const x=(H=I.payload)==null?void 0:H.tool_event;(x==null?void 0:x.event_type)==="Started"?(h.current.toolCalls=[...h.current.toolCalls,{name:x.tool_name,status:"running"}],o(t,h.current.text,{thinking:h.current.thinking,toolCalls:h.current.toolCalls})):(x==null?void 0:x.event_type)==="Completed"||(x==null?void 0:x.event_type)==="Succeeded"?(h.current.toolCalls=h.current.toolCalls.map(M=>M.name===x.tool_name&&M.status==="running"?{...M,status:"done"}:M),o(t,h.current.text,{thinking:h.current.thinking,toolCalls:h.current.toolCalls})):(x==null?void 0:x.event_type)==="Failed"&&(h.current.toolCalls=h.current.toolCalls.map(M=>M.name===x.tool_name&&M.status==="running"?{...M,status:"error"}:M),o(t,h.current.text,{thinking:h.current.thinking,toolCalls:h.current.toolCalls}))}else D==="stream_end"?(l(!1),h.current={thinking:"",text:"",toolCalls:[]}):D==="stream_error"?(l(!1),u(((Y=I.payload)==null?void 0:Y.error)||"Stream error"),h.current={thinking:"",text:"",toolCalls:[]}):D==="stream_cancelled"&&(l(!1),h.current={thinking:"",text:"",toolCalls:[]})});return()=>{k(),e.unsubscribeSession(t).catch(console.error)}},[t,e,l,i,o,u,a,r]),W.useEffect(()=>{var k;y||(k=m.current)==null||k.scrollIntoView({behavior:"smooth"})},[d,y]);const R=W.useCallback(async()=>{const k=c.trim();if(!(!k||s)){f(""),i(t,{id:`user-${Date.now()}`,role:"user",content:k,timestamp:new Date().toISOString()});try{await e.sendMessage(t,k)}catch(I){u(I.message)}}},[c,s,t,e,i,u]),C=k=>{k.key==="Enter"&&!k.shiftKey&&(k.preventDefault(),R())},N=async()=>{try{await e.cancelTask(t)}catch{}};return L.jsxs("div",{className:"chat-page",children:[L.jsxs("div",{className:"chat-page__header",children:[L.jsx("button",{className:"chat-page__back",onClick:n,children:"←"}),L.jsx("span",{className:"chat-page__title",children:"Session"}),s&&L.jsx("button",{className:"chat-page__cancel",onClick:N,children:"Stop"})]}),L.jsxs("div",{className:"chat-page__messages",ref:v,onScroll:E,children:[y&&L.jsx("div",{className:"chat-page__loading",children:"Loading older messages..."}),d.map(k=>{var q,$;if(k.role==="system"||k.role==="tool")return null;const I=((q=k.metadata)==null?void 0:q.thinking)||"",D=(($=k.metadata)==null?void 0:$.toolCalls)||[];return L.jsxs("div",{className:`chat-msg chat-msg--${k.role}`,children:[L.jsx("div",{className:"chat-msg__role",children:k.role==="user"?"You":"BitFun"}),L.jsxs("div",{className:"chat-msg__content",children:[k.role==="assistant"&&L.jsxs(L.Fragment,{children:[L.jsx(vH,{thinking:I}),L.jsx(kH,{toolCalls:D})]}),k.content&&L.jsx(XR,{content:k.content}),k.role==="assistant"&&s&&!k.content&&!I&&L.jsx("span",{className:"chat-msg__typing",children:"●●●"})]})]},k.id)}),L.jsx("div",{ref:m})]}),L.jsxs("div",{className:"chat-page__input-bar",children:[L.jsx("textarea",{ref:p,className:"chat-page__input",placeholder:"Type a message...",value:c,onChange:k=>f(k.target.value),onKeyDown:C,rows:1}),L.jsx("button",{className:"chat-page__send",onClick:R,disabled:!c.trim()||s,children:"Send"})]})]})},_H=()=>{const[e,t]=W.useState("pairing"),[n,r]=W.useState(null),a=W.useRef(null),i=W.useRef(null),o=W.useCallback((c,f)=>{a.current=c,i.current=f,c.setMessageHandler(p=>{f.handleMessage(p)}),t("sessions")},[]),s=W.useCallback(()=>{t("workspace")},[]),l=W.useCallback(()=>{t("sessions")},[]),u=W.useCallback(c=>{r(c),t("chat")},[]),d=W.useCallback(()=>{r(null),t("sessions")},[]);return L.jsxs("div",{className:"mobile-app",children:[e==="pairing"&&L.jsx(Zx,{onPaired:o}),e==="workspace"&&i.current&&L.jsx(Qx,{sessionMgr:i.current,onReady:l}),e==="sessions"&&i.current&&L.jsx(tO,{sessionMgr:i.current,onSelectSession:u,onOpenWorkspace:s}),e==="chat"&&i.current&&n&&L.jsx(wH,{sessionMgr:i.current,sessionId:n,onBack:d})]})};Wp.createRoot(document.getElementById("root")).render(L.jsx(Ft.StrictMode,{children:L.jsx(_H,{})})); diff --git a/src/apps/relay-server/static/index.html b/src/apps/relay-server/static/index.html new file mode 100644 index 00000000..f7c493e0 --- /dev/null +++ b/src/apps/relay-server/static/index.html @@ -0,0 +1,18 @@ + + + + + + + BitFun Remote + + + + + +
+ + diff --git a/src/apps/relay-server/test_incremental_upload.py b/src/apps/relay-server/test_incremental_upload.py new file mode 100644 index 00000000..7ac71e4d --- /dev/null +++ b/src/apps/relay-server/test_incremental_upload.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python3 +""" +Test script for the incremental web file upload feature on the relay server. + +Tests: + 1. Create room via WebSocket (keep connection alive) + 2. Legacy full upload (upload-web) with global content store + 3. check-web-files: all files should already exist + 4. check-web-files: 2 existing + 1 new + 5. upload-web-files: only the needed file + 6. Serve uploaded files via /r/{room_id}/ + 7. Second room reuses global store — zero uploads needed + 8. Hash mismatch rejection + +Usage: + python3 test_incremental_upload.py [relay_url] +""" + +import asyncio +import base64 +import hashlib +import json +import sys +import time +import urllib.request +import urllib.error + +try: + import websockets +except ImportError: + print("Installing websockets...") + import subprocess + subprocess.check_call([sys.executable, "-m", "pip", "install", "websockets", "-q"]) + import websockets + +RELAY_URL = sys.argv[1] if len(sys.argv) > 1 else "http://remote.openbitfun.com/relay" +WS_URL = RELAY_URL.replace("http://", "ws://").replace("https://", "wss://") + "/ws" + +PASS = 0 +FAIL = 0 + + +def green(s): + print(f"\033[32m PASS: {s}\033[0m") + + +def red(s): + print(f"\033[31m FAIL: {s}\033[0m") + + +def assert_eq(desc, expected, actual): + global PASS, FAIL + if expected == actual: + green(desc) + PASS += 1 + else: + red(f"{desc} (expected={expected!r}, actual={actual!r})") + FAIL += 1 + + +def assert_contains(desc, haystack, needle): + global PASS, FAIL + if needle in str(haystack): + green(desc) + PASS += 1 + else: + red(f"{desc} (expected to contain {needle!r}, got: {haystack!r})") + FAIL += 1 + + +def b64enc(s: str) -> str: + return base64.b64encode(s.encode()).decode() + + +def sha256hex(s: str) -> str: + return hashlib.sha256(s.encode()).hexdigest() + + +def http_get(url: str) -> tuple: + """Returns (status_code, body_text).""" + try: + req = urllib.request.Request(url) + with urllib.request.urlopen(req, timeout=10) as resp: + return resp.status, resp.read().decode() + except urllib.error.HTTPError as e: + return e.code, e.read().decode() if e.fp else "" + except Exception as e: + return 0, str(e) + + +def http_post_json(url: str, data: dict) -> tuple: + """Returns (status_code, parsed_json_or_None).""" + try: + body = json.dumps(data).encode() + req = urllib.request.Request(url, data=body, method="POST") + req.add_header("Content-Type", "application/json") + with urllib.request.urlopen(req, timeout=10) as resp: + text = resp.read().decode() + try: + return resp.status, json.loads(text) + except json.JSONDecodeError: + return resp.status, text + except urllib.error.HTTPError as e: + text = e.read().decode() if e.fp else "" + try: + return e.code, json.loads(text) + except (json.JSONDecodeError, Exception): + return e.code, text + except Exception as e: + return 0, str(e) + + +async def create_room_ws(room_id: str): + """Create a room via WebSocket and return the connection (kept alive).""" + ws = await websockets.connect(WS_URL) + await ws.send(json.dumps({ + "type": "create_room", + "room_id": room_id, + "device_id": f"test-{room_id}", + "device_type": "desktop", + "public_key": "dGVzdA==", + })) + resp = await asyncio.wait_for(ws.recv(), timeout=5) + data = json.loads(resp) + return ws, data + + +async def run_tests(): + global PASS, FAIL + + ts = int(time.time()) + room1 = f"test_incr_{ts}_1" + room2 = f"test_incr_{ts}_2" + + # Test data + file1_content = "Hello BitFun Test" + file2_content = "body { margin: 0; background: #1a1a2e; }" + file3_content = "console.log('BitFun incremental upload test');" + + file1_b64 = b64enc(file1_content) + file2_b64 = b64enc(file2_content) + file3_b64 = b64enc(file3_content) + + file1_hash = sha256hex(file1_content) + file2_hash = sha256hex(file2_content) + file3_hash = sha256hex(file3_content) + + file1_size = len(file1_content) + file2_size = len(file2_content) + file3_size = len(file3_content) + + print("=" * 50) + print(" Incremental Upload Test Suite") + print(f" Relay: {RELAY_URL}") + print(f" WS: {WS_URL}") + print("=" * 50) + print() + + # ── [0] Health check ── + print("[0] Health check") + status, body = http_get(f"{RELAY_URL}/health") + assert_eq("Server is healthy", 200, status) + assert_contains("Response contains 'healthy'", body, "healthy") + print() + + print("Test files prepared:") + print(f" index.html hash={file1_hash[:12]}... size={file1_size}") + print(f" assets/style.css hash={file2_hash[:12]}... size={file2_size}") + print(f" assets/app.js hash={file3_hash[:12]}... size={file3_size}") + print() + + # ── [1] Create rooms ── + print("[1] Create rooms via WebSocket (kept alive)") + ws1, data1 = await create_room_ws(room1) + assert_eq(f"Room 1 ({room1}) created", "room_created", data1.get("type")) + + ws2, data2 = await create_room_ws(room2) + assert_eq(f"Room 2 ({room2}) created", "room_created", data2.get("type")) + print() + + try: + # ── [2] Legacy full upload ── + print("[2] Legacy full upload (upload-web) to Room 1") + status, resp = http_post_json( + f"{RELAY_URL}/api/rooms/{room1}/upload-web", + {"files": {"index.html": file1_b64, "assets/style.css": file2_b64}}, + ) + assert_eq("HTTP 200", 200, status) + assert_eq("Status is ok", "ok", resp.get("status") if isinstance(resp, dict) else "") + assert_eq("2 new files written", 2, resp.get("files_written", 0) if isinstance(resp, dict) else 0) + assert_eq("0 files reused (first upload)", 0, resp.get("files_reused", 0) if isinstance(resp, dict) else -1) + print() + + # ── [3] Serve uploaded files ── + print("[3] Serve uploaded files via /r/{room_id}/") + status, html = http_get(f"{RELAY_URL}/r/{room1}/index.html") + assert_eq("index.html status 200", 200, status) + assert_eq("index.html content correct", file1_content, html) + + status, css = http_get(f"{RELAY_URL}/r/{room1}/assets/style.css") + assert_eq("style.css status 200", 200, status) + assert_eq("style.css content correct", file2_content, css) + print() + + # ── [4] check-web-files: all exist ── + print("[4] check-web-files: all files should already exist in store") + status, resp = http_post_json( + f"{RELAY_URL}/api/rooms/{room1}/check-web-files", + { + "files": [ + {"path": "index.html", "hash": file1_hash, "size": file1_size}, + {"path": "assets/style.css", "hash": file2_hash, "size": file2_size}, + ] + }, + ) + assert_eq("HTTP 200", 200, status) + needed = resp.get("needed", []) if isinstance(resp, dict) else [] + assert_eq("0 files needed", 0, len(needed)) + assert_eq("2 files exist", 2, resp.get("existing_count", 0) if isinstance(resp, dict) else 0) + assert_eq("Total count 2", 2, resp.get("total_count", 0) if isinstance(resp, dict) else 0) + print() + + # ── [5] check-web-files: 2 existing + 1 new ── + print("[5] check-web-files: 2 existing + 1 new file") + status, resp = http_post_json( + f"{RELAY_URL}/api/rooms/{room1}/check-web-files", + { + "files": [ + {"path": "index.html", "hash": file1_hash, "size": file1_size}, + {"path": "assets/style.css", "hash": file2_hash, "size": file2_size}, + {"path": "assets/app.js", "hash": file3_hash, "size": file3_size}, + ] + }, + ) + assert_eq("HTTP 200", 200, status) + needed = resp.get("needed", []) if isinstance(resp, dict) else [] + assert_eq("1 file needed", 1, len(needed)) + assert_eq("2 files exist", 2, resp.get("existing_count", 0) if isinstance(resp, dict) else 0) + assert_eq("Needed file is assets/app.js", "assets/app.js", needed[0] if needed else "") + print() + + # ── [6] upload-web-files: only needed ── + print("[6] Upload only the needed file via upload-web-files") + status, resp = http_post_json( + f"{RELAY_URL}/api/rooms/{room1}/upload-web-files", + { + "files": { + "assets/app.js": { + "content": file3_b64, + "hash": file3_hash, + } + } + }, + ) + assert_eq("HTTP 200", 200, status) + assert_eq("Status is ok", "ok", resp.get("status") if isinstance(resp, dict) else "") + assert_eq("1 file stored", 1, resp.get("files_stored", 0) if isinstance(resp, dict) else 0) + print() + + # ── [7] Verify newly uploaded file ── + print("[7] Verify newly uploaded file is served") + status, js = http_get(f"{RELAY_URL}/r/{room1}/assets/app.js") + assert_eq("app.js status 200", 200, status) + assert_eq("app.js content correct", file3_content, js) + print() + + # ── [8] Second room: all files reused ── + print("[8] Room 2: check-web-files should find all 3 in global store") + status, resp = http_post_json( + f"{RELAY_URL}/api/rooms/{room2}/check-web-files", + { + "files": [ + {"path": "index.html", "hash": file1_hash, "size": file1_size}, + {"path": "assets/style.css", "hash": file2_hash, "size": file2_size}, + {"path": "assets/app.js", "hash": file3_hash, "size": file3_size}, + ] + }, + ) + assert_eq("HTTP 200", 200, status) + needed = resp.get("needed", []) if isinstance(resp, dict) else [] + assert_eq("0 files needed (all reused)", 0, len(needed)) + assert_eq("3 files exist in global store", 3, resp.get("existing_count", 0) if isinstance(resp, dict) else 0) + print() + + # ── [9] Room 2 files served via symlinks ── + print("[9] Room 2: files served correctly via symlinks") + status, html2 = http_get(f"{RELAY_URL}/r/{room2}/index.html") + assert_eq("Room 2 index.html correct", file1_content, html2) + + status, css2 = http_get(f"{RELAY_URL}/r/{room2}/assets/style.css") + assert_eq("Room 2 style.css correct", file2_content, css2) + + status, js2 = http_get(f"{RELAY_URL}/r/{room2}/assets/app.js") + assert_eq("Room 2 app.js correct", file3_content, js2) + print() + + # ── [10] Hash mismatch rejection ── + print("[10] Upload with wrong hash should be rejected") + status, resp = http_post_json( + f"{RELAY_URL}/api/rooms/{room1}/upload-web-files", + { + "files": { + "bad.js": { + "content": file3_b64, + "hash": "0" * 64, + } + } + }, + ) + assert_eq("Wrong hash returns 400", 400, status) + print() + + # ── [11] check-web-files on nonexistent room ── + print("[11] check-web-files on nonexistent room should return 404") + status, resp = http_post_json( + f"{RELAY_URL}/api/rooms/nonexistent_room/check-web-files", + {"files": [{"path": "a.html", "hash": "abc", "size": 1}]}, + ) + assert_eq("Nonexistent room returns 404", 404, status) + print() + + finally: + await ws1.close() + await ws2.close() + + # ── Summary ── + print("=" * 50) + total = PASS + FAIL + if FAIL == 0: + print(f"\033[32m All {total} tests passed!\033[0m") + else: + print(f" Results: \033[32m{PASS} passed\033[0m, \033[31m{FAIL} failed\033[0m") + print("=" * 50) + + return FAIL == 0 + + +if __name__ == "__main__": + ok = asyncio.run(run_tests()) + sys.exit(0 if ok else 1) diff --git a/src/apps/server/README.md b/src/apps/server/README.md new file mode 100644 index 00000000..687ab94b --- /dev/null +++ b/src/apps/server/README.md @@ -0,0 +1,10 @@ +# BitFun Server (Web App Backend) + +This directory contains the `bitfun-server` application. + +If you are looking for **Remote Connect self-hosted relay deployment**, use: + +- `src/apps/relay-server/README.md` +- `src/apps/relay-server/deploy.sh` + +`src/apps/server` and `src/apps/relay-server` are different components. diff --git a/src/crates/core/Cargo.toml b/src/crates/core/Cargo.toml index 5ff8230b..86e44465 100644 --- a/src/crates/core/Cargo.toml +++ b/src/crates/core/Cargo.toml @@ -60,6 +60,7 @@ portable-pty = { workspace = true } # Command detection (cross-platform) which = { workspace = true } similar = { workspace = true } +urlencoding = { workspace = true } grep-searcher = { workspace = true } grep-regex = { workspace = true } @@ -91,6 +92,24 @@ terminal-core = { path = "src/service/terminal" } fluent-bundle = { workspace = true } unic-langid = { workspace = true } +# Encryption (Remote Connect E2E) +x25519-dalek = { workspace = true } +aes-gcm = { workspace = true } +sha2 = { workspace = true } +rand = { workspace = true } + +# Device/Network info (Remote Connect) +mac_address = { workspace = true } +local-ip-address = { workspace = true } +hostname = { workspace = true } + +# QR code generation +qrcode = { workspace = true } +image = { workspace = true } + +# WebSocket client +tokio-tungstenite = { workspace = true } + # Event layer dependency (lowest layer) bitfun-events = { path = "../events" } diff --git a/src/crates/core/src/agentic/coordination/coordinator.rs b/src/crates/core/src/agentic/coordination/coordinator.rs index a8604dde..f84b8cf4 100644 --- a/src/crates/core/src/agentic/coordination/coordinator.rs +++ b/src/crates/core/src/agentic/coordination/coordinator.rs @@ -82,9 +82,7 @@ impl ConversationCoordinator { agent_type: String, config: SessionConfig, ) -> BitFunResult { - self.session_manager - .create_session(session_name, agent_type, config) - .await + self.create_session_with_workspace(None, session_name, agent_type, config, None).await } /// Create a new session with optional session ID @@ -95,8 +93,49 @@ impl ConversationCoordinator { agent_type: String, config: SessionConfig, ) -> BitFunResult { - self.session_manager + self.create_session_with_workspace(session_id, session_name, agent_type, config, None).await + } + + /// Create a new session with optional session ID and workspace binding. + /// `workspace_path` is forwarded in the `SessionCreated` event and also stored + /// in the session's in-memory config so it can be retrieved without disk access. + pub async fn create_session_with_workspace( + &self, + session_id: Option, + session_name: String, + agent_type: String, + mut config: SessionConfig, + workspace_path: Option, + ) -> BitFunResult { + // Persist the workspace binding inside the session config so that SendMessage + // can retrieve it from memory (no slow disk search needed). + config.workspace_path = workspace_path.clone(); + let session = self + .session_manager .create_session_with_id(session_id, session_name, agent_type, config) + .await?; + self.emit_event(AgenticEvent::SessionCreated { + session_id: session.session_id.clone(), + session_name: session.session_name.clone(), + agent_type: session.agent_type.clone(), + workspace_path, + }) + .await; + Ok(session) + } + + /// Create a subagent session for internal AI execution. + /// Unlike `create_session`, this does NOT emit `SessionCreated` to the transport layer, + /// because subagent sessions are internal implementation details of the execution engine + /// and must never appear as top-level items in the UI. + async fn create_subagent_session( + &self, + session_name: String, + agent_type: String, + config: SessionConfig, + ) -> BitFunResult { + self.session_manager + .create_session_with_id(None, session_name, agent_type, config) .await } @@ -124,12 +163,14 @@ impl ConversationCoordinator { /// Start a new dialog turn /// Note: Events are sent to frontend via EventLoop, no Stream returned + /// skip_tool_confirmation: when true, all tool executions auto-approve (used by remote mobile messages) pub async fn start_dialog_turn( &self, session_id: String, user_input: String, turn_id: Option, agent_type: String, + skip_tool_confirmation: bool, ) -> BitFunResult<()> { // Get latest session (re-fetch each time to ensure latest state) let session = self @@ -290,6 +331,7 @@ impl ConversationCoordinator { agent_type: session.agent_type.clone(), context: context_vars, subagent_parent_info: None, + skip_tool_confirmation, }; // Start async execution task @@ -482,6 +524,16 @@ impl ConversationCoordinator { self.session_manager.get_messages(session_id).await } + /// Get session messages paginated + pub async fn get_messages_paginated( + &self, + session_id: &str, + limit: usize, + before_message_id: Option<&str>, + ) -> BitFunResult<(Vec, bool)> { + self.session_manager.get_messages_paginated(session_id, limit, before_message_id).await + } + /// Subscribe to internal events /// /// For internal systems to subscribe to events (e.g., logging, monitoring) @@ -548,9 +600,12 @@ impl ConversationCoordinator { } } - // Create independent subagent session + // Create independent subagent session. + // Use create_subagent_session (not create_session) so that no SessionCreated + // event is emitted to the transport layer — subagent sessions are internal + // implementation details and must not appear in the UI session list. let session = self - .create_session( + .create_subagent_session( format!("Subagent: {}", task_description), agent_type.clone(), Default::default(), @@ -604,6 +659,7 @@ impl ConversationCoordinator { agent_type: agent_type.clone(), context: context.unwrap_or_default(), subagent_parent_info: Some(subagent_parent_info), + skip_tool_confirmation: false, }; let initial_messages = vec![Message::user(task_description)]; diff --git a/src/crates/core/src/agentic/core/session.rs b/src/crates/core/src/agentic/core/session.rs index 1863a1e3..07ca3186 100644 --- a/src/crates/core/src/agentic/core/session.rs +++ b/src/crates/core/src/agentic/core/session.rs @@ -111,6 +111,10 @@ pub struct SessionConfig { pub enable_context_compression: bool, /// Compression threshold (token usage rate), compression triggered when exceeded pub compression_threshold: f32, + /// Workspace path bound to this session. Used to run AI in the correct workspace + /// without changing the desktop's foreground workspace. + #[serde(skip_serializing_if = "Option::is_none")] + pub workspace_path: Option, } impl Default for SessionConfig { @@ -123,6 +127,7 @@ impl Default for SessionConfig { max_turns: 200, enable_context_compression: true, compression_threshold: 0.8, // 80% + workspace_path: None, } } } diff --git a/src/crates/core/src/agentic/execution/execution_engine.rs b/src/crates/core/src/agentic/execution/execution_engine.rs index 0dcb8f2c..70512430 100644 --- a/src/crates/core/src/agentic/execution/execution_engine.rs +++ b/src/crates/core/src/agentic/execution/execution_engine.rs @@ -440,6 +440,10 @@ impl ExecutionEngine { } // Create round context + let mut round_context_vars = context.context.clone(); + if context.skip_tool_confirmation { + round_context_vars.insert("skip_tool_confirmation".to_string(), "true".to_string()); + } let round_context = RoundContext { session_id: context.session_id.clone(), subagent_parent_info: context.subagent_parent_info.clone(), @@ -454,7 +458,7 @@ impl ExecutionEngine { .cloned() .unwrap_or_else(|| "default".to_string()), agent_type: agent_type.clone(), - context_vars: context.context.clone(), + context_vars: round_context_vars, cancellation_token: CancellationToken::new(), }; diff --git a/src/crates/core/src/agentic/execution/round_executor.rs b/src/crates/core/src/agentic/execution/round_executor.rs index f953027d..9a0a8c84 100644 --- a/src/crates/core/src/agentic/execution/round_executor.rs +++ b/src/crates/core/src/agentic/execution/round_executor.rs @@ -359,8 +359,12 @@ impl RoundExecutor { (None, None, false) // Default: no timeout, requires confirmation }; - // If config skips confirmation, directly return false - let needs_confirm = if skip_confirmation { + let skip_from_context = context.context_vars + .get("skip_tool_confirmation") + .map(|v| v == "true") + .unwrap_or(false); + + let needs_confirm = if skip_confirmation || skip_from_context { false } else { // Otherwise judge based on tool's needs_permissions() diff --git a/src/crates/core/src/agentic/execution/types.rs b/src/crates/core/src/agentic/execution/types.rs index 472a0676..d4fd58ec 100644 --- a/src/crates/core/src/agentic/execution/types.rs +++ b/src/crates/core/src/agentic/execution/types.rs @@ -14,6 +14,7 @@ pub struct ExecutionContext { pub agent_type: String, pub context: HashMap, pub subagent_parent_info: Option, + pub skip_tool_confirmation: bool, } /// Round context diff --git a/src/crates/core/src/agentic/session/history_manager.rs b/src/crates/core/src/agentic/session/history_manager.rs index 64cd9f0d..702ce7b4 100644 --- a/src/crates/core/src/agentic/session/history_manager.rs +++ b/src/crates/core/src/agentic/session/history_manager.rs @@ -90,6 +90,35 @@ impl MessageHistoryManager { Ok(vec![]) } } + + /// Get paginated message history + pub async fn get_messages_paginated( + &self, + session_id: &str, + limit: usize, + before_message_id: Option<&str>, + ) -> BitFunResult<(Vec, bool)> { + let messages = self.get_messages(session_id).await?; + + if messages.is_empty() { + return Ok((vec![], false)); + } + + let end_idx = if let Some(before_id) = before_message_id { + messages.iter().position(|m| m.id == before_id).unwrap_or(0) + } else { + messages.len() + }; + + if end_idx == 0 { + return Ok((vec![], false)); + } + + let start_idx = end_idx.saturating_sub(limit); + let has_more = start_idx > 0; + + Ok((messages[start_idx..end_idx].to_vec(), has_more)) + } /// Get recent N messages pub async fn get_recent_messages(&self, session_id: &str, count: usize) -> BitFunResult> { diff --git a/src/crates/core/src/agentic/session/session_manager.rs b/src/crates/core/src/agentic/session/session_manager.rs index 94c9d92c..f26042ce 100644 --- a/src/crates/core/src/agentic/session/session_manager.rs +++ b/src/crates/core/src/agentic/session/session_manager.rs @@ -581,6 +581,16 @@ impl SessionManager { self.history_manager.get_messages(session_id).await } + /// Get session's message history (paginated) + pub async fn get_messages_paginated( + &self, + session_id: &str, + limit: usize, + before_message_id: Option<&str>, + ) -> BitFunResult<(Vec, bool)> { + self.history_manager.get_messages_paginated(session_id, limit, before_message_id).await + } + /// Get session's context messages (may be compressed) pub async fn get_context_messages(&self, session_id: &str) -> BitFunResult> { // Get context messages from compression manager (may be compressed) diff --git a/src/crates/core/src/service/conversation/persistence_manager.rs b/src/crates/core/src/service/conversation/persistence_manager.rs index c3a7c9fa..9a26d89c 100644 --- a/src/crates/core/src/service/conversation/persistence_manager.rs +++ b/src/crates/core/src/service/conversation/persistence_manager.rs @@ -154,8 +154,6 @@ impl ConversationPersistenceManager { if turn.turn_index >= metadata.turn_count { metadata.turn_count = turn.turn_index + 1; } - metadata.message_count += 1 + turn.model_rounds.len(); - metadata.tool_call_count += turn.count_tool_calls(); self.save_session_metadata(&metadata).await?; } diff --git a/src/crates/core/src/service/conversation/types.rs b/src/crates/core/src/service/conversation/types.rs index aeb79053..564ae260 100644 --- a/src/crates/core/src/service/conversation/types.rs +++ b/src/crates/core/src/service/conversation/types.rs @@ -68,6 +68,10 @@ pub struct SessionMetadata { /// Todo list (for persisting the session's todo state) #[serde(skip_serializing_if = "Option::is_none")] pub todos: Option, + + /// Workspace path this session belongs to (set at creation time) + #[serde(skip_serializing_if = "Option::is_none", alias = "workspace_path")] + pub workspace_path: Option, } /// Session status @@ -349,6 +353,7 @@ impl SessionMetadata { tags: Vec::new(), custom_metadata: None, todos: None, + workspace_path: None, } } diff --git a/src/crates/core/src/service/mod.rs b/src/crates/core/src/service/mod.rs index c6521d00..f7807208 100644 --- a/src/crates/core/src/service/mod.rs +++ b/src/crates/core/src/service/mod.rs @@ -16,6 +16,7 @@ pub mod project_context; // Project context management pub mod runtime; // Managed runtime and capability management pub mod snapshot; // Snapshot-based change tracking pub mod system; // System command detection and execution +pub mod remote_connect; // Remote Connect (phone → desktop) pub mod workspace; // Workspace management // Diff calculation and merge service // Terminal is a standalone crate; re-export it here. diff --git a/src/crates/core/src/service/remote_connect/bot/command_router.rs b/src/crates/core/src/service/remote_connect/bot/command_router.rs new file mode 100644 index 00000000..0d645bd0 --- /dev/null +++ b/src/crates/core/src/service/remote_connect/bot/command_router.rs @@ -0,0 +1,860 @@ +//! Shared command router for bot-based connections (Telegram & Feishu). +//! +//! Provides platform-agnostic command parsing, per-chat state management, and +//! dispatch to workspace / session services. Each platform adapter handles +//! message I/O while this module owns the business logic. + +use log::{error, info}; +use serde::{Deserialize, Serialize}; + +// ── Per-chat state ────────────────────────────────────────────────── + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BotChatState { + pub chat_id: String, + pub paired: bool, + pub current_workspace: Option, + pub current_session_id: Option, + #[serde(skip)] + pub pending_action: Option, +} + +impl BotChatState { + pub fn new(chat_id: String) -> Self { + Self { + chat_id, + paired: false, + current_workspace: None, + current_session_id: None, + pending_action: None, + } + } +} + +#[derive(Debug, Clone)] +pub enum PendingAction { + SelectWorkspace { + options: Vec<(String, String)>, + }, + SelectSession { + options: Vec<(String, String)>, + page: usize, + has_more: bool, + }, +} + +// ── Parsed command ────────────────────────────────────────────────── + +#[derive(Debug)] +pub enum BotCommand { + Start, + SwitchWorkspace, + ResumeSession, + NewCodeSession, + NewCoworkSession, + Help, + PairingCode(String), + NumberSelection(usize), + NextPage, + ChatMessage(String), +} + +// ── Handle result ─────────────────────────────────────────────────── + +pub struct HandleResult { + pub reply: String, + pub forward_to_session: Option, +} + +pub struct ForwardRequest { + pub session_id: String, + pub content: String, + pub agent_type: String, + pub workspace_path: Option, +} + +// ── Command parsing ───────────────────────────────────────────────── + +pub fn parse_command(text: &str) -> BotCommand { + let trimmed = text.trim(); + match trimmed { + "/start" => BotCommand::Start, + "/switch_workspace" => BotCommand::SwitchWorkspace, + "/resume_session" => BotCommand::ResumeSession, + "/new_code_session" => BotCommand::NewCodeSession, + "/new_cowork_session" => BotCommand::NewCoworkSession, + "/help" => BotCommand::Help, + "0" => BotCommand::NextPage, + _ => { + if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) { + BotCommand::PairingCode(trimmed.to_string()) + } else if let Ok(n) = trimmed.parse::() { + if (1..=99).contains(&n) { + BotCommand::NumberSelection(n) + } else { + BotCommand::ChatMessage(trimmed.to_string()) + } + } else { + BotCommand::ChatMessage(trimmed.to_string()) + } + } + } +} + +// ── Static messages ───────────────────────────────────────────────── + +pub const WELCOME_MESSAGE: &str = "\ +Welcome to BitFun! + +To connect your BitFun desktop app, please enter the 6-digit pairing code shown in your BitFun Remote Connect panel. + +Need a pairing code? Open BitFun Desktop -> Remote Connect -> Telegram/Feishu Bot -> copy the 6-digit code and send it here."; + +pub const HELP_MESSAGE: &str = "\ +Available commands: +/switch_workspace - List and switch workspaces +/resume_session - Resume an existing session +/new_code_session - Create a new coding session +/new_cowork_session - Create a new cowork session +/help - Show this help message"; + +pub fn paired_success_message() -> String { + format!("Pairing successful! BitFun is now connected.\n\n{}", HELP_MESSAGE) +} + +// ── Main dispatch ─────────────────────────────────────────────────── + +pub async fn handle_command(state: &mut BotChatState, cmd: BotCommand) -> HandleResult { + match cmd { + BotCommand::Start | BotCommand::Help => { + let reply = if state.paired { + HELP_MESSAGE.to_string() + } else { + WELCOME_MESSAGE.to_string() + }; + HandleResult { reply, forward_to_session: None } + } + BotCommand::PairingCode(_) => HandleResult { + reply: "Pairing codes are handled automatically. If you need to re-pair, \ + please restart the connection from BitFun Desktop." + .to_string(), + forward_to_session: None, + }, + BotCommand::SwitchWorkspace => { + if !state.paired { + return not_paired(); + } + handle_switch_workspace(state).await + } + BotCommand::ResumeSession => { + if !state.paired { + return not_paired(); + } + if state.current_workspace.is_none() { + return need_workspace(); + } + handle_resume_session(state, 0).await + } + BotCommand::NewCodeSession => { + if !state.paired { + return not_paired(); + } + if state.current_workspace.is_none() { + return need_workspace(); + } + handle_new_session(state, "agentic").await + } + BotCommand::NewCoworkSession => { + if !state.paired { + return not_paired(); + } + if state.current_workspace.is_none() { + return need_workspace(); + } + handle_new_session(state, "Cowork").await + } + BotCommand::NumberSelection(n) => { + if !state.paired { + return not_paired(); + } + handle_number_selection(state, n).await + } + BotCommand::NextPage => { + if !state.paired { + return not_paired(); + } + handle_next_page(state).await + } + BotCommand::ChatMessage(msg) => { + if !state.paired { + return not_paired(); + } + handle_chat_message(state, &msg).await + } + } +} + +// ── Helpers ───────────────────────────────────────────────────────── + +fn not_paired() -> HandleResult { + HandleResult { + reply: "Not connected to BitFun Desktop. Please enter the 6-digit pairing code first." + .to_string(), + forward_to_session: None, + } +} + +fn need_workspace() -> HandleResult { + HandleResult { + reply: "No workspace selected. Use /switch_workspace first.".to_string(), + forward_to_session: None, + } +} + +async fn handle_switch_workspace(state: &mut BotChatState) -> HandleResult { + use crate::infrastructure::get_workspace_path; + use crate::service::workspace::get_global_workspace_service; + + let current_ws = get_workspace_path().map(|p| p.to_string_lossy().to_string()); + + let ws_service = match get_global_workspace_service() { + Some(s) => s, + None => { + return HandleResult { + reply: "Workspace service not available.".to_string(), + forward_to_session: None, + }; + } + }; + + let workspaces = ws_service.get_recent_workspaces().await; + if workspaces.is_empty() { + return HandleResult { + reply: "No workspaces found. Please open a project in BitFun Desktop first." + .to_string(), + forward_to_session: None, + }; + } + + // Prefer the bot session's own workspace record; fall back to the desktop + // global path only if the bot has not yet selected one. Using || across + // both sources simultaneously can mark two different workspaces as + // [current] when the desktop and the bot session are on different paths. + let effective_current: Option<&str> = state + .current_workspace + .as_deref() + .or(current_ws.as_deref()); + + let mut text = String::from("Select a workspace:\n\n"); + let mut options: Vec<(String, String)> = Vec::new(); + for (i, ws) in workspaces.iter().enumerate() { + let path = ws.root_path.to_string_lossy().to_string(); + let is_current = effective_current == Some(path.as_str()); + let marker = if is_current { " [current]" } else { "" }; + text.push_str(&format!("{}. {}{}\n {}\n", i + 1, ws.name, marker, path)); + options.push((path, ws.name.clone())); + } + text.push_str("\nReply with the workspace number."); + + state.pending_action = Some(PendingAction::SelectWorkspace { options }); + HandleResult { reply: text, forward_to_session: None } +} + +async fn handle_resume_session(state: &mut BotChatState, page: usize) -> HandleResult { + use crate::infrastructure::PathManager; + use crate::service::conversation::ConversationPersistenceManager; + + let ws_path = match &state.current_workspace { + Some(p) => std::path::PathBuf::from(p), + None => return need_workspace(), + }; + + let page_size = 10usize; + let offset = page * page_size; + + let pm = match PathManager::new() { + Ok(pm) => std::sync::Arc::new(pm), + Err(e) => { + return HandleResult { + reply: format!("Failed to load sessions: {e}"), + forward_to_session: None, + }; + } + }; + + let conv_mgr = match ConversationPersistenceManager::new(pm, ws_path.clone()).await { + Ok(mgr) => mgr, + Err(e) => { + return HandleResult { + reply: format!("Failed to load sessions: {e}"), + forward_to_session: None, + }; + } + }; + + let all_meta = match conv_mgr.get_session_list().await { + Ok(m) => m, + Err(e) => { + return HandleResult { + reply: format!("Failed to list sessions: {e}"), + forward_to_session: None, + }; + } + }; + + if all_meta.is_empty() { + return HandleResult { + reply: "No sessions found in this workspace. Use /new_code_session or \ + /new_cowork_session to create one." + .to_string(), + forward_to_session: None, + }; + } + + let total = all_meta.len(); + let has_more = offset + page_size < total; + let sessions: Vec<_> = all_meta.into_iter().skip(offset).take(page_size).collect(); + + let ws_name = ws_path + .file_name() + .map(|n| n.to_string_lossy().to_string()) + .unwrap_or_else(|| "Unknown".to_string()); + + let mut text = format!("Sessions in {} (page {}):\n\n", ws_name, page + 1); + let mut options: Vec<(String, String)> = Vec::new(); + for (i, s) in sessions.iter().enumerate() { + let is_current = state.current_session_id.as_deref() == Some(&s.session_id); + let marker = if is_current { " [current]" } else { "" }; + let ts = chrono::DateTime::from_timestamp(s.last_active_at as i64 / 1000, 0) + .map(|dt| dt.format("%m-%d %H:%M").to_string()) + .unwrap_or_default(); + let turn_count = s.turn_count; + let msg_hint = if turn_count == 0 { + "no messages".to_string() + } else if turn_count == 1 { + "1 message".to_string() + } else { + format!("{turn_count} messages") + }; + text.push_str(&format!( + "{}. [{}] {}{}\n {} · {}\n", + i + 1, + s.agent_type, + s.session_name, + marker, + ts, + msg_hint, + )); + options.push((s.session_id.clone(), s.session_name.clone())); + } + if has_more { + text.push_str("\n0 - Next page\n"); + } + text.push_str("\nReply with the session number."); + + state.pending_action = Some(PendingAction::SelectSession { options, page, has_more }); + HandleResult { reply: text, forward_to_session: None } +} + +async fn handle_new_session(state: &mut BotChatState, agent_type: &str) -> HandleResult { + use crate::agentic::coordination::get_global_coordinator; + use crate::agentic::core::SessionConfig; + + let coordinator = match get_global_coordinator() { + Some(c) => c, + None => { + return HandleResult { + reply: "BitFun session system not ready.".to_string(), + forward_to_session: None, + }; + } + }; + + let ws_path = state.current_workspace.clone(); + let session_name = match agent_type { + "Cowork" => "Remote Cowork Session", + _ => "Remote Code Session", + }; + + match coordinator + .create_session_with_workspace( + None, + session_name.to_string(), + agent_type.to_string(), + SessionConfig::default(), + ws_path.clone(), + ) + .await + { + Ok(session) => { + let session_id = session.session_id.clone(); + persist_new_session(&session_id, session_name, agent_type, ws_path.as_deref()).await; + state.current_session_id = Some(session_id.clone()); + let label = if agent_type == "Cowork" { "cowork" } else { "coding" }; + let workspace = ws_path.as_deref().unwrap_or("(unknown)"); + HandleResult { + reply: format!( + "Created new {} session: {}\nSession ID: {}\nWorkspace: {}\n\n\ + You can now send messages to interact with the AI agent.", + label, session_name, session_id, workspace + ), + forward_to_session: None, + } + } + Err(e) => HandleResult { + reply: format!("Failed to create session: {e}"), + forward_to_session: None, + }, + } +} + +async fn persist_new_session( + session_id: &str, + session_name: &str, + agent_type: &str, + workspace_path: Option<&str>, +) { + use crate::infrastructure::PathManager; + use crate::service::conversation::{ + ConversationPersistenceManager, SessionMetadata, SessionStatus, + }; + + let Some(wp_str) = workspace_path else { return }; + let wp = std::path::PathBuf::from(wp_str); + + let pm = match PathManager::new() { + Ok(pm) => std::sync::Arc::new(pm), + Err(_) => return, + }; + let conv_mgr = match ConversationPersistenceManager::new(pm, wp).await { + Ok(m) => m, + Err(_) => return, + }; + + let now_ms = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64; + let meta = SessionMetadata { + session_id: session_id.to_string(), + session_name: session_name.to_string(), + agent_type: agent_type.to_string(), + model_name: "default".to_string(), + created_at: now_ms, + last_active_at: now_ms, + turn_count: 0, + message_count: 0, + tool_call_count: 0, + status: SessionStatus::Active, + terminal_session_id: None, + snapshot_session_id: None, + tags: vec![], + custom_metadata: None, + todos: None, + workspace_path: workspace_path.map(String::from), + }; + if let Err(e) = conv_mgr.save_session_metadata(&meta).await { + error!("Failed to persist bot session metadata: {e}"); + } +} + +async fn handle_number_selection(state: &mut BotChatState, n: usize) -> HandleResult { + let pending = state.pending_action.take(); + match pending { + Some(PendingAction::SelectWorkspace { options }) => { + if n < 1 || n > options.len() { + state.pending_action = Some(PendingAction::SelectWorkspace { options }); + return HandleResult { + reply: format!("Invalid selection. Please enter 1-{}.", state.pending_action.as_ref() + .map(|a| match a { PendingAction::SelectWorkspace { options } => options.len(), _ => 0 }) + .unwrap_or(0)), + forward_to_session: None, + }; + } + let (path, name) = options[n - 1].clone(); + select_workspace(state, &path, &name).await + } + Some(PendingAction::SelectSession { options, page, has_more }) => { + if n < 1 || n > options.len() { + let max = options.len(); + state.pending_action = Some(PendingAction::SelectSession { options, page, has_more }); + return HandleResult { + reply: format!("Invalid selection. Please enter 1-{max}."), + forward_to_session: None, + }; + } + let (session_id, session_name) = options[n - 1].clone(); + select_session(state, &session_id, &session_name).await + } + None => handle_chat_message(state, &n.to_string()).await, + } +} + +async fn select_workspace(state: &mut BotChatState, path: &str, name: &str) -> HandleResult { + use crate::service::workspace::get_global_workspace_service; + + let ws_service = match get_global_workspace_service() { + Some(s) => s, + None => { + return HandleResult { + reply: "Workspace service not available.".to_string(), + forward_to_session: None, + }; + } + }; + + let path_buf = std::path::PathBuf::from(path); + match ws_service.open_workspace(path_buf).await { + Ok(info) => { + if let Err(e) = crate::service::snapshot::initialize_global_snapshot_manager( + info.root_path.clone(), + None, + ) + .await + { + error!("Failed to init snapshot after bot workspace switch: {e}"); + } + state.current_workspace = Some(path.to_string()); + state.current_session_id = None; + info!("Bot switched workspace to: {path}"); + + let session_count = count_workspace_sessions(path).await; + let reply = build_workspace_switched_reply(name, session_count); + HandleResult { reply, forward_to_session: None } + } + Err(e) => HandleResult { + reply: format!("Failed to switch workspace: {e}"), + forward_to_session: None, + }, + } +} + +async fn count_workspace_sessions(workspace_path: &str) -> usize { + use crate::infrastructure::PathManager; + use crate::service::conversation::ConversationPersistenceManager; + + let wp = std::path::PathBuf::from(workspace_path); + let pm = match PathManager::new() { + Ok(pm) => std::sync::Arc::new(pm), + Err(_) => return 0, + }; + let conv_mgr = match ConversationPersistenceManager::new(pm, wp).await { + Ok(m) => m, + Err(_) => return 0, + }; + conv_mgr.get_session_list().await.map(|v| v.len()).unwrap_or(0) +} + +fn build_workspace_switched_reply(name: &str, session_count: usize) -> String { + let mut reply = format!("Switched to workspace: {name}\n\n"); + if session_count > 0 { + let s = if session_count == 1 { "" } else { "s" }; + reply.push_str(&format!( + "This workspace has {session_count} existing session{s}. What would you like to do?\n\n\ + /resume_session - Resume an existing session\n\ + /new_code_session - Start a new coding session\n\ + /new_cowork_session - Start a new cowork session" + )); + } else { + reply.push_str( + "No sessions found in this workspace. What would you like to do?\n\n\ + /new_code_session - Start a new coding session\n\ + /new_cowork_session - Start a new cowork session", + ); + } + reply +} + +async fn select_session( + state: &mut BotChatState, + session_id: &str, + session_name: &str, +) -> HandleResult { + use crate::agentic::coordination::get_global_coordinator; + + let coordinator = match get_global_coordinator() { + Some(c) => c, + None => { + state.current_session_id = Some(session_id.to_string()); + info!("Bot resumed session: {session_id}"); + return HandleResult { + reply: format!( + "Resumed session: {session_name}\n\n\ + You can now send messages to interact with the AI agent." + ), + forward_to_session: None, + }; + } + }; + + let _ = coordinator.restore_session(session_id).await; + state.current_session_id = Some(session_id.to_string()); + info!("Bot resumed session: {session_id}"); + + let last_pair = coordinator + .get_messages(session_id) + .await + .ok() + .and_then(|msgs| extract_last_dialog_pair(&msgs)); + + let mut reply = format!("Resumed session: {session_name}\n\n"); + if let Some((user_text, assistant_text)) = last_pair { + reply.push_str("— Last conversation —\n"); + reply.push_str(&format!("You: {user_text}\n\n")); + reply.push_str(&format!("AI: {assistant_text}\n\n")); + reply.push_str("You can continue the conversation."); + } else { + reply.push_str("You can now send messages to interact with the AI agent."); + } + + HandleResult { reply, forward_to_session: None } +} + +fn extract_last_dialog_pair( + messages: &[crate::agentic::core::Message], +) -> Option<(String, String)> { + use crate::agentic::core::MessageRole; + + const MAX_USER_LEN: usize = 200; + const MAX_AI_LEN: usize = 400; + + // Find the index of the last assistant message with readable text. + let assistant_idx = messages.iter().rposition(|m| { + m.role == MessageRole::Assistant && message_text(m).is_some() + })?; + + // Find the last user message that appears before the assistant message. + let user_idx = messages[..assistant_idx].iter().rposition(|m| { + m.role == MessageRole::User && message_text(m).is_some() + })?; + + let user_text = truncate_text(&message_text(&messages[user_idx])?, MAX_USER_LEN); + let assistant_text = truncate_text(&message_text(&messages[assistant_idx])?, MAX_AI_LEN); + + Some((user_text, assistant_text)) +} + +fn message_text(msg: &crate::agentic::core::Message) -> Option { + use crate::agentic::core::{MessageContent, MessageRole}; + let raw = match &msg.content { + MessageContent::Text(t) if !t.trim().is_empty() => t.as_str(), + MessageContent::Mixed { text, .. } if !text.trim().is_empty() => text.as_str(), + _ => return None, + }; + // User messages in agentic mode are wrapped with and may contain + // a trailing block — extract the visible portion only. + let cleaned = if msg.role == MessageRole::User { + strip_user_message_tags(raw) + } else { + raw.trim().to_string() + }; + if cleaned.is_empty() { None } else { Some(cleaned) } +} + +/// Strip XML wrapper tags injected by wrap_user_input before storing the message: +/// \n{content}\n\n... +fn strip_user_message_tags(raw: &str) -> String { + let text = raw.trim(); + + // Extract content inside ... if present. + let inner = if let Some(start) = text.find("") { + let after_open = &text[start + "".len()..]; + if let Some(end) = after_open.find("") { + after_open[..end].trim() + } else { + // Malformed — use everything after the opening tag. + after_open.trim() + } + } else { + text + }; + + // Drop any trailing block. + let result = if let Some(reminder_pos) = inner.find("") { + inner[..reminder_pos].trim() + } else { + inner.trim() + }; + + result.to_string() +} + +fn truncate_text(text: &str, max_chars: usize) -> String { + let trimmed = text.trim(); + if trimmed.chars().count() <= max_chars { + trimmed.to_string() + } else { + let truncated: String = trimmed.chars().take(max_chars).collect(); + format!("{truncated}...") + } +} + +async fn handle_next_page(state: &mut BotChatState) -> HandleResult { + let pending = state.pending_action.take(); + match pending { + Some(PendingAction::SelectSession { page, has_more, .. }) if has_more => { + handle_resume_session(state, page + 1).await + } + Some(action) => { + state.pending_action = Some(action); + HandleResult { + reply: "No more pages available.".to_string(), + forward_to_session: None, + } + } + None => handle_chat_message(state, "0").await, + } +} + +async fn handle_chat_message(state: &mut BotChatState, message: &str) -> HandleResult { + if state.current_workspace.is_none() { + return HandleResult { + reply: "No workspace selected. Use /switch_workspace to select one first.".to_string(), + forward_to_session: None, + }; + } + if state.current_session_id.is_none() { + return HandleResult { + reply: "No active session. Use /resume_session to resume one or \ + /new_code_session to create a new one." + .to_string(), + forward_to_session: None, + }; + } + + let session_id = state.current_session_id.clone().unwrap(); + let workspace_path = state.current_workspace.clone(); + + let agent_type = { + use crate::agentic::coordination::get_global_coordinator; + get_global_coordinator() + .and_then(|c| { + c.get_session_manager() + .get_session(&session_id) + .map(|s| s.agent_type.clone()) + }) + .unwrap_or_else(|| "agentic".to_string()) + }; + + HandleResult { + reply: "Processing your message...".to_string(), + forward_to_session: Some(ForwardRequest { + session_id, + content: message.to_string(), + agent_type, + workspace_path, + }), + } +} + +// ── Forwarded-turn execution ──────────────────────────────────────── + +enum StreamChunk { + Text(String), + Done, + Error(String), +} + +struct BotResponseCollector { + session_id: String, + chunk_tx: tokio::sync::mpsc::UnboundedSender, +} + +#[async_trait::async_trait] +impl crate::agentic::events::EventSubscriber for BotResponseCollector { + async fn on_event( + &self, + event: &crate::agentic::events::AgenticEvent, + ) -> crate::util::errors::BitFunResult<()> { + use bitfun_events::AgenticEvent as AE; + match event { + AE::TextChunk { text, session_id, .. } if session_id == &self.session_id => { + let _ = self.chunk_tx.send(StreamChunk::Text(text.clone())); + } + AE::DialogTurnCompleted { session_id, .. } if session_id == &self.session_id => { + let _ = self.chunk_tx.send(StreamChunk::Done); + } + AE::DialogTurnFailed { session_id, error, .. } if session_id == &self.session_id => { + let _ = self.chunk_tx.send(StreamChunk::Error(error.clone())); + } + _ => {} + } + Ok(()) + } +} + +/// Execute a forwarded dialog turn and return the AI response text. +/// +/// Called from the bot implementations after `handle_command` returns a +/// `ForwardRequest`. Subscribes to session events, starts the turn, and +/// collects text chunks until completion or timeout. +pub async fn execute_forwarded_turn(forward: ForwardRequest) -> String { + use crate::agentic::coordination::get_global_coordinator; + + let coordinator = match get_global_coordinator() { + Some(c) => c, + None => return "Session system not ready.".to_string(), + }; + + if let Some(wp) = &forward.workspace_path { + use crate::infrastructure::{get_workspace_path, set_workspace_path}; + let current = get_workspace_path().map(|p| p.to_string_lossy().to_string()); + if current.as_deref() != Some(wp.as_str()) { + set_workspace_path(Some(std::path::PathBuf::from(wp))); + } + } + + let (chunk_tx, mut chunk_rx) = tokio::sync::mpsc::unbounded_channel::(); + let subscriber_id = format!("bot_forward_{}", uuid::Uuid::new_v4()); + let collector = BotResponseCollector { + session_id: forward.session_id.clone(), + chunk_tx, + }; + coordinator.subscribe_internal(subscriber_id.clone(), collector); + + let turn_id = format!("turn_{}", chrono::Utc::now().timestamp_millis()); + if let Err(e) = coordinator + .start_dialog_turn( + forward.session_id.clone(), + forward.content, + Some(turn_id), + forward.agent_type, + true, + ) + .await + { + coordinator.unsubscribe_internal(&subscriber_id); + return format!("Failed to send message: {e}"); + } + + let sub_id = subscriber_id.clone(); + let result = tokio::time::timeout(std::time::Duration::from_secs(300), async { + let mut response = String::new(); + while let Some(chunk) = chunk_rx.recv().await { + match chunk { + StreamChunk::Text(t) => response.push_str(&t), + StreamChunk::Done => break, + StreamChunk::Error(e) => return format!("Error: {e}"), + } + } + response + }) + .await; + + if let Some(coord) = get_global_coordinator() { + coord.unsubscribe_internal(&sub_id); + } + + match result { + Ok(text) if text.is_empty() => "(No response)".to_string(), + Ok(mut text) => { + const MAX_BOT_MSG_LEN: usize = 4000; + if text.len() > MAX_BOT_MSG_LEN { + text.truncate(MAX_BOT_MSG_LEN); + text.push_str("\n\n... (truncated)"); + } + text + } + Err(_) => "Response timed out after 5 minutes.".to_string(), + } +} diff --git a/src/crates/core/src/service/remote_connect/bot/feishu.rs b/src/crates/core/src/service/remote_connect/bot/feishu.rs new file mode 100644 index 00000000..f5ed821e --- /dev/null +++ b/src/crates/core/src/service/remote_connect/bot/feishu.rs @@ -0,0 +1,716 @@ +//! Feishu (Lark) bot integration for Remote Connect. +//! +//! Users create their own Feishu bot on the Feishu Open Platform and provide +//! App ID + App Secret. The desktop receives messages via Feishu's WebSocket +//! long connection and routes them through the shared command router. + +use anyhow::{anyhow, Result}; +use futures_util::{SinkExt, StreamExt}; +use log::{debug, error, info, warn}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::sync::Arc; +use tokio::sync::RwLock; +use tokio_tungstenite::tungstenite::Message as WsMessage; + +use super::command_router::{ + execute_forwarded_turn, handle_command, paired_success_message, parse_command, BotChatState, + WELCOME_MESSAGE, +}; +use super::{load_bot_persistence, save_bot_persistence, BotConfig, SavedBotConnection}; + +// ── Minimal protobuf codec for Feishu WebSocket binary protocol ───────── + +mod pb { + //! Protobuf codec matching Feishu SDK's pbbp2.proto. + //! Field numbers from pbbp2.pb.go (proto2 with required fields): + //! 1: SeqID (uint64) + //! 2: LogID (uint64) + //! 3: Service (int32) + //! 4: Method (int32) — 0 = control, 1 = data + //! 5: Headers (repeated Header) + //! 6: PayloadEncoding (string) + //! 7: PayloadType (string) + //! 8: Payload (bytes) + //! 9: LogIDNew (string) + + #[derive(Debug, Default, Clone)] + pub struct Frame { + pub seq_id: u64, + pub log_id: u64, + pub service: i32, + pub method: i32, + pub headers: Vec<(String, String)>, + pub payload_encoding: String, + pub payload_type: String, + pub payload: Vec, + pub log_id_new: String, + } + + pub const FRAME_TYPE_CONTROL: i32 = 0; + pub const FRAME_TYPE_DATA: i32 = 1; + + fn decode_varint(data: &[u8], pos: &mut usize) -> Option { + let mut result: u64 = 0; + let mut shift = 0u32; + loop { + if *pos >= data.len() { return None; } + let byte = data[*pos]; + *pos += 1; + result |= ((byte & 0x7F) as u64) << shift; + if byte & 0x80 == 0 { return Some(result); } + shift += 7; + if shift >= 64 { return None; } + } + } + + fn encode_varint(mut val: u64) -> Vec { + let mut buf = Vec::with_capacity(10); + loop { + let mut byte = (val & 0x7F) as u8; + val >>= 7; + if val != 0 { byte |= 0x80; } + buf.push(byte); + if val == 0 { break; } + } + buf + } + + fn read_len<'a>(data: &'a [u8], pos: &mut usize) -> Option<&'a [u8]> { + let len = decode_varint(data, pos)? as usize; + if *pos + len > data.len() { return None; } + let slice = &data[*pos..*pos + len]; + *pos += len; + Some(slice) + } + + fn decode_header(data: &[u8]) -> Option<(String, String)> { + let mut pos = 0; + let (mut key, mut val) = (String::new(), String::new()); + while pos < data.len() { + let tag = decode_varint(data, &mut pos)? as u32; + match (tag >> 3, tag & 7) { + (1, 2) => key = String::from_utf8_lossy(read_len(data, &mut pos)?).into(), + (2, 2) => val = String::from_utf8_lossy(read_len(data, &mut pos)?).into(), + (_, 0) => { decode_varint(data, &mut pos)?; } + (_, 2) => { read_len(data, &mut pos)?; } + _ => return None, + } + } + Some((key, val)) + } + + pub fn decode_frame(data: &[u8]) -> Option { + let mut pos = 0; + let mut f = Frame::default(); + while pos < data.len() { + let tag = decode_varint(data, &mut pos)? as u32; + match (tag >> 3, tag & 7) { + (1, 0) => f.seq_id = decode_varint(data, &mut pos)?, + (2, 0) => f.log_id = decode_varint(data, &mut pos)?, + (3, 0) => f.service = decode_varint(data, &mut pos)? as i32, + (4, 0) => f.method = decode_varint(data, &mut pos)? as i32, + (5, 2) => { + if let Some(h) = decode_header(read_len(data, &mut pos)?) { + f.headers.push(h); + } + } + (6, 2) => f.payload_encoding = String::from_utf8_lossy(read_len(data, &mut pos)?).into(), + (7, 2) => f.payload_type = String::from_utf8_lossy(read_len(data, &mut pos)?).into(), + (8, 2) => f.payload = read_len(data, &mut pos)?.to_vec(), + (9, 2) => f.log_id_new = String::from_utf8_lossy(read_len(data, &mut pos)?).into(), + (_, 0) => { decode_varint(data, &mut pos)?; } + (_, 2) => { read_len(data, &mut pos)?; } + (_, 5) => { pos += 4; } // fixed32 + (_, 1) => { pos += 8; } // fixed64 + _ => return None, + } + } + Some(f) + } + + fn write_varint(buf: &mut Vec, field: u32, val: u64) { + buf.extend(encode_varint(((field << 3) | 0) as u64)); + buf.extend(encode_varint(val)); + } + + fn write_bytes(buf: &mut Vec, field: u32, data: &[u8]) { + buf.extend(encode_varint(((field << 3) | 2) as u64)); + buf.extend(encode_varint(data.len() as u64)); + buf.extend(data); + } + + fn encode_header(key: &str, value: &str) -> Vec { + let mut buf = Vec::new(); + write_bytes(&mut buf, 1, key.as_bytes()); + write_bytes(&mut buf, 2, value.as_bytes()); + buf + } + + pub fn encode_frame(frame: &Frame) -> Vec { + let mut buf = Vec::new(); + write_varint(&mut buf, 1, frame.seq_id); + write_varint(&mut buf, 2, frame.log_id); + write_varint(&mut buf, 3, frame.service as u64); + write_varint(&mut buf, 4, frame.method as u64); + for (k, v) in &frame.headers { + let hdr = encode_header(k, v); + write_bytes(&mut buf, 5, &hdr); + } + if !frame.payload_encoding.is_empty() { + write_bytes(&mut buf, 6, frame.payload_encoding.as_bytes()); + } + if !frame.payload_type.is_empty() { + write_bytes(&mut buf, 7, frame.payload_type.as_bytes()); + } + if !frame.payload.is_empty() { + write_bytes(&mut buf, 8, &frame.payload); + } + if !frame.log_id_new.is_empty() { + write_bytes(&mut buf, 9, frame.log_id_new.as_bytes()); + } + buf + } + + impl Frame { + pub fn get_header(&self, key: &str) -> Option<&str> { + self.headers.iter().find(|(k, _)| k == key).map(|(_, v)| v.as_str()) + } + + pub fn new_ping(service_id: i32) -> Self { + Frame { + method: FRAME_TYPE_CONTROL, + service: service_id, + headers: vec![("type".into(), "ping".into())], + ..Default::default() + } + } + + pub fn new_response(original: &Frame, status_code: u16) -> Self { + let mut headers = original.headers.clone(); + headers.push(("biz_rt".into(), "0".into())); + Frame { + seq_id: original.seq_id, + log_id: original.log_id, + service: original.service, + method: original.method, + headers, + payload: serde_json::to_vec(&serde_json::json!({"code": status_code})).unwrap_or_default(), + log_id_new: original.log_id_new.clone(), + ..Default::default() + } + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FeishuConfig { + pub app_id: String, + pub app_secret: String, +} + +#[derive(Debug, Clone)] +struct FeishuToken { + access_token: String, + expires_at: i64, +} + +pub struct FeishuBot { + config: FeishuConfig, + token: Arc>>, + pending_pairings: Arc>>, + chat_states: Arc>>, +} + +#[derive(Debug, Clone)] +struct PendingPairing { + created_at: i64, +} + +impl FeishuBot { + pub fn new(config: FeishuConfig) -> Self { + Self { + config, + token: Arc::new(RwLock::new(None)), + pending_pairings: Arc::new(RwLock::new(HashMap::new())), + chat_states: Arc::new(RwLock::new(HashMap::new())), + } + } + + pub async fn restore_chat_state(&self, chat_id: &str, state: BotChatState) { + self.chat_states + .write() + .await + .insert(chat_id.to_string(), state); + } + + async fn get_access_token(&self) -> Result { + { + let guard = self.token.read().await; + if let Some(t) = guard.as_ref() { + if t.expires_at > chrono::Utc::now().timestamp() + 60 { + return Ok(t.access_token.clone()); + } + } + } + + let client = reqwest::Client::new(); + let resp = client + .post("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal") + .json(&serde_json::json!({ + "app_id": self.config.app_id, + "app_secret": self.config.app_secret, + })) + .send() + .await + .map_err(|e| anyhow!("feishu token request: {e}"))?; + + let token_resp_text = resp.text().await.unwrap_or_default(); + let body: serde_json::Value = serde_json::from_str(&token_resp_text) + .map_err(|e| anyhow!("feishu token response parse error: {e}, body: {}", &token_resp_text[..token_resp_text.len().min(200)]))?; + let access_token = body["tenant_access_token"] + .as_str() + .ok_or_else(|| anyhow!("missing tenant_access_token in response"))? + .to_string(); + let expire = body["expire"].as_i64().unwrap_or(7200); + + *self.token.write().await = Some(FeishuToken { + access_token: access_token.clone(), + expires_at: chrono::Utc::now().timestamp() + expire, + }); + + info!("Feishu access token refreshed"); + Ok(access_token) + } + + pub async fn send_message(&self, chat_id: &str, content: &str) -> Result<()> { + let token = self.get_access_token().await?; + let client = reqwest::Client::new(); + let resp = client + .post("https://open.feishu.cn/open-apis/im/v1/messages") + .query(&[("receive_id_type", "chat_id")]) + .bearer_auth(&token) + .json(&serde_json::json!({ + "receive_id": chat_id, + "msg_type": "text", + "content": serde_json::to_string(&serde_json::json!({"text": content}))?, + })) + .send() + .await?; + + if !resp.status().is_success() { + let body = resp.text().await.unwrap_or_default(); + return Err(anyhow!("feishu send_message failed: {body}")); + } + debug!("Feishu message sent to {chat_id}"); + Ok(()) + } + + pub async fn register_pairing(&self, pairing_code: &str) -> Result<()> { + self.pending_pairings.write().await.insert( + pairing_code.to_string(), + PendingPairing { + created_at: chrono::Utc::now().timestamp(), + }, + ); + Ok(()) + } + + pub async fn verify_pairing_code(&self, code: &str) -> bool { + let mut pairings = self.pending_pairings.write().await; + if let Some(p) = pairings.remove(code) { + let age = chrono::Utc::now().timestamp() - p.created_at; + return age < 300; + } + false + } + + /// Obtain a WebSocket URL from Feishu for long-connection event delivery. + /// Uses direct AppID/AppSecret auth per Feishu SDK protocol (no bearer token). + async fn get_ws_endpoint(&self) -> Result<(String, serde_json::Value)> { + let client = reqwest::Client::new(); + let resp = client + .post("https://open.feishu.cn/callback/ws/endpoint") + .json(&serde_json::json!({ + "AppID": self.config.app_id, + "AppSecret": self.config.app_secret, + })) + .send() + .await + .map_err(|e| anyhow!("feishu ws endpoint request: {e}"))?; + + let ws_resp_text = resp.text().await.unwrap_or_default(); + let body: serde_json::Value = serde_json::from_str(&ws_resp_text) + .map_err(|e| anyhow!("feishu ws endpoint parse error: {e}, body: {}", &ws_resp_text[..ws_resp_text.len().min(300)]))?; + let code = body["code"].as_i64().unwrap_or(-1); + if code != 0 { + let msg = body["msg"].as_str().unwrap_or("unknown error"); + return Err(anyhow!("feishu ws endpoint error {code}: {msg}")); + } + + let url = body + .pointer("/data/URL") + .and_then(|v| v.as_str()) + .ok_or_else(|| anyhow!("missing WebSocket URL in feishu response"))? + .to_string(); + let client_config = body + .pointer("/data/ClientConfig") + .cloned() + .unwrap_or_default(); + + Ok((url, client_config)) + } + + /// Extract (chat_id, text) from a Feishu WebSocket event message. + fn parse_ws_event(event: &serde_json::Value) -> Option<(String, String)> { + let event_type = event + .pointer("/header/event_type") + .and_then(|v| v.as_str())?; + if event_type != "im.message.receive_v1" { + return None; + } + + let msg_type = event + .pointer("/event/message/message_type") + .and_then(|v| v.as_str())?; + if msg_type != "text" { + return None; + } + + let chat_id = event + .pointer("/event/message/chat_id") + .and_then(|v| v.as_str())? + .to_string(); + let content_str = event + .pointer("/event/message/content") + .and_then(|v| v.as_str())?; + let content: serde_json::Value = serde_json::from_str(content_str).ok()?; + let text = content["text"].as_str()?.trim().to_string(); + Some((chat_id, text)) + } + + /// Handle a single incoming protobuf data frame. + /// Returns Some(chat_id) if pairing succeeded, None to continue waiting. + async fn handle_data_frame_for_pairing( + &self, + frame: &pb::Frame, + write: &Arc>, + WsMessage, + >>>, + ) -> Option { + let msg_type = frame.get_header("type").unwrap_or(""); + if msg_type != "event" { + return None; + } + + let event: serde_json::Value = serde_json::from_slice(&frame.payload).ok()?; + + // Send ack response for this frame + let resp_frame = pb::Frame::new_response(frame, 200); + let _ = write.write().await.send(WsMessage::Binary(pb::encode_frame(&resp_frame))).await; + + if let Some((chat_id, msg_text)) = Self::parse_ws_event(&event) { + let trimmed = msg_text.trim(); + + if trimmed == "/start" { + self.send_message(&chat_id, WELCOME_MESSAGE).await.ok(); + } else if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) { + if self.verify_pairing_code(trimmed).await { + info!("Feishu pairing successful, chat_id={chat_id}"); + let msg = paired_success_message(); + self.send_message(&chat_id, &msg).await.ok(); + + let mut state = BotChatState::new(chat_id.clone()); + state.paired = true; + self.chat_states + .write() + .await + .insert(chat_id.clone(), state.clone()); + self.persist_chat_state(&chat_id, &state).await; + + return Some(chat_id); + } else { + self.send_message(&chat_id, "Invalid or expired pairing code. Please try again.") + .await.ok(); + } + } else { + self.send_message(&chat_id, "Please enter the 6-digit pairing code from BitFun Desktop.") + .await.ok(); + } + } + None + } + + /// Start polling for pairing codes. Returns the chat_id on success. + pub async fn wait_for_pairing(&self) -> Result { + info!("Feishu bot waiting for pairing code via WebSocket..."); + + let (ws_url, config) = self.get_ws_endpoint().await?; + + let (ws_stream, _) = tokio_tungstenite::connect_async(&ws_url) + .await + .map_err(|e| anyhow!("feishu ws connect: {e}"))?; + + let (write, mut read) = ws_stream.split(); + let write = Arc::new(RwLock::new(write)); + info!("Feishu WebSocket connected (binary proto), waiting for pairing..."); + + let service_id = Self::extract_service_id_from_url(&ws_url); + + let ping_interval = config + .get("PingInterval") + .and_then(|v| v.as_u64()) + .unwrap_or(120); + + let mut ping_timer = tokio::time::interval(std::time::Duration::from_secs(ping_interval)); + + loop { + tokio::select! { + msg = read.next() => { + match msg { + Some(Ok(WsMessage::Binary(data))) => { + let frame = match pb::decode_frame(&data) { + Some(f) => f, + None => continue, + }; + match frame.method { + pb::FRAME_TYPE_DATA => { + if let Some(chat_id) = self.handle_data_frame_for_pairing(&frame, &write).await { + return Ok(chat_id); + } + } + pb::FRAME_TYPE_CONTROL => { + debug!("Feishu WS control frame: type={}", frame.get_header("type").unwrap_or("?")); + } + _ => {} + } + } + Some(Ok(WsMessage::Ping(data))) => { + let _ = write.write().await.send(WsMessage::Pong(data)).await; + } + Some(Err(e)) => { + error!("Feishu WebSocket error during pairing: {e}"); + return Err(anyhow!("feishu ws error: {e}")); + } + None => { + return Err(anyhow!("feishu ws connection closed during pairing")); + } + _ => {} + } + } + _ = ping_timer.tick() => { + let ping = pb::Frame::new_ping(service_id); + let _ = write.write().await.send(WsMessage::Binary(pb::encode_frame(&ping))).await; + } + } + } + } + + fn extract_service_id_from_url(url: &str) -> i32 { + url.split('?') + .nth(1) + .and_then(|qs| { + qs.split('&').find_map(|pair| { + let mut kv = pair.splitn(2, '='); + match (kv.next(), kv.next()) { + (Some("service_id"), Some(v)) => v.parse::().ok(), + _ => None, + } + }) + }) + .unwrap_or(0) + } + + /// Main message loop that runs after pairing is complete. + /// Connects to Feishu WebSocket (binary protobuf protocol) and routes + /// incoming messages through the command router. + pub async fn run_message_loop( + self: Arc, + stop_rx: tokio::sync::watch::Receiver, + ) { + info!("Feishu bot message loop started"); + let mut stop = stop_rx; + + loop { + if *stop.borrow() { + info!("Feishu bot message loop stopped by signal"); + break; + } + + let ws_result = self.get_ws_endpoint().await; + let (ws_url, config) = match ws_result { + Ok(v) => v, + Err(e) => { + error!("Failed to get Feishu WS endpoint: {e}"); + tokio::time::sleep(std::time::Duration::from_secs(10)).await; + continue; + } + }; + + let ping_interval = config + .get("PingInterval") + .and_then(|v| v.as_u64()) + .unwrap_or(120); + + let service_id = Self::extract_service_id_from_url(&ws_url); + + let ws_conn = tokio_tungstenite::connect_async(&ws_url).await; + let (ws_stream, _) = match ws_conn { + Ok(v) => v, + Err(e) => { + error!("Feishu WS connect failed: {e}"); + tokio::time::sleep(std::time::Duration::from_secs(10)).await; + continue; + } + }; + info!("Feishu WebSocket connected for message loop (binary proto)"); + + let (write, mut read) = ws_stream.split(); + let write = Arc::new(RwLock::new(write)); + + let mut ping_timer = + tokio::time::interval(std::time::Duration::from_secs(ping_interval)); + + loop { + tokio::select! { + _ = stop.changed() => { + info!("Feishu bot message loop stopped by signal"); + return; + } + msg = read.next() => { + match msg { + Some(Ok(WsMessage::Binary(data))) => { + let frame = match pb::decode_frame(&data) { + Some(f) => f, + None => continue, + }; + + match frame.method { + pb::FRAME_TYPE_DATA => { + let msg_type = frame.get_header("type").unwrap_or(""); + if msg_type == "event" { + if let Ok(event) = serde_json::from_slice::(&frame.payload) { + // Send ack + let resp = pb::Frame::new_response(&frame, 200); + let _ = write.write().await.send(WsMessage::Binary(pb::encode_frame(&resp))).await; + + if let Some((chat_id, msg_text)) = Self::parse_ws_event(&event) { + let bot = self.clone(); + tokio::spawn(async move { + bot.handle_incoming_message(&chat_id, &msg_text).await; + }); + } + } + } + } + pb::FRAME_TYPE_CONTROL => { + debug!("Feishu WS control: type={}", frame.get_header("type").unwrap_or("?")); + } + _ => {} + } + } + Some(Ok(WsMessage::Ping(data))) => { + let _ = write.write().await.send(WsMessage::Pong(data)).await; + } + Some(Err(e)) => { + error!("Feishu WS error: {e}"); + break; + } + None => { + warn!("Feishu WS closed, reconnecting..."); + break; + } + _ => {} + } + } + _ = ping_timer.tick() => { + let ping = pb::Frame::new_ping(service_id); + let _ = write.write().await.send(WsMessage::Binary(pb::encode_frame(&ping))).await; + } + } + } + + let reconnect_interval = config + .get("ReconnectInterval") + .and_then(|v| v.as_u64()) + .unwrap_or(3); + tokio::time::sleep(std::time::Duration::from_secs(reconnect_interval)).await; + } + } + + async fn handle_incoming_message(self: &Arc, chat_id: &str, text: &str) { + let mut states = self.chat_states.write().await; + let state = states + .entry(chat_id.to_string()) + .or_insert_with(|| { + let mut s = BotChatState::new(chat_id.to_string()); + s.paired = true; + s + }); + + if !state.paired { + let trimmed = text.trim(); + if trimmed == "/start" { + self.send_message(chat_id, WELCOME_MESSAGE).await.ok(); + return; + } + if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) { + if self.verify_pairing_code(trimmed).await { + state.paired = true; + let msg = paired_success_message(); + self.send_message(chat_id, &msg).await.ok(); + self.persist_chat_state(chat_id, state).await; + return; + } else { + self.send_message( + chat_id, + "Invalid or expired pairing code. Please try again.", + ) + .await + .ok(); + return; + } + } + self.send_message( + chat_id, + "Please enter the 6-digit pairing code from BitFun Desktop.", + ) + .await + .ok(); + return; + } + + let cmd = parse_command(text); + let result = handle_command(state, cmd).await; + + self.persist_chat_state(chat_id, state).await; + drop(states); + + self.send_message(chat_id, &result.reply).await.ok(); + + if let Some(forward) = result.forward_to_session { + let bot = self.clone(); + let cid = chat_id.to_string(); + tokio::spawn(async move { + let response = execute_forwarded_turn(forward).await; + bot.send_message(&cid, &response).await.ok(); + }); + } + } + + async fn persist_chat_state(&self, chat_id: &str, state: &BotChatState) { + let mut data = load_bot_persistence(); + data.upsert(SavedBotConnection { + bot_type: "feishu".to_string(), + chat_id: chat_id.to_string(), + config: BotConfig::Feishu { + app_id: self.config.app_id.clone(), + app_secret: self.config.app_secret.clone(), + }, + chat_state: state.clone(), + connected_at: chrono::Utc::now().timestamp(), + }); + save_bot_persistence(&data); + } +} diff --git a/src/crates/core/src/service/remote_connect/bot/mod.rs b/src/crates/core/src/service/remote_connect/bot/mod.rs new file mode 100644 index 00000000..8a482664 --- /dev/null +++ b/src/crates/core/src/service/remote_connect/bot/mod.rs @@ -0,0 +1,94 @@ +//! Bot integration for Remote Connect. +//! +//! Supports Feishu and Telegram bots as relay channels. +//! Shared command logic lives in `command_router`; platform-specific +//! I/O is handled by `telegram` and `feishu`. + +pub mod command_router; +pub mod feishu; +pub mod telegram; + +use serde::{Deserialize, Serialize}; + +pub use command_router::{BotChatState, HandleResult, ForwardRequest}; + +/// Configuration for a bot-based connection. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "bot_type", rename_all = "snake_case")] +pub enum BotConfig { + Feishu { + app_id: String, + app_secret: String, + }, + Telegram { + bot_token: String, + }, +} + +/// Pairing state for bot-based connections. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BotPairingInfo { + pub pairing_code: String, + pub bot_type: String, + pub bot_link: String, + pub expires_at: i64, +} + +/// Persisted bot connection — saved to disk so reconnect survives restarts. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SavedBotConnection { + pub bot_type: String, + pub chat_id: String, + pub config: BotConfig, + pub chat_state: BotChatState, + pub connected_at: i64, +} + +/// All persisted bot connections (one per bot type at most). +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct BotPersistenceData { + pub connections: Vec, +} + +impl BotPersistenceData { + pub fn upsert(&mut self, conn: SavedBotConnection) { + self.connections.retain(|c| c.bot_type != conn.bot_type); + self.connections.push(conn); + } + + pub fn remove(&mut self, bot_type: &str) { + self.connections.retain(|c| c.bot_type != bot_type); + } + + pub fn get(&self, bot_type: &str) -> Option<&SavedBotConnection> { + self.connections.iter().find(|c| c.bot_type == bot_type) + } +} + +const BOT_PERSISTENCE_FILENAME: &str = "bot_connections.json"; + +pub fn bot_persistence_path() -> Option { + dirs::home_dir().map(|home| home.join(".bitfun").join(BOT_PERSISTENCE_FILENAME)) +} + +pub fn load_bot_persistence() -> BotPersistenceData { + let Some(path) = bot_persistence_path() else { + return BotPersistenceData::default(); + }; + match std::fs::read_to_string(&path) { + Ok(data) => serde_json::from_str(&data).unwrap_or_default(), + Err(_) => BotPersistenceData::default(), + } +} + +pub fn save_bot_persistence(data: &BotPersistenceData) { + let Some(path) = bot_persistence_path() else { return }; + if let Some(parent) = path.parent() { + let _ = std::fs::create_dir_all(parent); + } + if let Ok(json) = serde_json::to_string_pretty(data) { + if let Err(e) = std::fs::write(&path, json) { + log::error!("Failed to save bot persistence: {e}"); + } + } +} diff --git a/src/crates/core/src/service/remote_connect/bot/telegram.rs b/src/crates/core/src/service/remote_connect/bot/telegram.rs new file mode 100644 index 00000000..cdc59d33 --- /dev/null +++ b/src/crates/core/src/service/remote_connect/bot/telegram.rs @@ -0,0 +1,323 @@ +//! Telegram bot integration for Remote Connect. +//! +//! Users create their own bot via @BotFather, obtain a token, and enter it +//! in BitFun settings. The desktop polls for updates via the Telegram Bot +//! API (long polling) and routes messages through the shared command router. + +use anyhow::{anyhow, Result}; +use log::{debug, error, info, warn}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::sync::Arc; +use tokio::sync::RwLock; + +use super::command_router::{ + execute_forwarded_turn, handle_command, paired_success_message, parse_command, BotChatState, + WELCOME_MESSAGE, +}; +use super::{load_bot_persistence, save_bot_persistence, BotConfig, SavedBotConnection}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TelegramConfig { + pub bot_token: String, +} + +pub struct TelegramBot { + config: TelegramConfig, + pending_pairings: Arc>>, + last_update_id: Arc>, + chat_states: Arc>>, +} + +#[derive(Debug, Clone)] +struct PendingPairing { + created_at: i64, +} + +impl TelegramBot { + pub fn new(config: TelegramConfig) -> Self { + Self { + config, + pending_pairings: Arc::new(RwLock::new(HashMap::new())), + last_update_id: Arc::new(RwLock::new(0)), + chat_states: Arc::new(RwLock::new(HashMap::new())), + } + } + + /// Restore a previously paired chat so the bot skips the pairing step. + pub async fn restore_chat_state(&self, chat_id: i64, state: BotChatState) { + self.chat_states.write().await.insert(chat_id, state); + } + + fn api_url(&self, method: &str) -> String { + format!( + "https://api.telegram.org/bot{}/{}", + self.config.bot_token, method + ) + } + + pub async fn send_message(&self, chat_id: i64, text: &str) -> Result<()> { + let client = reqwest::Client::new(); + let resp = client + .post(&self.api_url("sendMessage")) + .json(&serde_json::json!({ + "chat_id": chat_id, + "text": text, + })) + .send() + .await?; + + if !resp.status().is_success() { + let body = resp.text().await.unwrap_or_default(); + return Err(anyhow!("telegram sendMessage failed: {body}")); + } + debug!("Telegram message sent to chat {chat_id}"); + Ok(()) + } + + /// Register the bot command menu visible in Telegram's "/" menu. + pub async fn set_bot_commands(&self) -> Result<()> { + let client = reqwest::Client::new(); + let commands = serde_json::json!({ + "commands": [ + { "command": "switch_workspace", "description": "List and switch workspaces" }, + { "command": "resume_session", "description": "Resume an existing session" }, + { "command": "new_code_session", "description": "Create a new coding session" }, + { "command": "new_cowork_session", "description": "Create a new cowork session" }, + { "command": "help", "description": "Show available commands" }, + ] + }); + let resp = client + .post(&self.api_url("setMyCommands")) + .json(&commands) + .send() + .await?; + if !resp.status().is_success() { + let body = resp.text().await.unwrap_or_default(); + warn!("Failed to set Telegram bot commands: {body}"); + } + Ok(()) + } + + pub async fn register_pairing(&self, pairing_code: &str) -> Result<()> { + self.pending_pairings.write().await.insert( + pairing_code.to_string(), + PendingPairing { + created_at: chrono::Utc::now().timestamp(), + }, + ); + Ok(()) + } + + pub async fn verify_pairing_code(&self, code: &str) -> bool { + let mut pairings = self.pending_pairings.write().await; + if let Some(p) = pairings.remove(code) { + let age = chrono::Utc::now().timestamp() - p.created_at; + return age < 300; + } + false + } + + pub async fn poll_updates(&self) -> Result> { + let offset = *self.last_update_id.read().await; + let client = reqwest::Client::builder() + .timeout(std::time::Duration::from_secs(35)) + .build()?; + + let resp = client + .get(&self.api_url("getUpdates")) + .query(&[ + ("offset", (offset + 1).to_string()), + ("timeout", "30".to_string()), + ]) + .send() + .await?; + + let body: serde_json::Value = resp.json().await?; + let results = body["result"].as_array().cloned().unwrap_or_default(); + + let mut messages = Vec::new(); + for update in results { + if let Some(update_id) = update["update_id"].as_i64() { + let mut last = self.last_update_id.write().await; + if update_id > *last { + *last = update_id; + } + } + + if let (Some(chat_id), Some(text)) = ( + update.pointer("/message/chat/id").and_then(|v| v.as_i64()), + update.pointer("/message/text").and_then(|v| v.as_str()), + ) { + messages.push((chat_id, text.trim().to_string())); + } + } + + Ok(messages) + } + + /// Start a polling loop that checks for pairing codes. + /// Returns the chat_id when a valid pairing code is received. + pub async fn wait_for_pairing(&self) -> Result { + info!("Telegram bot waiting for pairing code..."); + loop { + match self.poll_updates().await { + Ok(messages) => { + for (chat_id, text) in messages { + let trimmed = text.trim(); + + if trimmed == "/start" { + self.send_message(chat_id, WELCOME_MESSAGE).await.ok(); + continue; + } + + if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) { + if self.verify_pairing_code(trimmed).await { + info!("Telegram pairing successful, chat_id={chat_id}"); + let success_msg = paired_success_message(); + self.send_message(chat_id, &success_msg).await.ok(); + self.set_bot_commands().await.ok(); + + let mut state = BotChatState::new(chat_id.to_string()); + state.paired = true; + self.chat_states.write().await.insert(chat_id, state.clone()); + self.persist_chat_state(chat_id, &state).await; + + return Ok(chat_id); + } else { + self.send_message( + chat_id, + "Invalid or expired pairing code. Please try again.", + ) + .await + .ok(); + } + } else { + self.send_message( + chat_id, + "Please enter the 6-digit pairing code from BitFun Desktop.", + ) + .await + .ok(); + } + } + } + Err(e) => { + error!("Telegram poll error: {e}"); + tokio::time::sleep(std::time::Duration::from_secs(5)).await; + } + } + } + } + + /// Main message loop that runs after pairing is complete. + /// Continuously polls for messages and routes them through the command router. + pub async fn run_message_loop(self: Arc, stop_rx: tokio::sync::watch::Receiver) { + info!("Telegram bot message loop started"); + let mut stop = stop_rx; + + loop { + if *stop.borrow() { + info!("Telegram bot message loop stopped by signal"); + break; + } + + let poll_result = tokio::select! { + result = self.poll_updates() => result, + _ = stop.changed() => { + info!("Telegram bot message loop stopped by signal"); + break; + } + }; + + match poll_result { + Ok(messages) => { + for (chat_id, text) in messages { + let bot = self.clone(); + tokio::spawn(async move { + bot.handle_incoming_message(chat_id, &text).await; + }); + } + } + Err(e) => { + error!("Telegram poll error in message loop: {e}"); + tokio::time::sleep(std::time::Duration::from_secs(5)).await; + } + } + } + } + + async fn handle_incoming_message(self: &Arc, chat_id: i64, text: &str) { + let mut states = self.chat_states.write().await; + let state = states + .entry(chat_id) + .or_insert_with(|| { + let mut s = BotChatState::new(chat_id.to_string()); + s.paired = true; + s + }); + + if !state.paired { + let trimmed = text.trim(); + if trimmed == "/start" { + self.send_message(chat_id, WELCOME_MESSAGE).await.ok(); + return; + } + if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) { + if self.verify_pairing_code(trimmed).await { + state.paired = true; + let msg = paired_success_message(); + self.send_message(chat_id, &msg).await.ok(); + self.set_bot_commands().await.ok(); + self.persist_chat_state(chat_id, state).await; + return; + } else { + self.send_message( + chat_id, + "Invalid or expired pairing code. Please try again.", + ) + .await + .ok(); + return; + } + } + self.send_message( + chat_id, + "Please enter the 6-digit pairing code from BitFun Desktop.", + ) + .await + .ok(); + return; + } + + let cmd = parse_command(text); + let result = handle_command(state, cmd).await; + + self.persist_chat_state(chat_id, state).await; + drop(states); + + self.send_message(chat_id, &result.reply).await.ok(); + + if let Some(forward) = result.forward_to_session { + let bot = self.clone(); + tokio::spawn(async move { + let response = execute_forwarded_turn(forward).await; + bot.send_message(chat_id, &response).await.ok(); + }); + } + } + + async fn persist_chat_state(&self, chat_id: i64, state: &BotChatState) { + let mut data = load_bot_persistence(); + data.upsert(SavedBotConnection { + bot_type: "telegram".to_string(), + chat_id: chat_id.to_string(), + config: BotConfig::Telegram { + bot_token: self.config.bot_token.clone(), + }, + chat_state: state.clone(), + connected_at: chrono::Utc::now().timestamp(), + }); + save_bot_persistence(&data); + } +} diff --git a/src/crates/core/src/service/remote_connect/device.rs b/src/crates/core/src/service/remote_connect/device.rs new file mode 100644 index 00000000..264d16ce --- /dev/null +++ b/src/crates/core/src/service/remote_connect/device.rs @@ -0,0 +1,74 @@ +//! Device identity for Remote Connect pairing. +//! +//! Generates a stable `device_id` from `SHA-256(hostname + MAC address)`. +//! Falls back gracefully when MAC or hostname are unavailable. + +use anyhow::Result; +use sha2::{Digest, Sha256}; + +/// Represents a device's identity used for pairing. +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct DeviceIdentity { + pub device_id: String, + pub device_name: String, + pub mac_address: String, +} + +impl DeviceIdentity { + /// Build the device identity from the current machine. + pub fn from_current_machine() -> Result { + let device_name = get_hostname(); + let mac_address = get_mac_address(); + + let mut hasher = Sha256::new(); + hasher.update(device_name.as_bytes()); + hasher.update(b":"); + hasher.update(mac_address.as_bytes()); + let hash = hasher.finalize(); + let device_id = hash[..16] + .iter() + .map(|b| format!("{b:02x}")) + .collect::(); + + Ok(Self { + device_id, + device_name, + mac_address, + }) + } +} + +fn get_hostname() -> String { + hostname::get() + .ok() + .and_then(|h| h.into_string().ok()) + .unwrap_or_else(|| "unknown-host".to_string()) +} + +fn get_mac_address() -> String { + mac_address::get_mac_address() + .ok() + .flatten() + .map(|ma| ma.to_string()) + .unwrap_or_else(|| "00:00:00:00:00:00".to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_device_identity_creation() { + let identity = DeviceIdentity::from_current_machine().unwrap(); + assert!(!identity.device_id.is_empty()); + assert!(!identity.device_name.is_empty()); + assert_eq!(identity.device_id.len(), 32); // 16 bytes hex = 32 chars + } + + #[test] + fn test_device_identity_stable() { + let id1 = DeviceIdentity::from_current_machine().unwrap(); + let id2 = DeviceIdentity::from_current_machine().unwrap(); + assert_eq!(id1.device_id, id2.device_id); + } +} diff --git a/src/crates/core/src/service/remote_connect/embedded_relay.rs b/src/crates/core/src/service/remote_connect/embedded_relay.rs new file mode 100644 index 00000000..7b80f2cd --- /dev/null +++ b/src/crates/core/src/service/remote_connect/embedded_relay.rs @@ -0,0 +1,837 @@ +//! Embedded mini relay server for LAN / ngrok modes. +//! +//! Runs inside the desktop process using axum + WebSocket. +//! Supports the same protocol as the standalone relay-server. + +use axum::{ + extract::{ + ws::{Message, WebSocket, WebSocketUpgrade}, + State, + }, + response::{IntoResponse, Response}, + routing::get, + Json, Router, +}; +use dashmap::DashMap; +use futures_util::{SinkExt, StreamExt}; +use log::{debug, info}; +use serde::{Deserialize, Serialize}; +use std::sync::{ + atomic::{AtomicU64, Ordering}, + Arc, +}; +use tokio::sync::mpsc; + +type ConnId = u64; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum MessageDirection { + ToMobile, + ToDesktop, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BufferedMessage { + pub seq: u64, + pub timestamp: i64, + pub direction: MessageDirection, + pub encrypted_data: String, + pub nonce: String, +} + +struct Participant { + conn_id: ConnId, + device_id: String, + device_type: String, + public_key: String, + tx: Option>, + last_activity: i64, +} + +struct Room { + participants: Vec, + message_store: Vec, + next_seq: u64, +} + +impl Room { + fn buffer_message(&mut self, direction: MessageDirection, encrypted_data: String, nonce: String) -> u64 { + let seq = self.next_seq; + self.next_seq += 1; + self.message_store.push(BufferedMessage { + seq, + timestamp: chrono::Utc::now().timestamp(), + direction, + encrypted_data, + nonce, + }); + seq + } +} + +struct RelayState { + rooms: DashMap, + conn_to_room: DashMap, + next_id: AtomicU64, + /// Global content-addressed store: sha256 hex -> file bytes. + content_store: DashMap>>, + /// Per-room file manifests: room_id -> (relative_path -> sha256 hex). + room_manifests: DashMap>, +} + +impl RelayState { + fn new() -> Arc { + Arc::new(Self { + rooms: DashMap::new(), + conn_to_room: DashMap::new(), + next_id: AtomicU64::new(1), + content_store: DashMap::new(), + room_manifests: DashMap::new(), + }) + } +} + +#[derive(Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +enum Inbound { + CreateRoom { + room_id: Option, + device_id: String, + device_type: String, + public_key: String, + }, + JoinRoom { + room_id: String, + device_id: String, + device_type: String, + public_key: String, + }, + Relay { + #[allow(dead_code)] + room_id: String, + encrypted_data: String, + nonce: String, + }, + Heartbeat, +} + +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +enum Outbound { + RoomCreated { room_id: String }, + PeerJoined { device_id: String, device_type: String, public_key: String }, + Relay { room_id: String, encrypted_data: String, nonce: String }, + PeerDisconnected { device_id: String }, + HeartbeatAck, + Error { message: String }, +} + +/// Start the embedded relay and return a shutdown handle. +/// The server listens on `0.0.0.0:{port}`. +/// +/// If `static_dir` is provided, the server also serves mobile-web static files +/// as a fallback for requests that don't match any API or WebSocket route. +pub async fn start_embedded_relay(port: u16, static_dir: Option<&str>) -> anyhow::Result { + let state = RelayState::new(); + let app_state = state.clone(); + + let cleanup_state = state.clone(); + tokio::spawn(async move { + loop { + tokio::time::sleep(std::time::Duration::from_secs(60)).await; + let now = chrono::Utc::now().timestamp(); + let stale_ids: Vec = cleanup_state.rooms + .iter() + .filter(|r| (now - r.participants.iter().map(|p| p.last_activity).max().unwrap_or(now)) > 300) + .map(|r| r.key().clone()) + .collect(); + + for id in stale_ids { + if let Some((_, room)) = cleanup_state.rooms.remove(&id) { + for p in room.participants { + cleanup_state.conn_to_room.remove(&p.conn_id); + } + } + } + } + }); + + let mut app = Router::new() + .route("/ws", get(ws_handler)) + .route("/health", get(health)) + .route("/api/rooms/:room_id/join", axum::routing::post(join_room_http)) + .route("/api/rooms/:room_id/message", axum::routing::post(relay_message_http)) + .route("/api/rooms/:room_id/poll", get(poll_messages_http)) + .route("/api/rooms/:room_id/ack", axum::routing::post(ack_messages_http)) + .route("/api/rooms/:room_id/upload-web", axum::routing::post(upload_web_http)) + .route("/api/rooms/:room_id/check-web-files", axum::routing::post(check_web_files_http)) + .route("/api/rooms/:room_id/upload-web-files", axum::routing::post(upload_web_files_http)) + .route("/r/*path", get(serve_room_web_http)) + .layer(tower_http::cors::CorsLayer::permissive()) + .with_state(app_state); + + if let Some(dir) = static_dir { + info!("Embedded relay: serving static files from {dir}"); + let serve_dir = tower_http::services::ServeDir::new(dir) + .append_index_html_on_directories(true); + // Wrap with cache-control middleware: + // - HTML: no-cache (always fetch fresh to pick up new asset hashes) + // - Hashed assets: immutable long-cache (filename contains content hash) + let static_app = Router::<()>::new() + .fallback_service(serve_dir) + .layer(axum::middleware::from_fn(static_cache_headers)); + app = app.fallback_service(static_app); + } + + let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}")) + .await + .map_err(|e| anyhow::anyhow!("failed to bind embedded relay on port {port}: {e}"))?; + + info!("Embedded relay started on 0.0.0.0:{port}"); + + let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel::<()>(); + tokio::spawn(async move { + axum::serve(listener, app) + .with_graceful_shutdown(async { let _ = shutdown_rx.await; }) + .await + .ok(); + }); + + tokio::time::sleep(std::time::Duration::from_millis(200)).await; + + Ok(EmbeddedRelayHandle { _shutdown: Some(shutdown_tx) }) +} + +/// Middleware that sets Cache-Control headers for static file responses. +/// HTML files get `no-cache` so the browser always checks for updates, +/// while hashed asset files (JS/CSS in /assets/) get long-term caching. +async fn static_cache_headers( + request: axum::extract::Request, + next: axum::middleware::Next, +) -> Response { + let path = request.uri().path().to_string(); + let mut response = next.run(request).await; + let headers = response.headers_mut(); + if path == "/" || path.ends_with(".html") { + headers.insert( + axum::http::header::CACHE_CONTROL, + axum::http::HeaderValue::from_static("no-cache, no-store, must-revalidate"), + ); + headers.insert( + axum::http::header::PRAGMA, + axum::http::HeaderValue::from_static("no-cache"), + ); + } else if path.starts_with("/assets/") { + headers.insert( + axum::http::header::CACHE_CONTROL, + axum::http::HeaderValue::from_static("public, max-age=31536000, immutable"), + ); + } + response +} + +pub struct EmbeddedRelayHandle { + _shutdown: Option>, +} + +impl EmbeddedRelayHandle { + pub fn stop(&mut self) { + if let Some(tx) = self._shutdown.take() { + let _ = tx.send(()); + info!("Embedded relay stopped"); + } + } +} + +impl Drop for EmbeddedRelayHandle { + fn drop(&mut self) { + self.stop(); + } +} + +async fn health() -> impl IntoResponse { + Json(serde_json::json!({"status": "healthy"})) +} + +async fn ws_handler(ws: WebSocketUpgrade, State(state): State>) -> Response { + ws.on_upgrade(move |socket| handle_socket(socket, state)) +} + +async fn handle_socket(socket: WebSocket, state: Arc) { + let (mut ws_tx, mut ws_rx) = socket.split(); + let (out_tx, mut out_rx) = mpsc::unbounded_channel::(); + + let conn_id = state.next_id.fetch_add(1, Ordering::Relaxed); + + let write_task = tokio::spawn(async move { + while let Some(text) = out_rx.recv().await { + if ws_tx.send(Message::Text(text)).await.is_err() { + break; + } + } + }); + + while let Some(Ok(msg)) = ws_rx.next().await { + if let Message::Text(text) = msg { + handle_msg(&text, conn_id, &state, &out_tx); + } + } + + on_disconnect(conn_id, &state); + drop(out_tx); + let _ = write_task.await; + debug!("Embedded relay: conn {conn_id} closed"); +} + +fn handle_msg( + text: &str, + conn_id: ConnId, + state: &Arc, + out_tx: &mpsc::UnboundedSender, +) { + let msg: Inbound = match serde_json::from_str(text) { + Ok(m) => m, + Err(e) => { + send(&Some(out_tx.clone()), &Outbound::Error { message: format!("bad message: {e}") }); + return; + } + }; + + match msg { + Inbound::CreateRoom { room_id, device_id, device_type, public_key } => { + let room_id = room_id.unwrap_or_else(gen_room_id); + let mut room = Room { + participants: Vec::with_capacity(2), + message_store: Vec::new(), + next_seq: 1, + }; + room.participants.push(Participant { + conn_id, device_id, device_type, public_key, tx: Some(out_tx.clone()), last_activity: chrono::Utc::now().timestamp(), + }); + state.rooms.insert(room_id.clone(), room); + state.conn_to_room.insert(conn_id, room_id.clone()); + send(&Some(out_tx.clone()), &Outbound::RoomCreated { room_id }); + } + + Inbound::JoinRoom { room_id, device_id, device_type, public_key } => { + let existing_peer = state.rooms.get(&room_id).and_then(|r| { + r.participants.first().map(|p| (p.device_id.clone(), p.device_type.clone(), p.public_key.clone())) + }); + + let ok = if let Some(mut room) = state.rooms.get_mut(&room_id) { + if room.participants.len() < 2 { + room.participants.push(Participant { + conn_id, + device_id: device_id.clone(), + device_type: device_type.clone(), + public_key: public_key.clone(), + tx: Some(out_tx.clone()), + last_activity: chrono::Utc::now().timestamp(), + }); + state.conn_to_room.insert(conn_id, room_id.clone()); + true + } else { + false + } + } else { + false + }; + + if ok { + if let Some(room) = state.rooms.get(&room_id) { + for p in &room.participants { + if p.conn_id != conn_id { + send(&p.tx, &Outbound::PeerJoined { + device_id: device_id.clone(), + device_type: device_type.clone(), + public_key: public_key.clone(), + }); + } + } + } + if let Some((pdid, pdt, ppk)) = existing_peer { + send(&Some(out_tx.clone()), &Outbound::PeerJoined { + device_id: pdid, device_type: pdt, public_key: ppk, + }); + } + } else { + send(&Some(out_tx.clone()), &Outbound::Error { message: format!("cannot join room {room_id}") }); + } + } + + Inbound::Relay { room_id, encrypted_data, nonce } => { + if let Some(rid) = state.conn_to_room.get(&conn_id) { + if let Some(mut room) = state.rooms.get_mut(rid.value()) { + let sender_type = room.participants.iter() + .find(|p| p.conn_id == conn_id) + .map(|p| p.device_type.clone()) + .unwrap_or_default(); + + let direction = if sender_type == "desktop" { + MessageDirection::ToMobile + } else { + MessageDirection::ToDesktop + }; + + room.buffer_message(direction, encrypted_data.clone(), nonce.clone()); + + let relay_json = serde_json::to_string(&Outbound::Relay { + room_id: room_id.clone(), encrypted_data, nonce, + }).unwrap_or_default(); + for p in &room.participants { + if p.conn_id != conn_id { + if let Some(ref tx) = p.tx { + let _ = tx.send(relay_json.clone()); + } + } + } + } + } + } + + Inbound::Heartbeat => { + if let Some(room_id) = state.conn_to_room.get(&conn_id) { + if let Some(mut room) = state.rooms.get_mut(room_id.value()) { + if let Some(p) = room.participants.iter_mut().find(|p| p.conn_id == conn_id) { + p.last_activity = chrono::Utc::now().timestamp(); + } + } + send(&Some(out_tx.clone()), &Outbound::HeartbeatAck); + } else { + send(&Some(out_tx.clone()), &Outbound::Error { message: "Room not found".into() }); + } + } + } +} + +fn on_disconnect(conn_id: ConnId, state: &Arc) { + if let Some((_, room_id)) = state.conn_to_room.remove(&conn_id) { + let mut should_remove = false; + if let Some(mut room) = state.rooms.get_mut(&room_id) { + let removed = room.participants.iter().position(|p| p.conn_id == conn_id); + if let Some(idx) = removed { + let p = room.participants.remove(idx); + let notif = serde_json::to_string(&Outbound::PeerDisconnected { + device_id: p.device_id, + }).unwrap_or_default(); + for other in &room.participants { + if let Some(ref tx) = other.tx { + let _ = tx.send(notif.clone()); + } + } + } + should_remove = room.participants.is_empty(); + } + if should_remove { + state.rooms.remove(&room_id); + } + } +} + +fn send(tx: &Option>, msg: &Outbound) { + if let Some(tx) = tx { + if let Ok(json) = serde_json::to_string(msg) { + let _ = tx.send(json); + } + } +} + +fn gen_room_id() -> String { + let bytes: [u8; 6] = rand::random(); + bytes.iter().map(|b| format!("{b:02x}")).collect() +} + +// ── HTTP Handlers ─────────────────────────────────────────────────── + +#[derive(Deserialize)] +struct JoinRoomRequest { + device_id: String, + device_type: String, + public_key: String, +} + +async fn join_room_http( + State(state): State>, + axum::extract::Path(room_id): axum::extract::Path, + Json(body): Json, +) -> Result, axum::http::StatusCode> { + let conn_id = state.next_id.fetch_add(1, Ordering::Relaxed); + + let existing_peer = state.rooms.get(&room_id).and_then(|r| { + r.participants.first().map(|p| (p.device_id.clone(), p.device_type.clone(), p.public_key.clone())) + }); + + let ok = if let Some(mut room) = state.rooms.get_mut(&room_id) { + if room.participants.len() < 2 { + room.participants.push(Participant { + conn_id, + device_id: body.device_id.clone(), + device_type: body.device_type.clone(), + public_key: body.public_key.clone(), + tx: None, // HTTP client + last_activity: chrono::Utc::now().timestamp(), + }); + state.conn_to_room.insert(conn_id, room_id.clone()); + true + } else { + false + } + } else { + false + }; + + if ok { + if let Some(room) = state.rooms.get(&room_id) { + for p in &room.participants { + if p.conn_id != conn_id { + send(&p.tx, &Outbound::PeerJoined { + device_id: body.device_id.clone(), + device_type: body.device_type.clone(), + public_key: body.public_key.clone(), + }); + } + } + } + + if let Some((pdid, pdt, ppk)) = existing_peer { + Ok(Json(serde_json::json!({ + "status": "joined", + "peer": { + "device_id": pdid, + "device_type": pdt, + "public_key": ppk + } + }))) + } else { + Ok(Json(serde_json::json!({ + "status": "joined", + "peer": null + }))) + } + } else { + Err(axum::http::StatusCode::BAD_REQUEST) + } +} + +#[derive(Deserialize)] +struct RelayMessageRequest { + device_id: String, + encrypted_data: String, + nonce: String, +} + +async fn relay_message_http( + State(state): State>, + axum::extract::Path(room_id): axum::extract::Path, + Json(body): Json, +) -> axum::http::StatusCode { + if let Some(mut room) = state.rooms.get_mut(&room_id) { + let sender_conn_id = room.participants.iter() + .find(|p| p.device_id == body.device_id) + .map(|p| p.conn_id); + + if let Some(conn_id) = sender_conn_id { + let sender_type = room.participants.iter() + .find(|p| p.conn_id == conn_id) + .map(|p| p.device_type.clone()) + .unwrap_or_default(); + + let direction = if sender_type == "desktop" { + MessageDirection::ToMobile + } else { + MessageDirection::ToDesktop + }; + + room.buffer_message(direction, body.encrypted_data.clone(), body.nonce.clone()); + + let relay_json = serde_json::to_string(&Outbound::Relay { + room_id: room_id.clone(), + encrypted_data: body.encrypted_data, + nonce: body.nonce, + }).unwrap_or_default(); + + for p in &room.participants { + if p.conn_id != conn_id { + if let Some(ref tx) = p.tx { + let _ = tx.send(relay_json.clone()); + } + } + } + return axum::http::StatusCode::OK; + } + } + axum::http::StatusCode::NOT_FOUND +} + +#[derive(Deserialize)] +struct PollQuery { + since_seq: Option, + device_type: Option, +} + +#[derive(Serialize)] +struct PollResponse { + messages: Vec, + peer_connected: bool, +} + +async fn poll_messages_http( + State(state): State>, + axum::extract::Path(room_id): axum::extract::Path, + axum::extract::Query(query): axum::extract::Query, +) -> Result, axum::http::StatusCode> { + let since = query.since_seq.unwrap_or(0); + let direction_str = query.device_type.as_deref().unwrap_or("mobile"); + let direction = match direction_str { + "desktop" => MessageDirection::ToDesktop, + _ => MessageDirection::ToMobile, + }; + + if let Some(mut room) = state.rooms.get_mut(&room_id) { + if let Some(p) = room.participants.iter_mut().find(|p| p.device_type == direction_str) { + p.last_activity = chrono::Utc::now().timestamp(); + } + let peer_connected = room.participants.iter().any(|p| p.device_type != direction_str); + let messages = room.message_store + .iter() + .filter(|m| m.direction == direction && m.seq > since) + .cloned() + .collect(); + Ok(Json(PollResponse { messages, peer_connected })) + } else { + Ok(Json(PollResponse { messages: vec![], peer_connected: false })) + } +} + +#[derive(Deserialize)] +struct AckRequest { + ack_seq: u64, + device_type: Option, +} + +async fn ack_messages_http( + State(state): State>, + axum::extract::Path(room_id): axum::extract::Path, + Json(body): Json, +) -> axum::http::StatusCode { + let direction_str = body.device_type.as_deref().unwrap_or("mobile"); + let direction = match direction_str { + "desktop" => MessageDirection::ToDesktop, + _ => MessageDirection::ToMobile, + }; + + if let Some(mut room) = state.rooms.get_mut(&room_id) { + if let Some(p) = room.participants.iter_mut().find(|p| p.device_type == direction_str) { + p.last_activity = chrono::Utc::now().timestamp(); + } + room.message_store.retain(|m| !(m.direction == direction && m.seq <= body.ack_seq)); + } + axum::http::StatusCode::OK +} + +// ── Mobile-web upload & serving (content-addressed in-memory store) ───── + +fn hex_sha256(data: &[u8]) -> String { + use sha2::{Digest, Sha256}; + let mut hasher = Sha256::new(); + hasher.update(data); + format!("{:x}", hasher.finalize()) +} + +#[derive(Deserialize)] +struct UploadWebRequest { + files: std::collections::HashMap, +} + +async fn upload_web_http( + State(state): State>, + axum::extract::Path(room_id): axum::extract::Path, + Json(body): Json, +) -> Result, axum::http::StatusCode> { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + + if !state.rooms.contains_key(&room_id) { + return Err(axum::http::StatusCode::NOT_FOUND); + } + + let mut manifest = std::collections::HashMap::new(); + let mut written = 0usize; + let mut reused = 0usize; + + for (rel_path, b64_content) in &body.files { + if rel_path.contains("..") { + continue; + } + let decoded = B64.decode(b64_content).map_err(|_| axum::http::StatusCode::BAD_REQUEST)?; + let hash = hex_sha256(&decoded); + + if !state.content_store.contains_key(&hash) { + state.content_store.insert(hash.clone(), Arc::new(decoded)); + written += 1; + } else { + reused += 1; + } + manifest.insert(rel_path.clone(), hash); + } + + state.room_manifests.insert(room_id.clone(), manifest); + info!("Room {room_id}: upload-web complete (new={written}, reused={reused})"); + Ok(Json(serde_json::json!({ + "status": "ok", + "files_written": written, + "files_reused": reused + }))) +} + +#[derive(Deserialize)] +struct FileManifestEntry { + path: String, + hash: String, + #[allow(dead_code)] + size: u64, +} + +#[derive(Deserialize)] +struct CheckWebFilesRequest { + files: Vec, +} + +async fn check_web_files_http( + State(state): State>, + axum::extract::Path(room_id): axum::extract::Path, + Json(body): Json, +) -> Result, axum::http::StatusCode> { + if !state.rooms.contains_key(&room_id) { + return Err(axum::http::StatusCode::NOT_FOUND); + } + + let mut manifest = std::collections::HashMap::new(); + let mut needed = Vec::new(); + let mut existing_count = 0usize; + + for entry in &body.files { + if entry.path.contains("..") { + continue; + } + manifest.insert(entry.path.clone(), entry.hash.clone()); + if state.content_store.contains_key(&entry.hash) { + existing_count += 1; + } else { + needed.push(entry.path.clone()); + } + } + + state.room_manifests.insert(room_id.clone(), manifest); + + info!( + "Room {room_id}: check-web-files total={}, existing={existing_count}, needed={}", + body.files.len(), + needed.len() + ); + + Ok(Json(serde_json::json!({ + "needed": needed, + "existing_count": existing_count, + "total_count": body.files.len() + }))) +} + +#[derive(Deserialize)] +struct UploadWebFilesEntry { + content: String, + hash: String, +} + +#[derive(Deserialize)] +struct UploadWebFilesRequest { + files: std::collections::HashMap, +} + +async fn upload_web_files_http( + State(state): State>, + axum::extract::Path(room_id): axum::extract::Path, + Json(body): Json, +) -> Result, axum::http::StatusCode> { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + + if !state.rooms.contains_key(&room_id) { + return Err(axum::http::StatusCode::NOT_FOUND); + } + + let mut stored = 0usize; + for (rel_path, entry) in &body.files { + if rel_path.contains("..") { + continue; + } + let decoded = B64.decode(&entry.content).map_err(|_| axum::http::StatusCode::BAD_REQUEST)?; + let actual_hash = hex_sha256(&decoded); + if actual_hash != entry.hash { + return Err(axum::http::StatusCode::BAD_REQUEST); + } + + if !state.content_store.contains_key(&actual_hash) { + state.content_store.insert(actual_hash.clone(), Arc::new(decoded)); + stored += 1; + } + + if let Some(mut manifest) = state.room_manifests.get_mut(&room_id) { + manifest.insert(rel_path.clone(), actual_hash); + } + } + + info!("Room {room_id}: upload-web-files stored {stored} new files"); + Ok(Json(serde_json::json!({ "status": "ok", "files_stored": stored }))) +} + +async fn serve_room_web_http( + State(state): State>, + axum::extract::Path(path): axum::extract::Path, +) -> Result { + use axum::body::Body; + use axum::http::header; + use axum::response::IntoResponse; + + let path = path.trim_start_matches('/'); + let (room_id, file_path) = match path.find('/') { + Some(idx) => (&path[..idx], &path[idx + 1..]), + None => (path, ""), + }; + let file_path = if file_path.is_empty() { "index.html" } else { file_path }; + let room_id = room_id.to_string(); + + let manifest = state + .room_manifests + .get(&room_id) + .ok_or(axum::http::StatusCode::NOT_FOUND)?; + + let hash = manifest + .get(file_path) + .or_else(|| manifest.get("index.html")) + .ok_or(axum::http::StatusCode::NOT_FOUND)?; + + let content = state + .content_store + .get(hash) + .ok_or(axum::http::StatusCode::NOT_FOUND)?; + + let mime = mime_from_ext(file_path); + Ok(([(header::CONTENT_TYPE, mime)], Body::from(content.value().as_ref().clone())).into_response()) +} + +fn mime_from_ext(path: &str) -> &'static str { + match path.rsplit('.').next() { + Some("html") => "text/html; charset=utf-8", + Some("js") => "application/javascript; charset=utf-8", + Some("css") => "text/css; charset=utf-8", + Some("json") => "application/json", + Some("png") => "image/png", + Some("svg") => "image/svg+xml", + Some("ico") => "image/x-icon", + Some("woff2") => "font/woff2", + Some("woff") => "font/woff", + Some("ttf") => "font/ttf", + Some("wasm") => "application/wasm", + _ => "application/octet-stream", + } +} diff --git a/src/crates/core/src/service/remote_connect/encryption.rs b/src/crates/core/src/service/remote_connect/encryption.rs new file mode 100644 index 00000000..a4f10839 --- /dev/null +++ b/src/crates/core/src/service/remote_connect/encryption.rs @@ -0,0 +1,189 @@ +//! End-to-end encryption for Remote Connect. +//! +//! Uses X25519 ECDH for key exchange and AES-256-GCM for authenticated encryption. +//! Both sides generate ephemeral keypairs; the shared secret is derived via ECDH +//! and used directly as the AES-256-GCM key (X25519 output is already 32 bytes). + +use aes_gcm::aead::{Aead, KeyInit, OsRng}; +use aes_gcm::{Aes256Gcm, Nonce}; +use anyhow::{anyhow, Result}; +use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; +use rand::RngCore; +use x25519_dalek::{PublicKey, StaticSecret}; + +const NONCE_SIZE: usize = 12; + +/// Holds a keypair for X25519 ECDH key exchange. +pub struct KeyPair { + secret: StaticSecret, + public: PublicKey, +} + +impl KeyPair { + pub fn generate() -> Self { + let secret = StaticSecret::random_from_rng(OsRng); + let public = PublicKey::from(&secret); + Self { secret, public } + } + + pub fn public_key_bytes(&self) -> [u8; 32] { + self.public.to_bytes() + } + + pub fn public_key_base64(&self) -> String { + BASE64.encode(self.public.to_bytes()) + } + + /// Derive a shared secret from our secret key and the peer's public key. + pub fn derive_shared_secret(&self, peer_public_bytes: &[u8; 32]) -> [u8; 32] { + let peer_public = PublicKey::from(*peer_public_bytes); + let shared = self.secret.diffie_hellman(&peer_public); + *shared.as_bytes() + } +} + +/// Encrypts plaintext using AES-256-GCM with a random nonce. +/// Returns `(ciphertext, nonce)` both as raw bytes. +pub fn encrypt(shared_secret: &[u8; 32], plaintext: &[u8]) -> Result<(Vec, [u8; NONCE_SIZE])> { + let cipher = + Aes256Gcm::new_from_slice(shared_secret).map_err(|e| anyhow!("cipher init: {e}"))?; + + let mut nonce_bytes = [0u8; NONCE_SIZE]; + OsRng.fill_bytes(&mut nonce_bytes); + let nonce = Nonce::from_slice(&nonce_bytes); + + let ciphertext = cipher + .encrypt(nonce, plaintext) + .map_err(|e| anyhow!("encrypt: {e}"))?; + + Ok((ciphertext, nonce_bytes)) +} + +/// Decrypts ciphertext using AES-256-GCM. +pub fn decrypt( + shared_secret: &[u8; 32], + ciphertext: &[u8], + nonce_bytes: &[u8; NONCE_SIZE], +) -> Result> { + let cipher = + Aes256Gcm::new_from_slice(shared_secret).map_err(|e| anyhow!("cipher init: {e}"))?; + let nonce = Nonce::from_slice(nonce_bytes); + + cipher + .decrypt(nonce, ciphertext) + .map_err(|e| anyhow!("decrypt: {e}")) +} + +/// Convenience: encrypt a string and return base64-encoded `(data, nonce)`. +pub fn encrypt_to_base64(shared_secret: &[u8; 32], plaintext: &str) -> Result<(String, String)> { + let (ct, nonce) = encrypt(shared_secret, plaintext.as_bytes())?; + Ok((BASE64.encode(ct), BASE64.encode(nonce))) +} + +/// Convenience: decrypt from base64-encoded `(data, nonce)`. +pub fn decrypt_from_base64( + shared_secret: &[u8; 32], + ciphertext_b64: &str, + nonce_b64: &str, +) -> Result { + let ct = BASE64 + .decode(ciphertext_b64) + .map_err(|e| anyhow!("base64 decode ciphertext: {e}"))?; + let nonce_vec = BASE64 + .decode(nonce_b64) + .map_err(|e| anyhow!("base64 decode nonce: {e}"))?; + + if nonce_vec.len() != NONCE_SIZE { + return Err(anyhow!( + "invalid nonce length: expected {NONCE_SIZE}, got {}", + nonce_vec.len() + )); + } + let mut nonce = [0u8; NONCE_SIZE]; + nonce.copy_from_slice(&nonce_vec); + + let plaintext = decrypt(shared_secret, &ct, &nonce)?; + String::from_utf8(plaintext).map_err(|e| anyhow!("utf8 decode: {e}")) +} + +/// Parse a base64-encoded public key into 32-byte array. +pub fn parse_public_key(b64: &str) -> Result<[u8; 32]> { + let bytes = BASE64 + .decode(b64) + .map_err(|e| anyhow!("base64 decode public key: {e}"))?; + if bytes.len() != 32 { + return Err(anyhow!( + "invalid public key length: expected 32, got {}", + bytes.len() + )); + } + let mut key = [0u8; 32]; + key.copy_from_slice(&bytes); + Ok(key) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_key_exchange_and_encrypt_decrypt() { + let alice = KeyPair::generate(); + let bob = KeyPair::generate(); + + let alice_shared = alice.derive_shared_secret(&bob.public_key_bytes()); + let bob_shared = bob.derive_shared_secret(&alice.public_key_bytes()); + assert_eq!(alice_shared, bob_shared); + + let message = "Hello, Remote Connect!"; + let (ct, nonce) = encrypt(&alice_shared, message.as_bytes()).unwrap(); + let decrypted = decrypt(&bob_shared, &ct, &nonce).unwrap(); + assert_eq!(decrypted, message.as_bytes()); + } + + #[test] + fn test_base64_round_trip() { + let alice = KeyPair::generate(); + let bob = KeyPair::generate(); + + let shared = alice.derive_shared_secret(&bob.public_key_bytes()); + let message = "加密测试消息 with unicode 🔒"; + let (ct_b64, nonce_b64) = encrypt_to_base64(&shared, message).unwrap(); + let decrypted = decrypt_from_base64(&shared, &ct_b64, &nonce_b64).unwrap(); + assert_eq!(decrypted, message); + } + + #[test] + fn test_wrong_key_fails() { + let alice = KeyPair::generate(); + let bob = KeyPair::generate(); + let eve = KeyPair::generate(); + + let alice_shared = alice.derive_shared_secret(&bob.public_key_bytes()); + let eve_shared = eve.derive_shared_secret(&bob.public_key_bytes()); + + let (ct, nonce) = encrypt(&alice_shared, b"secret").unwrap(); + assert!(decrypt(&eve_shared, &ct, &nonce).is_err()); + } + + #[test] + fn test_parse_public_key() { + let kp = KeyPair::generate(); + let b64 = kp.public_key_base64(); + let parsed = parse_public_key(&b64).unwrap(); + assert_eq!(parsed, kp.public_key_bytes()); + } + + #[test] + fn test_tampered_ciphertext_fails() { + let alice = KeyPair::generate(); + let bob = KeyPair::generate(); + let shared = alice.derive_shared_secret(&bob.public_key_bytes()); + + let (mut ct, nonce) = encrypt(&shared, b"secret data").unwrap(); + if let Some(byte) = ct.last_mut() { + *byte ^= 0xff; + } + assert!(decrypt(&shared, &ct, &nonce).is_err()); + } +} diff --git a/src/crates/core/src/service/remote_connect/lan.rs b/src/crates/core/src/service/remote_connect/lan.rs new file mode 100644 index 00000000..2df68eda --- /dev/null +++ b/src/crates/core/src/service/remote_connect/lan.rs @@ -0,0 +1,34 @@ +//! LAN mode: starts an embedded relay server on the local network. +//! +//! The desktop runs a mini relay server, and the QR code points to the local IP. + +use anyhow::{anyhow, Result}; +use log::info; + +/// Detect the local LAN IP address. +pub fn get_local_ip() -> Result { + let ip = local_ip_address::local_ip().map_err(|e| anyhow!("failed to detect LAN IP: {e}"))?; + Ok(ip.to_string()) +} + +/// Build the relay URL for LAN mode. +pub fn build_lan_relay_url(port: u16) -> Result { + let ip = get_local_ip()?; + let url = format!("http://{ip}:{port}"); + info!("LAN relay URL: {url}"); + Ok(url) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_local_ip() { + let ip = get_local_ip(); + // May fail in CI environments without network, so just check it doesn't panic + if let Ok(ip) = ip { + assert!(!ip.is_empty()); + } + } +} diff --git a/src/crates/core/src/service/remote_connect/mod.rs b/src/crates/core/src/service/remote_connect/mod.rs new file mode 100644 index 00000000..034a071c --- /dev/null +++ b/src/crates/core/src/service/remote_connect/mod.rs @@ -0,0 +1,1014 @@ +//! Remote Connect service module. +//! +//! Provides phone-to-desktop remote connection capabilities with E2E encryption. +//! Supports multiple connection methods: LAN, ngrok, relay server, and bots. +//! +//! Bot connections (Telegram / Feishu) run independently of relay connections +//! (LAN / ngrok / BitFun Server / Custom Server). Calling `stop()` only +//! tears down the relay side; bots keep running. Use `stop_bot()` or +//! `stop_all()` to shut everything down. + +pub mod bot; +pub mod device; +pub mod embedded_relay; +pub mod encryption; +pub mod lan; +pub mod ngrok; +pub mod pairing; +pub mod qr_generator; +pub mod relay_client; +pub mod remote_server; + +pub use device::DeviceIdentity; +pub use encryption::{decrypt_from_base64, encrypt_to_base64, KeyPair}; +pub use pairing::{PairingProtocol, PairingState}; +pub use qr_generator::QrGenerator; +pub use relay_client::RelayClient; +pub use remote_server::RemoteServer; + +use anyhow::Result; +use log::{error, info}; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::RwLock; + +/// Supported connection methods. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ConnectionMethod { + Lan, + Ngrok, + BitfunServer, + CustomServer { url: String }, + BotFeishu, + BotTelegram, +} + +/// Configuration for Remote Connect. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RemoteConnectConfig { + pub lan_port: u16, + pub bitfun_server_url: String, + pub web_app_url: String, + pub custom_server_url: Option, + pub bot_feishu: Option, + pub bot_telegram: Option, + pub mobile_web_dir: Option, +} + +impl Default for RemoteConnectConfig { + fn default() -> Self { + Self { + lan_port: 9700, + bitfun_server_url: "http://remote.openbitfun.com/relay".to_string(), + web_app_url: "http://remote.openbitfun.com/relay".to_string(), + custom_server_url: None, + bot_feishu: None, + bot_telegram: None, + mobile_web_dir: None, + } + } +} + +/// Result of starting a remote connection. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ConnectionResult { + pub method: ConnectionMethod, + pub qr_data: Option, + pub qr_svg: Option, + pub qr_url: Option, + pub bot_pairing_code: Option, + pub bot_link: Option, + pub pairing_state: PairingState, +} + +/// Handle to a running bot (Telegram or Feishu). +struct BotHandle { + stop_tx: tokio::sync::watch::Sender, +} + +impl BotHandle { + fn stop(&self) { + let _ = self.stop_tx.send(true); + } +} + +/// Unified Remote Connect service that orchestrates all connection methods. +pub struct RemoteConnectService { + config: RemoteConnectConfig, + device_identity: DeviceIdentity, + pairing: Arc>, + relay_client: Arc>>, + remote_server: Arc>>, + active_method: Arc>>, + ngrok_tunnel: Arc>>, + embedded_relay: Arc>>, + // Bot handles live independently of relay connections + bot_telegram_handle: Arc>>, + bot_feishu_handle: Arc>>, + // Keep Arc references to bots for send_message etc. + telegram_bot: Arc>>>, + feishu_bot: Arc>>>, + /// Independent bot connection state — not tied to PairingProtocol. + /// Stores the peer description (e.g. "Telegram(7096812005)") when a bot is active. + bot_connected_info: Arc>>, +} + +impl RemoteConnectService { + pub fn new(config: RemoteConnectConfig) -> Result { + let device_identity = DeviceIdentity::from_current_machine()?; + let pairing = PairingProtocol::new(device_identity.clone()); + + Ok(Self { + config, + device_identity, + pairing: Arc::new(RwLock::new(pairing)), + relay_client: Arc::new(RwLock::new(None)), + remote_server: Arc::new(RwLock::new(None)), + active_method: Arc::new(RwLock::new(None)), + ngrok_tunnel: Arc::new(RwLock::new(None)), + embedded_relay: Arc::new(RwLock::new(None)), + bot_telegram_handle: Arc::new(RwLock::new(None)), + bot_feishu_handle: Arc::new(RwLock::new(None)), + telegram_bot: Arc::new(RwLock::new(None)), + feishu_bot: Arc::new(RwLock::new(None)), + bot_connected_info: Arc::new(RwLock::new(None)), + }) + } + + pub fn device_identity(&self) -> &DeviceIdentity { + &self.device_identity + } + + pub fn update_bot_config(&mut self, bot_config: bot::BotConfig) { + match bot_config { + bot::BotConfig::Feishu { app_id, app_secret } => { + self.config.bot_feishu = Some(bot::BotConfig::Feishu { app_id, app_secret }); + } + bot::BotConfig::Telegram { bot_token } => { + self.config.bot_telegram = Some(bot::BotConfig::Telegram { bot_token }); + } + } + } + + pub async fn available_methods(&self) -> Vec { + vec![ + ConnectionMethod::Lan, + ConnectionMethod::Ngrok, + ConnectionMethod::BitfunServer, + ConnectionMethod::CustomServer { + url: self.config.custom_server_url.clone().unwrap_or_default(), + }, + ConnectionMethod::BotFeishu, + ConnectionMethod::BotTelegram, + ] + } + + /// Start a remote connection with the given method. + /// + /// For relay methods (LAN / ngrok / BitFun Server / Custom Server) this + /// tears down any existing relay and starts a new one. + /// For bot methods, this starts the bot pairing flow without affecting + /// any running relay connection. + pub async fn start(&self, method: ConnectionMethod) -> Result { + info!("Starting remote connect: {method:?}"); + + match &method { + ConnectionMethod::BotFeishu | ConnectionMethod::BotTelegram => { + return self.start_bot_connection(&method).await; + } + _ => {} + } + + // Relay methods: clean up previous relay (but leave bots alone) + self.stop_relay().await; + + let static_dir = self.config.mobile_web_dir.as_deref(); + + let relay_url = match &method { + ConnectionMethod::Lan => { + let handle = + embedded_relay::start_embedded_relay(self.config.lan_port, static_dir).await?; + *self.embedded_relay.write().await = Some(handle); + match lan::build_lan_relay_url(self.config.lan_port) { + Ok(url) => url, + Err(e) => { + if let Some(ref mut relay) = *self.embedded_relay.write().await { + relay.stop(); + } + *self.embedded_relay.write().await = None; + return Err(e); + } + } + } + ConnectionMethod::Ngrok => { + let handle = + embedded_relay::start_embedded_relay(self.config.lan_port, static_dir).await?; + *self.embedded_relay.write().await = Some(handle); + + let tunnel = match ngrok::start_ngrok_tunnel(self.config.lan_port).await { + Ok(tunnel) => tunnel, + Err(e) => { + if let Some(ref mut relay) = *self.embedded_relay.write().await { + relay.stop(); + } + *self.embedded_relay.write().await = None; + return Err(e); + } + }; + let url = tunnel.public_url.clone(); + *self.ngrok_tunnel.write().await = Some(tunnel); + url + } + ConnectionMethod::BitfunServer => self.config.bitfun_server_url.clone(), + ConnectionMethod::CustomServer { url } => url.clone(), + _ => unreachable!(), + }; + + let mut pairing = self.pairing.write().await; + pairing.reset().await; + let qr_payload = pairing.initiate(&relay_url).await?; + + let ws_url = match &method { + ConnectionMethod::Lan | ConnectionMethod::Ngrok => { + format!("ws://127.0.0.1:{}/ws", self.config.lan_port) + } + _ => { + format!( + "{}/ws", + relay_url + .replace("https://", "wss://") + .replace("http://", "ws://") + ) + } + }; + + let (client, mut event_rx) = RelayClient::new(); + client.connect(&ws_url).await?; + client + .create_room( + &self.device_identity.device_id, + &qr_payload.public_key, + Some(&qr_payload.room_id), + ) + .await?; + + let web_app_url: String = match &method { + ConnectionMethod::Lan | ConnectionMethod::Ngrok => relay_url.clone(), + ConnectionMethod::BitfunServer => { + if let Some(web_dir) = static_dir { + match upload_mobile_web(&relay_url, &qr_payload.room_id, web_dir).await { + Ok(()) => { + let url = format!( + "{}/r/{}", + relay_url.trim_end_matches('/'), + qr_payload.room_id + ); + info!("Uploaded mobile-web to relay: {url}"); + url + } + Err(e) => { + error!("Failed to upload mobile-web to relay: {e}; falling back to server-hosted version"); + self.config.web_app_url.clone() + } + } + } else { + info!("No mobile_web_dir configured; using server-hosted mobile web"); + self.config.web_app_url.clone() + } + } + ConnectionMethod::CustomServer { .. } => { + if let Some(web_dir) = static_dir { + match upload_mobile_web(&relay_url, &qr_payload.room_id, web_dir).await { + Ok(()) => { + let url = format!( + "{}/r/{}", + relay_url.trim_end_matches('/'), + qr_payload.room_id + ); + info!("Uploaded mobile-web to relay: {url}"); + url + } + Err(e) => { + error!("Failed to upload mobile-web to custom relay: {e}; using custom server URL directly"); + relay_url.clone() + } + } + } else { + info!("No mobile_web_dir configured; using custom server URL directly"); + relay_url.clone() + } + } + _ => self.config.web_app_url.clone(), + }; + + let qr_url = QrGenerator::build_url(&qr_payload, &web_app_url); + let qr_svg = QrGenerator::generate_svg_from_url(&qr_url)?; + let qr_data = QrGenerator::generate_png_base64_from_url(&qr_url)?; + + *self.active_method.write().await = Some(method.clone()); + *self.relay_client.write().await = Some(client); + + let pairing_arc = self.pairing.clone(); + let relay_arc = self.relay_client.clone(); + let server_arc = self.remote_server.clone(); + tokio::spawn(async move { + while let Some(event) = event_rx.recv().await { + match event { + relay_client::RelayEvent::PeerJoined { + public_key, + device_id, + } => { + info!("Peer joined: {device_id}"); + let mut p = pairing_arc.write().await; + match p.on_peer_joined(&public_key).await { + Ok(challenge) => { + if let Some(secret) = p.shared_secret() { + let challenge_json = + serde_json::to_string(&challenge).unwrap_or_default(); + if let Ok((enc, nonce)) = + encryption::encrypt_to_base64(secret, &challenge_json) + { + if let Some(ref client) = *relay_arc.read().await { + if let Some(room) = p.room_id() { + let _ = client + .send_encrypted(room, &enc, &nonce) + .await; + } + } + } + } + } + Err(e) => { + error!("Pairing error on peer_joined: {e}"); + } + } + } + relay_client::RelayEvent::MessageReceived { + encrypted_data, + nonce, + } => { + let is_paired = server_arc.read().await.is_some(); + + if is_paired { + let server_guard = server_arc.read().await; + if let Some(ref server) = *server_guard { + match server.decrypt_command(&encrypted_data, &nonce) { + Ok((cmd, request_id)) => { + info!("Remote command: {cmd:?}"); + let response = server.dispatch(&cmd).await; + match server + .encrypt_response(&response, request_id.as_deref()) + { + Ok((enc, resp_nonce)) => { + if let Some(ref client) = *relay_arc.read().await { + let p = pairing_arc.read().await; + if let Some(room) = p.room_id() { + let _ = client + .send_encrypted( + room, &enc, &resp_nonce, + ) + .await; + } + } + } + Err(e) => { + error!("Failed to encrypt response: {e}"); + } + } + } + Err(e) => error!("Failed to decrypt command: {e}"), + } + } + } else { + let p = pairing_arc.read().await; + if let Some(secret) = p.shared_secret() { + if let Ok(json) = encryption::decrypt_from_base64( + secret, + &encrypted_data, + &nonce, + ) { + if let Ok(response) = + serde_json::from_str::(&json) + { + drop(p); + let mut pw = pairing_arc.write().await; + match pw.verify_response(&response).await { + Ok(true) => { + info!("Pairing verified successfully"); + if let Some(s) = pw.shared_secret() { + let (stream_tx, mut stream_rx) = tokio::sync::mpsc::unbounded_channel::(); + + let relay_for_stream = relay_arc.clone(); + let pairing_for_stream = pairing_arc.clone(); + tokio::spawn(async move { + while let Some((enc, nonce)) = + stream_rx.recv().await + { + if let Some(ref client) = + *relay_for_stream.read().await + { + let p = pairing_for_stream + .read() + .await; + if let Some(room) = p.room_id() { + let _ = client + .send_encrypted( + room, &enc, &nonce, + ) + .await; + } + } + } + }); + + let server = + RemoteServer::new(*s, stream_tx); + + let initial_sync = + server.generate_initial_sync().await; + if let Ok((enc, nonce)) = server + .encrypt_response(&initial_sync, None) + { + if let Some(ref client) = + *relay_arc.read().await + { + if let Some(room) = pw.room_id() { + info!("Sending initial sync to mobile after pairing"); + let _ = client + .send_encrypted( + room, &enc, &nonce, + ) + .await; + } + } + } + + *server_arc.write().await = Some(server); + } + } + Ok(false) => { + error!("Pairing verification failed"); + } + Err(e) => { + error!("Pairing verification error: {e}"); + } + } + } + } + } + } + } + relay_client::RelayEvent::PeerDisconnected { device_id } => { + info!("Peer disconnected: {device_id}"); + pairing_arc.write().await.disconnect().await; + *server_arc.write().await = None; + } + relay_client::RelayEvent::Reconnected => { + info!("Relay reconnected, resetting pairing state"); + pairing_arc.write().await.disconnect().await; + *server_arc.write().await = None; + } + relay_client::RelayEvent::Disconnected => { + info!("Relay disconnected"); + } + relay_client::RelayEvent::Error { message } => { + error!("Relay error: {message}"); + if message.contains("Room not found") { + info!("Room expired, disconnecting"); + pairing_arc.write().await.disconnect().await; + *server_arc.write().await = None; + } + } + _ => {} + } + } + }); + + let state = pairing.state().await; + Ok(ConnectionResult { + method, + qr_data: Some(qr_data), + qr_svg: Some(qr_svg), + qr_url: Some(qr_url), + bot_pairing_code: None, + bot_link: None, + pairing_state: state, + }) + } + + async fn start_bot_connection(&self, method: &ConnectionMethod) -> Result { + let pairing_code = PairingProtocol::generate_bot_pairing_code(); + + let bot_link = match method { + ConnectionMethod::BotTelegram => { + match &self.config.bot_telegram { + Some(bot::BotConfig::Telegram { bot_token }) if !bot_token.is_empty() => { + // Stop any existing Telegram bot + if let Some(handle) = self.bot_telegram_handle.write().await.take() { + handle.stop(); + } + + let tg_bot = Arc::new(bot::telegram::TelegramBot::new( + bot::telegram::TelegramConfig { + bot_token: bot_token.clone(), + }, + )); + tg_bot.register_pairing(&pairing_code).await?; + + let (stop_tx, stop_rx) = tokio::sync::watch::channel(false); + + let bot_connected_info = self.bot_connected_info.clone(); + let bot_for_pair = tg_bot.clone(); + let bot_for_loop = tg_bot.clone(); + let tg_bot_ref = self.telegram_bot.clone(); + + *tg_bot_ref.write().await = Some(tg_bot.clone()); + + tokio::spawn(async move { + match bot_for_pair.wait_for_pairing().await { + Ok(chat_id) => { + *bot_connected_info.write().await = + Some(format!("Telegram({chat_id})")); + info!("Telegram bot paired, starting message loop"); + bot_for_loop.run_message_loop(stop_rx).await; + } + Err(e) => { + error!("Telegram pairing failed: {e}"); + } + } + }); + + *self.bot_telegram_handle.write().await = + Some(BotHandle { stop_tx }); + + "https://t.me/BotFather".to_string() + } + _ => { + return Err(anyhow::anyhow!( + "Telegram bot token not configured. Please set bot token first." + )); + } + } + } + ConnectionMethod::BotFeishu => { + match &self.config.bot_feishu { + Some(bot::BotConfig::Feishu { app_id, app_secret }) + if !app_id.is_empty() && !app_secret.is_empty() => + { + if let Some(handle) = self.bot_feishu_handle.write().await.take() { + handle.stop(); + } + + let fs_bot = Arc::new(bot::feishu::FeishuBot::new( + bot::feishu::FeishuConfig { + app_id: app_id.clone(), + app_secret: app_secret.clone(), + }, + )); + fs_bot.register_pairing(&pairing_code).await?; + + let (stop_tx, stop_rx) = tokio::sync::watch::channel(false); + + let bot_connected_info = self.bot_connected_info.clone(); + let bot_for_pair = fs_bot.clone(); + let bot_for_loop = fs_bot.clone(); + let fs_bot_ref = self.feishu_bot.clone(); + + *fs_bot_ref.write().await = Some(fs_bot.clone()); + + tokio::spawn(async move { + match bot_for_pair.wait_for_pairing().await { + Ok(chat_id) => { + *bot_connected_info.write().await = + Some(format!("Feishu({chat_id})")); + info!("Feishu bot paired, starting message loop"); + bot_for_loop.run_message_loop(stop_rx).await; + } + Err(e) => { + error!("Feishu pairing failed: {e}"); + } + } + }); + + *self.bot_feishu_handle.write().await = Some(BotHandle { stop_tx }); + + "https://open.feishu.cn/app".to_string() + } + _ => { + return Err(anyhow::anyhow!( + "Feishu bot credentials not configured. \ + Please set App ID and App Secret first." + )); + } + } + } + _ => String::new(), + }; + + Ok(ConnectionResult { + method: method.clone(), + qr_data: None, + qr_svg: None, + qr_url: None, + bot_pairing_code: Some(pairing_code), + bot_link: Some(bot_link), + pairing_state: PairingState::WaitingForScan, + }) + } + + /// Restore a previously paired bot from persistence. + /// Skips the pairing step and directly starts the message loop. + pub async fn restore_bot(&self, saved: &bot::SavedBotConnection) -> Result<()> { + match saved.config { + bot::BotConfig::Telegram { ref bot_token } => { + if let Some(handle) = self.bot_telegram_handle.write().await.take() { + handle.stop(); + } + + let tg_bot = Arc::new(bot::telegram::TelegramBot::new( + bot::telegram::TelegramConfig { + bot_token: bot_token.clone(), + }, + )); + + let chat_id: i64 = saved.chat_id.parse().map_err(|_| { + anyhow::anyhow!("invalid saved telegram chat_id: {}", saved.chat_id) + })?; + tg_bot + .restore_chat_state(chat_id, saved.chat_state.clone()) + .await; + + let (stop_tx, stop_rx) = tokio::sync::watch::channel(false); + *self.telegram_bot.write().await = Some(tg_bot.clone()); + *self.bot_connected_info.write().await = + Some(format!("Telegram({chat_id})")); + + let bot_for_loop = tg_bot.clone(); + tokio::spawn(async move { + info!("Telegram bot restored from persistence, starting message loop"); + bot_for_loop.run_message_loop(stop_rx).await; + }); + + *self.bot_telegram_handle.write().await = Some(BotHandle { stop_tx }); + info!("Telegram bot restored for chat_id={chat_id}"); + } + bot::BotConfig::Feishu { + ref app_id, + ref app_secret, + } => { + if let Some(handle) = self.bot_feishu_handle.write().await.take() { + handle.stop(); + } + + let fs_bot = Arc::new(bot::feishu::FeishuBot::new( + bot::feishu::FeishuConfig { + app_id: app_id.clone(), + app_secret: app_secret.clone(), + }, + )); + + fs_bot + .restore_chat_state(&saved.chat_id, saved.chat_state.clone()) + .await; + + let (stop_tx, stop_rx) = tokio::sync::watch::channel(false); + *self.feishu_bot.write().await = Some(fs_bot.clone()); + + let cid = saved.chat_id.clone(); + *self.bot_connected_info.write().await = + Some(format!("Feishu({cid})")); + + let bot_for_loop = fs_bot.clone(); + tokio::spawn(async move { + info!("Feishu bot restored from persistence, starting message loop"); + bot_for_loop.run_message_loop(stop_rx).await; + }); + + *self.bot_feishu_handle.write().await = Some(BotHandle { stop_tx }); + info!("Feishu bot restored for chat_id={}", saved.chat_id); + } + } + Ok(()) + } + + pub async fn pairing_state(&self) -> PairingState { + self.pairing.read().await.state().await + } + + /// Stop relay connections (LAN / ngrok / BitFun Server / Custom Server). + /// Bot connections are left running. + pub async fn stop_relay(&self) { + if let Some(ref client) = *self.relay_client.read().await { + client.disconnect().await; + } + *self.relay_client.write().await = None; + *self.remote_server.write().await = None; + *self.active_method.write().await = None; + + if let Some(ref mut tunnel) = *self.ngrok_tunnel.write().await { + tunnel.stop().await; + } + *self.ngrok_tunnel.write().await = None; + + if let Some(ref mut relay) = *self.embedded_relay.write().await { + relay.stop(); + } + *self.embedded_relay.write().await = None; + + self.pairing.write().await.reset().await; + info!("Relay connections stopped (bots unaffected)"); + } + + /// Stop all bot connections. + pub async fn stop_bots(&self) { + if let Some(handle) = self.bot_telegram_handle.write().await.take() { + handle.stop(); + } + *self.telegram_bot.write().await = None; + + if let Some(handle) = self.bot_feishu_handle.write().await.take() { + handle.stop(); + } + *self.feishu_bot.write().await = None; + *self.bot_connected_info.write().await = None; + + info!("Bot connections stopped"); + } + + /// Legacy `stop()` — only stops relay for backward compatibility. + /// Bot connections persist independently. + pub async fn stop(&self) { + self.stop_relay().await; + } + + /// Stop everything (relay + bots). + pub async fn stop_all(&self) { + self.stop_relay().await; + self.stop_bots().await; + } + + pub async fn is_connected(&self) -> bool { + self.pairing.read().await.state().await == PairingState::Connected + } + + pub async fn active_method(&self) -> Option { + self.active_method.read().await.clone() + } + + pub async fn peer_device_name(&self) -> Option { + self.pairing + .read() + .await + .peer_device_name() + .map(String::from) + } + + /// Check whether a specific bot type is currently running. + pub async fn is_bot_running(&self, bot_type: &str) -> bool { + match bot_type { + "telegram" => self.bot_telegram_handle.read().await.is_some(), + "feishu" => self.bot_feishu_handle.read().await.is_some(), + _ => false, + } + } + + pub async fn bot_connected_info(&self) -> Option { + self.bot_connected_info.read().await.clone() + } +} + +// ── Upload mobile-web to relay server ────────────────────────────── + +/// File metadata used for the incremental upload check. +#[derive(serde::Serialize)] +struct FileManifestEntry { + path: String, + hash: String, + size: u64, +} + +/// Collected file data ready for upload. +struct CollectedFile { + rel_path: String, + content: Vec, + hash: String, +} + +async fn upload_mobile_web(relay_url: &str, room_id: &str, web_dir: &str) -> Result<()> { + let base = std::path::Path::new(web_dir); + if !base.join("index.html").exists() { + return Err(anyhow::anyhow!( + "mobile-web dir missing index.html: {}", + web_dir + )); + } + + let mut all_files: Vec = Vec::new(); + collect_files_with_hash(base, base, &mut all_files)?; + + info!( + "Collected {} mobile-web files ({} bytes total) for room {room_id}", + all_files.len(), + all_files.iter().map(|f| f.content.len()).sum::() + ); + + let client = reqwest::Client::new(); + let relay_base = relay_url.trim_end_matches('/'); + + // Step 1: try incremental check + let manifest: Vec = all_files + .iter() + .map(|f| FileManifestEntry { + path: f.rel_path.clone(), + hash: f.hash.clone(), + size: f.content.len() as u64, + }) + .collect(); + + let check_url = format!("{relay_base}/api/rooms/{room_id}/check-web-files"); + let check_result = client + .post(&check_url) + .json(&serde_json::json!({ "files": manifest })) + .timeout(std::time::Duration::from_secs(15)) + .send() + .await; + + match check_result { + Ok(resp) if resp.status().is_success() => { + let body: serde_json::Value = resp.json().await.map_err(|e| { + anyhow::anyhow!("parse check-web-files response: {e}") + })?; + let needed: Vec = body["needed"] + .as_array() + .map(|arr| { + arr.iter() + .filter_map(|v| v.as_str().map(String::from)) + .collect() + }) + .unwrap_or_default(); + + let existing = body["existing_count"].as_u64().unwrap_or(0); + let total = body["total_count"].as_u64().unwrap_or(0); + + if needed.is_empty() { + info!( + "All {total} files already exist on relay server, no upload needed" + ); + return Ok(()); + } + + info!( + "Incremental upload: {existing}/{total} files already on server, uploading {} needed", + needed.len() + ); + + upload_needed_files(&client, relay_base, room_id, &all_files, &needed).await + } + Ok(resp) if resp.status().as_u16() == 404 => { + info!("Relay server does not support incremental upload, falling back to full upload"); + upload_all_files(&client, relay_base, room_id, &all_files).await + } + Ok(resp) => { + let status = resp.status(); + info!("check-web-files returned HTTP {status}, falling back to full upload"); + upload_all_files(&client, relay_base, room_id, &all_files).await + } + Err(e) => { + info!("check-web-files request failed ({e}), falling back to full upload"); + upload_all_files(&client, relay_base, room_id, &all_files).await + } + } +} + +/// Upload only the files that the server said it needs. +async fn upload_needed_files( + client: &reqwest::Client, + relay_base: &str, + room_id: &str, + all_files: &[CollectedFile], + needed: &[String], +) -> Result<()> { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + use std::collections::HashMap; + + let needed_set: std::collections::HashSet<&str> = + needed.iter().map(|s| s.as_str()).collect(); + + let mut files_payload: HashMap = HashMap::new(); + for f in all_files { + if needed_set.contains(f.rel_path.as_str()) { + files_payload.insert( + f.rel_path.clone(), + serde_json::json!({ + "content": B64.encode(&f.content), + "hash": f.hash, + }), + ); + } + } + + let url = format!("{relay_base}/api/rooms/{room_id}/upload-web-files"); + let total_b64_bytes: usize = files_payload.values().map(|v| { + v["content"].as_str().map_or(0, |s| s.len()) + }).sum(); + + info!( + "Uploading {} needed files ({} bytes base64) to {url}", + files_payload.len(), + total_b64_bytes + ); + + let resp = client + .post(&url) + .json(&serde_json::json!({ "files": files_payload })) + .timeout(std::time::Duration::from_secs(30)) + .send() + .await + .map_err(|e| anyhow::anyhow!("upload-web-files: {e}"))?; + + if !resp.status().is_success() { + let status = resp.status(); + let body = resp.text().await.unwrap_or_default(); + return Err(anyhow::anyhow!( + "upload-web-files failed: HTTP {status} — {body}" + )); + } + + Ok(()) +} + +/// Fallback: upload all files using the legacy endpoint. +async fn upload_all_files( + client: &reqwest::Client, + relay_base: &str, + room_id: &str, + all_files: &[CollectedFile], +) -> Result<()> { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + use std::collections::HashMap; + + let mut files: HashMap = HashMap::new(); + for f in all_files { + files.insert(f.rel_path.clone(), B64.encode(&f.content)); + } + + let url = format!("{relay_base}/api/rooms/{room_id}/upload-web"); + + info!( + "Full upload: {} files ({} bytes base64) to {url}", + files.len(), + files.values().map(|v| v.len()).sum::() + ); + + let resp = client + .post(&url) + .json(&serde_json::json!({ "files": files })) + .timeout(std::time::Duration::from_secs(30)) + .send() + .await + .map_err(|e| anyhow::anyhow!("upload mobile-web: {e}"))?; + + if !resp.status().is_success() { + let status = resp.status(); + let body = resp.text().await.unwrap_or_default(); + return Err(anyhow::anyhow!( + "upload mobile-web failed: HTTP {status} — {body}" + )); + } + + Ok(()) +} + +/// Recursively collect files with their SHA-256 hash. +fn collect_files_with_hash( + base: &std::path::Path, + dir: &std::path::Path, + out: &mut Vec, +) -> Result<()> { + use sha2::{Digest, Sha256}; + + for entry in std::fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + collect_files_with_hash(base, &path, out)?; + } else if path.is_file() { + let rel = path + .strip_prefix(base) + .unwrap_or(&path) + .to_string_lossy() + .replace('\\', "/"); + let content = std::fs::read(&path)?; + let mut hasher = Sha256::new(); + hasher.update(&content); + let hash = format!("{:x}", hasher.finalize()); + out.push(CollectedFile { + rel_path: rel, + content, + hash, + }); + } + } + Ok(()) +} diff --git a/src/crates/core/src/service/remote_connect/ngrok.rs b/src/crates/core/src/service/remote_connect/ngrok.rs new file mode 100644 index 00000000..07806a3f --- /dev/null +++ b/src/crates/core/src/service/remote_connect/ngrok.rs @@ -0,0 +1,291 @@ +//! ngrok tunnel mode for Remote Connect. +//! +//! Supports macOS (pgrep) and Windows (tasklist) for process detection. + +use anyhow::{anyhow, Result}; +use log::{info, warn}; +use std::path::PathBuf; +use std::process::Stdio; +use std::sync::atomic::{AtomicU32, Ordering}; +use tokio::io::{AsyncBufReadExt, BufReader}; +use tokio::process::Command; + +/// Tracks the PID of the ngrok process we started, so it can be killed +/// synchronously during application exit even if async cleanup didn't run. +static NGROK_PID: AtomicU32 = AtomicU32::new(0); + +/// Find the ngrok binary, checking common locations beyond just PATH. +fn find_ngrok() -> Option { + if let Ok(path) = which::which("ngrok") { + return Some(path); + } + + let candidates: Vec = vec![ + PathBuf::from("/usr/local/bin/ngrok"), + PathBuf::from("/opt/homebrew/bin/ngrok"), + dirs::home_dir() + .map(|h| h.join("ngrok")) + .unwrap_or_default(), + dirs::home_dir() + .map(|h| h.join(".ngrok/ngrok")) + .unwrap_or_default(), + dirs::home_dir() + .map(|h| h.join("bin/ngrok")) + .unwrap_or_default(), + #[cfg(target_os = "windows")] + { + let appdata = std::env::var("LOCALAPPDATA").unwrap_or_default(); + PathBuf::from(format!("{appdata}\\ngrok\\ngrok.exe")) + }, + #[cfg(target_os = "windows")] + PathBuf::from("C:\\ngrok\\ngrok.exe"), + ]; + + for path in candidates { + if path.exists() && path.is_file() { + return Some(path); + } + } + + None +} + +/// Check if ngrok is installed and available. +pub async fn is_ngrok_available() -> bool { + find_ngrok().is_some() +} + +/// Check if any ngrok process is already running on the system. +/// Returns `Some(pids)` if found, `None` if not. +pub fn detect_running_ngrok() -> Option> { + let pids = list_ngrok_pids(); + if pids.is_empty() { + None + } else { + Some(pids) + } +} + +#[cfg(unix)] +fn list_ngrok_pids() -> Vec { + std::process::Command::new("pgrep") + .args(["-x", "ngrok"]) + .output() + .ok() + .and_then(|out| { + if out.status.success() { + let text = String::from_utf8_lossy(&out.stdout); + Some( + text.lines() + .filter_map(|l| l.trim().parse::().ok()) + .collect(), + ) + } else { + None + } + }) + .unwrap_or_default() +} + +#[cfg(windows)] +fn list_ngrok_pids() -> Vec { + std::process::Command::new("tasklist") + .args(["/FI", "IMAGENAME eq ngrok.exe", "/FO", "CSV", "/NH"]) + .output() + .ok() + .map(|out| { + let text = String::from_utf8_lossy(&out.stdout); + text.lines() + .filter_map(|line| { + // CSV format: "ngrok.exe","PID",... + let parts: Vec<&str> = line.split(',').collect(); + parts + .get(1) + .and_then(|s| s.trim_matches('"').trim().parse::().ok()) + }) + .collect() + }) + .unwrap_or_default() +} + +/// Start an ngrok HTTP tunnel and return the public URL. +/// +/// Parses the tunnel URL directly from ngrok's stdout JSON logs instead of +/// querying the shared 4040 API, which avoids conflicts with any pre-existing +/// ngrok process. +/// +/// Returns a descriptive error if: +/// - ngrok is not installed +/// - another ngrok process is already running +/// - the tunnel fails to establish within the timeout +pub async fn start_ngrok_tunnel(local_port: u16) -> Result { + let ngrok_path = find_ngrok().ok_or_else(|| { + anyhow!( + "ngrok is not installed.\n\ + Please install ngrok and configure your auth token, then retry.\n\ + No need to start ngrok manually — BitFun will start it automatically.\n\ + Setup guide: https://dashboard.ngrok.com/get-started/setup" + ) + })?; + + if let Some(pids) = detect_running_ngrok() { + return Err(anyhow!( + "An ngrok process is already running (PID: {}).\n\ + Please stop the existing ngrok process before starting a new tunnel,\n\ + or use the existing tunnel directly.", + pids.iter().map(|p| p.to_string()).collect::>().join(", ") + )); + } + + info!("Using ngrok at: {}", ngrok_path.display()); + + let mut child = Command::new(&ngrok_path) + .args([ + "http", + &local_port.to_string(), + "--log", + "stdout", + "--log-format", + "json", + ]) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| { + anyhow!( + "Failed to start ngrok process: {e}\n\ + Please ensure ngrok is installed and your auth token is configured \ + (run: ngrok config add-authtoken ).\n\ + No need to start ngrok manually — BitFun will start it automatically." + ) + })?; + + let pid = child.id().unwrap_or(0); + NGROK_PID.store(pid, Ordering::Relaxed); + info!("ngrok process started, pid={pid}"); + + let stdout = child + .stdout + .take() + .ok_or_else(|| anyhow!("Failed to capture ngrok stdout"))?; + + let public_url = match parse_tunnel_url_from_stdout(stdout).await { + Ok(url) => url, + Err(e) => { + let _ = child.kill().await; + return Err(anyhow!( + "ngrok tunnel failed to establish: {e}\n\ + Possible causes:\n\ + - ngrok auth token not configured (run: ngrok config add-authtoken )\n\ + - Network connectivity issue\n\ + - ngrok service outage\n\ + Note: You do not need to start ngrok manually." + )); + } + }; + + info!("ngrok tunnel established: {public_url}"); + + Ok(NgrokTunnel { + public_url, + local_port, + pid: Some(pid), + process: Some(child), + }) +} + +/// Read ngrok's JSON log lines from stdout until we find the tunnel URL. +/// ngrok v3 emits: `{"url":"https://xxx.ngrok-free.app", "msg":"started tunnel", ...}` +async fn parse_tunnel_url_from_stdout(stdout: tokio::process::ChildStdout) -> Result { + let reader = BufReader::new(stdout); + let mut lines = reader.lines(); + + let deadline = tokio::time::Instant::now() + std::time::Duration::from_secs(15); + + let (url_tx, url_rx) = tokio::sync::oneshot::channel::(); + let mut url_tx = Some(url_tx); + + tokio::spawn(async move { + while let Ok(Some(line)) = lines.next_line().await { + if let Ok(obj) = serde_json::from_str::(&line) { + if let Some(url) = obj.get("url").and_then(|v| v.as_str()) { + if url.starts_with("https://") || url.starts_with("http://") { + if let Some(tx) = url_tx.take() { + let _ = tx.send(url.to_string()); + } + } + } + } + } + drop(url_tx); + }); + + match tokio::time::timeout_at(deadline, url_rx).await { + Ok(Ok(url)) => Ok(url), + Ok(Err(_)) => Err(anyhow!("ngrok exited before establishing a tunnel")), + Err(_) => Err(anyhow!("timed out (15s)")), + } +} + +/// Force-kill an ngrok process by PID. +#[cfg(unix)] +fn kill_process(pid: u32) { + let _ = std::process::Command::new("kill") + .args(["-9", &pid.to_string()]) + .output(); +} + +#[cfg(windows)] +fn kill_process(pid: u32) { + let _ = std::process::Command::new("taskkill") + .args(["/F", "/PID", &pid.to_string()]) + .output(); +} + +pub struct NgrokTunnel { + pub public_url: String, + pub local_port: u16, + pid: Option, + process: Option, +} + +impl NgrokTunnel { + pub fn ws_url(&self) -> String { + self.public_url + .replace("https://", "wss://") + .replace("http://", "ws://") + } + + pub async fn stop(&mut self) { + if let Some(ref mut child) = self.process { + let _ = child.kill().await; + info!("ngrok tunnel stopped"); + } + self.process = None; + self.pid = None; + NGROK_PID.store(0, Ordering::Relaxed); + } +} + +impl Drop for NgrokTunnel { + fn drop(&mut self) { + if let Some(ref mut child) = self.process { + let _ = child.start_kill(); + } + if let Some(pid) = self.pid.take() { + kill_process(pid); + warn!("Force-killed ngrok process pid={pid} during cleanup"); + } + NGROK_PID.store(0, Ordering::Relaxed); + } +} + +/// Synchronous cleanup: kill the ngrok process we started (if any). +/// Safe to call from exit handlers and drop implementations. +pub fn cleanup_all_ngrok() { + let pid = NGROK_PID.swap(0, Ordering::Relaxed); + if pid != 0 { + info!("Cleaning up ngrok process pid={pid} on application exit"); + kill_process(pid); + } +} diff --git a/src/crates/core/src/service/remote_connect/pairing.rs b/src/crates/core/src/service/remote_connect/pairing.rs new file mode 100644 index 00000000..35b24ad7 --- /dev/null +++ b/src/crates/core/src/service/remote_connect/pairing.rs @@ -0,0 +1,272 @@ +//! Pairing protocol for establishing E2E encrypted connections. +//! +//! Desktop generates a keypair + room, encodes it in a QR code. +//! Mobile scans QR, joins room, sends its public key. +//! Both sides derive a shared secret via ECDH and verify with a challenge-response. + +use anyhow::{anyhow, Result}; +use rand::Rng; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::RwLock; + +use super::device::DeviceIdentity; +use super::encryption::{self, KeyPair}; + +/// Current state of the pairing process. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum PairingState { + Idle, + WaitingForScan, + Handshaking, + Verifying, + Connected, + Failed { reason: String }, + Disconnected, +} + +/// Information encoded in the QR code. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct QrPayload { + pub url: String, + pub room_id: String, + pub device_id: String, + pub device_name: String, + pub public_key: String, + pub version: u8, +} + +/// Challenge sent from desktop to mobile during pairing verification. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PairingChallenge { + pub challenge: String, + pub timestamp: i64, +} + +/// Response from mobile to desktop. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PairingResponse { + pub challenge_echo: String, + pub device_id: String, + pub device_name: String, +} + +/// Manages the pairing state machine. +pub struct PairingProtocol { + state: Arc>, + keypair: Option, + shared_secret: Option<[u8; 32]>, + room_id: Option, + device_identity: DeviceIdentity, + challenge: Option, + peer_device_id: Option, + peer_device_name: Option, +} + +impl PairingProtocol { + pub fn new(device_identity: DeviceIdentity) -> Self { + Self { + state: Arc::new(RwLock::new(PairingState::Idle)), + keypair: None, + shared_secret: None, + room_id: None, + device_identity, + challenge: None, + peer_device_id: None, + peer_device_name: None, + } + } + + pub async fn state(&self) -> PairingState { + self.state.read().await.clone() + } + + pub fn shared_secret(&self) -> Option<&[u8; 32]> { + self.shared_secret.as_ref() + } + + pub fn room_id(&self) -> Option<&str> { + self.room_id.as_deref() + } + + pub fn peer_device_name(&self) -> Option<&str> { + self.peer_device_name.as_deref() + } + + /// Step 1 (Desktop): Generate keypair and prepare QR payload. + pub async fn initiate(&mut self, relay_url: &str) -> Result { + let keypair = KeyPair::generate(); + let room_id = generate_room_id(); + + let payload = QrPayload { + url: relay_url.to_string(), + room_id: room_id.clone(), + device_id: self.device_identity.device_id.clone(), + device_name: self.device_identity.device_name.clone(), + public_key: keypair.public_key_base64(), + version: 1, + }; + + self.keypair = Some(keypair); + self.room_id = Some(room_id); + *self.state.write().await = PairingState::WaitingForScan; + + Ok(payload) + } + + /// Step 2 (Desktop): Peer joined with their public key — derive shared secret. + pub async fn on_peer_joined(&mut self, peer_public_key_b64: &str) -> Result { + let keypair = self + .keypair + .as_ref() + .ok_or_else(|| anyhow!("no keypair — call initiate() first"))?; + + let peer_pub = encryption::parse_public_key(peer_public_key_b64)?; + let shared = keypair.derive_shared_secret(&peer_pub); + self.shared_secret = Some(shared); + + let challenge = generate_challenge(); + self.challenge = Some(challenge.clone()); + + let challenge_payload = PairingChallenge { + challenge, + timestamp: chrono::Utc::now().timestamp(), + }; + + *self.state.write().await = PairingState::Verifying; + Ok(challenge_payload) + } + + /// Step 3 (Desktop): Verify the peer's challenge response. + pub async fn verify_response(&mut self, response: &PairingResponse) -> Result { + let expected = self + .challenge + .as_ref() + .ok_or_else(|| anyhow!("no challenge issued"))?; + + if response.challenge_echo != *expected { + *self.state.write().await = PairingState::Failed { + reason: "challenge mismatch".to_string(), + }; + return Ok(false); + } + + self.peer_device_id = Some(response.device_id.clone()); + self.peer_device_name = Some(response.device_name.clone()); + *self.state.write().await = PairingState::Connected; + Ok(true) + } + + /// Mobile side: process a received challenge and produce a response. + pub fn answer_challenge( + challenge: &PairingChallenge, + device_identity: &DeviceIdentity, + ) -> PairingResponse { + PairingResponse { + challenge_echo: challenge.challenge.clone(), + device_id: device_identity.device_id.clone(), + device_name: device_identity.device_name.clone(), + } + } + + pub async fn disconnect(&mut self) { + *self.state.write().await = PairingState::Disconnected; + self.shared_secret = None; + self.challenge = None; + self.peer_device_id = None; + self.peer_device_name = None; + } + + pub async fn reset(&mut self) { + *self.state.write().await = PairingState::Idle; + self.keypair = None; + self.shared_secret = None; + self.room_id = None; + self.challenge = None; + self.peer_device_id = None; + self.peer_device_name = None; + } + + pub async fn set_bot_connected(&mut self, peer_name: String) { + self.peer_device_name = Some(peer_name); + *self.state.write().await = PairingState::Connected; + } + + /// Generate a 6-digit pairing code for bot connections. + pub fn generate_bot_pairing_code() -> String { + let code: u32 = rand::thread_rng().gen_range(100_000..1_000_000); + format!("{code:06}") + } +} + +fn generate_room_id() -> String { + let mut rng = rand::thread_rng(); + let bytes: [u8; 8] = rng.gen(); + bytes.iter().map(|b| format!("{b:02x}")).collect() +} + +fn generate_challenge() -> String { + let mut rng = rand::thread_rng(); + let bytes: [u8; 16] = rng.gen(); + bytes.iter().map(|b| format!("{b:02x}")).collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_pairing_flow() { + let device = DeviceIdentity { + device_id: "test-desktop-id".into(), + device_name: "TestDesktop".into(), + mac_address: "AA:BB:CC:DD:EE:FF".into(), + }; + + let mobile_device = DeviceIdentity { + device_id: "test-mobile-id".into(), + device_name: "TestMobile".into(), + mac_address: "11:22:33:44:55:66".into(), + }; + + let mut protocol = PairingProtocol::new(device); + + // Step 1: Desktop initiates + let qr = protocol + .initiate("wss://relay.example.com") + .await + .unwrap(); + assert_eq!(protocol.state().await, PairingState::WaitingForScan); + assert!(!qr.room_id.is_empty()); + + // Simulate mobile generating a keypair and joining + let mobile_keypair = KeyPair::generate(); + let mobile_pub_b64 = mobile_keypair.public_key_base64(); + + // Step 2: Desktop receives mobile's public key + let challenge = protocol.on_peer_joined(&mobile_pub_b64).await.unwrap(); + assert_eq!(protocol.state().await, PairingState::Verifying); + + // Mobile answers the challenge + let response = PairingProtocol::answer_challenge(&challenge, &mobile_device); + + // Step 3: Desktop verifies + let ok = protocol.verify_response(&response).await.unwrap(); + assert!(ok); + assert_eq!(protocol.state().await, PairingState::Connected); + + // Both sides should have matching shared secrets + let desktop_secret = protocol.shared_secret().unwrap(); + let desktop_pub = encryption::parse_public_key(&qr.public_key).unwrap(); + let mobile_shared = mobile_keypair.derive_shared_secret(&desktop_pub); + assert_eq!(*desktop_secret, mobile_shared); + } + + #[test] + fn test_bot_pairing_code() { + let code = PairingProtocol::generate_bot_pairing_code(); + assert_eq!(code.len(), 6); + assert!(code.chars().all(|c| c.is_ascii_digit())); + } +} diff --git a/src/crates/core/src/service/remote_connect/qr_generator.rs b/src/crates/core/src/service/remote_connect/qr_generator.rs new file mode 100644 index 00000000..0a792173 --- /dev/null +++ b/src/crates/core/src/service/remote_connect/qr_generator.rs @@ -0,0 +1,60 @@ +//! QR code generation for Remote Connect pairing. + +use anyhow::{anyhow, Result}; +use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; +use qrcode::QrCode; + +use super::pairing::QrPayload; + +pub struct QrGenerator; + +impl QrGenerator { + /// Build the URL that the QR code points to. + /// `web_app_url` = where the mobile web app is hosted. + /// `payload.url` = the relay server that the mobile WebSocket should connect to. + pub fn build_url(payload: &QrPayload, web_app_url: &str) -> String { + let relay_ws = payload + .url + .replace("https://", "wss://") + .replace("http://", "ws://"); + format!( + "{web_app}/#/pair?room={room}&did={did}&pk={pk}&dn={dn}&relay={relay}&v={v}", + web_app = web_app_url.trim_end_matches('/'), + room = urlencoding::encode(&payload.room_id), + did = urlencoding::encode(&payload.device_id), + pk = urlencoding::encode(&payload.public_key), + dn = urlencoding::encode(&payload.device_name), + relay = urlencoding::encode(&relay_ws), + v = payload.version, + ) + } + + /// Generate a QR code as a base64-encoded PNG from a pre-built URL. + pub fn generate_png_base64_from_url(url: &str) -> Result { + let code = + QrCode::new(url.as_bytes()).map_err(|e| anyhow!("QR code generation failed: {e}"))?; + let img = code.render::>().quiet_zone(true).build(); + let mut buf = Vec::new(); + let encoder = image::codecs::png::PngEncoder::new(&mut buf); + image::ImageEncoder::write_image( + encoder, + img.as_raw(), + img.width(), + img.height(), + image::ExtendedColorType::L8, + ) + .map_err(|e| anyhow!("PNG encoding failed: {e}"))?; + Ok(BASE64.encode(&buf)) + } + + /// Generate the QR code as an SVG string from a pre-built URL. + pub fn generate_svg_from_url(url: &str) -> Result { + let code = + QrCode::new(url.as_bytes()).map_err(|e| anyhow!("QR code generation failed: {e}"))?; + let svg = code + .render::() + .quiet_zone(true) + .build(); + Ok(svg) + } +} diff --git a/src/crates/core/src/service/remote_connect/relay_client.rs b/src/crates/core/src/service/remote_connect/relay_client.rs new file mode 100644 index 00000000..450c5280 --- /dev/null +++ b/src/crates/core/src/service/remote_connect/relay_client.rs @@ -0,0 +1,391 @@ +//! WebSocket client for connecting to the Relay Server. +//! +//! Manages the desktop-side WebSocket connection, sends/receives relay protocol messages, +//! and dispatches events to the pairing and session bridge layers. +//! +//! Supports automatic reconnect: when the connection drops, it retries with exponential +//! backoff and re-creates the same room (same room_id + public_key) so that in-flight +//! QR codes remain valid. + +use anyhow::{anyhow, Result}; +use futures_util::{SinkExt, StreamExt}; +use log::{debug, error, info, warn}; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::{mpsc, RwLock}; +use tokio_tungstenite::tungstenite::Message; + +type WsStream = tokio_tungstenite::WebSocketStream< + tokio_tungstenite::MaybeTlsStream, +>; + +/// Messages in the relay protocol (both directions). +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum RelayMessage { + CreateRoom { + room_id: Option, + device_id: String, + device_type: String, + public_key: String, + }, + RoomCreated { + room_id: String, + }, + JoinRoom { + room_id: String, + device_id: String, + device_type: String, + public_key: String, + }, + PeerJoined { + device_id: String, + device_type: String, + public_key: String, + }, + Relay { + room_id: String, + encrypted_data: String, + nonce: String, + }, + Heartbeat, + HeartbeatAck, + PeerDisconnected { + device_id: String, + }, + Error { + message: String, + }, +} + +/// Events emitted by the relay client to the upper layers. +#[derive(Debug, Clone)] +pub enum RelayEvent { + Connected, + RoomCreated { room_id: String }, + PeerJoined { public_key: String, device_id: String }, + MessageReceived { encrypted_data: String, nonce: String }, + PeerDisconnected { device_id: String }, + /// Emitted after a successful automatic reconnect + room recreation. + Reconnected, + Disconnected, + Error { message: String }, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ConnectionState { + Disconnected, + Connecting, + Connected, + Reconnecting, +} + +/// Information kept to rebuild the room after a reconnect. +#[derive(Debug, Clone, Default)] +struct ReconnectCtx { + ws_url: String, + device_id: String, + room_id: String, + public_key: String, +} + +pub struct RelayClient { + state: Arc>, + event_tx: mpsc::UnboundedSender, + cmd_tx: Arc>>>, + room_id: Arc>>, + reconnect_ctx: Arc>>, +} + +impl RelayClient { + pub fn new() -> (Self, mpsc::UnboundedReceiver) { + let (event_tx, event_rx) = mpsc::unbounded_channel(); + let client = Self { + state: Arc::new(RwLock::new(ConnectionState::Disconnected)), + event_tx, + cmd_tx: Arc::new(RwLock::new(None)), + room_id: Arc::new(RwLock::new(None)), + reconnect_ctx: Arc::new(RwLock::new(None)), + }; + (client, event_rx) + } + + pub async fn connection_state(&self) -> ConnectionState { + self.state.read().await.clone() + } + + /// Connect to the relay server WebSocket endpoint and start background tasks. + pub async fn connect(&self, ws_url: &str) -> Result<()> { + *self.state.write().await = ConnectionState::Connecting; + + let ws_stream = dial(ws_url).await?; + + info!("Connected to relay server at {ws_url}"); + *self.state.write().await = ConnectionState::Connected; + + // Record the ws_url for future reconnect + *self.reconnect_ctx.write().await = Some(ReconnectCtx { + ws_url: ws_url.to_string(), + ..Default::default() + }); + + let _ = self.event_tx.send(RelayEvent::Connected); + self.launch_tasks(ws_stream).await; + Ok(()) + } + + /// Wire up read / write / heartbeat tasks for a live stream. + async fn launch_tasks(&self, ws_stream: WsStream) { + let (mut ws_write, ws_read) = ws_stream.split(); + let (cmd_tx, mut cmd_rx) = mpsc::unbounded_channel::(); + + // Share cmd_tx so `send()` / `create_room()` / heartbeat can enqueue messages + let cmd_tx_arc = self.cmd_tx.clone(); + let state_arc = self.state.clone(); + let room_id_arc = self.room_id.clone(); + let event_tx = self.event_tx.clone(); + let reconnect_arc = self.reconnect_ctx.clone(); + + // Store cmd_tx immediately (before spawning tasks, to avoid race with create_room) + *cmd_tx_arc.write().await = Some(cmd_tx); + + // ── Write task ──────────────────────────────────────────────────────── + tokio::spawn(async move { + while let Some(msg) = cmd_rx.recv().await { + if let Ok(json) = serde_json::to_string(&msg) { + if ws_write.send(Message::Text(json)).await.is_err() { + break; + } + } + } + debug!("Write task exited"); + }); + + // ── Read task with reconnect loop ───────────────────────────────────── + let mut ws_read = ws_read; + tokio::spawn(async move { + 'outer: loop { + // Read messages until connection drops + while let Some(res) = ws_read.next().await { + match res { + Ok(Message::Text(text)) => { + match serde_json::from_str::(&text) { + Ok(msg) => { + Self::dispatch(msg, &event_tx, &room_id_arc).await; + } + Err(e) => { + warn!("Unparseable relay msg: {e}"); + } + } + } + Ok(Message::Ping(_)) => {} + Ok(Message::Close(_)) => { + info!("Relay server closed connection"); + break; + } + Err(e) => { + error!("WebSocket read error: {e}"); + break; + } + _ => {} + } + } + + // Drop detected — enter reconnect loop + *state_arc.write().await = ConnectionState::Reconnecting; + info!("Relay connection dropped; will attempt reconnect"); + + let ctx = reconnect_arc.read().await.clone(); + let Some(ctx) = ctx else { + info!("No reconnect ctx — giving up"); + break 'outer; + }; + + if ctx.ws_url.is_empty() { + break 'outer; + } + + let mut backoff = 2u64; + loop { + if *state_arc.read().await == ConnectionState::Disconnected { + break 'outer; + } + + info!("Reconnect in {backoff}s (url={})", &ctx.ws_url); + tokio::time::sleep(std::time::Duration::from_secs(backoff)).await; + + match dial(&ctx.ws_url).await { + Ok(new_stream) => { + info!("Reconnected to relay server at {}", &ctx.ws_url); + *state_arc.write().await = ConnectionState::Connected; + + let (mut new_write, new_read) = new_stream.split(); + let (new_cmd_tx, mut new_cmd_rx) = + mpsc::unbounded_channel::(); + *cmd_tx_arc.write().await = Some(new_cmd_tx.clone()); + + // New write task + tokio::spawn(async move { + while let Some(msg) = new_cmd_rx.recv().await { + if let Ok(json) = serde_json::to_string(&msg) { + if new_write.send(Message::Text(json)).await.is_err() + { + break; + } + } + } + }); + + // Re-create the room so existing QR codes remain valid + if !ctx.room_id.is_empty() { + let recreate = RelayMessage::CreateRoom { + room_id: Some(ctx.room_id.clone()), + device_id: ctx.device_id.clone(), + device_type: "desktop".to_string(), + public_key: ctx.public_key.clone(), + }; + let _ = new_cmd_tx.send(recreate); + info!("Room '{}' recreated after reconnect", &ctx.room_id); + } + + let _ = event_tx.send(RelayEvent::Reconnected); + ws_read = new_read; + continue 'outer; + } + Err(e) => { + warn!("Reconnect attempt failed: {e}"); + backoff = std::cmp::min(backoff * 2, 30); + } + } + } + } + + *state_arc.write().await = ConnectionState::Disconnected; + let _ = event_tx.send(RelayEvent::Disconnected); + }); + + // ── Heartbeat task ──────────────────────────────────────────────────── + let hb_state = self.state.clone(); + let hb_cmd = self.cmd_tx.clone(); + tokio::spawn(async move { + loop { + tokio::time::sleep(std::time::Duration::from_secs(30)).await; + let st = hb_state.read().await.clone(); + if st == ConnectionState::Disconnected { + break; + } + if st != ConnectionState::Connected { + continue; // Don't heartbeat while reconnecting + } + if let Some(tx) = hb_cmd.read().await.as_ref() { + let _ = tx.send(RelayMessage::Heartbeat); + } + } + }); + } + + async fn dispatch( + msg: RelayMessage, + event_tx: &mpsc::UnboundedSender, + room_id_store: &Arc>>, + ) { + match msg { + RelayMessage::RoomCreated { room_id } => { + debug!("Room created/restored: {room_id}"); + *room_id_store.write().await = Some(room_id.clone()); + let _ = event_tx.send(RelayEvent::RoomCreated { room_id }); + } + RelayMessage::PeerJoined { device_id, public_key, .. } => { + info!("Peer joined: {device_id}"); + let _ = event_tx.send(RelayEvent::PeerJoined { public_key, device_id }); + } + RelayMessage::Relay { encrypted_data, nonce, .. } => { + let _ = event_tx.send(RelayEvent::MessageReceived { encrypted_data, nonce }); + } + RelayMessage::PeerDisconnected { device_id } => { + info!("Peer disconnected: {device_id}"); + let _ = event_tx.send(RelayEvent::PeerDisconnected { device_id }); + } + RelayMessage::HeartbeatAck => { + debug!("Heartbeat acknowledged"); + } + RelayMessage::Error { message } => { + error!("Relay error: {message}"); + let _ = event_tx.send(RelayEvent::Error { message }); + } + _ => {} + } + } + + /// Send a protocol message to the relay server. + pub async fn send(&self, msg: RelayMessage) -> Result<()> { + let guard = self.cmd_tx.read().await; + let tx = guard.as_ref().ok_or_else(|| anyhow!("not connected"))?; + tx.send(msg).map_err(|e| anyhow!("send failed: {e}"))?; + Ok(()) + } + + /// Create a room on the relay server. + /// + /// Also records the device_id / room_id / public_key in the reconnect context + /// so the room is automatically recreated after a transient disconnect. + pub async fn create_room( + &self, + device_id: &str, + public_key: &str, + room_id: Option<&str>, + ) -> Result<()> { + // Update reconnect context with room params + if let Some(rid) = room_id { + let mut guard = self.reconnect_ctx.write().await; + if let Some(ref mut ctx) = *guard { + ctx.device_id = device_id.to_string(); + ctx.room_id = rid.to_string(); + ctx.public_key = public_key.to_string(); + } + } + + self.send(RelayMessage::CreateRoom { + room_id: room_id.map(|s| s.to_string()), + device_id: device_id.to_string(), + device_type: "desktop".to_string(), + public_key: public_key.to_string(), + }) + .await + } + + /// Send an E2E-encrypted relay message. + pub async fn send_encrypted( + &self, + room_id: &str, + encrypted_data: &str, + nonce: &str, + ) -> Result<()> { + self.send(RelayMessage::Relay { + room_id: room_id.to_string(), + encrypted_data: encrypted_data.to_string(), + nonce: nonce.to_string(), + }) + .await + } + + pub async fn disconnect(&self) { + // Signal reconnect loop to stop by clearing the context and setting state + *self.state.write().await = ConnectionState::Disconnected; + *self.reconnect_ctx.write().await = None; + *self.cmd_tx.write().await = None; + info!("Relay client disconnected"); + } + + pub fn room_id(&self) -> &Arc>> { + &self.room_id + } +} + +/// Open a plain WebSocket connection (no TLS negotiation needed — nginx handles TLS). +async fn dial(ws_url: &str) -> Result { + let (stream, _) = tokio_tungstenite::connect_async(ws_url) + .await + .map_err(|e| anyhow!("dial {ws_url}: {e}"))?; + Ok(stream) +} diff --git a/src/crates/core/src/service/remote_connect/remote_server.rs b/src/crates/core/src/service/remote_connect/remote_server.rs new file mode 100644 index 00000000..b7c6764e --- /dev/null +++ b/src/crates/core/src/service/remote_connect/remote_server.rs @@ -0,0 +1,1195 @@ +//! Session bridge: translates remote commands into local session operations. +//! +//! The mobile client sends encrypted commands (list sessions, send message, etc.) +//! which are decrypted and dispatched to the local SessionManager via the global +//! ConversationCoordinator. +//! +//! After a SendMessage command, a `RemoteEventForwarder` is registered as an +//! internal event subscriber so that streaming progress (text chunks, tool events, +//! turn completion, etc.) is encrypted and relayed back to the mobile client. + +use anyhow::{anyhow, Result}; +use log::{debug, error, info}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use tokio::sync::mpsc; + +use super::encryption; + +/// Image sent from mobile as a base64 data-URL. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ImageAttachment { + pub name: String, + pub data_url: String, +} + +/// Commands that the mobile client can send to the desktop. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "cmd", rename_all = "snake_case")] +pub enum RemoteCommand { + GetWorkspaceInfo, + ListRecentWorkspaces, + SetWorkspace { + path: String, + }, + ListSessions { + /// Filter by workspace path. If omitted, falls back to the desktop's current workspace. + workspace_path: Option, + /// Max sessions to return per page (default 30, max 100). + limit: Option, + /// Zero-based offset for pagination. + offset: Option, + }, + CreateSession { + agent_type: Option, + session_name: Option, + /// Workspace to bind the new session to. Falls back to the desktop's + /// current workspace when not provided. + workspace_path: Option, + }, + GetSessionMessages { + session_id: String, + limit: Option, + before_message_id: Option, + }, + SendMessage { + session_id: String, + content: String, + /// When provided, overrides the session's current agent type for this + /// turn (e.g. "agentic", "Plan", "debug"). + agent_type: Option, + /// Images attached by the mobile user (base64 data-URL). + images: Option>, + }, + CancelTask { + session_id: String, + }, + DeleteSession { + session_id: String, + }, + SubscribeSession { + session_id: String, + }, + UnsubscribeSession { + session_id: String, + }, + Ping, +} + +/// Responses sent from desktop back to mobile. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "resp", rename_all = "snake_case")] +pub enum RemoteResponse { + WorkspaceInfo { + has_workspace: bool, + path: Option, + project_name: Option, + git_branch: Option, + }, + RecentWorkspaces { + workspaces: Vec, + }, + WorkspaceUpdated { + success: bool, + path: Option, + project_name: Option, + error: Option, + }, + SessionList { + sessions: Vec, + /// Whether more sessions exist beyond this page. + has_more: bool, + }, + SessionCreated { + session_id: String, + }, + Messages { + session_id: String, + messages: Vec, + has_more: bool, + }, + MessageSent { + session_id: String, + turn_id: String, + }, + StreamEvent { + session_id: String, + event_type: String, + payload: serde_json::Value, + }, + TaskCancelled { + session_id: String, + }, + SessionDeleted { + session_id: String, + }, + SessionSubscribed { + session_id: String, + }, + SessionUnsubscribed { + session_id: String, + }, + /// Pushed to mobile immediately after pairing – contains the desktop's + /// current workspace info and session list so the mobile can display the + /// same data as the desktop without extra round-trips. + InitialSync { + has_workspace: bool, + #[serde(skip_serializing_if = "Option::is_none")] + path: Option, + #[serde(skip_serializing_if = "Option::is_none")] + project_name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + git_branch: Option, + sessions: Vec, + has_more_sessions: bool, + }, + Pong, + Error { + message: String, + }, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SessionInfo { + pub session_id: String, + pub name: String, + pub agent_type: String, + pub created_at: String, + pub updated_at: String, + pub message_count: usize, + /// Workspace path this session belongs to + #[serde(skip_serializing_if = "Option::is_none")] + pub workspace_path: Option, + /// Workspace display name (last path component) + #[serde(skip_serializing_if = "Option::is_none")] + pub workspace_name: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ChatMessage { + pub id: String, + pub role: String, + pub content: String, + pub timestamp: String, + pub metadata: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RecentWorkspaceEntry { + pub path: String, + pub name: String, + pub last_opened: String, +} + +/// An encrypted (data, nonce) pair ready to be sent over the relay. +pub type EncryptedPayload = (String, String); + +/// Strip XML wrapper tags that the agent system adds to user input before storage. +/// e.g. "\nHello\n\n..." +/// → "Hello" +fn strip_user_input_tags(content: &str) -> String { + let s = content.trim(); + // Extract inner content of ... + if s.starts_with("") { + if let Some(end) = s.find("") { + let inner = s["".len()..end].trim(); + return inner.to_string(); + } + } + // Drop section (can appear without wrapper) + if let Some(pos) = s.find("") { + return s[..pos].trim().to_string(); + } + s.to_string() +} + +/// Map mobile-friendly agent type names to the actual agent registry IDs. +fn resolve_agent_type(mobile_type: Option<&str>) -> &'static str { + match mobile_type { + Some("code") | Some("agentic") | Some("Agentic") => "agentic", + Some("cowork") | Some("Cowork") => "Cowork", + Some("plan") | Some("Plan") => "Plan", + Some("debug") | Some("Debug") => "debug", + _ => "agentic", + } +} + +/// Decode a `data:image/...;base64,...` URL and save it as a file. +/// Returns the absolute path to the saved image on success. +fn save_data_url_image( + dir: &std::path::Path, + name: &str, + data_url: &str, +) -> Option { + use base64::{engine::general_purpose::STANDARD as B64, Engine}; + + let (header, b64_data) = data_url.split_once(",")?; + let ext = if header.contains("png") { + "png" + } else if header.contains("gif") { + "gif" + } else if header.contains("webp") { + "webp" + } else { + "jpg" + }; + + let decoded = B64.decode(b64_data.trim()).ok()?; + + let stem = std::path::Path::new(name) + .file_stem() + .and_then(|s| s.to_str()) + .unwrap_or("image"); + let ts = chrono::Utc::now().timestamp_millis(); + let filename = format!("{stem}_{ts}.{ext}"); + let path = dir.join(&filename); + + std::fs::write(&path, &decoded).ok()?; + Some(path) +} + +/// Bridges remote commands to local session operations. +pub struct RemoteServer { + shared_secret: [u8; 32], + active_subscriptions: std::sync::Mutex>, + stream_tx: mpsc::UnboundedSender, +} + +impl Drop for RemoteServer { + fn drop(&mut self) { + if let Ok(subs) = self.active_subscriptions.lock() { + for sub_id in subs.iter() { + unregister_stream_forwarder(sub_id); + } + } + } +} + +impl RemoteServer { + pub fn new(shared_secret: [u8; 32], stream_tx: mpsc::UnboundedSender) -> Self { + Self { + shared_secret, + active_subscriptions: std::sync::Mutex::new(std::collections::HashSet::new()), + stream_tx, + } + } + + pub fn shared_secret(&self) -> &[u8; 32] { + &self.shared_secret + } + + pub fn decrypt_command( + &self, + encrypted_data: &str, + nonce: &str, + ) -> Result<(RemoteCommand, Option)> { + let json = encryption::decrypt_from_base64(&self.shared_secret, encrypted_data, nonce)?; + let value: Value = serde_json::from_str(&json).map_err(|e| anyhow!("parse json: {e}"))?; + let request_id = value + .get("_request_id") + .and_then(|v| v.as_str()) + .map(String::from); + let cmd: RemoteCommand = + serde_json::from_value(value).map_err(|e| anyhow!("parse command: {e}"))?; + Ok((cmd, request_id)) + } + + pub fn encrypt_response( + &self, + response: &RemoteResponse, + request_id: Option<&str>, + ) -> Result { + let mut value = + serde_json::to_value(response).map_err(|e| anyhow!("serialize response: {e}"))?; + if let (Some(id), Some(obj)) = (request_id, value.as_object_mut()) { + obj.insert("_request_id".to_string(), Value::String(id.to_string())); + } + let json = serde_json::to_string(&value).map_err(|e| anyhow!("to_string: {e}"))?; + encryption::encrypt_to_base64(&self.shared_secret, &json) + } + + pub async fn dispatch(&self, cmd: &RemoteCommand) -> RemoteResponse { + match cmd { + RemoteCommand::Ping => RemoteResponse::Pong, + + RemoteCommand::GetWorkspaceInfo | + RemoteCommand::ListRecentWorkspaces | + RemoteCommand::SetWorkspace { .. } => { + self.handle_workspace_command(cmd).await + } + + RemoteCommand::ListSessions { .. } | + RemoteCommand::CreateSession { .. } | + RemoteCommand::GetSessionMessages { .. } | + RemoteCommand::DeleteSession { .. } => { + self.handle_session_command(cmd).await + } + + RemoteCommand::SendMessage { .. } | + RemoteCommand::CancelTask { .. } => { + self.handle_execution_command(cmd).await + } + + RemoteCommand::SubscribeSession { .. } | + RemoteCommand::UnsubscribeSession { .. } => { + self.handle_subscription_command(cmd).await + } + } + } + + /// Build the initial sync payload that is pushed to the mobile right after + /// pairing completes. This reads the same disk source as the desktop UI's + /// `get_conversation_sessions` so the session lists are guaranteed consistent. + pub async fn generate_initial_sync(&self) -> RemoteResponse { + use crate::infrastructure::{get_workspace_path, PathManager}; + use crate::service::conversation::ConversationPersistenceManager; + + let ws_path = get_workspace_path(); + let (has_workspace, path_str, project_name, git_branch) = if let Some(ref p) = ws_path { + let name = p.file_name().map(|n| n.to_string_lossy().to_string()); + let branch = git2::Repository::open(p) + .ok() + .and_then(|repo| repo.head().ok().and_then(|h| h.shorthand().map(String::from))); + (true, Some(p.to_string_lossy().to_string()), name, branch) + } else { + (false, None, None, None) + }; + + let (sessions, has_more) = if let Some(ref wp) = ws_path { + let ws_str = wp.to_string_lossy().to_string(); + let ws_name = wp.file_name().map(|n| n.to_string_lossy().to_string()); + if let Ok(pm) = PathManager::new() { + let pm = std::sync::Arc::new(pm); + if let Ok(conv_mgr) = ConversationPersistenceManager::new(pm, wp.clone()).await { + if let Ok(all_meta) = conv_mgr.get_session_list().await { + let total = all_meta.len(); + let page_size = 100usize; + let has_more = total > page_size; + let sessions: Vec = all_meta + .into_iter() + .take(page_size) + .map(|s| SessionInfo { + session_id: s.session_id, + name: s.session_name, + agent_type: s.agent_type, + created_at: (s.created_at / 1000).to_string(), + updated_at: (s.last_active_at / 1000).to_string(), + message_count: s.turn_count, + workspace_path: Some(ws_str.clone()), + workspace_name: ws_name.clone(), + }) + .collect(); + (sessions, has_more) + } else { + (vec![], false) + } + } else { + (vec![], false) + } + } else { + (vec![], false) + } + } else { + (vec![], false) + }; + + RemoteResponse::InitialSync { + has_workspace, + path: path_str, + project_name, + git_branch, + sessions, + has_more_sessions: has_more, + } + } + + async fn handle_workspace_command(&self, cmd: &RemoteCommand) -> RemoteResponse { + use crate::infrastructure::get_workspace_path; + use crate::service::workspace::get_global_workspace_service; + + match cmd { + RemoteCommand::GetWorkspaceInfo => { + let ws_path = get_workspace_path(); + let (project_name, git_branch) = if let Some(ref p) = ws_path { + let name = p + .file_name() + .map(|n| n.to_string_lossy().to_string()); + let branch = git2::Repository::open(p) + .ok() + .and_then(|repo| { + repo.head() + .ok() + .and_then(|h| h.shorthand().map(String::from)) + }); + (name, branch) + } else { + (None, None) + }; + RemoteResponse::WorkspaceInfo { + has_workspace: ws_path.is_some(), + path: ws_path.map(|p| p.to_string_lossy().to_string()), + project_name, + git_branch, + } + } + RemoteCommand::ListRecentWorkspaces => { + let ws_service = match get_global_workspace_service() { + Some(s) => s, + None => { + return RemoteResponse::RecentWorkspaces { + workspaces: vec![], + }; + } + }; + let recent = ws_service.get_recent_workspaces().await; + let entries = recent + .into_iter() + .map(|w| RecentWorkspaceEntry { + path: w.root_path.to_string_lossy().to_string(), + name: w.name.clone(), + last_opened: w.last_accessed.to_rfc3339(), + }) + .collect(); + RemoteResponse::RecentWorkspaces { workspaces: entries } + } + RemoteCommand::SetWorkspace { path } => { + let ws_service = match get_global_workspace_service() { + Some(s) => s, + None => { + return RemoteResponse::WorkspaceUpdated { + success: false, + path: None, + project_name: None, + error: Some("Workspace service not available".into()), + }; + } + }; + let path_buf = std::path::PathBuf::from(path); + match ws_service.open_workspace(path_buf).await { + Ok(info) => { + if let Err(e) = + crate::service::snapshot::initialize_global_snapshot_manager( + info.root_path.clone(), + None, + ) + .await + { + error!("Failed to initialize snapshot after remote workspace set: {e}"); + } + RemoteResponse::WorkspaceUpdated { + success: true, + path: Some(info.root_path.to_string_lossy().to_string()), + project_name: Some(info.name.clone()), + error: None, + } + } + Err(e) => RemoteResponse::WorkspaceUpdated { + success: false, + path: None, + project_name: None, + error: Some(e.to_string()), + }, + } + } + _ => RemoteResponse::Error { message: "Unknown workspace command".into() }, + } + } + + async fn handle_session_command(&self, cmd: &RemoteCommand) -> RemoteResponse { + use crate::agentic::{coordination::get_global_coordinator, core::SessionConfig}; + + let coordinator = match get_global_coordinator() { + Some(c) => c, + None => { + return RemoteResponse::Error { + message: "Desktop session system not ready".into(), + }; + } + }; + + match cmd { + RemoteCommand::ListSessions { workspace_path, limit, offset } => { + // Only query the explicitly-requested workspace (or fall back to the + // desktop's current workspace when none is specified). Sessions are + // served page-by-page so the frontend never needs to receive more than + // it intends to display. + use crate::infrastructure::{get_workspace_path, PathManager}; + use crate::service::conversation::ConversationPersistenceManager; + + let page_size = limit.unwrap_or(30).min(100); + let page_offset = offset.unwrap_or(0); + + // Resolve which workspace to query + let effective_ws: Option = workspace_path + .as_deref() + .map(std::path::PathBuf::from) + .or_else(|| get_workspace_path()); + + if let Some(ref wp) = effective_ws { + let ws_str = wp.to_string_lossy().to_string(); + let workspace_name = wp.file_name() + .map(|n| n.to_string_lossy().to_string()); + + if let Ok(pm) = PathManager::new() { + let pm = std::sync::Arc::new(pm); + match ConversationPersistenceManager::new(pm, wp.clone()).await { + Ok(conv_mgr) => { + match conv_mgr.get_session_list().await { + Ok(all_meta) => { + // The list is already sorted by last_active_at desc + // at persistence time; apply server-side pagination. + let total = all_meta.len(); + let has_more = page_offset + page_size < total; + let sessions: Vec = all_meta + .into_iter() + .skip(page_offset) + .take(page_size) + .map(|s| { + let created = (s.created_at / 1000).to_string(); + let updated = (s.last_active_at / 1000).to_string(); + SessionInfo { + session_id: s.session_id, + name: s.session_name, + agent_type: s.agent_type, + created_at: created, + updated_at: updated, + message_count: s.turn_count, + workspace_path: Some(ws_str.clone()), + workspace_name: workspace_name.clone(), + } + }) + .collect(); + return RemoteResponse::SessionList { sessions, has_more }; + } + Err(e) => debug!("Session list read failed for {ws_str}: {e}"), + } + } + Err(e) => debug!("ConversationPersistenceManager init failed for {ws_str}: {e}"), + } + } + } + + // Fallback: global in-memory sessions (no workspace available) + match coordinator.list_sessions().await { + Ok(summaries) => { + let total = summaries.len(); + let has_more = page_offset + page_size < total; + let sessions = summaries + .into_iter() + .skip(page_offset) + .take(page_size) + .map(|s| { + let created = s.created_at + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_secs() + .to_string(); + let updated = s.last_activity_at + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_secs() + .to_string(); + SessionInfo { + session_id: s.session_id, + name: s.session_name, + agent_type: s.agent_type, + created_at: created, + updated_at: updated, + message_count: s.turn_count, + workspace_path: None, + workspace_name: None, + } + }) + .collect(); + RemoteResponse::SessionList { sessions, has_more } + } + Err(e) => RemoteResponse::Error { message: e.to_string() }, + } + } + RemoteCommand::CreateSession { + agent_type, + session_name: custom_name, + workspace_path: requested_ws_path, + } => { + use crate::infrastructure::{get_workspace_path, PathManager}; + use crate::service::conversation::{ConversationPersistenceManager, SessionMetadata, SessionStatus}; + + let agent = resolve_agent_type(agent_type.as_deref()); + let session_name = custom_name + .as_deref() + .filter(|n| !n.is_empty()) + .unwrap_or(match agent { + "Cowork" => "Remote Cowork Session", + _ => "Remote Code Session", + }); + // Determine the binding workspace BEFORE creating the session so that + // the workspace_path can be embedded in the SessionCreated event. + // This allows the desktop UI to filter out sessions from other workspaces. + let binding_ws_path: Option = requested_ws_path + .as_deref() + .map(std::path::PathBuf::from) + .or_else(|| get_workspace_path()); + let binding_ws_str = binding_ws_path.as_ref() + .map(|p| p.to_string_lossy().to_string()); + + debug!("Remote CreateSession: requested_ws={:?}, binding_ws={:?}", requested_ws_path, binding_ws_str); + match coordinator + .create_session_with_workspace( + None, + session_name.to_string(), + agent.to_string(), + SessionConfig::default(), + binding_ws_str.clone(), + ) + .await + { + Ok(session) => { + let session_id = session.session_id.clone(); + + if let Some(wp) = binding_ws_path { + if let Ok(pm) = PathManager::new() { + let pm = std::sync::Arc::new(pm); + if let Ok(conv_mgr) = ConversationPersistenceManager::new(pm, wp.clone()).await { + let now_ms = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64; + let meta = SessionMetadata { + session_id: session_id.clone(), + session_name: session_name.to_string(), + agent_type: agent.to_string(), + model_name: "default".to_string(), + created_at: now_ms, + last_active_at: now_ms, + turn_count: 0, + message_count: 0, + tool_call_count: 0, + status: SessionStatus::Active, + terminal_session_id: None, + snapshot_session_id: None, + tags: vec![], + custom_metadata: None, + todos: None, + workspace_path: binding_ws_str, + }; + if let Err(e) = conv_mgr.save_session_metadata(&meta).await { + error!("Failed to sync remote session to workspace: {e}"); + } else { + info!("Remote session synced to workspace: {session_id}"); + } + } + } + } + + RemoteResponse::SessionCreated { session_id } + } + Err(e) => RemoteResponse::Error { + message: e.to_string(), + }, + } + } + RemoteCommand::GetSessionMessages { session_id, limit, before_message_id } => { + let limit = limit.unwrap_or(50); + let session_mgr = coordinator.get_session_manager(); + if session_mgr.get_session(session_id).is_none() { + let _ = coordinator.restore_session(session_id).await; + } + match coordinator.get_messages_paginated(session_id, limit, before_message_id.as_deref()).await { + Ok((messages, has_more)) => { + let chat_msgs = messages + .into_iter() + .map(|m| { + use crate::agentic::core::MessageRole; + let role = match m.role { + MessageRole::User => "user", + MessageRole::Assistant => "assistant", + MessageRole::Tool => "tool", + MessageRole::System => "system", + }; + let raw_content = match &m.content { + crate::agentic::core::MessageContent::Text(t) => t.clone(), + crate::agentic::core::MessageContent::Mixed { + text, .. + } => text.clone(), + crate::agentic::core::MessageContent::ToolResult { + result_for_assistant, + result, + .. + } => result_for_assistant + .clone() + .unwrap_or_else(|| result.to_string()), + }; + // Strip agent-internal XML tags from user messages + let content = if matches!(m.role, MessageRole::User) { + strip_user_input_tags(&raw_content) + } else { + raw_content + }; + let ts = m + .timestamp + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_secs() + .to_string(); + ChatMessage { + id: m.id.clone(), + role: role.to_string(), + content, + timestamp: ts, + metadata: None, + } + }) + .collect(); + RemoteResponse::Messages { + session_id: session_id.clone(), + messages: chat_msgs, + has_more, + } + } + Err(e) => { + RemoteResponse::Error { + message: e.to_string(), + } + } + } + } + RemoteCommand::DeleteSession { session_id } => { + match coordinator.delete_session(session_id).await { + Ok(_) => RemoteResponse::SessionDeleted { + session_id: session_id.clone(), + }, + Err(e) => RemoteResponse::Error { + message: e.to_string(), + }, + } + } + _ => RemoteResponse::Error { message: "Unknown session command".into() }, + } + } + + async fn handle_execution_command(&self, cmd: &RemoteCommand) -> RemoteResponse { + use crate::agentic::coordination::get_global_coordinator; + + let coordinator = match get_global_coordinator() { + Some(c) => c, + None => { + return RemoteResponse::Error { + message: "Desktop session system not ready".into(), + }; + } + }; + + match cmd { + RemoteCommand::SendMessage { + session_id, + content, + agent_type: requested_agent_type, + images, + } => { + let session_mgr = coordinator.get_session_manager(); + let (session_agent_type, session_ws) = session_mgr + .get_session(session_id) + .map(|s| (s.agent_type.clone(), s.config.workspace_path.clone())) + .unwrap_or_else(|| ("default".to_string(), None)); + + let agent_type = requested_agent_type + .as_deref() + .map(|t| resolve_agent_type(Some(t)).to_string()) + .unwrap_or(session_agent_type); + + if let Some(ws_path_str) = &session_ws { + use crate::infrastructure::{get_workspace_path, set_workspace_path}; + let current = get_workspace_path(); + let current_str = current.as_ref().map(|p| p.to_string_lossy().to_string()); + if current_str.as_deref() != Some(ws_path_str.as_str()) { + info!("Remote send_message: temporarily setting workspace for session={session_id} to {ws_path_str}"); + set_workspace_path(Some(std::path::PathBuf::from(ws_path_str))); + } + } + + let full_content = if let Some(imgs) = &images { + if imgs.is_empty() { + content.clone() + } else { + let save_dir = if let Some(ws) = &session_ws { + let d = std::path::PathBuf::from(ws) + .join(".bitfun") + .join("remote-images"); + let _ = std::fs::create_dir_all(&d); + Some(d) + } else { + None + }; + + let mut extra = String::new(); + for (i, img) in imgs.iter().enumerate() { + if let Some(ref dir) = save_dir { + if let Some(saved) = save_data_url_image(dir, &img.name, &img.data_url) { + let path_str = saved.to_string_lossy(); + extra.push_str(&format!( + "\n\n[Image: {}]\nPath: {}\nTip: You can use the AnalyzeImage tool with the image_path parameter.", + img.name, path_str + )); + info!("Remote image {i} saved: {path_str}"); + continue; + } + } + extra.push_str(&format!( + "\n\n[Image: {} (inline)]\nData URL provided inline.\nTip: You can use the AnalyzeImage tool with the data_url parameter.", + img.name + )); + } + format!("{content}{extra}") + } + } else { + content.clone() + }; + + info!("Remote send_message: session={session_id}, agent_type={agent_type}, images={}", images.as_ref().map_or(0, |v| v.len())); + let turn_id = format!("turn_{}", chrono::Utc::now().timestamp_millis()); + match coordinator + .start_dialog_turn( + session_id.clone(), + full_content, + Some(turn_id.clone()), + agent_type, + true, + ) + .await + { + Ok(()) => RemoteResponse::MessageSent { + session_id: session_id.clone(), + turn_id, + }, + Err(e) => RemoteResponse::Error { + message: e.to_string(), + }, + } + } + RemoteCommand::CancelTask { session_id } => { + let session_mgr = coordinator.get_session_manager(); + if let Some(session) = session_mgr.get_session(session_id) { + use crate::agentic::core::SessionState; + let _ = session_mgr + .update_session_state(session_id, SessionState::Idle) + .await; + if let Some(last_turn_id) = session.dialog_turn_ids.last() { + let _ = coordinator.cancel_dialog_turn(session_id, last_turn_id).await; + } + } + RemoteResponse::TaskCancelled { + session_id: session_id.clone(), + } + } + _ => RemoteResponse::Error { message: "Unknown execution command".into() }, + } + } + + async fn handle_subscription_command(&self, cmd: &RemoteCommand) -> RemoteResponse { + match cmd { + RemoteCommand::SubscribeSession { session_id } => { + let subscriber_id = format!("remote_stream_{}", session_id); + + let mut subs = self.active_subscriptions.lock().unwrap(); + if !subs.contains(&subscriber_id) { + if let Some((sub_id, mut stream_rx)) = register_stream_forwarder(session_id, self.shared_secret) { + subs.insert(sub_id.clone()); + + let stream_tx = self.stream_tx.clone(); + tokio::spawn(async move { + while let Some(payload) = stream_rx.recv().await { + let _ = stream_tx.send(payload); + } + debug!("Stream forwarder channel closed: {sub_id}"); + }); + } + } + + RemoteResponse::SessionSubscribed { + session_id: session_id.clone(), + } + } + RemoteCommand::UnsubscribeSession { session_id } => { + let subscriber_id = format!("remote_stream_{}", session_id); + + let mut subs = self.active_subscriptions.lock().unwrap(); + if subs.remove(&subscriber_id) { + unregister_stream_forwarder(&subscriber_id); + } + + RemoteResponse::SessionUnsubscribed { + session_id: session_id.clone(), + } + } + _ => RemoteResponse::Error { message: "Unknown subscription command".into() }, + } + } +} + +// ── Stream event forwarding ────────────────────────────────────── + +/// Converts `AgenticEvent`s for a specific session into encrypted relay +/// payloads and sends them through a channel. +pub struct RemoteEventForwarder { + target_session_id: String, + shared_secret: [u8; 32], + payload_tx: mpsc::UnboundedSender, +} + +impl RemoteEventForwarder { + pub fn new( + target_session_id: String, + shared_secret: [u8; 32], + payload_tx: mpsc::UnboundedSender, + ) -> Self { + Self { + target_session_id, + shared_secret, + payload_tx, + } + } + + fn try_forward(&self, event: &crate::agentic::events::AgenticEvent) { + use bitfun_events::AgenticEvent as AE; + + // Check if this is a direct event for our session, or a subagent event + // whose parent session is our target. Subagent events carry subagent_parent_info + // with the parent session id. We forward both cases so the mobile can see + // subagent tool calls and streaming text as part of the main session. + let is_direct = event.session_id() == Some(self.target_session_id.as_str()); + let parent_turn_id: Option = if !is_direct { + match event { + AE::TextChunk { subagent_parent_info, .. } + | AE::ThinkingChunk { subagent_parent_info, .. } + | AE::ToolEvent { subagent_parent_info, .. } => { + subagent_parent_info.as_ref().and_then(|p| { + if p.session_id == self.target_session_id { + Some(p.dialog_turn_id.clone()) + } else { + None + } + }) + } + _ => None, + } + } else { + None + }; + + // Only proceed if this is a direct event or a relevant subagent event + if !is_direct && parent_turn_id.is_none() { + return; + } + + let session_id = self.target_session_id.clone(); + + let (event_type, payload) = match event { + AE::TextChunk { text, turn_id, .. } => { + // For subagent text chunks, use the parent turn_id so mobile groups them correctly + let effective_turn_id = parent_turn_id.as_deref().unwrap_or(turn_id.as_str()); + ( + "text_chunk", + serde_json::json!({ "text": text, "turn_id": effective_turn_id }), + ) + } + AE::ThinkingChunk { + content, turn_id, .. + } => { + // Strip model-internal boundary markers (e.g. ) from thinking content + let clean_content = content + .replace("", "") + .replace("", "") + .replace("", ""); + let effective_turn_id = parent_turn_id.as_deref().unwrap_or(turn_id.as_str()); + ( + "thinking_chunk", + serde_json::json!({ "content": clean_content, "turn_id": effective_turn_id }), + ) + } + AE::ToolEvent { + tool_event, + turn_id, + .. + } => { + let effective_turn_id = parent_turn_id.as_deref().unwrap_or(turn_id.as_str()); + ( + "tool_event", + serde_json::json!({ + "turn_id": effective_turn_id, + "tool_event": serde_json::to_value(tool_event).unwrap_or_default(), + }), + ) + } + // The following events are only forwarded for the direct (main) session + AE::DialogTurnStarted { + turn_id, + user_input, + .. + } => ( + "stream_start", + serde_json::json!({ "turn_id": turn_id, "user_input": strip_user_input_tags(user_input) }), + ), + AE::DialogTurnCompleted { + turn_id, + total_rounds, + duration_ms, + .. + } => ( + "stream_end", + serde_json::json!({ + "turn_id": turn_id, + "total_rounds": total_rounds, + "duration_ms": duration_ms, + }), + ), + AE::DialogTurnFailed { + turn_id, error, .. + } => ( + "stream_error", + serde_json::json!({ "turn_id": turn_id, "error": error }), + ), + AE::DialogTurnCancelled { turn_id, .. } => ( + "stream_cancelled", + serde_json::json!({ "turn_id": turn_id }), + ), + AE::ModelRoundStarted { + turn_id, + round_index, + .. + } => ( + "round_started", + serde_json::json!({ "turn_id": turn_id, "round_index": round_index }), + ), + AE::ModelRoundCompleted { + turn_id, + has_tool_calls, + .. + } => ( + "round_completed", + serde_json::json!({ "turn_id": turn_id, "has_tool_calls": has_tool_calls }), + ), + AE::SessionStateChanged { new_state, .. } => ( + "session_state_changed", + serde_json::json!({ "new_state": new_state }), + ), + AE::SessionTitleGenerated { title, .. } => ( + "session_title", + serde_json::json!({ "title": title }), + ), + _ => return, + }; + + let resp = RemoteResponse::StreamEvent { + session_id, + event_type: event_type.to_string(), + payload, + }; + + match encryption::encrypt_to_base64( + &self.shared_secret, + &serde_json::to_string(&resp).unwrap_or_default(), + ) { + Ok(encrypted) => { + let _ = self.payload_tx.send(encrypted); + } + Err(e) => { + error!("Failed to encrypt stream event: {e}"); + } + } + } +} + +#[async_trait::async_trait] +impl crate::agentic::events::EventSubscriber for RemoteEventForwarder { + async fn on_event( + &self, + event: &crate::agentic::events::AgenticEvent, + ) -> crate::util::errors::BitFunResult<()> { + self.try_forward(event); + Ok(()) + } +} + +/// Register a forwarder for a session. Returns the subscriber_id (for later unsubscription) +/// and the receiving end of the encrypted payload channel. +pub fn register_stream_forwarder( + session_id: &str, + shared_secret: [u8; 32], +) -> Option<(String, mpsc::UnboundedReceiver)> { + use crate::agentic::coordination::get_global_coordinator; + + let coordinator = get_global_coordinator()?; + let (tx, rx) = mpsc::unbounded_channel(); + let subscriber_id = format!("remote_stream_{}", session_id); + + let forwarder = RemoteEventForwarder::new(session_id.to_string(), shared_secret, tx); + + coordinator.subscribe_internal(subscriber_id.clone(), forwarder); + info!("Registered remote stream forwarder: {subscriber_id}"); + Some((subscriber_id, rx)) +} + +/// Unregister a previously registered forwarder. +pub fn unregister_stream_forwarder(subscriber_id: &str) { + use crate::agentic::coordination::get_global_coordinator; + + if let Some(coordinator) = get_global_coordinator() { + coordinator.unsubscribe_internal(subscriber_id); + info!("Unregistered remote stream forwarder: {subscriber_id}"); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::service::remote_connect::encryption::KeyPair; + + #[test] + fn test_command_round_trip() { + let alice = KeyPair::generate(); + let bob = KeyPair::generate(); + let shared = alice.derive_shared_secret(&bob.public_key_bytes()); + + let (stream_tx, _stream_rx) = mpsc::unbounded_channel::(); + let bridge = RemoteServer::new(shared, stream_tx); + + let cmd_json = serde_json::json!({ + "cmd": "send_message", + "session_id": "sess-123", + "content": "Hello from mobile!", + "_request_id": "req_abc" + }); + let json = cmd_json.to_string(); + let (enc, nonce) = encryption::encrypt_to_base64(&shared, &json).unwrap(); + let (decoded, req_id) = bridge.decrypt_command(&enc, &nonce).unwrap(); + + assert_eq!(req_id.as_deref(), Some("req_abc")); + if let RemoteCommand::SendMessage { + session_id, + content, + .. + } = decoded + { + assert_eq!(session_id, "sess-123"); + assert_eq!(content, "Hello from mobile!"); + } else { + panic!("unexpected command variant"); + } + } + + #[test] + fn test_response_with_request_id() { + let alice = KeyPair::generate(); + let shared = alice.derive_shared_secret(&alice.public_key_bytes()); + let (stream_tx, _stream_rx) = mpsc::unbounded_channel::(); + let bridge = RemoteServer::new(shared, stream_tx); + + let resp = RemoteResponse::Pong; + let (enc, nonce) = bridge.encrypt_response(&resp, Some("req_xyz")).unwrap(); + + let json = encryption::decrypt_from_base64(&shared, &enc, &nonce).unwrap(); + let value: Value = serde_json::from_str(&json).unwrap(); + assert_eq!(value["resp"], "pong"); + assert_eq!(value["_request_id"], "req_xyz"); + } +} diff --git a/src/crates/core/src/service/workspace/mod.rs b/src/crates/core/src/service/workspace/mod.rs index f01c0e55..59898366 100644 --- a/src/crates/core/src/service/workspace/mod.rs +++ b/src/crates/core/src/service/workspace/mod.rs @@ -22,7 +22,7 @@ pub use manager::{ }; pub use provider::{WorkspaceCleanupResult, WorkspaceProvider, WorkspaceSystemSummary}; pub use service::{ - BatchImportResult, BatchRemoveResult, WorkspaceCreateOptions, WorkspaceExport, - WorkspaceHealthStatus, WorkspaceImportResult, WorkspaceInfoUpdates, WorkspaceQuickSummary, - WorkspaceService, + get_global_workspace_service, set_global_workspace_service, BatchImportResult, + BatchRemoveResult, WorkspaceCreateOptions, WorkspaceExport, WorkspaceHealthStatus, + WorkspaceImportResult, WorkspaceInfoUpdates, WorkspaceQuickSummary, WorkspaceService, }; diff --git a/src/crates/core/src/service/workspace/service.rs b/src/crates/core/src/service/workspace/service.rs index d64ea4a2..be5d45f5 100644 --- a/src/crates/core/src/service/workspace/service.rs +++ b/src/crates/core/src/service/workspace/service.rs @@ -759,3 +759,19 @@ struct WorkspacePersistenceData { pub recent_workspaces: Vec, pub saved_at: chrono::DateTime, } + +// ── Global workspace service singleton ────────────────────────────── + +static GLOBAL_WORKSPACE_SERVICE: std::sync::OnceLock> = + std::sync::OnceLock::new(); + +pub fn set_global_workspace_service(service: Arc) { + match GLOBAL_WORKSPACE_SERVICE.set(service) { + Ok(_) => info!("Global workspace service set"), + Err(_) => info!("Global workspace service already exists, skipping set"), + } +} + +pub fn get_global_workspace_service() -> Option> { + GLOBAL_WORKSPACE_SERVICE.get().cloned() +} diff --git a/src/crates/events/src/agentic.rs b/src/crates/events/src/agentic.rs index 5117c1e9..fda73528 100644 --- a/src/crates/events/src/agentic.rs +++ b/src/crates/events/src/agentic.rs @@ -27,6 +27,9 @@ pub enum AgenticEvent { session_id: String, session_name: String, agent_type: String, + /// Workspace path this session belongs to. None for locally-created sessions. + #[serde(skip_serializing_if = "Option::is_none")] + workspace_path: Option, }, SessionStateChanged { diff --git a/src/crates/transport/src/adapters/tauri.rs b/src/crates/transport/src/adapters/tauri.rs index 893fdfcf..d297032f 100644 --- a/src/crates/transport/src/adapters/tauri.rs +++ b/src/crates/transport/src/adapters/tauri.rs @@ -41,10 +41,25 @@ impl fmt::Debug for TauriTransportAdapter { impl TransportAdapter for TauriTransportAdapter { async fn emit_event(&self, _session_id: &str, event: AgenticEvent) -> anyhow::Result<()> { match event { - AgenticEvent::DialogTurnStarted { session_id, turn_id, subagent_parent_info, .. } => { + AgenticEvent::SessionCreated { session_id, session_name, agent_type, workspace_path } => { + self.app_handle.emit("agentic://session-created", json!({ + "sessionId": session_id, + "sessionName": session_name, + "agentType": agent_type, + "workspacePath": workspace_path, + }))?; + } + AgenticEvent::SessionDeleted { session_id } => { + self.app_handle.emit("agentic://session-deleted", json!({ + "sessionId": session_id, + }))?; + } + AgenticEvent::DialogTurnStarted { session_id, turn_id, turn_index, user_input, subagent_parent_info } => { self.app_handle.emit("agentic://dialog-turn-started", json!({ "sessionId": session_id, "turnId": turn_id, + "turnIndex": turn_index, + "userInput": user_input, "subagentParentInfo": subagent_parent_info, }))?; } diff --git a/src/crates/transport/src/adapters/websocket.rs b/src/crates/transport/src/adapters/websocket.rs index 696e9ca2..a3723dc5 100644 --- a/src/crates/transport/src/adapters/websocket.rs +++ b/src/crates/transport/src/adapters/websocket.rs @@ -51,11 +51,12 @@ impl fmt::Debug for WebSocketTransportAdapter { impl TransportAdapter for WebSocketTransportAdapter { async fn emit_event(&self, _session_id: &str, event: AgenticEvent) -> anyhow::Result<()> { let message = match event { - AgenticEvent::DialogTurnStarted { session_id, turn_id, .. } => { + AgenticEvent::DialogTurnStarted { session_id, turn_id, turn_index, .. } => { json!({ "type": "dialog-turn-started", "sessionId": session_id, "turnId": turn_id, + "turnIndex": turn_index, }) } AgenticEvent::ModelRoundStarted { session_id, turn_id, round_id, .. } => { diff --git a/src/mobile-web/index.html b/src/mobile-web/index.html new file mode 100644 index 00000000..ca443af8 --- /dev/null +++ b/src/mobile-web/index.html @@ -0,0 +1,17 @@ + + + + + + + BitFun Remote + + + +
+ + + diff --git a/src/mobile-web/package-lock.json b/src/mobile-web/package-lock.json new file mode 100644 index 00000000..18678285 --- /dev/null +++ b/src/mobile-web/package-lock.json @@ -0,0 +1,4018 @@ +{ + "name": "bitfun-mobile-web", + "version": "0.1.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "bitfun-mobile-web", + "version": "0.1.1", + "dependencies": { + "@noble/ciphers": "^2.1.1", + "@noble/curves": "^2.0.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-markdown": "^9.0.0", + "react-syntax-highlighter": "^15.5.0", + "remark-gfm": "^4.0.1", + "zustand": "^4.5.0" + }, + "devDependencies": { + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@types/react-syntax-highlighter": "^15.5.0", + "@vitejs/plugin-react": "^4.2.0", + "sass": "^1.69.0", + "typescript": "^5.3.0", + "vite": "^5.0.0", + "ws": "^8.19.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@noble/ciphers": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.1.1.tgz", + "integrity": "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz", + "integrity": "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "2.0.1" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/react-syntax-highlighter": { + "version": "15.5.13", + "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz", + "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001775", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz", + "integrity": "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz", + "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fault": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript/node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/hastscript/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/hastscript/node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hastscript/node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hastscript/node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/highlightjs-vue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz", + "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", + "license": "CC0-1.0" + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lowlight": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "license": "MIT", + "dependencies": { + "fault": "^1.0.0", + "highlight.js": "~10.7.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-markdown": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.1.0.tgz", + "integrity": "sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-syntax-highlighter": { + "version": "15.6.6", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz", + "integrity": "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.3.1", + "highlight.js": "^10.4.1", + "highlightjs-vue": "^1.0.0", + "lowlight": "^1.17.0", + "prismjs": "^1.30.0", + "refractor": "^3.6.0" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/refractor": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", + "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "license": "MIT", + "dependencies": { + "hastscript": "^6.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.27.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "license": "MIT", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/prismjs": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", + "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/sass": { + "version": "1.97.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", + "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/src/mobile-web/package.json b/src/mobile-web/package.json new file mode 100644 index 00000000..cc66497a --- /dev/null +++ b/src/mobile-web/package.json @@ -0,0 +1,31 @@ +{ + "name": "bitfun-mobile-web", + "version": "0.1.1", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@noble/ciphers": "^2.1.1", + "@noble/curves": "^2.0.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-markdown": "^9.0.0", + "react-syntax-highlighter": "^15.5.0", + "remark-gfm": "^4.0.1", + "zustand": "^4.5.0" + }, + "devDependencies": { + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@types/react-syntax-highlighter": "^15.5.0", + "@vitejs/plugin-react": "^4.2.0", + "sass": "^1.69.0", + "typescript": "^5.3.0", + "vite": "^5.0.0", + "ws": "^8.19.0" + } +} diff --git a/src/mobile-web/src/App.tsx b/src/mobile-web/src/App.tsx new file mode 100644 index 00000000..b80324a5 --- /dev/null +++ b/src/mobile-web/src/App.tsx @@ -0,0 +1,93 @@ +import React, { useState, useCallback, useRef } from 'react'; +import PairingPage from './pages/PairingPage'; +import WorkspacePage from './pages/WorkspacePage'; +import SessionListPage from './pages/SessionListPage'; +import ChatPage from './pages/ChatPage'; +import { RelayConnection } from './services/RelayConnection'; +import { RemoteSessionManager } from './services/RemoteSessionManager'; +import { useMobileStore } from './services/store'; +import './styles/mobile.scss'; + +type Page = 'pairing' | 'workspace' | 'sessions' | 'chat'; + +const App: React.FC = () => { + const [page, setPage] = useState('pairing'); + const [activeSessionId, setActiveSessionId] = useState(null); + const [activeSessionName, setActiveSessionName] = useState('Session'); + const relayRef = useRef(null); + const sessionMgrRef = useRef(null); + + const handlePaired = useCallback((relay: RelayConnection, sessionMgr: RemoteSessionManager) => { + relayRef.current = relay; + sessionMgrRef.current = sessionMgr; + + relay.setMessageHandler((json: string) => { + sessionMgr.handleMessage(json); + }); + + // Listen for the initial sync that the desktop pushes right after pairing. + // This pre-populates workspace + sessions so the list page can render instantly. + sessionMgr.onInitialSync((data) => { + const store = useMobileStore.getState(); + if (data.has_workspace) { + store.setCurrentWorkspace({ + has_workspace: true, + path: data.path, + project_name: data.project_name, + git_branch: data.git_branch, + }); + } + store.setSessions(data.sessions); + }); + + setPage('sessions'); + }, []); + + const handleOpenWorkspace = useCallback(() => { + setPage('workspace'); + }, []); + + const handleWorkspaceReady = useCallback(() => { + setPage('sessions'); + }, []); + + const handleSelectSession = useCallback((sessionId: string, sessionName?: string) => { + setActiveSessionId(sessionId); + setActiveSessionName(sessionName || 'Session'); + setPage('chat'); + }, []); + + const handleBackToSessions = useCallback(() => { + setActiveSessionId(null); + setPage('sessions'); + }, []); + + return ( +
+ {page === 'pairing' && } + {page === 'workspace' && sessionMgrRef.current && ( + + )} + {page === 'sessions' && sessionMgrRef.current && ( + + )} + {page === 'chat' && sessionMgrRef.current && activeSessionId && ( + + )} +
+ ); +}; + +export default App; diff --git a/src/mobile-web/src/main.tsx b/src/mobile-web/src/main.tsx new file mode 100644 index 00000000..c018515c --- /dev/null +++ b/src/mobile-web/src/main.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/src/mobile-web/src/pages/ChatPage.tsx b/src/mobile-web/src/pages/ChatPage.tsx new file mode 100644 index 00000000..cbb79d54 --- /dev/null +++ b/src/mobile-web/src/pages/ChatPage.tsx @@ -0,0 +1,568 @@ +import React, { useEffect, useRef, useState, useCallback } from 'react'; +import ReactMarkdown from 'react-markdown'; +import remarkGfm from 'remark-gfm'; +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; +import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism'; +import { RemoteSessionManager } from '../services/RemoteSessionManager'; +import { useMobileStore } from '../services/store'; + +interface ChatPageProps { + sessionMgr: RemoteSessionManager; + sessionId: string; + sessionName?: string; + onBack: () => void; +} + +interface ToolCallEntry { + id: string; + name: string; + status: 'running' | 'done' | 'error'; + duration?: number; + startMs: number; +} + +interface StreamingAccum { + thinking: string; + text: string; + toolCalls: ToolCallEntry[]; +} + +/** Renders markdown content with syntax highlighting */ +const MarkdownContent: React.FC<{ content: string }> = ({ content }) => ( + + {codeStr} + + ) : ( + + {children} + + ); + }, + }} + > + {content} + +); + +/** Desktop-style collapsible thinking block */ +const ThinkingBlock: React.FC<{ thinking: string; streaming?: boolean }> = ({ thinking, streaming }) => { + const [open, setOpen] = useState(false); + if (!thinking && !streaming) return null; + const charCount = thinking.length; + return ( +
+ + {open && thinking && ( +
+ +
+ )} +
+ ); +}; + +/** Desktop-style individual tool card */ +const ToolCard: React.FC<{ tool: ToolCallEntry; now: number }> = ({ tool, now }) => { + const [_expanded, setExpanded] = useState(false); + + const durationLabel = tool.status === 'done' && tool.duration != null + ? `${(tool.duration / 1000).toFixed(1)}s` + : tool.status === 'running' + ? `${((now - tool.startMs) / 1000).toFixed(1)}s` + : ''; + + const toolTypeMap: Record = { + 'explore': 'Explore', + 'read_file': 'Read', + 'write_file': 'Write', + 'list_directory': 'LS', + 'bash': 'Shell', + 'glob': 'Glob', + 'grep': 'Grep', + 'create_file': 'Write', + 'delete_file': 'Delete', + 'execute_subagent': 'Task', + 'search': 'Search', + }; + const toolKey = tool.name.toLowerCase().replace(/[\s-]/g, '_'); + const typeLabel = toolTypeMap[toolKey] || toolTypeMap[tool.name] || 'Tool'; + + return ( +
+
setExpanded(e => !e)}> + + {tool.status === 'running' ? ( + + ) : tool.status === 'done' ? ( + + + + ) : ( + + + + )} + + {tool.name} + {typeLabel} + {durationLabel && ( + {durationLabel} + )} +
+
+ ); +}; + +/** Tool list */ +const ToolList: React.FC<{ toolCalls: ToolCallEntry[]; now: number }> = ({ toolCalls, now }) => { + if (!toolCalls || toolCalls.length === 0) return null; + return ( +
+ {toolCalls.map((tc) => ( + + ))} +
+ ); +}; + +/** Typing indicator dots */ +const TypingDots: React.FC = () => ( + + + +); + +type AgentMode = 'agentic' | 'Plan' | 'debug'; + +const MODE_OPTIONS: { id: AgentMode; label: string }[] = [ + { id: 'agentic', label: 'Agentic' }, + { id: 'Plan', label: 'Plan' }, + { id: 'debug', label: 'Debug' }, +]; + +const ChatPage: React.FC = ({ sessionMgr, sessionId, sessionName, onBack }) => { + const { + getMessages, + setMessages, + appendMessage, + updateLastMessageFull, + isStreaming, + setIsStreaming, + setError, + currentWorkspace, + } = useMobileStore(); + + const messages = getMessages(sessionId); + const [input, setInput] = useState(''); + const [agentMode, setAgentMode] = useState('agentic'); + const [pendingImages, setPendingImages] = useState<{ name: string; dataUrl: string }[]>([]); + const inputRef = useRef(null); + const fileInputRef = useRef(null); + const streamRef = useRef({ thinking: '', text: '', toolCalls: [] }); + + const [isLoadingMore, setIsLoadingMore] = useState(false); + const [hasMore, setHasMore] = useState(true); + const messagesEndRef = useRef(null); + const messagesContainerRef = useRef(null); + + // Live timer for running tools + const [now, setNow] = useState(() => Date.now()); + useEffect(() => { + if (!isStreaming) return; + const timer = setInterval(() => setNow(Date.now()), 500); + return () => clearInterval(timer); + }, [isStreaming]); + + const loadMessages = useCallback(async (beforeId?: string) => { + if (isLoadingMore || (!hasMore && beforeId)) return; + try { + setIsLoadingMore(true); + const resp = await sessionMgr.getSessionMessages(sessionId, 50, beforeId); + if (beforeId) { + const currentMsgs = getMessages(sessionId); + setMessages(sessionId, [...resp.messages, ...currentMsgs]); + } else { + setMessages(sessionId, resp.messages); + } + setHasMore(resp.has_more); + } catch (e: any) { + setError(e.message); + } finally { + setIsLoadingMore(false); + } + }, [sessionMgr, sessionId, setMessages, setError, getMessages, isLoadingMore, hasMore]); + + const handleScroll = useCallback(() => { + const container = messagesContainerRef.current; + if (!container) return; + if (container.scrollTop < 100 && hasMore && !isLoadingMore) { + const msgs = getMessages(sessionId); + if (msgs.length > 0) loadMessages(msgs[0].id); + } + }, [hasMore, isLoadingMore, getMessages, sessionId, loadMessages]); + + useEffect(() => { + sessionMgr.subscribeSession(sessionId).catch(console.error); + loadMessages(); + + const unsub = sessionMgr.onStreamEvent((event) => { + if (event.session_id !== sessionId) return; + const eventType = event.event_type; + + if (eventType === 'stream_start') { + streamRef.current = { thinking: '', text: '', toolCalls: [] }; + setIsStreaming(true); + appendMessage(sessionId, { + id: `stream-${Date.now()}`, + role: 'assistant', + content: '', + timestamp: new Date().toISOString(), + metadata: { thinking: '', toolCalls: [] }, + }); + + const userInput = event.payload?.user_input; + if (userInput && userInput.trim()) { + const currentMsgs = getMessages(sessionId); + const lastUserMsg = [...currentMsgs].reverse().find(m => m.role === 'user'); + if (!lastUserMsg || lastUserMsg.content !== userInput.trim()) { + const msgs = getMessages(sessionId); + const newUserMsg = { + id: `user-remote-${Date.now()}`, + role: 'user', + content: userInput.trim(), + timestamp: new Date().toISOString(), + }; + setMessages(sessionId, [ + ...msgs.slice(0, -1), + newUserMsg, + msgs[msgs.length - 1], + ]); + } + } + } else if (eventType === 'text_chunk') { + streamRef.current.text += event.payload?.text || ''; + updateLastMessageFull(sessionId, streamRef.current.text, { + thinking: streamRef.current.thinking, + toolCalls: streamRef.current.toolCalls, + }); + } else if (eventType === 'thinking_chunk') { + streamRef.current.thinking += event.payload?.content || ''; + updateLastMessageFull(sessionId, streamRef.current.text, { + thinking: streamRef.current.thinking, + toolCalls: streamRef.current.toolCalls, + }); + } else if (eventType === 'tool_event') { + const toolEvt = event.payload?.tool_event; + if (toolEvt?.event_type === 'Started') { + streamRef.current.toolCalls = [ + ...streamRef.current.toolCalls, + { + id: toolEvt.tool_id || `${toolEvt.tool_name}-${Date.now()}`, + name: toolEvt.tool_name, + status: 'running', + startMs: Date.now(), + }, + ]; + updateLastMessageFull(sessionId, streamRef.current.text, { + thinking: streamRef.current.thinking, + toolCalls: streamRef.current.toolCalls, + }); + } else if (toolEvt?.event_type === 'Completed' || toolEvt?.event_type === 'Succeeded') { + streamRef.current.toolCalls = streamRef.current.toolCalls.map(tc => + (tc.id === toolEvt.tool_id || tc.name === toolEvt.tool_name) && tc.status === 'running' + ? { ...tc, status: 'done' as const, duration: toolEvt.duration_ms } + : tc + ); + updateLastMessageFull(sessionId, streamRef.current.text, { + thinking: streamRef.current.thinking, + toolCalls: streamRef.current.toolCalls, + }); + } else if (toolEvt?.event_type === 'Failed') { + streamRef.current.toolCalls = streamRef.current.toolCalls.map(tc => + (tc.id === toolEvt.tool_id || tc.name === toolEvt.tool_name) && tc.status === 'running' + ? { ...tc, status: 'error' as const } + : tc + ); + updateLastMessageFull(sessionId, streamRef.current.text, { + thinking: streamRef.current.thinking, + toolCalls: streamRef.current.toolCalls, + }); + } + } else if (eventType === 'stream_end') { + setIsStreaming(false); + streamRef.current = { thinking: '', text: '', toolCalls: [] }; + // Reload to get persisted history + loadMessages(); + } else if (eventType === 'stream_error') { + setIsStreaming(false); + setError(event.payload?.error || 'Stream error'); + streamRef.current = { thinking: '', text: '', toolCalls: [] }; + } else if (eventType === 'stream_cancelled') { + setIsStreaming(false); + streamRef.current = { thinking: '', text: '', toolCalls: [] }; + } + }); + + return () => { + unsub(); + sessionMgr.unsubscribeSession(sessionId).catch(console.error); + }; + }, [sessionId, sessionMgr, setIsStreaming, appendMessage, updateLastMessageFull, setError, setMessages, getMessages]); + + useEffect(() => { + if (!isLoadingMore) { + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + } + }, [messages, isLoadingMore]); + + const handleSend = useCallback(async () => { + const text = input.trim(); + const imgs = pendingImages; + if ((!text && imgs.length === 0) || isStreaming) return; + setInput(''); + setPendingImages([]); + + const displayParts = [text]; + if (imgs.length > 0) { + displayParts.push(`[${imgs.length} image(s) attached]`); + } + appendMessage(sessionId, { + id: `user-${Date.now()}`, + role: 'user', + content: displayParts.filter(Boolean).join('\n'), + timestamp: new Date().toISOString(), + }); + try { + const imagePayload = imgs.length > 0 + ? imgs.map(i => ({ name: i.name, data_url: i.dataUrl })) + : undefined; + await sessionMgr.sendMessage(sessionId, text || '(see attached images)', agentMode, imagePayload); + } catch (e: any) { + setError(e.message); + } + }, [input, pendingImages, isStreaming, sessionId, sessionMgr, appendMessage, setError, agentMode]); + + const handleImageSelect = useCallback(() => { + fileInputRef.current?.click(); + }, []); + + const handleFileChange = useCallback((e: React.ChangeEvent) => { + const files = e.target.files; + if (!files) return; + const maxImages = 5; + const remaining = maxImages - pendingImages.length; + const toProcess = Array.from(files).slice(0, remaining); + + toProcess.forEach((file) => { + const reader = new FileReader(); + reader.onload = () => { + const dataUrl = reader.result as string; + setPendingImages((prev) => { + if (prev.length >= maxImages) return prev; + return [...prev, { name: file.name, dataUrl }]; + }); + }; + reader.readAsDataURL(file); + }); + e.target.value = ''; + }, [pendingImages.length]); + + const removeImage = useCallback((idx: number) => { + setPendingImages((prev) => prev.filter((_, i) => i !== idx)); + }, []); + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + handleSend(); + } + }; + + const handleCancel = async () => { + try { + await sessionMgr.cancelTask(sessionId); + } catch { + // best effort + } + }; + + const workspaceName = currentWorkspace?.project_name || currentWorkspace?.path?.split('/').pop() || ''; + const gitBranch = currentWorkspace?.git_branch; + const displayName = sessionName || 'Session'; + + return ( +
+ {/* Header */} +
+
+ +
+ {displayName} +
+ {isStreaming && ( + + )} +
+ {workspaceName && ( +
+ + + + + + {workspaceName} + {gitBranch && ( + + + {gitBranch} + + )} +
+ )} +
+ + {/* Messages */} +
+ {isLoadingMore && ( +
Loading older messages…
+ )} + + {messages.map((m) => { + if (m.role === 'system' || m.role === 'tool') return null; + + const thinking: string = m.metadata?.thinking || ''; + const toolCalls: ToolCallEntry[] = m.metadata?.toolCalls || []; + const isLastMsg = messages.indexOf(m) === messages.length - 1; + const streamingThis = isStreaming && isLastMsg && m.role === 'assistant'; + + if (m.role === 'user') { + return ( +
+
+ {m.content} +
+
+ ); + } + + // Assistant message + return ( +
+ {/* Thinking block */} + {(thinking || (streamingThis && !m.content)) && ( + + )} + + {/* Tool cards */} + + + {/* Main content */} + {m.content ? ( +
+ +
+ ) : streamingThis && !thinking && toolCalls.length === 0 ? ( +
+ +
+ ) : null} +
+ ); + })} + +
+
+ + {/* Input bar */} +
+
+
+ {MODE_OPTIONS.map((opt) => ( + + ))} +
+
+ + {pendingImages.length > 0 && ( +
+ {pendingImages.map((img, idx) => ( +
+ {img.name} + +
+ ))} +
+ )} + +
+ + +