diff --git a/.gitignore b/.gitignore index 5724507c..b3cad116 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,11 @@ public/sitemap.xml # Scraped documentation for LLM training scraped-docs/ /public/_scraped-docs +/public/llms.txt +/public/llms-full.txt + +# Per-page .md files generated at build time (Solana-style LLM access) +/public/**/*.md public/_seo-audit.json src/vendor/bytebellai/index.js src/vendor/bytebellai/style.css diff --git a/app/api/llm-md/[...path]/route.js b/app/api/llm-md/[...path]/route.js new file mode 100644 index 00000000..343b0ca1 --- /dev/null +++ b/app/api/llm-md/[...path]/route.js @@ -0,0 +1,112 @@ +import { NextResponse } from 'next/server'; +import fs from 'fs/promises'; +import path from 'path'; + +export async function GET(request, { params }) { + const { path: segments } = await params; + const docPath = segments.join('/'); + + const contentDir = path.join(process.cwd(), 'content'); + const candidates = [ + path.join(contentDir, `${docPath}.mdx`), + path.join(contentDir, `${docPath}.md`), + path.join(contentDir, docPath, 'index.mdx'), + path.join(contentDir, docPath, 'index.md') + ]; + + let raw = null; + for (const filePath of candidates) { + try { + raw = await fs.readFile(filePath, 'utf8'); + break; + } catch { + continue; + } + } + + if (!raw) { + return NextResponse.json({ error: 'Page not found' }, { status: 404 }); + } + + const markdown = mdxToMarkdown(raw, `https://docs.sei.io/${docPath}`); + + return new NextResponse(markdown, { + headers: { + 'Content-Type': 'text/markdown; charset=utf-8', + 'X-Robots-Tag': 'noindex' + } + }); +} + +function mdxToMarkdown(source, url) { + let result = source; + + // Extract and preserve frontmatter + let frontmatter = ''; + const fmMatch = result.match(/^---\n([\s\S]*?)\n---/); + if (fmMatch) { + frontmatter = fmMatch[1]; + result = result.slice(fmMatch[0].length); + } + + // Strip import statements + result = result.replace(/^import\s+.*$/gm, ''); + + // Strip JSX component wrappers like and but keep inner text + result = result.replace(/<(Callout|Steps|Cards|Card|Tabs|Tab|FileTree)(\s[^>]*)?\/?>/gi, ''); + result = result.replace(/<\/(Callout|Steps|Cards|Card|Tabs|Tab|FileTree)>/gi, ''); + + // Convert HTML tables to markdown tables + result = convertHtmlTablesToMarkdown(result); + + // Strip remaining HTML/JSX wrapper tags (div, span, section) but keep content + result = result.replace(/<\/?(div|span|section|article|thead|tbody|main)(\s[^>]*)?>/gi, ''); + + // Clean up excessive blank lines + result = result.replace(/\n{4,}/g, '\n\n\n'); + result = result.trim(); + + // Rebuild with frontmatter including the URL + let md = '---\n'; + if (frontmatter) md += frontmatter + '\n'; + md += `url: ${url}\n`; + md += '---\n\n'; + md += result; + + return md; +} + +function convertHtmlTablesToMarkdown(text) { + return text.replace(/]*>([\s\S]*?)<\/table>/gi, (_, tableContent) => { + const rows = []; + const rowMatches = tableContent.matchAll(/]*>([\s\S]*?)<\/tr>/gi); + + for (const rowMatch of rowMatches) { + const cells = []; + const cellMatches = rowMatch[1].matchAll(/<(th|td)[^>]*>([\s\S]*?)<\/\1>/gi); + for (const cellMatch of cellMatches) { + const cellText = cellMatch[2] + .replace(/<[^>]*>/g, '') + .replace(/\s+/g, ' ') + .trim(); + cells.push(cellText); + } + if (cells.length > 0) rows.push(cells); + } + + if (rows.length === 0) return ''; + + let md = ''; + const colCount = Math.max(...rows.map((r) => r.length)); + + rows.forEach((row, i) => { + const padded = Array.from({ length: colCount }, (_, j) => row[j] || ''); + md += '| ' + padded.join(' | ') + ' |\n'; + if (i === 0) { + md += '| ' + padded.map(() => '---').join(' | ') + ' |\n'; + } + }); + + return '\n' + md; + }); +} diff --git a/next.config.mjs b/next.config.mjs index bee3861b..6799f723 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -78,6 +78,15 @@ export default withNextra({ { key: 'Vercel-CDN-Cache-Control', value: 'public, max-age=3600, immutable' } ] }, + { + source: '/(.*)\\.(md|txt)', + headers: [ + { key: 'Content-Type', value: 'text/markdown; charset=utf-8' }, + { key: 'Cache-Control', value: 'public, max-age=3600, s-maxage=86400, stale-while-revalidate=604800' }, + { key: 'Vercel-CDN-Cache-Control', value: 'public, max-age=3600, s-maxage=86400, stale-while-revalidate=604800' }, + { key: 'X-Robots-Tag', value: 'noindex' } + ] + }, { source: '/(.*)', headers: [ diff --git a/package.json b/package.json index 77de5896..108dfc2f 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,6 @@ "devDependencies": { "@playwright/test": "^1.56.1", "@react-native-async-storage/async-storage": "^2.1.2", - "@sparticuz/chromium": "^141.0.0", - "@sparticuz/chromium-min": "^141.0.0", "@types/node": "18.11.10", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", @@ -66,8 +64,6 @@ "postcss": "^8.5.6", "postcss-simple-vars": "^7.0.1", "prettier": "^3.5.3", - "puppeteer": "^24.31.0", - "puppeteer-core": "^24.31.0", "tailwindcss": "^4.1.18", "terser": "^5.31.0", "tsx": "^4.19.3", diff --git a/proxy.ts b/proxy.ts new file mode 100644 index 00000000..f3e9f3b7 --- /dev/null +++ b/proxy.ts @@ -0,0 +1,19 @@ +import { NextResponse } from 'next/server'; +import type { NextRequest } from 'next/server'; + +export function proxy(request: NextRequest) { + const { pathname } = request.nextUrl; + + if (pathname.endsWith('.md')) { + const cleanPath = pathname.slice(0, -3); + const url = request.nextUrl.clone(); + url.pathname = `/api/llm-md${cleanPath}`; + return NextResponse.rewrite(url); + } + + return NextResponse.next(); +} + +export const config = { + matcher: ['/((?!api|_next|_pagefind|_scraped-docs|assets|favicon).+\\.md)'] +}; diff --git a/scripts/scrape-docs-direct.js b/scripts/scrape-docs-direct.js deleted file mode 100644 index 9d6f0fcd..00000000 --- a/scripts/scrape-docs-direct.js +++ /dev/null @@ -1,680 +0,0 @@ -const fs = require('fs').promises; -const path = require('path'); - -/** - * Main function to scrape documentation directly from MDX files and their JS/TS imports - */ -async function scrapeDocsRendered() { - const contentDir = './content'; - const srcDir = './src'; - const outputPath = './public/_scraped-docs'; - const scrapedPages = []; - - try { - console.log('πŸš€ Starting direct documentation scraping...'); - await fs.mkdir(outputPath, { recursive: true }); - - // Get all MDX files from content directory - const mdxFiles = await findMdxFiles(contentDir); - console.log(`πŸ“‹ Found ${mdxFiles.length} MDX files`); - - // Process each MDX file - for (let i = 0; i < mdxFiles.length; i++) { - const filePath = mdxFiles[i]; - console.log(`➑️ (${i + 1}/${mdxFiles.length}) Processing: ${filePath}`); - - try { - const pageData = await processMdxFile(filePath, srcDir); - if (pageData) { - scrapedPages.push(pageData); - console.log(` βœ… Done (${pageData.content.length} chars)`); - if (pageData.imports && pageData.imports.length > 0) { - console.log(` πŸ“¦ Imports: ${pageData.imports.length} found`); - } - } - } catch (error) { - console.warn(` ❌ Error processing ${filePath}:`, error.message); - } - } - - console.log(`βœ… Processed ${scrapedPages.length} pages`); - await saveScrapedContent(scrapedPages, outputPath); - } catch (err) { - console.error('❌ Fatal error:', err); - process.exit(1); - } -} - -/** - * Recursively find all MDX files in a directory - */ -async function findMdxFiles(dir, basePath = '') { - const files = []; - const items = await fs.readdir(dir); - - for (const item of items) { - const fullPath = path.join(dir, item); - const stat = await fs.stat(fullPath); - - if (stat.isDirectory() && !item.startsWith('_') && !item.startsWith('.')) { - const subFiles = await findMdxFiles(fullPath, path.join(basePath, item)); - files.push(...subFiles); - } else if (item.endsWith('.mdx')) { - files.push(fullPath); - } - } - - return files; -} - -/** - * Process a single MDX file and its imports - */ -async function processMdxFile(filePath, srcDir) { - try { - const content = await fs.readFile(filePath, 'utf8'); - - // Extract frontmatter - const metadata = extractFrontmatter(content); - - // Extract imports - const imports = extractImports(content); - - // Get imported content - const importedContent = await getImportedContent(imports, srcDir, filePath); - - // Clean MDX content (remove frontmatter and imports) - const cleanContent = cleanMdxContent(content); - - // Generate URL from file path - const url = generateUrlFromPath(filePath); - - // Combine content - const combinedContent = combineContent(cleanContent, importedContent); - - if (combinedContent.length < 50) { - return null; // Skip very short content - } - - return { - url: `https://docs.sei.io${url}`, - title: metadata?.title || extractTitleFromContent(cleanContent) || path.basename(filePath, '.mdx'), - description: metadata?.description || null, - keywords: metadata?.keywords || null, - content: combinedContent, - filePath: filePath, - imports: Object.keys(importedContent) - }; - } catch (error) { - console.warn(`Could not process ${filePath}:`, error.message); - return null; - } -} - -/** - * Extract frontmatter from MDX content - */ -function extractFrontmatter(content) { - const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); - if (!frontmatterMatch) return null; - - const frontmatterContent = frontmatterMatch[1]; - const metadata = {}; - - // Simple YAML parsing - const lines = frontmatterContent.split('\n'); - let currentKey = null; - let inArray = false; - - for (const line of lines) { - const trimmedLine = line.trim(); - if (!trimmedLine) continue; - - if (trimmedLine.startsWith('- ')) { - if (inArray && currentKey) { - if (!metadata[currentKey]) metadata[currentKey] = []; - metadata[currentKey].push(trimmedLine.slice(2).replace(/['"]/g, '')); - } - } else if (trimmedLine.includes(':')) { - const [key, ...valueParts] = trimmedLine.split(':'); - currentKey = key.trim(); - const value = valueParts.join(':').trim(); - - if (value === '' || value === '[') { - inArray = true; - metadata[currentKey] = []; - } else { - inArray = false; - if (value.startsWith('[') && value.endsWith(']')) { - const items = value - .slice(1, -1) - .split(',') - .map((item) => item.trim().replace(/['"]/g, '')); - metadata[currentKey] = items; - } else { - metadata[currentKey] = value.replace(/['"]/g, ''); - } - } - } - } - - return metadata; -} - -/** - * Extract import statements from MDX content - */ -function extractImports(content) { - const imports = {}; - const importRegex = /import\s+(?:{([^}]+)}|\*\s+as\s+(\w+)|(\w+))\s+from\s+['"]([^'"]+)['"];?/g; - - let match; - while ((match = importRegex.exec(content)) !== null) { - const [, namedImports, namespaceImport, defaultImport, importPath] = match; - - // Process both relative and absolute imports that start with src - if (importPath.startsWith('.') || importPath.startsWith('/') || importPath.includes('src/')) { - imports[importPath] = { - namedImports: namedImports ? namedImports.split(',').map((s) => s.trim()) : [], - namespaceImport: namespaceImport || null, - defaultImport: defaultImport || null - }; - } - } - - return imports; -} - -/** - * Get content from imported files - */ -async function getImportedContent(imports, srcDir, mdxFilePath) { - const importedContent = {}; - - for (const [importPath, importInfo] of Object.entries(imports)) { - try { - // Resolve the actual file path - const resolvedPath = await resolveImportPath(importPath, srcDir, mdxFilePath); - if (!resolvedPath) { - continue; - } - - const fileContent = await fs.readFile(resolvedPath, 'utf8'); - const extractedContent = extractContentFromJsTs(fileContent, importInfo, resolvedPath); - - if (extractedContent) { - importedContent[importPath] = extractedContent; - } - } catch (error) { - // Silent fail for imports that can't be resolved - } - } - - return importedContent; -} - -/** - * Resolve import path to actual file system path - */ -async function resolveImportPath(importPath, srcDir, mdxFilePath) { - let resolvedPath; - - if (importPath.startsWith('./') || importPath.startsWith('../')) { - // Relative import - resolve from the MDX file's directory - const mdxDir = path.dirname(mdxFilePath); - resolvedPath = path.resolve(mdxDir, importPath); - } else if (importPath.startsWith('/')) { - // Absolute import from root - resolvedPath = path.resolve('.', importPath.slice(1)); - } else if (importPath.includes('src/')) { - // Import that includes src path - resolvedPath = path.resolve('.', importPath); - } else { - // Module import - likely in src directory - resolvedPath = path.resolve(srcDir, importPath); - } - - // Try different extensions, including JSON first for data files - const extensions = ['.json', '.tsx', '.ts', '.jsx', '.js']; - - for (const ext of extensions) { - try { - const pathWithExt = resolvedPath + ext; - await fs.access(pathWithExt); - return pathWithExt; - } catch {} - } - - // Try index files - for (const ext of extensions) { - try { - const indexPath = path.join(resolvedPath, `index${ext}`); - await fs.access(indexPath); - return indexPath; - } catch {} - } - - return null; -} - -/** - * Extract meaningful content from JS/TS files - */ -function extractContentFromJsTs(fileContent, importInfo, filePath) { - let extractedContent = ''; - - // Extract comments (JSDoc, regular comments) - const commentRegex = /\/\*\*([\s\S]*?)\*\/|\/\*([\s\S]*?)\*\/|\/\/(.*)$/gm; - let match; - while ((match = commentRegex.exec(fileContent)) !== null) { - if (match[1]) { - // JSDoc comment - const docComment = match[1].replace(/\s*\*\s?/g, ' ').trim(); - if (docComment.length > 10) { - extractedContent += docComment + '\n'; - } - } else if (match[2]) { - // Block comment - const blockComment = match[2].trim(); - if (blockComment.length > 10) { - extractedContent += blockComment + '\n'; - } - } else if (match[3]) { - // Line comment - const lineComment = match[3].trim(); - if (lineComment.length > 10) { - extractedContent += lineComment + '\n'; - } - } - } - - // Extract data arrays and objects (especially useful for component data) - const dataArrayRegex = /(?:const|export\s+const)\s+(\w*(?:data|config|endpoints|options|items|list)\w*)\s*[:=]\s*\[[\s\S]*?\];?/gi; - while ((match = dataArrayRegex.exec(fileContent)) !== null) { - const dataName = match[1]; - let dataContent = match[0]; - // Extract meaningful data from arrays - if (dataContent.includes('url') || dataContent.includes('endpoint') || dataContent.includes('provider') || dataContent.includes('network')) { - // Extract URLs and endpoints - const urlMatches = dataContent.match(/['"`](https?:\/\/[^'"`]+)['"`]/g); - if (urlMatches) { - extractedContent += `${dataName} endpoints: ${urlMatches.map((u) => u.replace(/['"`]/g, '')).join(', ')}\n`; - } - - // Extract providers - const providerMatches = dataContent.match(/provider\s*:\s*['"`]([^'"`]+)['"`]/g); - if (providerMatches) { - extractedContent += `${dataName} providers: ${providerMatches.map((p) => p.replace(/provider\s*:\s*['"`]([^'"`]+)['"`]/, '$1')).join(', ')}\n`; - } - - // Extract descriptions - const descMatches = dataContent.match(/description\s*:\s*['"`]([^'"`]+)['"`]/g); - if (descMatches) { - extractedContent += `${dataName} descriptions: ${descMatches.map((d) => d.replace(/description\s*:\s*['"`]([^'"`]+)['"`]/, '$1')).join('; ')}\n`; - } - } - } - - // Extract string literals that look like documentation - const stringRegex = /(['"`])((?:(?!\1)[^\\]|\\.)*)(\1)/g; - while ((match = stringRegex.exec(fileContent)) !== null) { - const str = match[2]; - if ( - str.length > 30 && - (str.includes(' ') || str.includes('.')) && - (str.includes('description') || - str.includes('title') || - str.includes('text') || - str.includes('Official') || - str.includes('Community') || - str.includes('endpoint')) - ) { - extractedContent += str + '\n'; - } - } - - // Extract type definitions and interfaces - const typeRegex = /(?:interface|type|enum)\s+(\w+)[\s\S]*?(?=\n(?:interface|type|enum|export|const|function)|$)/g; - while ((match = typeRegex.exec(fileContent)) !== null) { - const typeDef = match[0]; - if (typeDef.includes('RpcEndpoint') || typeDef.includes('Network') || typeDef.includes('Config') || typeDef.includes('Data')) { - extractedContent += `Type definition: ${typeDef.substring(0, 300)}${typeDef.length > 300 ? '...' : ''}\n`; - } - } - - // Extract const declarations that might contain configuration - const constRegex = /export\s+const\s+(\w+)[\s\S]*?(?=\nexport|\nconst|\nfunction|$)/g; - while ((match = constRegex.exec(fileContent)) !== null) { - const constContent = match[0]; - if ( - constContent.includes('config') || - constContent.includes('data') || - constContent.includes('options') || - constContent.includes('endpoint') || - constContent.includes('network') || - constContent.includes('chain') - ) { - extractedContent += `Configuration/Data: ${constContent.substring(0, 500)}${constContent.length > 500 ? '...' : ''}\n`; - } - } - - // For JSON files, extract relevant data - if (filePath.endsWith('.json')) { - try { - const jsonData = JSON.parse(fileContent); - if (typeof jsonData === 'object') { - // Extract first level keys and some structure info - const structure = Object.keys(jsonData).slice(0, 20).join(', '); - extractedContent += `JSON data structure (keys): ${structure}\n`; - - // If it's a small JSON, include more content - if (fileContent.length < 2000) { - extractedContent += `JSON content: ${JSON.stringify(jsonData, null, 2)}\n`; - } else { - // For larger JSON, extract key-value pairs that look like documentation - const jsonStr = JSON.stringify(jsonData, null, 2); - const docKeys = ['title', 'description', 'name', 'url', 'endpoint', 'network', 'chain']; - docKeys.forEach((key) => { - const keyRegex = new RegExp(`"${key}"\\s*:\\s*"([^"]+)"`, 'gi'); - let keyMatch; - while ((keyMatch = keyRegex.exec(jsonStr)) !== null) { - extractedContent += `${key}: ${keyMatch[1]}\n`; - } - }); - } - } - } catch {} - } - - return extractedContent.trim(); -} - -/** - * Clean MDX content by removing frontmatter, imports, and JSX/HTML markup - */ -function cleanMdxContent(content) { - // Remove frontmatter - let cleaned = content.replace(/^---\n[\s\S]*?\n---\n?/, ''); - - // Remove import statements - cleaned = cleaned.replace(/import\s+(?:{[^}]+}|\*\s+as\s+\w+|\w+)\s+from\s+['"][^'"]+['"];?\n?/g, ''); - - // Remove JSX/HTML comments - cleaned = cleaned.replace(//g, ''); - cleaned = cleaned.replace(/{\/\*[\s\S]*?\*\/}/g, ''); - - // Replace common components with their text equivalents - cleaned = replaceComponentsWithText(cleaned); - - // Clean HTML/JSX tags but preserve structure and content - cleaned = cleanHtmlJsxTags(cleaned); - - return cleaned.trim(); -} - -/** - * Replace common components with their text equivalents - */ -function replaceComponentsWithText(content) { - // Replace RpcSelector with actual RPC endpoint information - content = content.replace( - //, - ` -**Available RPC Endpoints:** - -**Mainnet:** -- https://evm-rpc.sei-apis.com (Sei Foundation - Recommended for development, Rate limit: 10 req/s) -- https://evm-rpc-sei.stingray.plus (Staketab Community RPC) -- https://sei-evm-rpc.publicnode.com (PublicNode Community RPC, Rate limit: 5 req/s) -- https://seievm-rpc.polkachu.com (Polkachu Community RPC) -- https://jsonrpc.lavenderfive.com:443/sei (LavenderFive Community RPC) - -**Testnet (atlantic-2):** -- https://evm-rpc-testnet.sei-apis.com (Sei Foundation - Recommended for testing, Rate limit: 20 req/s) -- https://evm-rpc-testnet-sei.stingray.plus (Staketab Community RPC) -- https://seievm-testnet-rpc.polkachu.com (Polkachu Community RPC) -- https://sei-testnet.drpc.org (dRPC Community RPC) - - -**Local Development:** -- http://localhost:8545 (Local Node - For local development only) -` - ); - - // Replace other common components - content = content.replace(//, 'Add Sei Network to Wallet (interactive button)'); - content = content.replace(//, 'Network selection tabs for different Sei networks'); - content = content.replace(//, 'Chain information display component'); - content = content.replace(//, 'Faucet request form component'); - - // Replace icon components with text descriptions - content = content.replace(/]*\/?>|]*>[\s\S]*?<\/Icon(\w+)>/g, (match, iconName1, iconName2) => { - const iconName = iconName1 || iconName2; - const iconDescriptions = { - Rocket: 'πŸš€', - ArrowRight: 'β†’', - ChevronRight: 'β€Ί', - Check: 'βœ“', - Copy: 'πŸ“‹', - ExternalLink: 'πŸ”—', - Search: 'πŸ”', - Server: 'πŸ–₯️', - Terminal2: 'πŸ’»', - Package: 'πŸ“¦', - Wand: 'πŸͺ„', - LayoutDashboard: 'πŸ“Š', - Tools: 'πŸ”§', - InfoCircle: 'ℹ️' - }; - return iconDescriptions[iconName] || `[${iconName} icon]`; - }); - - return content; -} - -/** - * Clean HTML/JSX tags while preserving content structure - */ -function cleanHtmlJsxTags(content) { - // Remove complex className and style attributes first - content = content.replace(/\s+className\s*=\s*["'][^"']*["']/g, ''); - content = content.replace(/\s+style\s*=\s*{[^}]*}/g, ''); - - // Remove common wrapper divs and containers that don't add semantic meaning - content = content.replace(/]*>\s*]*>/g, ''); - content = content.replace(/<\/div>\s*<\/div>/g, ''); - content = content.replace(/]*>\s*$/gm, ''); - content = content.replace(/^\s*<\/div>/gm, ''); - - // Convert semantic HTML to markdown equivalents - content = content.replace(/]*>(.*?)<\/h[1-6]>/g, (_, level, text) => { - return '#'.repeat(parseInt(level)) + ' ' + text.trim(); - }); - - // Convert links to markdown - content = content.replace(/]*>(.*?)<\/a>/g, '[$2]($1)'); - - // Convert basic formatting - content = content.replace(/]*>(.*?)<\/strong>/g, '**$1**'); - content = content.replace(/]*>(.*?)<\/em>/g, '*$1*'); - content = content.replace(/]*>(.*?)<\/code>/g, '`$1`'); - - // Handle tables - content = content.replace(/]*>/g, '\n'); - content = content.replace(/<\/table>/g, '\n'); - content = content.replace(/]*>/g, ''); - content = content.replace(/<\/thead>/g, ''); - content = content.replace(/]*>/g, ''); - content = content.replace(/<\/tbody>/g, ''); - content = content.replace(/]*>/g, '| '); - content = content.replace(/<\/tr>/g, ' |\n'); - content = content.replace(/]*>(.*?)<\/th>/g, '$1 | '); - content = content.replace(/]*>(.*?)<\/td>/g, '$1 | '); - - // Remove remaining HTML/JSX tags but keep content - content = content.replace(/<[^>]+>/g, ' '); - - // Clean up extra whitespace - content = content.replace(/\n\s*\n\s*\n/g, '\n\n'); - content = content.replace(/[ \t]+/g, ' '); - content = content.replace(/^\s+|\s+$/gm, ''); - - return content; -} - -/** - * Generate URL from file path - */ -function generateUrlFromPath(filePath) { - // Convert file path to URL - let url = filePath.replace('./content', '').replace(/\.mdx$/, ''); - - // Handle index files - if (url.endsWith('/index')) { - url = url.replace('/index', ''); - } - - // Ensure starts with / - if (!url.startsWith('/')) { - url = '/' + url; - } - - // Handle root index - if (url === '/index') { - url = '/'; - } - - return url; -} - -/** - * Extract title from content - */ -function extractTitleFromContent(content) { - const titleMatch = content.match(/^#\s+(.+)$/m); - return titleMatch ? titleMatch[1].trim() : null; -} - -/** - * Combine MDX content with imported content - */ -function combineContent(mdxContent, importedContent) { - let combined = mdxContent; - - if (Object.keys(importedContent).length > 0) { - combined += '\n\n## Referenced Components and Utilities\n\n'; - - for (const [importPath, content] of Object.entries(importedContent)) { - if (content) { - combined += `### ${importPath}\n\n${content}\n\n`; - } - } - } - - return combined; -} - -/** - * Save scraped content - */ -async function saveScrapedContent(scrapedPages, outputPath) { - console.log('πŸ“ Saving scraped content...'); - - // Create consolidated content - let consolidatedContent = ''; - - for (const page of scrapedPages) { - const fileName = generateFileName(page.url); - - // Build frontmatter - let frontmatter = `--- -title: "${page.title}" -url: "${page.url}" -file_path: "${page.filePath}"`; - - if (page.description) { - const escapedDescription = page.description.replace(/"/g, '\\"'); - frontmatter += ` -description: "${escapedDescription}"`; - } - - if (page.keywords && Array.isArray(page.keywords) && page.keywords.length > 0) { - frontmatter += ` -keywords:`; - page.keywords.forEach((keyword) => { - frontmatter += ` - - "${keyword}"`; - }); - } - - if (page.imports && page.imports.length > 0) { - frontmatter += ` -imports:`; - page.imports.forEach((imp) => { - frontmatter += ` - - "${imp}"`; - }); - } - - frontmatter += ` ----`; - - const mdxContent = `${frontmatter} - -# ${page.title} - -${page.content} -`; - - // Save individual file - await fs.writeFile(path.join(outputPath, `${fileName}.mdx`), mdxContent, 'utf8'); - - // Add to consolidated content - consolidatedContent += `# ${page.title}\n\nURL: ${page.url}\nFile: ${page.filePath}\n`; - if (page.description) { - consolidatedContent += `Description: ${page.description}\n`; - } - if (page.keywords && page.keywords.length > 0) { - consolidatedContent += `Keywords: ${page.keywords.join(', ')}\n`; - } - if (page.imports && page.imports.length > 0) { - consolidatedContent += `Imports: ${page.imports.join(', ')}\n`; - } - consolidatedContent += `\n${page.content}\n\n---\n\n`; - } - - // Save consolidated content - await fs.writeFile(path.join(outputPath, 'sei-docs-consolidated.txt'), consolidatedContent, 'utf8'); - - // Save structured JSON - await fs.writeFile(path.join(outputPath, 'sei-docs-structured.json'), JSON.stringify(scrapedPages, null, 2), 'utf8'); - - console.log(`πŸ“„ Created consolidated text file: ${outputPath}/sei-docs-consolidated.txt`); - console.log(`πŸ“‹ Created structured JSON file: ${outputPath}/sei-docs-structured.json`); - console.log(`πŸ“ Created ${scrapedPages.length} individual .mdx files`); -} - -/** - * Generate filename from URL - */ -function generateFileName(url) { - try { - const urlObj = new URL(url); - let pathname = urlObj.pathname; - - // Remove leading/trailing slashes and replace special chars - pathname = pathname.replace(/^\/+|\/+$/g, ''); - pathname = pathname.replace(/[/\\:*?"<>|]/g, '-'); - pathname = pathname.replace(/-+/g, '-'); - - // Remove any "content-" prefix that might have been created - pathname = pathname.replace(/^content-?/, ''); - - return pathname || 'index'; - } catch { - return 'page-' + Date.now(); - } -} - -// Run the scraper -scrapeDocsRendered(); diff --git a/scripts/scrape-docs-html.js b/scripts/scrape-docs-html.js index da211ca5..79a87630 100644 --- a/scripts/scrape-docs-html.js +++ b/scripts/scrape-docs-html.js @@ -5,6 +5,235 @@ const { JSDOM } = require('jsdom'); // Configuration for parallel processing const CONCURRENCY_LIMIT = 20; // Number of files to process simultaneously +const SEI_LLMS_CONFIG = { + projectName: 'Sei Documentation', + blockquote: + 'Technical documentation for Sei, the fastest EVM blockchain. Covers smart contract development (Hardhat, Foundry), frontend integration (wagmi, ethers.js), AI tooling (MCP Server, Cambrian Agent Kit), x402 micropayments, node operations, and the Sei Giga upgrade roadmap.', + intro: + 'Sei is a parallelized EVM Layer 1 blockchain with 400ms finality, 100 MGas/s throughput, and full Ethereum tooling compatibility. Deploy standard Solidity contracts with no modifications. Chain ID: mainnet 1329, testnet 1328.', + quickReference: [ + 'Chain ID: mainnet 1329, testnet 1328', + 'RPC (mainnet): https://evm-rpc.sei-apis.com', + 'RPC (testnet): https://evm-rpc-testnet.sei-apis.com', + 'Native token: SEI (gas, staking, governance)', + 'USDC (mainnet): 0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392 (6 decimals)', + 'USDC (testnet): 0x4fCF1784B31630811181f670Aea7A7bEF803eaED (6 decimals)', + 'Block time: 400ms finality', + 'Throughput: 100 MGas/s (~12,500 TPS)', + 'EVM compatibility: Full β€” standard Solidity, Hardhat, Foundry, wagmi, ethers.js work unmodified' + ].join('\n'), + keyResources: [ + { + title: 'GitHub', + url: 'https://github.com/sei-protocol', + description: 'Open source repositories including sei-chain, sei-js, and MCP server' + }, + { + title: 'Sei-JS Documentation', + url: 'https://sei-js.docs.sei.io', + description: 'JavaScript/TypeScript SDK documentation for Sei-js blockchain integration' + }, + { + title: 'Ecosystem', + url: 'https://www.sei.io/ecosystem', + description: 'Directory of projects building on Sei' + }, + { + title: 'Blog', + url: 'https://blog.sei.io', + description: 'Latest news, announcements, and technical deep dives' + } + ] +}; + +/** URL prefixes to exclude entirely from llms.txt and llms-full.txt output. */ +const EXCLUDED_PREFIXES = ['/cosmos-sdk']; + +/** + * Section definitions ordered by match priority. + * More specific prefixes (e.g. /evm/ai-tooling) must come before broader ones (/evm). + */ +const LLMS_SECTION_ORDER = [ + { + name: 'Learn', + match: (urlPath) => urlPath.startsWith('/learn'), + overview: [ + 'Sei is a parallelized EVM Layer 1 blockchain. Its performance comes from Twin Turbo Consensus (optimistic block processing), parallel EVM execution (concurrent transaction processing for independent state), and SeiDB (high-throughput storage layer). Full Ethereum tooling compatibility β€” deploy standard Solidity contracts with no modifications.', + "Sei Giga is the next major upgrade targeting 200K TPS and 5 gigagas/s throughput via Autobahn multi-proposer BFT consensus and a custom EVM execution engine. For developers: Sei Giga's parallel execution engine rewards contracts with user-scoped state (mapping per address) over shared global state.", + 'Mainnet (pacific-1): Chain ID 1329. Testnet (atlantic-2): Chain ID 1328.' + ].join('\n\n') + }, + { + name: 'AI Tooling', + match: (urlPath) => urlPath.startsWith('/evm/ai-tooling') || urlPath.startsWith('/evm/x402'), + overview: [ + 'The Sei MCP Server (@sei-js/mcp-server) connects AI assistants to Sei with 29+ tools. Install: `npx -y @sei-js/mcp-server`. Read-only tools: get_chain_info, get_balance, get_erc20_balance, get_token_info, get_nft_info, and more. Wallet tools (require PRIVATE_KEY): transfer_sei, transfer_erc20, deploy_contract, write_contract, and more. Documentation search: search_docs, search_sei_js_docs.', + 'The Cambrian Agent Kit enables autonomous AI agents on Sei with DeFi protocol integrations (Takara lending, Silo lending, Citrex perpetuals, Symphony aggregation, DragonSwap liquidity).', + 'The x402 protocol enables HTTP 402-based micropayments for machine-to-machine payments β€” agents pay per-request for APIs, content, and services with instant settlement on Sei (~400ms finality). The sei-js library provides both server-side (payment verification) and client-side (payment signing) x402 packages.' + ].join('\n\n') + }, + { + name: 'EVM Development', + match: (urlPath) => urlPath.startsWith('/evm'), + overview: [ + "Sei's EVM is fully compatible with Ethereum. Standard Solidity contracts deploy without modification. All Ethereum tooling (Hardhat, Foundry, wagmi, ethers.js, viem, RainbowKit) works as-is. Transactions touching independent state execute concurrently.", + 'Precompiled contracts at fixed addresses expose native Sei functionality (staking, governance, IBC transfers, pointer contracts) to EVM.', + 'Native USDC: mainnet 0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392, testnet 0x4fCF1784B31630811181f670Aea7A7bEF803eaED (6 decimals).' + ].join('\n\n') + }, + { + name: 'Node Operations', + match: (urlPath) => urlPath.startsWith('/node'), + overview: + 'Sei supports full nodes (recent state, consensus relay), archive nodes (complete historical state), and validator nodes (block production and consensus). StateSync enables fast bootstrap β€” new nodes fetch a recent state snapshot instead of replaying all historical blocks.' + } +]; + +/** + * Assign each scraped page to a section based on its URL path. + * Returns { sections, assigned } where assigned is the Set of URLs that matched. + */ +function categorizePages(scrapedPages) { + const sections = LLMS_SECTION_ORDER.map((sec) => ({ + name: sec.name, + overview: sec.overview || null, + pages: [] + })); + + const assigned = new Set(); + + for (const page of scrapedPages) { + try { + const urlPath = new URL(page.url).pathname; + for (let i = 0; i < LLMS_SECTION_ORDER.length; i++) { + if (LLMS_SECTION_ORDER[i].match(urlPath)) { + sections[i].pages.push(page); + assigned.add(page.url); + break; + } + } + } catch { + // malformed URL β€” skip categorization + } + } + + return { sections: sections.filter((s) => s.pages.length > 0), assigned }; +} + +function formatLink(page) { + const desc = page.description ? `: ${page.description}` : ''; + return `- [${page.title}](${page.url})${desc}`; +} + +/** + * Generate llms.txt and llms-full.txt following https://llmstxt.org. + * + * llms.txt – project header, intro, categorized links with descriptions + * llms-full.txt – header, quick reference, section overviews, categorized links, + * key resources, then full scraped page content + */ +async function createLlmsFiles(scrapedPages, outputPath) { + try { + console.log('πŸ“ Generating llms.txt and llms-full.txt...'); + + const { projectName, blockquote, intro, quickReference, keyResources } = SEI_LLMS_CONFIG; + + const isExcluded = (url) => { + try { + const urlPath = new URL(url).pathname; + return EXCLUDED_PREFIXES.some((prefix) => urlPath.startsWith(prefix)); + } catch { + return false; + } + }; + const filteredPages = scrapedPages.filter((p) => !isExcluded(p.url)); + + const { sections, assigned } = categorizePages(filteredPages); + const uncategorized = filteredPages.filter((p) => !assigned.has(p.url)); + + // ---- llms.txt ---- + let llmsTxt = `# ${projectName}\n\n`; + llmsTxt += `> ${blockquote}\n\n`; + llmsTxt += `${intro}\n`; + llmsTxt += `\n## Quick Reference\n\n${quickReference}\n`; + + for (const section of sections) { + llmsTxt += `\n## ${section.name}\n\n`; + if (section.overview) { + llmsTxt += `${section.overview}\n\n`; + } + for (const page of section.pages) { + llmsTxt += formatLink(page) + '\n'; + } + } + + if (uncategorized.length > 0) { + llmsTxt += `\n## Optional\n\n`; + for (const page of uncategorized) { + llmsTxt += formatLink(page) + '\n'; + } + } + + if (keyResources.length > 0) { + llmsTxt += `\n## Key Resources\n\n`; + for (const res of keyResources) { + llmsTxt += `- [${res.title}](${res.url}): ${res.description}\n`; + } + } + + // ---- llms-full.txt ---- + let llmsFull = `# ${projectName}\n\n`; + llmsFull += `> ${blockquote}\n\n`; + llmsFull += `## Quick Reference\n\n${quickReference}\n`; + + for (const section of sections) { + llmsFull += `\n## ${section.name}\n\n`; + if (section.overview) { + llmsFull += `${section.overview}\n\n`; + } + for (const page of section.pages) { + llmsFull += formatLink(page) + '\n'; + } + } + + if (uncategorized.length > 0) { + llmsFull += `\n## Optional\n\n`; + for (const page of uncategorized) { + llmsFull += formatLink(page) + '\n'; + } + } + + if (keyResources.length > 0) { + llmsFull += `\n## Key Resources\n\n`; + for (const res of keyResources) { + llmsFull += `- [${res.title}](${res.url}): ${res.description}\n`; + } + } + + // Append full page content after a separator + llmsFull += '\n---\n\n'; + for (const page of filteredPages) { + llmsFull += `# ${page.title}\n\n`; + llmsFull += `URL: ${page.url}\n`; + if (page.description) { + llmsFull += `Description: ${page.description}\n`; + } + if (page.keywords && page.keywords.length > 0) { + llmsFull += `Keywords: ${page.keywords.join(', ')}\n`; + } + llmsFull += `\n${page.content}\n\n---\n\n`; + } + + await Promise.all([fs.writeFile(path.join(outputPath, 'llms.txt'), llmsTxt, 'utf8'), fs.writeFile(path.join(outputPath, 'llms-full.txt'), llmsFull, 'utf8')]); + + console.log('πŸ“„ Created llms.txt and llms-full.txt'); + } catch (error) { + console.error('❌ Error generating llms.txt files:', error.message); + } +} + +module.exports = { SEI_LLMS_CONFIG, LLMS_SECTION_ORDER, categorizePages, createLlmsFiles }; + /** * Scrape documentation from the built HTML files in .next/server/app */ @@ -29,8 +258,10 @@ async function scrapeBuiltHtml() { console.log(`βœ… Successfully processed ${scrapedPages.length} pages out of ${htmlFiles.length} total files`); await saveScrapedContent(scrapedPages, outputPath); - // Generate llms.txt and llms-full.txt following the llms.txt specification - await createLlmsFiles(scrapedPages, outputPath); + // Generate llms.txt and llms-full.txt at the public root (served as docs.sei.io/llms.txt) + await createLlmsFiles(scrapedPages, './public'); + // Generate per-page .md files mirroring URL paths (e.g. /evm/evm-general.md) + await createPerPageMarkdownFiles(scrapedPages, './public'); } catch (err) { console.error('❌ Fatal error:', err); process.exit(1); @@ -736,49 +967,6 @@ ${page.content} console.log(`πŸ“ Created ${scrapedPages.length} individual .mdx files`); } -/** - * Create llms.txt (summary) and llms-full.txt (summary + full context) files - * following the https://llmstxt.org specification. - */ -async function createLlmsFiles(scrapedPages, outputPath) { - try { - console.log('πŸ“ Generating llms.txt and llms-full.txt...'); - - const projectName = 'Sei Docs'; - const projectSummary = 'Comprehensive documentation for the Sei Network, including guides, tutorials, reference material, and API docs.'; - - // Build llms.txt content (high-level summary plus a list of pages) - let llmsTxt = `# ${projectName}\n\n`; - llmsTxt += `> ${projectSummary}\n\n`; - - llmsTxt += '## Docs\n\n'; - scrapedPages.forEach((page) => { - llmsTxt += `- [${page.title}](${page.url})\n`; - }); - - // Build llms-full.txt content (llms.txt + complete page text) - let llmsFull = llmsTxt + '\n---\n\n'; - scrapedPages.forEach((page) => { - llmsFull += `# ${page.title}\n\n`; - llmsFull += `URL: ${page.url}\n`; - if (page.description) { - llmsFull += `Description: ${page.description}\n`; - } - if (page.keywords && page.keywords.length > 0) { - llmsFull += `Keywords: ${page.keywords.join(', ')}\n`; - } - llmsFull += `\n${page.content}\n\n---\n\n`; - }); - - // Write files in parallel - await Promise.all([fs.writeFile(path.join(outputPath, 'llms.txt'), llmsTxt, 'utf8'), fs.writeFile(path.join(outputPath, 'llms-full.txt'), llmsFull, 'utf8')]); - - console.log('πŸ“„ Created llms.txt and llms-full.txt'); - } catch (error) { - console.error('❌ Error generating llms.txt files:', error.message); - } -} - /** * Generate filename from URL */ @@ -798,5 +986,49 @@ function generateFileName(url) { } } +/** + * Create per-page .md files that mirror the URL structure. + * E.g. a page at https://docs.sei.io/evm/evm-general gets a file at public/evm/evm-general.md + * so that docs.sei.io/evm/evm-general.md returns the LLM-friendly markdown. + */ +async function createPerPageMarkdownFiles(scrapedPages, publicDir) { + try { + console.log('πŸ“ Generating per-page .md files...'); + let created = 0; + + for (const page of scrapedPages) { + const urlObj = new URL(page.url); + let pathname = urlObj.pathname; + + // Skip the root page (index) + if (pathname === '/' || pathname === '') continue; + + // Remove leading slash + pathname = pathname.replace(/^\//, ''); + + const mdFilePath = path.join(publicDir, `${pathname}.md`); + + // Ensure the directory exists + await fs.mkdir(path.dirname(mdFilePath), { recursive: true }); + + // Build the markdown content with frontmatter + let md = `---\ntitle: ${page.title}\n`; + if (page.description) { + md += `description: ${page.description}\n`; + } + md += `url: ${page.url}\n---\n\n`; + md += `# ${page.title}\n\n`; + md += page.content; + + await fs.writeFile(mdFilePath, md, 'utf8'); + created++; + } + + console.log(`πŸ“„ Created ${created} per-page .md files (append .md to any docs URL)`); + } catch (error) { + console.error('❌ Error generating per-page .md files:', error.message); + } +} + // Run the scraper scrapeBuiltHtml(); diff --git a/scripts/scrape-docs-rendered.js b/scripts/scrape-docs-rendered.js deleted file mode 100644 index eccb1788..00000000 --- a/scripts/scrape-docs-rendered.js +++ /dev/null @@ -1,450 +0,0 @@ -const puppeteer = require('puppeteer'); -const fs = require('fs').promises; -const path = require('path'); -const { URL } = require('url'); - -/** - * Web scraper that crawls the actual rendered documentation site - */ -async function scrapeRenderedDocs() { - const baseUrl = 'https://docs.sei.io'; - const outputPath = './public/_scraped-docs'; - const scrapedPages = []; - const visitedUrls = new Set(); - const urlsToVisit = [baseUrl]; - - try { - console.log('πŸš€ Starting rendered documentation scraping...'); - await fs.mkdir(outputPath, { recursive: true }); - - // Launch browser - console.log('🌐 Launching browser...'); - const browser = await puppeteer.launch({ - headless: 'new', - args: ['--no-sandbox', '--disable-setuid-sandbox'] - }); - - const page = await browser.newPage(); - - // Set user agent and viewport - await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'); - await page.setViewport({ width: 1920, height: 1080 }); - - // Process URLs - while (urlsToVisit.length > 0 && visitedUrls.size < 100) { - // Limit to 100 pages - const currentUrl = urlsToVisit.shift(); - - if (visitedUrls.has(currentUrl) || !isValidDocUrl(currentUrl, baseUrl)) { - continue; - } - - visitedUrls.add(currentUrl); - console.log(`➑️ (${visitedUrls.size}/100) Processing: ${currentUrl}`); - - try { - // Navigate to page - await page.goto(currentUrl, { - waitUntil: 'networkidle2', - timeout: 30000 - }); - - // Wait for content to load - await page.waitForTimeout(2000); - - // Extract page data - const pageData = await extractPageData(page, currentUrl); - - if (pageData && pageData.content.length > 100) { - scrapedPages.push(pageData); - console.log(` βœ… Done (${pageData.content.length} chars)`); - } else { - console.log(` ⚠️ Skipped (too short or no content)`); - } - - // Find additional links to crawl - const links = await findDocumentationLinks(page, baseUrl); - links.forEach((link) => { - if (!visitedUrls.has(link) && !urlsToVisit.includes(link)) { - urlsToVisit.push(link); - } - }); - } catch (error) { - console.warn(` ❌ Error processing ${currentUrl}:`, error.message); - } - } - - await browser.close(); - console.log(`βœ… Processed ${scrapedPages.length} pages`); - await saveScrapedContent(scrapedPages, outputPath); - } catch (err) { - console.error('❌ Fatal error:', err); - process.exit(1); - } -} - -/** - * Check if URL is a valid documentation URL to crawl - */ -function isValidDocUrl(url, baseUrl) { - try { - const urlObj = new URL(url); - const baseUrlObj = new URL(baseUrl); - - // Must be same domain - if (urlObj.hostname !== baseUrlObj.hostname) { - return false; - } - - // Skip certain paths - const skipPaths = ['/api/', '/images/', '/assets/', '/_next/', '/favicon']; - if (skipPaths.some((path) => urlObj.pathname.startsWith(path))) { - return false; - } - - // Skip anchors and query params for crawling purposes - return true; - } catch { - return false; - } -} - -/** - * Extract page data from the rendered page - */ -async function extractPageData(page, url) { - const data = await page.evaluate(() => { - // Remove navigation, footer, and other non-content elements - const elementsToRemove = [ - 'nav', - 'header', - 'footer', - '[role="navigation"]', - '.sidebar', - '.nav', - '.navigation', - '.breadcrumb', - '.pagination', - 'script', - 'style', - 'noscript' - ]; - - elementsToRemove.forEach((selector) => { - const elements = document.querySelectorAll(selector); - elements.forEach((el) => el.remove()); - }); - - // Try to find the main content area - let contentElement = - document.querySelector('main') || - document.querySelector('[role="main"]') || - document.querySelector('.content') || - document.querySelector('.main-content') || - document.querySelector('article') || - document.body; - - // Get title - const title = - document.querySelector('h1')?.textContent?.trim() || document.querySelector('title')?.textContent?.replace(' | Sei Docs', '')?.trim() || 'Untitled'; - - // Get meta description - const metaDesc = document.querySelector('meta[name="description"]'); - const description = metaDesc ? metaDesc.getAttribute('content') : null; - - // Get keywords - const metaKeywords = document.querySelector('meta[name="keywords"]'); - const keywords = metaKeywords - ? metaKeywords - .getAttribute('content') - ?.split(',') - .map((k) => k.trim()) - : null; - - // Clean content - if (contentElement) { - // Remove empty elements - const emptyElements = contentElement.querySelectorAll('*:empty:not(img):not(input):not(textarea):not(br):not(hr)'); - emptyElements.forEach((el) => el.remove()); - - // Convert to markdown-like text - let content = processElement(contentElement); - - // Clean up whitespace - content = content - .replace(/\n\s*\n\s*\n/g, '\n\n') - .replace(/[ \t]+/g, ' ') - .trim(); - - return { - title, - description, - keywords, - content, - url: window.location.href - }; - } - - return null; - }); - - return data; -} - -/** - * Process DOM element to markdown-like text (runs in browser context) - */ -function processElement(element) { - let result = ''; - - for (const node of element.childNodes) { - if (node.nodeType === Node.TEXT_NODE) { - const text = node.textContent.trim(); - if (text) { - result += text + ' '; - } - } else if (node.nodeType === Node.ELEMENT_NODE) { - const tagName = node.tagName.toLowerCase(); - - switch (tagName) { - case 'h1': - result += '\n# ' + node.textContent.trim() + '\n\n'; - break; - case 'h2': - result += '\n## ' + node.textContent.trim() + '\n\n'; - break; - case 'h3': - result += '\n### ' + node.textContent.trim() + '\n\n'; - break; - case 'h4': - result += '\n#### ' + node.textContent.trim() + '\n\n'; - break; - case 'h5': - result += '\n##### ' + node.textContent.trim() + '\n\n'; - break; - case 'h6': - result += '\n###### ' + node.textContent.trim() + '\n\n'; - break; - case 'p': - result += '\n' + node.textContent.trim() + '\n\n'; - break; - case 'ul': - case 'ol': - result += '\n' + processListElement(node) + '\n'; - break; - case 'li': - // Handled by processListElement - break; - case 'a': - const href = node.getAttribute('href'); - const text = node.textContent.trim(); - if (href && text) { - result += `[${text}](${href})`; - } else { - result += text; - } - break; - case 'strong': - case 'b': - result += '**' + node.textContent.trim() + '**'; - break; - case 'em': - case 'i': - result += '*' + node.textContent.trim() + '*'; - break; - case 'code': - result += '`' + node.textContent.trim() + '`'; - break; - case 'pre': - result += '\n```\n' + node.textContent.trim() + '\n```\n\n'; - break; - case 'blockquote': - const lines = node.textContent.trim().split('\n'); - result += '\n' + lines.map((line) => '> ' + line.trim()).join('\n') + '\n\n'; - break; - case 'table': - result += '\n' + processTableElement(node) + '\n\n'; - break; - case 'br': - result += '\n'; - break; - case 'hr': - result += '\n---\n\n'; - break; - default: - // For other elements, just get the text content - const textContent = node.textContent.trim(); - if (textContent) { - result += textContent + ' '; - } - break; - } - } - } - - return result; -} - -/** - * Process list elements (runs in browser context) - */ -function processListElement(listElement) { - let result = ''; - const items = listElement.querySelectorAll('li'); - const isOrdered = listElement.tagName.toLowerCase() === 'ol'; - - items.forEach((item, index) => { - const prefix = isOrdered ? `${index + 1}. ` : '- '; - const text = item.textContent.trim(); - if (text) { - result += prefix + text + '\n'; - } - }); - - return result; -} - -/** - * Process table elements (runs in browser context) - */ -function processTableElement(tableElement) { - let result = ''; - const rows = tableElement.querySelectorAll('tr'); - - rows.forEach((row, rowIndex) => { - const cells = row.querySelectorAll('th, td'); - const cellTexts = Array.from(cells).map((cell) => cell.textContent.trim()); - - if (cellTexts.length > 0) { - result += '| ' + cellTexts.join(' | ') + ' |\n'; - - // Add separator row after header - if (rowIndex === 0 && row.querySelector('th')) { - result += '| ' + cellTexts.map(() => '---').join(' | ') + ' |\n'; - } - } - }); - - return result; -} - -/** - * Find documentation links to crawl - */ -async function findDocumentationLinks(page, baseUrl) { - const links = await page.evaluate((baseUrl) => { - const linkElements = document.querySelectorAll('a[href]'); - const links = []; - - linkElements.forEach((link) => { - const href = link.getAttribute('href'); - if (href) { - try { - const url = new URL(href, window.location.href); - - // Only include links from the same domain - if (url.hostname === new URL(baseUrl).hostname) { - // Clean URL (remove hash and query params for crawling) - url.hash = ''; - url.search = ''; - links.push(url.toString()); - } - } catch { - // Ignore invalid URLs - } - } - }); - - return [...new Set(links)]; // Remove duplicates - }, baseUrl); - - return links; -} - -/** - * Save scraped content - */ -async function saveScrapedContent(scrapedPages, outputPath) { - console.log('πŸ“ Saving scraped content...'); - - // Create consolidated content - let consolidatedContent = ''; - - for (const page of scrapedPages) { - const fileName = generateFileName(page.url); - - // Build frontmatter - let frontmatter = `--- -title: "${page.title.replace(/"/g, '\\"')}" -url: "${page.url}"`; - - if (page.description) { - frontmatter += ` -description: "${page.description.replace(/"/g, '\\"')}"`; - } - - if (page.keywords && Array.isArray(page.keywords) && page.keywords.length > 0) { - frontmatter += ` -keywords:`; - page.keywords.forEach((keyword) => { - frontmatter += ` - - "${keyword.replace(/"/g, '\\"')}"`; - }); - } - - frontmatter += ` ----`; - - const mdxContent = `${frontmatter} - -# ${page.title} - -${page.content} -`; - - // Save individual file - await fs.writeFile(path.join(outputPath, `${fileName}.mdx`), mdxContent, 'utf8'); - - // Add to consolidated content - consolidatedContent += `# ${page.title}\n\nURL: ${page.url}\n`; - if (page.description) { - consolidatedContent += `Description: ${page.description}\n`; - } - if (page.keywords && page.keywords.length > 0) { - consolidatedContent += `Keywords: ${page.keywords.join(', ')}\n`; - } - consolidatedContent += `\n${page.content}\n\n---\n\n`; - } - - // Save consolidated content - await fs.writeFile(path.join(outputPath, 'sei-docs-consolidated.txt'), consolidatedContent, 'utf8'); - - // Save structured JSON - await fs.writeFile(path.join(outputPath, 'sei-docs-structured.json'), JSON.stringify(scrapedPages, null, 2), 'utf8'); - - console.log(`πŸ“„ Created consolidated text file: ${outputPath}/sei-docs-consolidated.txt`); - console.log(`πŸ“‹ Created structured JSON file: ${outputPath}/sei-docs-structured.json`); - console.log(`πŸ“ Created ${scrapedPages.length} individual .mdx files`); -} - -/** - * Generate filename from URL - */ -function generateFileName(url) { - try { - const urlObj = new URL(url); - let pathname = urlObj.pathname; - - // Remove leading/trailing slashes and replace special chars - pathname = pathname.replace(/^\/+|\/+$/g, ''); - pathname = pathname.replace(/[/\\:*?"<>|]/g, '-'); - pathname = pathname.replace(/-+/g, '-'); - - return pathname || 'index'; - } catch { - return 'page-' + Date.now(); - } -} - -// Run the scraper -scrapeRenderedDocs(); diff --git a/scripts/scrape-docs.js b/scripts/scrape-docs.js deleted file mode 100644 index 81c8be0f..00000000 --- a/scripts/scrape-docs.js +++ /dev/null @@ -1,549 +0,0 @@ -const puppeteer = require('puppeteer-core'); -const fs = require('fs').promises; -const path = require('path'); -const { URL } = require('url'); -const { spawn } = require('child_process'); -const net = require('net'); - -/** - * Top‑level entry - */ -async function scrapeSeiDocs() { - const port = 3000; - const localBaseUrl = `http://localhost:${port}`; - const prodBaseUrl = 'https://docs.sei.io'; - const outputPath = './public/_scraped-docs'; - const scrapedPages = []; - let devServer; - - try { - console.log('πŸš€ Starting documentation scraping…'); - await fs.mkdir(outputPath, { recursive: true }); - - console.log(`🌟 Booting Next.js server on :${port}`); - devServer = await startDevServer(port); - - const browser = await launchBrowser(); - - // Generate list of URLs to scrape - const allUrls = await generateUrlsFromFileStructure(localBaseUrl); - const main = [`${localBaseUrl}/learn`, `${localBaseUrl}/evm`, `${localBaseUrl}/cosmos-sdk`, `${localBaseUrl}/node`, `${localBaseUrl}`]; - const urls = [...new Set([...main, ...allUrls])]; - - console.log(`πŸ“‹ Total URLs: ${urls.length}`); - await scrapeUrlsSequential(browser, urls, localBaseUrl, prodBaseUrl, scrapedPages); - - await browser.close(); - console.log(`βœ… Scraped ${scrapedPages.length} pages`); - - await saveScrapedContent(scrapedPages, outputPath); - } catch (err) { - console.error('❌ Fatal error:', err); - process.exit(1); - } finally { - if (devServer) { - console.log('πŸ›‘ Shutting dev server'); - devServer.kill(); - await new Promise((r) => setTimeout(r, 1_000)); - } - } -} - -/** - * Sequential scraping with a single re‑used page (Rec.Β #4), - * blocking images/fonts/css (Rec.Β #3) and retry/back‑off. - */ -async function scrapeUrlsSequential(browser, urls, localBaseUrl, prodBaseUrl, scrapedPages) { - const page = await browser.newPage(); - - // Intercept requests – drop heavy assets (Rec.Β #3) - await page.setRequestInterception(true); - page.on('request', (req) => { - const type = req.resourceType(); - if (['image', 'font', 'stylesheet', 'media'].includes(type)) { - return req.abort(); - } - req.continue(); - }); - - const MAX_RETRIES = 3; - - for (let i = 0; i < urls.length; i++) { - const url = urls[i]; - console.log(`➑️ (${i + 1}/${urls.length}) ${url}`); - - for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) { - try { - await page.goto(url, { - waitUntil: 'domcontentloaded', // lighter than networkidle - timeout: 60_000 - }); - - const pageData = await extractPageData(page, url, localBaseUrl, prodBaseUrl); - if (pageData) { - scrapedPages.push(pageData); - console.log(` βœ… Done (${pageData.content.length} chars)`); - } - break; // success – break retry loop - } catch (err) { - console.warn(` ⏳ Attempt ${attempt}/${MAX_RETRIES} failed: ${err.message}`); - if (attempt === MAX_RETRIES) console.warn(` ❌ Giving up on ${url}`); - else await new Promise((r) => setTimeout(r, attempt * 2_000)); // back‑off - } - } - } - - await page.close(); -} - -/** - * Extract text + metadata once the page is loaded. - */ -async function extractPageData(page, url, localBaseUrl, prodBaseUrl) { - // Only docs URLs - if (!url.startsWith(localBaseUrl)) return null; - - const pageData = await page.evaluate(() => { - const selectorsToNuke = ['nav', 'header', 'footer', '.nx-sidebar', '.nx-toc', '[data-nextra-nav]', '[data-nextra-sidebar]', 'button', '.search', '#search']; - selectorsToNuke.forEach((sel) => document.querySelectorAll(sel).forEach((el) => el.remove())); - - const main = document.querySelector('main') || document.body; - return { - title: document.title || (document.querySelector('h1')?.textContent ?? 'Untitled'), - content: main.innerText.trim() - }; - }); - - // filter empty pages - if (!pageData.content || pageData.content.length < 50) return null; - const prodUrl = url.replace(localBaseUrl, prodBaseUrl); - const originalMetadata = await getOriginalMetadata(url, localBaseUrl); - - return { - url: prodUrl, - title: originalMetadata?.title || pageData.title, - description: originalMetadata?.description || null, - keywords: originalMetadata?.keywords || null, - content: pageData.content - }; -} - -async function scrapeSinglePage(page, url, localBaseUrl, prodBaseUrl) { - // Skip if not a docs URL - if (!url.startsWith(localBaseUrl)) { - return null; - } - - console.log(`πŸ“„ Scraping: ${url}`); - - try { - await page.goto(url, { - waitUntil: 'networkidle0', // Faster loading for better performance - timeout: 30000 // Optimized timeout for reliability - }); - - // Wait for content to load - await new Promise((resolve) => setTimeout(resolve, 1000)); - - // Extract page content - const pageData = await page.evaluate(() => { - // Remove navigation, headers, footers, and other non-content elements - const elementsToRemove = [ - 'nav', - 'header', - 'footer', - '.nx-sidebar', - '.nx-toc', - '.nx-nav-container', - '[data-nextra-nav]', - '[data-nextra-sidebar]', - '.nextra-nav-container', - '.nextra-sidebar', - 'button', - '.search', - '#search' - ]; - - elementsToRemove.forEach((selector) => { - const elements = document.querySelectorAll(selector); - elements.forEach((el) => el.remove()); - }); - - // Get the main content area - const mainContent = - document.querySelector('main') || - document.querySelector('.nx-content') || - document.querySelector('[data-nextra-content]') || - document.querySelector('.nextra-content') || - document.body; - - const title = document.title || document.querySelector('h1')?.textContent || 'Untitled'; - const content = mainContent ? mainContent.innerText.trim() : ''; - - return { title, content }; - }); - - // Only return pages with substantial content - if (pageData.content && pageData.content.length > 50) { - // Convert localhost URL to production URL - const prodUrl = url.replace(localBaseUrl, prodBaseUrl); - - // Get original metadata from source file - const originalMetadata = await getOriginalMetadata(url, localBaseUrl); - - return { - url: prodUrl, - title: originalMetadata?.title || pageData.title, - description: originalMetadata?.description || null, - keywords: originalMetadata?.keywords || null, - content: pageData.content, - originalMetadata - }; - } - - return null; - } catch (error) { - throw error; - } -} - -async function getOriginalMetadata(url, localBaseUrl) { - try { - // Convert URL to file path - const urlPath = url.replace(localBaseUrl, ''); - let filePath = path.join('./content', urlPath); - - // Handle index files - if (urlPath === '' || urlPath === '/') { - filePath = './content/index.mdx'; - } else if (!urlPath.includes('.')) { - // Try both direct file and index file - const directFile = filePath + '.mdx'; - const indexFile = path.join(filePath, 'index.mdx'); - - // Check which file exists - try { - await fs.access(directFile); - filePath = directFile; - } catch { - try { - await fs.access(indexFile); - filePath = indexFile; - } catch { - return null; // No source file found - } - } - } - - // Read the source file - const fileContent = await fs.readFile(filePath, 'utf8'); - - // Extract frontmatter - const frontmatterMatch = fileContent.match(/^---\n([\s\S]*?)\n---/); - if (!frontmatterMatch) { - return null; // No frontmatter found - } - - const frontmatterContent = frontmatterMatch[1]; - const metadata = {}; - - // Parse YAML-like frontmatter manually (basic parsing) - const lines = frontmatterContent.split('\n'); - let currentKey = null; - let currentValue = ''; - let inArray = false; - - for (const line of lines) { - const trimmedLine = line.trim(); - if (!trimmedLine) continue; - - if (trimmedLine.startsWith('- ')) { - // Array item - if (inArray && currentKey) { - if (!metadata[currentKey]) metadata[currentKey] = []; - metadata[currentKey].push(trimmedLine.slice(2).replace(/['"]/g, '')); - } - } else if (trimmedLine.includes(':')) { - // Save previous key-value pair - if (currentKey && currentValue) { - metadata[currentKey] = currentValue.replace(/['"]/g, ''); - } - - // New key-value pair - const [key, ...valueParts] = trimmedLine.split(':'); - currentKey = key.trim(); - currentValue = valueParts.join(':').trim(); - - // Check if this starts an array - if (currentValue === '' || currentValue === '[') { - inArray = true; - metadata[currentKey] = []; - } else { - inArray = false; - if (currentValue.startsWith('[') && currentValue.endsWith(']')) { - // Inline array - const items = currentValue - .slice(1, -1) - .split(',') - .map((item) => item.trim().replace(/['"]/g, '')); - metadata[currentKey] = items; - currentKey = null; - currentValue = ''; - } - } - } - } - - // Save the last key-value pair - if (currentKey && currentValue && !inArray) { - metadata[currentKey] = currentValue.replace(/['"]/g, ''); - } - - return metadata; - } catch (error) { - console.warn(`⚠️ Could not read metadata for ${url}:`, error.message); - return null; - } -} - -async function saveScrapedContent(scrapedPages, outputPath) { - console.log('πŸ“ Saving scraped content...'); - - // Create consolidated content for LLM training - let consolidatedContent = ''; - - for (const page of scrapedPages) { - const fileName = generateFileName(page.url); - - // Build frontmatter with original metadata - let frontmatter = `--- -title: "${page.title}" -url: "${page.url}"`; - - if (page.description) { - // Escape quotes in description - const escapedDescription = page.description.replace(/"/g, '\\"'); - frontmatter += ` -description: "${escapedDescription}"`; - } - - if (page.keywords && Array.isArray(page.keywords) && page.keywords.length > 0) { - frontmatter += ` -keywords:`; - page.keywords.forEach((keyword) => { - frontmatter += ` - - "${keyword}"`; - }); - } - - frontmatter += ` ----`; - - const mdxContent = `${frontmatter} - -# ${page.title} - -${page.content} -`; - - // Save individual file - await fs.writeFile(path.join(outputPath, `${fileName}.mdx`), mdxContent, 'utf8'); - - // Add to consolidated content with metadata - consolidatedContent += `# ${page.title}\n\nURL: ${page.url}\n`; - if (page.description) { - consolidatedContent += `Description: ${page.description}\n`; - } - if (page.keywords && page.keywords.length > 0) { - consolidatedContent += `Keywords: ${page.keywords.join(', ')}\n`; - } - consolidatedContent += `\n${page.content}\n\n---\n\n`; - } - - // Save consolidated content - await fs.writeFile(path.join(outputPath, 'sei-docs-consolidated.txt'), consolidatedContent, 'utf8'); - - // Save structured JSON - await fs.writeFile(path.join(outputPath, 'sei-docs-structured.json'), JSON.stringify(scrapedPages, null, 2), 'utf8'); - - console.log(`πŸ“„ Created consolidated text file: ${outputPath}/sei-docs-consolidated.txt`); - console.log(`πŸ“‹ Created structured JSON file: ${outputPath}/sei-docs-structured.json`); - console.log(`πŸ“ Created ${scrapedPages.length} individual .mdx files`); -} - -function generateFileName(url) { - try { - const urlObj = new URL(url); - let pathname = urlObj.pathname; - - // Remove leading/trailing slashes and replace special chars - pathname = pathname.replace(/^\/+|\/+$/g, ''); - pathname = pathname.replace(/[/\\:*?"<>|]/g, '-'); - pathname = pathname.replace(/-+/g, '-'); - - return pathname || 'index'; - } catch { - return 'page-' + Date.now(); - } -} - -async function generateUrlsFromFileStructure(baseUrl) { - const urls = new Set(); - const contentDir = './content'; - - try { - const fs = require('fs'); - - // Recursively find all .mdx files and convert to URLs - function findMdxFiles(dir, basePath = '') { - const items = fs.readdirSync(dir); - - for (const item of items) { - const fullPath = path.join(dir, item); - const stat = fs.statSync(fullPath); - - if (stat.isDirectory() && !item.startsWith('_')) { - findMdxFiles(fullPath, basePath + '/' + item); - } else if (item.endsWith('.mdx') && item !== 'index.mdx') { - const urlPath = basePath + '/' + item.replace('.mdx', ''); - urls.add(baseUrl + urlPath); - } else if (item === 'index.mdx' && basePath) { - urls.add(baseUrl + basePath); - } - } - } - - if (fs.existsSync(contentDir)) { - findMdxFiles(contentDir); - } - - console.log(`πŸ“‹ Generated ${urls.size} URLs from file structure`); - } catch (error) { - console.warn('⚠️ Could not generate URLs from file structure:', error.message); - } - - return Array.from(urls); -} - -async function startDevServer(port = 3001) { - return new Promise((resolve, reject) => { - // Start the Next.js development server on specified port - const server = spawn('npx', ['next', 'start', '--port', port.toString()], { - stdio: ['ignore', 'pipe', 'pipe'], - env: { ...process.env, PORT: port.toString() } - }); - - let serverReady = false; - - // Listen for server output to detect when it's ready - server.stdout.on('data', (data) => { - const output = data.toString(); - console.log(`πŸ“‘ Server (${port}):`, output.trim()); - - // Check if server is ready - if (output.includes('Ready in') || output.includes('ready') || output.includes(`http://localhost:${port}`)) { - if (!serverReady) { - serverReady = true; - // Wait a bit more to ensure server is fully ready - setTimeout(() => resolve(server), 3000); - } - } - }); - - server.stderr.on('data', (data) => { - const errorOutput = data.toString(); - console.error(`πŸ“‘ Server Error (${port}):`, errorOutput); - - // Don't reject on warnings, only on actual startup failures - if (errorOutput.includes('EADDRINUSE') || errorOutput.includes('Error:')) { - if (!serverReady) { - reject(new Error(`Server startup failed: ${errorOutput}`)); - } - } - }); - - server.on('error', (error) => { - reject(new Error(`Failed to start server: ${error.message}`)); - }); - - server.on('exit', (code) => { - if (!serverReady) { - reject(new Error(`Server exited with code ${code} before becoming ready`)); - } - }); - - // Timeout after 45 seconds (longer for potential build time) - setTimeout(() => { - if (!serverReady) { - server.kill(); - reject(new Error('Server startup timeout - check if port is available')); - } - }, 45000); - }); -} - -async function launchBrowser() { - const isVercel = Boolean(process.env.VERCEL || process.env.NOW_BUILDER); - let browser; - - if (!isVercel) { - const puppeteer = require('puppeteer'); - browser = await puppeteer.launch({ - headless: 'new', - protocolTimeout: 120_000, - args: [ - '--single-process', - '--no-zygote', - '--disable-gpu', - '--disable-dev-shm-usage', - '--no-sandbox', - '--disable-setuid-sandbox', - '--disable-background-networking', - '--disable-extensions' - ], - defaultViewport: { width: 1280, height: 720 } - }); - } else { - const puppeteerCore = require('puppeteer-core'); - let chromium = require('@sparticuz/chromium-min'); - chromium = chromium.default ?? chromium; - chromium.setHeadlessMode = true; - chromium.setGraphicsMode = false; - const remotePack = 'https://github.com/Sparticuz/chromium/releases/download/v137.0.1/chromium-v137.0.1-pack.x64.tar'; - const executablePath = typeof chromium.executablePath === 'function' ? await chromium.executablePath(remotePack) : await chromium.executablePath; - - browser = await puppeteerCore.launch({ - executablePath, - headless: 'shell', - protocolTimeout: 120_000, - ignoreHTTPSErrors: true, - args: [ - ...chromium.args, - '--single-process', - '--no-zygote', - '--disable-gpu', - '--disable-dev-shm-usage', - '--no-sandbox', - '--disable-setuid-sandbox', - '--disable-background-networking', - '--disable-extensions' - ], - defaultViewport: { width: 1280, height: 720 } - }); - } - - // Fatal‑error diagnostics (Rec.Β #5) - if (browser.process && browser.process()) { - browser.process().stderr.on('data', (buf) => { - const msg = buf.toString(); - if (/FATAL|OOM|zygote/i.test(msg)) { - console.error('⚠️ Chromium fatal error:', msg); - } - }); - } - - return browser; -} - -// Run the scraper -scrapeSeiDocs(); diff --git a/vercel.json b/vercel.json index 2242f622..ac1d6d36 100644 --- a/vercel.json +++ b/vercel.json @@ -6,13 +6,13 @@ "permanent": true }, { - "source": "/llms.txt", - "destination": "/_scraped-docs/llms.txt", + "source": "/_scraped-docs/llms.txt", + "destination": "/llms.txt", "permanent": true }, { - "source": "/llms-full.txt", - "destination": "/_scraped-docs/llms-full.txt", + "source": "/_scraped-docs/llms-full.txt", + "destination": "/llms-full.txt", "permanent": true } ] diff --git a/yarn.lock b/yarn.lock index 2c87113f..ff23f0a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1460,32 +1460,6 @@ dependencies: playwright "1.56.1" -"@puppeteer/browsers@2.10.13": - version "2.10.13" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.10.13.tgz#42c8b7df14e992f311ca9dca5fed3f0c2182fd17" - integrity sha512-a9Ruw3j3qlnB5a/zHRTkruppynxqaeE4H9WNj5eYGRWqw0ZauZ23f4W2ARf3hghF5doozyD+CRtt7XSYuYRI/Q== - dependencies: - debug "^4.4.3" - extract-zip "^2.0.1" - progress "^2.0.3" - proxy-agent "^6.5.0" - semver "^7.7.3" - tar-fs "^3.1.1" - yargs "^17.7.2" - -"@puppeteer/browsers@2.11.0": - version "2.11.0" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.11.0.tgz#b2dcd7cb02dd2de5909531d00e717a04bd61de73" - integrity sha512-n6oQX6mYkG8TRPuPXmbPidkUbsSRalhmaaVAQxvH1IkQy63cwsH+kOjB3e4cpCDHg0aSvsiX9bQ4s2VB6mGWUQ== - dependencies: - debug "^4.4.3" - extract-zip "^2.0.1" - progress "^2.0.3" - proxy-agent "^6.5.0" - semver "^7.7.3" - tar-fs "^3.1.1" - yargs "^17.7.2" - "@radix-ui/colors@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/colors/-/colors-3.0.0.tgz#e8a591a303c44e503bd1212cacf40a09511165e0" @@ -2290,22 +2264,6 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@sparticuz/chromium-min@^141.0.0": - version "141.0.0" - resolved "https://registry.yarnpkg.com/@sparticuz/chromium-min/-/chromium-min-141.0.0.tgz#32e284027c463a241a8394db83cea89d34bd421b" - integrity sha512-1EAR1NBrY4sa0hysDUCxCSI+9xc88/LYB3YjWFqMMu3CF82ATp8FzOeu7icwGxI02NAPcwzb0Uf1kIzsfH7Eiw== - dependencies: - follow-redirects "^1.15.11" - tar-fs "^3.1.1" - -"@sparticuz/chromium@^141.0.0": - version "141.0.0" - resolved "https://registry.yarnpkg.com/@sparticuz/chromium/-/chromium-141.0.0.tgz#c8bb81181135e622723a15efdaf1fe83af555a04" - integrity sha512-JsTp4AqgStkqKki4dUpEM0GoisAjQhsqZ1lQTNMSKK5A9pw6BbIuIvv2HVYMYzSZGyDdQNJYBPPDg2eggCkezA== - dependencies: - follow-redirects "^1.15.11" - tar-fs "^3.1.1" - "@standard-schema/spec@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" @@ -2467,11 +2425,6 @@ npm-to-yarn "^3.0.0" unist-util-visit "^5.0.0" -"@tootallnate/quickjs-emscripten@^0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" - integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA== - "@trysound/sax@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" @@ -2885,13 +2838,6 @@ dependencies: "@types/yargs-parser" "*" -"@types/yauzl@^2.9.1": - version "2.10.3" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999" - integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q== - dependencies: - "@types/node" "*" - "@typescript/vfs@^1.6.1": version "1.6.1" resolved "https://registry.yarnpkg.com/@typescript/vfs/-/vfs-1.6.1.tgz#fe7087d5a43715754f7ea9bf6e0b905176c9eebd" @@ -3007,13 +2953,6 @@ array-iterate@^2.0.0: resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-2.0.1.tgz#6efd43f8295b3fee06251d3d62ead4bd9805dd24" integrity sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg== -ast-types@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" - integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== - dependencies: - tslib "^2.0.1" - astring@^1.8.0: version "1.9.0" resolved "https://registry.yarnpkg.com/astring/-/astring-1.9.0.tgz#cc73e6062a7eb03e7d19c22d8b0b3451fd9bfeef" @@ -3049,11 +2988,6 @@ axios@1.13.4, axios@^1.12.2: form-data "^4.0.4" proxy-from-env "^1.1.0" -b4a@^1.6.4: - version "1.6.7" - resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.7.tgz#a99587d4ebbfbd5a6e3b21bdb5d5fa385767abe4" - integrity sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg== - babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -3127,49 +3061,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bare-events@^2.2.0, bare-events@^2.5.4: - version "2.5.4" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.5.4.tgz#16143d435e1ed9eafd1ab85f12b89b3357a41745" - integrity sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA== - -bare-fs@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.1.5.tgz#1d06c076e68cc8bf97010d29af9e3ac3808cdcf7" - integrity sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA== - dependencies: - bare-events "^2.5.4" - bare-path "^3.0.0" - bare-stream "^2.6.4" - -bare-os@^3.0.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.6.1.tgz#9921f6f59edbe81afa9f56910658422c0f4858d4" - integrity sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g== - -bare-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178" - integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw== - dependencies: - bare-os "^3.0.1" - -bare-stream@^2.6.4: - version "2.6.5" - resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.6.5.tgz#bba8e879674c4c27f7e27805df005c15d7a2ca07" - integrity sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA== - dependencies: - streamx "^2.21.0" - baseline-browser-mapping@^2.8.3, baseline-browser-mapping@^2.8.9, baseline-browser-mapping@^2.9.0, baseline-browser-mapping@^2.9.14: version "2.9.19" resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz#3e508c43c46d961eb4d7d2e5b8d1dd0f9ee4f488" integrity sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg== -basic-ftp@^5.0.2: - version "5.0.5" - resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.5.tgz#14a474f5fffecca1f4f406f1c26b18f800225ac0" - integrity sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg== - better-react-mathjax@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/better-react-mathjax/-/better-react-mathjax-2.3.0.tgz#d9a29b2b9eae873e60c0ca8042d7ecb94e2aa297" @@ -3243,11 +3139,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== - buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -3353,22 +3244,6 @@ chevrotain@~11.0.3: "@chevrotain/utils" "11.0.3" lodash-es "4.17.21" -chromium-bidi@11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-11.0.0.tgz#193433d0722095abca0cada2fa0c5111b447bea3" - integrity sha512-cM3DI+OOb89T3wO8cpPSro80Q9eKYJ7hGVXoGS3GkDPxnYSqiv+6xwpIf6XERyJ9Tdsl09hmNmY94BkgZdVekw== - dependencies: - mitt "^3.0.1" - zod "^3.24.1" - -chromium-bidi@12.0.1: - version "12.0.1" - resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-12.0.1.tgz#3edb1420ab5a52004c10c223b928622c128b4f27" - integrity sha512-fGg+6jr0xjQhzpy5N4ErZxQ4wF7KLEvhGZXD6EgvZKDhu7iOhZXnZhcDxPJDcwTcrD48NPzOCo84RP2lv3Z+Cg== - dependencies: - mitt "^3.0.1" - zod "^3.24.1" - ci-info@^3.2.0: version "3.9.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" @@ -3557,16 +3432,6 @@ cose-base@^2.2.0: dependencies: layout-base "^2.0.0" -cosmiconfig@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" - integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== - dependencies: - env-paths "^2.2.1" - import-fresh "^3.3.0" - js-yaml "^4.1.0" - parse-json "^5.2.0" - create-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" @@ -4013,11 +3878,6 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== -data-uri-to-buffer@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz#8a58bb67384b261a38ef18bea1810cb01badd28b" - integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw== - data-urls@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-7.0.0.tgz#6dce8b63226a1ecfdd907ce18a8ccfb1eee506d3" @@ -4050,7 +3910,7 @@ debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4, debug@^4.4.0: dependencies: ms "^2.1.3" -debug@^4.3.1, debug@^4.4.3: +debug@^4.3.1: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== @@ -4079,15 +3939,6 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -degenerator@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5" - integrity sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ== - dependencies: - ast-types "^0.13.4" - escodegen "^2.1.0" - esprima "^4.0.1" - delaunator@5: version "5.0.1" resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" @@ -4127,16 +3978,6 @@ devlop@^1.0.0, devlop@^1.1.0: dependencies: dequal "^2.0.0" -devtools-protocol@0.0.1521046: - version "0.0.1521046" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1521046.tgz#918e6175ea83100fefcb2b78779f15a77aa8a41b" - integrity sha512-vhE6eymDQSKWUXwwA37NtTTVEzjtGVfDr3pRbsWEQ5onH/Snp2c+2xZHWJJawG/0hCCJLRGt4xVtEVUVILol4w== - -devtools-protocol@0.0.1534754: - version "0.0.1534754" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1534754.tgz#75fb0496ff133d8d7e73d2e49600b37fcb4f46a9" - integrity sha512-26T91cV5dbOYnXdJi5qQHoTtUoNEqwkHcAyu/IKtjIAxiEqPMrDiRkDOPWVsGfNZGmlQVHQbZRSjD8sxagWVsQ== - diff-sequences@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" @@ -4243,11 +4084,6 @@ entities@^6.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== -env-paths@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - environment@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" @@ -4353,32 +4189,16 @@ escape-string-regexp@^5.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== -escodegen@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" - integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionalDependencies: - source-map "~0.6.1" - esm@^3.2.25: version "3.2.25" resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - estree-util-attach-comments@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz#344bde6a64c8a31d15231e5ee9e297566a691c2d" @@ -4445,11 +4265,6 @@ estree-walker@^3.0.0: dependencies: "@types/estree" "^1.0.0" -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - eventemitter3@5.0.1, eventemitter3@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" @@ -4511,27 +4326,11 @@ extend@^3.0.0: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -extract-zip@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" - integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== - dependencies: - debug "^4.1.1" - get-stream "^5.1.0" - yauzl "^2.10.0" - optionalDependencies: - "@types/yauzl" "^2.9.1" - fast-copy@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" integrity sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ== -fast-fifo@^1.2.0, fast-fifo@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" - integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== - fast-glob@^3.2.12, fast-glob@^3.3.2, fast-glob@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" @@ -4574,13 +4373,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== - dependencies: - pend "~1.2.0" - fdir@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" @@ -4609,11 +4401,6 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -follow-redirects@^1.15.11: - version "1.15.11" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" - integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== - follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" @@ -4721,13 +4508,6 @@ get-proto@^1.0.1: dunder-proto "^1.0.1" es-object-atoms "^1.0.0" -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" @@ -4745,15 +4525,6 @@ get-tsconfig@^4.7.5: dependencies: resolve-pkg-maps "^1.0.0" -get-uri@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.4.tgz#6daaee9e12f9759e19e55ba313956883ef50e0a7" - integrity sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ== - dependencies: - basic-ftp "^5.0.2" - data-uri-to-buffer "^6.0.2" - debug "^4.3.4" - github-slugger@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-2.0.0.tgz#52cf2f9279a21eb6c59dd385b410f0c0adda8f1a" @@ -5042,7 +4813,7 @@ html-void-elements@^3.0.0: resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== -http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1, http-proxy-agent@^7.0.2: +http-proxy-agent@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== @@ -5085,14 +4856,6 @@ ignore@^7.0.3: resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.3.tgz#397ef9315dfe0595671eefe8b633fec6943ab733" integrity sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA== -import-fresh@^3.3.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" - integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - import-local@^3.0.2: version "3.2.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" @@ -5134,14 +4897,6 @@ internmap@^1.0.0: resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== -ip-address@^9.0.5: - version "9.0.5" - resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" - integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== - dependencies: - jsbn "1.1.0" - sprintf-js "^1.1.3" - is-alphabetical@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b" @@ -5719,18 +5474,13 @@ js-yaml@3.14.2, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@4.1.1, js-yaml@^4.1.0: +js-yaml@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== dependencies: argparse "^2.0.1" -jsbn@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" - integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== - jsdom@^28.0.0: version "28.0.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-28.0.0.tgz#53d5aff0b940e1d2ff6310c9e4c35fe45979ecbf" @@ -6007,11 +5757,6 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^7.14.1: - version "7.18.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" - integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== - magic-string@^0.30.21: version "0.30.21" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" @@ -6788,11 +6533,6 @@ minimist@^1.2.6, minimist@^1.2.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -mitt@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" - integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== - mj-context-menu@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz#a043c5282bf7e1cf3821de07b13525ca6f85aa69" @@ -6833,11 +6573,6 @@ negotiator@^1.0.0: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== -netmask@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" - integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== - next-sitemap@^4.0.4: version "4.2.3" resolved "https://registry.yarnpkg.com/next-sitemap/-/next-sitemap-4.2.3.tgz#5db3f650351a51e84b9fd6b58c5af2f9257b5058" @@ -7092,28 +6827,6 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pac-proxy-agent@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz#9cfaf33ff25da36f6147a20844230ec92c06e5df" - integrity sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA== - dependencies: - "@tootallnate/quickjs-emscripten" "^0.23.0" - agent-base "^7.1.2" - debug "^4.3.4" - get-uri "^6.0.1" - http-proxy-agent "^7.0.0" - https-proxy-agent "^7.0.6" - pac-resolver "^7.0.1" - socks-proxy-agent "^8.0.5" - -pac-resolver@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6" - integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg== - dependencies: - degenerator "^5.0.0" - netmask "^2.0.2" - package-manager-detector@^0.2.8: version "0.2.11" resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-0.2.11.tgz#3af0b34f99d86d24af0a0620603d2e1180d05c9c" @@ -7132,13 +6845,6 @@ pagefind@^1.3.0: "@pagefind/linux-x64" "1.3.0" "@pagefind/windows-x64" "1.3.0" -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - parse-entities@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.2.tgz#61d46f5ed28e4ee62e9ddc43d6b010188443f159" @@ -7238,11 +6944,6 @@ pathe@^2.0.1, pathe@^2.0.3: resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== - picocolors@^1.0.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -7592,11 +7293,6 @@ pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" -progress@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -7615,20 +7311,6 @@ property-information@^7.0.0: resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.0.0.tgz#3508a6d6b0b8eb3ca6eb2c6623b164d2ed2ab112" integrity sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg== -proxy-agent@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.5.0.tgz#9e49acba8e4ee234aacb539f89ed9c23d02f232d" - integrity sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A== - dependencies: - agent-base "^7.1.2" - debug "^4.3.4" - http-proxy-agent "^7.0.1" - https-proxy-agent "^7.0.6" - lru-cache "^7.14.1" - pac-proxy-agent "^7.1.0" - proxy-from-env "^1.1.0" - socks-proxy-agent "^8.0.5" - proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -7647,44 +7329,6 @@ punycode@^2.3.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -puppeteer-core@24.33.1: - version "24.33.1" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.33.1.tgz#80b9d79dd0597fd2b1de265aae4dd0d95df81c66" - integrity sha512-MZjFLeGMBFbSkc1xKfcv6hjFlfNi1bmQly++HyqxGPYzLIMY0mSYyjqkAzT1PtomTYHq7SEonciIKkeyHExA1g== - dependencies: - "@puppeteer/browsers" "2.11.0" - chromium-bidi "12.0.1" - debug "^4.4.3" - devtools-protocol "0.0.1534754" - typed-query-selector "^2.12.0" - webdriver-bidi-protocol "0.3.10" - ws "^8.18.3" - -puppeteer-core@^24.31.0: - version "24.31.0" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.31.0.tgz#a00daa971fb6a9f722264afda7290dd0bfd566f0" - integrity sha512-pnAohhSZipWQoFpXuGV7xCZfaGhqcBR9C4pVrU0QSrcMi7tQMH9J9lDBqBvyMAHQqe8HCARuREqFuVKRQOgTvg== - dependencies: - "@puppeteer/browsers" "2.10.13" - chromium-bidi "11.0.0" - debug "^4.4.3" - devtools-protocol "0.0.1521046" - typed-query-selector "^2.12.0" - webdriver-bidi-protocol "0.3.9" - ws "^8.18.3" - -puppeteer@^24.31.0: - version "24.33.1" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-24.33.1.tgz#c84c9545633bc731b92caead463e77928dcf183e" - integrity sha512-2KiSIXk+zFzmYsScv+hx/I3TODFGPcNpyJsWMQk1EQ2y8KZ2X6225/NingyqYxekzceSUnq5qX39dUezVDZ9EQ== - dependencies: - "@puppeteer/browsers" "2.11.0" - chromium-bidi "12.0.1" - cosmiconfig "^9.0.0" - devtools-protocol "0.0.1534754" - puppeteer-core "24.33.1" - typed-query-selector "^2.12.0" - pure-rand@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" @@ -8052,11 +7696,6 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - resolve-from@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" @@ -8322,28 +7961,6 @@ slice-ansi@^7.1.0: ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -socks-proxy-agent@^8.0.5: - version "8.0.5" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" - integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== - dependencies: - agent-base "^7.1.2" - debug "^4.3.4" - socks "^2.8.3" - -socks@^2.8.3: - version "2.8.5" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.5.tgz#bfe18f5ead1efc93f5ec90c79fa8bdccbcee2e64" - integrity sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww== - dependencies: - ip-address "^9.0.5" - smart-buffer "^4.2.0" - sonic-boom@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" @@ -8377,7 +7994,7 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -8406,11 +8023,6 @@ split2@^4.0.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== -sprintf-js@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" - integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -8423,16 +8035,6 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" -streamx@^2.15.0, streamx@^2.21.0: - version "2.22.1" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.22.1.tgz#c97cbb0ce18da4f4db5a971dc9ab68ff5dc7f5a5" - integrity sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA== - dependencies: - fast-fifo "^1.3.2" - text-decoder "^1.1.0" - optionalDependencies: - bare-events "^2.2.0" - string-argv@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" @@ -8605,26 +8207,6 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar-fs@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.1.1.tgz#4f164e59fb60f103d472360731e8c6bb4a7fe9ef" - integrity sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg== - dependencies: - pump "^3.0.0" - tar-stream "^3.1.5" - optionalDependencies: - bare-fs "^4.0.1" - bare-path "^3.0.0" - -tar-stream@^3.1.5: - version "3.1.7" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" - integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== - dependencies: - b4a "^1.6.4" - fast-fifo "^1.2.0" - streamx "^2.15.0" - terser@^5.31.0: version "5.44.0" resolved "https://registry.yarnpkg.com/terser/-/terser-5.44.0.tgz#ebefb8e5b8579d93111bfdfc39d2cf63879f4a82" @@ -8644,13 +8226,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-decoder@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" - integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA== - dependencies: - b4a "^1.6.4" - third-party-capital@1.0.20: version "1.0.20" resolved "https://registry.yarnpkg.com/third-party-capital/-/third-party-capital-1.0.20.tgz#e218a929a35bf4d2245da9addb8ab978d2f41685" @@ -8744,7 +8319,7 @@ ts-morph@^27.0.0: "@ts-morph/common" "~0.28.1" code-block-writer "^13.0.3" -tslib@2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0: +tslib@2, tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -8787,11 +8362,6 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -typed-query-selector@^2.12.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/typed-query-selector/-/typed-query-selector-2.12.0.tgz#92b65dbc0a42655fccf4aeb1a08b1dddce8af5f2" - integrity sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg== - typescript@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" @@ -9097,16 +8667,6 @@ web-streams-polyfill@^3.0.3: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== -webdriver-bidi-protocol@0.3.10: - version "0.3.10" - resolved "https://registry.yarnpkg.com/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.10.tgz#437405564ff7e200371468f4f1eba1ff5537e119" - integrity sha512-5LAE43jAVLOhB/QqX4bwSiv0Hg1HBfMmOuwBSXHdvg4GMGu9Y0lIq7p4R/yySu6w74WmaR4GM4H9t2IwLW7hgw== - -webdriver-bidi-protocol@0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.9.tgz#89abf021f2a557a2dd81772f9ce7172b01f8a0f0" - integrity sha512-uIYvlRQ0PwtZR1EzHlTMol1G0lAlmOe6wPykF9a77AK3bkpvZHzIVxRE2ThOx5vjy2zISe0zhwf5rzuUfbo1PQ== - webidl-conversions@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-8.0.1.tgz#0657e571fe6f06fcb15ca50ed1fdbcb495cd1686" @@ -9169,7 +8729,7 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@8.18.3, ws@8.19.0, ws@^8.18.3: +ws@8.18.3, ws@8.19.0: version "8.19.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.19.0.tgz#ddc2bdfa5b9ad860204f5a72a4863a8895fd8c8b" integrity sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg== @@ -9214,7 +8774,7 @@ yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@17.7.2, yargs@^17.3.1, yargs@^17.7.2: +yargs@17.7.2, yargs@^17.3.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -9227,24 +8787,11 @@ yargs@17.7.2, yargs@^17.3.1, yargs@^17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" -yauzl@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zod@^3.24.1: - version "3.25.67" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.67.tgz#62987e4078e2ab0f63b491ef0c4f33df24236da8" - integrity sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw== - zod@^4.1.12: version "4.2.1" resolved "https://registry.yarnpkg.com/zod/-/zod-4.2.1.tgz#07f0388c7edbfd5f5a2466181cb4adf5b5dbd57b"