diff --git a/frontend/input.css b/frontend/input.css index 7d4d583..03e799a 100644 --- a/frontend/input.css +++ b/frontend/input.css @@ -19,7 +19,7 @@ --secondary: theme(colors.zinc.200); --secondary-foreground: theme(colors.zinc.900); - --destructive: theme(colors.red.600); + --destructive: theme(colors.red.500); --destructive-foreground: theme(colors.white); --accent: theme(colors.zinc.100); --accent-foreground: theme(colors.zinc.900); @@ -69,10 +69,10 @@ @apply bg-primary text-primary-foreground hover:bg-primary/90; } .btn-secondary { - @apply bg-secondary text-secondary-foreground hover:bg-secondary/80; + @apply bg-secondary text-secondary-foreground border border-zinc-500/30 hover:bg-secondary/80; } .btn-destructive { - @apply bg-destructive text-destructive-foreground hover:bg-destructive/90; + @apply bg-destructive text-destructive-foreground border border-zinc-500/30 hover:bg-destructive/90; } .btn-outline { @apply border border-input bg-background hover:bg-accent hover:text-accent-foreground; @@ -83,7 +83,9 @@ .btn-link { @apply text-primary underline-offset-4 hover:underline; } - + .btn-group-item.active { + @apply bg-primary text-primary-foreground; + } /* 按钮尺寸变体 */ .btn-lg { @apply h-11 rounded-md px-8; } .btn-md { @apply h-10 px-4 py-2; } diff --git a/frontend/js/components/ui.js b/frontend/js/components/ui.js index b87730c..9e55a9b 100644 --- a/frontend/js/components/ui.js +++ b/frontend/js/components/ui.js @@ -326,6 +326,41 @@ class UIPatterns { }); } } + /** + * Sets a button to a loading state by disabling it and showing a spinner. + * It stores the button's original content to be restored later. + * @param {HTMLButtonElement} button - The button element to modify. + */ + setButtonLoading(button) { + if (!button) return; + // Store original content if it hasn't been stored already + if (!button.dataset.originalContent) { + button.dataset.originalContent = button.innerHTML; + } + button.disabled = true; + button.innerHTML = ''; + } + /** + * Restores a button from its loading state to its original content and enables it. + * @param {HTMLButtonElement} button - The button element to restore. + */ + clearButtonLoading(button) { + if (!button) return; + if (button.dataset.originalContent) { + button.innerHTML = button.dataset.originalContent; + // Clean up the data attribute + delete button.dataset.originalContent; + } + button.disabled = false; + } + /** + * Returns the HTML for a streaming text cursor animation. + * This is used as a placeholder in the chat UI while waiting for an assistant's response. + * @returns {string} The HTML string for the loader. + */ + renderStreamingLoader() { + return ''; + } } /** diff --git a/frontend/js/main.js b/frontend/js/main.js index 804761f..d159874 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -16,6 +16,7 @@ const pageModules = { 'dashboard': () => import('./pages/dashboard.js'), 'keys': () => import('./pages/keys/index.js'), 'logs': () => import('./pages/logs/index.js'), + 'chat': () => import('./pages/chat/index.js'), // 'settings': () => import('./pages/settings.js'), // 未来启用 settings 页面 // 未来新增的页面,只需在这里添加一行映射,esbuild会自动处理 }; diff --git a/frontend/js/pages/chat/SessionManager.js b/frontend/js/pages/chat/SessionManager.js new file mode 100644 index 0000000..ce5494b --- /dev/null +++ b/frontend/js/pages/chat/SessionManager.js @@ -0,0 +1,178 @@ +// Filename: frontend/js/pages/chat/SessionManager.js + +import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'; + +const LOCAL_STORAGE_KEY = 'gemini_chat_state'; + +/** + * Manages the state and persistence of chat sessions. + * This class handles loading from/saving to localStorage, + * and all operations like creating, switching, and deleting sessions. + */ +export class SessionManager { + constructor() { + this.state = null; + } + + /** + * Initializes the manager by loading state from localStorage or creating a default state. + */ + init() { + this._loadState(); + } + + // --- Public API for state access --- + + getSessions() { + return this.state.sessions; + } + + getCurrentSessionId() { + return this.state.currentSessionId; + } + + getCurrentSession() { + return this.state.sessions.find(s => s.id === this.state.currentSessionId); + } + + // --- Public API for state mutation --- + + /** + * Creates a new, empty session and sets it as the current one. + */ + createSession() { + const newSessionId = nanoid(); + const newSession = { + id: newSessionId, + name: '新会话', + systemPrompt: '', + messages: [], + modelConfig: { model: 'gemini-2.0-flash-lite' }, + params: { temperature: 0.7 } + }; + this.state.sessions.unshift(newSession); + this.state.currentSessionId = newSessionId; + this._saveState(); + } + + /** + * Switches the current session to the one with the given ID. + * @param {string} sessionId The ID of the session to switch to. + */ + switchSession(sessionId) { + if (this.state.currentSessionId === sessionId) return; + this.state.currentSessionId = sessionId; + this._saveState(); + } + + /** + * Deletes a session by its ID. + * @param {string} sessionId The ID of the session to delete. + */ + deleteSession(sessionId) { + this.state.sessions = this.state.sessions.filter(s => s.id !== sessionId); + + if (this.state.currentSessionId === sessionId) { + this.state.currentSessionId = this.state.sessions[0]?.id || null; + if (!this.state.currentSessionId) { + this._createInitialState(); // Create a new one if all are deleted + } + } + + this._saveState(); + } + + /** + * [NEW] Clears all messages from the currently active session. + */ + clearCurrentSession() { + const currentSession = this.getCurrentSession(); + if (currentSession) { + currentSession.messages = []; + this._saveState(); + } + } + + /** + * Adds a message to the current session and updates the session name if it's the first message. + * @param {object} message The message object to add. + * @returns {object} The session that was updated. + */ + addMessage(message) { + const currentSession = this.getCurrentSession(); + if (currentSession) { + if (currentSession.messages.length === 0 && message.role === 'user') { + currentSession.name = message.content.substring(0, 30); + } + currentSession.messages.push(message); + this._saveState(); + return currentSession; + } + return null; + } + + deleteMessage(messageId) { + const currentSession = this.getCurrentSession(); + if (currentSession) { + const messageIndex = currentSession.messages.findIndex(m => m.id === messageId); + if (messageIndex > -1) { + currentSession.messages.splice(messageIndex, 1); + this._saveState(); + console.log(`Message ${messageId} deleted.`); + } + } + } + + truncateMessagesAfter(messageId) { + const currentSession = this.getCurrentSession(); + if (currentSession) { + const messageIndex = currentSession.messages.findIndex(m => m.id === messageId); + // Ensure the message exists and it's not already the last one + if (messageIndex > -1 && messageIndex < currentSession.messages.length - 1) { + currentSession.messages.splice(messageIndex + 1); + this._saveState(); + console.log(`Truncated messages after ${messageId}.`); + } + } + } + // --- Private persistence methods --- + + _saveState() { + try { + localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(this.state)); + } catch (error) { + console.error("Failed to save session state:", error); + } + } + + _loadState() { + try { + const stateString = localStorage.getItem(LOCAL_STORAGE_KEY); + if (stateString) { + this.state = JSON.parse(stateString); + } else { + this._createInitialState(); + } + } catch (error) { + console.error("Failed to load session state, creating initial state:", error); + this._createInitialState(); + } + } + + _createInitialState() { + const initialSessionId = nanoid(); + this.state = { + sessions: [{ + id: initialSessionId, + name: '新会话', + systemPrompt: '', + messages: [], + modelConfig: { model: 'gemini-2.0-flash-lite' }, + params: { temperature: 0.7 } + }], + currentSessionId: initialSessionId, + settings: {} + }; + this._saveState(); + } +} diff --git a/frontend/js/pages/chat/chatSettings.js b/frontend/js/pages/chat/chatSettings.js new file mode 100644 index 0000000..cc23e33 --- /dev/null +++ b/frontend/js/pages/chat/chatSettings.js @@ -0,0 +1,113 @@ +// Filename: frontend/js/pages/chat/chatSettings.js + +export class ChatSettings { + constructor(elements) { + // [MODIFIED] Store the root elements passed from ChatPage + this.elements = {}; + this.elements.root = elements; // Keep a reference to all elements + + // [MODIFIED] Query for specific elements this class controls, relative to their panels + this._initScopedDOMElements(); + + // Initialize panel states to ensure they are collapsed on load + this.elements.quickSettingsPanel.style.gridTemplateRows = '0fr'; + this.elements.sessionParamsPanel.style.gridTemplateRows = '0fr'; + } + + // [NEW] A dedicated method to find elements within their specific panels + _initScopedDOMElements() { + this.elements.quickSettingsPanel = this.elements.root.quickSettingsPanel; + this.elements.sessionParamsPanel = this.elements.root.sessionParamsPanel; + this.elements.toggleQuickSettingsBtn = this.elements.root.toggleQuickSettingsBtn; + this.elements.toggleSessionParamsBtn = this.elements.root.toggleSessionParamsBtn; + + // Query elements within the quick settings panel + this.elements.btnGroups = this.elements.quickSettingsPanel.querySelectorAll('.btn-group'); + this.elements.directRoutingOptions = this.elements.quickSettingsPanel.querySelector('#direct-routing-options'); + + // Query elements within the session params panel + this.elements.temperatureSlider = this.elements.sessionParamsPanel.querySelector('#temperature-slider'); + this.elements.temperatureValue = this.elements.sessionParamsPanel.querySelector('#temperature-value'); + this.elements.contextSlider = this.elements.sessionParamsPanel.querySelector('#context-slider'); + this.elements.contextValue = this.elements.sessionParamsPanel.querySelector('#context-value'); + } + + init() { + if (!this.elements.toggleQuickSettingsBtn) { + console.warn("ChatSettings: Aborting initialization, required elements not found."); + return; + } + this._initPanelToggleListeners(); + this._initButtonGroupListeners(); + this._initSliderListeners(); + } + + _initPanelToggleListeners() { + this.elements.toggleQuickSettingsBtn.addEventListener('click', () => + this._togglePanel(this.elements.quickSettingsPanel, this.elements.toggleQuickSettingsBtn) + ); + this.elements.toggleSessionParamsBtn.addEventListener('click', () => + this._togglePanel(this.elements.sessionParamsPanel, this.elements.toggleSessionParamsBtn) + ); + } + + _initButtonGroupListeners() { + // [FIXED] This logic is now guaranteed to work with the correctly scoped elements. + this.elements.btnGroups.forEach(group => { + group.addEventListener('click', (e) => { + const button = e.target.closest('.btn-group-item'); + if (!button) return; + + group.querySelectorAll('.btn-group-item').forEach(btn => btn.removeAttribute('data-active')); + button.setAttribute('data-active', 'true'); + + if (button.dataset.group === 'routing-mode') { + this._handleRoutingModeChange(button.dataset.value); + } + }); + }); + } + + _initSliderListeners() { + // [FIXED] Add null checks for robustness, now that elements are queried scoped. + if (this.elements.temperatureSlider) { + this.elements.temperatureSlider.addEventListener('input', () => { + this.elements.temperatureValue.textContent = parseFloat(this.elements.temperatureSlider.value).toFixed(1); + }); + } + if (this.elements.contextSlider) { + this.elements.contextSlider.addEventListener('input', () => { + this.elements.contextValue.textContent = `${this.elements.contextSlider.value}k`; + }); + } + } + + _handleRoutingModeChange(selectedValue) { + // [FIXED] This logic now correctly targets the scoped element. + if (this.elements.directRoutingOptions) { + if (selectedValue === 'direct') { + this.elements.directRoutingOptions.classList.remove('hidden'); + } else { + this.elements.directRoutingOptions.classList.add('hidden'); + } + } + } + + _togglePanel(panel, button) { + const isExpanded = panel.hasAttribute('data-expanded'); + + this.elements.quickSettingsPanel.removeAttribute('data-expanded'); + this.elements.sessionParamsPanel.removeAttribute('data-expanded'); + this.elements.toggleQuickSettingsBtn.removeAttribute('data-active'); + this.elements.toggleSessionParamsBtn.removeAttribute('data-active'); + + this.elements.quickSettingsPanel.style.gridTemplateRows = '0fr'; + this.elements.sessionParamsPanel.style.gridTemplateRows = '0fr'; + + if (!isExpanded) { + panel.setAttribute('data-expanded', 'true'); + button.setAttribute('data-active', 'true'); + panel.style.gridTemplateRows = '1fr'; + } + } +} diff --git a/frontend/js/pages/chat/index.js b/frontend/js/pages/chat/index.js new file mode 100644 index 0000000..2c680e2 --- /dev/null +++ b/frontend/js/pages/chat/index.js @@ -0,0 +1,545 @@ +// Filename: frontend/js/pages/chat/index.js + +import { nanoid } from '../../vendor/nanoid.js'; +import { uiPatterns } from '../../components/ui.js'; +import { apiFetch } from '../../services/api.js'; +import { marked } from '../../vendor/marked.min.js'; +import { SessionManager } from './SessionManager.js'; +import { ChatSettings } from './chatSettings.js'; +import CustomSelectV2 from '../../components/customSelectV2.js'; + +marked.use({ breaks: true, gfm: true }); + +function getCookie(name) { + let cookieValue = null; + if (document.cookie && document.cookie !== '') { + const cookies = document.cookie.split(';'); + for (let i = 0; i < cookies.length; i++) { + const cookie = cookies[i].trim(); + if (cookie.substring(0, name.length + 1) === (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} + +class ChatPage { + constructor() { + this.sessionManager = new SessionManager(); + this.isStreaming = false; + this.elements = {}; + this.initialized = false; + this.searchTerm = ''; + this.settingsManager = null; + } + + init() { + if (!document.querySelector('[data-page-id="chat"]')) { return; } + + this.sessionManager.init(); + + this.initialized = true; + this._initDOMElements(); + this._initComponents(); + this._initEventListeners(); + this._render(); + console.log("ChatPage initialized. Session management is delegated.", this.sessionManager.state); + } + + _initDOMElements() { + this.elements.chatScrollContainer = document.getElementById('chat-scroll-container'); + this.elements.chatMessagesContainer = document.getElementById('chat-messages-container'); + this.elements.messageForm = document.getElementById('message-form'); + this.elements.messageInput = document.getElementById('message-input'); + this.elements.sendBtn = document.getElementById('send-btn'); + this.elements.newSessionBtn = document.getElementById('new-session-btn'); + this.elements.sessionListContainer = document.getElementById('session-list-container'); + this.elements.chatHeaderTitle = document.querySelector('.chat-header-title'); + this.elements.clearSessionBtn = document.getElementById('clear-session-btn'); + this.elements.sessionSearchInput = document.getElementById('session-search-input'); + this.elements.toggleQuickSettingsBtn = document.getElementById('toggle-quick-settings'); + this.elements.toggleSessionParamsBtn = document.getElementById('toggle-session-params'); + this.elements.quickSettingsPanel = document.getElementById('quick-settings-panel'); + this.elements.sessionParamsPanel = document.getElementById('session-params-panel'); + this.elements.directRoutingOptions = document.getElementById('direct-routing-options'); + this.elements.btnGroups = document.querySelectorAll('.btn-group'); + this.elements.temperatureSlider = document.getElementById('temperature-slider'); + this.elements.temperatureValue = document.getElementById('temperature-value'); + this.elements.contextSlider = document.getElementById('context-slider'); + this.elements.contextValue = document.getElementById('context-value'); + this.elements.groupSelectContainer = document.getElementById('group-select-container'); + } + // [NEW] A dedicated method for initializing complex UI components + _initComponents() { + if (this.elements.groupSelectContainer) { + new CustomSelectV2(this.elements.groupSelectContainer); + } + // In the future, we will initialize the model select component here as well + } + + _initEventListeners() { + // --- Initialize Settings Manager First --- + this.settingsManager = new ChatSettings(this.elements); + this.settingsManager.init(); + // --- Core Chat Event Listeners --- + this.elements.messageForm.addEventListener('submit', (e) => { e.preventDefault(); this._handleSendMessage(); }); + this.elements.messageInput.addEventListener('keydown', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); this._handleSendMessage(); } }); + this.elements.messageInput.addEventListener('input', () => this._autoResizeTextarea()); + this.elements.newSessionBtn.addEventListener('click', () => { + this.sessionManager.createSession(); + this._render(); + this.elements.messageInput.focus(); + }); + this.elements.sessionListContainer.addEventListener('click', (e) => { + const sessionItem = e.target.closest('[data-session-id]'); + const deleteBtn = e.target.closest('.delete-session-btn'); + + if (deleteBtn) { + e.preventDefault(); + const sessionId = deleteBtn.closest('[data-session-id]').dataset.sessionId; + this._handleDeleteSession(sessionId); + } else if (sessionItem) { + e.preventDefault(); + const sessionId = sessionItem.dataset.sessionId; + this.sessionManager.switchSession(sessionId); + this._render(); + this.elements.messageInput.focus(); + } + }); + this.elements.clearSessionBtn.addEventListener('click', () => this._handleClearSession()); + this.elements.sessionSearchInput.addEventListener('input', (e) => { + this.searchTerm = e.target.value.trim(); + this._renderSessionList(); + }); + this.elements.chatMessagesContainer.addEventListener('click', (e) => { + const messageElement = e.target.closest('[data-message-id]'); + if (!messageElement) return; + const messageId = messageElement.dataset.messageId; + const copyBtn = e.target.closest('.action-copy'); + const deleteBtn = e.target.closest('.action-delete'); + const retryBtn = e.target.closest('.action-retry'); + if (copyBtn) { + this._handleCopyMessage(messageId); + } else if (deleteBtn) { + this._handleDeleteMessage(messageId, e.target); + } else if (retryBtn) { + this._handleRetryMessage(messageId); + } + }); + } + + _handleCopyMessage(messageId) { + const currentSession = this.sessionManager.getCurrentSession(); + if (!currentSession) return; + const message = currentSession.messages.find(m => m.id === messageId); + if (!message || !message.content) { + console.error("Message content not found for copying."); + return; + } + // Handle cases where content might be HTML (like error messages) + // by stripping tags to get plain text. + let textToCopy = message.content; + if (textToCopy.includes('<') && textToCopy.includes('>')) { + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = textToCopy; + textToCopy = tempDiv.textContent || tempDiv.innerText || ''; + } + navigator.clipboard.writeText(textToCopy) + .then(() => { + Swal.fire({ + toast: true, + position: 'top-end', + icon: 'success', + title: '已复制', + showConfirmButton: false, + timer: 1500, + customClass: { + popup: `${document.documentElement.classList.contains('dark') ? 'swal2-dark' : ''}` + } + }); + }) + .catch(err => { + console.error('Failed to copy text: ', err); + Swal.fire({ + toast: true, + position: 'top-end', + icon: 'error', + title: '复制失败', + showConfirmButton: false, + timer: 1500, + customClass: { + popup: `${document.documentElement.classList.contains('dark') ? 'swal2-dark' : ''}` + } + }); + }); + } + + _handleDeleteMessage(messageId, targetElement) { + // Remove any existing popover first to prevent duplicates + const existingPopover = document.getElementById('delete-confirmation-popover'); + if (existingPopover) { + existingPopover.remove(); + } + // Create the popover element with your specified dimensions. + const popover = document.createElement('div'); + popover.id = 'delete-confirmation-popover'; + // [MODIFIED] - Using your w-36, and adding flexbox classes for centering. + popover.className = 'absolute z-50 p-3 w-45 border border-border rounded-md shadow-lg bg-background text-popover-foreground flex flex-col items-center'; + + // [MODIFIED] - Added an icon and classes for horizontal centering. + popover.innerHTML = ` +
+ +

确认删除此消息吗?

+
+
+ + +
+ `; + document.body.appendChild(popover); + // Position the popover above the clicked icon + const iconRect = targetElement.closest('button').getBoundingClientRect(); + const popoverRect = popover.getBoundingClientRect(); + popover.style.top = `${window.scrollY + iconRect.top - popoverRect.height - 8}px`; + popover.style.left = `${window.scrollX + iconRect.left + (iconRect.width / 2) - (popoverRect.width / 2)}px`; + // Event listener to close the popover if clicked outside + const outsideClickListener = (event) => { + if (!popover.contains(event.target) && event.target !== targetElement) { + popover.remove(); + document.removeEventListener('click', outsideClickListener); + } + }; + setTimeout(() => document.addEventListener('click', outsideClickListener), 0); + // Event listeners for the buttons inside the popover + popover.querySelector('.popover-confirm').addEventListener('click', () => { + this.sessionManager.deleteMessage(messageId); + this._renderChatMessages(); + this._renderSessionList(); + popover.remove(); + document.removeEventListener('click', outsideClickListener); + }); + popover.querySelector('.popover-cancel').addEventListener('click', () => { + popover.remove(); + document.removeEventListener('click', outsideClickListener); + }); + } + + _handleRetryMessage(messageId) { + if (this.isStreaming) return; // Prevent retrying while a response is already generating + const currentSession = this.sessionManager.getCurrentSession(); + if (!currentSession) return; + + const message = currentSession.messages.find(m => m.id === messageId); + if (!message) return; + if (message.role === 'user') { + // Logic for retrying from a user's prompt + this.sessionManager.truncateMessagesAfter(messageId); + } else if (message.role === 'assistant') { + // Logic for regenerating an assistant's response (must be the last one) + this.sessionManager.deleteMessage(messageId); + } + // After data manipulation, update the UI and trigger a new response + this._renderChatMessages(); + this._renderSessionList(); + this._getAssistantResponse(); + } + _autoResizeTextarea() { + const el = this.elements.messageInput; + el.style.height = 'auto'; + el.style.height = (el.scrollHeight) + 'px'; + } + + _handleSendMessage() { + if (this.isStreaming) return; + const content = this.elements.messageInput.value.trim(); + if (!content) return; + + const userMessage = { id: nanoid(), role: 'user', content: content }; + this.sessionManager.addMessage(userMessage); + + this._renderChatMessages(); + this._renderSessionList(); + + this.elements.messageInput.value = ''; + this._autoResizeTextarea(); + this.elements.messageInput.focus(); + this._getAssistantResponse(); + } + + async _getAssistantResponse() { + this.isStreaming = true; + this._setLoadingState(true); + const currentSession = this.sessionManager.getCurrentSession(); + const assistantMessageId = nanoid(); + let finalAssistantMessage = { id: assistantMessageId, role: 'assistant', content: '' }; + // Step 1: Create and render a temporary UI placeholder for streaming. + // [MODIFIED] The placeholder now uses the three-dot animation. + const placeholderHtml = ` +
+ + + +
+
+
+
+ + + +
+
+
+
+
`; + this.elements.chatMessagesContainer.insertAdjacentHTML('beforeend', placeholderHtml); + this._scrollToBottom(); + const assistantMessageContentEl = this.elements.chatMessagesContainer.querySelector(`[data-message-id="${assistantMessageId}"] .message-content`); + try { + const token = getCookie('gemini_admin_session'); + const headers = { 'Authorization': `Bearer ${token}` }; + const response = await apiFetch('/v1/chat/completions', { + method: 'POST', + headers, + body: JSON.stringify({ + model: currentSession.modelConfig.model, + messages: currentSession.messages.filter(m => m.content).map(({ role, content }) => ({ role, content })), + stream: true, + }) + }); + if (!response.body) throw new Error("Response body is null."); + + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + while (true) { + const { value, done } = await reader.read(); + if (done) break; + + const chunk = decoder.decode(value); + const lines = chunk.split('\n').filter(line => line.trim().startsWith('data:')); + + for (const line of lines) { + const dataStr = line.replace(/^data: /, '').trim(); + if (dataStr !== '[DONE]') { + try { + const data = JSON.parse(dataStr); + const deltaContent = data.choices[0]?.delta?.content; + if (deltaContent) { + finalAssistantMessage.content += deltaContent; + assistantMessageContentEl.innerHTML = marked.parse(finalAssistantMessage.content); + this._scrollToBottom(); + } + } catch (e) { /* ignore malformed JSON */ } + } + } + } + } catch (error) { + console.error('Fetch stream error:', error); + const errorMessage = error.rawMessageFromServer || error.message; + finalAssistantMessage.content = `请求失败: ${errorMessage}`; + } finally { + this.sessionManager.addMessage(finalAssistantMessage); + this._renderChatMessages(); + this._renderSessionList(); + this.isStreaming = false; + this._setLoadingState(false); + this.elements.messageInput.focus(); + } + } + + _renderMessage(message, replace = false, isLastMessage = false) { + let contentHtml; + if (message.role === 'user') { + const escapedContent = message.content.replace(//g, ">"); + contentHtml = `

${escapedContent.replace(/\n/g, '
')}

`; + } else { + // [FIXED] Simplified logic: if it's an assistant message, it either has real content or error HTML. + // The isStreamingPlaceholder case is now handled differently and removed from here. + const isErrorHtml = message.content && message.content.includes(''); + contentHtml = isErrorHtml ? + `
${message.content}
` : + `
${marked.parse(message.content || '')}
`; + } + + // [FIXED] No special handling for streaming placeholders needed anymore. + // If a message has content, it gets actions. An error message has content, so it will get actions. + let actionsHtml = ''; + let retryButton = ''; + if (message.role === 'user') { + retryButton = ` + `; + } else if (message.role === 'assistant' && isLastMessage) { + // This now correctly applies to final error messages too. + retryButton = ` + `; + } + const toolbarBaseClasses = "message-actions flex items-center gap-1 transition-opacity duration-200"; + const toolbarPositionClass = isLastMessage ? "mt-2" : "absolute bottom-2.5 right-2.5"; + const visibilityClass = isLastMessage ? "" : "opacity-0 group-hover:opacity-100"; + + actionsHtml = ` +
+ ${retryButton} + + +
+ `; + + const messageBubbleClasses = `relative group rounded-lg p-5 ${message.role === 'user' ? 'bg-muted' : 'bg-primary/10 border/20'}`; + const messageHtml = ` +
+ + + +
+
+ ${contentHtml} + ${actionsHtml} +
+
+
`; + + const existingElement = this.elements.chatMessagesContainer.querySelector(`[data-message-id="${message.id}"]`); + if (replace && existingElement) { + existingElement.outerHTML = messageHtml; + } else if (!existingElement) { + this.elements.chatMessagesContainer.insertAdjacentHTML('beforeend', messageHtml); + } + + if (!replace) { this._scrollToBottom(); } + } + + _scrollToBottom() { + this.elements.chatScrollContainer.scrollTop = this.elements.chatScrollContainer.scrollHeight; + } + + _render() { + this._renderSessionList(); + this._renderChatMessages(); + this._renderChatHeader(); + } + + _renderSessionList() { + let sessions = this.sessionManager.getSessions(); + const currentSessionId = this.sessionManager.getCurrentSessionId(); + if (this.searchTerm) { + const lowerCaseSearchTerm = this.searchTerm.toLowerCase(); + sessions = sessions.filter(session => { + const titleMatch = session.name.toLowerCase().includes(lowerCaseSearchTerm); + const messageMatch = session.messages.some(message => + message.content && message.content.toLowerCase().includes(lowerCaseSearchTerm) + ); + return titleMatch || messageMatch; + }); + } + + this.elements.sessionListContainer.innerHTML = sessions.map(session => { + const isActive = session.id === currentSessionId; + const lastMessage = session.messages.length > 0 ? session.messages[session.messages.length - 1].content : '新会话'; + + return ` +
+ +
${session.name}
+
${session.messages.length > 0 ? (lastMessage.includes('') ? '[请求失败]' : lastMessage) : '新会话'}
+
+ +
+ `; + }).join(''); + } + + _renderChatMessages() { + this.elements.chatMessagesContainer.innerHTML = ''; + const currentSession = this.sessionManager.getCurrentSession(); + if (currentSession) { + const messages = currentSession.messages; + const lastMessageIndex = messages.length > 0 ? messages.length - 1 : -1; + + messages.forEach((message, index) => { + const isLastMessage = (index === lastMessageIndex); + this._renderMessage(message, false, isLastMessage); + }); + } + } + + _renderChatHeader() { + const currentSession = this.sessionManager.getCurrentSession(); + if (currentSession && this.elements.chatHeaderTitle) { + this.elements.chatHeaderTitle.textContent = currentSession.name; + } + } + + _setLoadingState(isLoading) { + this.elements.messageInput.disabled = isLoading; + this.elements.sendBtn.disabled = isLoading; + if (isLoading) { + uiPatterns.setButtonLoading(this.elements.sendBtn); + } else { + uiPatterns.clearButtonLoading(this.elements.sendBtn); + } + } + _handleClearSession() { + Swal.fire({ + width: '22rem', + backdrop: `rgba(0,0,0,0.5)`, + heightAuto: false, + customClass: { popup: `swal2-custom-style ${document.documentElement.classList.contains('dark') ? 'swal2-dark' : ''}` }, + title: '确定要清空会话吗?', + text: '当前会话的所有聊天记录将被删除,但会话本身会保留。', + showCancelButton: true, + confirmButtonText: '确认清空', + cancelButtonText: '取消', + reverseButtons: false, + confirmButtonColor: '#ef4444', + cancelButtonColor: '#6b7280', + focusConfirm: false, + focusCancel: true, + }).then((result) => { + if (result.isConfirmed) { + this.sessionManager.clearCurrentSession(); // This method needs to be added to SessionManager + this._render(); + } + }); + } + _handleDeleteSession(sessionId) { + Swal.fire({ + width: '22rem', + backdrop: `rgba(0,0,0,0.5)`, + heightAuto: false, + customClass: { popup: `swal2-custom-style ${document.documentElement.classList.contains('dark') ? 'swal2-dark' : ''}` }, + title: '确定要删除吗?', + text: '此会话的所有记录将被永久删除,无法撤销。', + showCancelButton: true, + confirmButtonText: '确认删除', + cancelButtonText: '取消', + reverseButtons: false, + confirmButtonColor: '#ef4444', + cancelButtonColor: '#6b7280', + focusConfirm: false, + focusCancel: true, + }).then((result) => { + if (result.isConfirmed) { + this.sessionManager.deleteSession(sessionId); + this._render(); + } + }); + } +} + +export default function() { + const page = new ChatPage(); + page.init(); +} diff --git a/frontend/js/vendor/marked.min.js b/frontend/js/vendor/marked.min.js new file mode 100644 index 0000000..2a787ef --- /dev/null +++ b/frontend/js/vendor/marked.min.js @@ -0,0 +1,72 @@ +/** + * marked v17.0.1 - a markdown parser + * Copyright (c) 2018-2025, MarkedJS. (MIT License) + * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT License) + * https://github.com/markedjs/marked + */ + +/** + * DO NOT EDIT THIS FILE + * The code in this file is generated from files in ./src/ + */ + +function L(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var T=L();function Z(u){T=u}var C={exec:()=>null};function k(u,e=""){let t=typeof u=="string"?u:u.source,n={replace:(r,i)=>{let s=typeof i=="string"?i:i.source;return s=s.replace(m.caret,"$1"),t=t.replace(r,s),n},getRegex:()=>new RegExp(t,e)};return n}var me=(()=>{try{return!!new RegExp("(?<=1)(?/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:u=>new RegExp(`^( {0,3}${u})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}#`),htmlBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}<(?:[a-z].*>|!--)`,"i")},xe=/^(?:[ \t]*(?:\n|$))+/,be=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Re=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,I=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,Te=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,N=/(?:[*+-]|\d{1,9}[.)])/,re=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,se=k(re).replace(/bull/g,N).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),Oe=k(re).replace(/bull/g,N).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),Q=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,we=/^[^\n]+/,F=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,ye=k(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",F).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Pe=k(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,N).getRegex(),v="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|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",j=/|$))/,Se=k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",j).replace("tag",v).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),ie=k(Q).replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex(),$e=k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",ie).getRegex(),U={blockquote:$e,code:be,def:ye,fences:Re,heading:Te,hr:I,html:Se,lheading:se,list:Pe,newline:xe,paragraph:ie,table:C,text:we},te=k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex(),_e={...U,lheading:Oe,table:te,paragraph:k(Q).replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",te).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex()},Le={...U,html:k(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",j).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:C,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:k(Q).replace("hr",I).replace("heading",` *#{1,6} *[^ +]`).replace("lheading",se).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Me=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,ze=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,oe=/^( {2,}|\\)\n(?!\s*$)/,Ae=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\`+)[^`]+\k(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",me?"(?`+)[^`]+\k(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),ue=/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,qe=k(ue,"u").replace(/punct/g,D).getRegex(),ve=k(ue,"u").replace(/punct/g,le).getRegex(),pe="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",De=k(pe,"gu").replace(/notPunctSpace/g,ae).replace(/punctSpace/g,K).replace(/punct/g,D).getRegex(),He=k(pe,"gu").replace(/notPunctSpace/g,Ee).replace(/punctSpace/g,Ie).replace(/punct/g,le).getRegex(),Ze=k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,ae).replace(/punctSpace/g,K).replace(/punct/g,D).getRegex(),Ge=k(/\\(punct)/,"gu").replace(/punct/g,D).getRegex(),Ne=k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Qe=k(j).replace("(?:-->|$)","-->").getRegex(),Fe=k("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",Qe).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),q=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+[^`]*?`+(?!`)|[^\[\]\\`])*?/,je=k(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label",q).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),ce=k(/^!?\[(label)\]\[(ref)\]/).replace("label",q).replace("ref",F).getRegex(),he=k(/^!?\[(ref)\](?:\[\])?/).replace("ref",F).getRegex(),Ue=k("reflink|nolink(?!\\()","g").replace("reflink",ce).replace("nolink",he).getRegex(),ne=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,W={_backpedal:C,anyPunctuation:Ge,autolink:Ne,blockSkip:Be,br:oe,code:ze,del:C,emStrongLDelim:qe,emStrongRDelimAst:De,emStrongRDelimUnd:Ze,escape:Me,link:je,nolink:he,punctuation:Ce,reflink:ce,reflinkSearch:Ue,tag:Fe,text:Ae,url:C},Ke={...W,link:k(/^!?\[(label)\]\((.*?)\)/).replace("label",q).getRegex(),reflink:k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",q).getRegex()},G={...W,emStrongRDelimAst:He,emStrongLDelim:ve,url:k(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",ne).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:k(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},ke=u=>Xe[u];function w(u,e){if(e){if(m.escapeTest.test(u))return u.replace(m.escapeReplace,ke)}else if(m.escapeTestNoEncode.test(u))return u.replace(m.escapeReplaceNoEncode,ke);return u}function X(u){try{u=encodeURI(u).replace(m.percentDecode,"%")}catch{return null}return u}function J(u,e){let t=u.replace(m.findPipe,(i,s,a)=>{let o=!1,l=s;for(;--l>=0&&a[l]==="\\";)o=!o;return o?"|":" |"}),n=t.split(m.splitPipe),r=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length0?-2:-1}function ge(u,e,t,n,r){let i=e.href,s=e.title||null,a=u[1].replace(r.other.outputLinkReplace,"$1");n.state.inLink=!0;let o={type:u[0].charAt(0)==="!"?"image":"link",raw:t,href:i,title:s,text:a,tokens:n.inlineTokens(a)};return n.state.inLink=!1,o}function Je(u,e,t){let n=u.match(t.other.indentCodeCompensation);if(n===null)return e;let r=n[1];return e.split(` +`).map(i=>{let s=i.match(t.other.beginningSpace);if(s===null)return i;let[a]=s;return a.length>=r.length?i.slice(r.length):i}).join(` +`)}var y=class{options;rules;lexer;constructor(e){this.options=e||T}space(e){let t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:"space",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?n:z(n,` +`)}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],r=Je(n,t[3]||"",this.rules);return{type:"code",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:r}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let r=z(n,"#");(this.options.pedantic||!r||this.rules.other.endingSpaceChar.test(r))&&(n=r.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){let t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:z(t[0],` +`)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=z(t[0],` +`).split(` +`),r="",i="",s=[];for(;n.length>0;){let a=!1,o=[],l;for(l=0;l1,i={type:"list",raw:"",ordered:r,start:r?+n.slice(0,-1):"",loose:!1,items:[]};n=r?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=r?n:"[*+-]");let s=this.rules.other.listItemRegex(n),a=!1;for(;e;){let l=!1,p="",c="";if(!(t=s.exec(e))||this.rules.block.hr.test(e))break;p=t[0],e=e.substring(p.length);let g=t[2].split(` +`,1)[0].replace(this.rules.other.listReplaceTabs,O=>" ".repeat(3*O.length)),h=e.split(` +`,1)[0],R=!g.trim(),f=0;if(this.options.pedantic?(f=2,c=g.trimStart()):R?f=t[1].length+1:(f=t[2].search(this.rules.other.nonSpaceChar),f=f>4?1:f,c=g.slice(f),f+=t[1].length),R&&this.rules.other.blankLine.test(h)&&(p+=h+` +`,e=e.substring(h.length+1),l=!0),!l){let O=this.rules.other.nextBulletRegex(f),V=this.rules.other.hrRegex(f),Y=this.rules.other.fencesBeginRegex(f),ee=this.rules.other.headingBeginRegex(f),fe=this.rules.other.htmlBeginRegex(f);for(;e;){let H=e.split(` +`,1)[0],A;if(h=H,this.options.pedantic?(h=h.replace(this.rules.other.listReplaceNesting," "),A=h):A=h.replace(this.rules.other.tabCharGlobal," "),Y.test(h)||ee.test(h)||fe.test(h)||O.test(h)||V.test(h))break;if(A.search(this.rules.other.nonSpaceChar)>=f||!h.trim())c+=` +`+A.slice(f);else{if(R||g.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||Y.test(g)||ee.test(g)||V.test(g))break;c+=` +`+h}!R&&!h.trim()&&(R=!0),p+=H+` +`,e=e.substring(H.length+1),g=A.slice(f)}}i.loose||(a?i.loose=!0:this.rules.other.doubleBlankLine.test(p)&&(a=!0)),i.items.push({type:"list_item",raw:p,task:!!this.options.gfm&&this.rules.other.listIsTask.test(c),loose:!1,text:c,tokens:[]}),i.raw+=p}let o=i.items.at(-1);if(o)o.raw=o.raw.trimEnd(),o.text=o.text.trimEnd();else return;i.raw=i.raw.trimEnd();for(let l of i.items){if(this.lexer.state.top=!1,l.tokens=this.lexer.blockTokens(l.text,[]),l.task){if(l.text=l.text.replace(this.rules.other.listReplaceTask,""),l.tokens[0]?.type==="text"||l.tokens[0]?.type==="paragraph"){l.tokens[0].raw=l.tokens[0].raw.replace(this.rules.other.listReplaceTask,""),l.tokens[0].text=l.tokens[0].text.replace(this.rules.other.listReplaceTask,"");for(let c=this.lexer.inlineQueue.length-1;c>=0;c--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[c].src)){this.lexer.inlineQueue[c].src=this.lexer.inlineQueue[c].src.replace(this.rules.other.listReplaceTask,"");break}}let p=this.rules.other.listTaskCheckbox.exec(l.raw);if(p){let c={type:"checkbox",raw:p[0]+" ",checked:p[0]!=="[ ]"};l.checked=c.checked,i.loose?l.tokens[0]&&["paragraph","text"].includes(l.tokens[0].type)&&"tokens"in l.tokens[0]&&l.tokens[0].tokens?(l.tokens[0].raw=c.raw+l.tokens[0].raw,l.tokens[0].text=c.raw+l.tokens[0].text,l.tokens[0].tokens.unshift(c)):l.tokens.unshift({type:"paragraph",raw:c.raw,text:c.raw,tokens:[c]}):l.tokens.unshift(c)}}if(!i.loose){let p=l.tokens.filter(g=>g.type==="space"),c=p.length>0&&p.some(g=>this.rules.other.anyLine.test(g.raw));i.loose=c}}if(i.loose)for(let l of i.items){l.loose=!0;for(let p of l.tokens)p.type==="text"&&(p.type="paragraph")}return i}}html(e){let t=this.rules.block.html.exec(e);if(t)return{type:"html",block:!0,raw:t[0],pre:t[1]==="pre"||t[1]==="script"||t[1]==="style",text:t[0]}}def(e){let t=this.rules.block.def.exec(e);if(t){let n=t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),r=t[2]?t[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",i=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):t[3];return{type:"def",tag:n,raw:t[0],href:r,title:i}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=J(t[1]),r=t[2].replace(this.rules.other.tableAlignChars,"").split("|"),i=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,"").split(` +`):[],s={type:"table",raw:t[0],header:[],align:[],rows:[]};if(n.length===r.length){for(let a of r)this.rules.other.tableAlignRight.test(a)?s.align.push("right"):this.rules.other.tableAlignCenter.test(a)?s.align.push("center"):this.rules.other.tableAlignLeft.test(a)?s.align.push("left"):s.align.push(null);for(let a=0;a({text:o,tokens:this.lexer.inline(o),header:!1,align:s.align[l]})));return s}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:t[2].charAt(0)==="="?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=t[1].charAt(t[1].length-1)===` +`?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let s=z(n.slice(0,-1),"\\");if((n.length-s.length)%2===0)return}else{let s=de(t[2],"()");if(s===-2)return;if(s>-1){let o=(t[0].indexOf("!")===0?5:4)+t[1].length+s;t[2]=t[2].substring(0,s),t[0]=t[0].substring(0,o).trim(),t[3]=""}}let r=t[2],i="";if(this.options.pedantic){let s=this.rules.other.pedanticHrefTitle.exec(r);s&&(r=s[1],i=s[3])}else i=t[3]?t[3].slice(1,-1):"";return r=r.trim(),this.rules.other.startAngleBracket.test(r)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?r=r.slice(1):r=r.slice(1,-1)),ge(t,{href:r&&r.replace(this.rules.inline.anyPunctuation,"$1"),title:i&&i.replace(this.rules.inline.anyPunctuation,"$1")},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let r=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),i=t[r.toLowerCase()];if(!i){let s=n[0].charAt(0);return{type:"text",raw:s,text:s}}return ge(n,i,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let r=this.rules.inline.emStrongLDelim.exec(e);if(!r||r[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(r[1]||r[2]||"")||!n||this.rules.inline.punctuation.exec(n)){let s=[...r[0]].length-1,a,o,l=s,p=0,c=r[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(c.lastIndex=0,t=t.slice(-1*e.length+s);(r=c.exec(t))!=null;){if(a=r[1]||r[2]||r[3]||r[4]||r[5]||r[6],!a)continue;if(o=[...a].length,r[3]||r[4]){l+=o;continue}else if((r[5]||r[6])&&s%3&&!((s+o)%3)){p+=o;continue}if(l-=o,l>0)continue;o=Math.min(o,o+l+p);let g=[...r[0]][0].length,h=e.slice(0,s+r.index+g+o);if(Math.min(s,o)%2){let f=h.slice(1,-1);return{type:"em",raw:h,text:f,tokens:this.lexer.inlineTokens(f)}}let R=h.slice(2,-2);return{type:"strong",raw:h,text:R,tokens:this.lexer.inlineTokens(R)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){let n=t[2].replace(this.rules.other.newLineCharGlobal," "),r=this.rules.other.nonSpaceChar.test(n),i=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return r&&i&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){let t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,r;return t[2]==="@"?(n=t[1],r="mailto:"+n):(n=t[1],r=n),{type:"link",raw:t[0],text:n,href:r,tokens:[{type:"text",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,r;if(t[2]==="@")n=t[0],r="mailto:"+n;else{let i;do i=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??"";while(i!==t[0]);n=t[0],t[1]==="www."?r="http://"+t[0]:r=t[0]}return{type:"link",raw:t[0],text:n,href:r,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return{type:"text",raw:t[0],text:t[0],escaped:n}}}};var x=class u{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||T,this.options.tokenizer=this.options.tokenizer||new y,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let t={other:m,block:E.normal,inline:M.normal};this.options.pedantic?(t.block=E.pedantic,t.inline=M.pedantic):this.options.gfm&&(t.block=E.gfm,this.options.breaks?t.inline=M.breaks:t.inline=M.gfm),this.tokenizer.rules=t}static get rules(){return{block:E,inline:M}}static lex(e,t){return new u(t).lex(e)}static lexInline(e,t){return new u(t).inlineTokens(e)}lex(e){e=e.replace(m.carriageReturn,` +`),this.blockTokens(e,this.tokens);for(let t=0;t(r=s.call({lexer:this},e,t))?(e=e.substring(r.raw.length),t.push(r),!0):!1))continue;if(r=this.tokenizer.space(e)){e=e.substring(r.raw.length);let s=t.at(-1);r.raw.length===1&&s!==void 0?s.raw+=` +`:t.push(r);continue}if(r=this.tokenizer.code(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type==="paragraph"||s?.type==="text"?(s.raw+=(s.raw.endsWith(` +`)?"":` +`)+r.raw,s.text+=` +`+r.text,this.inlineQueue.at(-1).src=s.text):t.push(r);continue}if(r=this.tokenizer.fences(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.heading(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.hr(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.blockquote(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.list(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.html(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.def(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type==="paragraph"||s?.type==="text"?(s.raw+=(s.raw.endsWith(` +`)?"":` +`)+r.raw,s.text+=` +`+r.raw,this.inlineQueue.at(-1).src=s.text):this.tokens.links[r.tag]||(this.tokens.links[r.tag]={href:r.href,title:r.title},t.push(r));continue}if(r=this.tokenizer.table(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.lheading(e)){e=e.substring(r.raw.length),t.push(r);continue}let i=e;if(this.options.extensions?.startBlock){let s=1/0,a=e.slice(1),o;this.options.extensions.startBlock.forEach(l=>{o=l.call({lexer:this},a),typeof o=="number"&&o>=0&&(s=Math.min(s,o))}),s<1/0&&s>=0&&(i=e.substring(0,s+1))}if(this.state.top&&(r=this.tokenizer.paragraph(i))){let s=t.at(-1);n&&s?.type==="paragraph"?(s.raw+=(s.raw.endsWith(` +`)?"":` +`)+r.raw,s.text+=` +`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=s.text):t.push(r),n=i.length!==e.length,e=e.substring(r.raw.length);continue}if(r=this.tokenizer.text(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type==="text"?(s.raw+=(s.raw.endsWith(` +`)?"":` +`)+r.raw,s.text+=` +`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=s.text):t.push(r);continue}if(e){let s="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(s);break}else throw new Error(s)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,r=null;if(this.tokens.links){let o=Object.keys(this.tokens.links);if(o.length>0)for(;(r=this.tokenizer.rules.inline.reflinkSearch.exec(n))!=null;)o.includes(r[0].slice(r[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,r.index)+"["+"a".repeat(r[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(r=this.tokenizer.rules.inline.anyPunctuation.exec(n))!=null;)n=n.slice(0,r.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let i;for(;(r=this.tokenizer.rules.inline.blockSkip.exec(n))!=null;)i=r[2]?r[2].length:0,n=n.slice(0,r.index+i)+"["+"a".repeat(r[0].length-i-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);n=this.options.hooks?.emStrongMask?.call({lexer:this},n)??n;let s=!1,a="";for(;e;){s||(a=""),s=!1;let o;if(this.options.extensions?.inline?.some(p=>(o=p.call({lexer:this},e,t))?(e=e.substring(o.raw.length),t.push(o),!0):!1))continue;if(o=this.tokenizer.escape(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.tag(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.link(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(o.raw.length);let p=t.at(-1);o.type==="text"&&p?.type==="text"?(p.raw+=o.raw,p.text+=o.text):t.push(o);continue}if(o=this.tokenizer.emStrong(e,n,a)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.codespan(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.br(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.del(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.autolink(e)){e=e.substring(o.raw.length),t.push(o);continue}if(!this.state.inLink&&(o=this.tokenizer.url(e))){e=e.substring(o.raw.length),t.push(o);continue}let l=e;if(this.options.extensions?.startInline){let p=1/0,c=e.slice(1),g;this.options.extensions.startInline.forEach(h=>{g=h.call({lexer:this},c),typeof g=="number"&&g>=0&&(p=Math.min(p,g))}),p<1/0&&p>=0&&(l=e.substring(0,p+1))}if(o=this.tokenizer.inlineText(l)){e=e.substring(o.raw.length),o.raw.slice(-1)!=="_"&&(a=o.raw.slice(-1)),s=!0;let p=t.at(-1);p?.type==="text"?(p.raw+=o.raw,p.text+=o.text):t.push(o);continue}if(e){let p="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(p);break}else throw new Error(p)}}return t}};var P=class{options;parser;constructor(e){this.options=e||T}space(e){return""}code({text:e,lang:t,escaped:n}){let r=(t||"").match(m.notSpaceStart)?.[0],i=e.replace(m.endingNewline,"")+` +`;return r?'
'+(n?i:w(i,!0))+`
+`:"
"+(n?i:w(i,!0))+`
+`}blockquote({tokens:e}){return`
+${this.parser.parse(e)}
+`}html({text:e}){return e}def(e){return""}heading({tokens:e,depth:t}){return`${this.parser.parseInline(e)} +`}hr(e){return`
+`}list(e){let t=e.ordered,n=e.start,r="";for(let a=0;a +`+r+" +`}listitem(e){return`
  • ${this.parser.parse(e.tokens)}
  • +`}checkbox({checked:e}){return" '}paragraph({tokens:e}){return`

    ${this.parser.parseInline(e)}

    +`}table(e){let t="",n="";for(let i=0;i${r}`),` + +`+t+` +`+r+`
    +`}tablerow({text:e}){return` +${e} +`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+` +`}strong({tokens:e}){return`${this.parser.parseInline(e)}`}em({tokens:e}){return`${this.parser.parseInline(e)}`}codespan({text:e}){return`${w(e,!0)}`}br(e){return"
    "}del({tokens:e}){return`${this.parser.parseInline(e)}`}link({href:e,title:t,tokens:n}){let r=this.parser.parseInline(n),i=X(e);if(i===null)return r;e=i;let s='
    ",s}image({href:e,title:t,text:n,tokens:r}){r&&(n=this.parser.parseInline(r,this.parser.textRenderer));let i=X(e);if(i===null)return w(n);e=i;let s=`${n}{let a=i[s].flat(1/0);n=n.concat(this.walkTokens(a,t))}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let r={...n};if(r.async=this.defaults.async||r.async||!1,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error("extension name required");if("renderer"in i){let s=t.renderers[i.name];s?t.renderers[i.name]=function(...a){let o=i.renderer.apply(this,a);return o===!1&&(o=s.apply(this,a)),o}:t.renderers[i.name]=i.renderer}if("tokenizer"in i){if(!i.level||i.level!=="block"&&i.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let s=t[i.level];s?s.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&(i.level==="block"?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:i.level==="inline"&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]))}"childTokens"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens)}),r.extensions=t),n.renderer){let i=this.defaults.renderer||new P(this.defaults);for(let s in n.renderer){if(!(s in i))throw new Error(`renderer '${s}' does not exist`);if(["options","parser"].includes(s))continue;let a=s,o=n.renderer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c||""}}r.renderer=i}if(n.tokenizer){let i=this.defaults.tokenizer||new y(this.defaults);for(let s in n.tokenizer){if(!(s in i))throw new Error(`tokenizer '${s}' does not exist`);if(["options","rules","lexer"].includes(s))continue;let a=s,o=n.tokenizer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c}}r.tokenizer=i}if(n.hooks){let i=this.defaults.hooks||new S;for(let s in n.hooks){if(!(s in i))throw new Error(`hook '${s}' does not exist`);if(["options","block"].includes(s))continue;let a=s,o=n.hooks[a],l=i[a];S.passThroughHooks.has(s)?i[a]=p=>{if(this.defaults.async&&S.passThroughHooksRespectAsync.has(s))return(async()=>{let g=await o.call(i,p);return l.call(i,g)})();let c=o.call(i,p);return l.call(i,c)}:i[a]=(...p)=>{if(this.defaults.async)return(async()=>{let g=await o.apply(i,p);return g===!1&&(g=await l.apply(i,p)),g})();let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c}}r.hooks=i}if(n.walkTokens){let i=this.defaults.walkTokens,s=n.walkTokens;r.walkTokens=function(a){let o=[];return o.push(s.call(this,a)),i&&(o=o.concat(i.call(this,a))),o}}this.defaults={...this.defaults,...r}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return(n,r)=>{let i={...r},s={...this.defaults,...i},a=this.onError(!!s.silent,!!s.async);if(this.defaults.async===!0&&i.async===!1)return a(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof n>"u"||n===null)return a(new Error("marked(): input parameter is undefined or null"));if(typeof n!="string")return a(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(s.hooks&&(s.hooks.options=s,s.hooks.block=e),s.async)return(async()=>{let o=s.hooks?await s.hooks.preprocess(n):n,p=await(s.hooks?await s.hooks.provideLexer():e?x.lex:x.lexInline)(o,s),c=s.hooks?await s.hooks.processAllTokens(p):p;s.walkTokens&&await Promise.all(this.walkTokens(c,s.walkTokens));let h=await(s.hooks?await s.hooks.provideParser():e?b.parse:b.parseInline)(c,s);return s.hooks?await s.hooks.postprocess(h):h})().catch(a);try{s.hooks&&(n=s.hooks.preprocess(n));let l=(s.hooks?s.hooks.provideLexer():e?x.lex:x.lexInline)(n,s);s.hooks&&(l=s.hooks.processAllTokens(l)),s.walkTokens&&this.walkTokens(l,s.walkTokens);let c=(s.hooks?s.hooks.provideParser():e?b.parse:b.parseInline)(l,s);return s.hooks&&(c=s.hooks.postprocess(c)),c}catch(o){return a(o)}}}onError(e,t){return n=>{if(n.message+=` +Please report this to https://github.com/markedjs/marked.`,e){let r="

    An error occurred:

    "+w(n.message+"",!0)+"
    ";return t?Promise.resolve(r):r}if(t)return Promise.reject(n);throw n}}};var _=new B;function d(u,e){return _.parse(u,e)}d.options=d.setOptions=function(u){return _.setOptions(u),d.defaults=_.defaults,Z(d.defaults),d};d.getDefaults=L;d.defaults=T;d.use=function(...u){return _.use(...u),d.defaults=_.defaults,Z(d.defaults),d};d.walkTokens=function(u,e){return _.walkTokens(u,e)};d.parseInline=_.parseInline;d.Parser=b;d.parser=b.parse;d.Renderer=P;d.TextRenderer=$;d.Lexer=x;d.lexer=x.lex;d.Tokenizer=y;d.Hooks=S;d.parse=d;var Dt=d.options,Ht=d.setOptions,Zt=d.use,Gt=d.walkTokens,Nt=d.parseInline,Qt=d,Ft=b.parse,jt=x.lex;export{S as Hooks,x as Lexer,B as Marked,b as Parser,P as Renderer,$ as TextRenderer,y as Tokenizer,T as defaults,L as getDefaults,jt as lexer,d as marked,Dt as options,Qt as parse,Nt as parseInline,Ft as parser,Ht as setOptions,Zt as use,Gt as walkTokens}; +//# sourceMappingURL=marked.esm.js.map \ No newline at end of file diff --git a/frontend/js/vendor/nanoid.js b/frontend/js/vendor/nanoid.js new file mode 100644 index 0000000..ffa1d4b --- /dev/null +++ b/frontend/js/vendor/nanoid.js @@ -0,0 +1 @@ +let a="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";export let nanoid=(e=21)=>{let t="",r=crypto.getRandomValues(new Uint8Array(e));for(let n=0;n :not(:last-child)) { --tw-space-y-reverse: 0; @@ -1136,6 +1191,9 @@ .overflow-y-auto { overflow-y: auto; } + .overflow-y-hidden { + overflow-y: hidden; + } .rounded { border-radius: 0.25rem; } @@ -1154,6 +1212,9 @@ .rounded-xl { border-radius: var(--radius-xl); } + .rounded-xs { + border-radius: var(--radius-xs); + } .rounded-l-md { border-top-left-radius: var(--radius-md); border-bottom-left-radius: var(--radius-md); @@ -1235,15 +1296,6 @@ .border-green-200 { border-color: var(--color-green-200); } - .border-primary { - border-color: var(--color-primary); - } - .border-primary\/20 { - border-color: var(--color-primary); - @supports (color: color-mix(in lab, red, red)) { - border-color: color-mix(in oklab, var(--color-primary) 20%, transparent); - } - } .border-red-100 { border-color: var(--color-red-100); } @@ -1343,6 +1395,15 @@ background-color: color-mix(in oklab, var(--color-destructive) 10%, transparent); } } + .bg-foreground { + background-color: var(--color-foreground); + } + .bg-foreground\/50 { + background-color: var(--color-foreground); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-foreground) 50%, transparent); + } + } .bg-gray-50 { background-color: var(--color-gray-50); } @@ -1622,6 +1683,9 @@ .p-4 { padding: calc(var(--spacing) * 4); } + .p-5 { + padding: calc(var(--spacing) * 5); + } .p-6 { padding: calc(var(--spacing) * 6); } @@ -1679,6 +1743,9 @@ .pt-2 { padding-top: calc(var(--spacing) * 2); } + .pt-3 { + padding-top: calc(var(--spacing) * 3); + } .pt-4 { padding-top: calc(var(--spacing) * 4); } @@ -1703,6 +1770,9 @@ .pr-20 { padding-right: calc(var(--spacing) * 20); } + .pr-24 { + padding-right: calc(var(--spacing) * 24); + } .pb-1 { padding-bottom: calc(var(--spacing) * 1); } @@ -1911,6 +1981,12 @@ .text-muted-foreground { color: var(--color-muted-foreground); } + .text-muted-foreground\/60 { + color: var(--color-muted-foreground); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-muted-foreground) 60%, transparent); + } + } .text-orange-500 { color: var(--color-orange-500); } @@ -2137,6 +2213,11 @@ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); transition-duration: var(--tw-duration, var(--default-transition-duration)); } + .transition-\[grid-template-rows\] { + transition-property: grid-template-rows; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } .transition-all { transition-property: all; transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); @@ -2226,19 +2307,108 @@ } } } - .even\:bg-zinc-50\/50 { - &:nth-child(even) { - background-color: color-mix(in srgb, oklch(98.5% 0 0) 50%, transparent); + .peer-checked\:bg-primary { + &:is(:where(.peer):checked ~ *) { + background-color: var(--color-primary); + } + } + .peer-focus\:ring-2 { + &:is(:where(.peer):focus ~ *) { + --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + } + .peer-focus\:ring-primary\/50 { + &:is(:where(.peer):focus ~ *) { + --tw-ring-color: var(--color-primary); @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-zinc-50) 50%, transparent); + --tw-ring-color: color-mix(in oklab, var(--color-primary) 50%, transparent); } } } - .even\:bg-zinc-100\/50 { - &:nth-child(even) { - background-color: color-mix(in srgb, oklch(96.7% 0.001 286.375) 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-zinc-100) 50%, transparent); + .after\:absolute { + &::after { + content: var(--tw-content); + position: absolute; + } + } + .after\:top-0\.5 { + &::after { + content: var(--tw-content); + top: calc(var(--spacing) * 0.5); + } + } + .after\:left-\[2px\] { + &::after { + content: var(--tw-content); + left: 2px; + } + } + .after\:h-5 { + &::after { + content: var(--tw-content); + height: calc(var(--spacing) * 5); + } + } + .after\:w-5 { + &::after { + content: var(--tw-content); + width: calc(var(--spacing) * 5); + } + } + .after\:rounded-full { + &::after { + content: var(--tw-content); + border-radius: calc(infinity * 1px); + } + } + .after\:border { + &::after { + content: var(--tw-content); + border-style: var(--tw-border-style); + border-width: 1px; + } + } + .after\:border-border { + &::after { + content: var(--tw-content); + border-color: var(--color-border); + } + } + .after\:bg-white { + &::after { + content: var(--tw-content); + background-color: var(--color-white); + } + } + .after\:transition-all { + &::after { + content: var(--tw-content); + transition-property: all; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + } + .after\:content-\[\'\'\] { + &::after { + --tw-content: ''; + content: var(--tw-content); + } + } + .peer-checked\:after\:translate-x-full { + &:is(:where(.peer):checked ~ *) { + &::after { + content: var(--tw-content); + --tw-translate-x: 100%; + translate: var(--tw-translate-x) var(--tw-translate-y); + } + } + } + .peer-checked\:after\:border-white { + &:is(:where(.peer):checked ~ *) { + &::after { + content: var(--tw-content); + border-color: var(--color-white); } } } @@ -2250,14 +2420,6 @@ } } } - .even\:bg-zinc-200\/50 { - &:nth-child(even) { - background-color: color-mix(in srgb, oklch(92% 0.004 286.32) 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-zinc-200) 50%, transparent); - } - } - } .focus-within\:border-blue-500 { &:focus-within { border-color: var(--color-blue-500); @@ -2365,6 +2527,16 @@ } } } + .hover\:bg-destructive\/80 { + &:hover { + @media (hover: hover) { + background-color: var(--color-destructive); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-destructive) 80%, transparent); + } + } + } + } .hover\:bg-gray-50 { &:hover { @media (hover: hover) { @@ -2407,6 +2579,13 @@ } } } + .hover\:bg-green-600 { + &:hover { + @media (hover: hover) { + background-color: var(--color-green-600); + } + } + } .hover\:bg-green-700 { &:hover { @media (hover: hover) { @@ -2522,6 +2701,13 @@ } } } + .hover\:text-destructive-foreground { + &:hover { + @media (hover: hover) { + color: var(--color-destructive-foreground); + } + } + } .hover\:text-gray-800 { &:hover { @media (hover: hover) { @@ -2550,6 +2736,13 @@ } } } + .hover\:text-sky-500 { + &:hover { + @media (hover: hover) { + color: var(--color-sky-500); + } + } + } .hover\:text-yellow-500 { &:hover { @media (hover: hover) { @@ -2580,6 +2773,11 @@ } } } + .focus\:relative { + &:focus { + position: relative; + } + } .focus\:border-blue-500 { &:focus { border-color: var(--color-blue-500); @@ -2664,11 +2862,49 @@ cursor: not-allowed; } } + .disabled\:bg-green-500\/50 { + &:disabled { + background-color: color-mix(in srgb, oklch(72.3% 0.219 149.579) 50%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-green-500) 50%, transparent); + } + } + } .disabled\:opacity-50 { &:disabled { opacity: 50%; } } + .data-\[active\=true\]\:bg-muted { + &[data-active="true"] { + background-color: var(--color-muted); + } + } + .data-\[active\=true\]\:bg-primary { + &[data-active="true"] { + background-color: var(--color-primary); + } + } + .data-\[active\=true\]\:text-accent-foreground { + &[data-active="true"] { + color: var(--color-accent-foreground); + } + } + .data-\[active\=true\]\:text-primary-foreground { + &[data-active="true"] { + color: var(--color-primary-foreground); + } + } + .data-\[expanded\=true\]\:visible { + &[data-expanded="true"] { + visibility: visible; + } + } + .data-\[expanded\=true\]\:grid-rows-\[1\] { + &[data-expanded="true"] { + grid-template-rows: 1; + } + } .sm\:w-48 { @media (width >= 40rem) { width: calc(var(--spacing) * 48); @@ -2957,6 +3193,11 @@ background-color: var(--color-gray-800); } } + .dark\:bg-green-600 { + &:where(.dark, .dark *) { + background-color: var(--color-green-600); + } + } .dark\:bg-green-900 { &:where(.dark, .dark *) { background-color: var(--color-green-900); @@ -3107,6 +3348,11 @@ background-color: var(--color-zinc-950); } } + .dark\:text-black { + &:where(.dark, .dark *) { + color: var(--color-black); + } + } .dark\:text-blue-300 { &:where(.dark, .dark *) { color: var(--color-blue-300); @@ -3235,16 +3481,6 @@ } } } - .dark\:even\:bg-black\/5 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #000 5%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-black) 5%, transparent); - } - } - } - } .dark\:even\:bg-black\/10 { &:where(.dark, .dark *) { &:nth-child(even) { @@ -3255,86 +3491,6 @@ } } } - .dark\:even\:bg-black\/20 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #000 20%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-black) 20%, transparent); - } - } - } - } - .dark\:even\:bg-black\/30 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #000 30%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-black) 30%, transparent); - } - } - } - } - .dark\:even\:bg-black\/50 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #000 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-black) 50%, transparent); - } - } - } - } - .dark\:even\:bg-black\/60 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #000 60%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-black) 60%, transparent); - } - } - } - } - .dark\:even\:bg-black\/90 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #000 90%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-black) 90%, transparent); - } - } - } - } - .dark\:even\:bg-white\/5 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #fff 5%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 5%, transparent); - } - } - } - } - .dark\:even\:bg-white\/15 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #fff 15%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 15%, transparent); - } - } - } - } - .dark\:even\:bg-white\/50 { - &:where(.dark, .dark *) { - &:nth-child(even) { - background-color: color-mix(in srgb, #fff 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 50%, transparent); - } - } - } - } .dark\:hover\:border-blue-400 { &:where(.dark, .dark *) { &:hover { @@ -3356,6 +3512,15 @@ } } } + .dark\:hover\:bg-green-700 { + &:where(.dark, .dark *) { + &:hover { + @media (hover: hover) { + background-color: var(--color-green-700); + } + } + } + } .dark\:hover\:bg-muted\/80 { &:where(.dark, .dark *) { &:hover { @@ -3443,7 +3608,7 @@ --primary-foreground: #fff; --secondary: oklch(92% 0.004 286.32); --secondary-foreground: oklch(21% 0.006 285.885); - --destructive: oklch(57.7% 0.245 27.325); + --destructive: oklch(63.7% 0.237 25.331); --destructive-foreground: #fff; --accent: oklch(96.7% 0.001 286.375); --accent-foreground: oklch(21% 0.006 285.885); @@ -3518,6 +3683,12 @@ } } .btn-secondary { + border-style: var(--tw-border-style); + border-width: 1px; + border-color: color-mix(in srgb, oklch(55.2% 0.016 285.938) 30%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-zinc-500) 30%, transparent); + } background-color: var(--color-secondary); color: var(--color-secondary-foreground); &:hover { @@ -3530,6 +3701,12 @@ } } .btn-destructive { + border-style: var(--tw-border-style); + border-width: 1px; + border-color: color-mix(in srgb, oklch(55.2% 0.016 285.938) 30%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-zinc-500) 30%, transparent); + } background-color: var(--color-destructive); color: var(--color-destructive-foreground); &:hover { @@ -3578,6 +3755,10 @@ } } } + .btn-group-item.active { + background-color: var(--color-primary); + color: var(--color-primary-foreground); + } .btn-lg { height: calc(var(--spacing) * 11); border-radius: var(--radius-md); @@ -5888,6 +6069,11 @@ syntax: "*"; inherits: false; } +@property --tw-content { + syntax: "*"; + initial-value: ""; + inherits: false; +} @keyframes spin { to { transform: rotate(360deg); @@ -5904,6 +6090,16 @@ opacity: 0.5; } } +@keyframes bounce { + 0%, 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8, 0, 1, 1); + } + 50% { + transform: none; + animation-timing-function: cubic-bezier(0, 0, 0.2, 1); + } +} @layer properties { @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { *, ::before, ::after, ::backdrop { @@ -5978,6 +6174,7 @@ --tw-backdrop-sepia: initial; --tw-duration: initial; --tw-ease: initial; + --tw-content: ""; } } } diff --git a/web/static/js/chat-2W4NJWMO.js b/web/static/js/chat-2W4NJWMO.js new file mode 100644 index 0000000..df8b0d9 --- /dev/null +++ b/web/static/js/chat-2W4NJWMO.js @@ -0,0 +1,1926 @@ +import { + CustomSelectV2 +} from "./chunk-T5V6LQ42.js"; +import { + apiFetch, + uiPatterns +} from "./chunk-VOGCL6QZ.js"; +import "./chunk-JSBRDJBE.js"; + +// frontend/js/vendor/nanoid.js +var a = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; +var nanoid = (e = 21) => { + let t = "", r = crypto.getRandomValues(new Uint8Array(e)); + for (let n = 0; n < e; n++) t += a[63 & r[n]]; + return t; +}; + +// frontend/js/vendor/marked.min.js +function L() { + return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null }; +} +var T = L(); +function Z(u3) { + T = u3; +} +var C = { exec: () => null }; +function k(u3, e = "") { + let t = typeof u3 == "string" ? u3 : u3.source, n = { replace: (r, i) => { + let s = typeof i == "string" ? i : i.source; + return s = s.replace(m.caret, "$1"), t = t.replace(r, s), n; + }, getRegex: () => new RegExp(t, e) }; + return n; +} +var me = (() => { + try { + return !!new RegExp("(?<=1)(?/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceTabs: /^\t+/, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] +\S/, listReplaceTask: /^\[[ xX]\] +/, listTaskCheckbox: /\[[ xX]\]/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^
    /i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (u3) => new RegExp(`^( {0,3}${u3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`), hrRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), fencesBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}(?:\`\`\`|~~~)`), headingBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}#`), htmlBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}<(?:[a-z].*>|!--)`, "i") }; +var xe = /^(?:[ \t]*(?:\n|$))+/; +var be = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/; +var Re = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/; +var I = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/; +var Te = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/; +var N = /(?:[*+-]|\d{1,9}[.)])/; +var re = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/; +var se = k(re).replace(/bull/g, N).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex(); +var Oe = k(re).replace(/bull/g, N).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(); +var Q = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/; +var we = /^[^\n]+/; +var F = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/; +var ye = k(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", F).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(); +var Pe = k(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, N).getRegex(); +var v = "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|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul"; +var j = /|$))/; +var Se = k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", j).replace("tag", v).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(); +var ie = k(Q).replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex(); +var $e = k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", ie).getRegex(); +var U = { blockquote: $e, code: be, def: ye, fences: Re, heading: Te, hr: I, html: Se, lheading: se, list: Pe, newline: xe, paragraph: ie, table: C, text: we }; +var te = k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex(); +var _e = { ...U, lheading: Oe, table: te, paragraph: k(Q).replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", te).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", ")|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex() }; +var Le = { ...U, html: k(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", j).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: C, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: k(Q).replace("hr", I).replace("heading", ` *#{1,6} *[^ +]`).replace("lheading", se).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() }; +var Me = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/; +var ze = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/; +var oe = /^( {2,}|\\)\n(?!\s*$)/; +var Ae = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\`+)[^`]+\k(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", me ? "(?`+)[^`]+\k(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex(); +var ue = /^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/; +var qe = k(ue, "u").replace(/punct/g, D).getRegex(); +var ve = k(ue, "u").replace(/punct/g, le).getRegex(); +var pe = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)"; +var De = k(pe, "gu").replace(/notPunctSpace/g, ae).replace(/punctSpace/g, K).replace(/punct/g, D).getRegex(); +var He = k(pe, "gu").replace(/notPunctSpace/g, Ee).replace(/punctSpace/g, Ie).replace(/punct/g, le).getRegex(); +var Ze = k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, ae).replace(/punctSpace/g, K).replace(/punct/g, D).getRegex(); +var Ge = k(/\\(punct)/, "gu").replace(/punct/g, D).getRegex(); +var Ne = k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(); +var Qe = k(j).replace("(?:-->|$)", "-->").getRegex(); +var Fe = k("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment", Qe).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(); +var q = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+[^`]*?`+(?!`)|[^\[\]\\`])*?/; +var je = k(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label", q).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(); +var ce = k(/^!?\[(label)\]\[(ref)\]/).replace("label", q).replace("ref", F).getRegex(); +var he = k(/^!?\[(ref)\](?:\[\])?/).replace("ref", F).getRegex(); +var Ue = k("reflink|nolink(?!\\()", "g").replace("reflink", ce).replace("nolink", he).getRegex(); +var ne = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/; +var W = { _backpedal: C, anyPunctuation: Ge, autolink: Ne, blockSkip: Be, br: oe, code: ze, del: C, emStrongLDelim: qe, emStrongRDelimAst: De, emStrongRDelimUnd: Ze, escape: Me, link: je, nolink: he, punctuation: Ce, reflink: ce, reflinkSearch: Ue, tag: Fe, text: Ae, url: C }; +var Ke = { ...W, link: k(/^!?\[(label)\]\((.*?)\)/).replace("label", q).getRegex(), reflink: k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", q).getRegex() }; +var G = { ...W, emStrongRDelimAst: He, emStrongLDelim: ve, url: k(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", ne).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: k(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\": ">", '"': """, "'": "'" }; +var ke = (u3) => Xe[u3]; +function w(u3, e) { + if (e) { + if (m.escapeTest.test(u3)) return u3.replace(m.escapeReplace, ke); + } else if (m.escapeTestNoEncode.test(u3)) return u3.replace(m.escapeReplaceNoEncode, ke); + return u3; +} +function X(u3) { + try { + u3 = encodeURI(u3).replace(m.percentDecode, "%"); + } catch { + return null; + } + return u3; +} +function J(u3, e) { + let t = u3.replace(m.findPipe, (i, s, a2) => { + let o = false, l = s; + for (; --l >= 0 && a2[l] === "\\"; ) o = !o; + return o ? "|" : " |"; + }), n = t.split(m.splitPipe), r = 0; + if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e); + else for (; n.length < e; ) n.push(""); + for (; r < n.length; r++) n[r] = n[r].trim().replace(m.slashPipe, "|"); + return n; +} +function z(u3, e, t) { + let n = u3.length; + if (n === 0) return ""; + let r = 0; + for (; r < n; ) { + let i = u3.charAt(n - r - 1); + if (i === e && !t) r++; + else if (i !== e && t) r++; + else break; + } + return u3.slice(0, n - r); +} +function de(u3, e) { + if (u3.indexOf(e[1]) === -1) return -1; + let t = 0; + for (let n = 0; n < u3.length; n++) if (u3[n] === "\\") n++; + else if (u3[n] === e[0]) t++; + else if (u3[n] === e[1] && (t--, t < 0)) return n; + return t > 0 ? -2 : -1; +} +function ge(u3, e, t, n, r) { + let i = e.href, s = e.title || null, a2 = u3[1].replace(r.other.outputLinkReplace, "$1"); + n.state.inLink = true; + let o = { type: u3[0].charAt(0) === "!" ? "image" : "link", raw: t, href: i, title: s, text: a2, tokens: n.inlineTokens(a2) }; + return n.state.inLink = false, o; +} +function Je(u3, e, t) { + let n = u3.match(t.other.indentCodeCompensation); + if (n === null) return e; + let r = n[1]; + return e.split(` +`).map((i) => { + let s = i.match(t.other.beginningSpace); + if (s === null) return i; + let [a2] = s; + return a2.length >= r.length ? i.slice(r.length) : i; + }).join(` +`); +} +var y = class { + options; + rules; + lexer; + constructor(e) { + this.options = e || T; + } + space(e) { + let t = this.rules.block.newline.exec(e); + if (t && t[0].length > 0) return { type: "space", raw: t[0] }; + } + code(e) { + let t = this.rules.block.code.exec(e); + if (t) { + let n = t[0].replace(this.rules.other.codeRemoveIndent, ""); + return { type: "code", raw: t[0], codeBlockStyle: "indented", text: this.options.pedantic ? n : z(n, ` +`) }; + } + } + fences(e) { + let t = this.rules.block.fences.exec(e); + if (t) { + let n = t[0], r = Je(n, t[3] || "", this.rules); + return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: r }; + } + } + heading(e) { + let t = this.rules.block.heading.exec(e); + if (t) { + let n = t[2].trim(); + if (this.rules.other.endingHash.test(n)) { + let r = z(n, "#"); + (this.options.pedantic || !r || this.rules.other.endingSpaceChar.test(r)) && (n = r.trim()); + } + return { type: "heading", raw: t[0], depth: t[1].length, text: n, tokens: this.lexer.inline(n) }; + } + } + hr(e) { + let t = this.rules.block.hr.exec(e); + if (t) return { type: "hr", raw: z(t[0], ` +`) }; + } + blockquote(e) { + let t = this.rules.block.blockquote.exec(e); + if (t) { + let n = z(t[0], ` +`).split(` +`), r = "", i = "", s = []; + for (; n.length > 0; ) { + let a2 = false, o = [], l; + for (l = 0; l < n.length; l++) if (this.rules.other.blockquoteStart.test(n[l])) o.push(n[l]), a2 = true; + else if (!a2) o.push(n[l]); + else break; + n = n.slice(l); + let p = o.join(` +`), c = p.replace(this.rules.other.blockquoteSetextReplace, ` + $1`).replace(this.rules.other.blockquoteSetextReplace2, ""); + r = r ? `${r} +${p}` : p, i = i ? `${i} +${c}` : c; + let g = this.lexer.state.top; + if (this.lexer.state.top = true, this.lexer.blockTokens(c, s, true), this.lexer.state.top = g, n.length === 0) break; + let h = s.at(-1); + if (h?.type === "code") break; + if (h?.type === "blockquote") { + let R = h, f = R.raw + ` +` + n.join(` +`), O = this.blockquote(f); + s[s.length - 1] = O, r = r.substring(0, r.length - R.raw.length) + O.raw, i = i.substring(0, i.length - R.text.length) + O.text; + break; + } else if (h?.type === "list") { + let R = h, f = R.raw + ` +` + n.join(` +`), O = this.list(f); + s[s.length - 1] = O, r = r.substring(0, r.length - h.raw.length) + O.raw, i = i.substring(0, i.length - R.raw.length) + O.raw, n = f.substring(s.at(-1).raw.length).split(` +`); + continue; + } + } + return { type: "blockquote", raw: r, tokens: s, text: i }; + } + } + list(e) { + let t = this.rules.block.list.exec(e); + if (t) { + let n = t[1].trim(), r = n.length > 1, i = { type: "list", raw: "", ordered: r, start: r ? +n.slice(0, -1) : "", loose: false, items: [] }; + n = r ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = r ? n : "[*+-]"); + let s = this.rules.other.listItemRegex(n), a2 = false; + for (; e; ) { + let l = false, p = "", c = ""; + if (!(t = s.exec(e)) || this.rules.block.hr.test(e)) break; + p = t[0], e = e.substring(p.length); + let g = t[2].split(` +`, 1)[0].replace(this.rules.other.listReplaceTabs, (O) => " ".repeat(3 * O.length)), h = e.split(` +`, 1)[0], R = !g.trim(), f = 0; + if (this.options.pedantic ? (f = 2, c = g.trimStart()) : R ? f = t[1].length + 1 : (f = t[2].search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, c = g.slice(f), f += t[1].length), R && this.rules.other.blankLine.test(h) && (p += h + ` +`, e = e.substring(h.length + 1), l = true), !l) { + let O = this.rules.other.nextBulletRegex(f), V = this.rules.other.hrRegex(f), Y = this.rules.other.fencesBeginRegex(f), ee = this.rules.other.headingBeginRegex(f), fe = this.rules.other.htmlBeginRegex(f); + for (; e; ) { + let H = e.split(` +`, 1)[0], A; + if (h = H, this.options.pedantic ? (h = h.replace(this.rules.other.listReplaceNesting, " "), A = h) : A = h.replace(this.rules.other.tabCharGlobal, " "), Y.test(h) || ee.test(h) || fe.test(h) || O.test(h) || V.test(h)) break; + if (A.search(this.rules.other.nonSpaceChar) >= f || !h.trim()) c += ` +` + A.slice(f); + else { + if (R || g.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || Y.test(g) || ee.test(g) || V.test(g)) break; + c += ` +` + h; + } + !R && !h.trim() && (R = true), p += H + ` +`, e = e.substring(H.length + 1), g = A.slice(f); + } + } + i.loose || (a2 ? i.loose = true : this.rules.other.doubleBlankLine.test(p) && (a2 = true)), i.items.push({ type: "list_item", raw: p, task: !!this.options.gfm && this.rules.other.listIsTask.test(c), loose: false, text: c, tokens: [] }), i.raw += p; + } + let o = i.items.at(-1); + if (o) o.raw = o.raw.trimEnd(), o.text = o.text.trimEnd(); + else return; + i.raw = i.raw.trimEnd(); + for (let l of i.items) { + if (this.lexer.state.top = false, l.tokens = this.lexer.blockTokens(l.text, []), l.task) { + if (l.text = l.text.replace(this.rules.other.listReplaceTask, ""), l.tokens[0]?.type === "text" || l.tokens[0]?.type === "paragraph") { + l.tokens[0].raw = l.tokens[0].raw.replace(this.rules.other.listReplaceTask, ""), l.tokens[0].text = l.tokens[0].text.replace(this.rules.other.listReplaceTask, ""); + for (let c = this.lexer.inlineQueue.length - 1; c >= 0; c--) if (this.rules.other.listIsTask.test(this.lexer.inlineQueue[c].src)) { + this.lexer.inlineQueue[c].src = this.lexer.inlineQueue[c].src.replace(this.rules.other.listReplaceTask, ""); + break; + } + } + let p = this.rules.other.listTaskCheckbox.exec(l.raw); + if (p) { + let c = { type: "checkbox", raw: p[0] + " ", checked: p[0] !== "[ ]" }; + l.checked = c.checked, i.loose ? l.tokens[0] && ["paragraph", "text"].includes(l.tokens[0].type) && "tokens" in l.tokens[0] && l.tokens[0].tokens ? (l.tokens[0].raw = c.raw + l.tokens[0].raw, l.tokens[0].text = c.raw + l.tokens[0].text, l.tokens[0].tokens.unshift(c)) : l.tokens.unshift({ type: "paragraph", raw: c.raw, text: c.raw, tokens: [c] }) : l.tokens.unshift(c); + } + } + if (!i.loose) { + let p = l.tokens.filter((g) => g.type === "space"), c = p.length > 0 && p.some((g) => this.rules.other.anyLine.test(g.raw)); + i.loose = c; + } + } + if (i.loose) for (let l of i.items) { + l.loose = true; + for (let p of l.tokens) p.type === "text" && (p.type = "paragraph"); + } + return i; + } + } + html(e) { + let t = this.rules.block.html.exec(e); + if (t) return { type: "html", block: true, raw: t[0], pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", text: t[0] }; + } + def(e) { + let t = this.rules.block.def.exec(e); + if (t) { + let n = t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), r = t[2] ? t[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", i = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3]; + return { type: "def", tag: n, raw: t[0], href: r, title: i }; + } + } + table(e) { + let t = this.rules.block.table.exec(e); + if (!t || !this.rules.other.tableDelimiter.test(t[2])) return; + let n = J(t[1]), r = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), i = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(` +`) : [], s = { type: "table", raw: t[0], header: [], align: [], rows: [] }; + if (n.length === r.length) { + for (let a2 of r) this.rules.other.tableAlignRight.test(a2) ? s.align.push("right") : this.rules.other.tableAlignCenter.test(a2) ? s.align.push("center") : this.rules.other.tableAlignLeft.test(a2) ? s.align.push("left") : s.align.push(null); + for (let a2 = 0; a2 < n.length; a2++) s.header.push({ text: n[a2], tokens: this.lexer.inline(n[a2]), header: true, align: s.align[a2] }); + for (let a2 of i) s.rows.push(J(a2, s.header.length).map((o, l) => ({ text: o, tokens: this.lexer.inline(o), header: false, align: s.align[l] }))); + return s; + } + } + lheading(e) { + let t = this.rules.block.lheading.exec(e); + if (t) return { type: "heading", raw: t[0], depth: t[2].charAt(0) === "=" ? 1 : 2, text: t[1], tokens: this.lexer.inline(t[1]) }; + } + paragraph(e) { + let t = this.rules.block.paragraph.exec(e); + if (t) { + let n = t[1].charAt(t[1].length - 1) === ` +` ? t[1].slice(0, -1) : t[1]; + return { type: "paragraph", raw: t[0], text: n, tokens: this.lexer.inline(n) }; + } + } + text(e) { + let t = this.rules.block.text.exec(e); + if (t) return { type: "text", raw: t[0], text: t[0], tokens: this.lexer.inline(t[0]) }; + } + escape(e) { + let t = this.rules.inline.escape.exec(e); + if (t) return { type: "escape", raw: t[0], text: t[1] }; + } + tag(e) { + let t = this.rules.inline.tag.exec(e); + if (t) return !this.lexer.state.inLink && this.rules.other.startATag.test(t[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t[0] }; + } + link(e) { + let t = this.rules.inline.link.exec(e); + if (t) { + let n = t[2].trim(); + if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n)) { + if (!this.rules.other.endAngleBracket.test(n)) return; + let s = z(n.slice(0, -1), "\\"); + if ((n.length - s.length) % 2 === 0) return; + } else { + let s = de(t[2], "()"); + if (s === -2) return; + if (s > -1) { + let o = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + s; + t[2] = t[2].substring(0, s), t[0] = t[0].substring(0, o).trim(), t[3] = ""; + } + } + let r = t[2], i = ""; + if (this.options.pedantic) { + let s = this.rules.other.pedanticHrefTitle.exec(r); + s && (r = s[1], i = s[3]); + } else i = t[3] ? t[3].slice(1, -1) : ""; + return r = r.trim(), this.rules.other.startAngleBracket.test(r) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(n) ? r = r.slice(1) : r = r.slice(1, -1)), ge(t, { href: r && r.replace(this.rules.inline.anyPunctuation, "$1"), title: i && i.replace(this.rules.inline.anyPunctuation, "$1") }, t[0], this.lexer, this.rules); + } + } + reflink(e, t) { + let n; + if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) { + let r = (n[2] || n[1]).replace(this.rules.other.multipleSpaceGlobal, " "), i = t[r.toLowerCase()]; + if (!i) { + let s = n[0].charAt(0); + return { type: "text", raw: s, text: s }; + } + return ge(n, i, n[0], this.lexer, this.rules); + } + } + emStrong(e, t, n = "") { + let r = this.rules.inline.emStrongLDelim.exec(e); + if (!r || r[3] && n.match(this.rules.other.unicodeAlphaNumeric)) return; + if (!(r[1] || r[2] || "") || !n || this.rules.inline.punctuation.exec(n)) { + let s = [...r[0]].length - 1, a2, o, l = s, p = 0, c = r[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd; + for (c.lastIndex = 0, t = t.slice(-1 * e.length + s); (r = c.exec(t)) != null; ) { + if (a2 = r[1] || r[2] || r[3] || r[4] || r[5] || r[6], !a2) continue; + if (o = [...a2].length, r[3] || r[4]) { + l += o; + continue; + } else if ((r[5] || r[6]) && s % 3 && !((s + o) % 3)) { + p += o; + continue; + } + if (l -= o, l > 0) continue; + o = Math.min(o, o + l + p); + let g = [...r[0]][0].length, h = e.slice(0, s + r.index + g + o); + if (Math.min(s, o) % 2) { + let f = h.slice(1, -1); + return { type: "em", raw: h, text: f, tokens: this.lexer.inlineTokens(f) }; + } + let R = h.slice(2, -2); + return { type: "strong", raw: h, text: R, tokens: this.lexer.inlineTokens(R) }; + } + } + } + codespan(e) { + let t = this.rules.inline.code.exec(e); + if (t) { + let n = t[2].replace(this.rules.other.newLineCharGlobal, " "), r = this.rules.other.nonSpaceChar.test(n), i = this.rules.other.startingSpaceChar.test(n) && this.rules.other.endingSpaceChar.test(n); + return r && i && (n = n.substring(1, n.length - 1)), { type: "codespan", raw: t[0], text: n }; + } + } + br(e) { + let t = this.rules.inline.br.exec(e); + if (t) return { type: "br", raw: t[0] }; + } + del(e) { + let t = this.rules.inline.del.exec(e); + if (t) return { type: "del", raw: t[0], text: t[2], tokens: this.lexer.inlineTokens(t[2]) }; + } + autolink(e) { + let t = this.rules.inline.autolink.exec(e); + if (t) { + let n, r; + return t[2] === "@" ? (n = t[1], r = "mailto:" + n) : (n = t[1], r = n), { type: "link", raw: t[0], text: n, href: r, tokens: [{ type: "text", raw: n, text: n }] }; + } + } + url(e) { + let t; + if (t = this.rules.inline.url.exec(e)) { + let n, r; + if (t[2] === "@") n = t[0], r = "mailto:" + n; + else { + let i; + do + i = t[0], t[0] = this.rules.inline._backpedal.exec(t[0])?.[0] ?? ""; + while (i !== t[0]); + n = t[0], t[1] === "www." ? r = "http://" + t[0] : r = t[0]; + } + return { type: "link", raw: t[0], text: n, href: r, tokens: [{ type: "text", raw: n, text: n }] }; + } + } + inlineText(e) { + let t = this.rules.inline.text.exec(e); + if (t) { + let n = this.lexer.state.inRawBlock; + return { type: "text", raw: t[0], text: t[0], escaped: n }; + } + } +}; +var x = class u { + tokens; + options; + state; + inlineQueue; + tokenizer; + constructor(e) { + this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || T, this.options.tokenizer = this.options.tokenizer || new y(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, top: true }; + let t = { other: m, block: E.normal, inline: M.normal }; + this.options.pedantic ? (t.block = E.pedantic, t.inline = M.pedantic) : this.options.gfm && (t.block = E.gfm, this.options.breaks ? t.inline = M.breaks : t.inline = M.gfm), this.tokenizer.rules = t; + } + static get rules() { + return { block: E, inline: M }; + } + static lex(e, t) { + return new u(t).lex(e); + } + static lexInline(e, t) { + return new u(t).inlineTokens(e); + } + lex(e) { + e = e.replace(m.carriageReturn, ` +`), this.blockTokens(e, this.tokens); + for (let t = 0; t < this.inlineQueue.length; t++) { + let n = this.inlineQueue[t]; + this.inlineTokens(n.src, n.tokens); + } + return this.inlineQueue = [], this.tokens; + } + blockTokens(e, t = [], n = false) { + for (this.options.pedantic && (e = e.replace(m.tabCharGlobal, " ").replace(m.spaceLine, "")); e; ) { + let r; + if (this.options.extensions?.block?.some((s) => (r = s.call({ lexer: this }, e, t)) ? (e = e.substring(r.raw.length), t.push(r), true) : false)) continue; + if (r = this.tokenizer.space(e)) { + e = e.substring(r.raw.length); + let s = t.at(-1); + r.raw.length === 1 && s !== void 0 ? s.raw += ` +` : t.push(r); + continue; + } + if (r = this.tokenizer.code(e)) { + e = e.substring(r.raw.length); + let s = t.at(-1); + s?.type === "paragraph" || s?.type === "text" ? (s.raw += (s.raw.endsWith(` +`) ? "" : ` +`) + r.raw, s.text += ` +` + r.text, this.inlineQueue.at(-1).src = s.text) : t.push(r); + continue; + } + if (r = this.tokenizer.fences(e)) { + e = e.substring(r.raw.length), t.push(r); + continue; + } + if (r = this.tokenizer.heading(e)) { + e = e.substring(r.raw.length), t.push(r); + continue; + } + if (r = this.tokenizer.hr(e)) { + e = e.substring(r.raw.length), t.push(r); + continue; + } + if (r = this.tokenizer.blockquote(e)) { + e = e.substring(r.raw.length), t.push(r); + continue; + } + if (r = this.tokenizer.list(e)) { + e = e.substring(r.raw.length), t.push(r); + continue; + } + if (r = this.tokenizer.html(e)) { + e = e.substring(r.raw.length), t.push(r); + continue; + } + if (r = this.tokenizer.def(e)) { + e = e.substring(r.raw.length); + let s = t.at(-1); + s?.type === "paragraph" || s?.type === "text" ? (s.raw += (s.raw.endsWith(` +`) ? "" : ` +`) + r.raw, s.text += ` +` + r.raw, this.inlineQueue.at(-1).src = s.text) : this.tokens.links[r.tag] || (this.tokens.links[r.tag] = { href: r.href, title: r.title }, t.push(r)); + continue; + } + if (r = this.tokenizer.table(e)) { + e = e.substring(r.raw.length), t.push(r); + continue; + } + if (r = this.tokenizer.lheading(e)) { + e = e.substring(r.raw.length), t.push(r); + continue; + } + let i = e; + if (this.options.extensions?.startBlock) { + let s = 1 / 0, a2 = e.slice(1), o; + this.options.extensions.startBlock.forEach((l) => { + o = l.call({ lexer: this }, a2), typeof o == "number" && o >= 0 && (s = Math.min(s, o)); + }), s < 1 / 0 && s >= 0 && (i = e.substring(0, s + 1)); + } + if (this.state.top && (r = this.tokenizer.paragraph(i))) { + let s = t.at(-1); + n && s?.type === "paragraph" ? (s.raw += (s.raw.endsWith(` +`) ? "" : ` +`) + r.raw, s.text += ` +` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = s.text) : t.push(r), n = i.length !== e.length, e = e.substring(r.raw.length); + continue; + } + if (r = this.tokenizer.text(e)) { + e = e.substring(r.raw.length); + let s = t.at(-1); + s?.type === "text" ? (s.raw += (s.raw.endsWith(` +`) ? "" : ` +`) + r.raw, s.text += ` +` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = s.text) : t.push(r); + continue; + } + if (e) { + let s = "Infinite loop on byte: " + e.charCodeAt(0); + if (this.options.silent) { + console.error(s); + break; + } else throw new Error(s); + } + } + return this.state.top = true, t; + } + inline(e, t = []) { + return this.inlineQueue.push({ src: e, tokens: t }), t; + } + inlineTokens(e, t = []) { + let n = e, r = null; + if (this.tokens.links) { + let o = Object.keys(this.tokens.links); + if (o.length > 0) for (; (r = this.tokenizer.rules.inline.reflinkSearch.exec(n)) != null; ) o.includes(r[0].slice(r[0].lastIndexOf("[") + 1, -1)) && (n = n.slice(0, r.index) + "[" + "a".repeat(r[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex)); + } + for (; (r = this.tokenizer.rules.inline.anyPunctuation.exec(n)) != null; ) n = n.slice(0, r.index) + "++" + n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex); + let i; + for (; (r = this.tokenizer.rules.inline.blockSkip.exec(n)) != null; ) i = r[2] ? r[2].length : 0, n = n.slice(0, r.index + i) + "[" + "a".repeat(r[0].length - i - 2) + "]" + n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n; + let s = false, a2 = ""; + for (; e; ) { + s || (a2 = ""), s = false; + let o; + if (this.options.extensions?.inline?.some((p) => (o = p.call({ lexer: this }, e, t)) ? (e = e.substring(o.raw.length), t.push(o), true) : false)) continue; + if (o = this.tokenizer.escape(e)) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + if (o = this.tokenizer.tag(e)) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + if (o = this.tokenizer.link(e)) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + if (o = this.tokenizer.reflink(e, this.tokens.links)) { + e = e.substring(o.raw.length); + let p = t.at(-1); + o.type === "text" && p?.type === "text" ? (p.raw += o.raw, p.text += o.text) : t.push(o); + continue; + } + if (o = this.tokenizer.emStrong(e, n, a2)) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + if (o = this.tokenizer.codespan(e)) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + if (o = this.tokenizer.br(e)) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + if (o = this.tokenizer.del(e)) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + if (o = this.tokenizer.autolink(e)) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + if (!this.state.inLink && (o = this.tokenizer.url(e))) { + e = e.substring(o.raw.length), t.push(o); + continue; + } + let l = e; + if (this.options.extensions?.startInline) { + let p = 1 / 0, c = e.slice(1), g; + this.options.extensions.startInline.forEach((h) => { + g = h.call({ lexer: this }, c), typeof g == "number" && g >= 0 && (p = Math.min(p, g)); + }), p < 1 / 0 && p >= 0 && (l = e.substring(0, p + 1)); + } + if (o = this.tokenizer.inlineText(l)) { + e = e.substring(o.raw.length), o.raw.slice(-1) !== "_" && (a2 = o.raw.slice(-1)), s = true; + let p = t.at(-1); + p?.type === "text" ? (p.raw += o.raw, p.text += o.text) : t.push(o); + continue; + } + if (e) { + let p = "Infinite loop on byte: " + e.charCodeAt(0); + if (this.options.silent) { + console.error(p); + break; + } else throw new Error(p); + } + } + return t; + } +}; +var P = class { + options; + parser; + constructor(e) { + this.options = e || T; + } + space(e) { + return ""; + } + code({ text: e, lang: t, escaped: n }) { + let r = (t || "").match(m.notSpaceStart)?.[0], i = e.replace(m.endingNewline, "") + ` +`; + return r ? '
    ' + (n ? i : w(i, true)) + `
    +` : "
    " + (n ? i : w(i, true)) + `
    +`; + } + blockquote({ tokens: e }) { + return `
    +${this.parser.parse(e)}
    +`; + } + html({ text: e }) { + return e; + } + def(e) { + return ""; + } + heading({ tokens: e, depth: t }) { + return `${this.parser.parseInline(e)} +`; + } + hr(e) { + return `
    +`; + } + list(e) { + let t = e.ordered, n = e.start, r = ""; + for (let a2 = 0; a2 < e.items.length; a2++) { + let o = e.items[a2]; + r += this.listitem(o); + } + let i = t ? "ol" : "ul", s = t && n !== 1 ? ' start="' + n + '"' : ""; + return "<" + i + s + `> +` + r + " +`; + } + listitem(e) { + return `
  • ${this.parser.parse(e.tokens)}
  • +`; + } + checkbox({ checked: e }) { + return " '; + } + paragraph({ tokens: e }) { + return `

    ${this.parser.parseInline(e)}

    +`; + } + table(e) { + let t = "", n = ""; + for (let i = 0; i < e.header.length; i++) n += this.tablecell(e.header[i]); + t += this.tablerow({ text: n }); + let r = ""; + for (let i = 0; i < e.rows.length; i++) { + let s = e.rows[i]; + n = ""; + for (let a2 = 0; a2 < s.length; a2++) n += this.tablecell(s[a2]); + r += this.tablerow({ text: n }); + } + return r && (r = `${r}`), ` + +` + t + ` +` + r + `
    +`; + } + tablerow({ text: e }) { + return ` +${e} +`; + } + tablecell(e) { + let t = this.parser.parseInline(e.tokens), n = e.header ? "th" : "td"; + return (e.align ? `<${n} align="${e.align}">` : `<${n}>`) + t + ` +`; + } + strong({ tokens: e }) { + return `${this.parser.parseInline(e)}`; + } + em({ tokens: e }) { + return `${this.parser.parseInline(e)}`; + } + codespan({ text: e }) { + return `${w(e, true)}`; + } + br(e) { + return "
    "; + } + del({ tokens: e }) { + return `${this.parser.parseInline(e)}`; + } + link({ href: e, title: t, tokens: n }) { + let r = this.parser.parseInline(n), i = X(e); + if (i === null) return r; + e = i; + let s = '
    ", s; + } + image({ href: e, title: t, text: n, tokens: r }) { + r && (n = this.parser.parseInline(r, this.parser.textRenderer)); + let i = X(e); + if (i === null) return w(n); + e = i; + let s = `${n} { + let a2 = i[s].flat(1 / 0); + n = n.concat(this.walkTokens(a2, t)); + }) : i.tokens && (n = n.concat(this.walkTokens(i.tokens, t))); + } + } + return n; + } + use(...e) { + let t = this.defaults.extensions || { renderers: {}, childTokens: {} }; + return e.forEach((n) => { + let r = { ...n }; + if (r.async = this.defaults.async || r.async || false, n.extensions && (n.extensions.forEach((i) => { + if (!i.name) throw new Error("extension name required"); + if ("renderer" in i) { + let s = t.renderers[i.name]; + s ? t.renderers[i.name] = function(...a2) { + let o = i.renderer.apply(this, a2); + return o === false && (o = s.apply(this, a2)), o; + } : t.renderers[i.name] = i.renderer; + } + if ("tokenizer" in i) { + if (!i.level || i.level !== "block" && i.level !== "inline") throw new Error("extension level must be 'block' or 'inline'"); + let s = t[i.level]; + s ? s.unshift(i.tokenizer) : t[i.level] = [i.tokenizer], i.start && (i.level === "block" ? t.startBlock ? t.startBlock.push(i.start) : t.startBlock = [i.start] : i.level === "inline" && (t.startInline ? t.startInline.push(i.start) : t.startInline = [i.start])); + } + "childTokens" in i && i.childTokens && (t.childTokens[i.name] = i.childTokens); + }), r.extensions = t), n.renderer) { + let i = this.defaults.renderer || new P(this.defaults); + for (let s in n.renderer) { + if (!(s in i)) throw new Error(`renderer '${s}' does not exist`); + if (["options", "parser"].includes(s)) continue; + let a2 = s, o = n.renderer[a2], l = i[a2]; + i[a2] = (...p) => { + let c = o.apply(i, p); + return c === false && (c = l.apply(i, p)), c || ""; + }; + } + r.renderer = i; + } + if (n.tokenizer) { + let i = this.defaults.tokenizer || new y(this.defaults); + for (let s in n.tokenizer) { + if (!(s in i)) throw new Error(`tokenizer '${s}' does not exist`); + if (["options", "rules", "lexer"].includes(s)) continue; + let a2 = s, o = n.tokenizer[a2], l = i[a2]; + i[a2] = (...p) => { + let c = o.apply(i, p); + return c === false && (c = l.apply(i, p)), c; + }; + } + r.tokenizer = i; + } + if (n.hooks) { + let i = this.defaults.hooks || new S(); + for (let s in n.hooks) { + if (!(s in i)) throw new Error(`hook '${s}' does not exist`); + if (["options", "block"].includes(s)) continue; + let a2 = s, o = n.hooks[a2], l = i[a2]; + S.passThroughHooks.has(s) ? i[a2] = (p) => { + if (this.defaults.async && S.passThroughHooksRespectAsync.has(s)) return (async () => { + let g = await o.call(i, p); + return l.call(i, g); + })(); + let c = o.call(i, p); + return l.call(i, c); + } : i[a2] = (...p) => { + if (this.defaults.async) return (async () => { + let g = await o.apply(i, p); + return g === false && (g = await l.apply(i, p)), g; + })(); + let c = o.apply(i, p); + return c === false && (c = l.apply(i, p)), c; + }; + } + r.hooks = i; + } + if (n.walkTokens) { + let i = this.defaults.walkTokens, s = n.walkTokens; + r.walkTokens = function(a2) { + let o = []; + return o.push(s.call(this, a2)), i && (o = o.concat(i.call(this, a2))), o; + }; + } + this.defaults = { ...this.defaults, ...r }; + }), this; + } + setOptions(e) { + return this.defaults = { ...this.defaults, ...e }, this; + } + lexer(e, t) { + return x.lex(e, t ?? this.defaults); + } + parser(e, t) { + return b.parse(e, t ?? this.defaults); + } + parseMarkdown(e) { + return (n, r) => { + let i = { ...r }, s = { ...this.defaults, ...i }, a2 = this.onError(!!s.silent, !!s.async); + if (this.defaults.async === true && i.async === false) return a2(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.")); + if (typeof n > "u" || n === null) return a2(new Error("marked(): input parameter is undefined or null")); + if (typeof n != "string") return a2(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected")); + if (s.hooks && (s.hooks.options = s, s.hooks.block = e), s.async) return (async () => { + let o = s.hooks ? await s.hooks.preprocess(n) : n, p = await (s.hooks ? await s.hooks.provideLexer() : e ? x.lex : x.lexInline)(o, s), c = s.hooks ? await s.hooks.processAllTokens(p) : p; + s.walkTokens && await Promise.all(this.walkTokens(c, s.walkTokens)); + let h = await (s.hooks ? await s.hooks.provideParser() : e ? b.parse : b.parseInline)(c, s); + return s.hooks ? await s.hooks.postprocess(h) : h; + })().catch(a2); + try { + s.hooks && (n = s.hooks.preprocess(n)); + let l = (s.hooks ? s.hooks.provideLexer() : e ? x.lex : x.lexInline)(n, s); + s.hooks && (l = s.hooks.processAllTokens(l)), s.walkTokens && this.walkTokens(l, s.walkTokens); + let c = (s.hooks ? s.hooks.provideParser() : e ? b.parse : b.parseInline)(l, s); + return s.hooks && (c = s.hooks.postprocess(c)), c; + } catch (o) { + return a2(o); + } + }; + } + onError(e, t) { + return (n) => { + if (n.message += ` +Please report this to https://github.com/markedjs/marked.`, e) { + let r = "

    An error occurred:

    " + w(n.message + "", true) + "
    "; + return t ? Promise.resolve(r) : r; + } + if (t) return Promise.reject(n); + throw n; + }; + } +}; +var _ = new B(); +function d(u3, e) { + return _.parse(u3, e); +} +d.options = d.setOptions = function(u3) { + return _.setOptions(u3), d.defaults = _.defaults, Z(d.defaults), d; +}; +d.getDefaults = L; +d.defaults = T; +d.use = function(...u3) { + return _.use(...u3), d.defaults = _.defaults, Z(d.defaults), d; +}; +d.walkTokens = function(u3, e) { + return _.walkTokens(u3, e); +}; +d.parseInline = _.parseInline; +d.Parser = b; +d.parser = b.parse; +d.Renderer = P; +d.TextRenderer = $; +d.Lexer = x; +d.lexer = x.lex; +d.Tokenizer = y; +d.Hooks = S; +d.parse = d; +var Dt = d.options; +var Ht = d.setOptions; +var Zt = d.use; +var Gt = d.walkTokens; +var Nt = d.parseInline; +var Ft = b.parse; +var jt = x.lex; + +// frontend/js/pages/chat/SessionManager.js +import { nanoid as nanoid2 } from "https://cdn.jsdelivr.net/npm/nanoid/nanoid.js"; +var LOCAL_STORAGE_KEY = "gemini_chat_state"; +var SessionManager = class { + constructor() { + this.state = null; + } + /** + * Initializes the manager by loading state from localStorage or creating a default state. + */ + init() { + this._loadState(); + } + // --- Public API for state access --- + getSessions() { + return this.state.sessions; + } + getCurrentSessionId() { + return this.state.currentSessionId; + } + getCurrentSession() { + return this.state.sessions.find((s) => s.id === this.state.currentSessionId); + } + // --- Public API for state mutation --- + /** + * Creates a new, empty session and sets it as the current one. + */ + createSession() { + const newSessionId = nanoid2(); + const newSession = { + id: newSessionId, + name: "\u65B0\u4F1A\u8BDD", + systemPrompt: "", + messages: [], + modelConfig: { model: "gemini-2.0-flash-lite" }, + params: { temperature: 0.7 } + }; + this.state.sessions.unshift(newSession); + this.state.currentSessionId = newSessionId; + this._saveState(); + } + /** + * Switches the current session to the one with the given ID. + * @param {string} sessionId The ID of the session to switch to. + */ + switchSession(sessionId) { + if (this.state.currentSessionId === sessionId) return; + this.state.currentSessionId = sessionId; + this._saveState(); + } + /** + * Deletes a session by its ID. + * @param {string} sessionId The ID of the session to delete. + */ + deleteSession(sessionId) { + this.state.sessions = this.state.sessions.filter((s) => s.id !== sessionId); + if (this.state.currentSessionId === sessionId) { + this.state.currentSessionId = this.state.sessions[0]?.id || null; + if (!this.state.currentSessionId) { + this._createInitialState(); + } + } + this._saveState(); + } + /** + * [NEW] Clears all messages from the currently active session. + */ + clearCurrentSession() { + const currentSession = this.getCurrentSession(); + if (currentSession) { + currentSession.messages = []; + this._saveState(); + } + } + /** + * Adds a message to the current session and updates the session name if it's the first message. + * @param {object} message The message object to add. + * @returns {object} The session that was updated. + */ + addMessage(message) { + const currentSession = this.getCurrentSession(); + if (currentSession) { + if (currentSession.messages.length === 0 && message.role === "user") { + currentSession.name = message.content.substring(0, 30); + } + currentSession.messages.push(message); + this._saveState(); + return currentSession; + } + return null; + } + deleteMessage(messageId) { + const currentSession = this.getCurrentSession(); + if (currentSession) { + const messageIndex = currentSession.messages.findIndex((m2) => m2.id === messageId); + if (messageIndex > -1) { + currentSession.messages.splice(messageIndex, 1); + this._saveState(); + console.log(`Message ${messageId} deleted.`); + } + } + } + truncateMessagesAfter(messageId) { + const currentSession = this.getCurrentSession(); + if (currentSession) { + const messageIndex = currentSession.messages.findIndex((m2) => m2.id === messageId); + if (messageIndex > -1 && messageIndex < currentSession.messages.length - 1) { + currentSession.messages.splice(messageIndex + 1); + this._saveState(); + console.log(`Truncated messages after ${messageId}.`); + } + } + } + // --- Private persistence methods --- + _saveState() { + try { + localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(this.state)); + } catch (error) { + console.error("Failed to save session state:", error); + } + } + _loadState() { + try { + const stateString = localStorage.getItem(LOCAL_STORAGE_KEY); + if (stateString) { + this.state = JSON.parse(stateString); + } else { + this._createInitialState(); + } + } catch (error) { + console.error("Failed to load session state, creating initial state:", error); + this._createInitialState(); + } + } + _createInitialState() { + const initialSessionId = nanoid2(); + this.state = { + sessions: [{ + id: initialSessionId, + name: "\u65B0\u4F1A\u8BDD", + systemPrompt: "", + messages: [], + modelConfig: { model: "gemini-2.0-flash-lite" }, + params: { temperature: 0.7 } + }], + currentSessionId: initialSessionId, + settings: {} + }; + this._saveState(); + } +}; + +// frontend/js/pages/chat/chatSettings.js +var ChatSettings = class { + constructor(elements) { + this.elements = {}; + this.elements.root = elements; + this._initScopedDOMElements(); + this.elements.quickSettingsPanel.style.gridTemplateRows = "0fr"; + this.elements.sessionParamsPanel.style.gridTemplateRows = "0fr"; + } + // [NEW] A dedicated method to find elements within their specific panels + _initScopedDOMElements() { + this.elements.quickSettingsPanel = this.elements.root.quickSettingsPanel; + this.elements.sessionParamsPanel = this.elements.root.sessionParamsPanel; + this.elements.toggleQuickSettingsBtn = this.elements.root.toggleQuickSettingsBtn; + this.elements.toggleSessionParamsBtn = this.elements.root.toggleSessionParamsBtn; + this.elements.btnGroups = this.elements.quickSettingsPanel.querySelectorAll(".btn-group"); + this.elements.directRoutingOptions = this.elements.quickSettingsPanel.querySelector("#direct-routing-options"); + this.elements.temperatureSlider = this.elements.sessionParamsPanel.querySelector("#temperature-slider"); + this.elements.temperatureValue = this.elements.sessionParamsPanel.querySelector("#temperature-value"); + this.elements.contextSlider = this.elements.sessionParamsPanel.querySelector("#context-slider"); + this.elements.contextValue = this.elements.sessionParamsPanel.querySelector("#context-value"); + } + init() { + if (!this.elements.toggleQuickSettingsBtn) { + console.warn("ChatSettings: Aborting initialization, required elements not found."); + return; + } + this._initPanelToggleListeners(); + this._initButtonGroupListeners(); + this._initSliderListeners(); + } + _initPanelToggleListeners() { + this.elements.toggleQuickSettingsBtn.addEventListener( + "click", + () => this._togglePanel(this.elements.quickSettingsPanel, this.elements.toggleQuickSettingsBtn) + ); + this.elements.toggleSessionParamsBtn.addEventListener( + "click", + () => this._togglePanel(this.elements.sessionParamsPanel, this.elements.toggleSessionParamsBtn) + ); + } + _initButtonGroupListeners() { + this.elements.btnGroups.forEach((group) => { + group.addEventListener("click", (e) => { + const button = e.target.closest(".btn-group-item"); + if (!button) return; + group.querySelectorAll(".btn-group-item").forEach((btn) => btn.removeAttribute("data-active")); + button.setAttribute("data-active", "true"); + if (button.dataset.group === "routing-mode") { + this._handleRoutingModeChange(button.dataset.value); + } + }); + }); + } + _initSliderListeners() { + if (this.elements.temperatureSlider) { + this.elements.temperatureSlider.addEventListener("input", () => { + this.elements.temperatureValue.textContent = parseFloat(this.elements.temperatureSlider.value).toFixed(1); + }); + } + if (this.elements.contextSlider) { + this.elements.contextSlider.addEventListener("input", () => { + this.elements.contextValue.textContent = `${this.elements.contextSlider.value}k`; + }); + } + } + _handleRoutingModeChange(selectedValue) { + if (this.elements.directRoutingOptions) { + if (selectedValue === "direct") { + this.elements.directRoutingOptions.classList.remove("hidden"); + } else { + this.elements.directRoutingOptions.classList.add("hidden"); + } + } + } + _togglePanel(panel, button) { + const isExpanded = panel.hasAttribute("data-expanded"); + this.elements.quickSettingsPanel.removeAttribute("data-expanded"); + this.elements.sessionParamsPanel.removeAttribute("data-expanded"); + this.elements.toggleQuickSettingsBtn.removeAttribute("data-active"); + this.elements.toggleSessionParamsBtn.removeAttribute("data-active"); + this.elements.quickSettingsPanel.style.gridTemplateRows = "0fr"; + this.elements.sessionParamsPanel.style.gridTemplateRows = "0fr"; + if (!isExpanded) { + panel.setAttribute("data-expanded", "true"); + button.setAttribute("data-active", "true"); + panel.style.gridTemplateRows = "1fr"; + } + } +}; + +// frontend/js/pages/chat/index.js +d.use({ breaks: true, gfm: true }); +function getCookie(name) { + let cookieValue = null; + if (document.cookie && document.cookie !== "") { + const cookies = document.cookie.split(";"); + for (let i = 0; i < cookies.length; i++) { + const cookie = cookies[i].trim(); + if (cookie.substring(0, name.length + 1) === name + "=") { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} +var ChatPage = class { + constructor() { + this.sessionManager = new SessionManager(); + this.isStreaming = false; + this.elements = {}; + this.initialized = false; + this.searchTerm = ""; + this.settingsManager = null; + } + init() { + if (!document.querySelector('[data-page-id="chat"]')) { + return; + } + this.sessionManager.init(); + this.initialized = true; + this._initDOMElements(); + this._initComponents(); + this._initEventListeners(); + this._render(); + console.log("ChatPage initialized. Session management is delegated.", this.sessionManager.state); + } + _initDOMElements() { + this.elements.chatScrollContainer = document.getElementById("chat-scroll-container"); + this.elements.chatMessagesContainer = document.getElementById("chat-messages-container"); + this.elements.messageForm = document.getElementById("message-form"); + this.elements.messageInput = document.getElementById("message-input"); + this.elements.sendBtn = document.getElementById("send-btn"); + this.elements.newSessionBtn = document.getElementById("new-session-btn"); + this.elements.sessionListContainer = document.getElementById("session-list-container"); + this.elements.chatHeaderTitle = document.querySelector(".chat-header-title"); + this.elements.clearSessionBtn = document.getElementById("clear-session-btn"); + this.elements.sessionSearchInput = document.getElementById("session-search-input"); + this.elements.toggleQuickSettingsBtn = document.getElementById("toggle-quick-settings"); + this.elements.toggleSessionParamsBtn = document.getElementById("toggle-session-params"); + this.elements.quickSettingsPanel = document.getElementById("quick-settings-panel"); + this.elements.sessionParamsPanel = document.getElementById("session-params-panel"); + this.elements.directRoutingOptions = document.getElementById("direct-routing-options"); + this.elements.btnGroups = document.querySelectorAll(".btn-group"); + this.elements.temperatureSlider = document.getElementById("temperature-slider"); + this.elements.temperatureValue = document.getElementById("temperature-value"); + this.elements.contextSlider = document.getElementById("context-slider"); + this.elements.contextValue = document.getElementById("context-value"); + this.elements.groupSelectContainer = document.getElementById("group-select-container"); + } + // [NEW] A dedicated method for initializing complex UI components + _initComponents() { + if (this.elements.groupSelectContainer) { + new CustomSelectV2(this.elements.groupSelectContainer); + } + } + _initEventListeners() { + this.settingsManager = new ChatSettings(this.elements); + this.settingsManager.init(); + this.elements.messageForm.addEventListener("submit", (e) => { + e.preventDefault(); + this._handleSendMessage(); + }); + this.elements.messageInput.addEventListener("keydown", (e) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + this._handleSendMessage(); + } + }); + this.elements.messageInput.addEventListener("input", () => this._autoResizeTextarea()); + this.elements.newSessionBtn.addEventListener("click", () => { + this.sessionManager.createSession(); + this._render(); + this.elements.messageInput.focus(); + }); + this.elements.sessionListContainer.addEventListener("click", (e) => { + const sessionItem = e.target.closest("[data-session-id]"); + const deleteBtn = e.target.closest(".delete-session-btn"); + if (deleteBtn) { + e.preventDefault(); + const sessionId = deleteBtn.closest("[data-session-id]").dataset.sessionId; + this._handleDeleteSession(sessionId); + } else if (sessionItem) { + e.preventDefault(); + const sessionId = sessionItem.dataset.sessionId; + this.sessionManager.switchSession(sessionId); + this._render(); + this.elements.messageInput.focus(); + } + }); + this.elements.clearSessionBtn.addEventListener("click", () => this._handleClearSession()); + this.elements.sessionSearchInput.addEventListener("input", (e) => { + this.searchTerm = e.target.value.trim(); + this._renderSessionList(); + }); + this.elements.chatMessagesContainer.addEventListener("click", (e) => { + const messageElement = e.target.closest("[data-message-id]"); + if (!messageElement) return; + const messageId = messageElement.dataset.messageId; + const copyBtn = e.target.closest(".action-copy"); + const deleteBtn = e.target.closest(".action-delete"); + const retryBtn = e.target.closest(".action-retry"); + if (copyBtn) { + this._handleCopyMessage(messageId); + } else if (deleteBtn) { + this._handleDeleteMessage(messageId, e.target); + } else if (retryBtn) { + this._handleRetryMessage(messageId); + } + }); + } + _handleCopyMessage(messageId) { + const currentSession = this.sessionManager.getCurrentSession(); + if (!currentSession) return; + const message = currentSession.messages.find((m2) => m2.id === messageId); + if (!message || !message.content) { + console.error("Message content not found for copying."); + return; + } + let textToCopy = message.content; + if (textToCopy.includes("<") && textToCopy.includes(">")) { + const tempDiv = document.createElement("div"); + tempDiv.innerHTML = textToCopy; + textToCopy = tempDiv.textContent || tempDiv.innerText || ""; + } + navigator.clipboard.writeText(textToCopy).then(() => { + Swal.fire({ + toast: true, + position: "top-end", + icon: "success", + title: "\u5DF2\u590D\u5236", + showConfirmButton: false, + timer: 1500, + customClass: { + popup: `${document.documentElement.classList.contains("dark") ? "swal2-dark" : ""}` + } + }); + }).catch((err) => { + console.error("Failed to copy text: ", err); + Swal.fire({ + toast: true, + position: "top-end", + icon: "error", + title: "\u590D\u5236\u5931\u8D25", + showConfirmButton: false, + timer: 1500, + customClass: { + popup: `${document.documentElement.classList.contains("dark") ? "swal2-dark" : ""}` + } + }); + }); + } + _handleDeleteMessage(messageId, targetElement) { + const existingPopover = document.getElementById("delete-confirmation-popover"); + if (existingPopover) { + existingPopover.remove(); + } + const popover = document.createElement("div"); + popover.id = "delete-confirmation-popover"; + popover.className = "absolute z-50 p-3 w-45 border border-border rounded-md shadow-lg bg-background text-popover-foreground flex flex-col items-center"; + popover.innerHTML = ` +
    + +

    \u786E\u8BA4\u5220\u9664\u6B64\u6D88\u606F\u5417?

    +
    +
    + + +
    + `; + document.body.appendChild(popover); + const iconRect = targetElement.closest("button").getBoundingClientRect(); + const popoverRect = popover.getBoundingClientRect(); + popover.style.top = `${window.scrollY + iconRect.top - popoverRect.height - 8}px`; + popover.style.left = `${window.scrollX + iconRect.left + iconRect.width / 2 - popoverRect.width / 2}px`; + const outsideClickListener = (event) => { + if (!popover.contains(event.target) && event.target !== targetElement) { + popover.remove(); + document.removeEventListener("click", outsideClickListener); + } + }; + setTimeout(() => document.addEventListener("click", outsideClickListener), 0); + popover.querySelector(".popover-confirm").addEventListener("click", () => { + this.sessionManager.deleteMessage(messageId); + this._renderChatMessages(); + this._renderSessionList(); + popover.remove(); + document.removeEventListener("click", outsideClickListener); + }); + popover.querySelector(".popover-cancel").addEventListener("click", () => { + popover.remove(); + document.removeEventListener("click", outsideClickListener); + }); + } + _handleRetryMessage(messageId) { + if (this.isStreaming) return; + const currentSession = this.sessionManager.getCurrentSession(); + if (!currentSession) return; + const message = currentSession.messages.find((m2) => m2.id === messageId); + if (!message) return; + if (message.role === "user") { + this.sessionManager.truncateMessagesAfter(messageId); + } else if (message.role === "assistant") { + this.sessionManager.deleteMessage(messageId); + } + this._renderChatMessages(); + this._renderSessionList(); + this._getAssistantResponse(); + } + _autoResizeTextarea() { + const el = this.elements.messageInput; + el.style.height = "auto"; + el.style.height = el.scrollHeight + "px"; + } + _handleSendMessage() { + if (this.isStreaming) return; + const content = this.elements.messageInput.value.trim(); + if (!content) return; + const userMessage = { id: nanoid(), role: "user", content }; + this.sessionManager.addMessage(userMessage); + this._renderChatMessages(); + this._renderSessionList(); + this.elements.messageInput.value = ""; + this._autoResizeTextarea(); + this.elements.messageInput.focus(); + this._getAssistantResponse(); + } + async _getAssistantResponse() { + this.isStreaming = true; + this._setLoadingState(true); + const currentSession = this.sessionManager.getCurrentSession(); + const assistantMessageId = nanoid(); + let finalAssistantMessage = { id: assistantMessageId, role: "assistant", content: "" }; + const placeholderHtml = ` +
    + + + +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    `; + this.elements.chatMessagesContainer.insertAdjacentHTML("beforeend", placeholderHtml); + this._scrollToBottom(); + const assistantMessageContentEl = this.elements.chatMessagesContainer.querySelector(`[data-message-id="${assistantMessageId}"] .message-content`); + try { + const token = getCookie("gemini_admin_session"); + const headers = { "Authorization": `Bearer ${token}` }; + const response = await apiFetch("/v1/chat/completions", { + method: "POST", + headers, + body: JSON.stringify({ + model: currentSession.modelConfig.model, + messages: currentSession.messages.filter((m2) => m2.content).map(({ role, content }) => ({ role, content })), + stream: true + }) + }); + if (!response.body) throw new Error("Response body is null."); + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + while (true) { + const { value, done } = await reader.read(); + if (done) break; + const chunk = decoder.decode(value); + const lines = chunk.split("\n").filter((line) => line.trim().startsWith("data:")); + for (const line of lines) { + const dataStr = line.replace(/^data: /, "").trim(); + if (dataStr !== "[DONE]") { + try { + const data = JSON.parse(dataStr); + const deltaContent = data.choices[0]?.delta?.content; + if (deltaContent) { + finalAssistantMessage.content += deltaContent; + assistantMessageContentEl.innerHTML = d.parse(finalAssistantMessage.content); + this._scrollToBottom(); + } + } catch (e) { + } + } + } + } + } catch (error) { + console.error("Fetch stream error:", error); + const errorMessage = error.rawMessageFromServer || error.message; + finalAssistantMessage.content = `\u8BF7\u6C42\u5931\u8D25: ${errorMessage}`; + } finally { + this.sessionManager.addMessage(finalAssistantMessage); + this._renderChatMessages(); + this._renderSessionList(); + this.isStreaming = false; + this._setLoadingState(false); + this.elements.messageInput.focus(); + } + } + _renderMessage(message, replace = false, isLastMessage = false) { + let contentHtml; + if (message.role === "user") { + const escapedContent = message.content.replace(//g, ">"); + contentHtml = `

    ${escapedContent.replace(/\n/g, "
    ")}

    `; + } else { + const isErrorHtml = message.content && message.content.includes(''); + contentHtml = isErrorHtml ? `
    ${message.content}
    ` : `
    ${d.parse(message.content || "")}
    `; + } + let actionsHtml = ""; + let retryButton = ""; + if (message.role === "user") { + retryButton = ` + `; + } else if (message.role === "assistant" && isLastMessage) { + retryButton = ` + `; + } + const toolbarBaseClasses = "message-actions flex items-center gap-1 transition-opacity duration-200"; + const toolbarPositionClass = isLastMessage ? "mt-2" : "absolute bottom-2.5 right-2.5"; + const visibilityClass = isLastMessage ? "" : "opacity-0 group-hover:opacity-100"; + actionsHtml = ` +
    + ${retryButton} + + +
    + `; + const messageBubbleClasses = `relative group rounded-lg p-5 ${message.role === "user" ? "bg-muted" : "bg-primary/10 border/20"}`; + const messageHtml = ` +
    + + + +
    +
    + ${contentHtml} + ${actionsHtml} +
    +
    +
    `; + const existingElement = this.elements.chatMessagesContainer.querySelector(`[data-message-id="${message.id}"]`); + if (replace && existingElement) { + existingElement.outerHTML = messageHtml; + } else if (!existingElement) { + this.elements.chatMessagesContainer.insertAdjacentHTML("beforeend", messageHtml); + } + if (!replace) { + this._scrollToBottom(); + } + } + _scrollToBottom() { + this.elements.chatScrollContainer.scrollTop = this.elements.chatScrollContainer.scrollHeight; + } + _render() { + this._renderSessionList(); + this._renderChatMessages(); + this._renderChatHeader(); + } + _renderSessionList() { + let sessions = this.sessionManager.getSessions(); + const currentSessionId = this.sessionManager.getCurrentSessionId(); + if (this.searchTerm) { + const lowerCaseSearchTerm = this.searchTerm.toLowerCase(); + sessions = sessions.filter((session) => { + const titleMatch = session.name.toLowerCase().includes(lowerCaseSearchTerm); + const messageMatch = session.messages.some( + (message) => message.content && message.content.toLowerCase().includes(lowerCaseSearchTerm) + ); + return titleMatch || messageMatch; + }); + } + this.elements.sessionListContainer.innerHTML = sessions.map((session) => { + const isActive = session.id === currentSessionId; + const lastMessage = session.messages.length > 0 ? session.messages[session.messages.length - 1].content : "\u65B0\u4F1A\u8BDD"; + return ` +
    + `; + }).join(""); + } + _renderChatMessages() { + this.elements.chatMessagesContainer.innerHTML = ""; + const currentSession = this.sessionManager.getCurrentSession(); + if (currentSession) { + const messages = currentSession.messages; + const lastMessageIndex = messages.length > 0 ? messages.length - 1 : -1; + messages.forEach((message, index) => { + const isLastMessage = index === lastMessageIndex; + this._renderMessage(message, false, isLastMessage); + }); + } + } + _renderChatHeader() { + const currentSession = this.sessionManager.getCurrentSession(); + if (currentSession && this.elements.chatHeaderTitle) { + this.elements.chatHeaderTitle.textContent = currentSession.name; + } + } + _setLoadingState(isLoading) { + this.elements.messageInput.disabled = isLoading; + this.elements.sendBtn.disabled = isLoading; + if (isLoading) { + uiPatterns.setButtonLoading(this.elements.sendBtn); + } else { + uiPatterns.clearButtonLoading(this.elements.sendBtn); + } + } + _handleClearSession() { + Swal.fire({ + width: "22rem", + backdrop: `rgba(0,0,0,0.5)`, + heightAuto: false, + customClass: { popup: `swal2-custom-style ${document.documentElement.classList.contains("dark") ? "swal2-dark" : ""}` }, + title: "\u786E\u5B9A\u8981\u6E05\u7A7A\u4F1A\u8BDD\u5417\uFF1F", + text: "\u5F53\u524D\u4F1A\u8BDD\u7684\u6240\u6709\u804A\u5929\u8BB0\u5F55\u5C06\u88AB\u5220\u9664\uFF0C\u4F46\u4F1A\u8BDD\u672C\u8EAB\u4F1A\u4FDD\u7559\u3002", + showCancelButton: true, + confirmButtonText: "\u786E\u8BA4\u6E05\u7A7A", + cancelButtonText: "\u53D6\u6D88", + reverseButtons: false, + confirmButtonColor: "#ef4444", + cancelButtonColor: "#6b7280", + focusConfirm: false, + focusCancel: true + }).then((result) => { + if (result.isConfirmed) { + this.sessionManager.clearCurrentSession(); + this._render(); + } + }); + } + _handleDeleteSession(sessionId) { + Swal.fire({ + width: "22rem", + backdrop: `rgba(0,0,0,0.5)`, + heightAuto: false, + customClass: { popup: `swal2-custom-style ${document.documentElement.classList.contains("dark") ? "swal2-dark" : ""}` }, + title: "\u786E\u5B9A\u8981\u5220\u9664\u5417\uFF1F", + text: "\u6B64\u4F1A\u8BDD\u7684\u6240\u6709\u8BB0\u5F55\u5C06\u88AB\u6C38\u4E45\u5220\u9664\uFF0C\u65E0\u6CD5\u64A4\u9500\u3002", + showCancelButton: true, + confirmButtonText: "\u786E\u8BA4\u5220\u9664", + cancelButtonText: "\u53D6\u6D88", + reverseButtons: false, + confirmButtonColor: "#ef4444", + cancelButtonColor: "#6b7280", + focusConfirm: false, + focusCancel: true + }).then((result) => { + if (result.isConfirmed) { + this.sessionManager.deleteSession(sessionId); + this._render(); + } + }); + } +}; +function chat_default() { + const page = new ChatPage(); + page.init(); +} +export { + chat_default as default +}; diff --git a/web/static/js/chunk-T5V6LQ42.js b/web/static/js/chunk-T5V6LQ42.js new file mode 100644 index 0000000..aed0a12 --- /dev/null +++ b/web/static/js/chunk-T5V6LQ42.js @@ -0,0 +1,606 @@ +import { + __commonJS, + __toESM +} from "./chunk-JSBRDJBE.js"; + +// frontend/js/vendor/popper.esm.min.js +var require_popper_esm_min = __commonJS({ + "frontend/js/vendor/popper.esm.min.js"(exports, module) { + !(function(e, t) { + "object" == typeof exports && "undefined" != typeof module ? t(exports) : "function" == typeof define && define.amd ? define(["exports"], t) : t((e = "undefined" != typeof globalThis ? globalThis : e || self).Popper = {}); + })(exports, (function(e) { + "use strict"; + function t(e2) { + if (null == e2) return window; + if ("[object Window]" !== e2.toString()) { + var t2 = e2.ownerDocument; + return t2 && t2.defaultView || window; + } + return e2; + } + function n(e2) { + return e2 instanceof t(e2).Element || e2 instanceof Element; + } + function r(e2) { + return e2 instanceof t(e2).HTMLElement || e2 instanceof HTMLElement; + } + function o(e2) { + return "undefined" != typeof ShadowRoot && (e2 instanceof t(e2).ShadowRoot || e2 instanceof ShadowRoot); + } + var i = Math.max, a = Math.min, s = Math.round; + function f() { + var e2 = navigator.userAgentData; + return null != e2 && e2.brands && Array.isArray(e2.brands) ? e2.brands.map((function(e3) { + return e3.brand + "/" + e3.version; + })).join(" ") : navigator.userAgent; + } + function c() { + return !/^((?!chrome|android).)*safari/i.test(f()); + } + function p(e2, o2, i2) { + void 0 === o2 && (o2 = false), void 0 === i2 && (i2 = false); + var a2 = e2.getBoundingClientRect(), f2 = 1, p2 = 1; + o2 && r(e2) && (f2 = e2.offsetWidth > 0 && s(a2.width) / e2.offsetWidth || 1, p2 = e2.offsetHeight > 0 && s(a2.height) / e2.offsetHeight || 1); + var u2 = (n(e2) ? t(e2) : window).visualViewport, l2 = !c() && i2, d2 = (a2.left + (l2 && u2 ? u2.offsetLeft : 0)) / f2, h2 = (a2.top + (l2 && u2 ? u2.offsetTop : 0)) / p2, m2 = a2.width / f2, v2 = a2.height / p2; + return { width: m2, height: v2, top: h2, right: d2 + m2, bottom: h2 + v2, left: d2, x: d2, y: h2 }; + } + function u(e2) { + var n2 = t(e2); + return { scrollLeft: n2.pageXOffset, scrollTop: n2.pageYOffset }; + } + function l(e2) { + return e2 ? (e2.nodeName || "").toLowerCase() : null; + } + function d(e2) { + return ((n(e2) ? e2.ownerDocument : e2.document) || window.document).documentElement; + } + function h(e2) { + return p(d(e2)).left + u(e2).scrollLeft; + } + function m(e2) { + return t(e2).getComputedStyle(e2); + } + function v(e2) { + var t2 = m(e2), n2 = t2.overflow, r2 = t2.overflowX, o2 = t2.overflowY; + return /auto|scroll|overlay|hidden/.test(n2 + o2 + r2); + } + function y(e2, n2, o2) { + void 0 === o2 && (o2 = false); + var i2, a2, f2 = r(n2), c2 = r(n2) && (function(e3) { + var t2 = e3.getBoundingClientRect(), n3 = s(t2.width) / e3.offsetWidth || 1, r2 = s(t2.height) / e3.offsetHeight || 1; + return 1 !== n3 || 1 !== r2; + })(n2), m2 = d(n2), y2 = p(e2, c2, o2), g2 = { scrollLeft: 0, scrollTop: 0 }, b2 = { x: 0, y: 0 }; + return (f2 || !f2 && !o2) && (("body" !== l(n2) || v(m2)) && (g2 = (i2 = n2) !== t(i2) && r(i2) ? { scrollLeft: (a2 = i2).scrollLeft, scrollTop: a2.scrollTop } : u(i2)), r(n2) ? ((b2 = p(n2, true)).x += n2.clientLeft, b2.y += n2.clientTop) : m2 && (b2.x = h(m2))), { x: y2.left + g2.scrollLeft - b2.x, y: y2.top + g2.scrollTop - b2.y, width: y2.width, height: y2.height }; + } + function g(e2) { + var t2 = p(e2), n2 = e2.offsetWidth, r2 = e2.offsetHeight; + return Math.abs(t2.width - n2) <= 1 && (n2 = t2.width), Math.abs(t2.height - r2) <= 1 && (r2 = t2.height), { x: e2.offsetLeft, y: e2.offsetTop, width: n2, height: r2 }; + } + function b(e2) { + return "html" === l(e2) ? e2 : e2.assignedSlot || e2.parentNode || (o(e2) ? e2.host : null) || d(e2); + } + function x(e2) { + return ["html", "body", "#document"].indexOf(l(e2)) >= 0 ? e2.ownerDocument.body : r(e2) && v(e2) ? e2 : x(b(e2)); + } + function w(e2, n2) { + var r2; + void 0 === n2 && (n2 = []); + var o2 = x(e2), i2 = o2 === (null == (r2 = e2.ownerDocument) ? void 0 : r2.body), a2 = t(o2), s2 = i2 ? [a2].concat(a2.visualViewport || [], v(o2) ? o2 : []) : o2, f2 = n2.concat(s2); + return i2 ? f2 : f2.concat(w(b(s2))); + } + function O(e2) { + return ["table", "td", "th"].indexOf(l(e2)) >= 0; + } + function j(e2) { + return r(e2) && "fixed" !== m(e2).position ? e2.offsetParent : null; + } + function E(e2) { + for (var n2 = t(e2), i2 = j(e2); i2 && O(i2) && "static" === m(i2).position; ) i2 = j(i2); + return i2 && ("html" === l(i2) || "body" === l(i2) && "static" === m(i2).position) ? n2 : i2 || (function(e3) { + var t2 = /firefox/i.test(f()); + if (/Trident/i.test(f()) && r(e3) && "fixed" === m(e3).position) return null; + var n3 = b(e3); + for (o(n3) && (n3 = n3.host); r(n3) && ["html", "body"].indexOf(l(n3)) < 0; ) { + var i3 = m(n3); + if ("none" !== i3.transform || "none" !== i3.perspective || "paint" === i3.contain || -1 !== ["transform", "perspective"].indexOf(i3.willChange) || t2 && "filter" === i3.willChange || t2 && i3.filter && "none" !== i3.filter) return n3; + n3 = n3.parentNode; + } + return null; + })(e2) || n2; + } + var D = "top", A = "bottom", L = "right", P = "left", M = "auto", k = [D, A, L, P], W = "start", B = "end", H = "viewport", T = "popper", R = k.reduce((function(e2, t2) { + return e2.concat([t2 + "-" + W, t2 + "-" + B]); + }), []), S = [].concat(k, [M]).reduce((function(e2, t2) { + return e2.concat([t2, t2 + "-" + W, t2 + "-" + B]); + }), []), V = ["beforeRead", "read", "afterRead", "beforeMain", "main", "afterMain", "beforeWrite", "write", "afterWrite"]; + function q(e2) { + var t2 = /* @__PURE__ */ new Map(), n2 = /* @__PURE__ */ new Set(), r2 = []; + function o2(e3) { + n2.add(e3.name), [].concat(e3.requires || [], e3.requiresIfExists || []).forEach((function(e4) { + if (!n2.has(e4)) { + var r3 = t2.get(e4); + r3 && o2(r3); + } + })), r2.push(e3); + } + return e2.forEach((function(e3) { + t2.set(e3.name, e3); + })), e2.forEach((function(e3) { + n2.has(e3.name) || o2(e3); + })), r2; + } + function C(e2, t2) { + var n2 = t2.getRootNode && t2.getRootNode(); + if (e2.contains(t2)) return true; + if (n2 && o(n2)) { + var r2 = t2; + do { + if (r2 && e2.isSameNode(r2)) return true; + r2 = r2.parentNode || r2.host; + } while (r2); + } + return false; + } + function N(e2) { + return Object.assign({}, e2, { left: e2.x, top: e2.y, right: e2.x + e2.width, bottom: e2.y + e2.height }); + } + function I(e2, r2, o2) { + return r2 === H ? N((function(e3, n2) { + var r3 = t(e3), o3 = d(e3), i2 = r3.visualViewport, a2 = o3.clientWidth, s2 = o3.clientHeight, f2 = 0, p2 = 0; + if (i2) { + a2 = i2.width, s2 = i2.height; + var u2 = c(); + (u2 || !u2 && "fixed" === n2) && (f2 = i2.offsetLeft, p2 = i2.offsetTop); + } + return { width: a2, height: s2, x: f2 + h(e3), y: p2 }; + })(e2, o2)) : n(r2) ? (function(e3, t2) { + var n2 = p(e3, false, "fixed" === t2); + return n2.top = n2.top + e3.clientTop, n2.left = n2.left + e3.clientLeft, n2.bottom = n2.top + e3.clientHeight, n2.right = n2.left + e3.clientWidth, n2.width = e3.clientWidth, n2.height = e3.clientHeight, n2.x = n2.left, n2.y = n2.top, n2; + })(r2, o2) : N((function(e3) { + var t2, n2 = d(e3), r3 = u(e3), o3 = null == (t2 = e3.ownerDocument) ? void 0 : t2.body, a2 = i(n2.scrollWidth, n2.clientWidth, o3 ? o3.scrollWidth : 0, o3 ? o3.clientWidth : 0), s2 = i(n2.scrollHeight, n2.clientHeight, o3 ? o3.scrollHeight : 0, o3 ? o3.clientHeight : 0), f2 = -r3.scrollLeft + h(e3), c2 = -r3.scrollTop; + return "rtl" === m(o3 || n2).direction && (f2 += i(n2.clientWidth, o3 ? o3.clientWidth : 0) - a2), { width: a2, height: s2, x: f2, y: c2 }; + })(d(e2))); + } + function _(e2, t2, o2, s2) { + var f2 = "clippingParents" === t2 ? (function(e3) { + var t3 = w(b(e3)), o3 = ["absolute", "fixed"].indexOf(m(e3).position) >= 0 && r(e3) ? E(e3) : e3; + return n(o3) ? t3.filter((function(e4) { + return n(e4) && C(e4, o3) && "body" !== l(e4); + })) : []; + })(e2) : [].concat(t2), c2 = [].concat(f2, [o2]), p2 = c2[0], u2 = c2.reduce((function(t3, n2) { + var r2 = I(e2, n2, s2); + return t3.top = i(r2.top, t3.top), t3.right = a(r2.right, t3.right), t3.bottom = a(r2.bottom, t3.bottom), t3.left = i(r2.left, t3.left), t3; + }), I(e2, p2, s2)); + return u2.width = u2.right - u2.left, u2.height = u2.bottom - u2.top, u2.x = u2.left, u2.y = u2.top, u2; + } + function F(e2) { + return e2.split("-")[0]; + } + function U(e2) { + return e2.split("-")[1]; + } + function z(e2) { + return ["top", "bottom"].indexOf(e2) >= 0 ? "x" : "y"; + } + function X(e2) { + var t2, n2 = e2.reference, r2 = e2.element, o2 = e2.placement, i2 = o2 ? F(o2) : null, a2 = o2 ? U(o2) : null, s2 = n2.x + n2.width / 2 - r2.width / 2, f2 = n2.y + n2.height / 2 - r2.height / 2; + switch (i2) { + case D: + t2 = { x: s2, y: n2.y - r2.height }; + break; + case A: + t2 = { x: s2, y: n2.y + n2.height }; + break; + case L: + t2 = { x: n2.x + n2.width, y: f2 }; + break; + case P: + t2 = { x: n2.x - r2.width, y: f2 }; + break; + default: + t2 = { x: n2.x, y: n2.y }; + } + var c2 = i2 ? z(i2) : null; + if (null != c2) { + var p2 = "y" === c2 ? "height" : "width"; + switch (a2) { + case W: + t2[c2] = t2[c2] - (n2[p2] / 2 - r2[p2] / 2); + break; + case B: + t2[c2] = t2[c2] + (n2[p2] / 2 - r2[p2] / 2); + } + } + return t2; + } + function Y(e2) { + return Object.assign({}, { top: 0, right: 0, bottom: 0, left: 0 }, e2); + } + function G(e2, t2) { + return t2.reduce((function(t3, n2) { + return t3[n2] = e2, t3; + }), {}); + } + function J(e2, t2) { + void 0 === t2 && (t2 = {}); + var r2 = t2, o2 = r2.placement, i2 = void 0 === o2 ? e2.placement : o2, a2 = r2.strategy, s2 = void 0 === a2 ? e2.strategy : a2, f2 = r2.boundary, c2 = void 0 === f2 ? "clippingParents" : f2, u2 = r2.rootBoundary, l2 = void 0 === u2 ? H : u2, h2 = r2.elementContext, m2 = void 0 === h2 ? T : h2, v2 = r2.altBoundary, y2 = void 0 !== v2 && v2, g2 = r2.padding, b2 = void 0 === g2 ? 0 : g2, x2 = Y("number" != typeof b2 ? b2 : G(b2, k)), w2 = m2 === T ? "reference" : T, O2 = e2.rects.popper, j2 = e2.elements[y2 ? w2 : m2], E2 = _(n(j2) ? j2 : j2.contextElement || d(e2.elements.popper), c2, l2, s2), P2 = p(e2.elements.reference), M2 = X({ reference: P2, element: O2, strategy: "absolute", placement: i2 }), W2 = N(Object.assign({}, O2, M2)), B2 = m2 === T ? W2 : P2, R2 = { top: E2.top - B2.top + x2.top, bottom: B2.bottom - E2.bottom + x2.bottom, left: E2.left - B2.left + x2.left, right: B2.right - E2.right + x2.right }, S2 = e2.modifiersData.offset; + if (m2 === T && S2) { + var V2 = S2[i2]; + Object.keys(R2).forEach((function(e3) { + var t3 = [L, A].indexOf(e3) >= 0 ? 1 : -1, n2 = [D, A].indexOf(e3) >= 0 ? "y" : "x"; + R2[e3] += V2[n2] * t3; + })); + } + return R2; + } + var K = { placement: "bottom", modifiers: [], strategy: "absolute" }; + function Q() { + for (var e2 = arguments.length, t2 = new Array(e2), n2 = 0; n2 < e2; n2++) t2[n2] = arguments[n2]; + return !t2.some((function(e3) { + return !(e3 && "function" == typeof e3.getBoundingClientRect); + })); + } + function Z(e2) { + void 0 === e2 && (e2 = {}); + var t2 = e2, r2 = t2.defaultModifiers, o2 = void 0 === r2 ? [] : r2, i2 = t2.defaultOptions, a2 = void 0 === i2 ? K : i2; + return function(e3, t3, r3) { + void 0 === r3 && (r3 = a2); + var i3, s2, f2 = { placement: "bottom", orderedModifiers: [], options: Object.assign({}, K, a2), modifiersData: {}, elements: { reference: e3, popper: t3 }, attributes: {}, styles: {} }, c2 = [], p2 = false, u2 = { state: f2, setOptions: function(r4) { + var i4 = "function" == typeof r4 ? r4(f2.options) : r4; + l2(), f2.options = Object.assign({}, a2, f2.options, i4), f2.scrollParents = { reference: n(e3) ? w(e3) : e3.contextElement ? w(e3.contextElement) : [], popper: w(t3) }; + var s3, p3, d2 = (function(e4) { + var t4 = q(e4); + return V.reduce((function(e5, n2) { + return e5.concat(t4.filter((function(e6) { + return e6.phase === n2; + }))); + }), []); + })((s3 = [].concat(o2, f2.options.modifiers), p3 = s3.reduce((function(e4, t4) { + var n2 = e4[t4.name]; + return e4[t4.name] = n2 ? Object.assign({}, n2, t4, { options: Object.assign({}, n2.options, t4.options), data: Object.assign({}, n2.data, t4.data) }) : t4, e4; + }), {}), Object.keys(p3).map((function(e4) { + return p3[e4]; + })))); + return f2.orderedModifiers = d2.filter((function(e4) { + return e4.enabled; + })), f2.orderedModifiers.forEach((function(e4) { + var t4 = e4.name, n2 = e4.options, r5 = void 0 === n2 ? {} : n2, o3 = e4.effect; + if ("function" == typeof o3) { + var i5 = o3({ state: f2, name: t4, instance: u2, options: r5 }), a3 = function() { + }; + c2.push(i5 || a3); + } + })), u2.update(); + }, forceUpdate: function() { + if (!p2) { + var e4 = f2.elements, t4 = e4.reference, n2 = e4.popper; + if (Q(t4, n2)) { + f2.rects = { reference: y(t4, E(n2), "fixed" === f2.options.strategy), popper: g(n2) }, f2.reset = false, f2.placement = f2.options.placement, f2.orderedModifiers.forEach((function(e5) { + return f2.modifiersData[e5.name] = Object.assign({}, e5.data); + })); + for (var r4 = 0; r4 < f2.orderedModifiers.length; r4++) if (true !== f2.reset) { + var o3 = f2.orderedModifiers[r4], i4 = o3.fn, a3 = o3.options, s3 = void 0 === a3 ? {} : a3, c3 = o3.name; + "function" == typeof i4 && (f2 = i4({ state: f2, options: s3, name: c3, instance: u2 }) || f2); + } else f2.reset = false, r4 = -1; + } + } + }, update: (i3 = function() { + return new Promise((function(e4) { + u2.forceUpdate(), e4(f2); + })); + }, function() { + return s2 || (s2 = new Promise((function(e4) { + Promise.resolve().then((function() { + s2 = void 0, e4(i3()); + })); + }))), s2; + }), destroy: function() { + l2(), p2 = true; + } }; + if (!Q(e3, t3)) return u2; + function l2() { + c2.forEach((function(e4) { + return e4(); + })), c2 = []; + } + return u2.setOptions(r3).then((function(e4) { + !p2 && r3.onFirstUpdate && r3.onFirstUpdate(e4); + })), u2; + }; + } + var $ = { passive: true }; + var ee = { name: "eventListeners", enabled: true, phase: "write", fn: function() { + }, effect: function(e2) { + var n2 = e2.state, r2 = e2.instance, o2 = e2.options, i2 = o2.scroll, a2 = void 0 === i2 || i2, s2 = o2.resize, f2 = void 0 === s2 || s2, c2 = t(n2.elements.popper), p2 = [].concat(n2.scrollParents.reference, n2.scrollParents.popper); + return a2 && p2.forEach((function(e3) { + e3.addEventListener("scroll", r2.update, $); + })), f2 && c2.addEventListener("resize", r2.update, $), function() { + a2 && p2.forEach((function(e3) { + e3.removeEventListener("scroll", r2.update, $); + })), f2 && c2.removeEventListener("resize", r2.update, $); + }; + }, data: {} }; + var te = { name: "popperOffsets", enabled: true, phase: "read", fn: function(e2) { + var t2 = e2.state, n2 = e2.name; + t2.modifiersData[n2] = X({ reference: t2.rects.reference, element: t2.rects.popper, strategy: "absolute", placement: t2.placement }); + }, data: {} }, ne = { top: "auto", right: "auto", bottom: "auto", left: "auto" }; + function re(e2) { + var n2, r2 = e2.popper, o2 = e2.popperRect, i2 = e2.placement, a2 = e2.variation, f2 = e2.offsets, c2 = e2.position, p2 = e2.gpuAcceleration, u2 = e2.adaptive, l2 = e2.roundOffsets, h2 = e2.isFixed, v2 = f2.x, y2 = void 0 === v2 ? 0 : v2, g2 = f2.y, b2 = void 0 === g2 ? 0 : g2, x2 = "function" == typeof l2 ? l2({ x: y2, y: b2 }) : { x: y2, y: b2 }; + y2 = x2.x, b2 = x2.y; + var w2 = f2.hasOwnProperty("x"), O2 = f2.hasOwnProperty("y"), j2 = P, M2 = D, k2 = window; + if (u2) { + var W2 = E(r2), H2 = "clientHeight", T2 = "clientWidth"; + if (W2 === t(r2) && "static" !== m(W2 = d(r2)).position && "absolute" === c2 && (H2 = "scrollHeight", T2 = "scrollWidth"), W2 = W2, i2 === D || (i2 === P || i2 === L) && a2 === B) M2 = A, b2 -= (h2 && W2 === k2 && k2.visualViewport ? k2.visualViewport.height : W2[H2]) - o2.height, b2 *= p2 ? 1 : -1; + if (i2 === P || (i2 === D || i2 === A) && a2 === B) j2 = L, y2 -= (h2 && W2 === k2 && k2.visualViewport ? k2.visualViewport.width : W2[T2]) - o2.width, y2 *= p2 ? 1 : -1; + } + var R2, S2 = Object.assign({ position: c2 }, u2 && ne), V2 = true === l2 ? (function(e3, t2) { + var n3 = e3.x, r3 = e3.y, o3 = t2.devicePixelRatio || 1; + return { x: s(n3 * o3) / o3 || 0, y: s(r3 * o3) / o3 || 0 }; + })({ x: y2, y: b2 }, t(r2)) : { x: y2, y: b2 }; + return y2 = V2.x, b2 = V2.y, p2 ? Object.assign({}, S2, ((R2 = {})[M2] = O2 ? "0" : "", R2[j2] = w2 ? "0" : "", R2.transform = (k2.devicePixelRatio || 1) <= 1 ? "translate(" + y2 + "px, " + b2 + "px)" : "translate3d(" + y2 + "px, " + b2 + "px, 0)", R2)) : Object.assign({}, S2, ((n2 = {})[M2] = O2 ? b2 + "px" : "", n2[j2] = w2 ? y2 + "px" : "", n2.transform = "", n2)); + } + var oe = { name: "computeStyles", enabled: true, phase: "beforeWrite", fn: function(e2) { + var t2 = e2.state, n2 = e2.options, r2 = n2.gpuAcceleration, o2 = void 0 === r2 || r2, i2 = n2.adaptive, a2 = void 0 === i2 || i2, s2 = n2.roundOffsets, f2 = void 0 === s2 || s2, c2 = { placement: F(t2.placement), variation: U(t2.placement), popper: t2.elements.popper, popperRect: t2.rects.popper, gpuAcceleration: o2, isFixed: "fixed" === t2.options.strategy }; + null != t2.modifiersData.popperOffsets && (t2.styles.popper = Object.assign({}, t2.styles.popper, re(Object.assign({}, c2, { offsets: t2.modifiersData.popperOffsets, position: t2.options.strategy, adaptive: a2, roundOffsets: f2 })))), null != t2.modifiersData.arrow && (t2.styles.arrow = Object.assign({}, t2.styles.arrow, re(Object.assign({}, c2, { offsets: t2.modifiersData.arrow, position: "absolute", adaptive: false, roundOffsets: f2 })))), t2.attributes.popper = Object.assign({}, t2.attributes.popper, { "data-popper-placement": t2.placement }); + }, data: {} }; + var ie = { name: "applyStyles", enabled: true, phase: "write", fn: function(e2) { + var t2 = e2.state; + Object.keys(t2.elements).forEach((function(e3) { + var n2 = t2.styles[e3] || {}, o2 = t2.attributes[e3] || {}, i2 = t2.elements[e3]; + r(i2) && l(i2) && (Object.assign(i2.style, n2), Object.keys(o2).forEach((function(e4) { + var t3 = o2[e4]; + false === t3 ? i2.removeAttribute(e4) : i2.setAttribute(e4, true === t3 ? "" : t3); + }))); + })); + }, effect: function(e2) { + var t2 = e2.state, n2 = { popper: { position: t2.options.strategy, left: "0", top: "0", margin: "0" }, arrow: { position: "absolute" }, reference: {} }; + return Object.assign(t2.elements.popper.style, n2.popper), t2.styles = n2, t2.elements.arrow && Object.assign(t2.elements.arrow.style, n2.arrow), function() { + Object.keys(t2.elements).forEach((function(e3) { + var o2 = t2.elements[e3], i2 = t2.attributes[e3] || {}, a2 = Object.keys(t2.styles.hasOwnProperty(e3) ? t2.styles[e3] : n2[e3]).reduce((function(e4, t3) { + return e4[t3] = "", e4; + }), {}); + r(o2) && l(o2) && (Object.assign(o2.style, a2), Object.keys(i2).forEach((function(e4) { + o2.removeAttribute(e4); + }))); + })); + }; + }, requires: ["computeStyles"] }; + var ae = { name: "offset", enabled: true, phase: "main", requires: ["popperOffsets"], fn: function(e2) { + var t2 = e2.state, n2 = e2.options, r2 = e2.name, o2 = n2.offset, i2 = void 0 === o2 ? [0, 0] : o2, a2 = S.reduce((function(e3, n3) { + return e3[n3] = (function(e4, t3, n4) { + var r3 = F(e4), o3 = [P, D].indexOf(r3) >= 0 ? -1 : 1, i3 = "function" == typeof n4 ? n4(Object.assign({}, t3, { placement: e4 })) : n4, a3 = i3[0], s3 = i3[1]; + return a3 = a3 || 0, s3 = (s3 || 0) * o3, [P, L].indexOf(r3) >= 0 ? { x: s3, y: a3 } : { x: a3, y: s3 }; + })(n3, t2.rects, i2), e3; + }), {}), s2 = a2[t2.placement], f2 = s2.x, c2 = s2.y; + null != t2.modifiersData.popperOffsets && (t2.modifiersData.popperOffsets.x += f2, t2.modifiersData.popperOffsets.y += c2), t2.modifiersData[r2] = a2; + } }, se = { left: "right", right: "left", bottom: "top", top: "bottom" }; + function fe(e2) { + return e2.replace(/left|right|bottom|top/g, (function(e3) { + return se[e3]; + })); + } + var ce = { start: "end", end: "start" }; + function pe(e2) { + return e2.replace(/start|end/g, (function(e3) { + return ce[e3]; + })); + } + function ue(e2, t2) { + void 0 === t2 && (t2 = {}); + var n2 = t2, r2 = n2.placement, o2 = n2.boundary, i2 = n2.rootBoundary, a2 = n2.padding, s2 = n2.flipVariations, f2 = n2.allowedAutoPlacements, c2 = void 0 === f2 ? S : f2, p2 = U(r2), u2 = p2 ? s2 ? R : R.filter((function(e3) { + return U(e3) === p2; + })) : k, l2 = u2.filter((function(e3) { + return c2.indexOf(e3) >= 0; + })); + 0 === l2.length && (l2 = u2); + var d2 = l2.reduce((function(t3, n3) { + return t3[n3] = J(e2, { placement: n3, boundary: o2, rootBoundary: i2, padding: a2 })[F(n3)], t3; + }), {}); + return Object.keys(d2).sort((function(e3, t3) { + return d2[e3] - d2[t3]; + })); + } + var le = { name: "flip", enabled: true, phase: "main", fn: function(e2) { + var t2 = e2.state, n2 = e2.options, r2 = e2.name; + if (!t2.modifiersData[r2]._skip) { + for (var o2 = n2.mainAxis, i2 = void 0 === o2 || o2, a2 = n2.altAxis, s2 = void 0 === a2 || a2, f2 = n2.fallbackPlacements, c2 = n2.padding, p2 = n2.boundary, u2 = n2.rootBoundary, l2 = n2.altBoundary, d2 = n2.flipVariations, h2 = void 0 === d2 || d2, m2 = n2.allowedAutoPlacements, v2 = t2.options.placement, y2 = F(v2), g2 = f2 || (y2 === v2 || !h2 ? [fe(v2)] : (function(e3) { + if (F(e3) === M) return []; + var t3 = fe(e3); + return [pe(e3), t3, pe(t3)]; + })(v2)), b2 = [v2].concat(g2).reduce((function(e3, n3) { + return e3.concat(F(n3) === M ? ue(t2, { placement: n3, boundary: p2, rootBoundary: u2, padding: c2, flipVariations: h2, allowedAutoPlacements: m2 }) : n3); + }), []), x2 = t2.rects.reference, w2 = t2.rects.popper, O2 = /* @__PURE__ */ new Map(), j2 = true, E2 = b2[0], k2 = 0; k2 < b2.length; k2++) { + var B2 = b2[k2], H2 = F(B2), T2 = U(B2) === W, R2 = [D, A].indexOf(H2) >= 0, S2 = R2 ? "width" : "height", V2 = J(t2, { placement: B2, boundary: p2, rootBoundary: u2, altBoundary: l2, padding: c2 }), q2 = R2 ? T2 ? L : P : T2 ? A : D; + x2[S2] > w2[S2] && (q2 = fe(q2)); + var C2 = fe(q2), N2 = []; + if (i2 && N2.push(V2[H2] <= 0), s2 && N2.push(V2[q2] <= 0, V2[C2] <= 0), N2.every((function(e3) { + return e3; + }))) { + E2 = B2, j2 = false; + break; + } + O2.set(B2, N2); + } + if (j2) for (var I2 = function(e3) { + var t3 = b2.find((function(t4) { + var n3 = O2.get(t4); + if (n3) return n3.slice(0, e3).every((function(e4) { + return e4; + })); + })); + if (t3) return E2 = t3, "break"; + }, _2 = h2 ? 3 : 1; _2 > 0; _2--) { + if ("break" === I2(_2)) break; + } + t2.placement !== E2 && (t2.modifiersData[r2]._skip = true, t2.placement = E2, t2.reset = true); + } + }, requiresIfExists: ["offset"], data: { _skip: false } }; + function de(e2, t2, n2) { + return i(e2, a(t2, n2)); + } + var he = { name: "preventOverflow", enabled: true, phase: "main", fn: function(e2) { + var t2 = e2.state, n2 = e2.options, r2 = e2.name, o2 = n2.mainAxis, s2 = void 0 === o2 || o2, f2 = n2.altAxis, c2 = void 0 !== f2 && f2, p2 = n2.boundary, u2 = n2.rootBoundary, l2 = n2.altBoundary, d2 = n2.padding, h2 = n2.tether, m2 = void 0 === h2 || h2, v2 = n2.tetherOffset, y2 = void 0 === v2 ? 0 : v2, b2 = J(t2, { boundary: p2, rootBoundary: u2, padding: d2, altBoundary: l2 }), x2 = F(t2.placement), w2 = U(t2.placement), O2 = !w2, j2 = z(x2), M2 = "x" === j2 ? "y" : "x", k2 = t2.modifiersData.popperOffsets, B2 = t2.rects.reference, H2 = t2.rects.popper, T2 = "function" == typeof y2 ? y2(Object.assign({}, t2.rects, { placement: t2.placement })) : y2, R2 = "number" == typeof T2 ? { mainAxis: T2, altAxis: T2 } : Object.assign({ mainAxis: 0, altAxis: 0 }, T2), S2 = t2.modifiersData.offset ? t2.modifiersData.offset[t2.placement] : null, V2 = { x: 0, y: 0 }; + if (k2) { + if (s2) { + var q2, C2 = "y" === j2 ? D : P, N2 = "y" === j2 ? A : L, I2 = "y" === j2 ? "height" : "width", _2 = k2[j2], X2 = _2 + b2[C2], Y2 = _2 - b2[N2], G2 = m2 ? -H2[I2] / 2 : 0, K2 = w2 === W ? B2[I2] : H2[I2], Q2 = w2 === W ? -H2[I2] : -B2[I2], Z2 = t2.elements.arrow, $2 = m2 && Z2 ? g(Z2) : { width: 0, height: 0 }, ee2 = t2.modifiersData["arrow#persistent"] ? t2.modifiersData["arrow#persistent"].padding : { top: 0, right: 0, bottom: 0, left: 0 }, te2 = ee2[C2], ne2 = ee2[N2], re2 = de(0, B2[I2], $2[I2]), oe2 = O2 ? B2[I2] / 2 - G2 - re2 - te2 - R2.mainAxis : K2 - re2 - te2 - R2.mainAxis, ie2 = O2 ? -B2[I2] / 2 + G2 + re2 + ne2 + R2.mainAxis : Q2 + re2 + ne2 + R2.mainAxis, ae2 = t2.elements.arrow && E(t2.elements.arrow), se2 = ae2 ? "y" === j2 ? ae2.clientTop || 0 : ae2.clientLeft || 0 : 0, fe2 = null != (q2 = null == S2 ? void 0 : S2[j2]) ? q2 : 0, ce2 = _2 + ie2 - fe2, pe2 = de(m2 ? a(X2, _2 + oe2 - fe2 - se2) : X2, _2, m2 ? i(Y2, ce2) : Y2); + k2[j2] = pe2, V2[j2] = pe2 - _2; + } + if (c2) { + var ue2, le2 = "x" === j2 ? D : P, he2 = "x" === j2 ? A : L, me2 = k2[M2], ve2 = "y" === M2 ? "height" : "width", ye2 = me2 + b2[le2], ge2 = me2 - b2[he2], be2 = -1 !== [D, P].indexOf(x2), xe2 = null != (ue2 = null == S2 ? void 0 : S2[M2]) ? ue2 : 0, we2 = be2 ? ye2 : me2 - B2[ve2] - H2[ve2] - xe2 + R2.altAxis, Oe = be2 ? me2 + B2[ve2] + H2[ve2] - xe2 - R2.altAxis : ge2, je = m2 && be2 ? (function(e3, t3, n3) { + var r3 = de(e3, t3, n3); + return r3 > n3 ? n3 : r3; + })(we2, me2, Oe) : de(m2 ? we2 : ye2, me2, m2 ? Oe : ge2); + k2[M2] = je, V2[M2] = je - me2; + } + t2.modifiersData[r2] = V2; + } + }, requiresIfExists: ["offset"] }; + var me = { name: "arrow", enabled: true, phase: "main", fn: function(e2) { + var t2, n2 = e2.state, r2 = e2.name, o2 = e2.options, i2 = n2.elements.arrow, a2 = n2.modifiersData.popperOffsets, s2 = F(n2.placement), f2 = z(s2), c2 = [P, L].indexOf(s2) >= 0 ? "height" : "width"; + if (i2 && a2) { + var p2 = (function(e3, t3) { + return Y("number" != typeof (e3 = "function" == typeof e3 ? e3(Object.assign({}, t3.rects, { placement: t3.placement })) : e3) ? e3 : G(e3, k)); + })(o2.padding, n2), u2 = g(i2), l2 = "y" === f2 ? D : P, d2 = "y" === f2 ? A : L, h2 = n2.rects.reference[c2] + n2.rects.reference[f2] - a2[f2] - n2.rects.popper[c2], m2 = a2[f2] - n2.rects.reference[f2], v2 = E(i2), y2 = v2 ? "y" === f2 ? v2.clientHeight || 0 : v2.clientWidth || 0 : 0, b2 = h2 / 2 - m2 / 2, x2 = p2[l2], w2 = y2 - u2[c2] - p2[d2], O2 = y2 / 2 - u2[c2] / 2 + b2, j2 = de(x2, O2, w2), M2 = f2; + n2.modifiersData[r2] = ((t2 = {})[M2] = j2, t2.centerOffset = j2 - O2, t2); + } + }, effect: function(e2) { + var t2 = e2.state, n2 = e2.options.element, r2 = void 0 === n2 ? "[data-popper-arrow]" : n2; + null != r2 && ("string" != typeof r2 || (r2 = t2.elements.popper.querySelector(r2))) && C(t2.elements.popper, r2) && (t2.elements.arrow = r2); + }, requires: ["popperOffsets"], requiresIfExists: ["preventOverflow"] }; + function ve(e2, t2, n2) { + return void 0 === n2 && (n2 = { x: 0, y: 0 }), { top: e2.top - t2.height - n2.y, right: e2.right - t2.width + n2.x, bottom: e2.bottom - t2.height + n2.y, left: e2.left - t2.width - n2.x }; + } + function ye(e2) { + return [D, L, A, P].some((function(t2) { + return e2[t2] >= 0; + })); + } + var ge = { name: "hide", enabled: true, phase: "main", requiresIfExists: ["preventOverflow"], fn: function(e2) { + var t2 = e2.state, n2 = e2.name, r2 = t2.rects.reference, o2 = t2.rects.popper, i2 = t2.modifiersData.preventOverflow, a2 = J(t2, { elementContext: "reference" }), s2 = J(t2, { altBoundary: true }), f2 = ve(a2, r2), c2 = ve(s2, o2, i2), p2 = ye(f2), u2 = ye(c2); + t2.modifiersData[n2] = { referenceClippingOffsets: f2, popperEscapeOffsets: c2, isReferenceHidden: p2, hasPopperEscaped: u2 }, t2.attributes.popper = Object.assign({}, t2.attributes.popper, { "data-popper-reference-hidden": p2, "data-popper-escaped": u2 }); + } }, be = Z({ defaultModifiers: [ee, te, oe, ie] }), xe = [ee, te, oe, ie, ae, le, he, me, ge], we = Z({ defaultModifiers: xe }); + e.applyStyles = ie, e.arrow = me, e.computeStyles = oe, e.createPopper = we, e.createPopperLite = be, e.defaultModifiers = xe, e.detectOverflow = J, e.eventListeners = ee, e.flip = le, e.hide = ge, e.offset = ae, e.popperGenerator = Z, e.popperOffsets = te, e.preventOverflow = he, Object.defineProperty(e, "__esModule", { value: true }); + })); + } +}); + +// frontend/js/components/customSelectV2.js +var import_popper_esm_min = __toESM(require_popper_esm_min()); +var CustomSelectV2 = class _CustomSelectV2 { + constructor(container) { + this.container = container; + this.trigger = this.container.querySelector(".custom-select-trigger"); + this.nativeSelect = this.container.querySelector("select"); + this.template = this.container.querySelector(".custom-select-panel-template"); + if (!this.trigger || !this.nativeSelect || !this.template) { + console.warn("CustomSelectV2 cannot initialize: missing required elements.", this.container); + return; + } + this.panel = null; + this.popperInstance = null; + this.isOpen = false; + this.triggerText = this.trigger.querySelector("span"); + if (typeof _CustomSelectV2.openInstance === "undefined") { + _CustomSelectV2.openInstance = null; + _CustomSelectV2.initGlobalListener(); + } + this.updateTriggerText(); + this.bindEvents(); + } + static initGlobalListener() { + document.addEventListener("click", (event) => { + const instance = _CustomSelectV2.openInstance; + if (instance && !instance.container.contains(event.target) && (!instance.panel || !instance.panel.contains(event.target))) { + instance.close(); + } + }); + } + createPanel() { + const panelFragment = this.template.content.cloneNode(true); + this.panel = panelFragment.querySelector(".custom-select-panel"); + document.body.appendChild(this.panel); + this.panel.innerHTML = ""; + Array.from(this.nativeSelect.options).forEach((option) => { + const item = document.createElement("a"); + item.href = "#"; + item.className = "custom-select-option block w-full text-left px-3 py-1.5 text-sm text-zinc-700 hover:bg-zinc-100 dark:text-zinc-200 dark:hover:bg-zinc-700"; + item.textContent = option.textContent; + item.dataset.value = option.value; + if (option.selected) { + item.classList.add("is-selected"); + } + this.panel.appendChild(item); + }); + this.panel.addEventListener("click", (event) => { + event.preventDefault(); + const optionEl = event.target.closest(".custom-select-option"); + if (optionEl) { + this.selectOption(optionEl); + } + }); + } + bindEvents() { + this.trigger.addEventListener("click", (event) => { + event.stopPropagation(); + if (_CustomSelectV2.openInstance && _CustomSelectV2.openInstance !== this) { + _CustomSelectV2.openInstance.close(); + } + this.toggle(); + }); + } + selectOption(optionEl) { + const selectedValue = optionEl.dataset.value; + if (this.nativeSelect.value !== selectedValue) { + this.nativeSelect.value = selectedValue; + this.nativeSelect.dispatchEvent(new Event("change", { bubbles: true })); + } + this.updateTriggerText(); + this.close(); + } + updateTriggerText() { + const selectedOption = this.nativeSelect.options[this.nativeSelect.selectedIndex]; + if (selectedOption) { + this.triggerText.textContent = selectedOption.textContent; + } + } + toggle() { + this.isOpen ? this.close() : this.open(); + } + open() { + if (this.isOpen) return; + this.isOpen = true; + if (!this.panel) { + this.createPanel(); + } + this.panel.style.display = "block"; + this.panel.offsetHeight; + this.popperInstance = (0, import_popper_esm_min.createPopper)(this.trigger, this.panel, { + placement: "top-start", + modifiers: [ + { name: "offset", options: { offset: [0, 8] } }, + { name: "flip", options: { fallbackPlacements: ["bottom-start"] } } + ] + }); + _CustomSelectV2.openInstance = this; + } + close() { + if (!this.isOpen) return; + this.isOpen = false; + if (this.popperInstance) { + this.popperInstance.destroy(); + this.popperInstance = null; + } + if (this.panel) { + this.panel.remove(); + this.panel = null; + } + if (_CustomSelectV2.openInstance === this) { + _CustomSelectV2.openInstance = null; + } + } +}; + +export { + require_popper_esm_min, + CustomSelectV2 +}; diff --git a/web/static/js/chunk-SHK62ZJN.js b/web/static/js/chunk-VOGCL6QZ.js similarity index 92% rename from web/static/js/chunk-SHK62ZJN.js rename to web/static/js/chunk-VOGCL6QZ.js index 49befa4..a81dfe2 100644 --- a/web/static/js/chunk-SHK62ZJN.js +++ b/web/static/js/chunk-VOGCL6QZ.js @@ -269,6 +269,39 @@ var UIPatterns = class { }); } } + /** + * Sets a button to a loading state by disabling it and showing a spinner. + * It stores the button's original content to be restored later. + * @param {HTMLButtonElement} button - The button element to modify. + */ + setButtonLoading(button) { + if (!button) return; + if (!button.dataset.originalContent) { + button.dataset.originalContent = button.innerHTML; + } + button.disabled = true; + button.innerHTML = ''; + } + /** + * Restores a button from its loading state to its original content and enables it. + * @param {HTMLButtonElement} button - The button element to restore. + */ + clearButtonLoading(button) { + if (!button) return; + if (button.dataset.originalContent) { + button.innerHTML = button.dataset.originalContent; + delete button.dataset.originalContent; + } + button.disabled = false; + } + /** + * Returns the HTML for a streaming text cursor animation. + * This is used as a placeholder in the chat UI while waiting for an assistant's response. + * @returns {string} The HTML string for the loader. + */ + renderStreamingLoader() { + return '\u258B'; + } }; var modalManager = new ModalManager(); var uiPatterns = new UIPatterns(); diff --git a/web/static/js/keys-YEK3YJ77.js b/web/static/js/keys-V4KPRAAB.js similarity index 99% rename from web/static/js/keys-YEK3YJ77.js rename to web/static/js/keys-V4KPRAAB.js index bddd083..1df7efd 100644 --- a/web/static/js/keys-YEK3YJ77.js +++ b/web/static/js/keys-V4KPRAAB.js @@ -12,7 +12,7 @@ import { apiFetch, apiFetchJson, modalManager -} from "./chunk-SHK62ZJN.js"; +} from "./chunk-VOGCL6QZ.js"; import "./chunk-JSBRDJBE.js"; // frontend/js/components/tagInput.js diff --git a/web/static/js/logs-SSK3L2XT.js b/web/static/js/logs-4XXDCFYG.js similarity index 78% rename from web/static/js/logs-SSK3L2XT.js rename to web/static/js/logs-4XXDCFYG.js index f67d0c6..a966a6f 100644 --- a/web/static/js/logs-SSK3L2XT.js +++ b/web/static/js/logs-4XXDCFYG.js @@ -2,496 +2,19 @@ import { debounce, escapeHTML } from "./chunk-A4OOMLXK.js"; +import { + CustomSelectV2, + require_popper_esm_min +} from "./chunk-T5V6LQ42.js"; import { apiFetchJson, modalManager -} from "./chunk-SHK62ZJN.js"; +} from "./chunk-VOGCL6QZ.js"; import { __commonJS, __toESM } from "./chunk-JSBRDJBE.js"; -// frontend/js/vendor/popper.esm.min.js -var require_popper_esm_min = __commonJS({ - "frontend/js/vendor/popper.esm.min.js"(exports, module) { - !(function(e, t) { - "object" == typeof exports && "undefined" != typeof module ? t(exports) : "function" == typeof define && define.amd ? define(["exports"], t) : t((e = "undefined" != typeof globalThis ? globalThis : e || self).Popper = {}); - })(exports, (function(e) { - "use strict"; - function t(e2) { - if (null == e2) return window; - if ("[object Window]" !== e2.toString()) { - var t2 = e2.ownerDocument; - return t2 && t2.defaultView || window; - } - return e2; - } - function n(e2) { - return e2 instanceof t(e2).Element || e2 instanceof Element; - } - function r(e2) { - return e2 instanceof t(e2).HTMLElement || e2 instanceof HTMLElement; - } - function o(e2) { - return "undefined" != typeof ShadowRoot && (e2 instanceof t(e2).ShadowRoot || e2 instanceof ShadowRoot); - } - var i = Math.max, a = Math.min, s = Math.round; - function f() { - var e2 = navigator.userAgentData; - return null != e2 && e2.brands && Array.isArray(e2.brands) ? e2.brands.map((function(e3) { - return e3.brand + "/" + e3.version; - })).join(" ") : navigator.userAgent; - } - function c() { - return !/^((?!chrome|android).)*safari/i.test(f()); - } - function p(e2, o2, i2) { - void 0 === o2 && (o2 = false), void 0 === i2 && (i2 = false); - var a2 = e2.getBoundingClientRect(), f2 = 1, p2 = 1; - o2 && r(e2) && (f2 = e2.offsetWidth > 0 && s(a2.width) / e2.offsetWidth || 1, p2 = e2.offsetHeight > 0 && s(a2.height) / e2.offsetHeight || 1); - var u2 = (n(e2) ? t(e2) : window).visualViewport, l2 = !c() && i2, d2 = (a2.left + (l2 && u2 ? u2.offsetLeft : 0)) / f2, h2 = (a2.top + (l2 && u2 ? u2.offsetTop : 0)) / p2, m2 = a2.width / f2, v2 = a2.height / p2; - return { width: m2, height: v2, top: h2, right: d2 + m2, bottom: h2 + v2, left: d2, x: d2, y: h2 }; - } - function u(e2) { - var n2 = t(e2); - return { scrollLeft: n2.pageXOffset, scrollTop: n2.pageYOffset }; - } - function l(e2) { - return e2 ? (e2.nodeName || "").toLowerCase() : null; - } - function d(e2) { - return ((n(e2) ? e2.ownerDocument : e2.document) || window.document).documentElement; - } - function h(e2) { - return p(d(e2)).left + u(e2).scrollLeft; - } - function m(e2) { - return t(e2).getComputedStyle(e2); - } - function v(e2) { - var t2 = m(e2), n2 = t2.overflow, r2 = t2.overflowX, o2 = t2.overflowY; - return /auto|scroll|overlay|hidden/.test(n2 + o2 + r2); - } - function y(e2, n2, o2) { - void 0 === o2 && (o2 = false); - var i2, a2, f2 = r(n2), c2 = r(n2) && (function(e3) { - var t2 = e3.getBoundingClientRect(), n3 = s(t2.width) / e3.offsetWidth || 1, r2 = s(t2.height) / e3.offsetHeight || 1; - return 1 !== n3 || 1 !== r2; - })(n2), m2 = d(n2), y2 = p(e2, c2, o2), g2 = { scrollLeft: 0, scrollTop: 0 }, b2 = { x: 0, y: 0 }; - return (f2 || !f2 && !o2) && (("body" !== l(n2) || v(m2)) && (g2 = (i2 = n2) !== t(i2) && r(i2) ? { scrollLeft: (a2 = i2).scrollLeft, scrollTop: a2.scrollTop } : u(i2)), r(n2) ? ((b2 = p(n2, true)).x += n2.clientLeft, b2.y += n2.clientTop) : m2 && (b2.x = h(m2))), { x: y2.left + g2.scrollLeft - b2.x, y: y2.top + g2.scrollTop - b2.y, width: y2.width, height: y2.height }; - } - function g(e2) { - var t2 = p(e2), n2 = e2.offsetWidth, r2 = e2.offsetHeight; - return Math.abs(t2.width - n2) <= 1 && (n2 = t2.width), Math.abs(t2.height - r2) <= 1 && (r2 = t2.height), { x: e2.offsetLeft, y: e2.offsetTop, width: n2, height: r2 }; - } - function b(e2) { - return "html" === l(e2) ? e2 : e2.assignedSlot || e2.parentNode || (o(e2) ? e2.host : null) || d(e2); - } - function x(e2) { - return ["html", "body", "#document"].indexOf(l(e2)) >= 0 ? e2.ownerDocument.body : r(e2) && v(e2) ? e2 : x(b(e2)); - } - function w(e2, n2) { - var r2; - void 0 === n2 && (n2 = []); - var o2 = x(e2), i2 = o2 === (null == (r2 = e2.ownerDocument) ? void 0 : r2.body), a2 = t(o2), s2 = i2 ? [a2].concat(a2.visualViewport || [], v(o2) ? o2 : []) : o2, f2 = n2.concat(s2); - return i2 ? f2 : f2.concat(w(b(s2))); - } - function O(e2) { - return ["table", "td", "th"].indexOf(l(e2)) >= 0; - } - function j(e2) { - return r(e2) && "fixed" !== m(e2).position ? e2.offsetParent : null; - } - function E(e2) { - for (var n2 = t(e2), i2 = j(e2); i2 && O(i2) && "static" === m(i2).position; ) i2 = j(i2); - return i2 && ("html" === l(i2) || "body" === l(i2) && "static" === m(i2).position) ? n2 : i2 || (function(e3) { - var t2 = /firefox/i.test(f()); - if (/Trident/i.test(f()) && r(e3) && "fixed" === m(e3).position) return null; - var n3 = b(e3); - for (o(n3) && (n3 = n3.host); r(n3) && ["html", "body"].indexOf(l(n3)) < 0; ) { - var i3 = m(n3); - if ("none" !== i3.transform || "none" !== i3.perspective || "paint" === i3.contain || -1 !== ["transform", "perspective"].indexOf(i3.willChange) || t2 && "filter" === i3.willChange || t2 && i3.filter && "none" !== i3.filter) return n3; - n3 = n3.parentNode; - } - return null; - })(e2) || n2; - } - var D = "top", A = "bottom", L = "right", P = "left", M = "auto", k = [D, A, L, P], W = "start", B = "end", H = "viewport", T = "popper", R = k.reduce((function(e2, t2) { - return e2.concat([t2 + "-" + W, t2 + "-" + B]); - }), []), S = [].concat(k, [M]).reduce((function(e2, t2) { - return e2.concat([t2, t2 + "-" + W, t2 + "-" + B]); - }), []), V = ["beforeRead", "read", "afterRead", "beforeMain", "main", "afterMain", "beforeWrite", "write", "afterWrite"]; - function q(e2) { - var t2 = /* @__PURE__ */ new Map(), n2 = /* @__PURE__ */ new Set(), r2 = []; - function o2(e3) { - n2.add(e3.name), [].concat(e3.requires || [], e3.requiresIfExists || []).forEach((function(e4) { - if (!n2.has(e4)) { - var r3 = t2.get(e4); - r3 && o2(r3); - } - })), r2.push(e3); - } - return e2.forEach((function(e3) { - t2.set(e3.name, e3); - })), e2.forEach((function(e3) { - n2.has(e3.name) || o2(e3); - })), r2; - } - function C(e2, t2) { - var n2 = t2.getRootNode && t2.getRootNode(); - if (e2.contains(t2)) return true; - if (n2 && o(n2)) { - var r2 = t2; - do { - if (r2 && e2.isSameNode(r2)) return true; - r2 = r2.parentNode || r2.host; - } while (r2); - } - return false; - } - function N(e2) { - return Object.assign({}, e2, { left: e2.x, top: e2.y, right: e2.x + e2.width, bottom: e2.y + e2.height }); - } - function I(e2, r2, o2) { - return r2 === H ? N((function(e3, n2) { - var r3 = t(e3), o3 = d(e3), i2 = r3.visualViewport, a2 = o3.clientWidth, s2 = o3.clientHeight, f2 = 0, p2 = 0; - if (i2) { - a2 = i2.width, s2 = i2.height; - var u2 = c(); - (u2 || !u2 && "fixed" === n2) && (f2 = i2.offsetLeft, p2 = i2.offsetTop); - } - return { width: a2, height: s2, x: f2 + h(e3), y: p2 }; - })(e2, o2)) : n(r2) ? (function(e3, t2) { - var n2 = p(e3, false, "fixed" === t2); - return n2.top = n2.top + e3.clientTop, n2.left = n2.left + e3.clientLeft, n2.bottom = n2.top + e3.clientHeight, n2.right = n2.left + e3.clientWidth, n2.width = e3.clientWidth, n2.height = e3.clientHeight, n2.x = n2.left, n2.y = n2.top, n2; - })(r2, o2) : N((function(e3) { - var t2, n2 = d(e3), r3 = u(e3), o3 = null == (t2 = e3.ownerDocument) ? void 0 : t2.body, a2 = i(n2.scrollWidth, n2.clientWidth, o3 ? o3.scrollWidth : 0, o3 ? o3.clientWidth : 0), s2 = i(n2.scrollHeight, n2.clientHeight, o3 ? o3.scrollHeight : 0, o3 ? o3.clientHeight : 0), f2 = -r3.scrollLeft + h(e3), c2 = -r3.scrollTop; - return "rtl" === m(o3 || n2).direction && (f2 += i(n2.clientWidth, o3 ? o3.clientWidth : 0) - a2), { width: a2, height: s2, x: f2, y: c2 }; - })(d(e2))); - } - function _(e2, t2, o2, s2) { - var f2 = "clippingParents" === t2 ? (function(e3) { - var t3 = w(b(e3)), o3 = ["absolute", "fixed"].indexOf(m(e3).position) >= 0 && r(e3) ? E(e3) : e3; - return n(o3) ? t3.filter((function(e4) { - return n(e4) && C(e4, o3) && "body" !== l(e4); - })) : []; - })(e2) : [].concat(t2), c2 = [].concat(f2, [o2]), p2 = c2[0], u2 = c2.reduce((function(t3, n2) { - var r2 = I(e2, n2, s2); - return t3.top = i(r2.top, t3.top), t3.right = a(r2.right, t3.right), t3.bottom = a(r2.bottom, t3.bottom), t3.left = i(r2.left, t3.left), t3; - }), I(e2, p2, s2)); - return u2.width = u2.right - u2.left, u2.height = u2.bottom - u2.top, u2.x = u2.left, u2.y = u2.top, u2; - } - function F(e2) { - return e2.split("-")[0]; - } - function U(e2) { - return e2.split("-")[1]; - } - function z(e2) { - return ["top", "bottom"].indexOf(e2) >= 0 ? "x" : "y"; - } - function X(e2) { - var t2, n2 = e2.reference, r2 = e2.element, o2 = e2.placement, i2 = o2 ? F(o2) : null, a2 = o2 ? U(o2) : null, s2 = n2.x + n2.width / 2 - r2.width / 2, f2 = n2.y + n2.height / 2 - r2.height / 2; - switch (i2) { - case D: - t2 = { x: s2, y: n2.y - r2.height }; - break; - case A: - t2 = { x: s2, y: n2.y + n2.height }; - break; - case L: - t2 = { x: n2.x + n2.width, y: f2 }; - break; - case P: - t2 = { x: n2.x - r2.width, y: f2 }; - break; - default: - t2 = { x: n2.x, y: n2.y }; - } - var c2 = i2 ? z(i2) : null; - if (null != c2) { - var p2 = "y" === c2 ? "height" : "width"; - switch (a2) { - case W: - t2[c2] = t2[c2] - (n2[p2] / 2 - r2[p2] / 2); - break; - case B: - t2[c2] = t2[c2] + (n2[p2] / 2 - r2[p2] / 2); - } - } - return t2; - } - function Y(e2) { - return Object.assign({}, { top: 0, right: 0, bottom: 0, left: 0 }, e2); - } - function G(e2, t2) { - return t2.reduce((function(t3, n2) { - return t3[n2] = e2, t3; - }), {}); - } - function J(e2, t2) { - void 0 === t2 && (t2 = {}); - var r2 = t2, o2 = r2.placement, i2 = void 0 === o2 ? e2.placement : o2, a2 = r2.strategy, s2 = void 0 === a2 ? e2.strategy : a2, f2 = r2.boundary, c2 = void 0 === f2 ? "clippingParents" : f2, u2 = r2.rootBoundary, l2 = void 0 === u2 ? H : u2, h2 = r2.elementContext, m2 = void 0 === h2 ? T : h2, v2 = r2.altBoundary, y2 = void 0 !== v2 && v2, g2 = r2.padding, b2 = void 0 === g2 ? 0 : g2, x2 = Y("number" != typeof b2 ? b2 : G(b2, k)), w2 = m2 === T ? "reference" : T, O2 = e2.rects.popper, j2 = e2.elements[y2 ? w2 : m2], E2 = _(n(j2) ? j2 : j2.contextElement || d(e2.elements.popper), c2, l2, s2), P2 = p(e2.elements.reference), M2 = X({ reference: P2, element: O2, strategy: "absolute", placement: i2 }), W2 = N(Object.assign({}, O2, M2)), B2 = m2 === T ? W2 : P2, R2 = { top: E2.top - B2.top + x2.top, bottom: B2.bottom - E2.bottom + x2.bottom, left: E2.left - B2.left + x2.left, right: B2.right - E2.right + x2.right }, S2 = e2.modifiersData.offset; - if (m2 === T && S2) { - var V2 = S2[i2]; - Object.keys(R2).forEach((function(e3) { - var t3 = [L, A].indexOf(e3) >= 0 ? 1 : -1, n2 = [D, A].indexOf(e3) >= 0 ? "y" : "x"; - R2[e3] += V2[n2] * t3; - })); - } - return R2; - } - var K = { placement: "bottom", modifiers: [], strategy: "absolute" }; - function Q() { - for (var e2 = arguments.length, t2 = new Array(e2), n2 = 0; n2 < e2; n2++) t2[n2] = arguments[n2]; - return !t2.some((function(e3) { - return !(e3 && "function" == typeof e3.getBoundingClientRect); - })); - } - function Z(e2) { - void 0 === e2 && (e2 = {}); - var t2 = e2, r2 = t2.defaultModifiers, o2 = void 0 === r2 ? [] : r2, i2 = t2.defaultOptions, a2 = void 0 === i2 ? K : i2; - return function(e3, t3, r3) { - void 0 === r3 && (r3 = a2); - var i3, s2, f2 = { placement: "bottom", orderedModifiers: [], options: Object.assign({}, K, a2), modifiersData: {}, elements: { reference: e3, popper: t3 }, attributes: {}, styles: {} }, c2 = [], p2 = false, u2 = { state: f2, setOptions: function(r4) { - var i4 = "function" == typeof r4 ? r4(f2.options) : r4; - l2(), f2.options = Object.assign({}, a2, f2.options, i4), f2.scrollParents = { reference: n(e3) ? w(e3) : e3.contextElement ? w(e3.contextElement) : [], popper: w(t3) }; - var s3, p3, d2 = (function(e4) { - var t4 = q(e4); - return V.reduce((function(e5, n2) { - return e5.concat(t4.filter((function(e6) { - return e6.phase === n2; - }))); - }), []); - })((s3 = [].concat(o2, f2.options.modifiers), p3 = s3.reduce((function(e4, t4) { - var n2 = e4[t4.name]; - return e4[t4.name] = n2 ? Object.assign({}, n2, t4, { options: Object.assign({}, n2.options, t4.options), data: Object.assign({}, n2.data, t4.data) }) : t4, e4; - }), {}), Object.keys(p3).map((function(e4) { - return p3[e4]; - })))); - return f2.orderedModifiers = d2.filter((function(e4) { - return e4.enabled; - })), f2.orderedModifiers.forEach((function(e4) { - var t4 = e4.name, n2 = e4.options, r5 = void 0 === n2 ? {} : n2, o3 = e4.effect; - if ("function" == typeof o3) { - var i5 = o3({ state: f2, name: t4, instance: u2, options: r5 }), a3 = function() { - }; - c2.push(i5 || a3); - } - })), u2.update(); - }, forceUpdate: function() { - if (!p2) { - var e4 = f2.elements, t4 = e4.reference, n2 = e4.popper; - if (Q(t4, n2)) { - f2.rects = { reference: y(t4, E(n2), "fixed" === f2.options.strategy), popper: g(n2) }, f2.reset = false, f2.placement = f2.options.placement, f2.orderedModifiers.forEach((function(e5) { - return f2.modifiersData[e5.name] = Object.assign({}, e5.data); - })); - for (var r4 = 0; r4 < f2.orderedModifiers.length; r4++) if (true !== f2.reset) { - var o3 = f2.orderedModifiers[r4], i4 = o3.fn, a3 = o3.options, s3 = void 0 === a3 ? {} : a3, c3 = o3.name; - "function" == typeof i4 && (f2 = i4({ state: f2, options: s3, name: c3, instance: u2 }) || f2); - } else f2.reset = false, r4 = -1; - } - } - }, update: (i3 = function() { - return new Promise((function(e4) { - u2.forceUpdate(), e4(f2); - })); - }, function() { - return s2 || (s2 = new Promise((function(e4) { - Promise.resolve().then((function() { - s2 = void 0, e4(i3()); - })); - }))), s2; - }), destroy: function() { - l2(), p2 = true; - } }; - if (!Q(e3, t3)) return u2; - function l2() { - c2.forEach((function(e4) { - return e4(); - })), c2 = []; - } - return u2.setOptions(r3).then((function(e4) { - !p2 && r3.onFirstUpdate && r3.onFirstUpdate(e4); - })), u2; - }; - } - var $ = { passive: true }; - var ee = { name: "eventListeners", enabled: true, phase: "write", fn: function() { - }, effect: function(e2) { - var n2 = e2.state, r2 = e2.instance, o2 = e2.options, i2 = o2.scroll, a2 = void 0 === i2 || i2, s2 = o2.resize, f2 = void 0 === s2 || s2, c2 = t(n2.elements.popper), p2 = [].concat(n2.scrollParents.reference, n2.scrollParents.popper); - return a2 && p2.forEach((function(e3) { - e3.addEventListener("scroll", r2.update, $); - })), f2 && c2.addEventListener("resize", r2.update, $), function() { - a2 && p2.forEach((function(e3) { - e3.removeEventListener("scroll", r2.update, $); - })), f2 && c2.removeEventListener("resize", r2.update, $); - }; - }, data: {} }; - var te = { name: "popperOffsets", enabled: true, phase: "read", fn: function(e2) { - var t2 = e2.state, n2 = e2.name; - t2.modifiersData[n2] = X({ reference: t2.rects.reference, element: t2.rects.popper, strategy: "absolute", placement: t2.placement }); - }, data: {} }, ne = { top: "auto", right: "auto", bottom: "auto", left: "auto" }; - function re(e2) { - var n2, r2 = e2.popper, o2 = e2.popperRect, i2 = e2.placement, a2 = e2.variation, f2 = e2.offsets, c2 = e2.position, p2 = e2.gpuAcceleration, u2 = e2.adaptive, l2 = e2.roundOffsets, h2 = e2.isFixed, v2 = f2.x, y2 = void 0 === v2 ? 0 : v2, g2 = f2.y, b2 = void 0 === g2 ? 0 : g2, x2 = "function" == typeof l2 ? l2({ x: y2, y: b2 }) : { x: y2, y: b2 }; - y2 = x2.x, b2 = x2.y; - var w2 = f2.hasOwnProperty("x"), O2 = f2.hasOwnProperty("y"), j2 = P, M2 = D, k2 = window; - if (u2) { - var W2 = E(r2), H2 = "clientHeight", T2 = "clientWidth"; - if (W2 === t(r2) && "static" !== m(W2 = d(r2)).position && "absolute" === c2 && (H2 = "scrollHeight", T2 = "scrollWidth"), W2 = W2, i2 === D || (i2 === P || i2 === L) && a2 === B) M2 = A, b2 -= (h2 && W2 === k2 && k2.visualViewport ? k2.visualViewport.height : W2[H2]) - o2.height, b2 *= p2 ? 1 : -1; - if (i2 === P || (i2 === D || i2 === A) && a2 === B) j2 = L, y2 -= (h2 && W2 === k2 && k2.visualViewport ? k2.visualViewport.width : W2[T2]) - o2.width, y2 *= p2 ? 1 : -1; - } - var R2, S2 = Object.assign({ position: c2 }, u2 && ne), V2 = true === l2 ? (function(e3, t2) { - var n3 = e3.x, r3 = e3.y, o3 = t2.devicePixelRatio || 1; - return { x: s(n3 * o3) / o3 || 0, y: s(r3 * o3) / o3 || 0 }; - })({ x: y2, y: b2 }, t(r2)) : { x: y2, y: b2 }; - return y2 = V2.x, b2 = V2.y, p2 ? Object.assign({}, S2, ((R2 = {})[M2] = O2 ? "0" : "", R2[j2] = w2 ? "0" : "", R2.transform = (k2.devicePixelRatio || 1) <= 1 ? "translate(" + y2 + "px, " + b2 + "px)" : "translate3d(" + y2 + "px, " + b2 + "px, 0)", R2)) : Object.assign({}, S2, ((n2 = {})[M2] = O2 ? b2 + "px" : "", n2[j2] = w2 ? y2 + "px" : "", n2.transform = "", n2)); - } - var oe = { name: "computeStyles", enabled: true, phase: "beforeWrite", fn: function(e2) { - var t2 = e2.state, n2 = e2.options, r2 = n2.gpuAcceleration, o2 = void 0 === r2 || r2, i2 = n2.adaptive, a2 = void 0 === i2 || i2, s2 = n2.roundOffsets, f2 = void 0 === s2 || s2, c2 = { placement: F(t2.placement), variation: U(t2.placement), popper: t2.elements.popper, popperRect: t2.rects.popper, gpuAcceleration: o2, isFixed: "fixed" === t2.options.strategy }; - null != t2.modifiersData.popperOffsets && (t2.styles.popper = Object.assign({}, t2.styles.popper, re(Object.assign({}, c2, { offsets: t2.modifiersData.popperOffsets, position: t2.options.strategy, adaptive: a2, roundOffsets: f2 })))), null != t2.modifiersData.arrow && (t2.styles.arrow = Object.assign({}, t2.styles.arrow, re(Object.assign({}, c2, { offsets: t2.modifiersData.arrow, position: "absolute", adaptive: false, roundOffsets: f2 })))), t2.attributes.popper = Object.assign({}, t2.attributes.popper, { "data-popper-placement": t2.placement }); - }, data: {} }; - var ie = { name: "applyStyles", enabled: true, phase: "write", fn: function(e2) { - var t2 = e2.state; - Object.keys(t2.elements).forEach((function(e3) { - var n2 = t2.styles[e3] || {}, o2 = t2.attributes[e3] || {}, i2 = t2.elements[e3]; - r(i2) && l(i2) && (Object.assign(i2.style, n2), Object.keys(o2).forEach((function(e4) { - var t3 = o2[e4]; - false === t3 ? i2.removeAttribute(e4) : i2.setAttribute(e4, true === t3 ? "" : t3); - }))); - })); - }, effect: function(e2) { - var t2 = e2.state, n2 = { popper: { position: t2.options.strategy, left: "0", top: "0", margin: "0" }, arrow: { position: "absolute" }, reference: {} }; - return Object.assign(t2.elements.popper.style, n2.popper), t2.styles = n2, t2.elements.arrow && Object.assign(t2.elements.arrow.style, n2.arrow), function() { - Object.keys(t2.elements).forEach((function(e3) { - var o2 = t2.elements[e3], i2 = t2.attributes[e3] || {}, a2 = Object.keys(t2.styles.hasOwnProperty(e3) ? t2.styles[e3] : n2[e3]).reduce((function(e4, t3) { - return e4[t3] = "", e4; - }), {}); - r(o2) && l(o2) && (Object.assign(o2.style, a2), Object.keys(i2).forEach((function(e4) { - o2.removeAttribute(e4); - }))); - })); - }; - }, requires: ["computeStyles"] }; - var ae = { name: "offset", enabled: true, phase: "main", requires: ["popperOffsets"], fn: function(e2) { - var t2 = e2.state, n2 = e2.options, r2 = e2.name, o2 = n2.offset, i2 = void 0 === o2 ? [0, 0] : o2, a2 = S.reduce((function(e3, n3) { - return e3[n3] = (function(e4, t3, n4) { - var r3 = F(e4), o3 = [P, D].indexOf(r3) >= 0 ? -1 : 1, i3 = "function" == typeof n4 ? n4(Object.assign({}, t3, { placement: e4 })) : n4, a3 = i3[0], s3 = i3[1]; - return a3 = a3 || 0, s3 = (s3 || 0) * o3, [P, L].indexOf(r3) >= 0 ? { x: s3, y: a3 } : { x: a3, y: s3 }; - })(n3, t2.rects, i2), e3; - }), {}), s2 = a2[t2.placement], f2 = s2.x, c2 = s2.y; - null != t2.modifiersData.popperOffsets && (t2.modifiersData.popperOffsets.x += f2, t2.modifiersData.popperOffsets.y += c2), t2.modifiersData[r2] = a2; - } }, se = { left: "right", right: "left", bottom: "top", top: "bottom" }; - function fe(e2) { - return e2.replace(/left|right|bottom|top/g, (function(e3) { - return se[e3]; - })); - } - var ce = { start: "end", end: "start" }; - function pe(e2) { - return e2.replace(/start|end/g, (function(e3) { - return ce[e3]; - })); - } - function ue(e2, t2) { - void 0 === t2 && (t2 = {}); - var n2 = t2, r2 = n2.placement, o2 = n2.boundary, i2 = n2.rootBoundary, a2 = n2.padding, s2 = n2.flipVariations, f2 = n2.allowedAutoPlacements, c2 = void 0 === f2 ? S : f2, p2 = U(r2), u2 = p2 ? s2 ? R : R.filter((function(e3) { - return U(e3) === p2; - })) : k, l2 = u2.filter((function(e3) { - return c2.indexOf(e3) >= 0; - })); - 0 === l2.length && (l2 = u2); - var d2 = l2.reduce((function(t3, n3) { - return t3[n3] = J(e2, { placement: n3, boundary: o2, rootBoundary: i2, padding: a2 })[F(n3)], t3; - }), {}); - return Object.keys(d2).sort((function(e3, t3) { - return d2[e3] - d2[t3]; - })); - } - var le = { name: "flip", enabled: true, phase: "main", fn: function(e2) { - var t2 = e2.state, n2 = e2.options, r2 = e2.name; - if (!t2.modifiersData[r2]._skip) { - for (var o2 = n2.mainAxis, i2 = void 0 === o2 || o2, a2 = n2.altAxis, s2 = void 0 === a2 || a2, f2 = n2.fallbackPlacements, c2 = n2.padding, p2 = n2.boundary, u2 = n2.rootBoundary, l2 = n2.altBoundary, d2 = n2.flipVariations, h2 = void 0 === d2 || d2, m2 = n2.allowedAutoPlacements, v2 = t2.options.placement, y2 = F(v2), g2 = f2 || (y2 === v2 || !h2 ? [fe(v2)] : (function(e3) { - if (F(e3) === M) return []; - var t3 = fe(e3); - return [pe(e3), t3, pe(t3)]; - })(v2)), b2 = [v2].concat(g2).reduce((function(e3, n3) { - return e3.concat(F(n3) === M ? ue(t2, { placement: n3, boundary: p2, rootBoundary: u2, padding: c2, flipVariations: h2, allowedAutoPlacements: m2 }) : n3); - }), []), x2 = t2.rects.reference, w2 = t2.rects.popper, O2 = /* @__PURE__ */ new Map(), j2 = true, E2 = b2[0], k2 = 0; k2 < b2.length; k2++) { - var B2 = b2[k2], H2 = F(B2), T2 = U(B2) === W, R2 = [D, A].indexOf(H2) >= 0, S2 = R2 ? "width" : "height", V2 = J(t2, { placement: B2, boundary: p2, rootBoundary: u2, altBoundary: l2, padding: c2 }), q2 = R2 ? T2 ? L : P : T2 ? A : D; - x2[S2] > w2[S2] && (q2 = fe(q2)); - var C2 = fe(q2), N2 = []; - if (i2 && N2.push(V2[H2] <= 0), s2 && N2.push(V2[q2] <= 0, V2[C2] <= 0), N2.every((function(e3) { - return e3; - }))) { - E2 = B2, j2 = false; - break; - } - O2.set(B2, N2); - } - if (j2) for (var I2 = function(e3) { - var t3 = b2.find((function(t4) { - var n3 = O2.get(t4); - if (n3) return n3.slice(0, e3).every((function(e4) { - return e4; - })); - })); - if (t3) return E2 = t3, "break"; - }, _2 = h2 ? 3 : 1; _2 > 0; _2--) { - if ("break" === I2(_2)) break; - } - t2.placement !== E2 && (t2.modifiersData[r2]._skip = true, t2.placement = E2, t2.reset = true); - } - }, requiresIfExists: ["offset"], data: { _skip: false } }; - function de(e2, t2, n2) { - return i(e2, a(t2, n2)); - } - var he = { name: "preventOverflow", enabled: true, phase: "main", fn: function(e2) { - var t2 = e2.state, n2 = e2.options, r2 = e2.name, o2 = n2.mainAxis, s2 = void 0 === o2 || o2, f2 = n2.altAxis, c2 = void 0 !== f2 && f2, p2 = n2.boundary, u2 = n2.rootBoundary, l2 = n2.altBoundary, d2 = n2.padding, h2 = n2.tether, m2 = void 0 === h2 || h2, v2 = n2.tetherOffset, y2 = void 0 === v2 ? 0 : v2, b2 = J(t2, { boundary: p2, rootBoundary: u2, padding: d2, altBoundary: l2 }), x2 = F(t2.placement), w2 = U(t2.placement), O2 = !w2, j2 = z(x2), M2 = "x" === j2 ? "y" : "x", k2 = t2.modifiersData.popperOffsets, B2 = t2.rects.reference, H2 = t2.rects.popper, T2 = "function" == typeof y2 ? y2(Object.assign({}, t2.rects, { placement: t2.placement })) : y2, R2 = "number" == typeof T2 ? { mainAxis: T2, altAxis: T2 } : Object.assign({ mainAxis: 0, altAxis: 0 }, T2), S2 = t2.modifiersData.offset ? t2.modifiersData.offset[t2.placement] : null, V2 = { x: 0, y: 0 }; - if (k2) { - if (s2) { - var q2, C2 = "y" === j2 ? D : P, N2 = "y" === j2 ? A : L, I2 = "y" === j2 ? "height" : "width", _2 = k2[j2], X2 = _2 + b2[C2], Y2 = _2 - b2[N2], G2 = m2 ? -H2[I2] / 2 : 0, K2 = w2 === W ? B2[I2] : H2[I2], Q2 = w2 === W ? -H2[I2] : -B2[I2], Z2 = t2.elements.arrow, $2 = m2 && Z2 ? g(Z2) : { width: 0, height: 0 }, ee2 = t2.modifiersData["arrow#persistent"] ? t2.modifiersData["arrow#persistent"].padding : { top: 0, right: 0, bottom: 0, left: 0 }, te2 = ee2[C2], ne2 = ee2[N2], re2 = de(0, B2[I2], $2[I2]), oe2 = O2 ? B2[I2] / 2 - G2 - re2 - te2 - R2.mainAxis : K2 - re2 - te2 - R2.mainAxis, ie2 = O2 ? -B2[I2] / 2 + G2 + re2 + ne2 + R2.mainAxis : Q2 + re2 + ne2 + R2.mainAxis, ae2 = t2.elements.arrow && E(t2.elements.arrow), se2 = ae2 ? "y" === j2 ? ae2.clientTop || 0 : ae2.clientLeft || 0 : 0, fe2 = null != (q2 = null == S2 ? void 0 : S2[j2]) ? q2 : 0, ce2 = _2 + ie2 - fe2, pe2 = de(m2 ? a(X2, _2 + oe2 - fe2 - se2) : X2, _2, m2 ? i(Y2, ce2) : Y2); - k2[j2] = pe2, V2[j2] = pe2 - _2; - } - if (c2) { - var ue2, le2 = "x" === j2 ? D : P, he2 = "x" === j2 ? A : L, me2 = k2[M2], ve2 = "y" === M2 ? "height" : "width", ye2 = me2 + b2[le2], ge2 = me2 - b2[he2], be2 = -1 !== [D, P].indexOf(x2), xe2 = null != (ue2 = null == S2 ? void 0 : S2[M2]) ? ue2 : 0, we2 = be2 ? ye2 : me2 - B2[ve2] - H2[ve2] - xe2 + R2.altAxis, Oe = be2 ? me2 + B2[ve2] + H2[ve2] - xe2 - R2.altAxis : ge2, je = m2 && be2 ? (function(e3, t3, n3) { - var r3 = de(e3, t3, n3); - return r3 > n3 ? n3 : r3; - })(we2, me2, Oe) : de(m2 ? we2 : ye2, me2, m2 ? Oe : ge2); - k2[M2] = je, V2[M2] = je - me2; - } - t2.modifiersData[r2] = V2; - } - }, requiresIfExists: ["offset"] }; - var me = { name: "arrow", enabled: true, phase: "main", fn: function(e2) { - var t2, n2 = e2.state, r2 = e2.name, o2 = e2.options, i2 = n2.elements.arrow, a2 = n2.modifiersData.popperOffsets, s2 = F(n2.placement), f2 = z(s2), c2 = [P, L].indexOf(s2) >= 0 ? "height" : "width"; - if (i2 && a2) { - var p2 = (function(e3, t3) { - return Y("number" != typeof (e3 = "function" == typeof e3 ? e3(Object.assign({}, t3.rects, { placement: t3.placement })) : e3) ? e3 : G(e3, k)); - })(o2.padding, n2), u2 = g(i2), l2 = "y" === f2 ? D : P, d2 = "y" === f2 ? A : L, h2 = n2.rects.reference[c2] + n2.rects.reference[f2] - a2[f2] - n2.rects.popper[c2], m2 = a2[f2] - n2.rects.reference[f2], v2 = E(i2), y2 = v2 ? "y" === f2 ? v2.clientHeight || 0 : v2.clientWidth || 0 : 0, b2 = h2 / 2 - m2 / 2, x2 = p2[l2], w2 = y2 - u2[c2] - p2[d2], O2 = y2 / 2 - u2[c2] / 2 + b2, j2 = de(x2, O2, w2), M2 = f2; - n2.modifiersData[r2] = ((t2 = {})[M2] = j2, t2.centerOffset = j2 - O2, t2); - } - }, effect: function(e2) { - var t2 = e2.state, n2 = e2.options.element, r2 = void 0 === n2 ? "[data-popper-arrow]" : n2; - null != r2 && ("string" != typeof r2 || (r2 = t2.elements.popper.querySelector(r2))) && C(t2.elements.popper, r2) && (t2.elements.arrow = r2); - }, requires: ["popperOffsets"], requiresIfExists: ["preventOverflow"] }; - function ve(e2, t2, n2) { - return void 0 === n2 && (n2 = { x: 0, y: 0 }), { top: e2.top - t2.height - n2.y, right: e2.right - t2.width + n2.x, bottom: e2.bottom - t2.height + n2.y, left: e2.left - t2.width - n2.x }; - } - function ye(e2) { - return [D, L, A, P].some((function(t2) { - return e2[t2] >= 0; - })); - } - var ge = { name: "hide", enabled: true, phase: "main", requiresIfExists: ["preventOverflow"], fn: function(e2) { - var t2 = e2.state, n2 = e2.name, r2 = t2.rects.reference, o2 = t2.rects.popper, i2 = t2.modifiersData.preventOverflow, a2 = J(t2, { elementContext: "reference" }), s2 = J(t2, { altBoundary: true }), f2 = ve(a2, r2), c2 = ve(s2, o2, i2), p2 = ye(f2), u2 = ye(c2); - t2.modifiersData[n2] = { referenceClippingOffsets: f2, popperEscapeOffsets: c2, isReferenceHidden: p2, hasPopperEscaped: u2 }, t2.attributes.popper = Object.assign({}, t2.attributes.popper, { "data-popper-reference-hidden": p2, "data-popper-escaped": u2 }); - } }, be = Z({ defaultModifiers: [ee, te, oe, ie] }), xe = [ee, te, oe, ie, ae, le, he, me, ge], we = Z({ defaultModifiers: xe }); - e.applyStyles = ie, e.arrow = me, e.computeStyles = oe, e.createPopper = we, e.createPopperLite = be, e.defaultModifiers = xe, e.detectOverflow = J, e.eventListeners = ee, e.flip = le, e.hide = ge, e.offset = ae, e.popperGenerator = Z, e.popperOffsets = te, e.preventOverflow = he, Object.defineProperty(e, "__esModule", { value: true }); - })); - } -}); - // frontend/js/vendor/flatpickr.js var require_flatpickr = __commonJS({ "frontend/js/vendor/flatpickr.js"(exports, module) { @@ -1647,127 +1170,11 @@ var LogList = class { }; var logList_default = LogList; -// frontend/js/components/customSelectV2.js -var import_popper_esm_min = __toESM(require_popper_esm_min()); -var CustomSelectV2 = class _CustomSelectV2 { - constructor(container) { - this.container = container; - this.trigger = this.container.querySelector(".custom-select-trigger"); - this.nativeSelect = this.container.querySelector("select"); - this.template = this.container.querySelector(".custom-select-panel-template"); - if (!this.trigger || !this.nativeSelect || !this.template) { - console.warn("CustomSelectV2 cannot initialize: missing required elements.", this.container); - return; - } - this.panel = null; - this.popperInstance = null; - this.isOpen = false; - this.triggerText = this.trigger.querySelector("span"); - if (typeof _CustomSelectV2.openInstance === "undefined") { - _CustomSelectV2.openInstance = null; - _CustomSelectV2.initGlobalListener(); - } - this.updateTriggerText(); - this.bindEvents(); - } - static initGlobalListener() { - document.addEventListener("click", (event) => { - const instance = _CustomSelectV2.openInstance; - if (instance && !instance.container.contains(event.target) && (!instance.panel || !instance.panel.contains(event.target))) { - instance.close(); - } - }); - } - createPanel() { - const panelFragment = this.template.content.cloneNode(true); - this.panel = panelFragment.querySelector(".custom-select-panel"); - document.body.appendChild(this.panel); - this.panel.innerHTML = ""; - Array.from(this.nativeSelect.options).forEach((option) => { - const item = document.createElement("a"); - item.href = "#"; - item.className = "custom-select-option block w-full text-left px-3 py-1.5 text-sm text-zinc-700 hover:bg-zinc-100 dark:text-zinc-200 dark:hover:bg-zinc-700"; - item.textContent = option.textContent; - item.dataset.value = option.value; - if (option.selected) { - item.classList.add("is-selected"); - } - this.panel.appendChild(item); - }); - this.panel.addEventListener("click", (event) => { - event.preventDefault(); - const optionEl = event.target.closest(".custom-select-option"); - if (optionEl) { - this.selectOption(optionEl); - } - }); - } - bindEvents() { - this.trigger.addEventListener("click", (event) => { - event.stopPropagation(); - if (_CustomSelectV2.openInstance && _CustomSelectV2.openInstance !== this) { - _CustomSelectV2.openInstance.close(); - } - this.toggle(); - }); - } - selectOption(optionEl) { - const selectedValue = optionEl.dataset.value; - if (this.nativeSelect.value !== selectedValue) { - this.nativeSelect.value = selectedValue; - this.nativeSelect.dispatchEvent(new Event("change", { bubbles: true })); - } - this.updateTriggerText(); - this.close(); - } - updateTriggerText() { - const selectedOption = this.nativeSelect.options[this.nativeSelect.selectedIndex]; - if (selectedOption) { - this.triggerText.textContent = selectedOption.textContent; - } - } - toggle() { - this.isOpen ? this.close() : this.open(); - } - open() { - if (this.isOpen) return; - this.isOpen = true; - if (!this.panel) { - this.createPanel(); - } - this.panel.style.display = "block"; - this.panel.offsetHeight; - this.popperInstance = (0, import_popper_esm_min.createPopper)(this.trigger, this.panel, { - placement: "top-start", - modifiers: [ - { name: "offset", options: { offset: [0, 8] } }, - { name: "flip", options: { fallbackPlacements: ["bottom-start"] } } - ] - }); - _CustomSelectV2.openInstance = this; - } - close() { - if (!this.isOpen) return; - this.isOpen = false; - if (this.popperInstance) { - this.popperInstance.destroy(); - this.popperInstance = null; - } - if (this.panel) { - this.panel.remove(); - this.panel = null; - } - if (_CustomSelectV2.openInstance === this) { - _CustomSelectV2.openInstance = null; - } - } -}; - // frontend/js/components/filterPopover.js -var import_popper_esm_min2 = __toESM(require_popper_esm_min()); +var import_popper_esm_min = __toESM(require_popper_esm_min()); var FilterPopover = class { constructor(triggerElement, options, title) { - if (!triggerElement || typeof import_popper_esm_min2.createPopper !== "function") { + if (!triggerElement || typeof import_popper_esm_min.createPopper !== "function") { console.error("FilterPopover: Trigger element or Popper.js not found."); return; } @@ -1776,7 +1183,7 @@ var FilterPopover = class { this.title = title; this.selectedValues = /* @__PURE__ */ new Set(); this._createPopoverHTML(); - this.popperInstance = (0, import_popper_esm_min2.createPopper)(this.triggerElement, this.popoverElement, { + this.popperInstance = (0, import_popper_esm_min.createPopper)(this.triggerElement, this.popoverElement, { placement: "bottom-start", modifiers: [{ name: "offset", options: { offset: [0, 8] } }] }); diff --git a/web/static/js/main.js b/web/static/js/main.js index 9c89f76..e55a067 100644 --- a/web/static/js/main.js +++ b/web/static/js/main.js @@ -8,7 +8,7 @@ import { apiFetchJson, modalManager, uiPatterns -} from "./chunk-SHK62ZJN.js"; +} from "./chunk-VOGCL6QZ.js"; import "./chunk-JSBRDJBE.js"; // frontend/js/vendor/sweetalert2.esm.js @@ -4631,8 +4631,9 @@ var pageModules = { // 键 'dashboard' 对应一个函数,该函数调用 import() 返回一个 Promise // esbuild 看到这个 import() 语法,就会自动将 dashboard.js 及其依赖打包成一个独立的 chunk 文件 "dashboard": () => import("./dashboard-XFUWX3IN.js"), - "keys": () => import("./keys-YEK3YJ77.js"), - "logs": () => import("./logs-SSK3L2XT.js") + "keys": () => import("./keys-V4KPRAAB.js"), + "logs": () => import("./logs-4XXDCFYG.js"), + "chat": () => import("./chat-2W4NJWMO.js") // 'settings': () => import('./pages/settings.js'), // 未来启用 settings 页面 // 未来新增的页面,只需在这里添加一行映射,esbuild会自动处理 }; diff --git a/web/templates/chat.html b/web/templates/chat.html index 3755f99..5c0da4c 100644 --- a/web/templates/chat.html +++ b/web/templates/chat.html @@ -8,47 +8,118 @@ + + + @@ -58,9 +129,9 @@
    -

    关于Python异步编程

    +

    新会话

    -
    -
    -
    - -
    - - - -
    -
    -

    你能给我解释一下 aiohttp 客户端的 session 和 connector 管理吗?我总是搞不清楚什么时候应该创建,什么时候应该关闭。

    -
    -
    -
    - -
    - - - -
    -
    -

    当然可以。这是一个非常经典的问题。简单来说,`ClientSession` 应该在你的应用程序的生命周期内尽可能地保持单例存在...

    -
    -
    -
    +
    +
    +
    -
    - -
    - + -
    -
    +
    {% endblock %} {% block page_scripts %} + {% endblock page_scripts %} \ No newline at end of file