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 deleted file mode 100644 index 7d022d1..0000000 --- a/site/plugins/toc/index.php +++ /dev/null @@ -1,63 +0,0 @@ -(.*?)<\/\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' => [ - '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; - } - } - - return $items; - }, - - 'bodyWithAnchors' => function(): string { - $content = getTocContent($this); - - if (!$content) return ''; - - return preg_replace_callback( - HEADING_PATTERN, - fn($m) => '<' . $m[1] . ' id="' . Str::slug($m[3]) . '"' . $m[2] . '>' . $m[3] . '', - $content - ); - } - ] -]); diff --git a/site/plugins/web2print/.editorconfig b/site/plugins/web2print/.editorconfig deleted file mode 100644 index 3b762c9..0000000 --- a/site/plugins/web2print/.editorconfig +++ /dev/null @@ -1,20 +0,0 @@ -# This file is for unifying the coding style for different editors and IDEs -# editorconfig.org - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -[*.php] -indent_size = 4 - -[*.md,*.txt] -trim_trailing_whitespace = false -insert_final_newline = false - -[composer.json] -indent_size = 4 diff --git a/site/plugins/web2print/.gitattributes b/site/plugins/web2print/.gitattributes deleted file mode 100644 index 033ba13..0000000 --- a/site/plugins/web2print/.gitattributes +++ /dev/null @@ -1,11 +0,0 @@ -# Note: You need to uncomment the lines you want to use; the other lines can be deleted - -# Git -# .gitattributes export-ignore -# .gitignore export-ignore - -# Tests -# /.coveralls.yml export-ignore -# /.travis.yml export-ignore -# /phpunit.xml.dist export-ignore -# /tests/ export-ignore diff --git a/site/plugins/web2print/.gitignore b/site/plugins/web2print/.gitignore deleted file mode 100644 index 4d81cf5..0000000 --- a/site/plugins/web2print/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# OS files -.DS_Store - -# npm modules -/node_modules - -# Parcel cache folder -.cache - -# Composer files -/vendor - -# kirbyup temp development entry -/index.dev.mjs diff --git a/site/plugins/web2print/LICENSE.md b/site/plugins/web2print/LICENSE.md deleted file mode 100644 index 8e663d7..0000000 --- a/site/plugins/web2print/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/site/plugins/web2print/README.md b/site/plugins/web2print/README.md deleted file mode 100644 index ad2b202..0000000 --- a/site/plugins/web2print/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# Kirby Pluginkit: Example plugin for Kirby - -> Variant "Panel plugin setup" - -This is a boilerplate for a Kirby Panel plugin that can be installed via all three [supported installation methods](https://getkirby.com/docs/guide/plugins/plugin-setup-basic#the-three-plugin-installation-methods). - -You can find a list of Pluginkit variants on the [`master` branch](https://github.com/getkirby/pluginkit/tree/master). - -**** - -## How to use the Pluginkit - -1. Fork this repository -2. Change the plugin name and description in the `composer.json` -3. Change the plugin name in the `index.php` and `src/index.js` -4. Change the license if you don't want to publish under MIT -5. Add your plugin code to the `index.php` and `src/index.js` -6. Update this `README` with instructions for your plugin - -### Install the development and build setup - -We use [kirbyup](https://github.com/johannschopplich/kirbyup) for the development and build setup. - -You can start developing directly. kirbyup will be fetched remotely with your first `npm run` command, which may take a short amount of time. - -### Development - -You can start the dev process with: - -```bash -npm run dev -``` - -This will automatically update the `index.js` and `index.css` of your plugin as soon as you make changes. -Reload the Panel to see your code changes reflected. - -With kirbyup 2.0.0+ and Kirby 3.7.4+ you can alternatively use hot module reloading (HMR): - -```bash -npm run serve -``` - -This will start a development server that updates the page as soon as you make changes. Some updates are instant, like CSS or Vue template changes, others require a reload of the page, which happens automatically. - -> [!NOTE] -> The live reload functionality requires top level await, [which is only supported in modern browsers](https://caniuse.com/mdn-javascript_operators_await_top_level). If you're developing in older browsers, use `npm run dev` and reload the page manually to see changes. - -### Production - -As soon as you are happy with your plugin, you should build the final version with: - -```bash -npm run build -``` - -This will automatically create a minified and optimized version of your `index.js` and `index.css` -which you can ship with your plugin. - -We have a tutorial on how to build your own plugin based on the Pluginkit [in the Kirby documentation](https://getkirby.com/docs/guide/plugins/plugin-setup-basic). - -### Build reproducibility - -While kirbyup will stay backwards compatible, exact build reproducibility may be of importance to you. If so, we recommend to target a specific package version, rather than using npx: - -```json -{ - "scripts": { - "dev": "kirbyup src/index.js --watch", - "build": "kirbyup src/index.js" - }, - "devDependencies": { - "kirbyup": "^3.1.0" - } -} -``` - -What follows is an example README for your plugin. - -**** - -## Installation - -### Download - -Download and copy this repository to `/site/plugins/{{ plugin-name }}`. - -### Git submodule - -```bash -git submodule add https://github.com/{{ your-name }}/{{ plugin-name }}.git site/plugins/{{ plugin-name }} -``` - -### Composer - -```bash -composer require {{ your-name }}/{{ plugin-name }} -``` - -## Setup - -*Additional instructions on how to configure the plugin (e.g. blueprint setup, config options, etc.)* - -## Options - -*Document the options and APIs that this plugin offers* - -## Development - -*Add instructions on how to help working on the plugin (e.g. npm setup, Composer dev dependencies, etc.)* - -## License - -MIT - -## Credits - -- [Your Name](https://github.com/ghost) diff --git a/site/plugins/web2print/SECURITY.md b/site/plugins/web2print/SECURITY.md deleted file mode 100644 index 3726336..0000000 --- a/site/plugins/web2print/SECURITY.md +++ /dev/null @@ -1,18 +0,0 @@ -# Security Policy - -## Supported Versions - -*Use this section to tell people about which versions of your project are currently being supported with security updates.* - -| Version | Supported | -| ------- | ------------------ | -| 5.1.x | :white_check_mark: | -| 5.0.x | :x: | -| 4.0.x | :white_check_mark: | -| < 4.0 | :x: | - -## Reporting a Vulnerability - -*Use this section to tell people how to report a vulnerability.* - -*Tell them where to go, how often they can expect to get an update on a reported vulnerability, what to expect if the vulnerability is accepted or declined, etc.* diff --git a/site/plugins/web2print/composer.json b/site/plugins/web2print/composer.json deleted file mode 100644 index fa07b14..0000000 --- a/site/plugins/web2print/composer.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "getkirby/pluginkit", - "description": "Kirby Example Plugin", - "license": "MIT", - "type": "kirby-plugin", - "version": "1.0.0", - "authors": [ - { - "name": "Your Name", - "email": "you@example.com" - } - ], - "require": { - "getkirby/composer-installer": "^1.1" - }, - "config": { - "allow-plugins": { - "getkirby/composer-installer": true - } - } -} diff --git a/site/plugins/web2print/composer.lock b/site/plugins/web2print/composer.lock deleted file mode 100644 index a5ae0fa..0000000 --- a/site/plugins/web2print/composer.lock +++ /dev/null @@ -1,66 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "37a8e61308b9b6f49cb9835f477f0c64", - "packages": [ - { - "name": "getkirby/composer-installer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/getkirby/composer-installer.git", - "reference": "c98ece30bfba45be7ce457e1102d1b169d922f3d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/getkirby/composer-installer/zipball/c98ece30bfba45be7ce457e1102d1b169d922f3d", - "reference": "c98ece30bfba45be7ce457e1102d1b169d922f3d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0" - }, - "require-dev": { - "composer/composer": "^1.8 || ^2.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Kirby\\ComposerInstaller\\Plugin" - }, - "autoload": { - "psr-4": { - "Kirby\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Kirby's custom Composer installer for the Kirby CMS and for Kirby plugins", - "homepage": "https://getkirby.com", - "support": { - "issues": "https://github.com/getkirby/composer-installer/issues", - "source": "https://github.com/getkirby/composer-installer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://getkirby.com/buy", - "type": "custom" - } - ], - "time": "2020-12-28T12:54:39+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.6.0" -} diff --git a/site/plugins/web2print/index.css b/site/plugins/web2print/index.css deleted file mode 100644 index e69de29..0000000 diff --git a/site/plugins/web2print/index.js b/site/plugins/web2print/index.js deleted file mode 100644 index 351c544..0000000 --- a/site/plugins/web2print/index.js +++ /dev/null @@ -1 +0,0 @@ -(function(){"use strict";function f(t,n,e,i,r,s,g,a){var o=typeof t=="function"?t.options:t;return n&&(o.render=n,o.staticRenderFns=e,o._compiled=!0),{exports:t,options:o}}const l={__name:"Web2PrintBtn",props:{htmlPageString:String,cssPath:String,printFormat:String,pageId:String},setup(t){const{htmlPageString:n,cssPath:e,printFormat:i,pageId:r}=t;async function s(){const a={method:"POST",body:JSON.stringify({html:n,cssPath:e,printFormat:i,pageId:r})},c=await(await fetch("/web2print.json",a)).json();console.log(c),c.success&&window.panel.view.reload()}return{__sfc:!0,getPdf:s}}};var u=function(){var n=this,e=n._self._c,i=n._self._setupProxy;return e("k-button",{attrs:{variant:"filled"},on:{click:function(r){return i.getPdf()}}},[n._v("Générer")])},_=[],d=f(l,u,_);const p=d.exports;window.panel.plugin("studio-variable/web2print",{fields:{web2print:p}})})(); diff --git a/site/plugins/web2print/index.php b/site/plugins/web2print/index.php deleted file mode 100644 index dc19457..0000000 --- a/site/plugins/web2print/index.php +++ /dev/null @@ -1,33 +0,0 @@ - [ - 'web2print' => [ - 'props' => [ - 'cssPath' => function($cssPath = null) { - return $cssPath; - } - ], - 'computed' => [ - 'htmlPageString' => function() { - return $this->model()->render(); - }, - 'cssPath' => function() { - return $this->cssPath ?? 'assets/css/style.css'; - }, - 'printFormat' => function() { - return $this->model()->printFormat()->value() ?? 'A4'; - }, - 'pageId' => function() { - return $this->model()->id(); - } - ] - ] - ], - 'routes' => [ - require __DIR__ . '/src/routes/web2print.php', - ], - 'blueprints' => [ - 'tabs/web2print' => __DIR__ . '/src/blueprints/tabs/web2print.yml' - ] -]); diff --git a/site/plugins/web2print/package.json b/site/plugins/web2print/package.json deleted file mode 100644 index 1913c34..0000000 --- a/site/plugins/web2print/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "getkirby/pluginkit", - "description": "Kirby Example Plugin", - "license": "MIT", - "type": "kirby-plugin", - "version": "1.0.0", - "scripts": { - "dev": "npx -y kirbyup src/index.js --watch", - "serve": "npx -y kirbyup serve src/index.js", - "build": "npx -y kirbyup src/index.js" - } -} diff --git a/site/plugins/web2print/src/blueprints/tabs/web2print.yml b/site/plugins/web2print/src/blueprints/tabs/web2print.yml deleted file mode 100644 index 09ac537..0000000 --- a/site/plugins/web2print/src/blueprints/tabs/web2print.yml +++ /dev/null @@ -1,20 +0,0 @@ -label: web2print -icon: print -sections: - web2printSection: - type: fields - fields: - printFormat: - label: Format - type: select - options: - - A4 - - A5 - width: 1/4 - generatePdfBtn: - type: web2print - width: 1/4 - generatedPdfs: - label: PDF générés - type: files - width: 1/4 diff --git a/site/plugins/web2print/src/components/Web2PrintBtn.vue b/site/plugins/web2print/src/components/Web2PrintBtn.vue deleted file mode 100644 index 51f331c..0000000 --- a/site/plugins/web2print/src/components/Web2PrintBtn.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - diff --git a/site/plugins/web2print/src/index.js b/site/plugins/web2print/src/index.js deleted file mode 100644 index 9990c88..0000000 --- a/site/plugins/web2print/src/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import Web2PrintBtn from "./components/Web2PrintBtn.vue"; - -window.panel.plugin("studio-variable/web2print", { - fields: { - web2print: Web2PrintBtn, - }, -}); diff --git a/site/plugins/web2print/src/routes/web2print.php b/site/plugins/web2print/src/routes/web2print.php deleted file mode 100644 index 088d7a9..0000000 --- a/site/plugins/web2print/src/routes/web2print.php +++ /dev/null @@ -1,189 +0,0 @@ - '/web2print.json', - 'method' => 'POST', - 'action' => function () { - header('Content-Type: application/json'); - - $jsonRequest = file_get_contents('php://input'); - $body = json_decode($jsonRequest); - - if (!$body || !isset($body->html)) { - http_response_code(400); - return json_encode(['error' => 'Missing html parameter']); - } - - if (!isset($body->pageId) || empty($body->pageId)) { - http_response_code(400); - return json_encode(['error' => 'Missing pageId parameter']); - } - - // Récupérer le cssPath depuis le body ou utiliser la valeur par défaut - $cssPath = isset($body->cssPath) && !empty($body->cssPath) - ? $body->cssPath - : 'assets/css/style.css'; - - // Récupérer le format d'impression - $printFormat = isset($body->printFormat) && !empty($body->printFormat) - ? $body->printFormat - : 'A4'; - - // Récupérer la page Kirby - $page = kirby()->page($body->pageId); - if (!$page) { - http_response_code(404); - return json_encode(['error' => 'Page not found']); - } - - $ch = curl_init('https://web2print.studio-variable.com/generate'); - - $html = $body->html; - - // Nettoyer le HTML pour la génération PDF - $dom = new DOMDocument(); - @$dom->loadHTML('' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); - - // Supprimer tous les scripts - $scripts = $dom->getElementsByTagName('script'); - while ($scripts->length > 0) { - $scripts->item(0)->parentNode->removeChild($scripts->item(0)); - } - - // Supprimer les attributs Alpine.js (x-data, x-show, @click, etc.) - $xpath = new DOMXPath($dom); - $elements = $xpath->query('//*[@*[starts-with(name(), "x-") or starts-with(name(), "@") or starts-with(name(), ":")]]'); - foreach ($elements as $element) { - $attributesToRemove = []; - foreach ($element->attributes as $attr) { - if (strpos($attr->name, 'x-') === 0 || strpos($attr->name, '@') === 0 || strpos($attr->name, ':') === 0) { - $attributesToRemove[] = $attr->name; - } - } - foreach ($attributesToRemove as $attrName) { - $element->removeAttribute($attrName); - } - } - - // Supprimer les liens CSS et les remplacer par un style inline - $head = $dom->getElementsByTagName('head')->item(0); - if ($head) { - // Supprimer tous les - $links = $dom->getElementsByTagName('link'); - $linksToRemove = []; - foreach ($links as $link) { - if ($link->getAttribute('rel') === 'stylesheet') { - $linksToRemove[] = $link; - } - } - foreach ($linksToRemove as $link) { - $link->parentNode->removeChild($link); - } - - - - // Charger et résoudre le CSS - $fullCssPath = kirby()->root() . '/' . $cssPath; - $resolvedCss = resolveCssImports($fullCssPath); - - // Ajouter les règles @page pour le format d'impression - $pageRules = "\n\n@page {\n size: " . $printFormat . ";\n}\n"; - $resolvedCss .= $pageRules; - - // Créer une balise @@ -81,21 +84,19 @@ $entryTopPos ??= 20; -
- - \ No newline at end of file + \ No newline at end of file diff --git a/site/snippets/nav.php b/site/snippets/nav.php new file mode 100644 index 0000000..3c4cbee --- /dev/null +++ b/site/snippets/nav.php @@ -0,0 +1,23 @@ + + \ No newline at end of file diff --git a/site/snippets/nav__texts--all.php b/site/snippets/nav__texts--all.php index ff5c07f..8ee0245 100644 --- a/site/snippets/nav__texts--all.php +++ b/site/snippets/nav__texts--all.php @@ -1,4 +1,4 @@ -