diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml deleted file mode 100644 index 2701862..0000000 --- a/.forgejo/workflows/deploy.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Deploy - -on: - push: - branches: - - main - -jobs: - deploy: - name: Deploy to Production - runs-on: docker - steps: - - name: Checkout code - run: | - git clone --depth 1 --branch main https://oauth2:${{ github.token }}@forge.studio-variable.com/${{ github.repository }}.git . - ls -la - - - name: Deploy via FTP - env: - USERNAME: ${{ secrets.USERNAME }} - PASSWORD: ${{ secrets.PASSWORD }} - HOST: ${{ secrets.HOST }} - run: | - apt-get update -qq && apt-get install -y -qq lftp - cat > /tmp/lftp-script.txt < - - - -{#if showLoop} -
- - - - {#each visibleComments as comment (comment.id)} - - {/each} - - -{/if} - - diff --git a/site/plugins/loop/frontend/src/composables/decodeHTMLEntities.ts b/site/plugins/loop/frontend/src/composables/decodeHTMLEntities.ts deleted file mode 100644 index e65ea71..0000000 --- a/site/plugins/loop/frontend/src/composables/decodeHTMLEntities.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Decodes HTML entities in a string - * @param text The text that may contain HTML entities - * @returns The decoded text - */ -export function decodeHTMLEntities(text: string): string { - const entityMap: Record = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - ''': "'", - '/': '/', - '`': '`', - '=': '=' - }; - - return text.replace(/&[#\w]+;/g, (entity) => entityMap[entity] || entity); -} diff --git a/site/plugins/loop/frontend/src/composables/formatDate.ts b/site/plugins/loop/frontend/src/composables/formatDate.ts deleted file mode 100644 index 3b8177c..0000000 --- a/site/plugins/loop/frontend/src/composables/formatDate.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { t, tt } from "../store/translations.svelte"; - -export function formatDate(timestamp: number, humanize = true): string { - const date = new Date(timestamp * 1000); - const now = new Date(); - const diffInMs = now.getTime() - date.getTime(); - const diffInMinutes = Math.floor(diffInMs / (1000 * 60)); - const diffInHours = Math.floor(diffInMs / (1000 * 60 * 60)); - const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24)); - - // Show relative time for up to 3 days - if (humanize && diffInDays <= 3) { - if (diffInMinutes < 1) { - return t("ui.time.just_now", "just now"); - } else if (diffInMinutes === 1) { - return t("ui.time.minute_ago", "a minute ago"); - } else if (diffInMinutes < 60) { - return tt("ui.time.minutes_ago", "{count} minutes ago", { count: diffInMinutes.toString() }); - } else if (diffInHours === 1) { - return t("ui.time.hour_ago", "an hour ago"); - } else if (diffInHours < 24) { - return tt("ui.time.hours_ago", "{count} hours ago", { count: diffInHours.toString() }); - } else if (diffInDays === 1) { - return t("ui.time.yesterday", "yesterday"); - } else { - return tt("ui.time.days_ago", "{count} days ago", { count: diffInDays.toString() }); - } - } - - return date.toLocaleString(undefined, { dateStyle: "short", timeStyle: "short" }); -} diff --git a/site/plugins/loop/frontend/src/composables/formatDateISO.ts b/site/plugins/loop/frontend/src/composables/formatDateISO.ts deleted file mode 100644 index ba5c164..0000000 --- a/site/plugins/loop/frontend/src/composables/formatDateISO.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function formatDateISO(timestamp: number): string { - return new Date(timestamp * 1000).toISOString(); -} \ No newline at end of file diff --git a/site/plugins/loop/frontend/src/composables/getDialogPosition.ts b/site/plugins/loop/frontend/src/composables/getDialogPosition.ts deleted file mode 100644 index 1e54920..0000000 --- a/site/plugins/loop/frontend/src/composables/getDialogPosition.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { getDocumentHeight } from "./getDocumentHeight"; -import { getDocumentWidth } from "./getDocumentWidth"; - -export const getDialogPosition = (marker: { pagePositionX: number, pagePositionY: number } | null, - dialogElement: HTMLDialogElement | null): { left: number, top: number } => { - // Default position (fallback) - let left = 0; - let top = 0; - - if (!marker || !dialogElement) return { left, top }; - - // Get marker position - left = marker.pagePositionX; - top = marker.pagePositionY; - - // Get dialog dimensions - const dialogWidth = dialogElement.offsetWidth; - const dialogHeight = dialogElement.offsetHeight; - - // Get document dimensions - const documentWidth = getDocumentWidth(); - const documentHeight = getDocumentHeight(); - - // Ensure dialog doesn't go off-screen to the right - if (left + dialogWidth > documentWidth) { - left = documentWidth - dialogWidth; - } - - // Ensure dialog doesn't go off-screen to the bottom - if (top + dialogHeight > documentHeight) { - top = documentHeight - dialogHeight; - } - - // Ensure dialog doesn't go off-screen to the left or top - left = Math.max(0, left); - top = Math.max(0, top); - - return { left, top }; -} diff --git a/site/plugins/loop/frontend/src/composables/getDocumentHeight.ts b/site/plugins/loop/frontend/src/composables/getDocumentHeight.ts deleted file mode 100644 index 8171a77..0000000 --- a/site/plugins/loop/frontend/src/composables/getDocumentHeight.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Get the entire document height, including scrollable area -export const getDocumentHeight = (): number => { - const body = document.body; - const html = document.documentElement; - - return Math.max( - body.scrollHeight, - body.offsetHeight, - html.clientHeight, - html.scrollHeight, - html.offsetHeight - ); -}; diff --git a/site/plugins/loop/frontend/src/composables/getDocumentWidth.ts b/site/plugins/loop/frontend/src/composables/getDocumentWidth.ts deleted file mode 100644 index 1eb49d6..0000000 --- a/site/plugins/loop/frontend/src/composables/getDocumentWidth.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Get the entire document width, including scrollable area -export const getDocumentWidth = (): number => { - const body = document.body; - const html = document.documentElement; - - return Math.max( - body.scrollWidth, - body.offsetWidth, - html.clientWidth, - html.scrollWidth, - html.offsetWidth - ); -}; diff --git a/site/plugins/loop/frontend/src/composables/getSelectorOffset.ts b/site/plugins/loop/frontend/src/composables/getSelectorOffset.ts deleted file mode 100644 index 4a35241..0000000 --- a/site/plugins/loop/frontend/src/composables/getSelectorOffset.ts +++ /dev/null @@ -1,26 +0,0 @@ -export const getSelectorOffset = (e: MouseEvent, element: HTMLElement): { selectorOffsetX: number, selectorOffsetY: number } => { - // Get absolute click position (relative to the document) - const clickX = e.pageX; - const clickY = e.pageY; - - // Get element's position relative to the document - const rect = element.getBoundingClientRect(); - const elementX = rect.left + window.scrollX; - const elementY = rect.top + window.scrollY; - - // Calculate relative offsets - const offsetXRel = clickX - elementX; - const offsetYRel = clickY - elementY; - - // Convert to percentages - let offsetX = (offsetXRel / element.offsetWidth) * 100; - let offsetY = (offsetYRel / element.offsetHeight) * 100; - - // Round to 2 decimal places - offsetX = Number(offsetX.toFixed(2)); - offsetY = Number(offsetY.toFixed(2)); - - return { - selectorOffsetX: offsetX, selectorOffsetY: offsetY - }; -} diff --git a/site/plugins/loop/frontend/src/composables/setNewMarker.ts b/site/plugins/loop/frontend/src/composables/setNewMarker.ts deleted file mode 100644 index 09802a4..0000000 --- a/site/plugins/loop/frontend/src/composables/setNewMarker.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { useGenerateSelector } from "./useGenerateSelector"; -import { getSelectorOffset } from "./getSelectorOffset"; - -export const setNewMarker = (e: MouseEvent) => { - - const selector = useGenerateSelector(e); - const element: HTMLElement | null = document.querySelector(selector); - - // error out, if no selector found - if (!element) return; - - const { selectorOffsetX, selectorOffsetY } = getSelectorOffset(e, element); - - // Store absolute position on the page - let pagePositionX = e.pageX; - let pagePositionY = e.pageY; - - // Round to 2 digits - pagePositionX = Number(pagePositionX.toFixed(2)); - pagePositionY = Number(pagePositionY.toFixed(2)); - - return { - selector, - selectorOffsetX, - selectorOffsetY, - pagePositionX, - pagePositionY - } - -} - -export default setNewMarker; diff --git a/site/plugins/loop/frontend/src/composables/useGenerateSelector.ts b/site/plugins/loop/frontend/src/composables/useGenerateSelector.ts deleted file mode 100644 index 8c06b59..0000000 --- a/site/plugins/loop/frontend/src/composables/useGenerateSelector.ts +++ /dev/null @@ -1,352 +0,0 @@ -/** - * CSS Selector Generator Composable - * Generates reliable, unique CSS selectors for clicked DOM elements - */ - -type SelectorStrategy = { - name: string; - generator: (element: Element) => string | null; - priority: number; -}; - -/** - * Main composable function to generate CSS selector from click event - * @param event - Mouse event from user click - * @returns CSS selector string that uniquely identifies the clicked element - */ -export function useGenerateSelector(event: MouseEvent): string { - const target = event.target as Element; - - if (!target) { - throw new Error('No target element found in event'); - } - - // Try each strategy in priority order - const strategies = getSelectorStrategies(); - - for (const strategy of strategies) { - try { - const selector = strategy.generator(target); - - if (selector && validateSelector(selector, target)) { - return selector; - } - } catch (error) { - console.warn(`Strategy ${strategy.name} failed:`, error); - } - } - - // Ultimate fallback - generate a path selector - return generatePathSelector(target); -} - -/** - * Define selector generation strategies in priority order - */ -function getSelectorStrategies(): SelectorStrategy[] { - return [ - { - name: 'ID', - priority: 1, - generator: (element: Element) => { - if (element.id && isValidId(element.id)) { - return `#${CSS.escape(element.id)}`; - } - return null; - } - }, - { - name: 'Unique Attributes', - priority: 2, - generator: (element: Element) => { - const uniqueAttrs = ['data-testid', 'data-id', 'name', 'for']; - - for (const attr of uniqueAttrs) { - const value = element.getAttribute(attr); - if (value) { - const selector = `${element.tagName.toLowerCase()}[${attr}="${CSS.escape(value)}"]`; - if (isUniqueSelector(selector)) { - return selector; - } - } - } - return null; - } - }, - { - name: 'Semantic Attributes', - priority: 3, - generator: (element: Element) => { - const semanticAttrs = [ - 'aria-label', - 'aria-labelledby', - 'role', - 'type', - 'placeholder', - 'title', - 'alt' - ]; - - const tagName = element.tagName.toLowerCase(); - const selectors: string[] = [tagName]; - - for (const attr of semanticAttrs) { - const value = element.getAttribute(attr); - if (value) { - selectors.push(`[${attr}="${CSS.escape(value)}"]`); - } - } - - if (selectors.length > 1) { - const selector = selectors.join(''); - if (isUniqueSelector(selector)) { - return selector; - } - } - - return null; - } - }, - { - name: 'Structural Attributes', - priority: 4, - generator: (element: Element) => { - const structuralAttrs = ['href', 'src', 'action', 'value']; - const tagName = element.tagName.toLowerCase(); - - for (const attr of structuralAttrs) { - const value = element.getAttribute(attr); - if (value && value.length > 0) { - const selector = `${tagName}[${attr}="${CSS.escape(value)}"]`; - if (isUniqueSelector(selector)) { - return selector; - } - } - } - - return null; - } - }, - { - name: 'Class Combinations', - priority: 5, - generator: (element: Element) => { - const classes = getStableClasses(element); - - if (classes.length === 0) { - return null; - } - - const tagName = element.tagName.toLowerCase(); - - // Try single class first - for (const className of classes) { - const selector = `${tagName}.${CSS.escape(className)}`; - if (isUniqueSelector(selector)) { - return selector; - } - } - - // Try combinations of classes - if (classes.length >= 2) { - const classSelector = classes.slice(0, 3).map(c => `.${CSS.escape(c)}`).join(''); - const selector = `${tagName}${classSelector}`; - if (isUniqueSelector(selector)) { - return selector; - } - } - - return null; - } - }, - { - name: 'Parent Context', - priority: 6, - generator: (element: Element) => { - const parent = element.parentElement; - if (!parent) return null; - - // Try to get a unique selector for parent - const parentSelector = getSimpleSelector(parent); - if (!parentSelector) return null; - - const tagName = element.tagName.toLowerCase(); - const siblingIndex = getSiblingIndex(element); - - if (siblingIndex > 0) { - const selector = `${parentSelector} > ${tagName}:nth-of-type(${siblingIndex})`; - if (isUniqueSelector(selector)) { - return selector; - } - } - - // Try with classes - const classes = getStableClasses(element); - if (classes.length > 0) { - const selector = `${parentSelector} > ${tagName}.${CSS.escape(classes[0])}`; - if (isUniqueSelector(selector)) { - return selector; - } - } - - return null; - } - } - ]; -} - -/** - * Get stable classes (excluding utility/state classes) - */ -function getStableClasses(element: Element): string[] { - const classes = Array.from(element.classList); - - // Filter out common utility/state classes - const unstablePatterns = [ - /^(is-|has-|js-)/, // State prefixes - /^(active|disabled|loading|selected|hover|focus)/, // State classes - /^[a-z]+-[0-9]+$/, // Generated classes like 'item-123' - /^(sm-|md-|lg-|xl-)/, // Responsive utilities - /^(m-|p-|w-|h-|text-|bg-)/, // Tailwind-like utilities - /^[a-f0-9]{6,}$/, // Hash-like classes - ]; - - return classes.filter(className => { - return !unstablePatterns.some(pattern => pattern.test(className)); - }); -} - -/** - * Generate a path-based selector as fallback - */ -function generatePathSelector(element: Element): string { - const path: string[] = []; - let current: Element | null = element; - - while (current && current !== document.body && path.length < 5) { - const selector = getElementSelector(current); - path.unshift(selector); - - // Check if this partial path is unique - const partialSelector = path.join(' > '); - if (isUniqueSelector(partialSelector)) { - return partialSelector; - } - - current = current.parentElement; - } - - return path.join(' > '); -} - -/** - * Get a simple selector for an element - */ -function getSimpleSelector(element: Element): string | null { - // Try ID first - if (element.id && isValidId(element.id)) { - return `#${CSS.escape(element.id)}`; - } - - // Try unique attributes - const uniqueAttrs = ['data-testid', 'data-id', 'name']; - for (const attr of uniqueAttrs) { - const value = element.getAttribute(attr); - if (value) { - return `[${attr}="${CSS.escape(value)}"]`; - } - } - - // Try tag + first stable class - const tagName = element.tagName.toLowerCase(); - const classes = getStableClasses(element); - - if (classes.length > 0) { - return `${tagName}.${CSS.escape(classes[0])}`; - } - - return null; -} - -/** - * Get selector for element in path - */ -function getElementSelector(element: Element): string { - const tagName = element.tagName.toLowerCase(); - - // Use ID if available - if (element.id && isValidId(element.id)) { - return `#${CSS.escape(element.id)}`; - } - - // Use classes if available - const classes = getStableClasses(element); - if (classes.length > 0) { - return `${tagName}.${CSS.escape(classes[0])}`; - } - - // Use nth-of-type for siblings - const index = getSiblingIndex(element); - if (index > 1) { - return `${tagName}:nth-of-type(${index})`; - } - - return tagName; -} - -/** - * Get sibling index for nth-of-type - */ -function getSiblingIndex(element: Element): number { - let index = 1; - let sibling = element.previousElementSibling; - - while (sibling) { - if (sibling.tagName === element.tagName) { - index++; - } - sibling = sibling.previousElementSibling; - } - - return index; -} - -/** - * Validate that a selector uniquely identifies the target element - */ -function validateSelector(selector: string, target: Element): boolean { - try { - const matches = document.querySelectorAll(selector); - return matches.length === 1 && matches[0] === target; - } catch (error) { - console.warn(`Invalid selector: ${selector}`, error); - return false; - } -} - -/** - * Check if a selector matches exactly one element - */ -function isUniqueSelector(selector: string): boolean { - try { - const matches = document.querySelectorAll(selector); - return matches.length === 1; - } catch (error) { - return false; - } -} - -/** - * Check if ID is valid (not auto-generated) - */ -function isValidId(id: string): boolean { - // Skip IDs that look auto-generated - const invalidPatterns = [ - /^[a-f0-9]{8,}$/, // Hex strings - /^(ember|react|vue)[0-9]+/, // Framework generated - /^[0-9]+$/, // Pure numbers - /^temp-/, // Temporary prefixes - ]; - - return !invalidPatterns.some(pattern => pattern.test(id)); -} diff --git a/site/plugins/loop/frontend/src/composables/useResizeHandler.ts b/site/plugins/loop/frontend/src/composables/useResizeHandler.ts deleted file mode 100644 index 719df77..0000000 --- a/site/plugins/loop/frontend/src/composables/useResizeHandler.ts +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Performance-optimized resize handler with debouncing and RAF - */ - -interface ResizeCallback { - (): void; -} - -interface ResizeHandlerOptions { - /** Debounce delay in milliseconds (default: 100) */ - debounceDelay?: number; - /** Whether to use requestAnimationFrame (default: true) */ - useRAF?: boolean; -} - -class ResizeHandler { - private callbacks = new Set(); - private debounceTimer: number | null = null; - private rafId: number | null = null; - private isListening = false; - private options: Required; - - constructor(options: ResizeHandlerOptions = {}) { - this.options = { - debounceDelay: options.debounceDelay ?? 100, - useRAF: options.useRAF ?? true, - }; - } - - private handleResize = () => { - // Clear existing timers - if (this.debounceTimer) { - clearTimeout(this.debounceTimer); - } - if (this.rafId) { - cancelAnimationFrame(this.rafId); - } - - // Debounce the resize event - this.debounceTimer = window.setTimeout(() => { - if (this.options.useRAF) { - // Use RAF for smooth updates - this.rafId = requestAnimationFrame(() => { - this.executeCallbacks(); - }); - } else { - this.executeCallbacks(); - } - }, this.options.debounceDelay); - }; - - private executeCallbacks() { - this.callbacks.forEach(callback => { - try { - callback(); - } catch (error) { - console.error('Error in resize callback:', error); - } - }); - } - - private startListening() { - if (!this.isListening) { - window.addEventListener('resize', this.handleResize, { passive: true }); - this.isListening = true; - } - } - - private stopListening() { - if (this.isListening) { - window.removeEventListener('resize', this.handleResize); - this.isListening = false; - } - } - - /** - * Add a callback to be executed on resize - */ - subscribe(callback: ResizeCallback): () => void { - this.callbacks.add(callback); - this.startListening(); - - // Return unsubscribe function - return () => { - this.callbacks.delete(callback); - if (this.callbacks.size === 0) { - this.stopListening(); - } - }; - } - - /** - * Clean up all resources - */ - destroy() { - this.callbacks.clear(); - this.stopListening(); - if (this.debounceTimer) { - clearTimeout(this.debounceTimer); - } - if (this.rafId) { - cancelAnimationFrame(this.rafId); - } - } -} - -// Singleton instance for global use -const globalResizeHandler = new ResizeHandler(); - -/** - * Svelte composable for handling window resize events with performance optimization - * @param callback Function to call on resize - * @param options Configuration options - * @returns Cleanup function - */ -export function useResizeHandler( - callback: ResizeCallback, - options?: ResizeHandlerOptions -): () => void { - if (options) { - // Create a new handler with custom options - const handler = new ResizeHandler(options); - return handler.subscribe(callback); - } else { - // Use the global handler - return globalResizeHandler.subscribe(callback); - } -} - -export default useResizeHandler; \ No newline at end of file diff --git a/site/plugins/loop/frontend/src/lib/Author.svelte b/site/plugins/loop/frontend/src/lib/Author.svelte deleted file mode 100644 index 0be9b17..0000000 --- a/site/plugins/loop/frontend/src/lib/Author.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - -
- {initials} -
- - diff --git a/site/plugins/loop/frontend/src/lib/Button.svelte b/site/plugins/loop/frontend/src/lib/Button.svelte deleted file mode 100644 index 75f7063..0000000 --- a/site/plugins/loop/frontend/src/lib/Button.svelte +++ /dev/null @@ -1,256 +0,0 @@ - - - - - diff --git a/site/plugins/loop/frontend/src/lib/Comment.svelte b/site/plugins/loop/frontend/src/lib/Comment.svelte deleted file mode 100644 index cd74c17..0000000 --- a/site/plugins/loop/frontend/src/lib/Comment.svelte +++ /dev/null @@ -1,227 +0,0 @@ - - -
- - -
-
- {comment.author} - -
-
{decodeHTMLEntities(comment.comment)}
-
- - {#if !detailsOpen} - - {/if} -
- - {#if comment.replies?.length > 0} -
    - {#each comment.replies as reply (reply.id)} -
  • - -
  • - {/each} -
- {/if} - -
- {#if openReplyForm} - { - openReplyForm = false; - handleSubmit(e); - }} - cancel={() => { - openReplyForm = false; - cancel(); - }} - parentId={comment.id} - /> - {:else} -
- {#if comment.status === "OPEN"} - - - {:else} - - {/if} -
- {/if} -
-
- - diff --git a/site/plugins/loop/frontend/src/lib/CommentDialog.svelte b/site/plugins/loop/frontend/src/lib/CommentDialog.svelte deleted file mode 100644 index 5e21a08..0000000 --- a/site/plugins/loop/frontend/src/lib/CommentDialog.svelte +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - diff --git a/site/plugins/loop/frontend/src/lib/CommentForm.svelte b/site/plugins/loop/frontend/src/lib/CommentForm.svelte deleted file mode 100644 index d8d9cd1..0000000 --- a/site/plugins/loop/frontend/src/lib/CommentForm.svelte +++ /dev/null @@ -1,99 +0,0 @@ - - -
-
- -
-
- {t("ui.comment.keyboardHint", "⌘+Enter or Ctrl+Enter to submit")} -
-
- - -
-
- - diff --git a/site/plugins/loop/frontend/src/lib/ContextMenu.svelte b/site/plugins/loop/frontend/src/lib/ContextMenu.svelte deleted file mode 100644 index f90fb93..0000000 --- a/site/plugins/loop/frontend/src/lib/ContextMenu.svelte +++ /dev/null @@ -1,187 +0,0 @@ - - -
-
- -
- - -
- - diff --git a/site/plugins/loop/frontend/src/lib/Header.svelte b/site/plugins/loop/frontend/src/lib/Header.svelte deleted file mode 100644 index 711bef3..0000000 --- a/site/plugins/loop/frontend/src/lib/Header.svelte +++ /dev/null @@ -1,89 +0,0 @@ - - -
-
- - -
- -
- - diff --git a/site/plugins/loop/frontend/src/lib/Marker.svelte b/site/plugins/loop/frontend/src/lib/Marker.svelte deleted file mode 100644 index 96bcd52..0000000 --- a/site/plugins/loop/frontend/src/lib/Marker.svelte +++ /dev/null @@ -1,179 +0,0 @@ - - -{#if comment} -
- -
-{/if} - - diff --git a/site/plugins/loop/frontend/src/lib/Panel.svelte b/site/plugins/loop/frontend/src/lib/Panel.svelte deleted file mode 100644 index 8cfbc4e..0000000 --- a/site/plugins/loop/frontend/src/lib/Panel.svelte +++ /dev/null @@ -1,181 +0,0 @@ - - - -
- -
- -
    - {#if filteredComments.length === 0} -
  • -

    - {t("ui.panel.no.comments", "No comments yet.")} -

    -
  • - {:else if filteredComments.length === 0 && panel.showResolvedOnly} -
  • -

    {t("ui.panel.no.resolved", "No resolved comments yet.")}

    -
  • - {:else} - {#each filteredComments as comment (comment.id)} -
  • - -
  • - {/each} - {/if} -
- - -
- - diff --git a/site/plugins/loop/frontend/src/lib/Reply.svelte b/site/plugins/loop/frontend/src/lib/Reply.svelte deleted file mode 100644 index 8902dab..0000000 --- a/site/plugins/loop/frontend/src/lib/Reply.svelte +++ /dev/null @@ -1,67 +0,0 @@ - - -
- -
-
- {reply.author} - -
-
{decodeHTMLEntities(reply.comment)}
-
-
- - diff --git a/site/plugins/loop/frontend/src/lib/WelcomeDialog.svelte b/site/plugins/loop/frontend/src/lib/WelcomeDialog.svelte deleted file mode 100644 index 2c9b412..0000000 --- a/site/plugins/loop/frontend/src/lib/WelcomeDialog.svelte +++ /dev/null @@ -1,168 +0,0 @@ - - - -
- {#if welcomeEnabled} -

{headline}

-

{text}

- {/if} - - {#if !authenticated} -
-
- -
-
- {/if} - -
- - -
-
-
- - diff --git a/site/plugins/loop/frontend/src/main.ts b/site/plugins/loop/frontend/src/main.ts deleted file mode 100644 index 04ebb82..0000000 --- a/site/plugins/loop/frontend/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import App from './App.svelte' -import "./styles/variables.css" -import "./styles/app.css" - -export default App; diff --git a/site/plugins/loop/frontend/src/store/api.svelte.ts b/site/plugins/loop/frontend/src/store/api.svelte.ts deleted file mode 100644 index bdc5c71..0000000 --- a/site/plugins/loop/frontend/src/store/api.svelte.ts +++ /dev/null @@ -1,111 +0,0 @@ -import type { Comment, CommentPayload, Reply, ReplyPayload } from '../types'; - -export const store: { comments: Comment[] } = $state({ - comments: [] -}); - -const apiPrefix = 'loop'; -const KirbyLoop = document.querySelector('kirby-loop'); -const csrfToken = KirbyLoop?.getAttribute('csrf-token') || ''; -const apiBase = KirbyLoop?.getAttribute('apibase') || '/'; -const headers = { - 'Content-Type': 'application/json', - 'X-CSRF-Token': csrfToken || '' -}; - -const buildApiUrl = (endpoint: string): string => { - const url = new URL(`${apiBase}/${apiPrefix}/${endpoint}`, window.location.origin); - - // Add token query params from current page if they exist - const currentParams = new URLSearchParams(window.location.search); - const token = currentParams.get('token') || currentParams.get('_token'); - if (token) { - url.searchParams.set(currentParams.has('token') ? 'token' : '_token', token); - } - - return url.toString(); -}; - -export const getComments = async (pageId: string): Promise => { - const url = buildApiUrl(`comments/${pageId}`); - const response = await fetch(url, { - headers - }); - const data = await response.json(); - if (data.status === 'ok') { - store.comments = data.comments; - } - return data.status === 'ok'; -} - -export const addComment = async (comment: CommentPayload) => { - const url = buildApiUrl('comment/new'); - const response = await fetch(url, { - method: 'POST', - headers, - body: JSON.stringify(comment) - }); - const data: { comment: Comment, status: string } = await response.json(); - if (data.status === 'ok') { - store.comments = [data.comment, ...store.comments]; - } -} - -export const resolveComment = async (comment: Comment) => { - const url = buildApiUrl('comment/resolve'); - const response = await fetch(url, { - method: 'POST', - headers, - body: JSON.stringify({ id: comment.id }) - }); - const data: { success: boolean } = await response.json(); - if (data.success) { - const commentIndex = store.comments.findIndex(c => c.id === comment.id); - if (commentIndex !== -1) { - store.comments[commentIndex].status = 'RESOLVED'; - } - } - return data.success; -} - -export const unresolveComment = async (comment: Comment) => { - const url = buildApiUrl('comment/unresolve'); - const response = await fetch(url, { - method: 'POST', - headers, - body: JSON.stringify({ id: comment.id }) - }); - const data: { success: boolean } = await response.json(); - if (data.success) { - const commentIndex = store.comments.findIndex(c => c.id === comment.id); - if (commentIndex !== -1) { - store.comments[commentIndex].status = 'OPEN'; - } - } - return data.success; -} - -export const setGuestName = async (name: string) => { - const response = await fetch(buildApiUrl('guest/name'), { - method: 'POST', - headers, - body: JSON.stringify({ name }) - }); - return await response.json(); -} - -export const addReply = async (reply: ReplyPayload) => { - const url = buildApiUrl('comment/reply'); - const response = await fetch(url, { - method: 'POST', - headers, - body: JSON.stringify(reply) - }); - const data: { reply: Reply, status: string } = await response.json(); - if (data.status === 'ok') { - const parent = store.comments.find(c => c.id === data.reply.parentId) - if (parent) parent.replies = [...parent.replies, data.reply]; - } -} - -export default store; diff --git a/site/plugins/loop/frontend/src/store/form.svelte.ts b/site/plugins/loop/frontend/src/store/form.svelte.ts deleted file mode 100644 index a33d7a5..0000000 --- a/site/plugins/loop/frontend/src/store/form.svelte.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { FormData } from '../types'; - -export const formData: FormData = $state({ - text: "", - parentId: null -}); - -export const reset = () => { - formData.text = "" - formData.parentId = null -} diff --git a/site/plugins/loop/frontend/src/store/translations.svelte.ts b/site/plugins/loop/frontend/src/store/translations.svelte.ts deleted file mode 100644 index 5edeb33..0000000 --- a/site/plugins/loop/frontend/src/store/translations.svelte.ts +++ /dev/null @@ -1,19 +0,0 @@ -let translations = $state>({}); - -export const t = (key: string, fallback?: string): string => { - return translations[key] || fallback || key; -}; - -export const tt = (key: string, fallback: string, replacements: Record): string => { - let text = translations[key] || fallback || key; - - for (const [placeholder, value] of Object.entries(replacements)) { - text = text.replace(`{${placeholder}}`, value); - } - - return text; -}; - -export const setTranslations = (newTranslations: Record) => { - translations = newTranslations; -}; \ No newline at end of file diff --git a/site/plugins/loop/frontend/src/store/ui.svelte.ts b/site/plugins/loop/frontend/src/store/ui.svelte.ts deleted file mode 100644 index 305b47c..0000000 --- a/site/plugins/loop/frontend/src/store/ui.svelte.ts +++ /dev/null @@ -1,34 +0,0 @@ -export const panel = $state({ - open: false, - currentCommentId: 0, - showResolvedOnly: false, - pulseMarkerId: 0 -}); -export const overlay = $state({ open: false }); - -// Guest name management -let guestNameValue = $state(""); - -export const guestName = { - get value() { - return guestNameValue; - }, - set(name: string) { - guestNameValue = name; - if (typeof window !== 'undefined') { - sessionStorage.setItem('loop-guest-name', name); - } - }, - get() { - if (!guestNameValue && typeof window !== 'undefined') { - guestNameValue = sessionStorage.getItem('loop-guest-name') || ""; - } - return guestNameValue; - }, - clear() { - guestNameValue = ""; - if (typeof window !== 'undefined') { - sessionStorage.removeItem('loop-guest-name'); - } - } -}; diff --git a/site/plugins/loop/frontend/src/styles/app.css b/site/plugins/loop/frontend/src/styles/app.css deleted file mode 100644 index fd92a49..0000000 --- a/site/plugins/loop/frontend/src/styles/app.css +++ /dev/null @@ -1,13 +0,0 @@ -kirby-loop { - font-family: var(--font-family); - line-height: var(--line-height); - font-weight: var(--font-weight-normal); - font-size: var(--font-size-7); - box-sizing: border-box; -} - -html.loop-overlay-open { - a { - pointer-events: none; - } -} diff --git a/site/plugins/loop/frontend/src/styles/theme-dark.css b/site/plugins/loop/frontend/src/styles/theme-dark.css deleted file mode 100644 index a7ce655..0000000 --- a/site/plugins/loop/frontend/src/styles/theme-dark.css +++ /dev/null @@ -1,35 +0,0 @@ -kirby-loop[theme="dark"] { - /* Accent lightness values */ - --color-accent-l: 0.85; - - /* Neutral lightness values */ - --color-neutral-l-0: 0; - --color-neutral-l-100: 0.1; - --color-neutral-l-200: 0.2; - --color-neutral-l-300: 0.45; - --color-neutral-l-400: 0.5; - --color-neutral-l-600: 0.55; - --color-neutral-l-500: 0.6; - --color-neutral-l-700: 0.7; - --color-neutral-l-800: 0.8; - --color-neutral-l-900: 0.95; - --color-neutral-l-1000: 1; - - /* Shadow tokens */ - --shadow-s: 0 0.1em 0.25em oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.1); - --shadow-m: 0 2px 8px oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.08), - 0 8px 16px oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.12), - 0 16px 24px oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.08); - --shadow-l: 0 4px 16px oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.08), - 0 12px 32px oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.12), - 0 24px 48px oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.16), - 0 48px 80px oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.08); - --shadow-light-edge: inset 1px 1px 1px oklch(var(--color-neutral-l-1000) var(--color-neutral-c) var(--color-neutral-h) / 0.3); - --shadow-dark-edge: inset -1px -1px 1px oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h) / 0.3); - - /* Background tokens */ - --background-glass: linear-gradient(135deg, transparent, var(--color-base-background-o-50)); - - /* Panel */ - --panel-threads-background: oklch(var(--color-neutral-l-200) var(--color-neutral-c) var(--color-neutral-h) / 0.99) -} \ No newline at end of file diff --git a/site/plugins/loop/frontend/src/styles/theme-default.css b/site/plugins/loop/frontend/src/styles/theme-default.css deleted file mode 100644 index f8f39bc..0000000 --- a/site/plugins/loop/frontend/src/styles/theme-default.css +++ /dev/null @@ -1,23 +0,0 @@ -kirby-loop { - /* Color Customization */ - --color-neutral-h: 900; - --color-neutral-c: 0; - --color-accent-h: 900; - --color-accent-c: 0.18; - --color-accent-l: 0.75; - --color-accent-dark-factor: 0.4; - --color-accent-light-factor: 1.2; - - /* Neutral lightness values */ - --color-neutral-l-0: 1; - --color-neutral-l-100: 0.95; - --color-neutral-l-200: 0.9; - --color-neutral-l-300: 0.7; - --color-neutral-l-400: 0.6; - --color-neutral-l-600: 0.4; - --color-neutral-l-500: 0.5; - --color-neutral-l-700: 0.3; - --color-neutral-l-800: 0.2; - --color-neutral-l-900: 0.1; - --color-neutral-l-1000: 0; -} \ No newline at end of file diff --git a/site/plugins/loop/frontend/src/styles/variables.css b/site/plugins/loop/frontend/src/styles/variables.css deleted file mode 100644 index 19d41d1..0000000 --- a/site/plugins/loop/frontend/src/styles/variables.css +++ /dev/null @@ -1,421 +0,0 @@ -@import "./theme-default.css"; -@import "./theme-dark.css"; - -kirby-loop { - /* Colors */ - --color-base: var(--color-neutral-900); - --color-base-background: var(--color-neutral-0); - - --color-base-background-o-5: oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h) / 0.05); - --color-base-background-o-10: oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h) / 0.1); - --color-base-background-o-20: oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h) / 0.2); - --color-base-background-o-50: oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h) / 0.5); - --color-base-background-o-60: oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h) / 0.6); - --color-base-background-o-75: oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h) / 0.75); - --color-base-background-o-95: oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h) / 0.95); - - --color-accent-light: oklch(calc(var(--color-accent-l) * var(--color-accent-light-factor)) var(--color-accent-c) var(--color-accent-h)); - --color-accent: oklch(var(--color-accent-l) var(--color-accent-c) var(--color-accent-h)); - --color-accent-dark: oklch(calc(var(--color-accent-l) * var(--color-accent-dark-factor)) var(--color-accent-c) var(--color-accent-h)); - - --color-neutral-0: oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-100: oklch(var(--color-neutral-l-100) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-200: oklch(var(--color-neutral-l-200) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-300: oklch(var(--color-neutral-l-300) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-400: oklch(var(--color-neutral-l-400) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-500: oklch(var(--color-neutral-l-500) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-600: oklch(var(--color-neutral-l-600) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-700: oklch(var(--color-neutral-l-700) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-800: oklch(var(--color-neutral-l-800) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-900: oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h)); - --color-neutral-1000: oklch(var(--color-neutral-l-1000) var(--color-neutral-c) var(--color-neutral-h)); - - --color-success: oklch(0.65 0.15 150); - --color-warning: oklch(0.75 0.15 80); - --color-error: oklch(0.65 0.18 25); - --color-info: oklch(0.65 0.15 220); - - --font-family: -apple-system, - BlinkMacSystemFont, - "Segoe UI", - Roboto, - Helvetica, - Arial, - sans-serif, - "Apple Color Emoji", - "Segoe UI Emoji", - "Segoe UI Symbol", - sans-serif; - - --line-height: 1.4; - - --font-weight-light: 300; - --font-weight-normal: 400; - --font-weight-medium: 550; - --font-weight-bold: 700; - - --font-size-3: clamp(1.9531rem, 1.4262rem + 1.7565vw, 3.5339rem); - --font-size-4: clamp(1.5625rem, 1.2503rem + 1.0408vw, 2.4992rem); - --font-size-5: clamp(1.25rem, 1.0775rem + 0.575vw, 1.7675rem); - --font-size-6: clamp(1rem, 0.9167rem + 0.2778vw, 1.25rem); - --font-size-7: clamp(0.8rem, 0.772rem + 0.0934vw, 0.884rem); - --font-size-8: clamp(0.6252rem, 0.6449rem + -0.0165vw, 0.64rem); - - --border-radius-s: 0.125rem; - --border-radius: 0.25rem; - --border-radius-rounded: 4096px; - - --space-2xs: clamp(0.25rem, 0.2292rem + 0.0694vw, 0.3125rem); - --space-xs: clamp(0.5rem, 0.4583rem + 0.1389vw, 0.625rem); - --space-s: clamp(1rem, 0.9167rem + 0.2778vw, 1.25rem); - --space-m: clamp(1.5rem, 1.375rem + 0.4167vw, 1.875rem); - --space-l: clamp(2rem, 1.8333rem + 0.5556vw, 2.5rem); - --space-2xs-xs: clamp(0.25rem, 0.125rem + 0.4167vw, 0.625rem); - --space-xs-s: clamp(0.5rem, 0.25rem + 0.8333vw, 1.25rem); - --space-s-m: clamp(1rem, 0.7083rem + 0.9722vw, 1.875rem); - --space-m-l: clamp(1.5rem, 1.1667rem + 1.1111vw, 2.5rem); - --space-s-l: clamp(1rem, 0.5rem + 1.6667vw, 2.5rem); - - /* Shadow tokens */ - --shadow-s: 0 0.1em 0.25em oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.1); - --shadow-m: 0 2px 8px oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.08), - 0 8px 16px oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.12), - 0 16px 24px oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.08); - --shadow-l: 0 4px 16px oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.08), - 0 12px 32px oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.12), - 0 24px 48px oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.16), - 0 48px 80px oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.08); - --shadow-light-edge: inset 1px 1px 1px oklch(var(--color-neutral-l-0) var(--color-neutral-c) var(--color-neutral-h) / 0.3); - --shadow-dark-edge: inset 0 -1px 1px oklch(var(--color-neutral-l-900) var(--color-neutral-c) var(--color-neutral-h) / 0.3); - - /* Backdrop tokens */ - --backdrop-blur: blur(6px); - --backdrop-glass: var(--backdrop-blur) saturate(1.4) brightness(1.2); - - /* Background tokens */ - --background-glass: linear-gradient(135deg, transparent, var(--color-base-background-o-95)); - --background-glass-frosted: linear-gradient(0deg, var(--color-base-background-o-75) 0%, var(--color-base-background-o-95) 50%); - - /* Opacity tokens */ - --opacity-subtle: 0.5; - --opacity-medium: 0.7; - --opacity-strong: 0.9; - - /* Outline tokens */ - --outline-color: var(--color-accent); - --outline-offset: 0.25rem; - - /* Transition tokens */ - --transition-duration: 0.2s; - --transition-duration-jump: 0.4s; - --transition-easing-jump: cubic-bezier(0.44, 1.2, 0.64, 1); - --transition-easing: cubic-bezier(0, 0, 0.2, 1); - - /* Z-index tokens */ - --z-loop-marker: 9998; - --z-loop-panel: 9999; - --z-loop-dialog: 10000; - - /* Author */ - --author-avatar-color: var(--color-neutral-600); - --author-avatar-background-color: var(--color-neutral-100); - --author-avatar-size: 2.5rem; - --author-avatar-border-radius: var(--border-radius-rounded); - --author-avatar-font-size: var(--font-size-6); - - /* Button */ - --button-background: transparent; - --button-color: var(--color-neutral-600); - --button-border-radius: var(--border-radius); - --button-padding: 0 var(--space-xs); - --button-gap: var(--space-2xs); - --button-font-size: var(--font-size-7); - --button-font-weight: var(--font-weight-medium); - --button-height: 2.25rem; - --button-transition: var(--transition-duration) var(--transition-easing); - --button-outline-color: var(--outline-color); - --button-outline-offset: var(--outline-offset); - - --button-hover-color: var(--color-neutral-900); - --button-hover-background: var(--color-neutral-200); - - --button-header-background: transparent; - --button-header-height: 3rem; - --button-header-padding: 0 var(--space-s); - --button-header-hover-background: var(--color-base-background-o-95); - --button-header-blend-mode: multiply; - - --button-panel-background: transparent; - --button-panel-padding: 0 calc(var(--space-s) * 0.4); - - --button-solid-background: var(--color-neutral-100); - --button-solid-hover-color: var(--color-neutral-900); - --button-solid-hover-background: var(--color-neutral-200); - - --button-small-height: 1.5rem; - --button-small-font-size: var(--font-size-7); - - --button-icon-background: var(--color-neutral-0); - --button-icon-color: var(--color-neutral-500); - --button-icon-height: 3rem; - --button-icon-shadow: var(--shadow-s); - --button-icon-border-radius: var(--border-radius-rounded); - --button-icon-font-size: var(--font-size-6); - --button-icon-hover-background: var(--color-neutral-200); - --button-icon-hover-color: var(--color-neutral-900); - - --button-marker-background: var(--color-accent); - --button-marker-color: var(--color-accent-dark); - --button-marker-font-weight: var(--font-weight-bold); - --button-marker-border-radius: var(--border-radius-rounded); - --button-marker-highlighted-background: var(--color-accent); - --button-marker-highlighted-color: var(--color-accent-dark); - - --button-filter-background: transparent; - --button-filter-color: var(--color-neutral-500); - --button-filter-height: 1.75rem; - --button-filter-font-size: var(--font-size-8); - --button-filter-padding: 0 var(--space-xs); - --button-filter-border-radius: calc(var(--border-radius) - 2px); - --button-filter-hover-color: var(--color-neutral-700); - --button-filter-hover-background: var(--color-neutral-200); - --button-filter-active-background: var(--color-base-background); - --button-filter-active-color: var(--color-base); - --button-filter-active-font-weight: var(--font-weight-medium); - - --button-menu-item-background: transparent; - --button-menu-item-color: var(--color-neutral-700); - --button-menu-item-padding: var(--space-2xs) var(--space-xs); - --button-menu-item-border-radius: calc(var(--border-radius) - 2px); - --button-menu-item-font-size: var(--font-size-7); - --button-menu-item-gap: var(--space-2xs); - --button-menu-item-hover-background: var(--color-neutral-100); - --button-menu-item-hover-color: var(--color-neutral-900); - --button-menu-item-active-background: var(--color-accent-light); - --button-menu-item-active-color: var(--color-accent-dark); - --button-menu-item-active-font-weight: var(--font-weight-medium); - - --button-active-background: var(--color-accent); - --button-active-color: var(--color-accent-dark); - - --button-disabled-opacity: var(--opacity-subtle); - --button-disabled-hover-color: var(--color-neutral-700); - --button-disabled-hover-background: var(--color-neutral-100); - - /* Comment */ - --comment-avatar-size: 2.5rem; - --comment-marker-background: var(--color-neutral-200); - --comment-marker-color: var(--color-neutral-800); - --comment-line-background: var(--color-neutral-100); - --comment-line-width: 0.1rem; - --comment-line-offset: calc(var(--space-s) + var(--comment-avatar-size) / 2); - - --comment-header-font-size: var(--font-size-7); - --comment-header-padding: var(--space-s); - --comment-header-gap: var(--space-s); - --comment-header-outline-color: var(--outline-color); - --comment-header-outline-offset: -2px; - --comment-header-border-radius: var(--border-radius); - - --comment-content-padding: var(--space-xs); - --comment-content-background: var(--color-neutral-100); - --comment-content-background-dark: var(--color-neutral-200); - --comment-content-border-radius: var(--border-radius); - - --comment-author-gap: var(--space-xs); - --comment-author-margin-bottom: var(--space-2xs); - --comment-timestamp-font-size: var(--font-size-8); - --comment-timestamp-color: var(--color-neutral-300); - - --comment-replies-padding: 0 var(--space-s); - --comment-replies-gap: var(--space-s); - - --comment-footer-padding: var(--space-s); - --comment-footer-gap: var(--space-s); - --comment-buttons-gap: var(--space-xs); - - /* CommentDialog */ - --comment-dialog-position: absolute; - --comment-dialog-max-width: 300px; - --comment-dialog-border-radius: var(--border-radius); - --comment-dialog-shadow: var(--shadow-s); - --comment-dialog-backdrop-background: transparent; - --comment-dialog-textarea-font-size: var(--font-size-6); - - /* CommentForm */ - --comment-form-background: var(--color-base-background); - --comment-form-color: var(--color-base); - --comment-form-border: 1px solid var(--color-neutral-200); - --comment-form-border-radius: var(--border-radius); - - --comment-form-textarea-height: 15ch; - --comment-form-textarea-padding: var(--space-s); - --comment-form-textarea-background: var(--color-base-background); - --comment-form-textarea-font-family: var(--font-family); - --comment-form-textarea-font-size: var(--font-size-7); - - --comment-form-footer-padding: var(--space-xs); - --comment-form-footer-gap: var(--space-xs); - - --comment-form-hint-font-size: var(--font-size-8); - --comment-form-hint-color: var(--color-neutral-300); - --comment-form-hint-padding: 0 var(--space-xs) var(--space-xs) var(--space-xs); - - /* ContextMenu */ - --context-menu-container-bottom: var(--space-s); - --context-menu-container-right: var(--space-s); - --context-menu-container-z-index: 10; - - --context-menu-trigger-size: 2.5rem; - --context-menu-trigger-border-radius: var(--border-radius-rounded); - - --context-menu-background: var(--color-base-background); - --context-menu-border-radius: var(--border-radius); - --context-menu-shadow: var(--shadow-s); - --context-menu-padding: var(--space-xs); - --context-menu-min-width: 12rem; - --context-menu-backdrop-background: transparent; - - --context-menu-section-gap: var(--space-2xs); - - --context-menu-title-font-size: var(--font-size-8); - --context-menu-title-font-weight: var(--font-weight-medium); - --context-menu-title-color: var(--color-neutral-500); - --context-menu-title-margin-bottom: var(--space-2xs); - --context-menu-title-letter-spacing: 0.05em; - - --context-menu-filter-gap: 1px; - - --context-menu-filter-dot-size: 0.5em; - --context-menu-filter-dot-border-radius: 50%; - --context-menu-filter-dot-margin-right: var(--space-2xs); - --context-menu-filter-dot-open-background: var(--color-accent); - --context-menu-filter-dot-resolved-background: var(--color-neutral-400); - - /* Header */ - --header-position: fixed; - --header-top: var(--space-xs); - --header-transform: translateX(-50%); - --header-color: var(--color-base); - --header-border-radius: var(--border-radius-rounded); - --header-z-index: 9999; - --header-bottom-position: var(--space-xs); - --header-backdrop-filter: var(--backdrop-glass); - --header-background: var(--background-glass); - - --header-count-size: 2rem; - --header-count-border-radius: var(--border-radius-rounded); - --header-count-backdrop-filter: var(--backdrop-glass); - --header-count-background: var(--background-glass); - - /* Marker */ - --marker-size: 2rem; - --marker-position: absolute; - --marker-z-index: var(--z-loop-marker); - --marker-transform: translate(-50%, -50%); - --marker-border-radius: var(--border-radius-rounded); - - /* Panel */ - --panel-width: 380px; - --panel-mobile-width: 85svw; - --panel-position: fixed; - --panel-right: var(--space-xs); - --panel-top: var(--space-xs); - --panel-height: calc(100svh - var(--space-xs) * 2); - --panel-transform-closed: translateX(calc(100% + var(--space-xs))); - --panel-transform-open: translateX(0); - --panel-color: var(--color-base); - --panel-border-radius: var(--border-radius); - --panel-border-top-left-radius: 0; - --panel-transition: var(--transition-duration-jump) var(--transition-easing-jump); - --panel-z-index: var(--z-loop-panel); - --panel-shadow: var(--shadow-m); - - --panel-header-transform-closed: translate(-95%); - --panel-header-transform-open: translate(calc(-100% + 1px)); - --panel-header-transform-hover: translate(calc(-100% + 1px)); - --panel-header-border-radius: var(--border-radius-rounded); - --panel-header-gap: var(--space-xs); - --panel-header-backdrop-filter: var(--backdrop-glass); - --panel-header-background: var(--background-glass); - - --panel-threads-background: var(--color-base-background-o-95); - --panel-threads-backdrop: var(--backdrop-blur); - --panel-threads-border-radius: var(--border-radius); - --panel-threads-border-top-left-radius: 0; - --panel-threads-padding: 0 0 var(--space-s) 0; - --panel-threads-item-margin: var(--space-s); - --panel-threads-scrollbar-width: thin; - - --panel-no-threads-padding: var(--space-s) var(--space-l); - --panel-no-threads-font-size: var(--font-size-6); - --panel-no-threads-color: var(--color-neutral-300); - - /* Reply */ - --reply-gap: var(--space-s); - --reply-content-padding: var(--space-xs); - --reply-content-background: var(--color-neutral-100); - --reply-content-background-dark: var(--color-neutral-200); - --reply-content-border-radius: var(--border-radius); - - --reply-header-gap: var(--space-xs); - --reply-header-margin-bottom: var(--space-2xs); - --reply-timestamp-font-size: var(--font-size-8); - --reply-timestamp-color: var(--color-neutral-300); - - /* WelcomeDialog */ - --welcome-dialog-background: var(--background-glass-frosted); - --welcome-dialog-backdrop-filter: var(--backdrop-glass); - --welcome-dialog-border: 0px; - --welcome-dialog-border-radius: var(--border-radius); - --welcome-dialog-shadow: var(--shadow-l), var(--shadow-light-edge), - var(--shadow-dark-edge); - --welcome-dialog-max-width: 500px; - - --welcome-dialog-backdrop-background: var(--color-base-background-o-10); - --welcome-dialog-backdrop-backdrop-filter: none; - - --welcome-dialog-form-padding: var(--space-l); - - --welcome-dialog-title-margin: 0 0 var(--space-s) 0; - --welcome-dialog-title-font-size: var(--font-size-4); - --welcome-dialog-title-color: var(--color-base); - --welcome-dialog-title-font-weight: var(--font-weight-bold); - - --welcome-dialog-text-margin: 0 0 var(--space-m) 0; - --welcome-dialog-text-font-size: var(--font-size-6); - --welcome-dialog-text-color: var(--color-neutral-600); - --welcome-dialog-text-line-height: var(--line-height); - - --welcome-dialog-name-section-margin: var(--space-l); - - --welcome-dialog-input-border: 1px solid var(--color-neutral-300); - --welcome-dialog-input-border-radius: var(--border-radius-s); - --welcome-dialog-input-padding: var(--space-xs); - --welcome-dialog-input-font-family: var(--font-family); - --welcome-dialog-input-font-size: var(--font-size-6); - --welcome-dialog-input-color: var(--color-base); - --welcome-dialog-input-background: var(--color-base-background); - --welcome-dialog-input-outline-color: var(--outline-color); - --welcome-dialog-input-outline-offset: var(--outline-offset); - - --welcome-dialog-footer-gap: var(--space-xs); - - /* Icon */ - --icon-size: 1em; -} - -/* Dark theme overrides */ -kirby-loop[data-theme="dark"] { - --color-neutral-l-0: 0; - --color-neutral-l-100: 0.1; - --color-neutral-l-200: 0.2; - --color-neutral-l-300: 0.3; - --color-neutral-l-400: 0.4; - --color-neutral-l-500: 0.5; - --color-neutral-l-600: 0.6; - --color-neutral-l-700: 0.7; - --color-neutral-l-800: 0.9; - --color-neutral-l-900: 0.95; - --color-neutral-l-1000: 1; -} diff --git a/site/plugins/loop/frontend/src/types.ts b/site/plugins/loop/frontend/src/types.ts deleted file mode 100644 index 0c726fa..0000000 --- a/site/plugins/loop/frontend/src/types.ts +++ /dev/null @@ -1,100 +0,0 @@ -// TypeScript interfaces for loop - -export interface LoopProps { - position: 'top' | 'bottom'; - language?: string; - apibase?: string; - pageId: string; - authenticated?: 'true' | 'false'; - 'welcome-enabled'?: 'true' | 'false'; - 'welcome-headline'?: string; - 'welcome-text'?: string; - translations?: string; -} - -export interface Comment { - id: number; - author: string; - url: string; - page: string; - comment: string; - selector: string; - selectorOffsetX: number; - selectorOffsetY: number; - pagePositionX: number; - pagePositionY: number; - status: string; - timestamp: number; - lang: string; - replies: Reply[]; -} - -export interface Reply { - id?: number; - author: string; - comment: string; - parentId: number | null; - timestamp: number; -} - -export interface CommentPayload { - url: string; - comment: string; - selector: string; - selectorOffsetX: number; - selectorOffsetY: number; - pagePositionX: number; - pagePositionY: number; - parentId: number | null; - lang: string; - pageId: string; -} - -export interface ReplyPayload { - comment: string; - parentId: number | null; -} - -export interface MarkerPosition { - selector: string; - selectorOffsetX: number; - selectorOffsetY: number; - pagePositionX: number; - pagePositionY: number; -} - -export interface ApiResponse { - status: 'ok' | 'error'; - message?: string; - code?: string; - data?: T; -} - -export interface CommentsResponse extends ApiResponse { - comments: Comment[]; -} - -export interface CommentResponse extends ApiResponse { - comment: Comment; -} - -export interface ReplyResponse extends ApiResponse { - reply: Reply; -} - -// Store interfaces -export interface FormData { - text: string; - parentId: number | null; -} - -export interface UIState { - open: boolean; - sidebarOpen: boolean; -} - -export interface APIStore { - comments: Comment[]; - loading: boolean; - error: string | null; -} diff --git a/site/plugins/loop/frontend/src/vite-env.d.ts b/site/plugins/loop/frontend/src/vite-env.d.ts deleted file mode 100644 index 4078e74..0000000 --- a/site/plugins/loop/frontend/src/vite-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/site/plugins/loop/frontend/svelte.config.js b/site/plugins/loop/frontend/svelte.config.js deleted file mode 100644 index bb11984..0000000 --- a/site/plugins/loop/frontend/svelte.config.js +++ /dev/null @@ -1,10 +0,0 @@ -import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; - -export default { - // Consult https://svelte.dev/docs#compile-time-svelte-preprocess - // for more information about preprocessors - preprocess: vitePreprocess(), - compilerOptions: { - customElement: true, - }, -}; diff --git a/site/plugins/loop/frontend/tsconfig.app.json b/site/plugins/loop/frontend/tsconfig.app.json deleted file mode 100644 index 55a2f9b..0000000 --- a/site/plugins/loop/frontend/tsconfig.app.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "@tsconfig/svelte/tsconfig.json", - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "resolveJsonModule": true, - /** - * Typecheck JS in `.svelte` and `.js` files by default. - * Disable checkJs if you'd like to use dynamic types in JS. - * Note that setting allowJs false does not prevent the use - * of JS in `.svelte` files. - */ - "allowJs": true, - "checkJs": true, - "isolatedModules": true, - "moduleDetection": "force" - }, - "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] -} diff --git a/site/plugins/loop/frontend/tsconfig.json b/site/plugins/loop/frontend/tsconfig.json deleted file mode 100644 index 1ffef60..0000000 --- a/site/plugins/loop/frontend/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "files": [], - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ] -} diff --git a/site/plugins/loop/frontend/tsconfig.node.json b/site/plugins/loop/frontend/tsconfig.node.json deleted file mode 100644 index db0becc..0000000 --- a/site/plugins/loop/frontend/tsconfig.node.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "target": "ES2022", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/site/plugins/loop/frontend/vite.config.ts b/site/plugins/loop/frontend/vite.config.ts deleted file mode 100644 index f7c36cd..0000000 --- a/site/plugins/loop/frontend/vite.config.ts +++ /dev/null @@ -1,69 +0,0 @@ -/// - -import { defineConfig, loadEnv } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import { resolve, dirname } from "node:path"; -import { fileURLToPath } from "node:url"; -import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js"; -import { ViteEjsPlugin } from 'vite-plugin-ejs' -import { browserslistToTargets } from 'lightningcss'; -import browserslist from "browserslist" - -// Isomorphic dirname -const _dirname = - typeof __dirname !== "undefined" - ? __dirname - : dirname(fileURLToPath(import.meta.url)); - -// Config -export default defineConfig(({ mode }) => { - const env = loadEnv(mode, process.cwd()); - return { - base: env.VITE_DEMO_BASE, - compilerOptions: { - hmr: !process.env.VITEST && mode !== 'production', - }, - build: { - cssMinify: 'lightningcss', - minify: true, - lib: { - entry: resolve(_dirname, "src/main.ts"), - name: "Loop", - fileName: "loop", - formats: ["es"], - }, - outDir: "../assets", - }, - css: { - transformer: 'lightningcss', - lightningcss: { - drafts: { - customMedia: true - }, - targets: browserslistToTargets(browserslist(["last 2 versions", ">= 0.4%", "not dead", "Firefox ESR", "not op_mini all", "not and_uc > 0"])) - } - }, - define: { - APP_VERSION: JSON.stringify(process.env.npm_package_version), - }, - plugins: [ - svelte({ compilerOptions: { customElement: true } }), - cssInjectedByJsPlugin(), - ViteEjsPlugin((viteConfig) => ({ - // viteConfig is the current Vite resolved config - env: viteConfig.env, - })) - ], - test: { - globals: true, - environment: "jsdom", - }, - server: { - allowedHosts: ['kirby-loop.test'], - cors: { - // Allow ddev and .test domains - origin: /https?:\/\/([A-Za-z0-9\-\.]+)?(\.(ddev\.site|test))(?::\d+)?$/, - }, - } - } -}); diff --git a/site/plugins/loop/index.php b/site/plugins/loop/index.php deleted file mode 100644 index 1426882..0000000 --- a/site/plugins/loop/index.php +++ /dev/null @@ -1,333 +0,0 @@ - 'src/App.php', -// 'moinframe\\loop\\Database' => 'src/Database.php', -// 'moinframe\\loop\\Middleware' => 'src/Middleware.php', -// 'moinframe\\loop\\Options' => 'src/Options.php', -// 'moinframe\\loop\\Routes' => 'src/Routes.php', -// 'moinframe\\loop\\Models\\Comment' => 'src/Models/Comment.php', -// 'moinframe\\loop\\Models\\Reply' => 'src/Models/Reply.php', -// 'moinframe\\loop\\Enums\\CommentStatus' => 'src/Enums/CommentStatus.php', -// ], __DIR__); - -// Kirby::plugin('moinframe/loop', [ -// 'translations' => [ -// 'en' => [ -// // General errors -// 'moinframe.loop.csrf.invalid' => 'Invalid CSRF token', -// 'moinframe.loop.field.required' => 'Missing required field: {field}', - -// // Page errors -// 'moinframe.loop.page.not.found' => 'Page with id {pageId} not found', -// 'moinframe.loop.page.path.not.found' => 'Page not found: {path}', - -// // Comment validation -// 'moinframe.loop.comment.required' => 'Comment text is required', -// 'moinframe.loop.comment.max.length' => 'Comment text must be less than 5000 characters', -// 'moinframe.loop.comment.validation.failed' => 'Comment validation failed: {errors}', -// 'moinframe.loop.comment.validation.error' => 'Comment validation failed: {errors}', -// 'moinframe.loop.comment.creation.failed' => 'Comment creation failed: {error}', -// 'moinframe.loop.comment.add.failed' => 'Failed to add comment: {error}', - -// // Reply validation -// 'moinframe.loop.reply.validation.failed' => 'Reply validation failed: {errors}', -// 'moinframe.loop.reply.validation.error' => 'Reply validation failed: {errors}', -// 'moinframe.loop.reply.creation.failed' => 'Reply creation failed: {error}', -// 'moinframe.loop.reply.add.failed' => 'Failed to add reply: {error}', -// 'moinframe.loop.reply.index.error' => 'Reply {index}: {error}', - -// // Author validation -// 'moinframe.loop.author.required' => 'Author is required', -// 'moinframe.loop.author.max.length' => 'Author name must be less than 255 characters', - -// // Page field validation -// 'moinframe.loop.page.required' => 'Page identifier is required', -// 'moinframe.loop.page.max.length' => 'Page identifier must be less than 255 characters', - -// // Selector validation -// 'moinframe.loop.selector.required' => 'Element selector is required', -// 'moinframe.loop.selector.max.length' => 'Element selector must be less than 1000 characters', -// 'moinframe.loop.selector.offset.x.min' => 'Selector offset X must be non-negative', -// 'moinframe.loop.selector.offset.y.min' => 'Selector offset Y must be non-negative', - -// // URL validation -// 'moinframe.loop.url.format.invalid' => 'URL format is invalid', -// 'moinframe.loop.url.max.length' => 'URL must be less than 2048 characters', - -// // Position validation -// 'moinframe.loop.page.position.x.min' => 'Page position X must be non-negative', -// 'moinframe.loop.page.position.y.min' => 'Page position Y must be non-negative', - -// // Other field validation -// 'moinframe.loop.timestamp.min' => 'Timestamp must be non-negative', -// 'moinframe.loop.parent.id.min' => 'Parent ID must be non-negative', -// 'moinframe.loop.parent.id.required' => 'Valid parent comment ID is required', - -// // Welcome dialog -// 'moinframe.loop.welcome.headline' => 'Welcome! 👋', -// 'moinframe.loop.welcome.text' => 'We\'re excited to hear your thoughts! This page has an interactive feedback system that lets you comment directly on any element. Simply use the action bar at the {position} of your screen to switch between browsing and commenting mode. When in commenting mode, click anywhere on the page to leave your feedback.', - -// // Frontend UI translations -// 'moinframe.loop.ui.comment.placeholder' => 'Enter your comment...', -// 'moinframe.loop.ui.comment.submit' => 'Submit', -// 'moinframe.loop.ui.comment.cancel' => 'Cancel', -// 'moinframe.loop.ui.comment.keyboardHint' => '⌘+Enter or Ctrl+Enter to submit', -// 'moinframe.loop.ui.comment.replies.aria.label' => 'Show replies', -// 'moinframe.loop.ui.reply.placeholder' => 'Write a reply...', -// 'moinframe.loop.ui.reply.submit' => 'Reply', -// 'moinframe.loop.ui.panel.no.comments' => 'No comments. Add your first comment to get started.', -// 'moinframe.loop.ui.header.browse.mode' => 'Browse', -// 'moinframe.loop.ui.header.comment.mode' => 'Comment', -// 'moinframe.loop.ui.header.aria.count' => 'unresolved comments', -// 'moinframe.loop.ui.welcome.guest.name.placeholder' => 'Enter your name', -// 'moinframe.loop.ui.welcome.continue' => 'Continue', -// 'moinframe.loop.ui.welcome.dismiss' => 'Dismiss', -// 'moinframe.loop.ui.header.position.top' => 'top', -// 'moinframe.loop.ui.header.position.bottom' => 'bottom', -// 'moinframe.loop.ui.comment.mark.solved' => 'Resolve', -// 'moinframe.loop.ui.comment.mark.unsolved' => 'Reopen', -// 'moinframe.loop.ui.comment.maker.aria.label' => 'Jump to marker', -// 'moinframe.loop.ui.comment.summary.aria.label' => 'Comment by', -// 'moinframe.loop.ui.reply.aria.label' => 'Reply by', -// 'moinframe.loop.ui.panel.open' => 'Open comments', -// 'moinframe.loop.ui.panel.show.resolved' => 'Show Resolved Only', -// 'moinframe.loop.ui.panel.show.all' => 'Show All Comments', -// 'moinframe.loop.ui.panel.filter.open' => 'Open', -// 'moinframe.loop.ui.panel.filter.resolved' => 'Resolved', -// 'moinframe.loop.ui.panel.filter.open.active' => 'Show open comments (currently selected)', -// 'moinframe.loop.ui.panel.filter.open.inactive' => 'Show open comments', -// 'moinframe.loop.ui.panel.filter.resolved.active' => 'Show resolved comments (currently selected)', -// 'moinframe.loop.ui.panel.filter.resolved.inactive' => 'Show resolved comments', -// 'moinframe.loop.ui.panel.menu.open' => 'Open menu', -// 'moinframe.loop.ui.panel.menu.filter.title' => 'Show Comments', -// 'moinframe.loop.ui.panel.no.resolved' => 'No resolved comments yet.', - -// // Time formatting -// 'moinframe.loop.ui.time.just_now' => 'just now', -// 'moinframe.loop.ui.time.minute_ago' => 'a minute ago', -// 'moinframe.loop.ui.time.minutes_ago' => '{count} minutes ago', -// 'moinframe.loop.ui.time.hour_ago' => 'an hour ago', -// 'moinframe.loop.ui.time.hours_ago' => '{count} hours ago', -// 'moinframe.loop.ui.time.yesterday' => 'yesterday', -// 'moinframe.loop.ui.time.days_ago' => '{count} days ago' -// ], -// 'de' => [ -// // General errors -// 'moinframe.loop.csrf.invalid' => 'Ungültiges CSRF-Token', -// 'moinframe.loop.field.required' => 'Pflichtfeld fehlt: {field}', - -// // Page errors -// 'moinframe.loop.page.not.found' => 'Seite mit ID {pageId} nicht gefunden', -// 'moinframe.loop.page.path.not.found' => 'Seite nicht gefunden: {path}', - -// // Comment validation -// 'moinframe.loop.comment.required' => 'Kommentartext ist erforderlich', -// 'moinframe.loop.comment.max.length' => 'Kommentartext darf maximal 5000 Zeichen lang sein', -// 'moinframe.loop.comment.validation.failed' => 'Kommentar-Validierung fehlgeschlagen: {errors}', -// 'moinframe.loop.comment.validation.error' => 'Kommentar-Validierung fehlgeschlagen: {errors}', -// 'moinframe.loop.comment.creation.failed' => 'Kommentar-Erstellung fehlgeschlagen: {error}', -// 'moinframe.loop.comment.add.failed' => 'Kommentar konnte nicht hinzugefügt werden: {error}', - -// // Reply validation -// 'moinframe.loop.reply.validation.failed' => 'Antwort-Validierung fehlgeschlagen: {errors}', -// 'moinframe.loop.reply.validation.error' => 'Antwort-Validierung fehlgeschlagen: {errors}', -// 'moinframe.loop.reply.creation.failed' => 'Antwort-Erstellung fehlgeschlagen: {error}', -// 'moinframe.loop.reply.add.failed' => 'Antwort konnte nicht hinzugefügt werden: {error}', -// 'moinframe.loop.reply.index.error' => 'Antwort {index}: {error}', - -// // Author validation -// 'moinframe.loop.author.required' => 'Autor ist erforderlich', -// 'moinframe.loop.author.max.length' => 'Autorname darf maximal 255 Zeichen lang sein', - -// // Page field validation -// 'moinframe.loop.page.required' => 'Seiten-Identifikator ist erforderlich', -// 'moinframe.loop.page.max.length' => 'Seiten-Identifikator darf maximal 255 Zeichen lang sein', - -// // Selector validation -// 'moinframe.loop.selector.required' => 'Element-Selektor ist erforderlich', -// 'moinframe.loop.selector.max.length' => 'Element-Selektor darf maximal 1000 Zeichen lang sein', -// 'moinframe.loop.selector.offset.x.min' => 'Selektor-Offset X muss nicht-negativ sein', -// 'moinframe.loop.selector.offset.y.min' => 'Selektor-Offset Y muss nicht-negativ sein', - -// // URL validation -// 'moinframe.loop.url.format.invalid' => 'URL-Format ist ungültig', -// 'moinframe.loop.url.max.length' => 'URL darf maximal 2048 Zeichen lang sein', - -// // Position validation -// 'moinframe.loop.page.position.x.min' => 'Seitenposition X muss nicht-negativ sein', -// 'moinframe.loop.page.position.y.min' => 'Seitenposition Y muss nicht-negativ sein', - -// // Other field validation -// 'moinframe.loop.timestamp.min' => 'Zeitstempel muss nicht-negativ sein', -// 'moinframe.loop.parent.id.min' => 'Eltern-ID muss nicht-negativ sein', -// 'moinframe.loop.parent.id.required' => 'Gültige Eltern-Kommentar-ID ist erforderlich', - -// // Welcome dialog -// 'moinframe.loop.welcome.headline' => 'Willkommen! 👋', -// 'moinframe.loop.welcome.text' => 'Wir freuen uns auf Ihr Feedback! Diese Seite verfügt über ein interaktives Feedback-System, mit dem Sie direkt zu jedem Element kommentieren können. Verwenden Sie einfach die Aktionsleiste {position} an ihrem Bildschirm, um zwischen Browse- und Kommentar-Modus zu wechseln. Im Kommentar-Modus klicken Sie einfach irgendwo auf die Seite, um Ihr Feedback zu hinterlassen.', - -// // Frontend UI translations -// 'moinframe.loop.ui.comment.placeholder' => 'Ihr Kommentar...', -// 'moinframe.loop.ui.comment.submit' => 'Senden', -// 'moinframe.loop.ui.comment.cancel' => 'Abbrechen', -// 'moinframe.loop.ui.comment.keyboardHint' => '⌘+Enter oder Strg+Enter zum Senden', -// 'moinframe.loop.ui.comment.replies.aria.label' => 'Antworten anzeigen', -// 'moinframe.loop.ui.comment.maker.aria.label' => 'Springe zu Marker', -// 'moinframe.loop.ui.comment.summary.aria.label' => 'Kommentar von', -// 'moinframe.loop.ui.reply.aria.label' => 'Antwort von', -// 'moinframe.loop.ui.reply.placeholder' => 'Antwort schreiben...', -// 'moinframe.loop.ui.reply.submit' => 'Antworten', -// 'moinframe.loop.ui.panel.no.comments' => 'Keine Kommentare. Fügen Sie Ihren ersten Kommentar hinzu, um zu beginnen.', -// 'moinframe.loop.ui.panel.open' => 'Kommentare öffnen', -// 'moinframe.loop.ui.header.browse.mode' => 'Navigieren', -// 'moinframe.loop.ui.header.comment.mode' => 'Kommentieren', -// 'moinframe.loop.ui.header.aria.count' => 'offene Kommentare', -// 'moinframe.loop.ui.welcome.guest.name.placeholder' => 'Geben Sie Ihren Namen ein', -// 'moinframe.loop.ui.welcome.continue' => 'Weiter', -// 'moinframe.loop.ui.welcome.dismiss' => 'Schließen', -// 'moinframe.loop.ui.header.position.top' => 'oben', -// 'moinframe.loop.ui.header.position.bottom' => 'unten', -// 'moinframe.loop.ui.comment.mark.solved' => 'Erledigt', -// 'moinframe.loop.ui.comment.mark.unsolved' => 'Wieder öffnen', -// 'moinframe.loop.ui.panel.show.resolved' => 'Nur erledigte anzeigen', -// 'moinframe.loop.ui.panel.show.all' => 'Alle Kommentare anzeigen', -// 'moinframe.loop.ui.panel.filter.open' => 'Offen', -// 'moinframe.loop.ui.panel.filter.resolved' => 'Erledigt', -// 'moinframe.loop.ui.panel.filter.open.active' => 'Offene Kommentare anzeigen (aktuell ausgewählt)', -// 'moinframe.loop.ui.panel.filter.open.inactive' => 'Offene Kommentare anzeigen', -// 'moinframe.loop.ui.panel.filter.resolved.active' => 'Erledigte Kommentare anzeigen (aktuell ausgewählt)', -// 'moinframe.loop.ui.panel.filter.resolved.inactive' => 'Erledigte Kommentare anzeigen', -// 'moinframe.loop.ui.panel.menu.open' => 'Menü öffnen', -// 'moinframe.loop.ui.panel.menu.filter.title' => 'Kommentare anzeigen', -// 'moinframe.loop.ui.panel.no.resolved' => 'Noch keine erledigten Kommentare.', - -// // Time formatting -// 'moinframe.loop.ui.time.just_now' => 'gerade eben', -// 'moinframe.loop.ui.time.minute_ago' => 'vor einer Minute', -// 'moinframe.loop.ui.time.minutes_ago' => 'vor {count} Minuten', -// 'moinframe.loop.ui.time.hour_ago' => 'vor einer Stunde', -// 'moinframe.loop.ui.time.hours_ago' => 'vor {count} Stunden', -// 'moinframe.loop.ui.time.yesterday' => 'gestern', -// 'moinframe.loop.ui.time.days_ago' => 'vor {count} Tagen' -// ], -// 'fr' => [ -// // General errors -// 'moinframe.loop.csrf.invalid' => 'Jeton CSRF invalide', -// 'moinframe.loop.field.required' => 'Champ obligatoire manquant : {field}', - -// // Page errors -// 'moinframe.loop.page.not.found' => 'Page avec l\'id {pageId} introuvable', -// 'moinframe.loop.page.path.not.found' => 'Page introuvable : {path}', - -// // Comment validation -// 'moinframe.loop.comment.required' => 'Le texte du commentaire est requis', -// 'moinframe.loop.comment.max.length' => 'Le commentaire ne doit pas dépasser 5000 caractères', -// 'moinframe.loop.comment.validation.failed' => 'Validation du commentaire échouée : {errors}', -// 'moinframe.loop.comment.validation.error' => 'Validation du commentaire échouée : {errors}', -// 'moinframe.loop.comment.creation.failed' => 'Création du commentaire échouée : {error}', -// 'moinframe.loop.comment.add.failed' => 'Impossible d\'ajouter le commentaire : {error}', - -// // Reply validation -// 'moinframe.loop.reply.validation.failed' => 'Validation de la réponse échouée : {errors}', -// 'moinframe.loop.reply.validation.error' => 'Validation de la réponse échouée : {errors}', -// 'moinframe.loop.reply.creation.failed' => 'Création de la réponse échouée : {error}', -// 'moinframe.loop.reply.add.failed' => 'Impossible d\'ajouter la réponse : {error}', -// 'moinframe.loop.reply.index.error' => 'Réponse {index} : {error}', - -// // Author validation -// 'moinframe.loop.author.required' => 'L\'auteur est requis', -// 'moinframe.loop.author.max.length' => 'Le nom de l\'auteur ne doit pas dépasser 255 caractères', - -// // Page field validation -// 'moinframe.loop.page.required' => 'L\'identifiant de page est requis', -// 'moinframe.loop.page.max.length' => 'L\'identifiant de page ne doit pas dépasser 255 caractères', - -// // Selector validation -// 'moinframe.loop.selector.required' => 'Le sélecteur d\'élément est requis', -// 'moinframe.loop.selector.max.length' => 'Le sélecteur d\'élément ne doit pas dépasser 1000 caractères', -// 'moinframe.loop.selector.offset.x.min' => 'L\'offset X du sélecteur doit être positif', -// 'moinframe.loop.selector.offset.y.min' => 'L\'offset Y du sélecteur doit être positif', - -// // URL validation -// 'moinframe.loop.url.format.invalid' => 'Format d\'URL invalide', -// 'moinframe.loop.url.max.length' => 'L\'URL ne doit pas dépasser 2048 caractères', - -// // Position validation -// 'moinframe.loop.page.position.x.min' => 'La position X doit être positive', -// 'moinframe.loop.page.position.y.min' => 'La position Y doit être positive', - -// // Other field validation -// 'moinframe.loop.timestamp.min' => 'L\'horodatage doit être positif', -// 'moinframe.loop.parent.id.min' => 'L\'ID parent doit être positif', -// 'moinframe.loop.parent.id.required' => 'Un ID de commentaire parent valide est requis', - -// // Welcome dialog -// 'moinframe.loop.welcome.headline' => 'Nouveauté', -// 'moinframe.loop.welcome.text' => 'Il est désormais possible de commenter directement n\'importe quel élément. Utilisez la barre d\'action en {position} de votre écran pour basculer entre le mode navigation et le mode commentaire. En mode commentaire, cliquez n\'importe où sur la page pour laisser votre message. Cette fonctionnalité n\'est accessible qu\'aux éditeurs connecté au back-office.', - -// // Frontend UI translations -// 'moinframe.loop.ui.comment.placeholder' => 'Votre commentaire...', -// 'moinframe.loop.ui.comment.submit' => 'Envoyer', -// 'moinframe.loop.ui.comment.cancel' => 'Annuler', -// 'moinframe.loop.ui.comment.keyboardHint' => '⌘+Entrée ou Ctrl+Entrée pour envoyer', -// 'moinframe.loop.ui.comment.replies.aria.label' => 'Afficher les réponses', -// 'moinframe.loop.ui.comment.maker.aria.label' => 'Aller au marqueur', -// 'moinframe.loop.ui.comment.summary.aria.label' => 'Commentaire de', -// 'moinframe.loop.ui.reply.aria.label' => 'Réponse de', -// 'moinframe.loop.ui.reply.placeholder' => 'Écrire une réponse...', -// 'moinframe.loop.ui.reply.submit' => 'Répondre', -// 'moinframe.loop.ui.panel.no.comments' => 'Aucun commentaire. Ajoutez votre premier commentaire pour commencer.', -// 'moinframe.loop.ui.panel.open' => 'Ouvrir les commentaires', -// 'moinframe.loop.ui.header.browse.mode' => 'Naviguer', -// 'moinframe.loop.ui.header.comment.mode' => 'Commenter', -// 'moinframe.loop.ui.header.aria.count' => 'commentaires non résolus', -// 'moinframe.loop.ui.welcome.guest.name.placeholder' => 'Entrez votre nom', -// 'moinframe.loop.ui.welcome.continue' => 'Continuer', -// 'moinframe.loop.ui.welcome.dismiss' => 'Fermer', -// 'moinframe.loop.ui.header.position.top' => 'haut', -// 'moinframe.loop.ui.header.position.bottom' => 'bas', -// 'moinframe.loop.ui.comment.mark.solved' => 'Résoudre', -// 'moinframe.loop.ui.comment.mark.unsolved' => 'Rouvrir', -// 'moinframe.loop.ui.panel.show.resolved' => 'Afficher les résolus uniquement', -// 'moinframe.loop.ui.panel.show.all' => 'Afficher tous les commentaires', -// 'moinframe.loop.ui.panel.filter.open' => 'Ouverts', -// 'moinframe.loop.ui.panel.filter.resolved' => 'Résolus', -// 'moinframe.loop.ui.panel.filter.open.active' => 'Afficher les commentaires ouverts (sélectionné)', -// 'moinframe.loop.ui.panel.filter.open.inactive' => 'Afficher les commentaires ouverts', -// 'moinframe.loop.ui.panel.filter.resolved.active' => 'Afficher les commentaires résolus (sélectionné)', -// 'moinframe.loop.ui.panel.filter.resolved.inactive' => 'Afficher les commentaires résolus', -// 'moinframe.loop.ui.panel.menu.open' => 'Ouvrir le menu', -// 'moinframe.loop.ui.panel.menu.filter.title' => 'Afficher les commentaires', -// 'moinframe.loop.ui.panel.no.resolved' => 'Aucun commentaire résolu pour le moment.', - -// // Time formatting -// 'moinframe.loop.ui.time.just_now' => 'à l\'instant', -// 'moinframe.loop.ui.time.minute_ago' => 'il y a une minute', -// 'moinframe.loop.ui.time.minutes_ago' => 'il y a {count} minutes', -// 'moinframe.loop.ui.time.hour_ago' => 'il y a une heure', -// 'moinframe.loop.ui.time.hours_ago' => 'il y a {count} heures', -// 'moinframe.loop.ui.time.yesterday' => 'hier', -// 'moinframe.loop.ui.time.days_ago' => 'il y a {count} jours' -// ] -// ], -// 'hooks' => [ -// 'page.render:after' => function (string $contentType, array $data, string $html, \Kirby\Cms\Page $page) { -// if ($contentType === 'html' && Options::autoInject() && Options::enabled()) { -// $snippet = snippet('loop/app', ['page' => $page], true); -// // @phpstan-ignore-next-line -// $html = str_replace('', $snippet . '', $html); -// } -// return $html; -// } -// ], -// 'routes' => Routes::register(), -// 'snippets' => [ -// 'loop/app' => __DIR__ . '/snippets/loop/app.php' -// ] -// ]); diff --git a/site/plugins/loop/kirby-loop.png b/site/plugins/loop/kirby-loop.png deleted file mode 100644 index 71f884b..0000000 Binary files a/site/plugins/loop/kirby-loop.png and /dev/null differ diff --git a/site/plugins/loop/package.json b/site/plugins/loop/package.json deleted file mode 100644 index 91f1f22..0000000 --- a/site/plugins/loop/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "moinframe-loop", - "version": "1.0.1", - "description": "", - "main": "index.js", - "scripts": { - "dev": "pnpm --filter=loop-frontend run dev", - "build": "pnpm --filter=loop-frontend run build", - "release": "release-it" - }, - "keywords": [], - "author": "Justus Kraft ", - "license": "MIT", - "packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac", - "devDependencies": { - "@release-it/bumper": "^7.0.1", - "@release-it/conventional-changelog": "^10.0.0", - "release-it": "^18.1.2" - } -} diff --git a/site/plugins/loop/phpstan.neon b/site/plugins/loop/phpstan.neon deleted file mode 100644 index 4117eaa..0000000 --- a/site/plugins/loop/phpstan.neon +++ /dev/null @@ -1,28 +0,0 @@ -parameters: - # Level 8 is the highest level of analysis (0 is the lowest) - # Adjust based on your project's maturity and needs - level: 8 - - # Paths to analyze - paths: - - index.php - - src - - # Exclude paths that don't need analysis - excludePaths: - analyseAndScan: - - vendor - - node_modules - - # Cache - tmpDir: .phpstan-cache - - - # Use cache - cache: - nodesByStringCountMax: 512 - -# Extension for better type inference -includes: - - vendor/phpstan/phpstan-strict-rules/rules.neon - - vendor/phpstan/phpstan-deprecation-rules/rules.neon diff --git a/site/plugins/loop/pnpm-lock.yaml b/site/plugins/loop/pnpm-lock.yaml deleted file mode 100644 index b4ad815..0000000 --- a/site/plugins/loop/pnpm-lock.yaml +++ /dev/null @@ -1,2870 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@release-it/bumper': - specifier: ^7.0.1 - version: 7.0.2(release-it@18.1.2(@types/node@22.13.10)) - '@release-it/conventional-changelog': - specifier: ^10.0.0 - version: 10.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0)(release-it@18.1.2(@types/node@22.13.10)) - release-it: - specifier: ^18.1.2 - version: 18.1.2(@types/node@22.13.10) - -packages: - - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - - '@conventional-changelog/git-client@1.0.1': - resolution: {integrity: sha512-PJEqBwAleffCMETaVm/fUgHldzBE35JFk3/9LL6NUA5EXa3qednu+UT6M7E5iBu3zIQZCULYIiZ90fBYHt6xUw==} - engines: {node: '>=18'} - peerDependencies: - conventional-commits-filter: ^5.0.0 - conventional-commits-parser: ^6.0.0 - peerDependenciesMeta: - conventional-commits-filter: - optional: true - conventional-commits-parser: - optional: true - - '@hutson/parse-repository-url@5.0.0': - resolution: {integrity: sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==} - engines: {node: '>=10.13.0'} - - '@iarna/toml@2.2.5': - resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} - - '@iarna/toml@3.0.0': - resolution: {integrity: sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==} - - '@inquirer/checkbox@4.1.4': - resolution: {integrity: sha512-d30576EZdApjAMceijXA5jDzRQHT/MygbC+J8I7EqA6f/FRpYxlRtRJbHF8gHeWYeSdOuTEJqonn7QLB1ELezA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/confirm@5.1.8': - resolution: {integrity: sha512-dNLWCYZvXDjO3rnQfk2iuJNL4Ivwz/T2+C3+WnNfJKsNGSuOs3wAo2F6e0p946gtSAk31nZMfW+MRmYaplPKsg==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/core@10.1.9': - resolution: {integrity: sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/editor@4.2.9': - resolution: {integrity: sha512-8HjOppAxO7O4wV1ETUlJFg6NDjp/W2NP5FB9ZPAcinAlNT4ZIWOLe2pUVwmmPRSV0NMdI5r/+lflN55AwZOKSw==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/expand@4.0.11': - resolution: {integrity: sha512-OZSUW4hFMW2TYvX/Sv+NnOZgO8CHT2TU1roUCUIF2T+wfw60XFRRp9MRUPCT06cRnKL+aemt2YmTWwt7rOrNEA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/figures@1.0.11': - resolution: {integrity: sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw==} - engines: {node: '>=18'} - - '@inquirer/input@4.1.8': - resolution: {integrity: sha512-WXJI16oOZ3/LiENCAxe8joniNp8MQxF6Wi5V+EBbVA0ZIOpFcL4I9e7f7cXse0HJeIPCWO8Lcgnk98juItCi7Q==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/number@3.0.11': - resolution: {integrity: sha512-pQK68CsKOgwvU2eA53AG/4npRTH2pvs/pZ2bFvzpBhrznh8Mcwt19c+nMO7LHRr3Vreu1KPhNBF3vQAKrjIulw==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/password@4.0.11': - resolution: {integrity: sha512-dH6zLdv+HEv1nBs96Case6eppkRggMe8LoOTl30+Gq5Wf27AO/vHFgStTVz4aoevLdNXqwE23++IXGw4eiOXTg==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/prompts@7.4.0': - resolution: {integrity: sha512-EZiJidQOT4O5PYtqnu1JbF0clv36oW2CviR66c7ma4LsupmmQlUwmdReGKRp456OWPWMz3PdrPiYg3aCk3op2w==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/rawlist@4.0.11': - resolution: {integrity: sha512-uAYtTx0IF/PqUAvsRrF3xvnxJV516wmR6YVONOmCWJbbt87HcDHLfL9wmBQFbNJRv5kCjdYKrZcavDkH3sVJPg==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/search@3.0.11': - resolution: {integrity: sha512-9CWQT0ikYcg6Ls3TOa7jljsD7PgjcsYEM0bYE+Gkz+uoW9u8eaJCRHJKkucpRE5+xKtaaDbrND+nPDoxzjYyew==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/select@4.1.0': - resolution: {integrity: sha512-z0a2fmgTSRN+YBuiK1ROfJ2Nvrpij5lVN3gPDkQGhavdvIVGHGW29LwYZfM/j42Ai2hUghTI/uoBuTbrJk42bA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/type@3.0.5': - resolution: {integrity: sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@octokit/auth-token@5.1.2': - resolution: {integrity: sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==} - engines: {node: '>= 18'} - - '@octokit/core@6.1.4': - resolution: {integrity: sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==} - engines: {node: '>= 18'} - - '@octokit/endpoint@10.1.3': - resolution: {integrity: sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==} - engines: {node: '>= 18'} - - '@octokit/graphql@8.2.1': - resolution: {integrity: sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==} - engines: {node: '>= 18'} - - '@octokit/openapi-types@24.2.0': - resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==} - - '@octokit/plugin-paginate-rest@11.6.0': - resolution: {integrity: sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '>=6' - - '@octokit/plugin-request-log@5.3.1': - resolution: {integrity: sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '>=6' - - '@octokit/plugin-rest-endpoint-methods@13.5.0': - resolution: {integrity: sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '>=6' - - '@octokit/request-error@6.1.7': - resolution: {integrity: sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==} - engines: {node: '>= 18'} - - '@octokit/request@9.2.2': - resolution: {integrity: sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==} - engines: {node: '>= 18'} - - '@octokit/rest@21.0.2': - resolution: {integrity: sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ==} - engines: {node: '>= 18'} - - '@octokit/types@13.10.0': - resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} - - '@pnpm/config.env-replace@1.1.0': - resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} - engines: {node: '>=12.22.0'} - - '@pnpm/network.ca-file@1.0.2': - resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} - engines: {node: '>=12.22.0'} - - '@pnpm/npm-conf@2.3.1': - resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} - engines: {node: '>=12'} - - '@release-it/bumper@7.0.2': - resolution: {integrity: sha512-OHcdArfUgSW//1GuzcjWOW2Sbx3tz9vgMyi2KQv8SEeLeWjIMAM2IxR+bXzbC2q40ACSa/cQRQE0HfHCMfkYwg==} - engines: {node: ^20.9.0 || >=22.0.0} - peerDependencies: - release-it: '>=18.0.0' - - '@release-it/conventional-changelog@10.0.0': - resolution: {integrity: sha512-49qf9phGmPUIGpY2kwfgehs9en1znbPv2zdNn1WMLAH9DtHUh4m6KNSB+mLFGAMUhv24JhsA8ruYRYgluc2UJw==} - engines: {node: ^20.9.0 || >=22.0.0} - peerDependencies: - release-it: ^18.0.0 - - '@sec-ant/readable-stream@0.4.1': - resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} - - '@sindresorhus/merge-streams@2.3.0': - resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} - engines: {node: '>=18'} - - '@sindresorhus/merge-streams@4.0.0': - resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} - engines: {node: '>=18'} - - '@tootallnate/quickjs-emscripten@0.23.0': - resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - - '@types/node@22.13.10': - resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==} - - '@types/normalize-package-data@2.4.4': - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - - '@types/parse-path@7.0.3': - resolution: {integrity: sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==} - - '@types/semver@7.5.8': - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - - add-stream@1.0.0: - resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} - - agent-base@7.1.3: - resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} - engines: {node: '>= 14'} - - ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-ify@1.0.0: - resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - - ast-types@0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} - - async-retry@1.3.3: - resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} - - atomically@2.0.3: - resolution: {integrity: sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - basic-ftp@5.0.5: - resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} - engines: {node: '>=10.0.0'} - - before-after-hook@3.0.2: - resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} - - boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - - boxen@8.0.1: - resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} - engines: {node: '>=18'} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - camelcase@8.0.0: - resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} - engines: {node: '>=16'} - - chalk@5.4.1: - resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - - cheerio-select@2.1.0: - resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} - - cheerio@1.0.0: - resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==} - engines: {node: '>=18.17'} - - ci-info@4.2.0: - resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} - engines: {node: '>=8'} - - cli-boxes@3.0.0: - resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} - engines: {node: '>=10'} - - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} - - cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - - cli-width@4.1.0: - resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} - engines: {node: '>= 12'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - compare-func@2.0.0: - resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - concat-stream@2.0.0: - resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} - engines: {'0': node >= 6.0} - - config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - - configstore@7.0.0: - resolution: {integrity: sha512-yk7/5PN5im4qwz0WFZW3PXnzHgPu9mX29Y8uZ3aefe2lBPC1FYttWZRcaW9fKkT0pBCJyuQ2HfbmPVaODi9jcQ==} - engines: {node: '>=18'} - - conventional-changelog-angular@8.0.0: - resolution: {integrity: sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==} - engines: {node: '>=18'} - - conventional-changelog-atom@5.0.0: - resolution: {integrity: sha512-WfzCaAvSCFPkznnLgLnfacRAzjgqjLUjvf3MftfsJzQdDICqkOOpcMtdJF3wTerxSpv2IAAjX8doM3Vozqle3g==} - engines: {node: '>=18'} - - conventional-changelog-codemirror@5.0.0: - resolution: {integrity: sha512-8gsBDI5Y3vrKUCxN6Ue8xr6occZ5nsDEc4C7jO/EovFGozx8uttCAyfhRrvoUAWi2WMm3OmYs+0mPJU7kQdYWQ==} - engines: {node: '>=18'} - - conventional-changelog-conventionalcommits@8.0.0: - resolution: {integrity: sha512-eOvlTO6OcySPyyyk8pKz2dP4jjElYunj9hn9/s0OB+gapTO8zwS9UQWrZ1pmF2hFs3vw1xhonOLGcGjy/zgsuA==} - engines: {node: '>=18'} - - conventional-changelog-core@8.0.0: - resolution: {integrity: sha512-EATUx5y9xewpEe10UEGNpbSHRC6cVZgO+hXQjofMqpy+gFIrcGvH3Fl6yk2VFKh7m+ffenup2N7SZJYpyD9evw==} - engines: {node: '>=18'} - - conventional-changelog-ember@5.0.0: - resolution: {integrity: sha512-RPflVfm5s4cSO33GH/Ey26oxhiC67akcxSKL8CLRT3kQX2W3dbE19sSOM56iFqUJYEwv9mD9r6k79weWe1urfg==} - engines: {node: '>=18'} - - conventional-changelog-eslint@6.0.0: - resolution: {integrity: sha512-eiUyULWjzq+ybPjXwU6NNRflApDWlPEQEHvI8UAItYW/h22RKkMnOAtfCZxMmrcMO1OKUWtcf2MxKYMWe9zJuw==} - engines: {node: '>=18'} - - conventional-changelog-express@5.0.0: - resolution: {integrity: sha512-D8Q6WctPkQpvr2HNCCmwU5GkX22BVHM0r4EW8vN0230TSyS/d6VQJDAxGb84lbg0dFjpO22MwmsikKL++Oo/oQ==} - engines: {node: '>=18'} - - conventional-changelog-jquery@6.0.0: - resolution: {integrity: sha512-2kxmVakyehgyrho2ZHBi90v4AHswkGzHuTaoH40bmeNqUt20yEkDOSpw8HlPBfvEQBwGtbE+5HpRwzj6ac2UfA==} - engines: {node: '>=18'} - - conventional-changelog-jshint@5.0.0: - resolution: {integrity: sha512-gGNphSb/opc76n2eWaO6ma4/Wqu3tpa2w7i9WYqI6Cs2fncDSI2/ihOfMvXveeTTeld0oFvwMVNV+IYQIk3F3g==} - engines: {node: '>=18'} - - conventional-changelog-preset-loader@5.0.0: - resolution: {integrity: sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==} - engines: {node: '>=18'} - - conventional-changelog-writer@8.0.1: - resolution: {integrity: sha512-hlqcy3xHred2gyYg/zXSMXraY2mjAYYo0msUCpK+BGyaVJMFCKWVXPIHiaacGO2GGp13kvHWXFhYmxT4QQqW3Q==} - engines: {node: '>=18'} - hasBin: true - - conventional-changelog@6.0.0: - resolution: {integrity: sha512-tuUH8H/19VjtD9Ig7l6TQRh+Z0Yt0NZ6w/cCkkyzUbGQTnUEmKfGtkC9gGfVgCfOL1Rzno5NgNF4KY8vR+Jo3w==} - engines: {node: '>=18'} - - conventional-commits-filter@5.0.0: - resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==} - engines: {node: '>=18'} - - conventional-commits-parser@6.1.0: - resolution: {integrity: sha512-5nxDo7TwKB5InYBl4ZC//1g9GRwB/F3TXOGR9hgUjMGfvSP4Vu5NkpNro2+1+TIEy1vwxApl5ircECr2ri5JIw==} - engines: {node: '>=18'} - hasBin: true - - conventional-recommended-bump@10.0.0: - resolution: {integrity: sha512-RK/fUnc2btot0oEVtrj3p2doImDSs7iiz/bftFCDzels0Qs1mxLghp+DFHMaOC0qiCI6sWzlTDyBFSYuot6pRA==} - engines: {node: '>=18'} - hasBin: true - - cosmiconfig@9.0.0: - resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - - css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - - data-uri-to-buffer@6.0.2: - resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} - engines: {node: '>= 14'} - - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - - default-browser-id@5.0.0: - resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} - engines: {node: '>=18'} - - default-browser@5.2.1: - resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} - engines: {node: '>=18'} - - define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - - degenerator@5.0.1: - resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} - engines: {node: '>= 14'} - - detect-indent@7.0.1: - resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} - engines: {node: '>=12.20'} - - dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - - domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - - domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - - domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - - dot-prop@5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} - - dot-prop@9.0.0: - resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} - engines: {node: '>=18'} - - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - encoding-sniffer@0.2.0: - resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==} - - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - - escape-goat@4.0.0: - resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} - engines: {node: '>=12'} - - escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} - hasBin: true - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - - execa@9.5.2: - resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==} - engines: {node: ^18.19.0 || >=20.5.0} - - external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - - fast-content-type-parse@2.0.1: - resolution: {integrity: sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==} - - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fastq@1.19.1: - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - - figures@6.1.0: - resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} - engines: {node: '>=18'} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up-simple@1.0.1: - resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} - engines: {node: '>=18'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - get-east-asian-width@1.3.0: - resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} - engines: {node: '>=18'} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - get-stream@9.0.1: - resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} - engines: {node: '>=18'} - - get-uri@6.0.4: - resolution: {integrity: sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==} - engines: {node: '>= 14'} - - git-raw-commits@5.0.0: - resolution: {integrity: sha512-I2ZXrXeOc0KrCvC7swqtIFXFN+rbjnC7b2T943tvemIOVNl+XP8YnA9UVwqFhzzLClnSA60KR/qEjLpXzs73Qg==} - engines: {node: '>=18'} - hasBin: true - - git-semver-tags@8.0.0: - resolution: {integrity: sha512-N7YRIklvPH3wYWAR2vysaqGLPRcpwQ0GKdlqTiVN5w1UmCdaeY3K8s6DMKRCh54DDdzyt/OAB6C8jgVtb7Y2Fg==} - engines: {node: '>=18'} - hasBin: true - - git-up@8.0.1: - resolution: {integrity: sha512-2XFu1uNZMSjkyetaF+8rqn6P0XqpMq/C+2ycjI6YwrIKcszZ5/WR4UubxjN0lILOKqLkLaHDaCr2B6fP1cke6g==} - - git-url-parse@16.0.0: - resolution: {integrity: sha512-Y8iAF0AmCaqXc6a5GYgPQW9ESbncNLOL+CeQAJRhmWUOmnPkKpBYeWYp4mFd3LA5j53CdGDdslzX12yEBVHQQg==} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - global-directory@4.0.1: - resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} - engines: {node: '>=18'} - - globby@14.0.2: - resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==} - engines: {node: '>=18'} - - graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - hosted-git-info@7.0.2: - resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} - engines: {node: ^16.14.0 || >=18.0.0} - - htmlparser2@9.1.0: - resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} - - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - - https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - human-signals@8.0.0: - resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==} - engines: {node: '>=18.18.0'} - - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} - - index-to-position@0.1.2: - resolution: {integrity: sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==} - engines: {node: '>=18'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - - ini@4.1.1: - resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - ini@5.0.0: - resolution: {integrity: sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==} - engines: {node: ^18.17.0 || >=20.5.0} - - inquirer@12.3.0: - resolution: {integrity: sha512-3NixUXq+hM8ezj2wc7wC37b32/rHq1MwNZDYdvx+d6jokOD+r+i8Q4Pkylh9tISYP114A128LCX8RKhopC5RfQ==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - - interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - - ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-in-ci@1.0.0: - resolution: {integrity: sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==} - engines: {node: '>=18'} - hasBin: true - - is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - - is-installed-globally@1.0.0: - resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} - engines: {node: '>=18'} - - is-interactive@2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} - - is-npm@6.0.0: - resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - - is-path-inside@4.0.0: - resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} - engines: {node: '>=12'} - - is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - - is-ssh@1.4.1: - resolution: {integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==} - - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - is-stream@4.0.1: - resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} - engines: {node: '>=18'} - - is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - - is-unicode-supported@2.1.0: - resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} - engines: {node: '>=18'} - - is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} - engines: {node: '>=16'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - issue-parser@7.0.1: - resolution: {integrity: sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==} - engines: {node: ^18.17 || >=20.6.1} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - ky@1.7.5: - resolution: {integrity: sha512-HzhziW6sc5m0pwi5M196+7cEBtbt0lCYi67wNsiwMUmz833wloE0gbzJPWKs1gliFKQb34huItDQX97LyOdPdA==} - engines: {node: '>=18'} - - latest-version@9.0.0: - resolution: {integrity: sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==} - engines: {node: '>=18'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - lodash-es@4.17.21: - resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} - - lodash.capitalize@4.2.1: - resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==} - - lodash.escaperegexp@4.1.2: - resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} - - lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - - lodash.isstring@4.0.1: - resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} - - lodash.uniqby@4.7.0: - resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - log-symbols@6.0.0: - resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} - engines: {node: '>=18'} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - - macos-release@3.3.0: - resolution: {integrity: sha512-tPJQ1HeyiU2vRruNGhZ+VleWuMQRro8iFtJxYgnS4NQe+EukKF6aGiIT+7flZhISAt2iaXBCfFGvAyif7/f8nQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - meow@13.2.0: - resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} - engines: {node: '>=18'} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - mute-stream@2.0.0: - resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} - engines: {node: ^18.17.0 || >=20.5.0} - - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - - netmask@2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} - - new-github-release-url@2.0.0: - resolution: {integrity: sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - normalize-package-data@6.0.2: - resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} - engines: {node: ^16.14.0 || >=18.0.0} - - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - npm-run-path@6.0.0: - resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} - engines: {node: '>=18'} - - nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} - - open@10.1.0: - resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} - engines: {node: '>=18'} - - ora@8.1.1: - resolution: {integrity: sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==} - engines: {node: '>=18'} - - os-name@6.0.0: - resolution: {integrity: sha512-bv608E0UX86atYi2GMGjDe0vF/X1TJjemNS8oEW6z22YW1Rc3QykSYoGfkQbX0zZX9H0ZB6CQP/3GTf1I5hURg==} - engines: {node: '>=18'} - - os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - - pac-proxy-agent@7.2.0: - resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} - engines: {node: '>= 14'} - - pac-resolver@7.0.1: - resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} - engines: {node: '>= 14'} - - package-json@10.0.1: - resolution: {integrity: sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==} - engines: {node: '>=18'} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - - parse-json@8.1.0: - resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==} - engines: {node: '>=18'} - - parse-ms@4.0.0: - resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} - engines: {node: '>=18'} - - parse-path@7.0.1: - resolution: {integrity: sha512-6ReLMptznuuOEzLoGEa+I1oWRSj2Zna5jLWC+l6zlfAI4dbbSaIES29ThzuPkbhNahT65dWzfoZEO6cfJw2Ksg==} - - parse-url@9.2.0: - resolution: {integrity: sha512-bCgsFI+GeGWPAvAiUv63ZorMeif3/U0zaXABGJbOWt5OH2KCaPHF6S+0ok4aqM9RuIPGyZdx9tR9l13PsW4AYQ==} - engines: {node: '>=14.13.0'} - - parse5-htmlparser2-tree-adapter@7.1.0: - resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} - - parse5-parser-stream@7.1.2: - resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} - - parse5@7.2.1: - resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-type@5.0.0: - resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} - engines: {node: '>=12'} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - pretty-ms@9.2.0: - resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} - engines: {node: '>=18'} - - proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - - protocols@2.0.2: - resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} - - proxy-agent@6.5.0: - resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} - engines: {node: '>= 14'} - - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - - pupa@3.1.0: - resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} - engines: {node: '>=12.20'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - - read-package-up@11.0.0: - resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==} - engines: {node: '>=18'} - - read-pkg@9.0.1: - resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} - engines: {node: '>=18'} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - - registry-auth-token@5.1.0: - resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} - engines: {node: '>=14'} - - registry-url@6.0.1: - resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} - engines: {node: '>=12'} - - release-it@18.1.2: - resolution: {integrity: sha512-HOVRcicehCgoCsPFOu0iCBlEC8GDOoKS5s6ICkWmqomGEoZtRQ88D3RCsI5MciSU8vAQU+aWZW2z57NQNNb74w==} - engines: {node: ^20.9.0 || >=22.0.0} - hasBin: true - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} - - retry@0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - run-applescript@7.0.0: - resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} - engines: {node: '>=18'} - - run-async@3.0.0: - resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} - engines: {node: '>=0.12.0'} - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - rxjs@7.8.2: - resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} - engines: {node: '>=10'} - hasBin: true - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - slash@5.1.0: - resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} - engines: {node: '>=14.16'} - - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - - socks-proxy-agent@8.0.5: - resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} - engines: {node: '>= 14'} - - socks@2.8.4: - resolution: {integrity: sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - - spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - - spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - - spdx-license-ids@3.0.21: - resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} - - sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - - stdin-discarder@0.2.2: - resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} - engines: {node: '>=18'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - strip-final-newline@4.0.0: - resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} - engines: {node: '>=18'} - - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - stubborn-fs@1.2.5: - resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - - type-fest@4.37.0: - resolution: {integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==} - engines: {node: '>=16'} - - typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - - uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} - engines: {node: '>=0.8.0'} - hasBin: true - - undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - - undici@6.21.1: - resolution: {integrity: sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==} - engines: {node: '>=18.17'} - - undici@6.21.2: - resolution: {integrity: sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==} - engines: {node: '>=18.17'} - - unicorn-magic@0.1.0: - resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} - engines: {node: '>=18'} - - unicorn-magic@0.3.0: - resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} - engines: {node: '>=18'} - - universal-user-agent@7.0.2: - resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==} - - update-notifier@7.3.1: - resolution: {integrity: sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA==} - engines: {node: '>=18'} - - url-join@5.0.0: - resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - - whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} - - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - - when-exit@2.1.4: - resolution: {integrity: sha512-4rnvd3A1t16PWzrBUcSDZqcAmsUIy4minDXT/CZ8F2mVDgd65i4Aalimgz1aQkRGU0iH5eT5+6Rx2TK8o443Pg==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - widest-line@5.0.0: - resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} - engines: {node: '>=18'} - - wildcard-match@5.1.4: - resolution: {integrity: sha512-wldeCaczs8XXq7hj+5d/F38JE2r7EXgb6WQDM84RVwxy81T/sxB5e9+uZLK9Q9oNz1mlvjut+QtvgaOQFPVq/g==} - - windows-release@6.0.1: - resolution: {integrity: sha512-MS3BzG8QK33dAyqwxfYJCJ03arkwKaddUOvvnnlFdXLudflsQF6I8yAxrLBeQk4yO8wjdH/+ax0YzxJEDrOftg==} - engines: {node: '>=18'} - - wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - - wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - - wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - xdg-basedir@5.1.0: - resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} - engines: {node: '>=12'} - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yoctocolors-cjs@2.1.2: - resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} - engines: {node: '>=18'} - - yoctocolors@2.1.1: - resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} - engines: {node: '>=18'} - -snapshots: - - '@babel/code-frame@7.26.2': - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/helper-validator-identifier@7.25.9': {} - - '@conventional-changelog/git-client@1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0)': - dependencies: - '@types/semver': 7.5.8 - semver: 7.7.1 - optionalDependencies: - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.1.0 - - '@hutson/parse-repository-url@5.0.0': {} - - '@iarna/toml@2.2.5': {} - - '@iarna/toml@3.0.0': {} - - '@inquirer/checkbox@4.1.4(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.5(@types/node@22.13.10) - ansi-escapes: 4.3.2 - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/confirm@5.1.8(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/type': 3.0.5(@types/node@22.13.10) - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/core@10.1.9(@types/node@22.13.10)': - dependencies: - '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.5(@types/node@22.13.10) - ansi-escapes: 4.3.2 - cli-width: 4.1.0 - mute-stream: 2.0.0 - signal-exit: 4.1.0 - wrap-ansi: 6.2.0 - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/editor@4.2.9(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/type': 3.0.5(@types/node@22.13.10) - external-editor: 3.1.0 - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/expand@4.0.11(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/type': 3.0.5(@types/node@22.13.10) - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/figures@1.0.11': {} - - '@inquirer/input@4.1.8(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/type': 3.0.5(@types/node@22.13.10) - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/number@3.0.11(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/type': 3.0.5(@types/node@22.13.10) - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/password@4.0.11(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/type': 3.0.5(@types/node@22.13.10) - ansi-escapes: 4.3.2 - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/prompts@7.4.0(@types/node@22.13.10)': - dependencies: - '@inquirer/checkbox': 4.1.4(@types/node@22.13.10) - '@inquirer/confirm': 5.1.8(@types/node@22.13.10) - '@inquirer/editor': 4.2.9(@types/node@22.13.10) - '@inquirer/expand': 4.0.11(@types/node@22.13.10) - '@inquirer/input': 4.1.8(@types/node@22.13.10) - '@inquirer/number': 3.0.11(@types/node@22.13.10) - '@inquirer/password': 4.0.11(@types/node@22.13.10) - '@inquirer/rawlist': 4.0.11(@types/node@22.13.10) - '@inquirer/search': 3.0.11(@types/node@22.13.10) - '@inquirer/select': 4.1.0(@types/node@22.13.10) - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/rawlist@4.0.11(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/type': 3.0.5(@types/node@22.13.10) - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/search@3.0.11(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.5(@types/node@22.13.10) - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/select@4.1.0(@types/node@22.13.10)': - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.5(@types/node@22.13.10) - ansi-escapes: 4.3.2 - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.13.10 - - '@inquirer/type@3.0.5(@types/node@22.13.10)': - optionalDependencies: - '@types/node': 22.13.10 - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.1 - - '@octokit/auth-token@5.1.2': {} - - '@octokit/core@6.1.4': - dependencies: - '@octokit/auth-token': 5.1.2 - '@octokit/graphql': 8.2.1 - '@octokit/request': 9.2.2 - '@octokit/request-error': 6.1.7 - '@octokit/types': 13.10.0 - before-after-hook: 3.0.2 - universal-user-agent: 7.0.2 - - '@octokit/endpoint@10.1.3': - dependencies: - '@octokit/types': 13.10.0 - universal-user-agent: 7.0.2 - - '@octokit/graphql@8.2.1': - dependencies: - '@octokit/request': 9.2.2 - '@octokit/types': 13.10.0 - universal-user-agent: 7.0.2 - - '@octokit/openapi-types@24.2.0': {} - - '@octokit/plugin-paginate-rest@11.6.0(@octokit/core@6.1.4)': - dependencies: - '@octokit/core': 6.1.4 - '@octokit/types': 13.10.0 - - '@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.4)': - dependencies: - '@octokit/core': 6.1.4 - - '@octokit/plugin-rest-endpoint-methods@13.5.0(@octokit/core@6.1.4)': - dependencies: - '@octokit/core': 6.1.4 - '@octokit/types': 13.10.0 - - '@octokit/request-error@6.1.7': - dependencies: - '@octokit/types': 13.10.0 - - '@octokit/request@9.2.2': - dependencies: - '@octokit/endpoint': 10.1.3 - '@octokit/request-error': 6.1.7 - '@octokit/types': 13.10.0 - fast-content-type-parse: 2.0.1 - universal-user-agent: 7.0.2 - - '@octokit/rest@21.0.2': - dependencies: - '@octokit/core': 6.1.4 - '@octokit/plugin-paginate-rest': 11.6.0(@octokit/core@6.1.4) - '@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.4) - '@octokit/plugin-rest-endpoint-methods': 13.5.0(@octokit/core@6.1.4) - - '@octokit/types@13.10.0': - dependencies: - '@octokit/openapi-types': 24.2.0 - - '@pnpm/config.env-replace@1.1.0': {} - - '@pnpm/network.ca-file@1.0.2': - dependencies: - graceful-fs: 4.2.10 - - '@pnpm/npm-conf@2.3.1': - dependencies: - '@pnpm/config.env-replace': 1.1.0 - '@pnpm/network.ca-file': 1.0.2 - config-chain: 1.1.13 - - '@release-it/bumper@7.0.2(release-it@18.1.2(@types/node@22.13.10))': - dependencies: - '@iarna/toml': 3.0.0 - cheerio: 1.0.0 - detect-indent: 7.0.1 - fast-glob: 3.3.3 - ini: 5.0.0 - js-yaml: 4.1.0 - lodash-es: 4.17.21 - release-it: 18.1.2(@types/node@22.13.10) - semver: 7.7.1 - - '@release-it/conventional-changelog@10.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0)(release-it@18.1.2(@types/node@22.13.10))': - dependencies: - concat-stream: 2.0.0 - conventional-changelog: 6.0.0(conventional-commits-filter@5.0.0) - conventional-recommended-bump: 10.0.0 - git-semver-tags: 8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) - release-it: 18.1.2(@types/node@22.13.10) - semver: 7.7.1 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-parser - - '@sec-ant/readable-stream@0.4.1': {} - - '@sindresorhus/merge-streams@2.3.0': {} - - '@sindresorhus/merge-streams@4.0.0': {} - - '@tootallnate/quickjs-emscripten@0.23.0': {} - - '@types/node@22.13.10': - dependencies: - undici-types: 6.20.0 - - '@types/normalize-package-data@2.4.4': {} - - '@types/parse-path@7.0.3': {} - - '@types/semver@7.5.8': {} - - add-stream@1.0.0: {} - - agent-base@7.1.3: {} - - ansi-align@3.0.1: - dependencies: - string-width: 4.2.3 - - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 - - ansi-regex@5.0.1: {} - - ansi-regex@6.1.0: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.1: {} - - argparse@2.0.1: {} - - array-ify@1.0.0: {} - - ast-types@0.13.4: - dependencies: - tslib: 2.8.1 - - async-retry@1.3.3: - dependencies: - retry: 0.13.1 - - atomically@2.0.3: - dependencies: - stubborn-fs: 1.2.5 - when-exit: 2.1.4 - - balanced-match@1.0.2: {} - - basic-ftp@5.0.5: {} - - before-after-hook@3.0.2: {} - - boolbase@1.0.0: {} - - boxen@8.0.1: - dependencies: - ansi-align: 3.0.1 - camelcase: 8.0.0 - chalk: 5.4.1 - cli-boxes: 3.0.0 - string-width: 7.2.0 - type-fest: 4.37.0 - widest-line: 5.0.0 - wrap-ansi: 9.0.0 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - buffer-from@1.1.2: {} - - bundle-name@4.1.0: - dependencies: - run-applescript: 7.0.0 - - callsites@3.1.0: {} - - camelcase@8.0.0: {} - - chalk@5.4.1: {} - - chardet@0.7.0: {} - - cheerio-select@2.1.0: - dependencies: - boolbase: 1.0.0 - css-select: 5.1.0 - css-what: 6.1.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - - cheerio@1.0.0: - dependencies: - cheerio-select: 2.1.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - domutils: 3.2.2 - encoding-sniffer: 0.2.0 - htmlparser2: 9.1.0 - parse5: 7.2.1 - parse5-htmlparser2-tree-adapter: 7.1.0 - parse5-parser-stream: 7.1.2 - undici: 6.21.2 - whatwg-mimetype: 4.0.0 - - ci-info@4.2.0: {} - - cli-boxes@3.0.0: {} - - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-spinners@2.9.2: {} - - cli-width@4.1.0: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - compare-func@2.0.0: - dependencies: - array-ify: 1.0.0 - dot-prop: 5.3.0 - - concat-map@0.0.1: {} - - concat-stream@2.0.0: - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 3.6.2 - typedarray: 0.0.6 - - config-chain@1.1.13: - dependencies: - ini: 1.3.8 - proto-list: 1.2.4 - - configstore@7.0.0: - dependencies: - atomically: 2.0.3 - dot-prop: 9.0.0 - graceful-fs: 4.2.11 - xdg-basedir: 5.1.0 - - conventional-changelog-angular@8.0.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-atom@5.0.0: {} - - conventional-changelog-codemirror@5.0.0: {} - - conventional-changelog-conventionalcommits@8.0.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-core@8.0.0(conventional-commits-filter@5.0.0): - dependencies: - '@hutson/parse-repository-url': 5.0.0 - add-stream: 1.0.0 - conventional-changelog-writer: 8.0.1 - conventional-commits-parser: 6.1.0 - git-raw-commits: 5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) - git-semver-tags: 8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) - hosted-git-info: 7.0.2 - normalize-package-data: 6.0.2 - read-package-up: 11.0.0 - read-pkg: 9.0.1 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-changelog-ember@5.0.0: {} - - conventional-changelog-eslint@6.0.0: {} - - conventional-changelog-express@5.0.0: {} - - conventional-changelog-jquery@6.0.0: {} - - conventional-changelog-jshint@5.0.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-preset-loader@5.0.0: {} - - conventional-changelog-writer@8.0.1: - dependencies: - conventional-commits-filter: 5.0.0 - handlebars: 4.7.8 - meow: 13.2.0 - semver: 7.7.1 - - conventional-changelog@6.0.0(conventional-commits-filter@5.0.0): - dependencies: - conventional-changelog-angular: 8.0.0 - conventional-changelog-atom: 5.0.0 - conventional-changelog-codemirror: 5.0.0 - conventional-changelog-conventionalcommits: 8.0.0 - conventional-changelog-core: 8.0.0(conventional-commits-filter@5.0.0) - conventional-changelog-ember: 5.0.0 - conventional-changelog-eslint: 6.0.0 - conventional-changelog-express: 5.0.0 - conventional-changelog-jquery: 6.0.0 - conventional-changelog-jshint: 5.0.0 - conventional-changelog-preset-loader: 5.0.0 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-filter@5.0.0: {} - - conventional-commits-parser@6.1.0: - dependencies: - meow: 13.2.0 - - conventional-recommended-bump@10.0.0: - dependencies: - '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) - conventional-changelog-preset-loader: 5.0.0 - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.1.0 - meow: 13.2.0 - - cosmiconfig@9.0.0: - dependencies: - env-paths: 2.2.1 - import-fresh: 3.3.1 - js-yaml: 4.1.0 - parse-json: 5.2.0 - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - css-select@5.1.0: - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 - - css-what@6.1.0: {} - - data-uri-to-buffer@6.0.2: {} - - debug@4.4.0: - dependencies: - ms: 2.1.3 - - deep-extend@0.6.0: {} - - default-browser-id@5.0.0: {} - - default-browser@5.2.1: - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.0 - - define-lazy-prop@3.0.0: {} - - degenerator@5.0.1: - dependencies: - ast-types: 0.13.4 - escodegen: 2.1.0 - esprima: 4.0.1 - - detect-indent@7.0.1: {} - - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - - domelementtype@2.3.0: {} - - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - - dot-prop@5.3.0: - dependencies: - is-obj: 2.0.0 - - dot-prop@9.0.0: - dependencies: - type-fest: 4.37.0 - - emoji-regex@10.4.0: {} - - emoji-regex@8.0.0: {} - - encoding-sniffer@0.2.0: - dependencies: - iconv-lite: 0.6.3 - whatwg-encoding: 3.1.1 - - entities@4.5.0: {} - - env-paths@2.2.1: {} - - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - - escape-goat@4.0.0: {} - - escodegen@2.1.0: - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 - - esprima@4.0.1: {} - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - execa@9.5.2: - dependencies: - '@sindresorhus/merge-streams': 4.0.0 - cross-spawn: 7.0.6 - figures: 6.1.0 - get-stream: 9.0.1 - human-signals: 8.0.0 - is-plain-obj: 4.1.0 - is-stream: 4.0.1 - npm-run-path: 6.0.0 - pretty-ms: 9.2.0 - signal-exit: 4.1.0 - strip-final-newline: 4.0.0 - yoctocolors: 2.1.1 - - external-editor@3.1.0: - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - - fast-content-type-parse@2.0.1: {} - - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fastq@1.19.1: - dependencies: - reusify: 1.1.0 - - figures@6.1.0: - dependencies: - is-unicode-supported: 2.1.0 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up-simple@1.0.1: {} - - fs.realpath@1.0.0: {} - - function-bind@1.1.2: {} - - get-east-asian-width@1.3.0: {} - - get-stream@8.0.1: {} - - get-stream@9.0.1: - dependencies: - '@sec-ant/readable-stream': 0.4.1 - is-stream: 4.0.1 - - get-uri@6.0.4: - dependencies: - basic-ftp: 5.0.5 - data-uri-to-buffer: 6.0.2 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - - git-raw-commits@5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0): - dependencies: - '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) - meow: 13.2.0 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-parser - - git-semver-tags@8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0): - dependencies: - '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.1.0) - meow: 13.2.0 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-parser - - git-up@8.0.1: - dependencies: - is-ssh: 1.4.1 - parse-url: 9.2.0 - - git-url-parse@16.0.0: - dependencies: - git-up: 8.0.1 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - global-directory@4.0.1: - dependencies: - ini: 4.1.1 - - globby@14.0.2: - dependencies: - '@sindresorhus/merge-streams': 2.3.0 - fast-glob: 3.3.3 - ignore: 5.3.2 - path-type: 5.0.0 - slash: 5.1.0 - unicorn-magic: 0.1.0 - - graceful-fs@4.2.10: {} - - graceful-fs@4.2.11: {} - - handlebars@4.7.8: - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - hosted-git-info@7.0.2: - dependencies: - lru-cache: 10.4.3 - - htmlparser2@9.1.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - entities: 4.5.0 - - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.3 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - - https-proxy-agent@7.0.6: - dependencies: - agent-base: 7.1.3 - debug: 4.4.0 - transitivePeerDependencies: - - supports-color - - human-signals@5.0.0: {} - - human-signals@8.0.0: {} - - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - - ignore@5.3.2: {} - - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - index-to-position@0.1.2: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - ini@1.3.8: {} - - ini@4.1.1: {} - - ini@5.0.0: {} - - inquirer@12.3.0(@types/node@22.13.10): - dependencies: - '@inquirer/core': 10.1.9(@types/node@22.13.10) - '@inquirer/prompts': 7.4.0(@types/node@22.13.10) - '@inquirer/type': 3.0.5(@types/node@22.13.10) - '@types/node': 22.13.10 - ansi-escapes: 4.3.2 - mute-stream: 2.0.0 - run-async: 3.0.0 - rxjs: 7.8.2 - - interpret@1.4.0: {} - - ip-address@9.0.5: - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 - - is-arrayish@0.2.1: {} - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-docker@3.0.0: {} - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-in-ci@1.0.0: {} - - is-inside-container@1.0.0: - dependencies: - is-docker: 3.0.0 - - is-installed-globally@1.0.0: - dependencies: - global-directory: 4.0.1 - is-path-inside: 4.0.0 - - is-interactive@2.0.0: {} - - is-npm@6.0.0: {} - - is-number@7.0.0: {} - - is-obj@2.0.0: {} - - is-path-inside@4.0.0: {} - - is-plain-obj@4.1.0: {} - - is-ssh@1.4.1: - dependencies: - protocols: 2.0.2 - - is-stream@3.0.0: {} - - is-stream@4.0.1: {} - - is-unicode-supported@1.3.0: {} - - is-unicode-supported@2.1.0: {} - - is-wsl@3.1.0: - dependencies: - is-inside-container: 1.0.0 - - isexe@2.0.0: {} - - issue-parser@7.0.1: - dependencies: - lodash.capitalize: 4.2.1 - lodash.escaperegexp: 4.1.2 - lodash.isplainobject: 4.0.6 - lodash.isstring: 4.0.1 - lodash.uniqby: 4.7.0 - - js-tokens@4.0.0: {} - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - jsbn@1.1.0: {} - - json-parse-even-better-errors@2.3.1: {} - - ky@1.7.5: {} - - latest-version@9.0.0: - dependencies: - package-json: 10.0.1 - - lines-and-columns@1.2.4: {} - - lodash-es@4.17.21: {} - - lodash.capitalize@4.2.1: {} - - lodash.escaperegexp@4.1.2: {} - - lodash.isplainobject@4.0.6: {} - - lodash.isstring@4.0.1: {} - - lodash.uniqby@4.7.0: {} - - lodash@4.17.21: {} - - log-symbols@6.0.0: - dependencies: - chalk: 5.4.1 - is-unicode-supported: 1.3.0 - - lru-cache@10.4.3: {} - - lru-cache@7.18.3: {} - - macos-release@3.3.0: {} - - meow@13.2.0: {} - - merge-stream@2.0.0: {} - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mimic-fn@4.0.0: {} - - mimic-function@5.0.1: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimist@1.2.8: {} - - ms@2.1.3: {} - - mute-stream@2.0.0: {} - - neo-async@2.6.2: {} - - netmask@2.0.2: {} - - new-github-release-url@2.0.0: - dependencies: - type-fest: 2.19.0 - - normalize-package-data@6.0.2: - dependencies: - hosted-git-info: 7.0.2 - semver: 7.7.1 - validate-npm-package-license: 3.0.4 - - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - - npm-run-path@6.0.0: - dependencies: - path-key: 4.0.0 - unicorn-magic: 0.3.0 - - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - - onetime@7.0.0: - dependencies: - mimic-function: 5.0.1 - - open@10.1.0: - dependencies: - default-browser: 5.2.1 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 3.1.0 - - ora@8.1.1: - dependencies: - chalk: 5.4.1 - cli-cursor: 5.0.0 - cli-spinners: 2.9.2 - is-interactive: 2.0.0 - is-unicode-supported: 2.1.0 - log-symbols: 6.0.0 - stdin-discarder: 0.2.2 - string-width: 7.2.0 - strip-ansi: 7.1.0 - - os-name@6.0.0: - dependencies: - macos-release: 3.3.0 - windows-release: 6.0.1 - - os-tmpdir@1.0.2: {} - - pac-proxy-agent@7.2.0: - dependencies: - '@tootallnate/quickjs-emscripten': 0.23.0 - agent-base: 7.1.3 - debug: 4.4.0 - get-uri: 6.0.4 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - pac-resolver: 7.0.1 - socks-proxy-agent: 8.0.5 - transitivePeerDependencies: - - supports-color - - pac-resolver@7.0.1: - dependencies: - degenerator: 5.0.1 - netmask: 2.0.2 - - package-json@10.0.1: - dependencies: - ky: 1.7.5 - registry-auth-token: 5.1.0 - registry-url: 6.0.1 - semver: 7.6.3 - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.26.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - parse-json@8.1.0: - dependencies: - '@babel/code-frame': 7.26.2 - index-to-position: 0.1.2 - type-fest: 4.37.0 - - parse-ms@4.0.0: {} - - parse-path@7.0.1: - dependencies: - protocols: 2.0.2 - - parse-url@9.2.0: - dependencies: - '@types/parse-path': 7.0.3 - parse-path: 7.0.1 - - parse5-htmlparser2-tree-adapter@7.1.0: - dependencies: - domhandler: 5.0.3 - parse5: 7.2.1 - - parse5-parser-stream@7.1.2: - dependencies: - parse5: 7.2.1 - - parse5@7.2.1: - dependencies: - entities: 4.5.0 - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-key@4.0.0: {} - - path-parse@1.0.7: {} - - path-type@5.0.0: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - pretty-ms@9.2.0: - dependencies: - parse-ms: 4.0.0 - - proto-list@1.2.4: {} - - protocols@2.0.2: {} - - proxy-agent@6.5.0: - dependencies: - agent-base: 7.1.3 - debug: 4.4.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - lru-cache: 7.18.3 - pac-proxy-agent: 7.2.0 - proxy-from-env: 1.1.0 - socks-proxy-agent: 8.0.5 - transitivePeerDependencies: - - supports-color - - proxy-from-env@1.1.0: {} - - pupa@3.1.0: - dependencies: - escape-goat: 4.0.0 - - queue-microtask@1.2.3: {} - - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - - read-package-up@11.0.0: - dependencies: - find-up-simple: 1.0.1 - read-pkg: 9.0.1 - type-fest: 4.37.0 - - read-pkg@9.0.1: - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 6.0.2 - parse-json: 8.1.0 - type-fest: 4.37.0 - unicorn-magic: 0.1.0 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - rechoir@0.6.2: - dependencies: - resolve: 1.22.10 - - registry-auth-token@5.1.0: - dependencies: - '@pnpm/npm-conf': 2.3.1 - - registry-url@6.0.1: - dependencies: - rc: 1.2.8 - - release-it@18.1.2(@types/node@22.13.10): - dependencies: - '@iarna/toml': 2.2.5 - '@octokit/rest': 21.0.2 - async-retry: 1.3.3 - chalk: 5.4.1 - ci-info: 4.2.0 - cosmiconfig: 9.0.0 - execa: 9.5.2 - git-url-parse: 16.0.0 - globby: 14.0.2 - inquirer: 12.3.0(@types/node@22.13.10) - issue-parser: 7.0.1 - lodash: 4.17.21 - mime-types: 2.1.35 - new-github-release-url: 2.0.0 - open: 10.1.0 - ora: 8.1.1 - os-name: 6.0.0 - proxy-agent: 6.5.0 - semver: 7.6.3 - shelljs: 0.8.5 - undici: 6.21.1 - update-notifier: 7.3.1 - url-join: 5.0.0 - wildcard-match: 5.1.4 - yargs-parser: 21.1.1 - transitivePeerDependencies: - - '@types/node' - - supports-color - - typescript - - resolve-from@4.0.0: {} - - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - - retry@0.13.1: {} - - reusify@1.1.0: {} - - run-applescript@7.0.0: {} - - run-async@3.0.0: {} - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - rxjs@7.8.2: - dependencies: - tslib: 2.8.1 - - safe-buffer@5.2.1: {} - - safer-buffer@2.1.2: {} - - semver@7.6.3: {} - - semver@7.7.1: {} - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - shelljs@0.8.5: - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - - signal-exit@4.1.0: {} - - slash@5.1.0: {} - - smart-buffer@4.2.0: {} - - socks-proxy-agent@8.0.5: - dependencies: - agent-base: 7.1.3 - debug: 4.4.0 - socks: 2.8.4 - transitivePeerDependencies: - - supports-color - - socks@2.8.4: - dependencies: - ip-address: 9.0.5 - smart-buffer: 4.2.0 - - source-map@0.6.1: {} - - spdx-correct@3.2.0: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.21 - - spdx-exceptions@2.5.0: {} - - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.21 - - spdx-license-ids@3.0.21: {} - - sprintf-js@1.1.3: {} - - stdin-discarder@0.2.2: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@7.2.0: - dependencies: - emoji-regex: 10.4.0 - get-east-asian-width: 1.3.0 - strip-ansi: 7.1.0 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - - strip-final-newline@3.0.0: {} - - strip-final-newline@4.0.0: {} - - strip-json-comments@2.0.1: {} - - stubborn-fs@1.2.5: {} - - supports-preserve-symlinks-flag@1.0.0: {} - - tmp@0.0.33: - dependencies: - os-tmpdir: 1.0.2 - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - tslib@2.8.1: {} - - type-fest@0.21.3: {} - - type-fest@2.19.0: {} - - type-fest@4.37.0: {} - - typedarray@0.0.6: {} - - uglify-js@3.19.3: - optional: true - - undici-types@6.20.0: {} - - undici@6.21.1: {} - - undici@6.21.2: {} - - unicorn-magic@0.1.0: {} - - unicorn-magic@0.3.0: {} - - universal-user-agent@7.0.2: {} - - update-notifier@7.3.1: - dependencies: - boxen: 8.0.1 - chalk: 5.4.1 - configstore: 7.0.0 - is-in-ci: 1.0.0 - is-installed-globally: 1.0.0 - is-npm: 6.0.0 - latest-version: 9.0.0 - pupa: 3.1.0 - semver: 7.6.3 - xdg-basedir: 5.1.0 - - url-join@5.0.0: {} - - util-deprecate@1.0.2: {} - - validate-npm-package-license@3.0.4: - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 - - whatwg-mimetype@4.0.0: {} - - when-exit@2.1.4: {} - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - widest-line@5.0.0: - dependencies: - string-width: 7.2.0 - - wildcard-match@5.1.4: {} - - windows-release@6.0.1: - dependencies: - execa: 8.0.1 - - wordwrap@1.0.0: {} - - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@9.0.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 7.2.0 - strip-ansi: 7.1.0 - - wrappy@1.0.2: {} - - xdg-basedir@5.1.0: {} - - yargs-parser@21.1.1: {} - - yoctocolors-cjs@2.1.2: {} - - yoctocolors@2.1.1: {} diff --git a/site/plugins/loop/snippets/loop/app.php b/site/plugins/loop/snippets/loop/app.php deleted file mode 100644 index a9e63ae..0000000 --- a/site/plugins/loop/snippets/loop/app.php +++ /dev/null @@ -1,74 +0,0 @@ - Translations - * - */ -function getTranslations(): array -{ - $customLang = Options::language(); - - return [ - 'ui.comment.placeholder' => t('moinframe.loop.ui.comment.placeholder', 'Enter your comment...', $customLang), - 'ui.comment.submit' => t('moinframe.loop.ui.comment.submit', 'Submit', $customLang), - 'ui.comment.cancel' => t('moinframe.loop.ui.comment.cancel', 'Cancel', $customLang), - 'ui.comment.keyboardHint' => t('moinframe.loop.ui.comment.keyboardHint', '⌘+Enter or Ctrl+Enter to submit', $customLang), - 'ui.comment.maker.aria.label' => t('moinframe.loop.ui.comment.maker.aria.label', 'Jump to marker', $customLang), - 'ui.comment.summary.aria.label' => t('moinframe.loop.ui.comment.summary.aria.label', 'Comment by', $customLang), - 'ui.reply.aria.label' => t('moinframe.loop.ui.reply.aria.label', 'Reply by', $customLang), - 'ui.comment.replies.aria.label' => t('moinframe.loop.ui.comment.replies.aria.label', 'Show replies', $customLang), - 'ui.reply.placeholder' => t('moinframe.loop.ui.reply.placeholder', 'Write a reply...', $customLang), - 'ui.reply.submit' => t('moinframe.loop.ui.reply.submit', 'Reply', $customLang), - 'ui.panel.no.comments' => t('moinframe.loop.ui.panel.no.comments', 'No comments yet. Add your first comment to get started.', $customLang), - 'ui.header.browse.mode' => t('moinframe.loop.ui.header.browse.mode', 'Browse', $customLang), - 'ui.header.comment.mode' => t('moinframe.loop.ui.header.comment.mode', 'Comment', $customLang), - 'ui.header.aria.count' => t('moinframe.loop.ui.header.aria.count', 'unresolved comments', $customLang), - 'ui.welcome.guest.name.placeholder' => t('moinframe.loop.ui.welcome.guest.name.placeholder', 'Enter your name', $customLang), - 'ui.welcome.continue' => t('moinframe.loop.ui.welcome.continue', 'Continue', $customLang), - 'ui.welcome.dismiss' => t('moinframe.loop.ui.welcome.dismiss', 'Dismiss', $customLang), - 'ui.comment.mark.solved' => t('moinframe.loop.ui.comment.mark.solved', 'Resolve', $customLang), - 'ui.comment.mark.unsolved' => t('moinframe.loop.ui.comment.mark.unsolved', 'Reopen', $customLang), - 'ui.panel.show.resolved' => t('moinframe.loop.ui.panel.show.resolved', 'Show Resolved Only', $customLang), - 'ui.panel.show.all' => t('moinframe.loop.ui.panel.show.all', 'Show All Comments', $customLang), - 'ui.panel.open' => t('moinframe.loop.ui.panel.open', 'Open comments', $customLang), - 'ui.panel.filter.open' => t('moinframe.loop.ui.panel.filter.open', 'Open', $customLang), - 'ui.panel.filter.resolved' => t('moinframe.loop.ui.panel.filter.resolved', 'Resolved', $customLang), - 'ui.panel.filter.open.active' => t('moinframe.loop.ui.panel.filter.open.active', 'Show open comments (currently selected)', $customLang), - 'ui.panel.filter.open.inactive' => t('moinframe.loop.ui.panel.filter.open.inactive', 'Show open comments', $customLang), - 'ui.panel.filter.resolved.active' => t('moinframe.loop.ui.panel.filter.resolved.active', 'Show resolved comments (currently selected)', $customLang), - 'ui.panel.filter.resolved.inactive' => t('moinframe.loop.ui.panel.filter.resolved.inactive', 'Show resolved comments', $customLang), - 'ui.panel.menu.open' => t('moinframe.loop.ui.panel.menu.open', 'Open menu', $customLang), - 'ui.panel.menu.filter.title' => t('moinframe.loop.ui.panel.menu.filter.title', 'Show Comments', $customLang), - 'ui.panel.no.resolved' => t('moinframe.loop.ui.panel.no.resolved', 'No resolved comments yet.', $customLang), - - // Time formatting - 'ui.time.just_now' => t('moinframe.loop.ui.time.just_now', 'just now', $customLang), - 'ui.time.minute_ago' => t('moinframe.loop.ui.time.minute_ago', 'a minute ago', $customLang), - 'ui.time.minutes_ago' => t('moinframe.loop.ui.time.minutes_ago', '{count} minutes ago', $customLang), - 'ui.time.hour_ago' => t('moinframe.loop.ui.time.hour_ago', 'an hour ago', $customLang), - 'ui.time.hours_ago' => t('moinframe.loop.ui.time.hours_ago', '{count} hours ago', $customLang), - 'ui.time.yesterday' => t('moinframe.loop.ui.time.yesterday', 'yesterday', $customLang), - 'ui.time.days_ago' => t('moinframe.loop.ui.time.days_ago', '{count} days ago', $customLang) - ]; -} - -if (Options::enabled() && (Options::public() || kirby()->user() !== null)): ?> - - - diff --git a/site/plugins/loop/src/App.php b/site/plugins/loop/src/App.php deleted file mode 100644 index 4181b8d..0000000 --- a/site/plugins/loop/src/App.php +++ /dev/null @@ -1,199 +0,0 @@ -user(); - - if (null === $user) { - return ''; - } - - return ''; - } - - /** - * Gets the database instance (singleton) - * @return Database - */ - protected static function db(): Database - { - if (self::$instance === null) { - self::$instance = new Database(); - } - - return self::$instance; - } - - /** - * Converts array data to Comment objects - * @param array $commentsData - * @return Comment[] - */ - private static function convertToCommentObjects(array $commentsData): array - { - $comments = []; - foreach ($commentsData as $commentData) { - $comment = Comment::fromArray($commentData); - $comments[] = $comment; - } - return $comments; - } - /** - * Get comments by kirby page - * @param Page $page - * @param string $lang Language code - * @return Comment[] - */ - public static function getCommentsByPage(\Kirby\Cms\Page $page, string $lang = ''): array - { - try { - // @phpstan-ignore method.notFound - $pageUuid = $page->content()->uuid()->value(); - $db = self::db(); - - // Use optimized query that filters at database level - $commentsData = $db::getCommentsByPage($pageUuid, $lang)->toArray(); - - return self::convertToCommentObjects($commentsData); - } catch (\Exception $e) { - return []; - } - } - - - /** - * Retrieves all comments organized in a nested structure - * @return Comment[] array of Comment objects with nested replies - * @remarks Top-level comments have replies as children - */ - public static function getComments(): array - { - try { - $db = self::db(); - // Use optimized query that fetches comments with replies in 2 queries instead of N+1 - $commentsData = $db::getCommentsWithReplies()->toArray(); - - return self::convertToCommentObjects($commentsData); - } catch (\Exception $e) { - return []; - } - } - - /** - * Creates a Comment from array data - * @param array $data - * @return Comment|null The created comment or null if validation fails - */ - public static function createComment(array $data): ?Comment - { - try { - return Comment::fromArray($data); - } catch (\InvalidArgumentException $e) { - error_log(tt('moinframe.loop.comment.creation.failed', ['error' => $e->getMessage()])); - return null; - } - } - - /** - * Creates a Reply from array data - * @param array $data - * @return Reply|null The created reply or null if validation fails - */ - public static function createReply(array $data): ?Reply - { - try { - return Reply::fromArray($data); - } catch (\InvalidArgumentException $e) { - error_log(tt('moinframe.loop.reply.creation.failed', ['error' => $e->getMessage()])); - return null; - } - } - - /** - * Adds a new comment to the database - * @param Comment $comment Comment to add - * @return Comment|null The added comment or null on failure - */ - public static function addComment(Comment $comment): ?Comment - { - try { - if (!$comment->isValid()) { - error_log(tt('moinframe.loop.comment.validation.error', ['errors' => implode(', ', $comment->validate())])); - return null; - } - - $comment = self::db()::addComment($comment); - return $comment; - } catch (\Exception $e) { - error_log(tt('moinframe.loop.comment.add.failed', ['error' => $e->getMessage()])); - return null; - } - } - - /** - * Adds a new reply to the database - * @param Reply $reply Reply to add - * @return Reply|null The added reply or null on failure - */ - public static function addReply(Reply $reply): ?Reply - { - try { - if (!$reply->isValid()) { - error_log(tt('moinframe.loop.reply.validation.error', ['errors' => implode(', ', $reply->validate())])); - return null; - } - - $reply = self::db()::addReply($reply); - return $reply; - } catch (\Exception $e) { - error_log(tt('moinframe.loop.reply.add.failed', ['error' => $e->getMessage()])); - return null; - } - } - - public static function resolveComment(string $commentId): bool - { - try { - $success = self::db()::updateCommentStatus($commentId, 'RESOLVED'); - return $success; - } catch (\Exception $e) { - return false; - } - } - - public static function unresolveComment(string $commentId): bool - { - try { - $success = self::db()::updateCommentStatus($commentId, 'OPEN'); - return $success; - } catch (\Exception $e) { - return false; - } - } -} diff --git a/site/plugins/loop/src/Database.php b/site/plugins/loop/src/Database.php deleted file mode 100644 index f412942..0000000 --- a/site/plugins/loop/src/Database.php +++ /dev/null @@ -1,356 +0,0 @@ - 'sqlite', - 'database' => $dbPath - ]); - } - } - - /** - * Creates an empty database with schema - * @param string $path Database file path - */ - protected static function createEmptyDatabase(string $path): void - { - $db = new \SQLite3($path); - $db->exec('PRAGMA foreign_keys = ON;'); - - $db->exec('CREATE TABLE IF NOT EXISTS comments ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - author TEXT NOT NULL, - url TEXT NOT NULL, - page TEXT NOT NULL, - comment TEXT NOT NULL, - selector TEXT NOT NULL, - selectorOffsetX REAL NOT NULL, - selectorOffsetY REAL NOT NULL, - pagePositionX REAL NOT NULL, - pagePositionY REAL NOT NULL, - status TEXT NOT NULL, - timestamp INTEGER NOT NULL, - lang TEXT NOT NULL DEFAULT "" - )'); - - // Create indexes for better performance - $db->exec('CREATE INDEX IF NOT EXISTS idx_comments_page_lang ON comments(page, lang)'); - $db->exec('CREATE INDEX IF NOT EXISTS idx_comments_status ON comments(status)'); - $db->exec('CREATE INDEX IF NOT EXISTS idx_comments_timestamp ON comments(timestamp)'); - - $db->exec('CREATE TABLE IF NOT EXISTS replies ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - author TEXT NOT NULL, - comment TEXT NOT NULL, - parentId INTEGER NOT NULL, - timestamp INTEGER NOT NULL, - FOREIGN KEY (parentId) REFERENCES comments(id) ON DELETE CASCADE - )'); - - // Create indexes for replies - $db->exec('CREATE INDEX IF NOT EXISTS idx_replies_parent ON replies(parentId)'); - $db->exec('CREATE INDEX IF NOT EXISTS idx_replies_timestamp ON replies(timestamp)'); - - $db->close(); - } - - /** - * Returns a query builder for replies table - * @return \Kirby\Database\Query - */ - protected static function tableReplies(): \Kirby\Database\Query - { - self::initializeDatabase(); - return Db::table('replies'); - } - - /** - * Returns a query builder for comments table - * @return \Kirby\Database\Query - */ - protected static function tableComments(): \Kirby\Database\Query - { - self::initializeDatabase(); - return Db::table('comments'); - } - - - /** - * Retrieves all comments from the database - * @return Collection Array of comments - */ - public static function getComments(): Collection - { - try { - $comments = self::tableComments() - ->select('*') - ->order('timestamp DESC') - ->all(); - return $comments; - } catch (\Exception $e) { - return new Collection(); - } - } - - /** - * Retrieves comments with their replies in a single optimized query - * @param string|null $status Filter by status (optional) - * @return Collection Array of comments with nested replies - */ - public static function getCommentsWithReplies(?string $status = null): Collection - { - try { - // Build the main comments query - $commentsQuery = self::tableComments()->select('*'); - - if ($status !== null) { - $commentsQuery = $commentsQuery->where('status', '!=', $status); - } - - $comments = $commentsQuery->order('timestamp DESC')->all(); - - if ($comments->count() === 0) { - return new Collection(); - } - - // Get all comment IDs for efficient reply lookup - $commentIds = $comments->pluck('id'); - - // Single query to get all replies for these comments - $replies = self::tableReplies() - ->select('*') - ->where('parentId', 'in', $commentIds) - ->order('timestamp ASC') - ->all(); - - // Group replies by parentId for efficient lookup - $repliesByParent = []; - foreach ($replies as $reply) { - $parentId = $reply->parentId; - if (!isset($repliesByParent[$parentId])) { - $repliesByParent[$parentId] = []; - } - $repliesByParent[$parentId][] = $reply->toArray(); - } - - // Add replies to their parent comments - $result = []; - foreach ($comments as $comment) { - $commentArray = $comment->toArray(); - $commentArray['replies'] = $repliesByParent[$comment->id] ?? []; - $result[] = $commentArray; - } - - return new Collection($result); - } catch (\Exception $e) { - return new Collection(); - } - } - - /** - * Retrieves comments for a specific page with their replies - * @param string $pageUuid Page UUID to filter by - * @param string $lang Language to filter by - * @param string|null $status Status to exclude (optional) - * @return Collection Array of comments with nested replies - */ - public static function getCommentsByPage(string $pageUuid, string $lang = '', ?string $status = null): Collection - { - try { - // Build the main comments query with page filter - $commentsQuery = self::tableComments() - ->select('*') - ->where('page', '=', $pageUuid); - - // Add language filter only if language is specified - if ($lang !== '') { - $commentsQuery = $commentsQuery->where('lang', '=', $lang); - } - - if ($status !== null) { - $commentsQuery = $commentsQuery->where('status', '!=', $status); - } - - $comments = $commentsQuery->order('timestamp DESC')->all(); - - if ($comments->count() === 0) { - return new Collection(); - } - - // Get all comment IDs for efficient reply lookup - $commentIds = $comments->pluck('id'); - - // Single query to get all replies for these comments - $replies = self::tableReplies() - ->select('*') - ->where('parentId', 'in', $commentIds) - ->order('timestamp ASC') - ->all(); - - // Group replies by parentId for efficient lookup - $repliesByParent = []; - foreach ($replies as $reply) { - $parentId = $reply->parentId(); - if (!isset($repliesByParent[$parentId])) { - $repliesByParent[$parentId] = []; - } - $repliesByParent[$parentId][] = $reply->toArray(); - } - - // Add replies to their parent comments - $result = []; - foreach ($comments as $comment) { - $commentArray = $comment->toArray(); - $commentArray['replies'] = $repliesByParent[$comment->id] ?? []; - $result[] = $commentArray; - } - - return new Collection($result); - } catch (\Exception $e) { - return new Collection(); - } - } - - /** - * Retrieves all replies from the database - * @return Collection Array of comments - */ - public static function getReplies(): Collection - { - try { - $replies = self::tableReplies() - ->select('*') - ->order('timestamp DESC') - ->all(); - return $replies; - } catch (\Exception $e) { - return new Collection(); - } - } - - /** - * Adds a new comment to the database - * @param Comment $comment Comment data - * @return Comment|null The added comment or null on failure - */ - public static function addComment(Comment $comment): ?Comment - { - try { - $data = $comment->toArray(); - // Remove id field for insertion to allow auto-increment - unset($data['id']); - - $id = self::tableComments()->insert($data); - - if (null !== $id) { - $comment->id = $id; - return $comment; - } - - return null; - } catch (\Exception $e) { - return null; - } - } - - /** - * Adds a new reply to the database - * @param Reply $reply Reply data - * @return Reply|null The added reply or null on failure - */ - public static function addReply(Reply $reply): ?Reply - { - try { - $data = $reply->toArray(); - // Remove id field for insertion to allow auto-increment - unset($data['id']); - - $id = self::tableReplies()->insert($data); - - if (null !== $id) { - $reply->id = $id; - return $reply; - } - - return null; - } catch (\Exception $e) { - return null; - } - } - - // /** - // * Updates a comment in the database - // * @param string $id Comment ID - // * @param array $data Updated comment data - // * @return bool Success status - // */ - // public static function updateComment(string $id, array $data): bool - // { - // try { - // $updateData = []; - - // foreach ($data as $key => $value) { - // if (in_array($key, ['comment', 'selector', 'posX', 'posY'])) { - // $updateData[$key] = $value; - // } - // } - - // if (empty($updateData)) { - // return false; - // } - - // return self::table()->update($updateData, ['id' => $id]); - // } catch (\Exception $e) { - // return false; - // } - // } - - /** - * Updates a comment's status - * @param string $id Comment ID - * @param string $status New status - * @return bool Success status - */ - public static function updateCommentStatus(string $id, string $status): bool - { - try { - return self::tableComments()->update( - ['status' => $status], - ['id' => $id] - ); - } catch (\Exception $e) { - return false; - } - } -} diff --git a/site/plugins/loop/src/Enums/CommentStatus.php b/site/plugins/loop/src/Enums/CommentStatus.php deleted file mode 100644 index b8418e5..0000000 --- a/site/plugins/loop/src/Enums/CommentStatus.php +++ /dev/null @@ -1,9 +0,0 @@ - 'error', - 'message' => 'Loop is disabled', - 'code' => 'DISABLED' - ], 403); - } - - $csrfToken = kirby()->request()->header('X-CSRF-Token'); - if (csrf($csrfToken) !== true) { - return Response::json([ - 'status' => 'error', - 'message' => t('moinframe.loop.csrf.invalid'), - 'code' => 'CSRF_INVALID' - ], 403); - } - - - if (Options::public() === false && kirby()->user() === null) { - return Response::json([ - 'status' => 'error', - 'message' => 'Unauthorized', - 'code' => 'UNAUTHORIZED' - ], 401); - } - - - return $next(...func_get_args()); - }; - } -} diff --git a/site/plugins/loop/src/Models/Comment.php b/site/plugins/loop/src/Models/Comment.php deleted file mode 100644 index b0cef59..0000000 --- a/site/plugins/loop/src/Models/Comment.php +++ /dev/null @@ -1,359 +0,0 @@ - 0) { - throw new \InvalidArgumentException(tt('moinframe.loop.comment.validation.failed', ['errors' => implode(', ', $errors)])); - } - - $data = static::transformNumbers($data); - - // Convert reply arrays to Reply objects - $replies = []; - if (isset($data['replies']) && is_array($data['replies'])) { - foreach ($data['replies'] as $replyData) { - $replies[] = Reply::fromArray($replyData); - } - } - - return new self( - id: $data['id'] ?? 0, - author: strip_tags($data['author'] ?? ''), - url: $data['url'] ?? '', - page: $data['page'] ?? '', - selector: $data['selector'] ?? '', - selectorOffsetX: $data['selectorOffsetX'] ?? 0, - selectorOffsetY: $data['selectorOffsetY'] ?? 0, - pagePositionX: $data['pagePositionX'] ?? 0, - pagePositionY: $data['pagePositionY'] ?? 0, - status: isset($data['status']) ? CommentStatus::from($data['status']) : CommentStatus::OPEN, - comment: strip_tags($data['comment'] ?? ''), - timestamp: $data['timestamp'] ?? 0, - lang: $data['lang'] ?? '', - replies: $replies - ); - } - - - /** - * Transforms numeric fields in comment data - * - * @param array $item - * @return array - */ - protected static function transformNumbers(array $item): array - { - // Create a new array instead of modifying the input - $result = $item; - - // Handle each numeric field explicitly - if (isset($result['id'])) { - $result['id'] = (int)$result['id']; - } - - if (isset($result['selectorOffsetX'])) { - $result['selectorOffsetX'] = (float)$result['selectorOffsetX']; - } - - if (isset($result['selectorOffsetY'])) { - $result['selectorOffsetY'] = (float)$result['selectorOffsetY']; - } - - if (isset($result['pagePositionX'])) { - $result['pagePositionX'] = (float)$result['pagePositionX']; - } - - if (isset($result['pagePositionY'])) { - $result['pagePositionY'] = (float)$result['pagePositionY']; - } - - if (isset($result['timestamp'])) { - $result['timestamp'] = (int)$result['timestamp']; - } - - - return $result; - } - - /** - * Validates the comment data using Kirby validators - * @return array Array of validation errors (empty if valid) - */ - /** @phpstan-ignore-next-line */ - public function validate(): array - { - $rules = [ - 'author' => ['required', 'maxLength' => 255], - 'comment' => ['required', 'maxLength' => 5000], - 'page' => ['required', 'maxLength' => 255], - 'selector' => ['required', 'maxLength' => 1000], - 'url' => ['maxLength' => 2048], - 'selectorOffsetX' => ['min' => 0], - 'selectorOffsetY' => ['min' => 0], - 'pagePositionX' => ['min' => 0], - 'pagePositionY' => ['min' => 0], - 'timestamp' => ['min' => 0] - ]; - - $messages = [ - 'author' => [ - t('moinframe.loop.author.required'), - t('moinframe.loop.author.max.length') - ], - 'comment' => [ - t('moinframe.loop.comment.required'), - t('moinframe.loop.comment.max.length') - ], - 'page' => [ - t('moinframe.loop.page.required'), - t('moinframe.loop.page.max.length') - ], - 'selector' => [ - t('moinframe.loop.selector.required'), - t('moinframe.loop.selector.max.length') - ], - 'url' => t('moinframe.loop.url.max.length'), - 'selectorOffsetX' => t('moinframe.loop.selector.offset.x.min'), - 'selectorOffsetY' => t('moinframe.loop.selector.offset.y.min'), - 'pagePositionX' => t('moinframe.loop.page.position.x.min'), - 'pagePositionY' => t('moinframe.loop.page.position.y.min'), - 'timestamp' => t('moinframe.loop.timestamp.min') - ]; - - $data = $this->toArray(); - - // Custom URL validation if provided - if (($data['url'] ?? '') !== '' && filter_var($data['url'], FILTER_VALIDATE_URL) === false) { - return [t('moinframe.loop.url.format.invalid')]; - } - - /** @phpstan-ignore-next-line */ - $invalid = invalid($data, $rules, $messages) ?: []; - - // Convert validation errors to flat array of strings - $errors = []; - foreach ($invalid as $field => $fieldErrors) { - if (is_array($fieldErrors)) { - // Multiple validation rules failed for this field - foreach ($fieldErrors as $error) { - $errors[] = (string) $error; - } - } else { - // Single validation rule failed - $errors[] = (string) $fieldErrors; - } - } - - // Validate replies - foreach ($this->replies as $index => $reply) { - $replyErrors = $reply->validate(); - foreach ($replyErrors as $replyError) { - $errors[] = tt('moinframe.loop.reply.index.error', ['index' => $index, 'error' => $replyError]); - } - } - - return $errors; - } - - /** - * Checks if the comment is valid - * @return bool - */ - public function isValid(): bool - { - return count($this->validate()) === 0; - } - - /** - * Validates data before creating Comment instance using Kirby validators - * @param array $data - * @return array Array of validation errors - */ - /** @phpstan-ignore-next-line */ - public static function validateData(array $data): array - { - $rules = [ - 'author' => ['required', 'maxLength' => 255], - 'comment' => ['required', 'maxLength' => 5000], - 'page' => ['required', 'maxLength' => 255], - 'selector' => ['required', 'maxLength' => 1000], - 'url' => ['maxLength' => 2048], - 'selectorOffsetX' => ['min' => 0], - 'selectorOffsetY' => ['min' => 0], - 'pagePositionX' => ['min' => 0], - 'pagePositionY' => ['min' => 0], - 'timestamp' => ['min' => 0] - ]; - - $messages = [ - 'author' => [ - t('moinframe.loop.author.required'), - t('moinframe.loop.author.max.length') - ], - 'comment' => [ - t('moinframe.loop.comment.required'), - t('moinframe.loop.comment.max.length') - ], - 'page' => [ - t('moinframe.loop.page.required'), - t('moinframe.loop.page.max.length') - ], - 'selector' => [ - t('moinframe.loop.selector.required'), - t('moinframe.loop.selector.max.length') - ], - 'url' => t('moinframe.loop.url.max.length'), - 'selectorOffsetX' => t('moinframe.loop.selector.offset.x.min'), - 'selectorOffsetY' => t('moinframe.loop.selector.offset.y.min'), - 'pagePositionX' => t('moinframe.loop.page.position.x.min'), - 'pagePositionY' => t('moinframe.loop.page.position.y.min'), - 'timestamp' => t('moinframe.loop.timestamp.min') - ]; - - // Custom URL validation if provided - if (($data['url'] ?? '') !== '' && filter_var($data['url'], FILTER_VALIDATE_URL) === false) { - return [t('moinframe.loop.url.format.invalid')]; - } - - /** @phpstan-ignore-next-line */ - $invalid = invalid($data, $rules, $messages) ?: []; - - // Convert validation errors to flat array of strings - $errors = []; - foreach ($invalid as $field => $fieldErrors) { - if (is_array($fieldErrors)) { - // Multiple validation rules failed for this field - foreach ($fieldErrors as $error) { - $errors[] = (string) $error; - } - } else { - // Single validation rule failed - $errors[] = (string) $fieldErrors; - } - } - - return $errors; - } - - /** - * Resolves the author string to a display name - * If author starts with 'user://', attempts to resolve Kirby user - * Returns user's name or email prefix, otherwise returns the stored string - * @return string Resolved author display name - */ - public function resolveAuthor(): string - { - // Check if author is a Kirby user reference - if (str_starts_with($this->author, 'user://')) { - $userId = substr($this->author, 7); // Remove 'user://' prefix - - try { - $user = kirby()->user($userId); - if ($user !== null && $user->exists()) { - // Return user's name if available - if ($user->name()->isNotEmpty()) { - return $user->name()->value(); - } - - // Fallback to email prefix (everything before @) - $email = $user->email(); - if ($email !== null && str_contains($email, '@')) { - return explode('@', $email)[0]; - } - - // Final fallback to email - return $email !== null ? $email : $this->author; - } - } catch (\Exception) { - // If user resolution fails, fall back to original string - } - } - - // Return the original author string if not a user reference or resolution failed - return $this->author; - } - - /** - * Convert Comment instance to array - * - * @return array - */ - public function toArray(): array - { - // Convert Reply objects to arrays - $replies = []; - foreach ($this->replies as $reply) { - $replies[] = $reply->toArray(); - } - - return [ - 'id' => $this->id ?? null, - 'author' => $this->resolveAuthor(), - 'url' => $this->url, - 'page' => $this->page, - 'comment' => $this->comment, - 'selector' => $this->selector, - 'selectorOffsetX' => $this->selectorOffsetX, - 'selectorOffsetY' => $this->selectorOffsetY, - 'pagePositionX' => $this->pagePositionX, - 'pagePositionY' => $this->pagePositionY, - 'status' => $this->status->value, - 'replies' => $replies, - 'timestamp' => $this->timestamp, - 'lang' => $this->lang - ]; - } -} diff --git a/site/plugins/loop/src/Models/Reply.php b/site/plugins/loop/src/Models/Reply.php deleted file mode 100644 index 15485c9..0000000 --- a/site/plugins/loop/src/Models/Reply.php +++ /dev/null @@ -1,198 +0,0 @@ - 0) { - throw new \InvalidArgumentException(tt('moinframe.loop.reply.validation.failed', ['errors' => implode(', ', $errors)])); - } - - $data = static::transformNumbers($data); - - return new self( - id: $data['id'] ?? 0, - author: strip_tags($data['author'] ?? ''), - comment: strip_tags($data['comment'] ?? ''), - parentId: $data['parentId'] ?? 0, - timestamp: $data['timestamp'] ?? 0 - ); - } - - /** - * Transforms numeric fields in reply data - * - * @param array $item - * @return array - */ - protected static function transformNumbers(array $item): array - { - $result = $item; - - if (isset($result['id'])) { - $result['id'] = (int)$result['id']; - } - - if (isset($result['parentId'])) { - $result['parentId'] = (int)$result['parentId']; - } - - if (isset($result['timestamp'])) { - $result['timestamp'] = (int)$result['timestamp']; - } - - return $result; - } - - /** - * Validates the reply data using Kirby validators - * @return array Array of validation errors (empty if valid) - */ - public function validate(): array - { - $rules = [ - 'author' => ['required', 'maxLength' => 255], - 'comment' => ['required', 'maxLength' => 5000], - 'parentId' => ['required', 'min' => 1], - 'timestamp' => ['min' => 0] - ]; - - $messages = [ - 'author' => [ - t('moinframe.loop.author.required'), - t('moinframe.loop.author.max.length') - ], - 'comment' => [ - t('moinframe.loop.comment.required'), - t('moinframe.loop.comment.max.length') - ], - 'parentId' => [ - t('moinframe.loop.parent.id.required'), - t('moinframe.loop.parent.id.required') - ], - 'timestamp' => t('moinframe.loop.timestamp.min') - ]; - - $data = $this->toArray(); - /** @phpstan-ignore-next-line */ - $invalid = invalid($data, $rules, $messages) ?: []; - return array_map('strval', array_values($invalid)); - } - - /** - * Checks if the reply is valid - * @return bool - */ - public function isValid(): bool - { - return count($this->validate()) === 0; - } - - /** - * Validates data before creating Reply instance using Kirby validators - * @param array $data - * @return array Array of validation errors - */ - public static function validateData(array $data): array - { - $rules = [ - 'author' => ['required', 'maxLength' => 255], - 'comment' => ['required', 'maxLength' => 5000], - 'parentId' => ['required', 'min' => 1], - 'timestamp' => ['min' => 0] - ]; - - $messages = [ - 'author' => [ - t('moinframe.loop.author.required'), - t('moinframe.loop.author.max.length') - ], - 'comment' => [ - t('moinframe.loop.comment.required'), - t('moinframe.loop.comment.max.length') - ], - 'parentId' => [ - t('moinframe.loop.parent.id.required'), - t('moinframe.loop.parent.id.required') - ], - 'timestamp' => t('moinframe.loop.timestamp.min') - ]; - - /** @phpstan-ignore-next-line */ - $invalid = invalid($data, $rules, $messages) ?: []; - return array_map('strval', array_values($invalid)); - } - - /** - * Resolves the author string to a display name - * If author starts with 'user://', attempts to resolve Kirby user - * Returns user's name or email prefix, otherwise returns the stored string - * @return string Resolved author display name - */ - public function resolveAuthor(): string - { - // Check if author is a Kirby user reference - if (str_starts_with($this->author, 'user://')) { - $userId = substr($this->author, 7); // Remove 'user://' prefix - - try { - $user = kirby()->user($userId); - if ($user !== null && $user->exists()) { - // Return user's name if available - if ($user->name()->isNotEmpty()) { - return $user->name()->value(); - } - - // Fallback to email prefix (everything before @) - $email = $user->email(); - if ($email !== null && str_contains($email, '@')) { - return explode('@', $email)[0]; - } - - // Final fallback to email - return $email !== null ? $email : $this->author; - } - } catch (\Exception) { - // If user resolution fails, fall back to original string - } - } - - // Return the original author string if not a user reference or resolution failed - return $this->author; - } - - /** - * Convert Reply instance to array - * - * @return array - */ - public function toArray(): array - { - return [ - 'id' => $this->id, - 'author' => $this->resolveAuthor(), - 'comment' => $this->comment, - 'parentId' => $this->parentId, - 'timestamp' => $this->timestamp - ]; - } -} diff --git a/site/plugins/loop/src/Options.php b/site/plugins/loop/src/Options.php deleted file mode 100644 index 0f6d6cd..0000000 --- a/site/plugins/loop/src/Options.php +++ /dev/null @@ -1,114 +0,0 @@ -root('logs') . '/loop/comments.sqlite'); - } - - /** - * Get header position (top or bottom) - * @return string - */ - public static function position(): string - { - return option('moinframe.loop.position', 'top'); - } - - /** - * Check if auto-injection is enabled - * @return bool - */ - public static function autoInject(): bool - { - return option('moinframe.loop.auto-inject', true); - } - - /** - * Check if loop is enabled for the current page - * @return bool - */ - public static function enabled(): bool - { - $enabledOption = option('moinframe.loop.enabled', true); - - // If it's a boolean, return it directly - if (is_bool($enabledOption)) { - return $enabledOption; - } - - // If it's a callable, execute it with the current page - if (is_callable($enabledOption)) { - $page = kirby()->site()->page(); - return (bool) $enabledOption($page); - } - - // Default to enabled if invalid configuration - return true; - } - - /** - * Check if welcome dialog is enabled - * @return bool - */ - public static function welcomeDialogEnabled(): bool - { - return option('moinframe.loop.welcome.enabled', true); - } - - /** - * Get welcome dialog headline - * @return string - */ - public static function welcomeDialogHeadline(): string - { - $customLang = self::language(); - return option('moinframe.loop.welcome.headline', $customLang !== null ? t('moinframe.loop.welcome.headline', '', $customLang) : t('moinframe.loop.welcome.headline')); - } - - /** - * Get welcome dialog text - * @return string - */ - public static function welcomeDialogText(): string - { - $customLang = self::language(); - $translatedPosition = t('moinframe.loop.ui.header.position.' . self::position(), self::position(), $customLang); - return option('moinframe.loop.welcome.text', $customLang !== null ? tt('moinframe.loop.welcome.text', '', ['position' => $translatedPosition], $customLang) : tt('moinframe.loop.welcome.text', ['position' => $translatedPosition])); - } - - /** - * Get custom language setting for loop - * @return string|null - */ - public static function language(): ?string - { - return option('moinframe.loop.language', null); - } - - /** - * Set a theme - * @return string - */ - public static function theme(): string - { - return option('moinframe.loop.theme', 'default'); - } -} diff --git a/site/plugins/loop/src/Routes.php b/site/plugins/loop/src/Routes.php deleted file mode 100644 index e7f39fa..0000000 --- a/site/plugins/loop/src/Routes.php +++ /dev/null @@ -1,312 +0,0 @@ - Error response array - */ - private static function errorResponse(string $message, ?string $code = null): array - { - $response = [ - 'status' => 'error', - 'message' => $message - ]; - - if ($code !== null) { - $response['code'] = $code; - } - - return $response; - } - /** - * Registers routes and returns route definitions - * @return array Route definitions array - */ - public static function register(): array - { - - return [ - [ - 'pattern' => 'loop/comments/(:all)', - 'method' => 'GET', - 'language' => '*', - 'action' => Middleware::auth(function ($language = null, $pageId = null) { - - // Handle both multilingual and non-multilingual cases - if ($pageId === null && $language !== null) { - // Non-multilingual: only pageId was passed as first argument - $pageId = $language; - $language = null; - } - $onPage = null; - - if ($pageId === 'home'): - $onPage = kirby()->site()->homePage(); - else: - $onPage = page($pageId); - endif; - - // If not found, check if it's a draft and validate access - if (null === $onPage) { - $draftPage = kirby()->page($pageId); - if ($draftPage !== null && $draftPage->isDraft() && ( - (App::getKirbyMajorVersion() >= 5 && $draftPage->renderVersionFromRequest() !== null) || - // @phpstan-ignore method.notFound - (App::getKirbyMajorVersion() < 5 && $draftPage->isVerified(get('token')) === true) - )) { - $onPage = $draftPage; - } - } - - if (null === $onPage) { - return Response::json(self::errorResponse( - tt('moinframe.loop.page.not.found', ['pageId' => $pageId]), - self::ERROR_PAGE_NOT_FOUND - ), 400); - } - - $comments = App::getCommentsByPage($onPage, $language ?? ''); - - // Convert Comment objects to arrays to ensure resolved authors are included - $commentsArray = array_map(function ($comment) { - return $comment->toArray(); - }, $comments); - - return Response::json([ - 'status' => 'ok', - 'comments' => $commentsArray - ], 200); - }) - ], - [ - 'pattern' => 'loop/comment/new', - 'method' => 'POST', - 'language' => '*', - 'action' => Middleware::auth(function ($language = null) { - - $data = kirby()->request()->data(); - - // Sanitize input data - if (isset($data['comment'])) { - $data['comment'] = htmlspecialchars(strip_tags($data['comment']), ENT_QUOTES, 'UTF-8'); - } - if (isset($data['selector'])) { - // Validate selector but don't HTML encode it as it needs to remain a valid CSS selector - $data['selector'] = trim($data['selector']); - // Basic validation - selector should not contain script tags or javascript - if (preg_match('/ $field]), - self::ERROR_FIELD_REQUIRED - ), 400); - } - } - - // Find page using page ID from data - $pageId = $data['pageId'] ?? null; - - if ($pageId === null) { - return Response::json(self::errorResponse( - tt('moinframe.loop.field.required', ['field' => 'pageId']), - self::ERROR_FIELD_REQUIRED - ), 400); - } - - $page = ($pageId === 'home') ? kirby()->site()->homePage() : page($pageId); - - // If not found, check if it's a draft and validate access - if (null === $page) { - $draftPage = kirby()->page($pageId); - if ($draftPage !== null && $draftPage->isDraft() && ( - (App::getKirbyMajorVersion() >= 5 && $draftPage->renderVersionFromRequest() !== null) || - // @phpstan-ignore method.notFound - (App::getKirbyMajorVersion() < 5 && $draftPage->isVerified(get('token')) === true) - )) { - $page = $draftPage; - } - } - - if (null === $page) { - return Response::json(self::errorResponse( - tt('moinframe.loop.page.path.not.found', ['path' => $pageId]), - self::ERROR_PAGE_NOT_FOUND - ), 404); - } - - $comment = [ - 'author' => ($user = kirby()->user()) !== null ? (string) $user->uuid() : (kirby()->session()->data()->get('loop.guest.name') ?? "guest"), - 'url' => $data['url'], - // @phpstan-ignore method.notFound - 'page' => $page->content()->uuid(), - 'comment' => $data['comment'], - 'selector' => $data['selector'], - 'selectorOffsetX' => $data['selectorOffsetX'], - 'selectorOffsetY' => $data['selectorOffsetY'], - 'pagePositionX' => $data['pagePositionX'], - 'pagePositionY' => $data['pagePositionY'], - 'timestamp' => time(), - 'lang' => $language ?? '', - 'replies' => [] - ]; - - $comment = Comment::fromArray($comment); - $result = App::addComment($comment); - return Response::json([ - 'status' => 'ok', - 'comment' => $result !== null ? $result->toArray() : null - ], 201); - }) - ], - [ - 'pattern' => 'loop/comment/resolve', - 'method' => 'POST', - 'language' => '*', - 'action' => Middleware::auth(function ($language = null) { - - - $data = kirby()->request()->data(); - - $required = ['id']; - - foreach ($required as $field) { - if (!isset($data[$field])) { - return Response::json(self::errorResponse( - tt('moinframe.loop.field.required', ['field' => $field]), - self::ERROR_FIELD_REQUIRED - ), 400); - } - } - - $success = App::resolveComment($data['id']); - - return Response::json([ - 'status' => 'ok', - 'success' => $success - ], 200); - }) - ], - [ - 'pattern' => 'loop/comment/reply', - 'method' => 'POST', - 'language' => '*', - 'action' => Middleware::auth(function ($language = null) { - - - $data = kirby()->request()->data(); - - // Sanitize input data - if (isset($data['comment'])) { - $data['comment'] = htmlspecialchars(strip_tags($data['comment']), ENT_QUOTES, 'UTF-8'); - } - - $required = ['comment', 'parentId']; - - foreach ($required as $field) { - if (!isset($data[$field])) { - return Response::json(self::errorResponse( - tt('moinframe.loop.field.required', ['field' => $field]), - self::ERROR_FIELD_REQUIRED - ), 400); - } - } - - $reply = Reply::fromArray([ - 'author' => ($user = kirby()->user()) !== null ? (string) $user->uuid() : (kirby()->session()->data()->get('loop.guest.name') ?? "guest"), - 'comment' => $data['comment'], - 'parentId' => (int) $data['parentId'], - 'timestamp' => time() - ]); - - $result = App::addReply($reply); - - return Response::json([ - 'status' => 'ok', - 'reply' => $result !== null ? $result->toArray() : null - ], 201); - }) - ], - [ - 'pattern' => 'loop/comment/unresolve', - 'method' => 'POST', - 'language' => '*', - 'action' => Middleware::auth(function ($language = null) { - - - $data = kirby()->request()->data(); - - $required = ['id']; - - foreach ($required as $field) { - if (!isset($data[$field])) { - return Response::json(self::errorResponse( - tt('moinframe.loop.field.required', ['field' => $field]), - self::ERROR_FIELD_REQUIRED - ), 400); - } - } - - $success = App::unresolveComment($data['id']); - - return Response::json([ - 'status' => 'ok', - 'success' => $success - ], 200); - }) - ], - [ - 'pattern' => 'loop/guest/name', - 'method' => 'POST', - 'language' => '*', - 'action' => Middleware::auth(function ($language = null) { - $data = kirby()->request()->data(); - - if (!isset($data['name']) || trim($data['name']) === '') { - return Response::json(self::errorResponse( - 'Name is required', - self::ERROR_INVALID_NAME - ), 400); - } - - $name = trim($data['name']); - kirby()->session()->data()->set('loop.guest.name', $name); - - return Response::json([ - 'status' => 'ok', - 'name' => $name - ], 200); - }) - ] - ]; - } -} diff --git a/site/plugins/send-button/routes/send-newsletter.php b/site/plugins/send-button/routes/send-newsletter.php index af4e508..ef4c4b8 100644 --- a/site/plugins/send-button/routes/send-newsletter.php +++ b/site/plugins/send-button/routes/send-newsletter.php @@ -62,14 +62,6 @@ return [ try { $response = $mailersend->bulkEmail->send($bulkEmailParams); file_put_contents($emailPage->root() . '/mailersend_log.json', json_encode($response, JSON_PRETTY_PRINT)); - - if (!$data->isTest) { - $emailPage->update([ - 'published' => Kirby\Toolkit\Date::today()->format('Y-m-d'), - ]); - $emailPage->changeStatus('listed'); - } - return json_encode([ 'status' => 'success', 'message' => 'All emails sent successfully.', @@ -86,5 +78,12 @@ return [ 'message' => 'Erreur enregistrée dans le log : ' . $e->getMessage(), ]); } + + if (!$data->isTest) { + $emailPage->update([ + 'published' => Kirby\Toolkit\Date::Today(), + ]); + $emailPage->changeStatus('listed'); + } }, ]; diff --git a/site/plugins/toc/index.php b/site/plugins/toc/index.php index 7d022d1..5a6e97d 100644 --- a/site/plugins/toc/index.php +++ b/site/plugins/toc/index.php @@ -1,62 +1,46 @@ (.*?)<\/\1>/'; - -function getContent($page) { - if ($page->intendedTemplate() == 'grid') return $page->body()->toBlocks(); - - if ($page->intendedTemplate() == 'linear') { - if ($page->isBlockMode()->isTrue()) return $page->bodyBlocks()->toBlocks(); - if ($page->isBlockMode()->isFalse()) return $page->body(); - } - - return null; -} - -function getTocContent($page) { - if (!$page->parents()->findBy('uri', 'textes')) return null; - - $content = (string) getContent($page); - - return $content ?: null; -} - Kirby::plugin('actuel-inactuel/toc', [ 'pageMethods' => [ + /** + * Vérifie si la page doit afficher une TOC + */ 'hasToc' => function(): bool { - return count($this->tocItems()) > 0; - }, - - 'tocItems' => function(): array { - $content = getTocContent($this); - if (!$content) return []; - - preg_match_all(HEADING_PATTERN, $content, $matches, PREG_SET_ORDER); - - $items = []; - foreach ($matches as $match) { - $entry = ['title' => $match[3], 'slug' => Str::slug($match[3])]; - - if ($match[1] === 'h3') { - $entry['children'] = []; - $items[] = $entry; - } elseif ($match[1] === 'h4' && count($items) > 0) { - $items[count($items) - 1]['children'][] = $entry; - } + if (!$this->parent()?->parent()?->is('textes')) { + return false; } - - return $items; + if (!$this->bodyBlocks()?->isNotEmpty()) { + return false; + } + return (bool) preg_match('/

/', $this->bodyBlocks()->toBlocks()); }, - 'bodyWithAnchors' => function(): string { - $content = getTocContent($this); - - if (!$content) return ''; + /** + * Retourne les items de la TOC + */ + 'tocItems' => function(): array { + if (!$this->bodyBlocks()?->isNotEmpty()) { + return []; + } + preg_match_all('/

(.*?)<\/h3>/', $this->bodyBlocks()->toBlocks(), $matches); + return array_map(fn($title) => [ + 'title' => $title, + 'slug' => Str::slug($title) + ], $matches[1]); + }, + + /** + * Retourne le contenu avec les ancres ajoutées aux h3 + */ + 'bodyWithAnchors' => function(): string { + if (!$this->bodyBlocks()?->isNotEmpty()) { + return ''; + } return preg_replace_callback( - HEADING_PATTERN, - fn($m) => '<' . $m[1] . ' id="' . Str::slug($m[3]) . '"' . $m[2] . '>' . $m[3] . '', - $content + '/

(.*?)<\/h3>/', + fn($m) => '

' . $m[1] . '

', + $this->bodyBlocks()->toBlocks() ); } ] diff --git a/site/snippets/blocks/image.php b/site/snippets/blocks/image.php index 9c8f225..2099224 100644 --- a/site/snippets/blocks/image.php +++ b/site/snippets/blocks/image.php @@ -14,7 +14,7 @@ if ($block->location() == 'web') { } elseif ($image = $block->image()->toFile()) { $alt = $alt->or($image->alt()); $src = $image->url(); - $srcset = $image->srcset('block-image-webp'); + $srcset = $image->srcset([300, 600, 900, 1200, 1800]); } ?> @@ -22,10 +22,10 @@ if ($block->location() == 'web') { $ratio, 'data-crop' => $crop], null, ' ') ?>> isNotEmpty()): ?> - <?= $alt->esc() ?> srcset="" sizes="(min-width: 768px) 720px, 95vw" loading="lazy"> + <?= $alt->esc() ?> srcset="" sizes="min(60vw, 45rem)" loading="lazy"> - <?= $alt->esc() ?> srcset="" sizes="(min-width: 768px) 720px, 95vw" loading="lazy"> + <?= $alt->esc() ?> srcset="" sizes="min(60vw, 45rem)" loading="lazy"> isNotEmpty()): ?> diff --git a/site/snippets/blocks/quote.php b/site/snippets/blocks/quote.php deleted file mode 100644 index e053b5d..0000000 --- a/site/snippets/blocks/quote.php +++ /dev/null @@ -1,9 +0,0 @@ - -
- text() ?> - citation()->isNotEmpty()): ?> -
- citation() ?> -
- -
\ No newline at end of file diff --git a/site/snippets/cover.php b/site/snippets/cover.php index 01db5c4..fc22ac3 100644 --- a/site/snippets/cover.php +++ b/site/snippets/cover.php @@ -8,6 +8,9 @@ $isOpen ??= false; title() ?> + hasToc()): ?> + + text()): ?>
text() ?> diff --git a/site/snippets/footer.php b/site/snippets/footer.php index a4e8fe0..93ebd30 100644 --- a/site/snippets/footer.php +++ b/site/snippets/footer.php @@ -1,14 +1,15 @@ is(page('lettre')) && !$page->is(page('a-propos'))): ?>