diff --git a/.changeset/silent-coats-sleep.md b/.changeset/silent-coats-sleep.md new file mode 100644 index 0000000..cc1e4e9 --- /dev/null +++ b/.changeset/silent-coats-sleep.md @@ -0,0 +1,5 @@ +--- +'@openassistantgpt/ui': patch +--- + +Dowload pdf instead of txt file for transcript diff --git a/packages/ui/components/chat.tsx b/packages/ui/components/chat.tsx index 9dbc8a8..6d0bf4c 100644 --- a/packages/ui/components/chat.tsx +++ b/packages/ui/components/chat.tsx @@ -4,6 +4,7 @@ import { Icons } from '@/components/icons'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { cn } from '@/lib/utils'; +import { generatePDFTranscript } from '@/lib/pdf-utils'; import { useAssistant, Message } from '@openassistantgpt/react'; import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react'; @@ -153,21 +154,17 @@ export function OpenAssistantGPTChat({ window.parent.postMessage('closeChat', '*'); } - function downloadTranscript() { - const transcript = - `assistant: ${chatbot.welcomeMessage}\n\n` + - messages - .map((msg: Message) => `${msg.role}: ${msg.content}`) - .join('\n\n'); - const blob = new Blob([transcript], { type: 'text/plain' }); - const url = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - a.style.display = 'none'; - a.href = url; - a.download = 'chat_transcript.txt'; - document.body.appendChild(a); - a.click(); - window.URL.revokeObjectURL(url); + async function downloadTranscript() { + try { + await generatePDFTranscript(messages, chatbot); + } catch (error) { + console.error('Error generating PDF:', error); + toast({ + title: 'Error', + description: 'Failed to generate PDF transcript. Please try again.', + variant: 'destructive', + }); + } } // files diff --git a/packages/ui/lib/pdf-utils.tsx b/packages/ui/lib/pdf-utils.tsx new file mode 100644 index 0000000..a8afdbe --- /dev/null +++ b/packages/ui/lib/pdf-utils.tsx @@ -0,0 +1,253 @@ +import React from 'react'; +// @ts-ignore - Type conflicts with React 19 RC +import { + Document, + Page, + Text, + View, + StyleSheet, + pdf, +} from '@react-pdf/renderer'; +import { Message } from '@openassistantgpt/react'; +import { ChatbotConfig } from '../src/chatbot'; + +// Define styles for the PDF with bubble layout +const styles = StyleSheet.create({ + page: { + flexDirection: 'column', + backgroundColor: '#ffffff', + padding: 20, + fontSize: 12, + fontFamily: 'Helvetica', + }, + header: { + fontSize: 20, + fontWeight: 'bold', + textAlign: 'center', + marginBottom: 15, + color: '#2563eb', + }, + subtitle: { + fontSize: 10, + textAlign: 'center', + color: '#6b7280', + marginBottom: 20, + }, + divider: { + borderBottomWidth: 1, + borderBottomColor: '#e5e7eb', + marginBottom: 20, + }, + messageRow: { + flexDirection: 'row', + marginBottom: 15, + width: '100%', + }, + // Assistant messages - left aligned + assistantRow: { + justifyContent: 'flex-start', + }, + assistantBubble: { + backgroundColor: '#f3f4f6', + borderRadius: 15, + borderTopLeftRadius: 5, + padding: 12, + maxWidth: '70%', + borderWidth: 1, + borderColor: '#e5e7eb', + }, + assistantLabel: { + fontSize: 10, + fontWeight: 'bold', + color: '#2563eb', + marginBottom: 4, + }, + assistantText: { + fontSize: 11, + lineHeight: 1.4, + color: '#374151', + }, + // User messages - right aligned + userRow: { + justifyContent: 'flex-end', + }, + userBubble: { + backgroundColor: '#f3f4f6', + borderColor: '#e5e7eb', + borderWidth: 1, + borderRadius: 15, + borderTopRightRadius: 5, + padding: 12, + maxWidth: '70%', + }, + userLabel: { + fontSize: 10, + fontWeight: 'bold', + color: '#2563eb', + marginBottom: 4, + }, + userText: { + fontSize: 11, + lineHeight: 1.4, + color: '#374151', + }, + footer: { + position: 'absolute', + bottom: 20, + left: 0, + right: 0, + textAlign: 'center', + fontSize: 8, + color: '#9ca3af', + }, +}); + +// Clean message content from markdown and special characters +function cleanMessageContent(content: string): string { + return content + .replace(/\*\*(.*?)\*\*/g, '$1') // Remove bold markdown + .replace(/\*(.*?)\*/g, '$1') // Remove italic markdown + .replace(/`(.*?)`/g, '$1') // Remove inline code markdown + .replace(/```[\s\S]*?```/g, '[Code Block]') // Replace code blocks + .replace(/#{1,6}\s*(.*)/g, '$1') // Remove headers + .replace(/\[(.*?)\]\((.*?)\)/g, '$1 ($2)') // Convert links + .replace(/\【.*?】/g, '') // Remove citation markers + .replace(/loading/g, 'Generating response...') + .trim(); +} + +// Function to generate and download PDF +export async function generatePDFTranscript( + messages: Message[], + chatbot: ChatbotConfig, +): Promise { + try { + // @ts-ignore - Working around React 19 RC type conflicts + const PDFDocument = React.createElement( + Document as any, + {}, + // @ts-ignore + React.createElement( + Page as any, + { size: 'A4', style: styles.page }, + // Header + // @ts-ignore + React.createElement( + Text as any, + { style: styles.header }, + 'Chat Transcript', + ), + // @ts-ignore + React.createElement( + Text as any, + { style: styles.subtitle }, + `Generated: ${new Date().toLocaleString()}`, + ), + // @ts-ignore + React.createElement(View as any, { style: styles.divider }), + + // Welcome Message - styled like assistant bubble + ...(chatbot.welcomeMessage + ? [ + // @ts-ignore + React.createElement( + View as any, + { + style: [styles.messageRow, styles.assistantRow], + key: 'welcome', + }, + // @ts-ignore + React.createElement( + View as any, + { style: styles.assistantBubble }, + // @ts-ignore + React.createElement( + Text as any, + { style: styles.assistantLabel }, + 'Assistant:', + ), + // @ts-ignore + React.createElement( + Text as any, + { style: styles.assistantText }, + cleanMessageContent(chatbot.welcomeMessage), + ), + ), + ), + ] + : []), + + // Messages with bubble layout + ...messages.map((message, index) => { + const isUser = message.role === 'user'; + // @ts-ignore + return React.createElement( + View as any, + { + style: [ + styles.messageRow, + isUser ? styles.userRow : styles.assistantRow, + ], + key: index.toString(), + }, + // @ts-ignore + React.createElement( + View as any, + { + style: isUser ? styles.userBubble : styles.assistantBubble, + }, + // @ts-ignore + React.createElement( + Text as any, + { + style: isUser ? styles.userLabel : styles.assistantLabel, + }, + isUser ? 'You:' : 'Assistant:', + ), + // @ts-ignore + React.createElement( + Text as any, + { + style: isUser ? styles.userText : styles.assistantText, + }, + cleanMessageContent(message.content), + ), + ), + ); + }), + + // Footer + // @ts-ignore + React.createElement(Text as any, { + style: styles.footer, + render: ({ pageNumber, totalPages }: any) => + `Page ${pageNumber} of ${totalPages}`, + fixed: true, + }), + ), + ); + + // Generate PDF blob + // @ts-ignore - Final type assertion for React 19 RC compatibility + const blob = await pdf(PDFDocument as any).toBlob(); + + // Create download link + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = `chat-transcript-${ + new Date().toISOString().split('T')[0] + }.pdf`; + + // Trigger download + document.body.appendChild(link); + link.click(); + + // Cleanup + document.body.removeChild(link); + URL.revokeObjectURL(url); + } catch (error) { + console.error('Error generating PDF:', error); + throw new Error('Failed to generate PDF transcript'); + } +} diff --git a/packages/ui/package.json b/packages/ui/package.json index 8b3c687..2c9c6b7 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -35,6 +35,7 @@ "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-toast": "^1.2.1", "@radix-ui/react-tooltip": "^1.1.2", + "@react-pdf/renderer": "^3.1.14", "@tailwindcss/typography": "^0.5.15", "autoprefixer": "^10.4.19", "better-react-mathjax": "^2.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c7b1992..846cc75 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -515,6 +515,9 @@ importers: '@radix-ui/react-tooltip': specifier: ^1.1.2 version: 1.1.2(@types/react-dom@18.2.4)(@types/react@18.2.8)(react-dom@18.2.0)(react@18.2.0) + '@react-pdf/renderer': + specifier: ^3.1.14 + version: 3.4.4(react@18.2.0) '@tailwindcss/typography': specifier: ^0.5.15 version: 0.5.15(tailwindcss@3.4.6) @@ -1180,7 +1183,7 @@ packages: resolution: {integrity: sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==} engines: {node: '>=6.9.0'} dependencies: - regenerator-runtime: 0.14.0 + regenerator-runtime: 0.14.1 /@babel/runtime@7.25.7: resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} @@ -1194,7 +1197,6 @@ packages: engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.1 - dev: true /@babel/template@7.25.7: resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} @@ -3144,6 +3146,190 @@ packages: resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==} dev: false + /@react-pdf/fns@2.2.1: + resolution: {integrity: sha512-s78aDg0vDYaijU5lLOCsUD+qinQbfOvcNeaoX9AiE7+kZzzCo6B/nX+l48cmt9OosJmvZvE9DWR9cLhrhOi2pA==} + dependencies: + '@babel/runtime': 7.26.0 + dev: false + + /@react-pdf/fns@3.1.2: + resolution: {integrity: sha512-qTKGUf0iAMGg2+OsUcp9ffKnKi41RukM/zYIWMDJ4hRVYSr89Q7e3wSDW/Koqx3ea3Uy/z3h2y3wPX6Bdfxk6g==} + dev: false + + /@react-pdf/font@2.5.2: + resolution: {integrity: sha512-Ud0EfZ2FwrbvwAWx8nz+KKLmiqACCH9a/N/xNDOja0e/YgSnqTpuyHegFBgIMKjuBtO5dNvkb4dXkxAhGe/ayw==} + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/types': 2.9.0 + cross-fetch: 3.2.0 + fontkit: 2.0.4 + is-url: 1.2.4 + transitivePeerDependencies: + - encoding + dev: false + + /@react-pdf/font@4.0.2: + resolution: {integrity: sha512-/dAWu7Y2RD1RxarDZ9SkYPHgBYOhmcDnet4W/qN/m8k+A2Hr3ja54GymSR7GGxWBtxjKtNauVKrTa9LS1n8WUw==} + dependencies: + '@react-pdf/pdfkit': 4.0.3 + '@react-pdf/types': 2.9.0 + fontkit: 2.0.4 + is-url: 1.2.4 + dev: false + + /@react-pdf/image@2.3.6: + resolution: {integrity: sha512-7iZDYZrZlJqNzS6huNl2XdMcLFUo68e6mOdzQeJ63d5eApdthhSHBnkGzHfLhH5t8DCpZNtClmklzuLL63ADfw==} + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/png-js': 2.3.1 + cross-fetch: 3.2.0 + jay-peg: 1.1.1 + transitivePeerDependencies: + - encoding + dev: false + + /@react-pdf/layout@3.13.0: + resolution: {integrity: sha512-lpPj/EJYHFOc0ALiJwLP09H28B4ADyvTjxOf67xTF+qkWd+dq1vg7dw3wnYESPnWk5T9NN+HlUenJqdYEY9AvA==} + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/fns': 2.2.1 + '@react-pdf/image': 2.3.6 + '@react-pdf/pdfkit': 3.2.0 + '@react-pdf/primitives': 3.1.1 + '@react-pdf/stylesheet': 4.3.0 + '@react-pdf/textkit': 4.4.1 + '@react-pdf/types': 2.9.0 + cross-fetch: 3.2.0 + emoji-regex: 10.4.0 + queue: 6.0.2 + yoga-layout: 2.0.1 + transitivePeerDependencies: + - encoding + dev: false + + /@react-pdf/pdfkit@3.2.0: + resolution: {integrity: sha512-OBfCcnTC6RpD9uv9L2woF60Zj1uQxhLFzTBXTdcYE9URzPE/zqXIyzpXEA4Vf3TFbvBCgFE2RzJ2ZUS0asq7yA==} + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/png-js': 2.3.1 + browserify-zlib: 0.2.0 + crypto-js: 4.2.0 + fontkit: 2.0.4 + jay-peg: 1.1.1 + vite-compatible-readable-stream: 3.6.1 + dev: false + + /@react-pdf/pdfkit@4.0.3: + resolution: {integrity: sha512-k+Lsuq8vTwWsCqTp+CCB4+2N+sOTFrzwGA7aw3H9ix/PDWR9QksbmNg0YkzGbLAPI6CeawmiLHcf4trZ5ecLPQ==} + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/png-js': 3.0.0 + browserify-zlib: 0.2.0 + crypto-js: 4.2.0 + fontkit: 2.0.4 + jay-peg: 1.1.1 + linebreak: 1.1.0 + vite-compatible-readable-stream: 3.6.1 + dev: false + + /@react-pdf/png-js@2.3.1: + resolution: {integrity: sha512-pEZ18I4t1vAUS4lmhvXPmXYP4PHeblpWP/pAlMMRkEyP7tdAeHUN7taQl9sf9OPq7YITMY3lWpYpJU6t4CZgZg==} + dependencies: + browserify-zlib: 0.2.0 + dev: false + + /@react-pdf/png-js@3.0.0: + resolution: {integrity: sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA==} + dependencies: + browserify-zlib: 0.2.0 + dev: false + + /@react-pdf/primitives@3.1.1: + resolution: {integrity: sha512-miwjxLwTnO3IjoqkTVeTI+9CdyDggwekmSLhVCw+a/7FoQc+gF3J2dSKwsHvAcVFM0gvU8mzCeTofgw0zPDq0w==} + dev: false + + /@react-pdf/primitives@4.1.1: + resolution: {integrity: sha512-IuhxYls1luJb7NUWy6q5avb1XrNaVj9bTNI40U9qGRuS6n7Hje/8H8Qi99Z9UKFV74bBP3DOf3L1wV2qZVgVrQ==} + dev: false + + /@react-pdf/render@3.5.0: + resolution: {integrity: sha512-gFOpnyqCgJ6l7VzfJz6rG1i2S7iVSD8bUHDjPW9Mze8TmyksHzN2zBH3y7NbsQOw1wU6hN4NhRmslrsn+BRDPA==} + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/fns': 2.2.1 + '@react-pdf/primitives': 3.1.1 + '@react-pdf/textkit': 4.4.1 + '@react-pdf/types': 2.9.0 + abs-svg-path: 0.1.1 + color-string: 1.9.1 + normalize-svg-path: 1.1.0 + parse-svg-path: 0.1.2 + svg-arc-to-cubic-bezier: 3.2.0 + dev: false + + /@react-pdf/renderer@3.4.4(react@18.2.0): + resolution: {integrity: sha512-j1TWMHHXDeHdoQE3xjhBh0MZ2rn7wHIlP/uglr/EJZXqnPbfg6bfLzRJCM6bs+XJV3d8+zLQjHf6sF/fWcBDfg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/font': 2.5.2 + '@react-pdf/layout': 3.13.0 + '@react-pdf/pdfkit': 3.2.0 + '@react-pdf/primitives': 3.1.1 + '@react-pdf/render': 3.5.0 + '@react-pdf/types': 2.9.0 + events: 3.3.0 + object-assign: 4.1.1 + prop-types: 15.8.1 + queue: 6.0.2 + react: 18.2.0 + scheduler: 0.17.0 + transitivePeerDependencies: + - encoding + dev: false + + /@react-pdf/stylesheet@4.3.0: + resolution: {integrity: sha512-x7IVZOqRrUum9quuDeFXBveXwBht+z/6B0M+z4a4XjfSg1vZVvzoTl07Oa1yvQ/4yIC5yIkG2TSMWeKnDB+hrw==} + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/fns': 2.2.1 + '@react-pdf/types': 2.9.0 + color-string: 1.9.1 + hsl-to-hex: 1.0.0 + media-engine: 1.0.3 + postcss-value-parser: 4.2.0 + dev: false + + /@react-pdf/stylesheet@6.1.0: + resolution: {integrity: sha512-BGZ2sYNUp38VJUegjva/jsri3iiRGnVNjWI+G9dTwAvLNOmwFvSJzqaCsEnqQ/DW5mrTBk/577FhDY7pv6AidA==} + dependencies: + '@react-pdf/fns': 3.1.2 + '@react-pdf/types': 2.9.0 + color-string: 1.9.1 + hsl-to-hex: 1.0.0 + media-engine: 1.0.3 + postcss-value-parser: 4.2.0 + dev: false + + /@react-pdf/textkit@4.4.1: + resolution: {integrity: sha512-Jl9wdTqIvJ5pX+vAGz0EOhP7ut5Two9H6CzTKo/YYPeD79cM2yTXF3JzTERBC28y7LR0Waq9D2LHQjI+b/EYUQ==} + dependencies: + '@babel/runtime': 7.26.0 + '@react-pdf/fns': 2.2.1 + bidi-js: 1.0.3 + hyphen: 1.10.6 + unicode-properties: 1.4.1 + dev: false + + /@react-pdf/types@2.9.0: + resolution: {integrity: sha512-ckj80vZLlvl9oYrQ4tovEaqKWP3O06Eb1D48/jQWbdwz1Yh7Y9v1cEmwlP8ET+a1Whp8xfdM0xduMexkuPANCQ==} + dependencies: + '@react-pdf/font': 4.0.2 + '@react-pdf/primitives': 4.1.1 + '@react-pdf/stylesheet': 6.1.0 + dev: false + /@rollup/rollup-android-arm-eabi@4.24.4: resolution: {integrity: sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==} cpu: [arm] @@ -3283,6 +3469,12 @@ packages: /@swc/counter@0.1.3: resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + /@swc/helpers@0.5.17: + resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} + dependencies: + tslib: 2.8.0 + dev: false + /@swc/helpers@0.5.5: resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} dependencies: @@ -3872,6 +4064,10 @@ packages: event-target-shim: 5.0.1 dev: false + /abs-svg-path@0.1.1: + resolution: {integrity: sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==} + dev: false + /acorn-jsx@5.3.2(acorn@7.4.1): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -4432,6 +4628,11 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /base64-js@0.0.8: + resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==} + engines: {node: '>= 0.4'} + dev: false + /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: false @@ -4452,6 +4653,12 @@ packages: react: 18.2.0 dev: false + /bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + dependencies: + require-from-string: 2.0.2 + dev: false + /binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -4473,6 +4680,18 @@ packages: dependencies: fill-range: 7.1.1 + /brotli@1.3.3: + resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==} + dependencies: + base64-js: 1.5.1 + dev: false + + /browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + dependencies: + pako: 1.0.11 + dev: false + /browserslist@4.23.2: resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -4700,6 +4919,11 @@ packages: wrap-ansi: 7.0.0 dev: true + /clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + dev: false + /clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} @@ -4730,6 +4954,13 @@ packages: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} requiresBuild: true + /color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false + /colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} dev: true @@ -4817,6 +5048,14 @@ packages: object-assign: 4.1.1 dev: false + /cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} dependencies: @@ -4833,6 +5072,10 @@ packages: shebang-command: 2.0.0 which: 2.0.2 + /crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + dev: false + /css-animation@1.6.1: resolution: {integrity: sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==} dependencies: @@ -5004,6 +5247,10 @@ packages: dequal: 2.0.3 dev: false + /dfa@1.2.0: + resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==} + dev: false + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -5123,7 +5370,6 @@ packages: /emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} - dev: true /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -6066,6 +6312,11 @@ packages: resolution: {integrity: sha512-hXZ5N9hmp3n7ovmVgG+2vIO6KcjSU10/d0A1Ixcf0i29dxCwAGTNGrSJCfLmlvmgQD8FYzyp//S8+Hpq4Nd7uA==} dev: false + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + /eventsource-parser@1.1.2: resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==} engines: {node: '>=14.18'} @@ -6202,6 +6453,20 @@ packages: /flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + /fontkit@2.0.4: + resolution: {integrity: sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==} + dependencies: + '@swc/helpers': 0.5.17 + brotli: 1.3.3 + clone: 2.1.2 + dfa: 1.2.0 + fast-deep-equal: 3.1.3 + restructure: 3.0.2 + tiny-inflate: 1.0.3 + unicode-properties: 1.4.1 + unicode-trie: 2.0.0 + dev: false + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: @@ -6570,6 +6835,16 @@ packages: react-is: 16.13.1 dev: false + /hsl-to-hex@1.0.0: + resolution: {integrity: sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==} + dependencies: + hsl-to-rgb-for-reals: 1.1.1 + dev: false + + /hsl-to-rgb-for-reals@1.1.1: + resolution: {integrity: sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==} + dev: false + /html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -6627,6 +6902,10 @@ packages: hasBin: true dev: true + /hyphen@1.10.6: + resolution: {integrity: sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw==} + dev: false + /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -6745,6 +7024,10 @@ packages: call-bind: 1.0.7 get-intrinsic: 1.2.4 + /is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: false + /is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -6952,6 +7235,10 @@ packages: dependencies: which-typed-array: 1.1.15 + /is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + dev: false + /is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -7011,6 +7298,12 @@ packages: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + /jay-peg@1.1.1: + resolution: {integrity: sha512-D62KEuBxz/ip2gQKOEhk/mx14o7eiFRaU+VNNSP4MOiIkwb/D6B3G1Mfas7C/Fit8EsSV2/IWjZElx/Gs6A4ww==} + dependencies: + restructure: 3.0.2 + dev: false + /jiti@1.21.6: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true @@ -7215,6 +7508,13 @@ packages: resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} + /linebreak@1.1.0: + resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==} + dependencies: + base64-js: 0.0.8 + unicode-trie: 2.0.0 + dev: false + /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -7599,6 +7899,10 @@ packages: '@types/mdast': 4.0.4 dev: false + /media-engine@1.0.3: + resolution: {integrity: sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==} + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -8209,6 +8513,12 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} + /normalize-svg-path@1.1.0: + resolution: {integrity: sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==} + dependencies: + svg-arc-to-cubic-bezier: 3.2.0 + dev: false + /npm-bundled@2.0.1: resolution: {integrity: sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -8468,6 +8778,14 @@ packages: resolution: {integrity: sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==} dev: true + /pako@0.2.9: + resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} + dev: false + + /pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + dev: false + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -8498,6 +8816,10 @@ packages: is-hexadecimal: 2.0.1 dev: false + /parse-svg-path@0.1.2: + resolution: {integrity: sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==} + dev: false + /parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} dependencies: @@ -8814,6 +9136,12 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + /queue@6.0.2: + resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} + dependencies: + inherits: 2.0.4 + dev: false + /raf@3.4.1: resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} dependencies: @@ -9587,12 +9915,8 @@ packages: resolution: {integrity: sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==} dev: false - /regenerator-runtime@0.14.0: - resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} - /regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true /regexp.prototype.flags@1.5.2: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} @@ -9669,7 +9993,6 @@ packages: /require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - dev: true /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} @@ -9715,6 +10038,10 @@ packages: signal-exit: 4.1.0 dev: true + /restructure@3.0.2: + resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==} + dev: false + /retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -9806,6 +10133,10 @@ packages: has-symbols: 1.0.3 isarray: 2.0.5 + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + /safe-regex-test@1.0.3: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} @@ -9824,6 +10155,13 @@ packages: xmlchars: 2.2.0 dev: true + /scheduler@0.17.0: + resolution: {integrity: sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + dev: false + /scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: @@ -9931,6 +10269,12 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + /simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + dependencies: + is-arrayish: 0.3.2 + dev: false + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -10129,6 +10473,12 @@ packages: define-properties: 1.2.1 es-object-atoms: 1.0.0 + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} dependencies: @@ -10272,6 +10622,10 @@ packages: zimmerframe: 1.1.2 dev: false + /svg-arc-to-cubic-bezier@3.2.0: + resolution: {integrity: sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==} + dev: false + /swr@2.2.5(react@18.2.0): resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==} peerDependencies: @@ -10420,6 +10774,10 @@ packages: dependencies: any-promise: 1.3.0 + /tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + dev: false + /tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} dev: true @@ -10732,6 +11090,20 @@ packages: '@fastify/busboy': 2.1.1 dev: false + /unicode-properties@1.4.1: + resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} + dependencies: + base64-js: 1.5.1 + unicode-trie: 2.0.0 + dev: false + + /unicode-trie@2.0.0: + resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} + dependencies: + pako: 0.2.9 + tiny-inflate: 1.0.3 + dev: false + /unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} dependencies: @@ -10938,6 +11310,15 @@ packages: vfile-message: 4.0.2 dev: false + /vite-compatible-readable-stream@3.6.1: + resolution: {integrity: sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + /vite-node@1.6.0: resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} engines: {node: ^18.0.0 || >=20.0.0} @@ -11365,6 +11746,10 @@ packages: engines: {node: '>=18'} dev: true + /yoga-layout@2.0.1: + resolution: {integrity: sha512-tT/oChyDXelLo2A+UVnlW9GU7CsvFMaEnd9kVFsaiCQonFAXd3xrHhkLYu+suwwosrAEQ746xBU+HvYtm1Zs2Q==} + dev: false + /zfd-color@0.0.1: resolution: {integrity: sha512-TgktxTHoNoo/50MWY5w2D0wMODYbzWxD8iGnvJCBGv3pq94GGD/wrT49Uy4oRz1FR0u+UOtx/6sjK8obtvWCeg==} dev: false