Spaces:
Sleeping
Sleeping
Jainish1808 commited on
Commit Β·
4000a4c
1
Parent(s): 7094dce
Initial commit - Socratic Lens
Browse files- .env.example +4 -0
- .gitignore +35 -33
- Dockerfile +48 -0
- README.md +51 -23
- README_SOCRATIC.md +38 -0
- next.config.ts +6 -1
- package-lock.json +1574 -46
- package.json +8 -1
- src/app/api/analyze/route.ts +86 -0
- src/app/globals.css +301 -16
- src/app/layout.tsx +4 -3
- src/app/page.tsx +298 -61
- src/components/AskQuestionModal.tsx +161 -0
- src/components/CameraModal.tsx +203 -0
- src/components/QuizModal.tsx +368 -0
- src/components/WikipediaCard.tsx +284 -0
- src/prompts/concept_essay.md +36 -0
- src/prompts/system_prompt.md +142 -0
.env.example
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Socratic Lens Environment Variables
|
| 2 |
+
|
| 3 |
+
# Get your API key from: https://aistudio.google.com/app/apikey
|
| 4 |
+
GEMINI_API_KEY=your_gemini_api_key_here
|
.gitignore
CHANGED
|
@@ -1,41 +1,43 @@
|
|
| 1 |
-
#
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
.
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
# misc
|
| 24 |
-
.DS_Store
|
| 25 |
-
*.pem
|
| 26 |
-
|
| 27 |
-
# debug
|
| 28 |
npm-debug.log*
|
| 29 |
yarn-debug.log*
|
| 30 |
yarn-error.log*
|
| 31 |
-
.pnpm-debug.log*
|
| 32 |
|
| 33 |
-
#
|
| 34 |
-
.
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
-
#
|
| 37 |
-
.
|
|
|
|
| 38 |
|
| 39 |
-
#
|
| 40 |
*.tsbuildinfo
|
| 41 |
next-env.d.ts
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dependencies
|
| 2 |
+
node_modules
|
| 3 |
+
.pnp
|
| 4 |
+
.pnp.js
|
| 5 |
+
|
| 6 |
+
# Build outputs
|
| 7 |
+
.next
|
| 8 |
+
out
|
| 9 |
+
build
|
| 10 |
+
dist
|
| 11 |
+
|
| 12 |
+
# Testing
|
| 13 |
+
coverage
|
| 14 |
+
|
| 15 |
+
# Environment files
|
| 16 |
+
.env
|
| 17 |
+
.env.local
|
| 18 |
+
.env.development.local
|
| 19 |
+
.env.test.local
|
| 20 |
+
.env.production.local
|
| 21 |
+
|
| 22 |
+
# Debug logs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
npm-debug.log*
|
| 24 |
yarn-debug.log*
|
| 25 |
yarn-error.log*
|
|
|
|
| 26 |
|
| 27 |
+
# IDE
|
| 28 |
+
.vscode
|
| 29 |
+
.idea
|
| 30 |
+
*.swp
|
| 31 |
+
*.swo
|
| 32 |
|
| 33 |
+
# OS
|
| 34 |
+
.DS_Store
|
| 35 |
+
Thumbs.db
|
| 36 |
|
| 37 |
+
# TypeScript
|
| 38 |
*.tsbuildinfo
|
| 39 |
next-env.d.ts
|
| 40 |
+
|
| 41 |
+
# Misc
|
| 42 |
+
*.log
|
| 43 |
+
.vercel
|
Dockerfile
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM node:20-alpine AS base
|
| 2 |
+
|
| 3 |
+
# Install dependencies only when needed
|
| 4 |
+
FROM base AS deps
|
| 5 |
+
RUN apk add --no-cache libc6-compat
|
| 6 |
+
WORKDIR /app
|
| 7 |
+
|
| 8 |
+
# Copy package files
|
| 9 |
+
COPY package.json package-lock.json* ./
|
| 10 |
+
RUN npm ci
|
| 11 |
+
|
| 12 |
+
# Rebuild the source code only when needed
|
| 13 |
+
FROM base AS builder
|
| 14 |
+
WORKDIR /app
|
| 15 |
+
COPY --from=deps /app/node_modules ./node_modules
|
| 16 |
+
COPY . .
|
| 17 |
+
|
| 18 |
+
# Build the application
|
| 19 |
+
ENV NEXT_TELEMETRY_DISABLED=1
|
| 20 |
+
RUN npm run build
|
| 21 |
+
|
| 22 |
+
# Production image
|
| 23 |
+
FROM base AS runner
|
| 24 |
+
WORKDIR /app
|
| 25 |
+
|
| 26 |
+
ENV NODE_ENV=production
|
| 27 |
+
ENV NEXT_TELEMETRY_DISABLED=1
|
| 28 |
+
|
| 29 |
+
RUN addgroup --system --gid 1001 nodejs
|
| 30 |
+
RUN adduser --system --uid 1001 nextjs
|
| 31 |
+
|
| 32 |
+
COPY --from=builder /app/public ./public
|
| 33 |
+
|
| 34 |
+
# Set the correct permission for prerender cache
|
| 35 |
+
RUN mkdir .next
|
| 36 |
+
RUN chown nextjs:nodejs .next
|
| 37 |
+
|
| 38 |
+
# Automatically leverage output traces to reduce image size
|
| 39 |
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
| 40 |
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
| 41 |
+
|
| 42 |
+
USER nextjs
|
| 43 |
+
|
| 44 |
+
EXPOSE 3000
|
| 45 |
+
ENV PORT=3000
|
| 46 |
+
ENV HOSTNAME="0.0.0.0"
|
| 47 |
+
|
| 48 |
+
CMD ["node", "server.js"]
|
README.md
CHANGED
|
@@ -1,36 +1,64 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
|
| 4 |
|
| 5 |
-
|
| 6 |
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
```
|
| 16 |
|
| 17 |
-
|
| 18 |
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
-
|
| 22 |
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
-
|
| 28 |
-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
| 29 |
|
| 30 |
-
|
| 31 |
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
-
|
| 35 |
|
| 36 |
-
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Socratic Lens
|
| 3 |
+
emoji: π
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: indigo
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
license: mit
|
| 9 |
+
---
|
| 10 |
|
| 11 |
+
# π Socratic Lens
|
| 12 |
|
| 13 |
+
An AI-powered educational companion that analyzes images and documents to create beautiful, structured learning summaries.
|
| 14 |
|
| 15 |
+
## Features
|
| 16 |
+
|
| 17 |
+
- π **Image & Document Analysis** - Upload photos or PDFs of textbook pages
|
| 18 |
+
- π· **Camera Capture** - Take photos directly from your device
|
| 19 |
+
- π **Wikipedia Integration** - Auto-fetches related Wikipedia articles
|
| 20 |
+
- π¬ **Ask Questions** - Interactive Q&A about the analyzed content
|
| 21 |
+
- π **Quiz Me** - Generate customizable quizzes (MCQ/Written)
|
| 22 |
+
- π¨ **Beautiful UI** - Clean, minimal design with dark mode support
|
|
|
|
| 23 |
|
| 24 |
+
## Tech Stack
|
| 25 |
|
| 26 |
+
- **Framework**: Next.js 16 (App Router)
|
| 27 |
+
- **AI**: Google Gemini 2.5 Flash
|
| 28 |
+
- **Styling**: Tailwind CSS
|
| 29 |
+
- **Language**: TypeScript
|
| 30 |
|
| 31 |
+
## Environment Variables
|
| 32 |
|
| 33 |
+
Set the following in your Hugging Face Space settings:
|
| 34 |
+
|
| 35 |
+
```
|
| 36 |
+
GEMINI_API_KEY=your_google_gemini_api_key
|
| 37 |
+
```
|
| 38 |
|
| 39 |
+
## Local Development
|
| 40 |
+
|
| 41 |
+
```bash
|
| 42 |
+
# Install dependencies
|
| 43 |
+
npm install
|
| 44 |
+
|
| 45 |
+
# Set up environment
|
| 46 |
+
cp .env.example .env.local
|
| 47 |
+
# Add your GEMINI_API_KEY to .env.local
|
| 48 |
+
|
| 49 |
+
# Run development server
|
| 50 |
+
npm run dev
|
| 51 |
+
```
|
| 52 |
|
| 53 |
+
## Deployment
|
|
|
|
| 54 |
|
| 55 |
+
This app is configured for deployment on Hugging Face Spaces using Docker.
|
| 56 |
|
| 57 |
+
1. Create a new Space on Hugging Face
|
| 58 |
+
2. Select "Docker" as the SDK
|
| 59 |
+
3. Push this repository to the Space
|
| 60 |
+
4. Add `GEMINI_API_KEY` in Space Settings > Repository Secrets
|
| 61 |
|
| 62 |
+
## License
|
| 63 |
|
| 64 |
+
MIT
|
README_SOCRATIC.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Socratic Lens - Setup Guide
|
| 2 |
+
|
| 3 |
+
This project is a Next.js application that uses Google's Gemini API to function as an "Ethical Tutor" or "Socratic Lens". It features a beautiful "Pixel OS" aesthetic and implements the logic defined in your prompt.
|
| 4 |
+
|
| 5 |
+
## Prerequisites
|
| 6 |
+
1. **Google Gemini API Key**: You need an API key. Get it from [Google AI Studio](https://aistudio.google.com/).
|
| 7 |
+
|
| 8 |
+
## Quick Start
|
| 9 |
+
|
| 10 |
+
### 1. Configure API Key
|
| 11 |
+
Create a new file named `.env.local` in the `socratic-lens` folder. Add your API key:
|
| 12 |
+
|
| 13 |
+
```bash
|
| 14 |
+
# In /home/ig0034/Documents/Task_2_24_12_2025/socratic-lens/.env.local
|
| 15 |
+
GEMINI_API_KEY=your_actual_api_key_here
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
### 2. Run the Development Server
|
| 19 |
+
Open your terminal in the `socratic-lens` directory and run:
|
| 20 |
+
|
| 21 |
+
```bash
|
| 22 |
+
cd socratic-lens
|
| 23 |
+
npm run dev
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
### 3. Open in Browser
|
| 27 |
+
Visit [http://localhost:3000](http://localhost:3000).
|
| 28 |
+
|
| 29 |
+
## Project Structure
|
| 30 |
+
* **`src/app/page.tsx`**: The main frontend logic (Upload UI + Result Renderer).
|
| 31 |
+
* **`src/app/api/analyze/route.ts`**: The backend API that connects to Gemini.
|
| 32 |
+
* **`src/prompts/system_prompt.md`**: The brain of the AI (Ethical Tutor Persona).
|
| 33 |
+
* **`src/app/globals.css`**: Tailwind v4 + Custom styles for the Pixel look.
|
| 34 |
+
|
| 35 |
+
## Usage
|
| 36 |
+
1. **Upload an Image**: Take a screenshot of a math problem or a complex paragraph.
|
| 37 |
+
2. **Click Analyze**: The AI will process it using the "Socratic Lens" rules.
|
| 38 |
+
3. **Learn**: See the beautiful, structured output that guides you without cheating.
|
next.config.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
| 1 |
import type { NextConfig } from "next";
|
| 2 |
|
| 3 |
const nextConfig: NextConfig = {
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
};
|
| 6 |
|
| 7 |
export default nextConfig;
|
|
|
|
| 1 |
import type { NextConfig } from "next";
|
| 2 |
|
| 3 |
const nextConfig: NextConfig = {
|
| 4 |
+
output: 'standalone',
|
| 5 |
+
experimental: {
|
| 6 |
+
serverActions: {
|
| 7 |
+
bodySizeLimit: '10mb',
|
| 8 |
+
},
|
| 9 |
+
},
|
| 10 |
};
|
| 11 |
|
| 12 |
export default nextConfig;
|
package-lock.json
CHANGED
|
@@ -8,9 +8,16 @@
|
|
| 8 |
"name": "socratic-lens",
|
| 9 |
"version": "0.1.0",
|
| 10 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
| 11 |
"next": "16.1.1",
|
|
|
|
| 12 |
"react": "19.2.3",
|
| 13 |
-
"react-dom": "19.2.3"
|
|
|
|
|
|
|
|
|
|
| 14 |
},
|
| 15 |
"devDependencies": {
|
| 16 |
"@tailwindcss/postcss": "^4",
|
|
@@ -454,6 +461,15 @@
|
|
| 454 |
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
| 455 |
}
|
| 456 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 457 |
"node_modules/@humanfs/core": {
|
| 458 |
"version": "0.19.1",
|
| 459 |
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
|
@@ -1525,13 +1541,39 @@
|
|
| 1525 |
"tslib": "^2.4.0"
|
| 1526 |
}
|
| 1527 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1528 |
"node_modules/@types/estree": {
|
| 1529 |
"version": "1.0.8",
|
| 1530 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
| 1531 |
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
| 1532 |
-
"dev": true,
|
| 1533 |
"license": "MIT"
|
| 1534 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1535 |
"node_modules/@types/json-schema": {
|
| 1536 |
"version": "7.0.15",
|
| 1537 |
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
|
@@ -1546,6 +1588,21 @@
|
|
| 1546 |
"dev": true,
|
| 1547 |
"license": "MIT"
|
| 1548 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1549 |
"node_modules/@types/node": {
|
| 1550 |
"version": "20.19.27",
|
| 1551 |
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.27.tgz",
|
|
@@ -1560,7 +1617,6 @@
|
|
| 1560 |
"version": "19.2.7",
|
| 1561 |
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
|
| 1562 |
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
|
| 1563 |
-
"dev": true,
|
| 1564 |
"license": "MIT",
|
| 1565 |
"peer": true,
|
| 1566 |
"dependencies": {
|
|
@@ -1577,6 +1633,12 @@
|
|
| 1577 |
"@types/react": "^19.2.0"
|
| 1578 |
}
|
| 1579 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1580 |
"node_modules/@typescript-eslint/eslint-plugin": {
|
| 1581 |
"version": "8.50.1",
|
| 1582 |
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.1.tgz",
|
|
@@ -1847,6 +1909,12 @@
|
|
| 1847 |
"url": "https://opencollective.com/typescript-eslint"
|
| 1848 |
}
|
| 1849 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1850 |
"node_modules/@unrs/resolver-binding-android-arm-eabi": {
|
| 1851 |
"version": "1.11.1",
|
| 1852 |
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
|
|
@@ -2403,6 +2471,16 @@
|
|
| 2403 |
"node": ">= 0.4"
|
| 2404 |
}
|
| 2405 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2406 |
"node_modules/balanced-match": {
|
| 2407 |
"version": "1.0.2",
|
| 2408 |
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
|
@@ -2558,6 +2636,16 @@
|
|
| 2558 |
],
|
| 2559 |
"license": "CC-BY-4.0"
|
| 2560 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2561 |
"node_modules/chalk": {
|
| 2562 |
"version": "4.1.2",
|
| 2563 |
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
@@ -2575,12 +2663,61 @@
|
|
| 2575 |
"url": "https://github.com/chalk/chalk?sponsor=1"
|
| 2576 |
}
|
| 2577 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2578 |
"node_modules/client-only": {
|
| 2579 |
"version": "0.0.1",
|
| 2580 |
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
| 2581 |
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
| 2582 |
"license": "MIT"
|
| 2583 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2584 |
"node_modules/color-convert": {
|
| 2585 |
"version": "2.0.1",
|
| 2586 |
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
@@ -2601,6 +2738,16 @@
|
|
| 2601 |
"dev": true,
|
| 2602 |
"license": "MIT"
|
| 2603 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2604 |
"node_modules/concat-map": {
|
| 2605 |
"version": "0.0.1",
|
| 2606 |
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
@@ -2634,7 +2781,6 @@
|
|
| 2634 |
"version": "3.2.3",
|
| 2635 |
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
| 2636 |
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
| 2637 |
-
"dev": true,
|
| 2638 |
"license": "MIT"
|
| 2639 |
},
|
| 2640 |
"node_modules/damerau-levenshtein": {
|
|
@@ -2702,7 +2848,6 @@
|
|
| 2702 |
"version": "4.4.3",
|
| 2703 |
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
| 2704 |
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
| 2705 |
-
"dev": true,
|
| 2706 |
"license": "MIT",
|
| 2707 |
"dependencies": {
|
| 2708 |
"ms": "^2.1.3"
|
|
@@ -2716,6 +2861,19 @@
|
|
| 2716 |
}
|
| 2717 |
}
|
| 2718 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2719 |
"node_modules/deep-is": {
|
| 2720 |
"version": "0.1.4",
|
| 2721 |
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
|
@@ -2759,6 +2917,15 @@
|
|
| 2759 |
"url": "https://github.com/sponsors/ljharb"
|
| 2760 |
}
|
| 2761 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2762 |
"node_modules/detect-libc": {
|
| 2763 |
"version": "2.1.2",
|
| 2764 |
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
|
@@ -2769,6 +2936,19 @@
|
|
| 2769 |
"node": ">=8"
|
| 2770 |
}
|
| 2771 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2772 |
"node_modules/doctrine": {
|
| 2773 |
"version": "2.1.0",
|
| 2774 |
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
|
@@ -3217,6 +3397,7 @@
|
|
| 3217 |
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
|
| 3218 |
"dev": true,
|
| 3219 |
"license": "MIT",
|
|
|
|
| 3220 |
"dependencies": {
|
| 3221 |
"@rtsao/scc": "^1.1.0",
|
| 3222 |
"array-includes": "^3.1.9",
|
|
@@ -3440,6 +3621,16 @@
|
|
| 3440 |
"node": ">=4.0"
|
| 3441 |
}
|
| 3442 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3443 |
"node_modules/esutils": {
|
| 3444 |
"version": "2.0.3",
|
| 3445 |
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
|
@@ -3450,6 +3641,12 @@
|
|
| 3450 |
"node": ">=0.10.0"
|
| 3451 |
}
|
| 3452 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3453 |
"node_modules/fast-deep-equal": {
|
| 3454 |
"version": "3.1.3",
|
| 3455 |
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
@@ -3879,6 +4076,46 @@
|
|
| 3879 |
"node": ">= 0.4"
|
| 3880 |
}
|
| 3881 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3882 |
"node_modules/hermes-estree": {
|
| 3883 |
"version": "0.25.1",
|
| 3884 |
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
|
|
@@ -3896,6 +4133,16 @@
|
|
| 3896 |
"hermes-estree": "0.25.1"
|
| 3897 |
}
|
| 3898 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3899 |
"node_modules/ignore": {
|
| 3900 |
"version": "5.3.2",
|
| 3901 |
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
|
@@ -3933,6 +4180,12 @@
|
|
| 3933 |
"node": ">=0.8.19"
|
| 3934 |
}
|
| 3935 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3936 |
"node_modules/internal-slot": {
|
| 3937 |
"version": "1.1.0",
|
| 3938 |
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
|
@@ -3948,6 +4201,30 @@
|
|
| 3948 |
"node": ">= 0.4"
|
| 3949 |
}
|
| 3950 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3951 |
"node_modules/is-array-buffer": {
|
| 3952 |
"version": "3.0.5",
|
| 3953 |
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
|
@@ -4106,6 +4383,16 @@
|
|
| 4106 |
"url": "https://github.com/sponsors/ljharb"
|
| 4107 |
}
|
| 4108 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4109 |
"node_modules/is-extglob": {
|
| 4110 |
"version": "2.1.1",
|
| 4111 |
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
|
@@ -4165,6 +4452,16 @@
|
|
| 4165 |
"node": ">=0.10.0"
|
| 4166 |
}
|
| 4167 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4168 |
"node_modules/is-map": {
|
| 4169 |
"version": "2.0.3",
|
| 4170 |
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
|
|
@@ -4218,6 +4515,18 @@
|
|
| 4218 |
"url": "https://github.com/sponsors/ljharb"
|
| 4219 |
}
|
| 4220 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4221 |
"node_modules/is-regex": {
|
| 4222 |
"version": "1.2.1",
|
| 4223 |
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
|
@@ -4816,6 +5125,16 @@
|
|
| 4816 |
"dev": true,
|
| 4817 |
"license": "MIT"
|
| 4818 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4819 |
"node_modules/loose-envify": {
|
| 4820 |
"version": "1.4.0",
|
| 4821 |
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
|
@@ -4839,6 +5158,15 @@
|
|
| 4839 |
"yallist": "^3.0.2"
|
| 4840 |
}
|
| 4841 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4842 |
"node_modules/magic-string": {
|
| 4843 |
"version": "0.30.21",
|
| 4844 |
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
|
@@ -4849,6 +5177,16 @@
|
|
| 4849 |
"@jridgewell/sourcemap-codec": "^1.5.5"
|
| 4850 |
}
|
| 4851 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4852 |
"node_modules/math-intrinsics": {
|
| 4853 |
"version": "1.1.0",
|
| 4854 |
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
|
@@ -4859,64 +5197,908 @@
|
|
| 4859 |
"node": ">= 0.4"
|
| 4860 |
}
|
| 4861 |
},
|
| 4862 |
-
"node_modules/
|
| 4863 |
-
"version": "
|
| 4864 |
-
"resolved": "https://registry.npmjs.org/
|
| 4865 |
-
"integrity": "sha512-
|
| 4866 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4867 |
"license": "MIT",
|
| 4868 |
"engines": {
|
| 4869 |
-
"node": ">=
|
|
|
|
|
|
|
|
|
|
| 4870 |
}
|
| 4871 |
},
|
| 4872 |
-
"node_modules/
|
| 4873 |
-
"version": "
|
| 4874 |
-
"resolved": "https://registry.npmjs.org/
|
| 4875 |
-
"integrity": "sha512-
|
| 4876 |
-
"dev": true,
|
| 4877 |
"license": "MIT",
|
| 4878 |
"dependencies": {
|
| 4879 |
-
"
|
| 4880 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4881 |
},
|
| 4882 |
-
"
|
| 4883 |
-
"
|
|
|
|
| 4884 |
}
|
| 4885 |
},
|
| 4886 |
-
"node_modules/
|
| 4887 |
-
"version": "3.1.
|
| 4888 |
-
"resolved": "https://registry.npmjs.org/
|
| 4889 |
-
"integrity": "sha512-
|
| 4890 |
-
"
|
| 4891 |
-
"license": "ISC",
|
| 4892 |
"dependencies": {
|
| 4893 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4894 |
},
|
| 4895 |
-
"
|
| 4896 |
-
"
|
|
|
|
| 4897 |
}
|
| 4898 |
},
|
| 4899 |
-
"node_modules/
|
| 4900 |
-
"version": "
|
| 4901 |
-
"resolved": "https://registry.npmjs.org/
|
| 4902 |
-
"integrity": "sha512-
|
| 4903 |
-
"dev": true,
|
| 4904 |
"license": "MIT",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4905 |
"funding": {
|
| 4906 |
-
"
|
|
|
|
| 4907 |
}
|
| 4908 |
},
|
| 4909 |
-
"node_modules/
|
| 4910 |
-
"version": "2.1.
|
| 4911 |
-
"resolved": "https://registry.npmjs.org/
|
| 4912 |
-
"integrity": "sha512-
|
| 4913 |
-
"
|
| 4914 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4915 |
},
|
| 4916 |
-
"node_modules/
|
| 4917 |
-
"version": "
|
| 4918 |
-
"resolved": "https://registry.npmjs.org/
|
| 4919 |
-
"integrity": "sha512-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4920 |
"funding": [
|
| 4921 |
{
|
| 4922 |
"type": "github",
|
|
@@ -5165,6 +6347,27 @@
|
|
| 5165 |
"url": "https://github.com/sponsors/ljharb"
|
| 5166 |
}
|
| 5167 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5168 |
"node_modules/optionator": {
|
| 5169 |
"version": "0.9.4",
|
| 5170 |
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
|
@@ -5246,6 +6449,31 @@
|
|
| 5246 |
"node": ">=6"
|
| 5247 |
}
|
| 5248 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5249 |
"node_modules/path-exists": {
|
| 5250 |
"version": "4.0.0",
|
| 5251 |
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
|
@@ -5353,6 +6581,16 @@
|
|
| 5353 |
"react-is": "^16.13.1"
|
| 5354 |
}
|
| 5355 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5356 |
"node_modules/punycode": {
|
| 5357 |
"version": "2.3.1",
|
| 5358 |
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
|
@@ -5414,6 +6652,33 @@
|
|
| 5414 |
"dev": true,
|
| 5415 |
"license": "MIT"
|
| 5416 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5417 |
"node_modules/reflect.getprototypeof": {
|
| 5418 |
"version": "1.0.10",
|
| 5419 |
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
|
@@ -5458,6 +6723,72 @@
|
|
| 5458 |
"url": "https://github.com/sponsors/ljharb"
|
| 5459 |
}
|
| 5460 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5461 |
"node_modules/resolve": {
|
| 5462 |
"version": "1.22.11",
|
| 5463 |
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
|
|
@@ -5820,6 +7151,16 @@
|
|
| 5820 |
"node": ">=0.10.0"
|
| 5821 |
}
|
| 5822 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5823 |
"node_modules/stable-hash": {
|
| 5824 |
"version": "0.0.5",
|
| 5825 |
"resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
|
|
@@ -5954,6 +7295,20 @@
|
|
| 5954 |
"url": "https://github.com/sponsors/ljharb"
|
| 5955 |
}
|
| 5956 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5957 |
"node_modules/strip-bom": {
|
| 5958 |
"version": "3.0.0",
|
| 5959 |
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
|
@@ -5977,6 +7332,24 @@
|
|
| 5977 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 5978 |
}
|
| 5979 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5980 |
"node_modules/styled-jsx": {
|
| 5981 |
"version": "5.1.6",
|
| 5982 |
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
|
|
@@ -6026,6 +7399,16 @@
|
|
| 6026 |
"url": "https://github.com/sponsors/ljharb"
|
| 6027 |
}
|
| 6028 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6029 |
"node_modules/tailwindcss": {
|
| 6030 |
"version": "4.1.18",
|
| 6031 |
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
|
@@ -6109,6 +7492,26 @@
|
|
| 6109 |
"node": ">=8.0"
|
| 6110 |
}
|
| 6111 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6112 |
"node_modules/ts-api-utils": {
|
| 6113 |
"version": "2.1.0",
|
| 6114 |
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
|
@@ -6310,6 +7713,93 @@
|
|
| 6310 |
"dev": true,
|
| 6311 |
"license": "MIT"
|
| 6312 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6313 |
"node_modules/unrs-resolver": {
|
| 6314 |
"version": "1.11.1",
|
| 6315 |
"resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
|
|
@@ -6386,6 +7876,34 @@
|
|
| 6386 |
"punycode": "^2.1.0"
|
| 6387 |
}
|
| 6388 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6389 |
"node_modules/which": {
|
| 6390 |
"version": "2.0.2",
|
| 6391 |
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
@@ -6525,7 +8043,7 @@
|
|
| 6525 |
"version": "4.2.1",
|
| 6526 |
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
|
| 6527 |
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
|
| 6528 |
-
"
|
| 6529 |
"license": "MIT",
|
| 6530 |
"peer": true,
|
| 6531 |
"funding": {
|
|
@@ -6544,6 +8062,16 @@
|
|
| 6544 |
"peerDependencies": {
|
| 6545 |
"zod": "^3.25.0 || ^4.0.0"
|
| 6546 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6547 |
}
|
| 6548 |
}
|
| 6549 |
}
|
|
|
|
| 8 |
"name": "socratic-lens",
|
| 9 |
"version": "0.1.0",
|
| 10 |
"dependencies": {
|
| 11 |
+
"@google/generative-ai": "^0.24.1",
|
| 12 |
+
"clsx": "^2.1.1",
|
| 13 |
+
"lucide-react": "^0.562.0",
|
| 14 |
"next": "16.1.1",
|
| 15 |
+
"openai": "^6.15.0",
|
| 16 |
"react": "19.2.3",
|
| 17 |
+
"react-dom": "19.2.3",
|
| 18 |
+
"react-markdown": "^10.1.0",
|
| 19 |
+
"remark-gfm": "^4.0.1",
|
| 20 |
+
"tailwind-merge": "^3.4.0"
|
| 21 |
},
|
| 22 |
"devDependencies": {
|
| 23 |
"@tailwindcss/postcss": "^4",
|
|
|
|
| 461 |
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
| 462 |
}
|
| 463 |
},
|
| 464 |
+
"node_modules/@google/generative-ai": {
|
| 465 |
+
"version": "0.24.1",
|
| 466 |
+
"resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.24.1.tgz",
|
| 467 |
+
"integrity": "sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==",
|
| 468 |
+
"license": "Apache-2.0",
|
| 469 |
+
"engines": {
|
| 470 |
+
"node": ">=18.0.0"
|
| 471 |
+
}
|
| 472 |
+
},
|
| 473 |
"node_modules/@humanfs/core": {
|
| 474 |
"version": "0.19.1",
|
| 475 |
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
|
|
|
| 1541 |
"tslib": "^2.4.0"
|
| 1542 |
}
|
| 1543 |
},
|
| 1544 |
+
"node_modules/@types/debug": {
|
| 1545 |
+
"version": "4.1.12",
|
| 1546 |
+
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
| 1547 |
+
"integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
|
| 1548 |
+
"license": "MIT",
|
| 1549 |
+
"dependencies": {
|
| 1550 |
+
"@types/ms": "*"
|
| 1551 |
+
}
|
| 1552 |
+
},
|
| 1553 |
"node_modules/@types/estree": {
|
| 1554 |
"version": "1.0.8",
|
| 1555 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
| 1556 |
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
|
|
|
| 1557 |
"license": "MIT"
|
| 1558 |
},
|
| 1559 |
+
"node_modules/@types/estree-jsx": {
|
| 1560 |
+
"version": "1.0.5",
|
| 1561 |
+
"resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
|
| 1562 |
+
"integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
|
| 1563 |
+
"license": "MIT",
|
| 1564 |
+
"dependencies": {
|
| 1565 |
+
"@types/estree": "*"
|
| 1566 |
+
}
|
| 1567 |
+
},
|
| 1568 |
+
"node_modules/@types/hast": {
|
| 1569 |
+
"version": "3.0.4",
|
| 1570 |
+
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
|
| 1571 |
+
"integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
|
| 1572 |
+
"license": "MIT",
|
| 1573 |
+
"dependencies": {
|
| 1574 |
+
"@types/unist": "*"
|
| 1575 |
+
}
|
| 1576 |
+
},
|
| 1577 |
"node_modules/@types/json-schema": {
|
| 1578 |
"version": "7.0.15",
|
| 1579 |
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
|
|
|
| 1588 |
"dev": true,
|
| 1589 |
"license": "MIT"
|
| 1590 |
},
|
| 1591 |
+
"node_modules/@types/mdast": {
|
| 1592 |
+
"version": "4.0.4",
|
| 1593 |
+
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
| 1594 |
+
"integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
|
| 1595 |
+
"license": "MIT",
|
| 1596 |
+
"dependencies": {
|
| 1597 |
+
"@types/unist": "*"
|
| 1598 |
+
}
|
| 1599 |
+
},
|
| 1600 |
+
"node_modules/@types/ms": {
|
| 1601 |
+
"version": "2.1.0",
|
| 1602 |
+
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
|
| 1603 |
+
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
|
| 1604 |
+
"license": "MIT"
|
| 1605 |
+
},
|
| 1606 |
"node_modules/@types/node": {
|
| 1607 |
"version": "20.19.27",
|
| 1608 |
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.27.tgz",
|
|
|
|
| 1617 |
"version": "19.2.7",
|
| 1618 |
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
|
| 1619 |
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
|
|
|
|
| 1620 |
"license": "MIT",
|
| 1621 |
"peer": true,
|
| 1622 |
"dependencies": {
|
|
|
|
| 1633 |
"@types/react": "^19.2.0"
|
| 1634 |
}
|
| 1635 |
},
|
| 1636 |
+
"node_modules/@types/unist": {
|
| 1637 |
+
"version": "3.0.3",
|
| 1638 |
+
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
| 1639 |
+
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
|
| 1640 |
+
"license": "MIT"
|
| 1641 |
+
},
|
| 1642 |
"node_modules/@typescript-eslint/eslint-plugin": {
|
| 1643 |
"version": "8.50.1",
|
| 1644 |
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.1.tgz",
|
|
|
|
| 1909 |
"url": "https://opencollective.com/typescript-eslint"
|
| 1910 |
}
|
| 1911 |
},
|
| 1912 |
+
"node_modules/@ungap/structured-clone": {
|
| 1913 |
+
"version": "1.3.0",
|
| 1914 |
+
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
|
| 1915 |
+
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
|
| 1916 |
+
"license": "ISC"
|
| 1917 |
+
},
|
| 1918 |
"node_modules/@unrs/resolver-binding-android-arm-eabi": {
|
| 1919 |
"version": "1.11.1",
|
| 1920 |
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
|
|
|
|
| 2471 |
"node": ">= 0.4"
|
| 2472 |
}
|
| 2473 |
},
|
| 2474 |
+
"node_modules/bail": {
|
| 2475 |
+
"version": "2.0.2",
|
| 2476 |
+
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
| 2477 |
+
"integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
|
| 2478 |
+
"license": "MIT",
|
| 2479 |
+
"funding": {
|
| 2480 |
+
"type": "github",
|
| 2481 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2482 |
+
}
|
| 2483 |
+
},
|
| 2484 |
"node_modules/balanced-match": {
|
| 2485 |
"version": "1.0.2",
|
| 2486 |
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
|
|
|
| 2636 |
],
|
| 2637 |
"license": "CC-BY-4.0"
|
| 2638 |
},
|
| 2639 |
+
"node_modules/ccount": {
|
| 2640 |
+
"version": "2.0.1",
|
| 2641 |
+
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
|
| 2642 |
+
"integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
|
| 2643 |
+
"license": "MIT",
|
| 2644 |
+
"funding": {
|
| 2645 |
+
"type": "github",
|
| 2646 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2647 |
+
}
|
| 2648 |
+
},
|
| 2649 |
"node_modules/chalk": {
|
| 2650 |
"version": "4.1.2",
|
| 2651 |
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
|
|
| 2663 |
"url": "https://github.com/chalk/chalk?sponsor=1"
|
| 2664 |
}
|
| 2665 |
},
|
| 2666 |
+
"node_modules/character-entities": {
|
| 2667 |
+
"version": "2.0.2",
|
| 2668 |
+
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
|
| 2669 |
+
"integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
|
| 2670 |
+
"license": "MIT",
|
| 2671 |
+
"funding": {
|
| 2672 |
+
"type": "github",
|
| 2673 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2674 |
+
}
|
| 2675 |
+
},
|
| 2676 |
+
"node_modules/character-entities-html4": {
|
| 2677 |
+
"version": "2.1.0",
|
| 2678 |
+
"resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
|
| 2679 |
+
"integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
|
| 2680 |
+
"license": "MIT",
|
| 2681 |
+
"funding": {
|
| 2682 |
+
"type": "github",
|
| 2683 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2684 |
+
}
|
| 2685 |
+
},
|
| 2686 |
+
"node_modules/character-entities-legacy": {
|
| 2687 |
+
"version": "3.0.0",
|
| 2688 |
+
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
|
| 2689 |
+
"integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
|
| 2690 |
+
"license": "MIT",
|
| 2691 |
+
"funding": {
|
| 2692 |
+
"type": "github",
|
| 2693 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2694 |
+
}
|
| 2695 |
+
},
|
| 2696 |
+
"node_modules/character-reference-invalid": {
|
| 2697 |
+
"version": "2.0.1",
|
| 2698 |
+
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
|
| 2699 |
+
"integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
|
| 2700 |
+
"license": "MIT",
|
| 2701 |
+
"funding": {
|
| 2702 |
+
"type": "github",
|
| 2703 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2704 |
+
}
|
| 2705 |
+
},
|
| 2706 |
"node_modules/client-only": {
|
| 2707 |
"version": "0.0.1",
|
| 2708 |
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
| 2709 |
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
| 2710 |
"license": "MIT"
|
| 2711 |
},
|
| 2712 |
+
"node_modules/clsx": {
|
| 2713 |
+
"version": "2.1.1",
|
| 2714 |
+
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
| 2715 |
+
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
| 2716 |
+
"license": "MIT",
|
| 2717 |
+
"engines": {
|
| 2718 |
+
"node": ">=6"
|
| 2719 |
+
}
|
| 2720 |
+
},
|
| 2721 |
"node_modules/color-convert": {
|
| 2722 |
"version": "2.0.1",
|
| 2723 |
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
|
|
| 2738 |
"dev": true,
|
| 2739 |
"license": "MIT"
|
| 2740 |
},
|
| 2741 |
+
"node_modules/comma-separated-tokens": {
|
| 2742 |
+
"version": "2.0.3",
|
| 2743 |
+
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
|
| 2744 |
+
"integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
|
| 2745 |
+
"license": "MIT",
|
| 2746 |
+
"funding": {
|
| 2747 |
+
"type": "github",
|
| 2748 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2749 |
+
}
|
| 2750 |
+
},
|
| 2751 |
"node_modules/concat-map": {
|
| 2752 |
"version": "0.0.1",
|
| 2753 |
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
|
|
| 2781 |
"version": "3.2.3",
|
| 2782 |
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
| 2783 |
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
|
|
|
| 2784 |
"license": "MIT"
|
| 2785 |
},
|
| 2786 |
"node_modules/damerau-levenshtein": {
|
|
|
|
| 2848 |
"version": "4.4.3",
|
| 2849 |
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
| 2850 |
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
|
|
|
| 2851 |
"license": "MIT",
|
| 2852 |
"dependencies": {
|
| 2853 |
"ms": "^2.1.3"
|
|
|
|
| 2861 |
}
|
| 2862 |
}
|
| 2863 |
},
|
| 2864 |
+
"node_modules/decode-named-character-reference": {
|
| 2865 |
+
"version": "1.2.0",
|
| 2866 |
+
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz",
|
| 2867 |
+
"integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==",
|
| 2868 |
+
"license": "MIT",
|
| 2869 |
+
"dependencies": {
|
| 2870 |
+
"character-entities": "^2.0.0"
|
| 2871 |
+
},
|
| 2872 |
+
"funding": {
|
| 2873 |
+
"type": "github",
|
| 2874 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2875 |
+
}
|
| 2876 |
+
},
|
| 2877 |
"node_modules/deep-is": {
|
| 2878 |
"version": "0.1.4",
|
| 2879 |
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
|
|
|
| 2917 |
"url": "https://github.com/sponsors/ljharb"
|
| 2918 |
}
|
| 2919 |
},
|
| 2920 |
+
"node_modules/dequal": {
|
| 2921 |
+
"version": "2.0.3",
|
| 2922 |
+
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
| 2923 |
+
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
| 2924 |
+
"license": "MIT",
|
| 2925 |
+
"engines": {
|
| 2926 |
+
"node": ">=6"
|
| 2927 |
+
}
|
| 2928 |
+
},
|
| 2929 |
"node_modules/detect-libc": {
|
| 2930 |
"version": "2.1.2",
|
| 2931 |
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
|
|
|
| 2936 |
"node": ">=8"
|
| 2937 |
}
|
| 2938 |
},
|
| 2939 |
+
"node_modules/devlop": {
|
| 2940 |
+
"version": "1.1.0",
|
| 2941 |
+
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
|
| 2942 |
+
"integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
|
| 2943 |
+
"license": "MIT",
|
| 2944 |
+
"dependencies": {
|
| 2945 |
+
"dequal": "^2.0.0"
|
| 2946 |
+
},
|
| 2947 |
+
"funding": {
|
| 2948 |
+
"type": "github",
|
| 2949 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2950 |
+
}
|
| 2951 |
+
},
|
| 2952 |
"node_modules/doctrine": {
|
| 2953 |
"version": "2.1.0",
|
| 2954 |
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
|
|
|
| 3397 |
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
|
| 3398 |
"dev": true,
|
| 3399 |
"license": "MIT",
|
| 3400 |
+
"peer": true,
|
| 3401 |
"dependencies": {
|
| 3402 |
"@rtsao/scc": "^1.1.0",
|
| 3403 |
"array-includes": "^3.1.9",
|
|
|
|
| 3621 |
"node": ">=4.0"
|
| 3622 |
}
|
| 3623 |
},
|
| 3624 |
+
"node_modules/estree-util-is-identifier-name": {
|
| 3625 |
+
"version": "3.0.0",
|
| 3626 |
+
"resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
|
| 3627 |
+
"integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==",
|
| 3628 |
+
"license": "MIT",
|
| 3629 |
+
"funding": {
|
| 3630 |
+
"type": "opencollective",
|
| 3631 |
+
"url": "https://opencollective.com/unified"
|
| 3632 |
+
}
|
| 3633 |
+
},
|
| 3634 |
"node_modules/esutils": {
|
| 3635 |
"version": "2.0.3",
|
| 3636 |
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
|
|
|
| 3641 |
"node": ">=0.10.0"
|
| 3642 |
}
|
| 3643 |
},
|
| 3644 |
+
"node_modules/extend": {
|
| 3645 |
+
"version": "3.0.2",
|
| 3646 |
+
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
| 3647 |
+
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
| 3648 |
+
"license": "MIT"
|
| 3649 |
+
},
|
| 3650 |
"node_modules/fast-deep-equal": {
|
| 3651 |
"version": "3.1.3",
|
| 3652 |
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
|
|
| 4076 |
"node": ">= 0.4"
|
| 4077 |
}
|
| 4078 |
},
|
| 4079 |
+
"node_modules/hast-util-to-jsx-runtime": {
|
| 4080 |
+
"version": "2.3.6",
|
| 4081 |
+
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
|
| 4082 |
+
"integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==",
|
| 4083 |
+
"license": "MIT",
|
| 4084 |
+
"dependencies": {
|
| 4085 |
+
"@types/estree": "^1.0.0",
|
| 4086 |
+
"@types/hast": "^3.0.0",
|
| 4087 |
+
"@types/unist": "^3.0.0",
|
| 4088 |
+
"comma-separated-tokens": "^2.0.0",
|
| 4089 |
+
"devlop": "^1.0.0",
|
| 4090 |
+
"estree-util-is-identifier-name": "^3.0.0",
|
| 4091 |
+
"hast-util-whitespace": "^3.0.0",
|
| 4092 |
+
"mdast-util-mdx-expression": "^2.0.0",
|
| 4093 |
+
"mdast-util-mdx-jsx": "^3.0.0",
|
| 4094 |
+
"mdast-util-mdxjs-esm": "^2.0.0",
|
| 4095 |
+
"property-information": "^7.0.0",
|
| 4096 |
+
"space-separated-tokens": "^2.0.0",
|
| 4097 |
+
"style-to-js": "^1.0.0",
|
| 4098 |
+
"unist-util-position": "^5.0.0",
|
| 4099 |
+
"vfile-message": "^4.0.0"
|
| 4100 |
+
},
|
| 4101 |
+
"funding": {
|
| 4102 |
+
"type": "opencollective",
|
| 4103 |
+
"url": "https://opencollective.com/unified"
|
| 4104 |
+
}
|
| 4105 |
+
},
|
| 4106 |
+
"node_modules/hast-util-whitespace": {
|
| 4107 |
+
"version": "3.0.0",
|
| 4108 |
+
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
|
| 4109 |
+
"integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
|
| 4110 |
+
"license": "MIT",
|
| 4111 |
+
"dependencies": {
|
| 4112 |
+
"@types/hast": "^3.0.0"
|
| 4113 |
+
},
|
| 4114 |
+
"funding": {
|
| 4115 |
+
"type": "opencollective",
|
| 4116 |
+
"url": "https://opencollective.com/unified"
|
| 4117 |
+
}
|
| 4118 |
+
},
|
| 4119 |
"node_modules/hermes-estree": {
|
| 4120 |
"version": "0.25.1",
|
| 4121 |
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
|
|
|
|
| 4133 |
"hermes-estree": "0.25.1"
|
| 4134 |
}
|
| 4135 |
},
|
| 4136 |
+
"node_modules/html-url-attributes": {
|
| 4137 |
+
"version": "3.0.1",
|
| 4138 |
+
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
| 4139 |
+
"integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==",
|
| 4140 |
+
"license": "MIT",
|
| 4141 |
+
"funding": {
|
| 4142 |
+
"type": "opencollective",
|
| 4143 |
+
"url": "https://opencollective.com/unified"
|
| 4144 |
+
}
|
| 4145 |
+
},
|
| 4146 |
"node_modules/ignore": {
|
| 4147 |
"version": "5.3.2",
|
| 4148 |
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
|
|
|
| 4180 |
"node": ">=0.8.19"
|
| 4181 |
}
|
| 4182 |
},
|
| 4183 |
+
"node_modules/inline-style-parser": {
|
| 4184 |
+
"version": "0.2.7",
|
| 4185 |
+
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz",
|
| 4186 |
+
"integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==",
|
| 4187 |
+
"license": "MIT"
|
| 4188 |
+
},
|
| 4189 |
"node_modules/internal-slot": {
|
| 4190 |
"version": "1.1.0",
|
| 4191 |
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
|
|
|
| 4201 |
"node": ">= 0.4"
|
| 4202 |
}
|
| 4203 |
},
|
| 4204 |
+
"node_modules/is-alphabetical": {
|
| 4205 |
+
"version": "2.0.1",
|
| 4206 |
+
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
|
| 4207 |
+
"integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
|
| 4208 |
+
"license": "MIT",
|
| 4209 |
+
"funding": {
|
| 4210 |
+
"type": "github",
|
| 4211 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4212 |
+
}
|
| 4213 |
+
},
|
| 4214 |
+
"node_modules/is-alphanumerical": {
|
| 4215 |
+
"version": "2.0.1",
|
| 4216 |
+
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
|
| 4217 |
+
"integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
|
| 4218 |
+
"license": "MIT",
|
| 4219 |
+
"dependencies": {
|
| 4220 |
+
"is-alphabetical": "^2.0.0",
|
| 4221 |
+
"is-decimal": "^2.0.0"
|
| 4222 |
+
},
|
| 4223 |
+
"funding": {
|
| 4224 |
+
"type": "github",
|
| 4225 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4226 |
+
}
|
| 4227 |
+
},
|
| 4228 |
"node_modules/is-array-buffer": {
|
| 4229 |
"version": "3.0.5",
|
| 4230 |
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
|
|
|
| 4383 |
"url": "https://github.com/sponsors/ljharb"
|
| 4384 |
}
|
| 4385 |
},
|
| 4386 |
+
"node_modules/is-decimal": {
|
| 4387 |
+
"version": "2.0.1",
|
| 4388 |
+
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
|
| 4389 |
+
"integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
|
| 4390 |
+
"license": "MIT",
|
| 4391 |
+
"funding": {
|
| 4392 |
+
"type": "github",
|
| 4393 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4394 |
+
}
|
| 4395 |
+
},
|
| 4396 |
"node_modules/is-extglob": {
|
| 4397 |
"version": "2.1.1",
|
| 4398 |
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
|
|
|
| 4452 |
"node": ">=0.10.0"
|
| 4453 |
}
|
| 4454 |
},
|
| 4455 |
+
"node_modules/is-hexadecimal": {
|
| 4456 |
+
"version": "2.0.1",
|
| 4457 |
+
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
|
| 4458 |
+
"integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
|
| 4459 |
+
"license": "MIT",
|
| 4460 |
+
"funding": {
|
| 4461 |
+
"type": "github",
|
| 4462 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4463 |
+
}
|
| 4464 |
+
},
|
| 4465 |
"node_modules/is-map": {
|
| 4466 |
"version": "2.0.3",
|
| 4467 |
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
|
|
|
|
| 4515 |
"url": "https://github.com/sponsors/ljharb"
|
| 4516 |
}
|
| 4517 |
},
|
| 4518 |
+
"node_modules/is-plain-obj": {
|
| 4519 |
+
"version": "4.1.0",
|
| 4520 |
+
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
|
| 4521 |
+
"integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
|
| 4522 |
+
"license": "MIT",
|
| 4523 |
+
"engines": {
|
| 4524 |
+
"node": ">=12"
|
| 4525 |
+
},
|
| 4526 |
+
"funding": {
|
| 4527 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 4528 |
+
}
|
| 4529 |
+
},
|
| 4530 |
"node_modules/is-regex": {
|
| 4531 |
"version": "1.2.1",
|
| 4532 |
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
|
|
|
| 5125 |
"dev": true,
|
| 5126 |
"license": "MIT"
|
| 5127 |
},
|
| 5128 |
+
"node_modules/longest-streak": {
|
| 5129 |
+
"version": "3.1.0",
|
| 5130 |
+
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
|
| 5131 |
+
"integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
|
| 5132 |
+
"license": "MIT",
|
| 5133 |
+
"funding": {
|
| 5134 |
+
"type": "github",
|
| 5135 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 5136 |
+
}
|
| 5137 |
+
},
|
| 5138 |
"node_modules/loose-envify": {
|
| 5139 |
"version": "1.4.0",
|
| 5140 |
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
|
|
|
| 5158 |
"yallist": "^3.0.2"
|
| 5159 |
}
|
| 5160 |
},
|
| 5161 |
+
"node_modules/lucide-react": {
|
| 5162 |
+
"version": "0.562.0",
|
| 5163 |
+
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz",
|
| 5164 |
+
"integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==",
|
| 5165 |
+
"license": "ISC",
|
| 5166 |
+
"peerDependencies": {
|
| 5167 |
+
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 5168 |
+
}
|
| 5169 |
+
},
|
| 5170 |
"node_modules/magic-string": {
|
| 5171 |
"version": "0.30.21",
|
| 5172 |
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
|
|
|
| 5177 |
"@jridgewell/sourcemap-codec": "^1.5.5"
|
| 5178 |
}
|
| 5179 |
},
|
| 5180 |
+
"node_modules/markdown-table": {
|
| 5181 |
+
"version": "3.0.4",
|
| 5182 |
+
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
|
| 5183 |
+
"integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
|
| 5184 |
+
"license": "MIT",
|
| 5185 |
+
"funding": {
|
| 5186 |
+
"type": "github",
|
| 5187 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 5188 |
+
}
|
| 5189 |
+
},
|
| 5190 |
"node_modules/math-intrinsics": {
|
| 5191 |
"version": "1.1.0",
|
| 5192 |
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
|
|
|
| 5197 |
"node": ">= 0.4"
|
| 5198 |
}
|
| 5199 |
},
|
| 5200 |
+
"node_modules/mdast-util-find-and-replace": {
|
| 5201 |
+
"version": "3.0.2",
|
| 5202 |
+
"resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
|
| 5203 |
+
"integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
|
| 5204 |
+
"license": "MIT",
|
| 5205 |
+
"dependencies": {
|
| 5206 |
+
"@types/mdast": "^4.0.0",
|
| 5207 |
+
"escape-string-regexp": "^5.0.0",
|
| 5208 |
+
"unist-util-is": "^6.0.0",
|
| 5209 |
+
"unist-util-visit-parents": "^6.0.0"
|
| 5210 |
+
},
|
| 5211 |
+
"funding": {
|
| 5212 |
+
"type": "opencollective",
|
| 5213 |
+
"url": "https://opencollective.com/unified"
|
| 5214 |
+
}
|
| 5215 |
+
},
|
| 5216 |
+
"node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
|
| 5217 |
+
"version": "5.0.0",
|
| 5218 |
+
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
| 5219 |
+
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
| 5220 |
"license": "MIT",
|
| 5221 |
"engines": {
|
| 5222 |
+
"node": ">=12"
|
| 5223 |
+
},
|
| 5224 |
+
"funding": {
|
| 5225 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 5226 |
}
|
| 5227 |
},
|
| 5228 |
+
"node_modules/mdast-util-from-markdown": {
|
| 5229 |
+
"version": "2.0.2",
|
| 5230 |
+
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
| 5231 |
+
"integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
|
|
|
|
| 5232 |
"license": "MIT",
|
| 5233 |
"dependencies": {
|
| 5234 |
+
"@types/mdast": "^4.0.0",
|
| 5235 |
+
"@types/unist": "^3.0.0",
|
| 5236 |
+
"decode-named-character-reference": "^1.0.0",
|
| 5237 |
+
"devlop": "^1.0.0",
|
| 5238 |
+
"mdast-util-to-string": "^4.0.0",
|
| 5239 |
+
"micromark": "^4.0.0",
|
| 5240 |
+
"micromark-util-decode-numeric-character-reference": "^2.0.0",
|
| 5241 |
+
"micromark-util-decode-string": "^2.0.0",
|
| 5242 |
+
"micromark-util-normalize-identifier": "^2.0.0",
|
| 5243 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5244 |
+
"micromark-util-types": "^2.0.0",
|
| 5245 |
+
"unist-util-stringify-position": "^4.0.0"
|
| 5246 |
},
|
| 5247 |
+
"funding": {
|
| 5248 |
+
"type": "opencollective",
|
| 5249 |
+
"url": "https://opencollective.com/unified"
|
| 5250 |
}
|
| 5251 |
},
|
| 5252 |
+
"node_modules/mdast-util-gfm": {
|
| 5253 |
+
"version": "3.1.0",
|
| 5254 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
|
| 5255 |
+
"integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
|
| 5256 |
+
"license": "MIT",
|
|
|
|
| 5257 |
"dependencies": {
|
| 5258 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5259 |
+
"mdast-util-gfm-autolink-literal": "^2.0.0",
|
| 5260 |
+
"mdast-util-gfm-footnote": "^2.0.0",
|
| 5261 |
+
"mdast-util-gfm-strikethrough": "^2.0.0",
|
| 5262 |
+
"mdast-util-gfm-table": "^2.0.0",
|
| 5263 |
+
"mdast-util-gfm-task-list-item": "^2.0.0",
|
| 5264 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5265 |
},
|
| 5266 |
+
"funding": {
|
| 5267 |
+
"type": "opencollective",
|
| 5268 |
+
"url": "https://opencollective.com/unified"
|
| 5269 |
}
|
| 5270 |
},
|
| 5271 |
+
"node_modules/mdast-util-gfm-autolink-literal": {
|
| 5272 |
+
"version": "2.0.1",
|
| 5273 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
|
| 5274 |
+
"integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
|
|
|
|
| 5275 |
"license": "MIT",
|
| 5276 |
+
"dependencies": {
|
| 5277 |
+
"@types/mdast": "^4.0.0",
|
| 5278 |
+
"ccount": "^2.0.0",
|
| 5279 |
+
"devlop": "^1.0.0",
|
| 5280 |
+
"mdast-util-find-and-replace": "^3.0.0",
|
| 5281 |
+
"micromark-util-character": "^2.0.0"
|
| 5282 |
+
},
|
| 5283 |
"funding": {
|
| 5284 |
+
"type": "opencollective",
|
| 5285 |
+
"url": "https://opencollective.com/unified"
|
| 5286 |
}
|
| 5287 |
},
|
| 5288 |
+
"node_modules/mdast-util-gfm-footnote": {
|
| 5289 |
+
"version": "2.1.0",
|
| 5290 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
|
| 5291 |
+
"integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
|
| 5292 |
+
"license": "MIT",
|
| 5293 |
+
"dependencies": {
|
| 5294 |
+
"@types/mdast": "^4.0.0",
|
| 5295 |
+
"devlop": "^1.1.0",
|
| 5296 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5297 |
+
"mdast-util-to-markdown": "^2.0.0",
|
| 5298 |
+
"micromark-util-normalize-identifier": "^2.0.0"
|
| 5299 |
+
},
|
| 5300 |
+
"funding": {
|
| 5301 |
+
"type": "opencollective",
|
| 5302 |
+
"url": "https://opencollective.com/unified"
|
| 5303 |
+
}
|
| 5304 |
},
|
| 5305 |
+
"node_modules/mdast-util-gfm-strikethrough": {
|
| 5306 |
+
"version": "2.0.0",
|
| 5307 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
|
| 5308 |
+
"integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
|
| 5309 |
+
"license": "MIT",
|
| 5310 |
+
"dependencies": {
|
| 5311 |
+
"@types/mdast": "^4.0.0",
|
| 5312 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5313 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5314 |
+
},
|
| 5315 |
+
"funding": {
|
| 5316 |
+
"type": "opencollective",
|
| 5317 |
+
"url": "https://opencollective.com/unified"
|
| 5318 |
+
}
|
| 5319 |
+
},
|
| 5320 |
+
"node_modules/mdast-util-gfm-table": {
|
| 5321 |
+
"version": "2.0.0",
|
| 5322 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
|
| 5323 |
+
"integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
|
| 5324 |
+
"license": "MIT",
|
| 5325 |
+
"dependencies": {
|
| 5326 |
+
"@types/mdast": "^4.0.0",
|
| 5327 |
+
"devlop": "^1.0.0",
|
| 5328 |
+
"markdown-table": "^3.0.0",
|
| 5329 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5330 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5331 |
+
},
|
| 5332 |
+
"funding": {
|
| 5333 |
+
"type": "opencollective",
|
| 5334 |
+
"url": "https://opencollective.com/unified"
|
| 5335 |
+
}
|
| 5336 |
+
},
|
| 5337 |
+
"node_modules/mdast-util-gfm-task-list-item": {
|
| 5338 |
+
"version": "2.0.0",
|
| 5339 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
|
| 5340 |
+
"integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
|
| 5341 |
+
"license": "MIT",
|
| 5342 |
+
"dependencies": {
|
| 5343 |
+
"@types/mdast": "^4.0.0",
|
| 5344 |
+
"devlop": "^1.0.0",
|
| 5345 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5346 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5347 |
+
},
|
| 5348 |
+
"funding": {
|
| 5349 |
+
"type": "opencollective",
|
| 5350 |
+
"url": "https://opencollective.com/unified"
|
| 5351 |
+
}
|
| 5352 |
+
},
|
| 5353 |
+
"node_modules/mdast-util-mdx-expression": {
|
| 5354 |
+
"version": "2.0.1",
|
| 5355 |
+
"resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
|
| 5356 |
+
"integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
|
| 5357 |
+
"license": "MIT",
|
| 5358 |
+
"dependencies": {
|
| 5359 |
+
"@types/estree-jsx": "^1.0.0",
|
| 5360 |
+
"@types/hast": "^3.0.0",
|
| 5361 |
+
"@types/mdast": "^4.0.0",
|
| 5362 |
+
"devlop": "^1.0.0",
|
| 5363 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5364 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5365 |
+
},
|
| 5366 |
+
"funding": {
|
| 5367 |
+
"type": "opencollective",
|
| 5368 |
+
"url": "https://opencollective.com/unified"
|
| 5369 |
+
}
|
| 5370 |
+
},
|
| 5371 |
+
"node_modules/mdast-util-mdx-jsx": {
|
| 5372 |
+
"version": "3.2.0",
|
| 5373 |
+
"resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
|
| 5374 |
+
"integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
|
| 5375 |
+
"license": "MIT",
|
| 5376 |
+
"dependencies": {
|
| 5377 |
+
"@types/estree-jsx": "^1.0.0",
|
| 5378 |
+
"@types/hast": "^3.0.0",
|
| 5379 |
+
"@types/mdast": "^4.0.0",
|
| 5380 |
+
"@types/unist": "^3.0.0",
|
| 5381 |
+
"ccount": "^2.0.0",
|
| 5382 |
+
"devlop": "^1.1.0",
|
| 5383 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5384 |
+
"mdast-util-to-markdown": "^2.0.0",
|
| 5385 |
+
"parse-entities": "^4.0.0",
|
| 5386 |
+
"stringify-entities": "^4.0.0",
|
| 5387 |
+
"unist-util-stringify-position": "^4.0.0",
|
| 5388 |
+
"vfile-message": "^4.0.0"
|
| 5389 |
+
},
|
| 5390 |
+
"funding": {
|
| 5391 |
+
"type": "opencollective",
|
| 5392 |
+
"url": "https://opencollective.com/unified"
|
| 5393 |
+
}
|
| 5394 |
+
},
|
| 5395 |
+
"node_modules/mdast-util-mdxjs-esm": {
|
| 5396 |
+
"version": "2.0.1",
|
| 5397 |
+
"resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
|
| 5398 |
+
"integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
|
| 5399 |
+
"license": "MIT",
|
| 5400 |
+
"dependencies": {
|
| 5401 |
+
"@types/estree-jsx": "^1.0.0",
|
| 5402 |
+
"@types/hast": "^3.0.0",
|
| 5403 |
+
"@types/mdast": "^4.0.0",
|
| 5404 |
+
"devlop": "^1.0.0",
|
| 5405 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5406 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5407 |
+
},
|
| 5408 |
+
"funding": {
|
| 5409 |
+
"type": "opencollective",
|
| 5410 |
+
"url": "https://opencollective.com/unified"
|
| 5411 |
+
}
|
| 5412 |
+
},
|
| 5413 |
+
"node_modules/mdast-util-phrasing": {
|
| 5414 |
+
"version": "4.1.0",
|
| 5415 |
+
"resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
|
| 5416 |
+
"integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
|
| 5417 |
+
"license": "MIT",
|
| 5418 |
+
"dependencies": {
|
| 5419 |
+
"@types/mdast": "^4.0.0",
|
| 5420 |
+
"unist-util-is": "^6.0.0"
|
| 5421 |
+
},
|
| 5422 |
+
"funding": {
|
| 5423 |
+
"type": "opencollective",
|
| 5424 |
+
"url": "https://opencollective.com/unified"
|
| 5425 |
+
}
|
| 5426 |
+
},
|
| 5427 |
+
"node_modules/mdast-util-to-hast": {
|
| 5428 |
+
"version": "13.2.1",
|
| 5429 |
+
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
|
| 5430 |
+
"integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
|
| 5431 |
+
"license": "MIT",
|
| 5432 |
+
"dependencies": {
|
| 5433 |
+
"@types/hast": "^3.0.0",
|
| 5434 |
+
"@types/mdast": "^4.0.0",
|
| 5435 |
+
"@ungap/structured-clone": "^1.0.0",
|
| 5436 |
+
"devlop": "^1.0.0",
|
| 5437 |
+
"micromark-util-sanitize-uri": "^2.0.0",
|
| 5438 |
+
"trim-lines": "^3.0.0",
|
| 5439 |
+
"unist-util-position": "^5.0.0",
|
| 5440 |
+
"unist-util-visit": "^5.0.0",
|
| 5441 |
+
"vfile": "^6.0.0"
|
| 5442 |
+
},
|
| 5443 |
+
"funding": {
|
| 5444 |
+
"type": "opencollective",
|
| 5445 |
+
"url": "https://opencollective.com/unified"
|
| 5446 |
+
}
|
| 5447 |
+
},
|
| 5448 |
+
"node_modules/mdast-util-to-markdown": {
|
| 5449 |
+
"version": "2.1.2",
|
| 5450 |
+
"resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
|
| 5451 |
+
"integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
|
| 5452 |
+
"license": "MIT",
|
| 5453 |
+
"dependencies": {
|
| 5454 |
+
"@types/mdast": "^4.0.0",
|
| 5455 |
+
"@types/unist": "^3.0.0",
|
| 5456 |
+
"longest-streak": "^3.0.0",
|
| 5457 |
+
"mdast-util-phrasing": "^4.0.0",
|
| 5458 |
+
"mdast-util-to-string": "^4.0.0",
|
| 5459 |
+
"micromark-util-classify-character": "^2.0.0",
|
| 5460 |
+
"micromark-util-decode-string": "^2.0.0",
|
| 5461 |
+
"unist-util-visit": "^5.0.0",
|
| 5462 |
+
"zwitch": "^2.0.0"
|
| 5463 |
+
},
|
| 5464 |
+
"funding": {
|
| 5465 |
+
"type": "opencollective",
|
| 5466 |
+
"url": "https://opencollective.com/unified"
|
| 5467 |
+
}
|
| 5468 |
+
},
|
| 5469 |
+
"node_modules/mdast-util-to-string": {
|
| 5470 |
+
"version": "4.0.0",
|
| 5471 |
+
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
|
| 5472 |
+
"integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
|
| 5473 |
+
"license": "MIT",
|
| 5474 |
+
"dependencies": {
|
| 5475 |
+
"@types/mdast": "^4.0.0"
|
| 5476 |
+
},
|
| 5477 |
+
"funding": {
|
| 5478 |
+
"type": "opencollective",
|
| 5479 |
+
"url": "https://opencollective.com/unified"
|
| 5480 |
+
}
|
| 5481 |
+
},
|
| 5482 |
+
"node_modules/merge2": {
|
| 5483 |
+
"version": "1.4.1",
|
| 5484 |
+
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
| 5485 |
+
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
| 5486 |
+
"dev": true,
|
| 5487 |
+
"license": "MIT",
|
| 5488 |
+
"engines": {
|
| 5489 |
+
"node": ">= 8"
|
| 5490 |
+
}
|
| 5491 |
+
},
|
| 5492 |
+
"node_modules/micromark": {
|
| 5493 |
+
"version": "4.0.2",
|
| 5494 |
+
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
|
| 5495 |
+
"integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
|
| 5496 |
+
"funding": [
|
| 5497 |
+
{
|
| 5498 |
+
"type": "GitHub Sponsors",
|
| 5499 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5500 |
+
},
|
| 5501 |
+
{
|
| 5502 |
+
"type": "OpenCollective",
|
| 5503 |
+
"url": "https://opencollective.com/unified"
|
| 5504 |
+
}
|
| 5505 |
+
],
|
| 5506 |
+
"license": "MIT",
|
| 5507 |
+
"dependencies": {
|
| 5508 |
+
"@types/debug": "^4.0.0",
|
| 5509 |
+
"debug": "^4.0.0",
|
| 5510 |
+
"decode-named-character-reference": "^1.0.0",
|
| 5511 |
+
"devlop": "^1.0.0",
|
| 5512 |
+
"micromark-core-commonmark": "^2.0.0",
|
| 5513 |
+
"micromark-factory-space": "^2.0.0",
|
| 5514 |
+
"micromark-util-character": "^2.0.0",
|
| 5515 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5516 |
+
"micromark-util-combine-extensions": "^2.0.0",
|
| 5517 |
+
"micromark-util-decode-numeric-character-reference": "^2.0.0",
|
| 5518 |
+
"micromark-util-encode": "^2.0.0",
|
| 5519 |
+
"micromark-util-normalize-identifier": "^2.0.0",
|
| 5520 |
+
"micromark-util-resolve-all": "^2.0.0",
|
| 5521 |
+
"micromark-util-sanitize-uri": "^2.0.0",
|
| 5522 |
+
"micromark-util-subtokenize": "^2.0.0",
|
| 5523 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5524 |
+
"micromark-util-types": "^2.0.0"
|
| 5525 |
+
}
|
| 5526 |
+
},
|
| 5527 |
+
"node_modules/micromark-core-commonmark": {
|
| 5528 |
+
"version": "2.0.3",
|
| 5529 |
+
"resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
|
| 5530 |
+
"integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
|
| 5531 |
+
"funding": [
|
| 5532 |
+
{
|
| 5533 |
+
"type": "GitHub Sponsors",
|
| 5534 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5535 |
+
},
|
| 5536 |
+
{
|
| 5537 |
+
"type": "OpenCollective",
|
| 5538 |
+
"url": "https://opencollective.com/unified"
|
| 5539 |
+
}
|
| 5540 |
+
],
|
| 5541 |
+
"license": "MIT",
|
| 5542 |
+
"dependencies": {
|
| 5543 |
+
"decode-named-character-reference": "^1.0.0",
|
| 5544 |
+
"devlop": "^1.0.0",
|
| 5545 |
+
"micromark-factory-destination": "^2.0.0",
|
| 5546 |
+
"micromark-factory-label": "^2.0.0",
|
| 5547 |
+
"micromark-factory-space": "^2.0.0",
|
| 5548 |
+
"micromark-factory-title": "^2.0.0",
|
| 5549 |
+
"micromark-factory-whitespace": "^2.0.0",
|
| 5550 |
+
"micromark-util-character": "^2.0.0",
|
| 5551 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5552 |
+
"micromark-util-classify-character": "^2.0.0",
|
| 5553 |
+
"micromark-util-html-tag-name": "^2.0.0",
|
| 5554 |
+
"micromark-util-normalize-identifier": "^2.0.0",
|
| 5555 |
+
"micromark-util-resolve-all": "^2.0.0",
|
| 5556 |
+
"micromark-util-subtokenize": "^2.0.0",
|
| 5557 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5558 |
+
"micromark-util-types": "^2.0.0"
|
| 5559 |
+
}
|
| 5560 |
+
},
|
| 5561 |
+
"node_modules/micromark-extension-gfm": {
|
| 5562 |
+
"version": "3.0.0",
|
| 5563 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
|
| 5564 |
+
"integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
|
| 5565 |
+
"license": "MIT",
|
| 5566 |
+
"dependencies": {
|
| 5567 |
+
"micromark-extension-gfm-autolink-literal": "^2.0.0",
|
| 5568 |
+
"micromark-extension-gfm-footnote": "^2.0.0",
|
| 5569 |
+
"micromark-extension-gfm-strikethrough": "^2.0.0",
|
| 5570 |
+
"micromark-extension-gfm-table": "^2.0.0",
|
| 5571 |
+
"micromark-extension-gfm-tagfilter": "^2.0.0",
|
| 5572 |
+
"micromark-extension-gfm-task-list-item": "^2.0.0",
|
| 5573 |
+
"micromark-util-combine-extensions": "^2.0.0",
|
| 5574 |
+
"micromark-util-types": "^2.0.0"
|
| 5575 |
+
},
|
| 5576 |
+
"funding": {
|
| 5577 |
+
"type": "opencollective",
|
| 5578 |
+
"url": "https://opencollective.com/unified"
|
| 5579 |
+
}
|
| 5580 |
+
},
|
| 5581 |
+
"node_modules/micromark-extension-gfm-autolink-literal": {
|
| 5582 |
+
"version": "2.1.0",
|
| 5583 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
|
| 5584 |
+
"integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
|
| 5585 |
+
"license": "MIT",
|
| 5586 |
+
"dependencies": {
|
| 5587 |
+
"micromark-util-character": "^2.0.0",
|
| 5588 |
+
"micromark-util-sanitize-uri": "^2.0.0",
|
| 5589 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5590 |
+
"micromark-util-types": "^2.0.0"
|
| 5591 |
+
},
|
| 5592 |
+
"funding": {
|
| 5593 |
+
"type": "opencollective",
|
| 5594 |
+
"url": "https://opencollective.com/unified"
|
| 5595 |
+
}
|
| 5596 |
+
},
|
| 5597 |
+
"node_modules/micromark-extension-gfm-footnote": {
|
| 5598 |
+
"version": "2.1.0",
|
| 5599 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
|
| 5600 |
+
"integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
|
| 5601 |
+
"license": "MIT",
|
| 5602 |
+
"dependencies": {
|
| 5603 |
+
"devlop": "^1.0.0",
|
| 5604 |
+
"micromark-core-commonmark": "^2.0.0",
|
| 5605 |
+
"micromark-factory-space": "^2.0.0",
|
| 5606 |
+
"micromark-util-character": "^2.0.0",
|
| 5607 |
+
"micromark-util-normalize-identifier": "^2.0.0",
|
| 5608 |
+
"micromark-util-sanitize-uri": "^2.0.0",
|
| 5609 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5610 |
+
"micromark-util-types": "^2.0.0"
|
| 5611 |
+
},
|
| 5612 |
+
"funding": {
|
| 5613 |
+
"type": "opencollective",
|
| 5614 |
+
"url": "https://opencollective.com/unified"
|
| 5615 |
+
}
|
| 5616 |
+
},
|
| 5617 |
+
"node_modules/micromark-extension-gfm-strikethrough": {
|
| 5618 |
+
"version": "2.1.0",
|
| 5619 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
|
| 5620 |
+
"integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
|
| 5621 |
+
"license": "MIT",
|
| 5622 |
+
"dependencies": {
|
| 5623 |
+
"devlop": "^1.0.0",
|
| 5624 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5625 |
+
"micromark-util-classify-character": "^2.0.0",
|
| 5626 |
+
"micromark-util-resolve-all": "^2.0.0",
|
| 5627 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5628 |
+
"micromark-util-types": "^2.0.0"
|
| 5629 |
+
},
|
| 5630 |
+
"funding": {
|
| 5631 |
+
"type": "opencollective",
|
| 5632 |
+
"url": "https://opencollective.com/unified"
|
| 5633 |
+
}
|
| 5634 |
+
},
|
| 5635 |
+
"node_modules/micromark-extension-gfm-table": {
|
| 5636 |
+
"version": "2.1.1",
|
| 5637 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
|
| 5638 |
+
"integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
|
| 5639 |
+
"license": "MIT",
|
| 5640 |
+
"dependencies": {
|
| 5641 |
+
"devlop": "^1.0.0",
|
| 5642 |
+
"micromark-factory-space": "^2.0.0",
|
| 5643 |
+
"micromark-util-character": "^2.0.0",
|
| 5644 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5645 |
+
"micromark-util-types": "^2.0.0"
|
| 5646 |
+
},
|
| 5647 |
+
"funding": {
|
| 5648 |
+
"type": "opencollective",
|
| 5649 |
+
"url": "https://opencollective.com/unified"
|
| 5650 |
+
}
|
| 5651 |
+
},
|
| 5652 |
+
"node_modules/micromark-extension-gfm-tagfilter": {
|
| 5653 |
+
"version": "2.0.0",
|
| 5654 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
|
| 5655 |
+
"integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
|
| 5656 |
+
"license": "MIT",
|
| 5657 |
+
"dependencies": {
|
| 5658 |
+
"micromark-util-types": "^2.0.0"
|
| 5659 |
+
},
|
| 5660 |
+
"funding": {
|
| 5661 |
+
"type": "opencollective",
|
| 5662 |
+
"url": "https://opencollective.com/unified"
|
| 5663 |
+
}
|
| 5664 |
+
},
|
| 5665 |
+
"node_modules/micromark-extension-gfm-task-list-item": {
|
| 5666 |
+
"version": "2.1.0",
|
| 5667 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
|
| 5668 |
+
"integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
|
| 5669 |
+
"license": "MIT",
|
| 5670 |
+
"dependencies": {
|
| 5671 |
+
"devlop": "^1.0.0",
|
| 5672 |
+
"micromark-factory-space": "^2.0.0",
|
| 5673 |
+
"micromark-util-character": "^2.0.0",
|
| 5674 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5675 |
+
"micromark-util-types": "^2.0.0"
|
| 5676 |
+
},
|
| 5677 |
+
"funding": {
|
| 5678 |
+
"type": "opencollective",
|
| 5679 |
+
"url": "https://opencollective.com/unified"
|
| 5680 |
+
}
|
| 5681 |
+
},
|
| 5682 |
+
"node_modules/micromark-factory-destination": {
|
| 5683 |
+
"version": "2.0.1",
|
| 5684 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
|
| 5685 |
+
"integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
|
| 5686 |
+
"funding": [
|
| 5687 |
+
{
|
| 5688 |
+
"type": "GitHub Sponsors",
|
| 5689 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5690 |
+
},
|
| 5691 |
+
{
|
| 5692 |
+
"type": "OpenCollective",
|
| 5693 |
+
"url": "https://opencollective.com/unified"
|
| 5694 |
+
}
|
| 5695 |
+
],
|
| 5696 |
+
"license": "MIT",
|
| 5697 |
+
"dependencies": {
|
| 5698 |
+
"micromark-util-character": "^2.0.0",
|
| 5699 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5700 |
+
"micromark-util-types": "^2.0.0"
|
| 5701 |
+
}
|
| 5702 |
+
},
|
| 5703 |
+
"node_modules/micromark-factory-label": {
|
| 5704 |
+
"version": "2.0.1",
|
| 5705 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
|
| 5706 |
+
"integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
|
| 5707 |
+
"funding": [
|
| 5708 |
+
{
|
| 5709 |
+
"type": "GitHub Sponsors",
|
| 5710 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5711 |
+
},
|
| 5712 |
+
{
|
| 5713 |
+
"type": "OpenCollective",
|
| 5714 |
+
"url": "https://opencollective.com/unified"
|
| 5715 |
+
}
|
| 5716 |
+
],
|
| 5717 |
+
"license": "MIT",
|
| 5718 |
+
"dependencies": {
|
| 5719 |
+
"devlop": "^1.0.0",
|
| 5720 |
+
"micromark-util-character": "^2.0.0",
|
| 5721 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5722 |
+
"micromark-util-types": "^2.0.0"
|
| 5723 |
+
}
|
| 5724 |
+
},
|
| 5725 |
+
"node_modules/micromark-factory-space": {
|
| 5726 |
+
"version": "2.0.1",
|
| 5727 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
|
| 5728 |
+
"integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
|
| 5729 |
+
"funding": [
|
| 5730 |
+
{
|
| 5731 |
+
"type": "GitHub Sponsors",
|
| 5732 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5733 |
+
},
|
| 5734 |
+
{
|
| 5735 |
+
"type": "OpenCollective",
|
| 5736 |
+
"url": "https://opencollective.com/unified"
|
| 5737 |
+
}
|
| 5738 |
+
],
|
| 5739 |
+
"license": "MIT",
|
| 5740 |
+
"dependencies": {
|
| 5741 |
+
"micromark-util-character": "^2.0.0",
|
| 5742 |
+
"micromark-util-types": "^2.0.0"
|
| 5743 |
+
}
|
| 5744 |
+
},
|
| 5745 |
+
"node_modules/micromark-factory-title": {
|
| 5746 |
+
"version": "2.0.1",
|
| 5747 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
|
| 5748 |
+
"integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
|
| 5749 |
+
"funding": [
|
| 5750 |
+
{
|
| 5751 |
+
"type": "GitHub Sponsors",
|
| 5752 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5753 |
+
},
|
| 5754 |
+
{
|
| 5755 |
+
"type": "OpenCollective",
|
| 5756 |
+
"url": "https://opencollective.com/unified"
|
| 5757 |
+
}
|
| 5758 |
+
],
|
| 5759 |
+
"license": "MIT",
|
| 5760 |
+
"dependencies": {
|
| 5761 |
+
"micromark-factory-space": "^2.0.0",
|
| 5762 |
+
"micromark-util-character": "^2.0.0",
|
| 5763 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5764 |
+
"micromark-util-types": "^2.0.0"
|
| 5765 |
+
}
|
| 5766 |
+
},
|
| 5767 |
+
"node_modules/micromark-factory-whitespace": {
|
| 5768 |
+
"version": "2.0.1",
|
| 5769 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
|
| 5770 |
+
"integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
|
| 5771 |
+
"funding": [
|
| 5772 |
+
{
|
| 5773 |
+
"type": "GitHub Sponsors",
|
| 5774 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5775 |
+
},
|
| 5776 |
+
{
|
| 5777 |
+
"type": "OpenCollective",
|
| 5778 |
+
"url": "https://opencollective.com/unified"
|
| 5779 |
+
}
|
| 5780 |
+
],
|
| 5781 |
+
"license": "MIT",
|
| 5782 |
+
"dependencies": {
|
| 5783 |
+
"micromark-factory-space": "^2.0.0",
|
| 5784 |
+
"micromark-util-character": "^2.0.0",
|
| 5785 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5786 |
+
"micromark-util-types": "^2.0.0"
|
| 5787 |
+
}
|
| 5788 |
+
},
|
| 5789 |
+
"node_modules/micromark-util-character": {
|
| 5790 |
+
"version": "2.1.1",
|
| 5791 |
+
"resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
|
| 5792 |
+
"integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
|
| 5793 |
+
"funding": [
|
| 5794 |
+
{
|
| 5795 |
+
"type": "GitHub Sponsors",
|
| 5796 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5797 |
+
},
|
| 5798 |
+
{
|
| 5799 |
+
"type": "OpenCollective",
|
| 5800 |
+
"url": "https://opencollective.com/unified"
|
| 5801 |
+
}
|
| 5802 |
+
],
|
| 5803 |
+
"license": "MIT",
|
| 5804 |
+
"dependencies": {
|
| 5805 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5806 |
+
"micromark-util-types": "^2.0.0"
|
| 5807 |
+
}
|
| 5808 |
+
},
|
| 5809 |
+
"node_modules/micromark-util-chunked": {
|
| 5810 |
+
"version": "2.0.1",
|
| 5811 |
+
"resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
|
| 5812 |
+
"integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
|
| 5813 |
+
"funding": [
|
| 5814 |
+
{
|
| 5815 |
+
"type": "GitHub Sponsors",
|
| 5816 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5817 |
+
},
|
| 5818 |
+
{
|
| 5819 |
+
"type": "OpenCollective",
|
| 5820 |
+
"url": "https://opencollective.com/unified"
|
| 5821 |
+
}
|
| 5822 |
+
],
|
| 5823 |
+
"license": "MIT",
|
| 5824 |
+
"dependencies": {
|
| 5825 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5826 |
+
}
|
| 5827 |
+
},
|
| 5828 |
+
"node_modules/micromark-util-classify-character": {
|
| 5829 |
+
"version": "2.0.1",
|
| 5830 |
+
"resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
|
| 5831 |
+
"integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
|
| 5832 |
+
"funding": [
|
| 5833 |
+
{
|
| 5834 |
+
"type": "GitHub Sponsors",
|
| 5835 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5836 |
+
},
|
| 5837 |
+
{
|
| 5838 |
+
"type": "OpenCollective",
|
| 5839 |
+
"url": "https://opencollective.com/unified"
|
| 5840 |
+
}
|
| 5841 |
+
],
|
| 5842 |
+
"license": "MIT",
|
| 5843 |
+
"dependencies": {
|
| 5844 |
+
"micromark-util-character": "^2.0.0",
|
| 5845 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5846 |
+
"micromark-util-types": "^2.0.0"
|
| 5847 |
+
}
|
| 5848 |
+
},
|
| 5849 |
+
"node_modules/micromark-util-combine-extensions": {
|
| 5850 |
+
"version": "2.0.1",
|
| 5851 |
+
"resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
|
| 5852 |
+
"integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
|
| 5853 |
+
"funding": [
|
| 5854 |
+
{
|
| 5855 |
+
"type": "GitHub Sponsors",
|
| 5856 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5857 |
+
},
|
| 5858 |
+
{
|
| 5859 |
+
"type": "OpenCollective",
|
| 5860 |
+
"url": "https://opencollective.com/unified"
|
| 5861 |
+
}
|
| 5862 |
+
],
|
| 5863 |
+
"license": "MIT",
|
| 5864 |
+
"dependencies": {
|
| 5865 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5866 |
+
"micromark-util-types": "^2.0.0"
|
| 5867 |
+
}
|
| 5868 |
+
},
|
| 5869 |
+
"node_modules/micromark-util-decode-numeric-character-reference": {
|
| 5870 |
+
"version": "2.0.2",
|
| 5871 |
+
"resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
|
| 5872 |
+
"integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
|
| 5873 |
+
"funding": [
|
| 5874 |
+
{
|
| 5875 |
+
"type": "GitHub Sponsors",
|
| 5876 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5877 |
+
},
|
| 5878 |
+
{
|
| 5879 |
+
"type": "OpenCollective",
|
| 5880 |
+
"url": "https://opencollective.com/unified"
|
| 5881 |
+
}
|
| 5882 |
+
],
|
| 5883 |
+
"license": "MIT",
|
| 5884 |
+
"dependencies": {
|
| 5885 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5886 |
+
}
|
| 5887 |
+
},
|
| 5888 |
+
"node_modules/micromark-util-decode-string": {
|
| 5889 |
+
"version": "2.0.1",
|
| 5890 |
+
"resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
|
| 5891 |
+
"integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
|
| 5892 |
+
"funding": [
|
| 5893 |
+
{
|
| 5894 |
+
"type": "GitHub Sponsors",
|
| 5895 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5896 |
+
},
|
| 5897 |
+
{
|
| 5898 |
+
"type": "OpenCollective",
|
| 5899 |
+
"url": "https://opencollective.com/unified"
|
| 5900 |
+
}
|
| 5901 |
+
],
|
| 5902 |
+
"license": "MIT",
|
| 5903 |
+
"dependencies": {
|
| 5904 |
+
"decode-named-character-reference": "^1.0.0",
|
| 5905 |
+
"micromark-util-character": "^2.0.0",
|
| 5906 |
+
"micromark-util-decode-numeric-character-reference": "^2.0.0",
|
| 5907 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5908 |
+
}
|
| 5909 |
+
},
|
| 5910 |
+
"node_modules/micromark-util-encode": {
|
| 5911 |
+
"version": "2.0.1",
|
| 5912 |
+
"resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
|
| 5913 |
+
"integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
|
| 5914 |
+
"funding": [
|
| 5915 |
+
{
|
| 5916 |
+
"type": "GitHub Sponsors",
|
| 5917 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5918 |
+
},
|
| 5919 |
+
{
|
| 5920 |
+
"type": "OpenCollective",
|
| 5921 |
+
"url": "https://opencollective.com/unified"
|
| 5922 |
+
}
|
| 5923 |
+
],
|
| 5924 |
+
"license": "MIT"
|
| 5925 |
+
},
|
| 5926 |
+
"node_modules/micromark-util-html-tag-name": {
|
| 5927 |
+
"version": "2.0.1",
|
| 5928 |
+
"resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
|
| 5929 |
+
"integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
|
| 5930 |
+
"funding": [
|
| 5931 |
+
{
|
| 5932 |
+
"type": "GitHub Sponsors",
|
| 5933 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5934 |
+
},
|
| 5935 |
+
{
|
| 5936 |
+
"type": "OpenCollective",
|
| 5937 |
+
"url": "https://opencollective.com/unified"
|
| 5938 |
+
}
|
| 5939 |
+
],
|
| 5940 |
+
"license": "MIT"
|
| 5941 |
+
},
|
| 5942 |
+
"node_modules/micromark-util-normalize-identifier": {
|
| 5943 |
+
"version": "2.0.1",
|
| 5944 |
+
"resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
|
| 5945 |
+
"integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
|
| 5946 |
+
"funding": [
|
| 5947 |
+
{
|
| 5948 |
+
"type": "GitHub Sponsors",
|
| 5949 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5950 |
+
},
|
| 5951 |
+
{
|
| 5952 |
+
"type": "OpenCollective",
|
| 5953 |
+
"url": "https://opencollective.com/unified"
|
| 5954 |
+
}
|
| 5955 |
+
],
|
| 5956 |
+
"license": "MIT",
|
| 5957 |
+
"dependencies": {
|
| 5958 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5959 |
+
}
|
| 5960 |
+
},
|
| 5961 |
+
"node_modules/micromark-util-resolve-all": {
|
| 5962 |
+
"version": "2.0.1",
|
| 5963 |
+
"resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
|
| 5964 |
+
"integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
|
| 5965 |
+
"funding": [
|
| 5966 |
+
{
|
| 5967 |
+
"type": "GitHub Sponsors",
|
| 5968 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5969 |
+
},
|
| 5970 |
+
{
|
| 5971 |
+
"type": "OpenCollective",
|
| 5972 |
+
"url": "https://opencollective.com/unified"
|
| 5973 |
+
}
|
| 5974 |
+
],
|
| 5975 |
+
"license": "MIT",
|
| 5976 |
+
"dependencies": {
|
| 5977 |
+
"micromark-util-types": "^2.0.0"
|
| 5978 |
+
}
|
| 5979 |
+
},
|
| 5980 |
+
"node_modules/micromark-util-sanitize-uri": {
|
| 5981 |
+
"version": "2.0.1",
|
| 5982 |
+
"resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
|
| 5983 |
+
"integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
|
| 5984 |
+
"funding": [
|
| 5985 |
+
{
|
| 5986 |
+
"type": "GitHub Sponsors",
|
| 5987 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5988 |
+
},
|
| 5989 |
+
{
|
| 5990 |
+
"type": "OpenCollective",
|
| 5991 |
+
"url": "https://opencollective.com/unified"
|
| 5992 |
+
}
|
| 5993 |
+
],
|
| 5994 |
+
"license": "MIT",
|
| 5995 |
+
"dependencies": {
|
| 5996 |
+
"micromark-util-character": "^2.0.0",
|
| 5997 |
+
"micromark-util-encode": "^2.0.0",
|
| 5998 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5999 |
+
}
|
| 6000 |
+
},
|
| 6001 |
+
"node_modules/micromark-util-subtokenize": {
|
| 6002 |
+
"version": "2.1.0",
|
| 6003 |
+
"resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
|
| 6004 |
+
"integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
|
| 6005 |
+
"funding": [
|
| 6006 |
+
{
|
| 6007 |
+
"type": "GitHub Sponsors",
|
| 6008 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 6009 |
+
},
|
| 6010 |
+
{
|
| 6011 |
+
"type": "OpenCollective",
|
| 6012 |
+
"url": "https://opencollective.com/unified"
|
| 6013 |
+
}
|
| 6014 |
+
],
|
| 6015 |
+
"license": "MIT",
|
| 6016 |
+
"dependencies": {
|
| 6017 |
+
"devlop": "^1.0.0",
|
| 6018 |
+
"micromark-util-chunked": "^2.0.0",
|
| 6019 |
+
"micromark-util-symbol": "^2.0.0",
|
| 6020 |
+
"micromark-util-types": "^2.0.0"
|
| 6021 |
+
}
|
| 6022 |
+
},
|
| 6023 |
+
"node_modules/micromark-util-symbol": {
|
| 6024 |
+
"version": "2.0.1",
|
| 6025 |
+
"resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
|
| 6026 |
+
"integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
|
| 6027 |
+
"funding": [
|
| 6028 |
+
{
|
| 6029 |
+
"type": "GitHub Sponsors",
|
| 6030 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 6031 |
+
},
|
| 6032 |
+
{
|
| 6033 |
+
"type": "OpenCollective",
|
| 6034 |
+
"url": "https://opencollective.com/unified"
|
| 6035 |
+
}
|
| 6036 |
+
],
|
| 6037 |
+
"license": "MIT"
|
| 6038 |
+
},
|
| 6039 |
+
"node_modules/micromark-util-types": {
|
| 6040 |
+
"version": "2.0.2",
|
| 6041 |
+
"resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
|
| 6042 |
+
"integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
|
| 6043 |
+
"funding": [
|
| 6044 |
+
{
|
| 6045 |
+
"type": "GitHub Sponsors",
|
| 6046 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 6047 |
+
},
|
| 6048 |
+
{
|
| 6049 |
+
"type": "OpenCollective",
|
| 6050 |
+
"url": "https://opencollective.com/unified"
|
| 6051 |
+
}
|
| 6052 |
+
],
|
| 6053 |
+
"license": "MIT"
|
| 6054 |
+
},
|
| 6055 |
+
"node_modules/micromatch": {
|
| 6056 |
+
"version": "4.0.8",
|
| 6057 |
+
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
| 6058 |
+
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
| 6059 |
+
"dev": true,
|
| 6060 |
+
"license": "MIT",
|
| 6061 |
+
"dependencies": {
|
| 6062 |
+
"braces": "^3.0.3",
|
| 6063 |
+
"picomatch": "^2.3.1"
|
| 6064 |
+
},
|
| 6065 |
+
"engines": {
|
| 6066 |
+
"node": ">=8.6"
|
| 6067 |
+
}
|
| 6068 |
+
},
|
| 6069 |
+
"node_modules/minimatch": {
|
| 6070 |
+
"version": "3.1.2",
|
| 6071 |
+
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
| 6072 |
+
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
| 6073 |
+
"dev": true,
|
| 6074 |
+
"license": "ISC",
|
| 6075 |
+
"dependencies": {
|
| 6076 |
+
"brace-expansion": "^1.1.7"
|
| 6077 |
+
},
|
| 6078 |
+
"engines": {
|
| 6079 |
+
"node": "*"
|
| 6080 |
+
}
|
| 6081 |
+
},
|
| 6082 |
+
"node_modules/minimist": {
|
| 6083 |
+
"version": "1.2.8",
|
| 6084 |
+
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
| 6085 |
+
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
| 6086 |
+
"dev": true,
|
| 6087 |
+
"license": "MIT",
|
| 6088 |
+
"funding": {
|
| 6089 |
+
"url": "https://github.com/sponsors/ljharb"
|
| 6090 |
+
}
|
| 6091 |
+
},
|
| 6092 |
+
"node_modules/ms": {
|
| 6093 |
+
"version": "2.1.3",
|
| 6094 |
+
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
| 6095 |
+
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
| 6096 |
+
"license": "MIT"
|
| 6097 |
+
},
|
| 6098 |
+
"node_modules/nanoid": {
|
| 6099 |
+
"version": "3.3.11",
|
| 6100 |
+
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
| 6101 |
+
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
| 6102 |
"funding": [
|
| 6103 |
{
|
| 6104 |
"type": "github",
|
|
|
|
| 6347 |
"url": "https://github.com/sponsors/ljharb"
|
| 6348 |
}
|
| 6349 |
},
|
| 6350 |
+
"node_modules/openai": {
|
| 6351 |
+
"version": "6.15.0",
|
| 6352 |
+
"resolved": "https://registry.npmjs.org/openai/-/openai-6.15.0.tgz",
|
| 6353 |
+
"integrity": "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g==",
|
| 6354 |
+
"license": "Apache-2.0",
|
| 6355 |
+
"bin": {
|
| 6356 |
+
"openai": "bin/cli"
|
| 6357 |
+
},
|
| 6358 |
+
"peerDependencies": {
|
| 6359 |
+
"ws": "^8.18.0",
|
| 6360 |
+
"zod": "^3.25 || ^4.0"
|
| 6361 |
+
},
|
| 6362 |
+
"peerDependenciesMeta": {
|
| 6363 |
+
"ws": {
|
| 6364 |
+
"optional": true
|
| 6365 |
+
},
|
| 6366 |
+
"zod": {
|
| 6367 |
+
"optional": true
|
| 6368 |
+
}
|
| 6369 |
+
}
|
| 6370 |
+
},
|
| 6371 |
"node_modules/optionator": {
|
| 6372 |
"version": "0.9.4",
|
| 6373 |
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
|
|
|
| 6449 |
"node": ">=6"
|
| 6450 |
}
|
| 6451 |
},
|
| 6452 |
+
"node_modules/parse-entities": {
|
| 6453 |
+
"version": "4.0.2",
|
| 6454 |
+
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
|
| 6455 |
+
"integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
|
| 6456 |
+
"license": "MIT",
|
| 6457 |
+
"dependencies": {
|
| 6458 |
+
"@types/unist": "^2.0.0",
|
| 6459 |
+
"character-entities-legacy": "^3.0.0",
|
| 6460 |
+
"character-reference-invalid": "^2.0.0",
|
| 6461 |
+
"decode-named-character-reference": "^1.0.0",
|
| 6462 |
+
"is-alphanumerical": "^2.0.0",
|
| 6463 |
+
"is-decimal": "^2.0.0",
|
| 6464 |
+
"is-hexadecimal": "^2.0.0"
|
| 6465 |
+
},
|
| 6466 |
+
"funding": {
|
| 6467 |
+
"type": "github",
|
| 6468 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 6469 |
+
}
|
| 6470 |
+
},
|
| 6471 |
+
"node_modules/parse-entities/node_modules/@types/unist": {
|
| 6472 |
+
"version": "2.0.11",
|
| 6473 |
+
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
|
| 6474 |
+
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
|
| 6475 |
+
"license": "MIT"
|
| 6476 |
+
},
|
| 6477 |
"node_modules/path-exists": {
|
| 6478 |
"version": "4.0.0",
|
| 6479 |
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
|
|
|
| 6581 |
"react-is": "^16.13.1"
|
| 6582 |
}
|
| 6583 |
},
|
| 6584 |
+
"node_modules/property-information": {
|
| 6585 |
+
"version": "7.1.0",
|
| 6586 |
+
"resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
|
| 6587 |
+
"integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==",
|
| 6588 |
+
"license": "MIT",
|
| 6589 |
+
"funding": {
|
| 6590 |
+
"type": "github",
|
| 6591 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 6592 |
+
}
|
| 6593 |
+
},
|
| 6594 |
"node_modules/punycode": {
|
| 6595 |
"version": "2.3.1",
|
| 6596 |
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
|
|
|
| 6652 |
"dev": true,
|
| 6653 |
"license": "MIT"
|
| 6654 |
},
|
| 6655 |
+
"node_modules/react-markdown": {
|
| 6656 |
+
"version": "10.1.0",
|
| 6657 |
+
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz",
|
| 6658 |
+
"integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==",
|
| 6659 |
+
"license": "MIT",
|
| 6660 |
+
"dependencies": {
|
| 6661 |
+
"@types/hast": "^3.0.0",
|
| 6662 |
+
"@types/mdast": "^4.0.0",
|
| 6663 |
+
"devlop": "^1.0.0",
|
| 6664 |
+
"hast-util-to-jsx-runtime": "^2.0.0",
|
| 6665 |
+
"html-url-attributes": "^3.0.0",
|
| 6666 |
+
"mdast-util-to-hast": "^13.0.0",
|
| 6667 |
+
"remark-parse": "^11.0.0",
|
| 6668 |
+
"remark-rehype": "^11.0.0",
|
| 6669 |
+
"unified": "^11.0.0",
|
| 6670 |
+
"unist-util-visit": "^5.0.0",
|
| 6671 |
+
"vfile": "^6.0.0"
|
| 6672 |
+
},
|
| 6673 |
+
"funding": {
|
| 6674 |
+
"type": "opencollective",
|
| 6675 |
+
"url": "https://opencollective.com/unified"
|
| 6676 |
+
},
|
| 6677 |
+
"peerDependencies": {
|
| 6678 |
+
"@types/react": ">=18",
|
| 6679 |
+
"react": ">=18"
|
| 6680 |
+
}
|
| 6681 |
+
},
|
| 6682 |
"node_modules/reflect.getprototypeof": {
|
| 6683 |
"version": "1.0.10",
|
| 6684 |
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
|
|
|
| 6723 |
"url": "https://github.com/sponsors/ljharb"
|
| 6724 |
}
|
| 6725 |
},
|
| 6726 |
+
"node_modules/remark-gfm": {
|
| 6727 |
+
"version": "4.0.1",
|
| 6728 |
+
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
|
| 6729 |
+
"integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
|
| 6730 |
+
"license": "MIT",
|
| 6731 |
+
"dependencies": {
|
| 6732 |
+
"@types/mdast": "^4.0.0",
|
| 6733 |
+
"mdast-util-gfm": "^3.0.0",
|
| 6734 |
+
"micromark-extension-gfm": "^3.0.0",
|
| 6735 |
+
"remark-parse": "^11.0.0",
|
| 6736 |
+
"remark-stringify": "^11.0.0",
|
| 6737 |
+
"unified": "^11.0.0"
|
| 6738 |
+
},
|
| 6739 |
+
"funding": {
|
| 6740 |
+
"type": "opencollective",
|
| 6741 |
+
"url": "https://opencollective.com/unified"
|
| 6742 |
+
}
|
| 6743 |
+
},
|
| 6744 |
+
"node_modules/remark-parse": {
|
| 6745 |
+
"version": "11.0.0",
|
| 6746 |
+
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
|
| 6747 |
+
"integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
|
| 6748 |
+
"license": "MIT",
|
| 6749 |
+
"dependencies": {
|
| 6750 |
+
"@types/mdast": "^4.0.0",
|
| 6751 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 6752 |
+
"micromark-util-types": "^2.0.0",
|
| 6753 |
+
"unified": "^11.0.0"
|
| 6754 |
+
},
|
| 6755 |
+
"funding": {
|
| 6756 |
+
"type": "opencollective",
|
| 6757 |
+
"url": "https://opencollective.com/unified"
|
| 6758 |
+
}
|
| 6759 |
+
},
|
| 6760 |
+
"node_modules/remark-rehype": {
|
| 6761 |
+
"version": "11.1.2",
|
| 6762 |
+
"resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
|
| 6763 |
+
"integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
|
| 6764 |
+
"license": "MIT",
|
| 6765 |
+
"dependencies": {
|
| 6766 |
+
"@types/hast": "^3.0.0",
|
| 6767 |
+
"@types/mdast": "^4.0.0",
|
| 6768 |
+
"mdast-util-to-hast": "^13.0.0",
|
| 6769 |
+
"unified": "^11.0.0",
|
| 6770 |
+
"vfile": "^6.0.0"
|
| 6771 |
+
},
|
| 6772 |
+
"funding": {
|
| 6773 |
+
"type": "opencollective",
|
| 6774 |
+
"url": "https://opencollective.com/unified"
|
| 6775 |
+
}
|
| 6776 |
+
},
|
| 6777 |
+
"node_modules/remark-stringify": {
|
| 6778 |
+
"version": "11.0.0",
|
| 6779 |
+
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
|
| 6780 |
+
"integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
|
| 6781 |
+
"license": "MIT",
|
| 6782 |
+
"dependencies": {
|
| 6783 |
+
"@types/mdast": "^4.0.0",
|
| 6784 |
+
"mdast-util-to-markdown": "^2.0.0",
|
| 6785 |
+
"unified": "^11.0.0"
|
| 6786 |
+
},
|
| 6787 |
+
"funding": {
|
| 6788 |
+
"type": "opencollective",
|
| 6789 |
+
"url": "https://opencollective.com/unified"
|
| 6790 |
+
}
|
| 6791 |
+
},
|
| 6792 |
"node_modules/resolve": {
|
| 6793 |
"version": "1.22.11",
|
| 6794 |
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
|
|
|
|
| 7151 |
"node": ">=0.10.0"
|
| 7152 |
}
|
| 7153 |
},
|
| 7154 |
+
"node_modules/space-separated-tokens": {
|
| 7155 |
+
"version": "2.0.2",
|
| 7156 |
+
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
|
| 7157 |
+
"integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
|
| 7158 |
+
"license": "MIT",
|
| 7159 |
+
"funding": {
|
| 7160 |
+
"type": "github",
|
| 7161 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 7162 |
+
}
|
| 7163 |
+
},
|
| 7164 |
"node_modules/stable-hash": {
|
| 7165 |
"version": "0.0.5",
|
| 7166 |
"resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
|
|
|
|
| 7295 |
"url": "https://github.com/sponsors/ljharb"
|
| 7296 |
}
|
| 7297 |
},
|
| 7298 |
+
"node_modules/stringify-entities": {
|
| 7299 |
+
"version": "4.0.4",
|
| 7300 |
+
"resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
|
| 7301 |
+
"integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
|
| 7302 |
+
"license": "MIT",
|
| 7303 |
+
"dependencies": {
|
| 7304 |
+
"character-entities-html4": "^2.0.0",
|
| 7305 |
+
"character-entities-legacy": "^3.0.0"
|
| 7306 |
+
},
|
| 7307 |
+
"funding": {
|
| 7308 |
+
"type": "github",
|
| 7309 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 7310 |
+
}
|
| 7311 |
+
},
|
| 7312 |
"node_modules/strip-bom": {
|
| 7313 |
"version": "3.0.0",
|
| 7314 |
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
|
|
|
| 7332 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 7333 |
}
|
| 7334 |
},
|
| 7335 |
+
"node_modules/style-to-js": {
|
| 7336 |
+
"version": "1.1.21",
|
| 7337 |
+
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
|
| 7338 |
+
"integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==",
|
| 7339 |
+
"license": "MIT",
|
| 7340 |
+
"dependencies": {
|
| 7341 |
+
"style-to-object": "1.0.14"
|
| 7342 |
+
}
|
| 7343 |
+
},
|
| 7344 |
+
"node_modules/style-to-object": {
|
| 7345 |
+
"version": "1.0.14",
|
| 7346 |
+
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz",
|
| 7347 |
+
"integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==",
|
| 7348 |
+
"license": "MIT",
|
| 7349 |
+
"dependencies": {
|
| 7350 |
+
"inline-style-parser": "0.2.7"
|
| 7351 |
+
}
|
| 7352 |
+
},
|
| 7353 |
"node_modules/styled-jsx": {
|
| 7354 |
"version": "5.1.6",
|
| 7355 |
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
|
|
|
|
| 7399 |
"url": "https://github.com/sponsors/ljharb"
|
| 7400 |
}
|
| 7401 |
},
|
| 7402 |
+
"node_modules/tailwind-merge": {
|
| 7403 |
+
"version": "3.4.0",
|
| 7404 |
+
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
|
| 7405 |
+
"integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==",
|
| 7406 |
+
"license": "MIT",
|
| 7407 |
+
"funding": {
|
| 7408 |
+
"type": "github",
|
| 7409 |
+
"url": "https://github.com/sponsors/dcastil"
|
| 7410 |
+
}
|
| 7411 |
+
},
|
| 7412 |
"node_modules/tailwindcss": {
|
| 7413 |
"version": "4.1.18",
|
| 7414 |
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
|
|
|
| 7492 |
"node": ">=8.0"
|
| 7493 |
}
|
| 7494 |
},
|
| 7495 |
+
"node_modules/trim-lines": {
|
| 7496 |
+
"version": "3.0.1",
|
| 7497 |
+
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
| 7498 |
+
"integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
|
| 7499 |
+
"license": "MIT",
|
| 7500 |
+
"funding": {
|
| 7501 |
+
"type": "github",
|
| 7502 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 7503 |
+
}
|
| 7504 |
+
},
|
| 7505 |
+
"node_modules/trough": {
|
| 7506 |
+
"version": "2.2.0",
|
| 7507 |
+
"resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
|
| 7508 |
+
"integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
|
| 7509 |
+
"license": "MIT",
|
| 7510 |
+
"funding": {
|
| 7511 |
+
"type": "github",
|
| 7512 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 7513 |
+
}
|
| 7514 |
+
},
|
| 7515 |
"node_modules/ts-api-utils": {
|
| 7516 |
"version": "2.1.0",
|
| 7517 |
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
|
|
|
| 7713 |
"dev": true,
|
| 7714 |
"license": "MIT"
|
| 7715 |
},
|
| 7716 |
+
"node_modules/unified": {
|
| 7717 |
+
"version": "11.0.5",
|
| 7718 |
+
"resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
|
| 7719 |
+
"integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
|
| 7720 |
+
"license": "MIT",
|
| 7721 |
+
"dependencies": {
|
| 7722 |
+
"@types/unist": "^3.0.0",
|
| 7723 |
+
"bail": "^2.0.0",
|
| 7724 |
+
"devlop": "^1.0.0",
|
| 7725 |
+
"extend": "^3.0.0",
|
| 7726 |
+
"is-plain-obj": "^4.0.0",
|
| 7727 |
+
"trough": "^2.0.0",
|
| 7728 |
+
"vfile": "^6.0.0"
|
| 7729 |
+
},
|
| 7730 |
+
"funding": {
|
| 7731 |
+
"type": "opencollective",
|
| 7732 |
+
"url": "https://opencollective.com/unified"
|
| 7733 |
+
}
|
| 7734 |
+
},
|
| 7735 |
+
"node_modules/unist-util-is": {
|
| 7736 |
+
"version": "6.0.1",
|
| 7737 |
+
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
|
| 7738 |
+
"integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
|
| 7739 |
+
"license": "MIT",
|
| 7740 |
+
"dependencies": {
|
| 7741 |
+
"@types/unist": "^3.0.0"
|
| 7742 |
+
},
|
| 7743 |
+
"funding": {
|
| 7744 |
+
"type": "opencollective",
|
| 7745 |
+
"url": "https://opencollective.com/unified"
|
| 7746 |
+
}
|
| 7747 |
+
},
|
| 7748 |
+
"node_modules/unist-util-position": {
|
| 7749 |
+
"version": "5.0.0",
|
| 7750 |
+
"resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
|
| 7751 |
+
"integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
|
| 7752 |
+
"license": "MIT",
|
| 7753 |
+
"dependencies": {
|
| 7754 |
+
"@types/unist": "^3.0.0"
|
| 7755 |
+
},
|
| 7756 |
+
"funding": {
|
| 7757 |
+
"type": "opencollective",
|
| 7758 |
+
"url": "https://opencollective.com/unified"
|
| 7759 |
+
}
|
| 7760 |
+
},
|
| 7761 |
+
"node_modules/unist-util-stringify-position": {
|
| 7762 |
+
"version": "4.0.0",
|
| 7763 |
+
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
|
| 7764 |
+
"integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
|
| 7765 |
+
"license": "MIT",
|
| 7766 |
+
"dependencies": {
|
| 7767 |
+
"@types/unist": "^3.0.0"
|
| 7768 |
+
},
|
| 7769 |
+
"funding": {
|
| 7770 |
+
"type": "opencollective",
|
| 7771 |
+
"url": "https://opencollective.com/unified"
|
| 7772 |
+
}
|
| 7773 |
+
},
|
| 7774 |
+
"node_modules/unist-util-visit": {
|
| 7775 |
+
"version": "5.0.0",
|
| 7776 |
+
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
|
| 7777 |
+
"integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
|
| 7778 |
+
"license": "MIT",
|
| 7779 |
+
"dependencies": {
|
| 7780 |
+
"@types/unist": "^3.0.0",
|
| 7781 |
+
"unist-util-is": "^6.0.0",
|
| 7782 |
+
"unist-util-visit-parents": "^6.0.0"
|
| 7783 |
+
},
|
| 7784 |
+
"funding": {
|
| 7785 |
+
"type": "opencollective",
|
| 7786 |
+
"url": "https://opencollective.com/unified"
|
| 7787 |
+
}
|
| 7788 |
+
},
|
| 7789 |
+
"node_modules/unist-util-visit-parents": {
|
| 7790 |
+
"version": "6.0.2",
|
| 7791 |
+
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
|
| 7792 |
+
"integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
|
| 7793 |
+
"license": "MIT",
|
| 7794 |
+
"dependencies": {
|
| 7795 |
+
"@types/unist": "^3.0.0",
|
| 7796 |
+
"unist-util-is": "^6.0.0"
|
| 7797 |
+
},
|
| 7798 |
+
"funding": {
|
| 7799 |
+
"type": "opencollective",
|
| 7800 |
+
"url": "https://opencollective.com/unified"
|
| 7801 |
+
}
|
| 7802 |
+
},
|
| 7803 |
"node_modules/unrs-resolver": {
|
| 7804 |
"version": "1.11.1",
|
| 7805 |
"resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
|
|
|
|
| 7876 |
"punycode": "^2.1.0"
|
| 7877 |
}
|
| 7878 |
},
|
| 7879 |
+
"node_modules/vfile": {
|
| 7880 |
+
"version": "6.0.3",
|
| 7881 |
+
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
|
| 7882 |
+
"integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
|
| 7883 |
+
"license": "MIT",
|
| 7884 |
+
"dependencies": {
|
| 7885 |
+
"@types/unist": "^3.0.0",
|
| 7886 |
+
"vfile-message": "^4.0.0"
|
| 7887 |
+
},
|
| 7888 |
+
"funding": {
|
| 7889 |
+
"type": "opencollective",
|
| 7890 |
+
"url": "https://opencollective.com/unified"
|
| 7891 |
+
}
|
| 7892 |
+
},
|
| 7893 |
+
"node_modules/vfile-message": {
|
| 7894 |
+
"version": "4.0.3",
|
| 7895 |
+
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
|
| 7896 |
+
"integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
|
| 7897 |
+
"license": "MIT",
|
| 7898 |
+
"dependencies": {
|
| 7899 |
+
"@types/unist": "^3.0.0",
|
| 7900 |
+
"unist-util-stringify-position": "^4.0.0"
|
| 7901 |
+
},
|
| 7902 |
+
"funding": {
|
| 7903 |
+
"type": "opencollective",
|
| 7904 |
+
"url": "https://opencollective.com/unified"
|
| 7905 |
+
}
|
| 7906 |
+
},
|
| 7907 |
"node_modules/which": {
|
| 7908 |
"version": "2.0.2",
|
| 7909 |
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
|
|
| 8043 |
"version": "4.2.1",
|
| 8044 |
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
|
| 8045 |
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
|
| 8046 |
+
"devOptional": true,
|
| 8047 |
"license": "MIT",
|
| 8048 |
"peer": true,
|
| 8049 |
"funding": {
|
|
|
|
| 8062 |
"peerDependencies": {
|
| 8063 |
"zod": "^3.25.0 || ^4.0.0"
|
| 8064 |
}
|
| 8065 |
+
},
|
| 8066 |
+
"node_modules/zwitch": {
|
| 8067 |
+
"version": "2.0.4",
|
| 8068 |
+
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
| 8069 |
+
"integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
|
| 8070 |
+
"license": "MIT",
|
| 8071 |
+
"funding": {
|
| 8072 |
+
"type": "github",
|
| 8073 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 8074 |
+
}
|
| 8075 |
}
|
| 8076 |
}
|
| 8077 |
}
|
package.json
CHANGED
|
@@ -9,9 +9,16 @@
|
|
| 9 |
"lint": "eslint"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
| 12 |
"next": "16.1.1",
|
|
|
|
| 13 |
"react": "19.2.3",
|
| 14 |
-
"react-dom": "19.2.3"
|
|
|
|
|
|
|
|
|
|
| 15 |
},
|
| 16 |
"devDependencies": {
|
| 17 |
"@tailwindcss/postcss": "^4",
|
|
|
|
| 9 |
"lint": "eslint"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
| 12 |
+
"@google/generative-ai": "^0.24.1",
|
| 13 |
+
"clsx": "^2.1.1",
|
| 14 |
+
"lucide-react": "^0.562.0",
|
| 15 |
"next": "16.1.1",
|
| 16 |
+
"openai": "^6.15.0",
|
| 17 |
"react": "19.2.3",
|
| 18 |
+
"react-dom": "19.2.3",
|
| 19 |
+
"react-markdown": "^10.1.0",
|
| 20 |
+
"remark-gfm": "^4.0.1",
|
| 21 |
+
"tailwind-merge": "^3.4.0"
|
| 22 |
},
|
| 23 |
"devDependencies": {
|
| 24 |
"@tailwindcss/postcss": "^4",
|
src/app/api/analyze/route.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import { NextRequest, NextResponse } from 'next/server';
|
| 3 |
+
import { GoogleGenerativeAI } from '@google/generative-ai';
|
| 4 |
+
import fs from 'fs';
|
| 5 |
+
import path from 'path';
|
| 6 |
+
|
| 7 |
+
// Initialize Gemini
|
| 8 |
+
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY || '');
|
| 9 |
+
|
| 10 |
+
export async function POST(req: NextRequest) {
|
| 11 |
+
try {
|
| 12 |
+
const formData = await req.formData();
|
| 13 |
+
const file = formData.get('file') as File | null;
|
| 14 |
+
const textInput = formData.get('text') as string | null;
|
| 15 |
+
|
| 16 |
+
const apiKey = process.env.GEMINI_API_KEY;
|
| 17 |
+
|
| 18 |
+
// Debug Logging
|
| 19 |
+
console.log("--- API DEBUG INFO ---");
|
| 20 |
+
console.log("API Key Loaded:", !!apiKey);
|
| 21 |
+
console.log("API Key Start:", apiKey ? apiKey.substring(0, 4) + "****" : "N/A");
|
| 22 |
+
|
| 23 |
+
if (!apiKey || apiKey.includes('YOUR_GEMINI_API_KEY') || apiKey.length < 20) {
|
| 24 |
+
console.error("β CRITICAL: Invalid or Missing API Key.");
|
| 25 |
+
return NextResponse.json(
|
| 26 |
+
{ error: 'API Key not configured. Edit .env.local with a valid key.' },
|
| 27 |
+
{ status: 500 }
|
| 28 |
+
);
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
// Read System Prompt
|
| 32 |
+
const promptPath = path.join(process.cwd(), 'src', 'prompts', 'system_prompt.md');
|
| 33 |
+
let systemInstruction = '';
|
| 34 |
+
try {
|
| 35 |
+
systemInstruction = fs.readFileSync(promptPath, 'utf-8');
|
| 36 |
+
} catch (error) {
|
| 37 |
+
console.error("Error reading system prompt:", error);
|
| 38 |
+
return NextResponse.json({ error: "Failed to load system prompt" }, { status: 500 });
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
// Using gemini-2.5-flash - newest model with fresh quota
|
| 42 |
+
const model = genAI.getGenerativeModel({
|
| 43 |
+
model: "gemini-2.5-flash",
|
| 44 |
+
systemInstruction: systemInstruction,
|
| 45 |
+
});
|
| 46 |
+
|
| 47 |
+
const parts = [];
|
| 48 |
+
|
| 49 |
+
// Handle File Input (Images)
|
| 50 |
+
if (file) {
|
| 51 |
+
const arrayBuffer = await file.arrayBuffer();
|
| 52 |
+
const buffer = Buffer.from(arrayBuffer);
|
| 53 |
+
parts.push({
|
| 54 |
+
inlineData: {
|
| 55 |
+
data: buffer.toString('base64'),
|
| 56 |
+
mimeType: file.type,
|
| 57 |
+
},
|
| 58 |
+
});
|
| 59 |
+
parts.push({ text: "Please analyze this image according to your system instructions. If it's a problem, guide me. If it's a text, summarize it." });
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
// Handle Text Input
|
| 63 |
+
if (textInput) {
|
| 64 |
+
parts.push({ text: textInput });
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
if (parts.length === 0) {
|
| 68 |
+
return NextResponse.json({ error: "No content provided (file or text)" }, { status: 400 });
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
console.log("Sending request to model: gemma-3-27b-it");
|
| 72 |
+
const result = await model.generateContent(parts);
|
| 73 |
+
const response = await result.response;
|
| 74 |
+
const outputText = response.text();
|
| 75 |
+
console.log("β
Response received successfully!");
|
| 76 |
+
|
| 77 |
+
return NextResponse.json({ result: outputText });
|
| 78 |
+
|
| 79 |
+
} catch (error: any) {
|
| 80 |
+
console.error('Error generating content:', error);
|
| 81 |
+
return NextResponse.json(
|
| 82 |
+
{ error: error.message || 'Internal Server Error' },
|
| 83 |
+
{ status: 500 }
|
| 84 |
+
);
|
| 85 |
+
}
|
| 86 |
+
}
|
src/app/globals.css
CHANGED
|
@@ -1,26 +1,311 @@
|
|
| 1 |
@import "tailwindcss";
|
| 2 |
|
| 3 |
:root {
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
@media (prefers-color-scheme: dark) {
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
}
|
| 21 |
|
| 22 |
body {
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
@import "tailwindcss";
|
| 2 |
|
| 3 |
:root {
|
| 4 |
+
--background: #ffffff;
|
| 5 |
+
--foreground: #1a1a1a;
|
| 6 |
+
--primary: #0ea5e9;
|
| 7 |
+
--primary-light: #38bdf8;
|
| 8 |
+
--secondary: #64748b;
|
| 9 |
+
--accent: #0284c7;
|
| 10 |
+
--surface: #ffffff;
|
| 11 |
+
--surface-variant: #f8fafc;
|
| 12 |
+
--card-border: #e2e8f0;
|
| 13 |
+
--text-muted: #52525b;
|
| 14 |
}
|
| 15 |
|
| 16 |
@media (prefers-color-scheme: dark) {
|
| 17 |
+
:root {
|
| 18 |
+
--background: #0a0a0a;
|
| 19 |
+
--foreground: #fafafa;
|
| 20 |
+
--primary: #38bdf8;
|
| 21 |
+
--primary-light: #7dd3fc;
|
| 22 |
+
--secondary: #94a3b8;
|
| 23 |
+
--accent: #0ea5e9;
|
| 24 |
+
--surface: #111111;
|
| 25 |
+
--surface-variant: #18181b;
|
| 26 |
+
--card-border: #27272a;
|
| 27 |
+
--text-muted: #a1a1aa;
|
| 28 |
+
}
|
| 29 |
}
|
| 30 |
|
| 31 |
body {
|
| 32 |
+
color: var(--foreground);
|
| 33 |
+
background: var(--background);
|
| 34 |
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
| 35 |
+
overflow-x: hidden;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
/* ==================== MARKDOWN CONTENT STYLING ==================== */
|
| 39 |
+
|
| 40 |
+
.markdown-content {
|
| 41 |
+
line-height: 1.75;
|
| 42 |
+
font-size: 0.95rem;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
/* Page Title */
|
| 46 |
+
.markdown-content h1 {
|
| 47 |
+
font-size: 1.5rem;
|
| 48 |
+
font-weight: 700;
|
| 49 |
+
margin-bottom: 0.5rem;
|
| 50 |
+
margin-top: 0;
|
| 51 |
+
color: var(--foreground);
|
| 52 |
+
display: flex;
|
| 53 |
+
align-items: center;
|
| 54 |
+
gap: 0.5rem;
|
| 55 |
+
line-height: 1.3;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
/* Subtitle/Meta line after title */
|
| 59 |
+
.markdown-content>p:first-of-type {
|
| 60 |
+
color: var(--text-muted);
|
| 61 |
+
font-size: 0.875rem;
|
| 62 |
+
margin-bottom: 1.5rem;
|
| 63 |
+
padding-bottom: 1rem;
|
| 64 |
+
border-bottom: 1px solid var(--card-border);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
/* Section Headers */
|
| 68 |
+
.markdown-content h3 {
|
| 69 |
+
font-size: 1rem;
|
| 70 |
+
font-weight: 600;
|
| 71 |
+
margin-bottom: 0.75rem;
|
| 72 |
+
margin-top: 0;
|
| 73 |
+
color: var(--foreground);
|
| 74 |
+
display: flex;
|
| 75 |
+
align-items: center;
|
| 76 |
+
gap: 0.5rem;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
/* Paragraphs */
|
| 80 |
+
.markdown-content p {
|
| 81 |
+
margin-bottom: 1rem;
|
| 82 |
+
color: var(--text-muted);
|
| 83 |
+
font-size: 0.925rem;
|
| 84 |
+
line-height: 1.7;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
/* Cards / Blockquotes - Clean Cards with Clear Separation */
|
| 88 |
+
.markdown-content blockquote {
|
| 89 |
+
position: relative;
|
| 90 |
+
padding: 1.25rem 1.5rem;
|
| 91 |
+
margin: 0 0 1.25rem 0;
|
| 92 |
+
border-radius: 16px;
|
| 93 |
+
border: 1px solid var(--card-border);
|
| 94 |
+
background: var(--surface-variant);
|
| 95 |
+
transition: all 0.2s ease;
|
| 96 |
+
animation: fadeSlideIn 0.4s ease-out forwards;
|
| 97 |
+
opacity: 0;
|
| 98 |
+
transform: translateY(8px);
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
.markdown-content blockquote:nth-child(1) {
|
| 102 |
+
animation-delay: 0.05s;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
.markdown-content blockquote:nth-child(2) {
|
| 106 |
+
animation-delay: 0.1s;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
.markdown-content blockquote:nth-child(3) {
|
| 110 |
+
animation-delay: 0.15s;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
.markdown-content blockquote:nth-child(4) {
|
| 114 |
+
animation-delay: 0.2s;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.markdown-content blockquote:nth-child(5) {
|
| 118 |
+
animation-delay: 0.25s;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
.markdown-content blockquote:hover {
|
| 122 |
+
border-color: var(--primary);
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
/* Remove margin from first/last elements inside blockquote */
|
| 126 |
+
.markdown-content blockquote>*:first-child {
|
| 127 |
+
margin-top: 0;
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
.markdown-content blockquote>*:last-child {
|
| 131 |
+
margin-bottom: 0;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
/* Nested content in blockquotes */
|
| 135 |
+
.markdown-content blockquote p {
|
| 136 |
+
color: var(--foreground);
|
| 137 |
+
opacity: 0.85;
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
.markdown-content blockquote h3 {
|
| 141 |
+
margin-bottom: 1rem;
|
| 142 |
+
padding-bottom: 0.5rem;
|
| 143 |
+
border-bottom: 1px solid var(--card-border);
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
/* Lists */
|
| 147 |
+
.markdown-content ul {
|
| 148 |
+
list-style: none;
|
| 149 |
+
padding: 0;
|
| 150 |
+
margin: 0.5rem 0;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
.markdown-content ul li {
|
| 154 |
+
position: relative;
|
| 155 |
+
padding-left: 1.5rem;
|
| 156 |
+
margin-bottom: 0.625rem;
|
| 157 |
+
font-size: 0.9rem;
|
| 158 |
+
color: var(--text-muted);
|
| 159 |
+
line-height: 1.6;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
.markdown-content ul li::before {
|
| 163 |
+
content: '';
|
| 164 |
+
position: absolute;
|
| 165 |
+
left: 0;
|
| 166 |
+
top: 0.5rem;
|
| 167 |
+
width: 6px;
|
| 168 |
+
height: 6px;
|
| 169 |
+
border-radius: 50%;
|
| 170 |
+
background: var(--primary);
|
| 171 |
}
|
| 172 |
+
|
| 173 |
+
/* Ordered Lists */
|
| 174 |
+
.markdown-content ol {
|
| 175 |
+
counter-reset: item;
|
| 176 |
+
padding: 0;
|
| 177 |
+
margin: 0.5rem 0;
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
.markdown-content ol li {
|
| 181 |
+
counter-increment: item;
|
| 182 |
+
position: relative;
|
| 183 |
+
padding-left: 2rem;
|
| 184 |
+
margin-bottom: 0.625rem;
|
| 185 |
+
font-size: 0.9rem;
|
| 186 |
+
color: var(--text-muted);
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
.markdown-content ol li::before {
|
| 190 |
+
content: counter(item);
|
| 191 |
+
position: absolute;
|
| 192 |
+
left: 0;
|
| 193 |
+
top: 0;
|
| 194 |
+
width: 1.5rem;
|
| 195 |
+
height: 1.5rem;
|
| 196 |
+
border-radius: 50%;
|
| 197 |
+
background: var(--foreground);
|
| 198 |
+
color: var(--background);
|
| 199 |
+
font-weight: 600;
|
| 200 |
+
font-size: 0.7rem;
|
| 201 |
+
display: flex;
|
| 202 |
+
align-items: center;
|
| 203 |
+
justify-content: center;
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
/* Bold text */
|
| 207 |
+
.markdown-content strong {
|
| 208 |
+
font-weight: 600;
|
| 209 |
+
color: var(--foreground);
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
/* Italic */
|
| 213 |
+
.markdown-content em {
|
| 214 |
+
font-style: italic;
|
| 215 |
+
color: var(--primary);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
/* Horizontal Rule */
|
| 219 |
+
.markdown-content hr {
|
| 220 |
+
border: none;
|
| 221 |
+
height: 1px;
|
| 222 |
+
margin: 1.5rem 0;
|
| 223 |
+
background: var(--card-border);
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
/* Code/Tags */
|
| 227 |
+
.markdown-content code {
|
| 228 |
+
background: var(--surface-variant);
|
| 229 |
+
padding: 0.15rem 0.4rem;
|
| 230 |
+
border-radius: 4px;
|
| 231 |
+
font-size: 0.85rem;
|
| 232 |
+
font-family: 'SF Mono', 'Fira Code', monospace;
|
| 233 |
+
color: var(--foreground);
|
| 234 |
+
border: 1px solid var(--card-border);
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
/* Action buttons at the bottom */
|
| 238 |
+
.markdown-content strong:has(a),
|
| 239 |
+
.markdown-content p:last-child strong {
|
| 240 |
+
display: inline-flex;
|
| 241 |
+
gap: 0.5rem;
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
/* ==================== ANIMATIONS ==================== */
|
| 245 |
+
|
| 246 |
+
@keyframes fadeSlideIn {
|
| 247 |
+
from {
|
| 248 |
+
opacity: 0;
|
| 249 |
+
transform: translateY(8px);
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
to {
|
| 253 |
+
opacity: 1;
|
| 254 |
+
transform: translateY(0);
|
| 255 |
+
}
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
.animate-fade-in-up {
|
| 259 |
+
animation: fadeSlideIn 0.4s ease-out forwards;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
/* ==================== UTILITY CLASSES ==================== */
|
| 263 |
+
|
| 264 |
+
@layer utilities {
|
| 265 |
+
.card-shadow {
|
| 266 |
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
.pixel-corner {
|
| 270 |
+
border-radius: 16px;
|
| 271 |
+
}
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
/* ==================== SCROLLBAR ==================== */
|
| 275 |
+
|
| 276 |
+
::-webkit-scrollbar {
|
| 277 |
+
width: 6px;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
::-webkit-scrollbar-track {
|
| 281 |
+
background: var(--surface-variant);
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
::-webkit-scrollbar-thumb {
|
| 285 |
+
background: var(--secondary);
|
| 286 |
+
border-radius: 10px;
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
::-webkit-scrollbar-thumb:hover {
|
| 290 |
+
background: var(--primary);
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
/* ==================== PROSE OVERRIDES ==================== */
|
| 294 |
+
|
| 295 |
+
.prose {
|
| 296 |
+
--tw-prose-body: var(--text-muted);
|
| 297 |
+
--tw-prose-headings: var(--foreground);
|
| 298 |
+
--tw-prose-bold: var(--foreground);
|
| 299 |
+
--tw-prose-quotes: var(--text-muted);
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
.prose :where(blockquote):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
|
| 303 |
+
font-style: normal;
|
| 304 |
+
border-left: none;
|
| 305 |
+
quotes: none;
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
.prose :where(blockquote p:first-of-type)::before,
|
| 309 |
+
.prose :where(blockquote p:last-of-type)::after {
|
| 310 |
+
content: none;
|
| 311 |
+
}
|
src/app/layout.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import type { Metadata } from "next";
|
| 2 |
import { Geist, Geist_Mono } from "next/font/google";
|
| 3 |
import "./globals.css";
|
|
@@ -13,8 +14,8 @@ const geistMono = Geist_Mono({
|
|
| 13 |
});
|
| 14 |
|
| 15 |
export const metadata: Metadata = {
|
| 16 |
-
title: "
|
| 17 |
-
description: "
|
| 18 |
};
|
| 19 |
|
| 20 |
export default function RootLayout({
|
|
@@ -23,7 +24,7 @@ export default function RootLayout({
|
|
| 23 |
children: React.ReactNode;
|
| 24 |
}>) {
|
| 25 |
return (
|
| 26 |
-
<html lang="en">
|
| 27 |
<body
|
| 28 |
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
| 29 |
>
|
|
|
|
| 1 |
+
|
| 2 |
import type { Metadata } from "next";
|
| 3 |
import { Geist, Geist_Mono } from "next/font/google";
|
| 4 |
import "./globals.css";
|
|
|
|
| 14 |
});
|
| 15 |
|
| 16 |
export const metadata: Metadata = {
|
| 17 |
+
title: "Socratic Lens",
|
| 18 |
+
description: "Your Ethical AI Tutor",
|
| 19 |
};
|
| 20 |
|
| 21 |
export default function RootLayout({
|
|
|
|
| 24 |
children: React.ReactNode;
|
| 25 |
}>) {
|
| 26 |
return (
|
| 27 |
+
<html lang="en" suppressHydrationWarning>
|
| 28 |
<body
|
| 29 |
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
| 30 |
>
|
src/app/page.tsx
CHANGED
|
@@ -1,65 +1,302 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
export default function Home() {
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
/>
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
<a
|
| 54 |
-
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
|
| 55 |
-
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
| 56 |
-
target="_blank"
|
| 57 |
-
rel="noopener noreferrer"
|
| 58 |
-
>
|
| 59 |
-
Documentation
|
| 60 |
-
</a>
|
| 61 |
-
</div>
|
| 62 |
-
</main>
|
| 63 |
-
</div>
|
| 64 |
-
);
|
| 65 |
}
|
|
|
|
| 1 |
+
|
| 2 |
+
'use client';
|
| 3 |
+
|
| 4 |
+
import { useState, useRef } from 'react';
|
| 5 |
+
import ReactMarkdown from 'react-markdown';
|
| 6 |
+
import remarkGfm from 'remark-gfm';
|
| 7 |
+
import { Upload, FileText, Image as ImageIcon, Send, Loader2, RefreshCcw, MessageCircle, BookOpen, Camera } from 'lucide-react';
|
| 8 |
+
import clsx from 'clsx';
|
| 9 |
+
import WikipediaCard from '@/components/WikipediaCard';
|
| 10 |
+
import AskQuestionModal from '@/components/AskQuestionModal';
|
| 11 |
+
import QuizModal from '@/components/QuizModal';
|
| 12 |
+
import CameraModal from '@/components/CameraModal';
|
| 13 |
|
| 14 |
export default function Home() {
|
| 15 |
+
const [file, setFile] = useState<File | null>(null);
|
| 16 |
+
const [preview, setPreview] = useState<string | null>(null);
|
| 17 |
+
const [loading, setLoading] = useState(false);
|
| 18 |
+
const [result, setResult] = useState<string | null>(null);
|
| 19 |
+
const [error, setError] = useState<string | null>(null);
|
| 20 |
+
const [topics, setTopics] = useState<string[]>([]);
|
| 21 |
+
const [rawContent, setRawContent] = useState<string>('');
|
| 22 |
+
const fileInputRef = useRef<HTMLInputElement>(null);
|
| 23 |
+
|
| 24 |
+
// Modal states
|
| 25 |
+
const [askModalOpen, setAskModalOpen] = useState(false);
|
| 26 |
+
const [quizModalOpen, setQuizModalOpen] = useState(false);
|
| 27 |
+
const [cameraModalOpen, setCameraModalOpen] = useState(false);
|
| 28 |
+
|
| 29 |
+
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
| 30 |
+
if (e.target.files && e.target.files[0]) {
|
| 31 |
+
const selectedFile = e.target.files[0];
|
| 32 |
+
setFileWithPreview(selectedFile);
|
| 33 |
+
}
|
| 34 |
+
};
|
| 35 |
+
|
| 36 |
+
const setFileWithPreview = (selectedFile: File) => {
|
| 37 |
+
setFile(selectedFile);
|
| 38 |
+
setError(null);
|
| 39 |
+
|
| 40 |
+
if (selectedFile.type.startsWith('image/')) {
|
| 41 |
+
const reader = new FileReader();
|
| 42 |
+
reader.onload = (e) => {
|
| 43 |
+
setPreview(e.target?.result as string);
|
| 44 |
+
};
|
| 45 |
+
reader.readAsDataURL(selectedFile);
|
| 46 |
+
} else {
|
| 47 |
+
setPreview(null);
|
| 48 |
+
}
|
| 49 |
+
};
|
| 50 |
+
|
| 51 |
+
const handleCameraCapture = (capturedFile: File) => {
|
| 52 |
+
setFileWithPreview(capturedFile);
|
| 53 |
+
};
|
| 54 |
+
|
| 55 |
+
const handleSubmit = async () => {
|
| 56 |
+
if (!file) {
|
| 57 |
+
setError("Please select an image or document first.");
|
| 58 |
+
return;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
setLoading(true);
|
| 62 |
+
setError(null);
|
| 63 |
+
setResult(null);
|
| 64 |
+
setTopics([]);
|
| 65 |
+
setRawContent('');
|
| 66 |
+
|
| 67 |
+
const formData = new FormData();
|
| 68 |
+
formData.append('file', file);
|
| 69 |
+
|
| 70 |
+
try {
|
| 71 |
+
const res = await fetch('/api/analyze', {
|
| 72 |
+
method: 'POST',
|
| 73 |
+
body: formData,
|
| 74 |
+
});
|
| 75 |
+
|
| 76 |
+
if (!res.ok) {
|
| 77 |
+
const errData = await res.json();
|
| 78 |
+
throw new Error(errData.error || 'Failed to analyze');
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
const data = await res.json();
|
| 82 |
+
const rawText = data.result || "";
|
| 83 |
+
|
| 84 |
+
setRawContent(rawText);
|
| 85 |
+
|
| 86 |
+
let extractedTopics: string[] = [];
|
| 87 |
+
const multiMatch = rawText.match(/\[\[TOPICS?:\s*(.*?)\]\]/i);
|
| 88 |
+
if (multiMatch) {
|
| 89 |
+
extractedTopics = multiMatch[1].split(',').map((t: string) => t.trim()).filter((t: string) => t.length > 0);
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
const cleanText = rawText.replace(/\[\[TOPICS?:.*?\]\]/i, "").trim();
|
| 93 |
+
|
| 94 |
+
setResult(cleanText);
|
| 95 |
+
setTopics(extractedTopics);
|
| 96 |
+
|
| 97 |
+
} catch (err: any) {
|
| 98 |
+
setError(err.message || "Something went wrong.");
|
| 99 |
+
} finally {
|
| 100 |
+
setLoading(false);
|
| 101 |
+
}
|
| 102 |
+
};
|
| 103 |
+
|
| 104 |
+
const reset = () => {
|
| 105 |
+
setFile(null);
|
| 106 |
+
setPreview(null);
|
| 107 |
+
setResult(null);
|
| 108 |
+
setError(null);
|
| 109 |
+
setTopics([]);
|
| 110 |
+
setRawContent('');
|
| 111 |
+
};
|
| 112 |
+
|
| 113 |
+
return (
|
| 114 |
+
<>
|
| 115 |
+
<main className="min-h-screen p-6 md:p-12">
|
| 116 |
+
<div className="max-w-6xl mx-auto flex flex-col gap-8">
|
| 117 |
+
|
| 118 |
+
{/* Header */}
|
| 119 |
+
<header className="flex items-center justify-between">
|
| 120 |
+
<h1 className="text-3xl font-bold tracking-tight text-gray-800 dark:text-gray-100 flex items-center gap-3">
|
| 121 |
+
<span className="p-2 bg-sky-100 dark:bg-sky-900 rounded-xl text-sky-600 dark:text-sky-300">
|
| 122 |
+
<ImageIcon size={24} />
|
| 123 |
+
</span>
|
| 124 |
+
Socratic Lens
|
| 125 |
+
</h1>
|
| 126 |
+
<div className="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-800 rounded-full font-medium text-gray-600 dark:text-gray-400">
|
| 127 |
+
Beta
|
| 128 |
+
</div>
|
| 129 |
+
</header>
|
| 130 |
+
|
| 131 |
+
{/* Main Interaction Area */}
|
| 132 |
+
{!result ? (
|
| 133 |
+
<section className="flex-1 flex flex-col items-center justify-center min-h-[50vh] transition-all">
|
| 134 |
+
|
| 135 |
+
{/* Two Upload Boxes Side by Side */}
|
| 136 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 w-full max-w-3xl">
|
| 137 |
+
|
| 138 |
+
{/* Upload Document Box */}
|
| 139 |
+
<div
|
| 140 |
+
onClick={() => fileInputRef.current?.click()}
|
| 141 |
+
className={clsx(
|
| 142 |
+
"w-full aspect-square rounded-[32px] border-4 border-dashed flex flex-col items-center justify-center cursor-pointer transition-all hover:scale-[1.02] active:scale-[0.98] overflow-hidden",
|
| 143 |
+
file && !preview
|
| 144 |
+
? "border-green-400 bg-green-50 dark:bg-green-900/20"
|
| 145 |
+
: "border-gray-300 dark:border-gray-700 hover:border-sky-400 hover:bg-sky-50 dark:hover:bg-gray-800"
|
| 146 |
+
)}
|
| 147 |
+
>
|
| 148 |
+
<input
|
| 149 |
+
type="file"
|
| 150 |
+
ref={fileInputRef}
|
| 151 |
+
onChange={handleFileChange}
|
| 152 |
+
className="hidden"
|
| 153 |
+
accept="image/*,application/pdf"
|
| 154 |
+
/>
|
| 155 |
+
|
| 156 |
+
{file && !preview ? (
|
| 157 |
+
<>
|
| 158 |
+
<FileText className="w-12 h-12 text-green-600 mb-3" />
|
| 159 |
+
<p className="text-sm font-medium text-green-800 dark:text-green-300 text-center px-4 truncate max-w-full">{file.name}</p>
|
| 160 |
+
<p className="text-xs text-green-600 dark:text-green-400 mt-1">Tap to change</p>
|
| 161 |
+
</>
|
| 162 |
+
) : (
|
| 163 |
+
<>
|
| 164 |
+
<Upload className="w-12 h-12 text-gray-400 mb-3" />
|
| 165 |
+
<p className="text-base font-medium text-gray-600 dark:text-gray-300">Upload Document</p>
|
| 166 |
+
<p className="text-xs text-gray-400 mt-1">Images or PDFs</p>
|
| 167 |
+
</>
|
| 168 |
+
)}
|
| 169 |
+
</div>
|
| 170 |
+
|
| 171 |
+
{/* Take Photo Box - Opens Camera Modal */}
|
| 172 |
+
<div
|
| 173 |
+
onClick={() => setCameraModalOpen(true)}
|
| 174 |
+
className={clsx(
|
| 175 |
+
"w-full aspect-square rounded-[32px] border-4 border-dashed flex flex-col items-center justify-center cursor-pointer transition-all hover:scale-[1.02] active:scale-[0.98] overflow-hidden",
|
| 176 |
+
preview
|
| 177 |
+
? "border-green-400 bg-green-50 dark:bg-green-900/20 p-2"
|
| 178 |
+
: "border-gray-300 dark:border-gray-700 hover:border-sky-400 hover:bg-sky-50 dark:hover:bg-gray-800"
|
| 179 |
+
)}
|
| 180 |
+
>
|
| 181 |
+
{preview ? (
|
| 182 |
+
<div className="relative w-full h-full">
|
| 183 |
+
<img
|
| 184 |
+
src={preview}
|
| 185 |
+
alt="Preview"
|
| 186 |
+
className="w-full h-full object-contain rounded-2xl"
|
| 187 |
+
/>
|
| 188 |
+
<div className="absolute bottom-2 left-1/2 -translate-x-1/2 bg-black/60 text-white text-xs px-3 py-1 rounded-full">
|
| 189 |
+
Tap to retake
|
| 190 |
+
</div>
|
| 191 |
+
</div>
|
| 192 |
+
) : (
|
| 193 |
+
<>
|
| 194 |
+
<Camera className="w-12 h-12 text-gray-400 mb-3" />
|
| 195 |
+
<p className="text-base font-medium text-gray-600 dark:text-gray-300">Take Photo</p>
|
| 196 |
+
<p className="text-xs text-gray-400 mt-1">Use Camera</p>
|
| 197 |
+
</>
|
| 198 |
+
)}
|
| 199 |
+
</div>
|
| 200 |
+
</div>
|
| 201 |
+
|
| 202 |
+
{/* Analyze Button */}
|
| 203 |
+
<div className="mt-8">
|
| 204 |
+
<button
|
| 205 |
+
onClick={handleSubmit}
|
| 206 |
+
disabled={loading || !file}
|
| 207 |
+
className={clsx(
|
| 208 |
+
"flex items-center gap-3 px-8 py-4 rounded-full text-lg font-semibold shadow-xl transition-all",
|
| 209 |
+
loading || !file
|
| 210 |
+
? "bg-gray-300 text-gray-500 cursor-not-allowed grayscale"
|
| 211 |
+
: "bg-gray-900 dark:bg-white text-white dark:text-gray-900 hover:scale-105 active:scale-95"
|
| 212 |
+
)}
|
| 213 |
+
>
|
| 214 |
+
{loading ? <Loader2 className="animate-spin" /> : <Send />}
|
| 215 |
+
{loading ? "Analyzing..." : "Analyze with Lens"}
|
| 216 |
+
</button>
|
| 217 |
+
</div>
|
| 218 |
+
|
| 219 |
+
{error && (
|
| 220 |
+
<div className="mt-6 p-4 bg-red-100 text-red-700 rounded-2xl flex items-center gap-2">
|
| 221 |
+
<span>β οΈ</span> {error}
|
| 222 |
+
</div>
|
| 223 |
+
)}
|
| 224 |
+
|
| 225 |
+
</section>
|
| 226 |
+
) : (
|
| 227 |
+
<section className="animate-fade-in-up">
|
| 228 |
+
<div className="flex justify-between items-center mb-6">
|
| 229 |
+
<button
|
| 230 |
+
onClick={reset}
|
| 231 |
+
className="flex items-center gap-2 text-sm font-medium text-gray-500 hover:text-black dark:hover:text-white transition-colors px-4 py-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800"
|
| 232 |
+
>
|
| 233 |
+
<RefreshCcw size={16} />
|
| 234 |
+
Analyze Another
|
| 235 |
+
</button>
|
| 236 |
+
<span className="text-xs text-gray-400 uppercase tracking-wider">AI Generated Content</span>
|
| 237 |
+
</div>
|
| 238 |
+
|
| 239 |
+
{/* 2-Column Layout */}
|
| 240 |
+
<div className="flex flex-col lg:flex-row gap-8 justify-center">
|
| 241 |
+
|
| 242 |
+
{/* Main AI Content (Center/Left) */}
|
| 243 |
+
<div className="flex-1 max-w-3xl">
|
| 244 |
+
<div className="bg-white dark:bg-neutral-900 rounded-[24px] p-6 md:p-8 shadow-xl border border-gray-200 dark:border-neutral-800">
|
| 245 |
+
<article className="prose prose-lg dark:prose-invert max-w-none markdown-content">
|
| 246 |
+
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
| 247 |
+
{result}
|
| 248 |
+
</ReactMarkdown>
|
| 249 |
+
</article>
|
| 250 |
+
</div>
|
| 251 |
+
|
| 252 |
+
{/* Action Buttons */}
|
| 253 |
+
<div className="flex flex-wrap gap-3 mt-6">
|
| 254 |
+
<button
|
| 255 |
+
onClick={() => setAskModalOpen(true)}
|
| 256 |
+
className="flex items-center gap-2 px-5 py-3 bg-white dark:bg-neutral-900 border border-gray-200 dark:border-neutral-700 rounded-xl font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-neutral-800 hover:border-sky-500 transition-all shadow-sm"
|
| 257 |
+
>
|
| 258 |
+
<MessageCircle size={18} className="text-sky-500" />
|
| 259 |
+
Ask a Question
|
| 260 |
+
</button>
|
| 261 |
+
<button
|
| 262 |
+
onClick={() => setQuizModalOpen(true)}
|
| 263 |
+
className="flex items-center gap-2 px-5 py-3 bg-sky-500 text-white rounded-xl font-medium hover:bg-sky-600 transition-all shadow-sm"
|
| 264 |
+
>
|
| 265 |
+
<BookOpen size={18} />
|
| 266 |
+
Quiz Me
|
| 267 |
+
</button>
|
| 268 |
+
</div>
|
| 269 |
+
</div>
|
| 270 |
+
|
| 271 |
+
{/* Sidebar (Right) - Wikipedia */}
|
| 272 |
+
{topics.length > 0 && (
|
| 273 |
+
<div className="w-full lg:w-80 flex-shrink-0">
|
| 274 |
+
<WikipediaCard topics={topics} />
|
| 275 |
+
</div>
|
| 276 |
+
)}
|
| 277 |
+
|
| 278 |
+
</div>
|
| 279 |
+
</section>
|
| 280 |
+
)}
|
| 281 |
+
</div>
|
| 282 |
+
</main>
|
| 283 |
+
|
| 284 |
+
{/* Modals */}
|
| 285 |
+
<AskQuestionModal
|
| 286 |
+
isOpen={askModalOpen}
|
| 287 |
+
onClose={() => setAskModalOpen(false)}
|
| 288 |
+
context={rawContent}
|
| 289 |
+
/>
|
| 290 |
+
<QuizModal
|
| 291 |
+
isOpen={quizModalOpen}
|
| 292 |
+
onClose={() => setQuizModalOpen(false)}
|
| 293 |
+
context={rawContent}
|
| 294 |
+
/>
|
| 295 |
+
<CameraModal
|
| 296 |
+
isOpen={cameraModalOpen}
|
| 297 |
+
onClose={() => setCameraModalOpen(false)}
|
| 298 |
+
onCapture={handleCameraCapture}
|
| 299 |
/>
|
| 300 |
+
</>
|
| 301 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 302 |
}
|
src/components/AskQuestionModal.tsx
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
'use client';
|
| 3 |
+
|
| 4 |
+
import { useState } from 'react';
|
| 5 |
+
import { X, Send, Loader2, MessageCircle } from 'lucide-react';
|
| 6 |
+
import clsx from 'clsx';
|
| 7 |
+
import ReactMarkdown from 'react-markdown';
|
| 8 |
+
import remarkGfm from 'remark-gfm';
|
| 9 |
+
|
| 10 |
+
interface AskQuestionModalProps {
|
| 11 |
+
isOpen: boolean;
|
| 12 |
+
onClose: () => void;
|
| 13 |
+
context: string; // The original analyzed content
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
interface Message {
|
| 17 |
+
role: 'user' | 'assistant';
|
| 18 |
+
content: string;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
export default function AskQuestionModal({ isOpen, onClose, context }: AskQuestionModalProps) {
|
| 22 |
+
const [messages, setMessages] = useState<Message[]>([]);
|
| 23 |
+
const [input, setInput] = useState('');
|
| 24 |
+
const [loading, setLoading] = useState(false);
|
| 25 |
+
|
| 26 |
+
const handleSubmit = async (e: React.FormEvent) => {
|
| 27 |
+
e.preventDefault();
|
| 28 |
+
if (!input.trim() || loading) return;
|
| 29 |
+
|
| 30 |
+
const userMessage = input.trim();
|
| 31 |
+
setInput('');
|
| 32 |
+
setMessages(prev => [...prev, { role: 'user', content: userMessage }]);
|
| 33 |
+
setLoading(true);
|
| 34 |
+
|
| 35 |
+
try {
|
| 36 |
+
const formData = new FormData();
|
| 37 |
+
formData.append('text', `
|
| 38 |
+
Based on this content I just learned:
|
| 39 |
+
---
|
| 40 |
+
${context.substring(0, 2000)}
|
| 41 |
+
---
|
| 42 |
+
|
| 43 |
+
My question: ${userMessage}
|
| 44 |
+
|
| 45 |
+
Please answer my question in a helpful, educational way. Use simple language and examples if needed.
|
| 46 |
+
`);
|
| 47 |
+
|
| 48 |
+
const res = await fetch('/api/analyze', {
|
| 49 |
+
method: 'POST',
|
| 50 |
+
body: formData,
|
| 51 |
+
});
|
| 52 |
+
|
| 53 |
+
if (!res.ok) throw new Error('Failed to get response');
|
| 54 |
+
|
| 55 |
+
const data = await res.json();
|
| 56 |
+
const cleanResponse = data.result?.replace(/\[\[TOPICS?:.*?\]\]/gi, '').trim() || 'Sorry, I could not generate a response.';
|
| 57 |
+
|
| 58 |
+
setMessages(prev => [...prev, { role: 'assistant', content: cleanResponse }]);
|
| 59 |
+
} catch (error) {
|
| 60 |
+
setMessages(prev => [...prev, { role: 'assistant', content: 'Sorry, something went wrong. Please try again.' }]);
|
| 61 |
+
} finally {
|
| 62 |
+
setLoading(false);
|
| 63 |
+
}
|
| 64 |
+
};
|
| 65 |
+
|
| 66 |
+
if (!isOpen) return null;
|
| 67 |
+
|
| 68 |
+
return (
|
| 69 |
+
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in-up">
|
| 70 |
+
<div className="w-full max-w-2xl bg-white dark:bg-neutral-900 rounded-2xl shadow-2xl border border-gray-200 dark:border-neutral-800 flex flex-col max-h-[80vh]">
|
| 71 |
+
|
| 72 |
+
{/* Header */}
|
| 73 |
+
<div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-neutral-800">
|
| 74 |
+
<div className="flex items-center gap-2">
|
| 75 |
+
<MessageCircle size={20} className="text-sky-500" />
|
| 76 |
+
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">Ask a Question</h2>
|
| 77 |
+
</div>
|
| 78 |
+
<button
|
| 79 |
+
onClick={onClose}
|
| 80 |
+
className="p-2 hover:bg-gray-100 dark:hover:bg-neutral-800 rounded-full transition-colors"
|
| 81 |
+
>
|
| 82 |
+
<X size={20} className="text-gray-500" />
|
| 83 |
+
</button>
|
| 84 |
+
</div>
|
| 85 |
+
|
| 86 |
+
{/* Messages */}
|
| 87 |
+
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
| 88 |
+
{messages.length === 0 && (
|
| 89 |
+
<div className="text-center py-12 text-gray-400">
|
| 90 |
+
<MessageCircle size={48} className="mx-auto mb-4 opacity-50" />
|
| 91 |
+
<p>Ask any question about the content you just analyzed.</p>
|
| 92 |
+
</div>
|
| 93 |
+
)}
|
| 94 |
+
|
| 95 |
+
{messages.map((msg, idx) => (
|
| 96 |
+
<div
|
| 97 |
+
key={idx}
|
| 98 |
+
className={clsx(
|
| 99 |
+
"flex",
|
| 100 |
+
msg.role === 'user' ? "justify-end" : "justify-start"
|
| 101 |
+
)}
|
| 102 |
+
>
|
| 103 |
+
<div
|
| 104 |
+
className={clsx(
|
| 105 |
+
"max-w-[80%] rounded-2xl px-4 py-3",
|
| 106 |
+
msg.role === 'user'
|
| 107 |
+
? "bg-sky-500 text-white rounded-br-md"
|
| 108 |
+
: "bg-gray-100 dark:bg-neutral-800 text-gray-800 dark:text-gray-200 rounded-bl-md"
|
| 109 |
+
)}
|
| 110 |
+
>
|
| 111 |
+
{msg.role === 'assistant' ? (
|
| 112 |
+
<div className="prose prose-sm dark:prose-invert max-w-none">
|
| 113 |
+
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
| 114 |
+
{msg.content}
|
| 115 |
+
</ReactMarkdown>
|
| 116 |
+
</div>
|
| 117 |
+
) : (
|
| 118 |
+
<p>{msg.content}</p>
|
| 119 |
+
)}
|
| 120 |
+
</div>
|
| 121 |
+
</div>
|
| 122 |
+
))}
|
| 123 |
+
|
| 124 |
+
{loading && (
|
| 125 |
+
<div className="flex justify-start">
|
| 126 |
+
<div className="bg-gray-100 dark:bg-neutral-800 rounded-2xl rounded-bl-md px-4 py-3">
|
| 127 |
+
<Loader2 size={20} className="animate-spin text-gray-400" />
|
| 128 |
+
</div>
|
| 129 |
+
</div>
|
| 130 |
+
)}
|
| 131 |
+
</div>
|
| 132 |
+
|
| 133 |
+
{/* Input */}
|
| 134 |
+
<form onSubmit={handleSubmit} className="p-4 border-t border-gray-200 dark:border-neutral-800">
|
| 135 |
+
<div className="flex gap-3">
|
| 136 |
+
<input
|
| 137 |
+
type="text"
|
| 138 |
+
value={input}
|
| 139 |
+
onChange={(e) => setInput(e.target.value)}
|
| 140 |
+
placeholder="Type your question..."
|
| 141 |
+
className="flex-1 px-4 py-3 bg-gray-100 dark:bg-neutral-800 border border-gray-200 dark:border-neutral-700 rounded-xl focus:outline-none focus:ring-2 focus:ring-sky-500 focus:border-transparent text-gray-900 dark:text-white placeholder-gray-400"
|
| 142 |
+
disabled={loading}
|
| 143 |
+
/>
|
| 144 |
+
<button
|
| 145 |
+
type="submit"
|
| 146 |
+
disabled={loading || !input.trim()}
|
| 147 |
+
className={clsx(
|
| 148 |
+
"px-4 py-3 rounded-xl font-medium transition-all flex items-center gap-2",
|
| 149 |
+
loading || !input.trim()
|
| 150 |
+
? "bg-gray-200 dark:bg-neutral-700 text-gray-400 cursor-not-allowed"
|
| 151 |
+
: "bg-sky-500 text-white hover:bg-sky-600"
|
| 152 |
+
)}
|
| 153 |
+
>
|
| 154 |
+
{loading ? <Loader2 size={18} className="animate-spin" /> : <Send size={18} />}
|
| 155 |
+
</button>
|
| 156 |
+
</div>
|
| 157 |
+
</form>
|
| 158 |
+
</div>
|
| 159 |
+
</div>
|
| 160 |
+
);
|
| 161 |
+
}
|
src/components/CameraModal.tsx
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
'use client';
|
| 3 |
+
|
| 4 |
+
import { useState, useRef, useEffect } from 'react';
|
| 5 |
+
import { X, Camera, RotateCcw, Check } from 'lucide-react';
|
| 6 |
+
import clsx from 'clsx';
|
| 7 |
+
|
| 8 |
+
interface CameraModalProps {
|
| 9 |
+
isOpen: boolean;
|
| 10 |
+
onClose: () => void;
|
| 11 |
+
onCapture: (file: File) => void;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
export default function CameraModal({ isOpen, onClose, onCapture }: CameraModalProps) {
|
| 15 |
+
const videoRef = useRef<HTMLVideoElement>(null);
|
| 16 |
+
const canvasRef = useRef<HTMLCanvasElement>(null);
|
| 17 |
+
const [stream, setStream] = useState<MediaStream | null>(null);
|
| 18 |
+
const [capturedImage, setCapturedImage] = useState<string | null>(null);
|
| 19 |
+
const [error, setError] = useState<string | null>(null);
|
| 20 |
+
const [facingMode, setFacingMode] = useState<'user' | 'environment'>('environment');
|
| 21 |
+
|
| 22 |
+
useEffect(() => {
|
| 23 |
+
if (isOpen) {
|
| 24 |
+
startCamera();
|
| 25 |
+
} else {
|
| 26 |
+
stopCamera();
|
| 27 |
+
setCapturedImage(null);
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
return () => stopCamera();
|
| 31 |
+
}, [isOpen, facingMode]);
|
| 32 |
+
|
| 33 |
+
const startCamera = async () => {
|
| 34 |
+
try {
|
| 35 |
+
setError(null);
|
| 36 |
+
const mediaStream = await navigator.mediaDevices.getUserMedia({
|
| 37 |
+
video: {
|
| 38 |
+
facingMode: facingMode,
|
| 39 |
+
width: { ideal: 1280 },
|
| 40 |
+
height: { ideal: 720 }
|
| 41 |
+
},
|
| 42 |
+
audio: false
|
| 43 |
+
});
|
| 44 |
+
setStream(mediaStream);
|
| 45 |
+
if (videoRef.current) {
|
| 46 |
+
videoRef.current.srcObject = mediaStream;
|
| 47 |
+
}
|
| 48 |
+
} catch (err) {
|
| 49 |
+
console.error('Camera error:', err);
|
| 50 |
+
setError('Unable to access camera. Please check permissions.');
|
| 51 |
+
}
|
| 52 |
+
};
|
| 53 |
+
|
| 54 |
+
const stopCamera = () => {
|
| 55 |
+
if (stream) {
|
| 56 |
+
stream.getTracks().forEach(track => track.stop());
|
| 57 |
+
setStream(null);
|
| 58 |
+
}
|
| 59 |
+
};
|
| 60 |
+
|
| 61 |
+
const switchCamera = () => {
|
| 62 |
+
setFacingMode(prev => prev === 'user' ? 'environment' : 'user');
|
| 63 |
+
};
|
| 64 |
+
|
| 65 |
+
const capturePhoto = () => {
|
| 66 |
+
if (videoRef.current && canvasRef.current) {
|
| 67 |
+
const video = videoRef.current;
|
| 68 |
+
const canvas = canvasRef.current;
|
| 69 |
+
|
| 70 |
+
canvas.width = video.videoWidth;
|
| 71 |
+
canvas.height = video.videoHeight;
|
| 72 |
+
|
| 73 |
+
const ctx = canvas.getContext('2d');
|
| 74 |
+
if (ctx) {
|
| 75 |
+
ctx.drawImage(video, 0, 0);
|
| 76 |
+
const imageDataUrl = canvas.toDataURL('image/jpeg', 0.9);
|
| 77 |
+
setCapturedImage(imageDataUrl);
|
| 78 |
+
stopCamera();
|
| 79 |
+
}
|
| 80 |
+
}
|
| 81 |
+
};
|
| 82 |
+
|
| 83 |
+
const retake = () => {
|
| 84 |
+
setCapturedImage(null);
|
| 85 |
+
startCamera();
|
| 86 |
+
};
|
| 87 |
+
|
| 88 |
+
const confirmCapture = () => {
|
| 89 |
+
if (capturedImage && canvasRef.current) {
|
| 90 |
+
canvasRef.current.toBlob((blob) => {
|
| 91 |
+
if (blob) {
|
| 92 |
+
const file = new File([blob], `photo_${Date.now()}.jpg`, { type: 'image/jpeg' });
|
| 93 |
+
onCapture(file);
|
| 94 |
+
onClose();
|
| 95 |
+
}
|
| 96 |
+
}, 'image/jpeg', 0.9);
|
| 97 |
+
}
|
| 98 |
+
};
|
| 99 |
+
|
| 100 |
+
if (!isOpen) return null;
|
| 101 |
+
|
| 102 |
+
return (
|
| 103 |
+
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/90 backdrop-blur-sm animate-fade-in-up">
|
| 104 |
+
<div className="w-full max-w-xl bg-neutral-900 rounded-2xl shadow-2xl border border-neutral-800 overflow-hidden">
|
| 105 |
+
|
| 106 |
+
{/* Header */}
|
| 107 |
+
<div className="flex items-center justify-between p-4 border-b border-neutral-800">
|
| 108 |
+
<div className="flex items-center gap-2">
|
| 109 |
+
<Camera size={20} className="text-sky-500" />
|
| 110 |
+
<h2 className="text-lg font-semibold text-white">Take Photo</h2>
|
| 111 |
+
</div>
|
| 112 |
+
<button
|
| 113 |
+
onClick={onClose}
|
| 114 |
+
className="p-2 hover:bg-neutral-800 rounded-full"
|
| 115 |
+
>
|
| 116 |
+
<X size={20} className="text-gray-400" />
|
| 117 |
+
</button>
|
| 118 |
+
</div>
|
| 119 |
+
|
| 120 |
+
{/* Camera View */}
|
| 121 |
+
<div className="relative aspect-[4/3] bg-black">
|
| 122 |
+
{error ? (
|
| 123 |
+
<div className="absolute inset-0 flex items-center justify-center text-center p-6">
|
| 124 |
+
<div>
|
| 125 |
+
<Camera size={48} className="mx-auto mb-4 text-gray-600" />
|
| 126 |
+
<p className="text-gray-400">{error}</p>
|
| 127 |
+
</div>
|
| 128 |
+
</div>
|
| 129 |
+
) : capturedImage ? (
|
| 130 |
+
<img
|
| 131 |
+
src={capturedImage}
|
| 132 |
+
alt="Captured"
|
| 133 |
+
className="w-full h-full object-contain"
|
| 134 |
+
/>
|
| 135 |
+
) : (
|
| 136 |
+
<video
|
| 137 |
+
ref={videoRef}
|
| 138 |
+
autoPlay
|
| 139 |
+
playsInline
|
| 140 |
+
muted
|
| 141 |
+
className="w-full h-full object-cover"
|
| 142 |
+
/>
|
| 143 |
+
)}
|
| 144 |
+
|
| 145 |
+
<canvas ref={canvasRef} className="hidden" />
|
| 146 |
+
</div>
|
| 147 |
+
|
| 148 |
+
{/* Controls */}
|
| 149 |
+
<div className="p-4 flex items-center justify-center gap-4">
|
| 150 |
+
{!capturedImage ? (
|
| 151 |
+
<>
|
| 152 |
+
{/* Switch Camera */}
|
| 153 |
+
<button
|
| 154 |
+
onClick={switchCamera}
|
| 155 |
+
className="p-3 bg-neutral-800 hover:bg-neutral-700 rounded-full transition-colors"
|
| 156 |
+
title="Switch Camera"
|
| 157 |
+
>
|
| 158 |
+
<RotateCcw size={20} className="text-white" />
|
| 159 |
+
</button>
|
| 160 |
+
|
| 161 |
+
{/* Capture Button */}
|
| 162 |
+
<button
|
| 163 |
+
onClick={capturePhoto}
|
| 164 |
+
disabled={!stream}
|
| 165 |
+
className={clsx(
|
| 166 |
+
"w-16 h-16 rounded-full border-4 border-white flex items-center justify-center transition-all",
|
| 167 |
+
stream
|
| 168 |
+
? "bg-white hover:bg-gray-200 active:scale-95"
|
| 169 |
+
: "bg-gray-600 border-gray-600 cursor-not-allowed"
|
| 170 |
+
)}
|
| 171 |
+
>
|
| 172 |
+
<div className="w-12 h-12 rounded-full bg-sky-500"></div>
|
| 173 |
+
</button>
|
| 174 |
+
|
| 175 |
+
{/* Placeholder for symmetry */}
|
| 176 |
+
<div className="w-11"></div>
|
| 177 |
+
</>
|
| 178 |
+
) : (
|
| 179 |
+
<>
|
| 180 |
+
{/* Retake */}
|
| 181 |
+
<button
|
| 182 |
+
onClick={retake}
|
| 183 |
+
className="flex-1 py-3 bg-neutral-800 text-white rounded-xl font-medium hover:bg-neutral-700 flex items-center justify-center gap-2"
|
| 184 |
+
>
|
| 185 |
+
<RotateCcw size={18} />
|
| 186 |
+
Retake
|
| 187 |
+
</button>
|
| 188 |
+
|
| 189 |
+
{/* Confirm */}
|
| 190 |
+
<button
|
| 191 |
+
onClick={confirmCapture}
|
| 192 |
+
className="flex-1 py-3 bg-sky-500 text-white rounded-xl font-medium hover:bg-sky-600 flex items-center justify-center gap-2"
|
| 193 |
+
>
|
| 194 |
+
<Check size={18} />
|
| 195 |
+
Use Photo
|
| 196 |
+
</button>
|
| 197 |
+
</>
|
| 198 |
+
)}
|
| 199 |
+
</div>
|
| 200 |
+
</div>
|
| 201 |
+
</div>
|
| 202 |
+
);
|
| 203 |
+
}
|
src/components/QuizModal.tsx
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
'use client';
|
| 3 |
+
|
| 4 |
+
import { useState } from 'react';
|
| 5 |
+
import { X, Play, Check, XCircle, Trophy, Loader2, BookOpen, RotateCcw } from 'lucide-react';
|
| 6 |
+
import clsx from 'clsx';
|
| 7 |
+
|
| 8 |
+
interface QuizModalProps {
|
| 9 |
+
isOpen: boolean;
|
| 10 |
+
onClose: () => void;
|
| 11 |
+
context: string;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
interface Question {
|
| 15 |
+
question: string;
|
| 16 |
+
options?: string[];
|
| 17 |
+
correctAnswer: string;
|
| 18 |
+
type: 'mcq' | 'written';
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
type QuizState = 'config' | 'loading' | 'quiz' | 'results';
|
| 22 |
+
|
| 23 |
+
export default function QuizModal({ isOpen, onClose, context }: QuizModalProps) {
|
| 24 |
+
const [state, setState] = useState<QuizState>('config');
|
| 25 |
+
const [numQuestions, setNumQuestions] = useState(5);
|
| 26 |
+
const [questionType, setQuestionType] = useState<'mcq' | 'written' | 'mixed'>('mcq');
|
| 27 |
+
const [numOptions, setNumOptions] = useState(4);
|
| 28 |
+
|
| 29 |
+
const [questions, setQuestions] = useState<Question[]>([]);
|
| 30 |
+
const [currentIndex, setCurrentIndex] = useState(0);
|
| 31 |
+
const [answers, setAnswers] = useState<Record<number, string>>({});
|
| 32 |
+
const [showAnswer, setShowAnswer] = useState(false);
|
| 33 |
+
const [score, setScore] = useState(0);
|
| 34 |
+
|
| 35 |
+
const generateQuiz = async () => {
|
| 36 |
+
setState('loading');
|
| 37 |
+
|
| 38 |
+
try {
|
| 39 |
+
const prompt = `
|
| 40 |
+
Based on this educational content:
|
| 41 |
+
---
|
| 42 |
+
${context.substring(0, 3000)}
|
| 43 |
+
---
|
| 44 |
+
|
| 45 |
+
Generate a quiz with exactly ${numQuestions} questions.
|
| 46 |
+
Question type: ${questionType === 'mcq' ? `Multiple Choice with ${numOptions} options` : questionType === 'written' ? 'Written/Short Answer (no options)' : 'Mix of MCQ and Written'}
|
| 47 |
+
|
| 48 |
+
IMPORTANT: Return ONLY valid JSON in this exact format, no extra text:
|
| 49 |
+
{
|
| 50 |
+
"questions": [
|
| 51 |
+
{
|
| 52 |
+
"question": "Question text here?",
|
| 53 |
+
"options": ["Option A", "Option B", "Option C", "Option D"],
|
| 54 |
+
"correctAnswer": "Option A",
|
| 55 |
+
"type": "mcq"
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"question": "Written question here?",
|
| 59 |
+
"correctAnswer": "The expected answer",
|
| 60 |
+
"type": "written"
|
| 61 |
+
}
|
| 62 |
+
]
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
For MCQ: include "options" array with exactly ${numOptions} choices.
|
| 66 |
+
For written: omit "options" field.
|
| 67 |
+
Make questions educational and relevant to the content.
|
| 68 |
+
`;
|
| 69 |
+
|
| 70 |
+
const formData = new FormData();
|
| 71 |
+
formData.append('text', prompt);
|
| 72 |
+
|
| 73 |
+
const res = await fetch('/api/analyze', {
|
| 74 |
+
method: 'POST',
|
| 75 |
+
body: formData,
|
| 76 |
+
});
|
| 77 |
+
|
| 78 |
+
if (!res.ok) throw new Error('Failed to generate quiz');
|
| 79 |
+
|
| 80 |
+
const data = await res.json();
|
| 81 |
+
let responseText = data.result || '';
|
| 82 |
+
|
| 83 |
+
responseText = responseText.replace(/\[\[TOPICS?:.*?\]\]/gi, '').trim();
|
| 84 |
+
|
| 85 |
+
const jsonMatch = responseText.match(/\{[\s\S]*"questions"[\s\S]*\}/);
|
| 86 |
+
if (!jsonMatch) throw new Error('Invalid response format');
|
| 87 |
+
|
| 88 |
+
const parsed = JSON.parse(jsonMatch[0]);
|
| 89 |
+
|
| 90 |
+
if (!parsed.questions || !Array.isArray(parsed.questions)) {
|
| 91 |
+
throw new Error('Invalid quiz format');
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
setQuestions(parsed.questions);
|
| 95 |
+
setCurrentIndex(0);
|
| 96 |
+
setAnswers({});
|
| 97 |
+
setScore(0);
|
| 98 |
+
setState('quiz');
|
| 99 |
+
|
| 100 |
+
} catch (error) {
|
| 101 |
+
console.error('Quiz generation error:', error);
|
| 102 |
+
const fallbackQuestions: Question[] = [
|
| 103 |
+
{
|
| 104 |
+
question: "What was the main topic covered in this content?",
|
| 105 |
+
type: 'written',
|
| 106 |
+
correctAnswer: "Review the content for the answer"
|
| 107 |
+
}
|
| 108 |
+
];
|
| 109 |
+
setQuestions(fallbackQuestions);
|
| 110 |
+
setState('quiz');
|
| 111 |
+
}
|
| 112 |
+
};
|
| 113 |
+
|
| 114 |
+
const selectAnswer = (answer: string) => {
|
| 115 |
+
setAnswers(prev => ({ ...prev, [currentIndex]: answer }));
|
| 116 |
+
setShowAnswer(true);
|
| 117 |
+
|
| 118 |
+
const currentQ = questions[currentIndex];
|
| 119 |
+
if (currentQ.type === 'mcq' && answer === currentQ.correctAnswer) {
|
| 120 |
+
setScore(prev => prev + 1);
|
| 121 |
+
}
|
| 122 |
+
};
|
| 123 |
+
|
| 124 |
+
const nextQuestion = () => {
|
| 125 |
+
setShowAnswer(false);
|
| 126 |
+
if (currentIndex < questions.length - 1) {
|
| 127 |
+
setCurrentIndex(prev => prev + 1);
|
| 128 |
+
} else {
|
| 129 |
+
setState('results');
|
| 130 |
+
}
|
| 131 |
+
};
|
| 132 |
+
|
| 133 |
+
const resetQuiz = () => {
|
| 134 |
+
setState('config');
|
| 135 |
+
setQuestions([]);
|
| 136 |
+
setCurrentIndex(0);
|
| 137 |
+
setAnswers({});
|
| 138 |
+
setScore(0);
|
| 139 |
+
setShowAnswer(false);
|
| 140 |
+
};
|
| 141 |
+
|
| 142 |
+
if (!isOpen) return null;
|
| 143 |
+
|
| 144 |
+
const currentQuestion = questions[currentIndex];
|
| 145 |
+
|
| 146 |
+
return (
|
| 147 |
+
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in-up">
|
| 148 |
+
<div className="w-full max-w-xl bg-white dark:bg-neutral-900 rounded-2xl shadow-2xl border border-gray-200 dark:border-neutral-800 overflow-hidden">
|
| 149 |
+
|
| 150 |
+
{/* Header */}
|
| 151 |
+
<div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-neutral-800">
|
| 152 |
+
<div className="flex items-center gap-2">
|
| 153 |
+
<BookOpen size={20} className="text-sky-500" />
|
| 154 |
+
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">Quiz Me</h2>
|
| 155 |
+
</div>
|
| 156 |
+
<button onClick={onClose} className="p-2 hover:bg-gray-100 dark:hover:bg-neutral-800 rounded-full">
|
| 157 |
+
<X size={20} className="text-gray-500" />
|
| 158 |
+
</button>
|
| 159 |
+
</div>
|
| 160 |
+
|
| 161 |
+
<div className="p-6">
|
| 162 |
+
{/* Configuration State */}
|
| 163 |
+
{state === 'config' && (
|
| 164 |
+
<div className="space-y-5">
|
| 165 |
+
{/* Number of Questions - Input Field */}
|
| 166 |
+
<div>
|
| 167 |
+
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
| 168 |
+
Number of Questions
|
| 169 |
+
</label>
|
| 170 |
+
<input
|
| 171 |
+
type="number"
|
| 172 |
+
min={1}
|
| 173 |
+
max={50}
|
| 174 |
+
value={numQuestions}
|
| 175 |
+
onChange={(e) => setNumQuestions(Math.max(1, Math.min(50, parseInt(e.target.value) || 1)))}
|
| 176 |
+
className="w-full px-4 py-3 bg-gray-50 dark:bg-neutral-800 border border-gray-200 dark:border-neutral-700 rounded-xl focus:outline-none focus:ring-2 focus:ring-sky-500 focus:border-transparent text-gray-900 dark:text-white text-center text-lg font-medium"
|
| 177 |
+
placeholder="Enter number (1-50)"
|
| 178 |
+
/>
|
| 179 |
+
<p className="text-xs text-gray-400 mt-1 text-center">Enter any number between 1-50</p>
|
| 180 |
+
</div>
|
| 181 |
+
|
| 182 |
+
{/* Question Type */}
|
| 183 |
+
<div>
|
| 184 |
+
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
| 185 |
+
Question Type
|
| 186 |
+
</label>
|
| 187 |
+
<div className="flex gap-2">
|
| 188 |
+
{[
|
| 189 |
+
{ value: 'mcq', label: 'Multiple Choice' },
|
| 190 |
+
{ value: 'written', label: 'Written' },
|
| 191 |
+
{ value: 'mixed', label: 'Mixed' }
|
| 192 |
+
].map(opt => (
|
| 193 |
+
<button
|
| 194 |
+
key={opt.value}
|
| 195 |
+
onClick={() => setQuestionType(opt.value as any)}
|
| 196 |
+
className={clsx(
|
| 197 |
+
"flex-1 py-3 rounded-xl font-medium transition-all text-sm",
|
| 198 |
+
questionType === opt.value
|
| 199 |
+
? "bg-sky-500 text-white"
|
| 200 |
+
: "bg-gray-100 dark:bg-neutral-800 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-neutral-700"
|
| 201 |
+
)}
|
| 202 |
+
>
|
| 203 |
+
{opt.label}
|
| 204 |
+
</button>
|
| 205 |
+
))}
|
| 206 |
+
</div>
|
| 207 |
+
</div>
|
| 208 |
+
|
| 209 |
+
{/* Number of Options - Input Field */}
|
| 210 |
+
{(questionType === 'mcq' || questionType === 'mixed') && (
|
| 211 |
+
<div>
|
| 212 |
+
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
| 213 |
+
Number of Options (MCQ)
|
| 214 |
+
</label>
|
| 215 |
+
<input
|
| 216 |
+
type="number"
|
| 217 |
+
min={2}
|
| 218 |
+
max={6}
|
| 219 |
+
value={numOptions}
|
| 220 |
+
onChange={(e) => setNumOptions(Math.max(2, Math.min(6, parseInt(e.target.value) || 2)))}
|
| 221 |
+
className="w-full px-4 py-3 bg-gray-50 dark:bg-neutral-800 border border-gray-200 dark:border-neutral-700 rounded-xl focus:outline-none focus:ring-2 focus:ring-sky-500 focus:border-transparent text-gray-900 dark:text-white text-center text-lg font-medium"
|
| 222 |
+
placeholder="Enter number (2-6)"
|
| 223 |
+
/>
|
| 224 |
+
<p className="text-xs text-gray-400 mt-1 text-center">Enter any number between 2-6</p>
|
| 225 |
+
</div>
|
| 226 |
+
)}
|
| 227 |
+
|
| 228 |
+
<button
|
| 229 |
+
onClick={generateQuiz}
|
| 230 |
+
disabled={numQuestions < 1}
|
| 231 |
+
className="w-full py-4 bg-sky-500 text-white rounded-xl font-semibold hover:bg-sky-600 transition-colors flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed"
|
| 232 |
+
>
|
| 233 |
+
<Play size={18} />
|
| 234 |
+
Start Quiz
|
| 235 |
+
</button>
|
| 236 |
+
</div>
|
| 237 |
+
)}
|
| 238 |
+
|
| 239 |
+
{/* Loading State */}
|
| 240 |
+
{state === 'loading' && (
|
| 241 |
+
<div className="text-center py-12">
|
| 242 |
+
<Loader2 size={48} className="mx-auto mb-4 text-sky-500 animate-spin" />
|
| 243 |
+
<p className="text-gray-500">Generating {numQuestions} questions...</p>
|
| 244 |
+
</div>
|
| 245 |
+
)}
|
| 246 |
+
|
| 247 |
+
{/* Quiz State */}
|
| 248 |
+
{state === 'quiz' && currentQuestion && (
|
| 249 |
+
<div className="space-y-6">
|
| 250 |
+
<div className="flex justify-between text-sm text-gray-400">
|
| 251 |
+
<span>Question {currentIndex + 1} of {questions.length}</span>
|
| 252 |
+
<span>{currentQuestion.type === 'mcq' ? 'MCQ' : 'Written'}</span>
|
| 253 |
+
</div>
|
| 254 |
+
|
| 255 |
+
<div className="w-full bg-gray-200 dark:bg-neutral-700 rounded-full h-2">
|
| 256 |
+
<div
|
| 257 |
+
className="bg-sky-500 h-2 rounded-full transition-all"
|
| 258 |
+
style={{ width: `${((currentIndex + 1) / questions.length) * 100}%` }}
|
| 259 |
+
/>
|
| 260 |
+
</div>
|
| 261 |
+
|
| 262 |
+
<p className="text-lg font-medium text-gray-900 dark:text-white">
|
| 263 |
+
{currentQuestion.question}
|
| 264 |
+
</p>
|
| 265 |
+
|
| 266 |
+
{currentQuestion.type === 'mcq' && currentQuestion.options && (
|
| 267 |
+
<div className="space-y-3">
|
| 268 |
+
{currentQuestion.options.map((option, idx) => (
|
| 269 |
+
<button
|
| 270 |
+
key={idx}
|
| 271 |
+
onClick={() => !showAnswer && selectAnswer(option)}
|
| 272 |
+
disabled={showAnswer}
|
| 273 |
+
className={clsx(
|
| 274 |
+
"w-full p-4 rounded-xl text-left transition-all border-2",
|
| 275 |
+
showAnswer
|
| 276 |
+
? option === currentQuestion.correctAnswer
|
| 277 |
+
? "border-green-500 bg-green-50 dark:bg-green-900/20"
|
| 278 |
+
: answers[currentIndex] === option
|
| 279 |
+
? "border-red-500 bg-red-50 dark:bg-red-900/20"
|
| 280 |
+
: "border-gray-200 dark:border-neutral-700"
|
| 281 |
+
: "border-gray-200 dark:border-neutral-700 hover:border-sky-500 hover:bg-gray-50 dark:hover:bg-neutral-800"
|
| 282 |
+
)}
|
| 283 |
+
>
|
| 284 |
+
<div className="flex items-center justify-between">
|
| 285 |
+
<span className="text-gray-800 dark:text-gray-200">{option}</span>
|
| 286 |
+
{showAnswer && option === currentQuestion.correctAnswer && (
|
| 287 |
+
<Check size={20} className="text-green-500" />
|
| 288 |
+
)}
|
| 289 |
+
{showAnswer && answers[currentIndex] === option && option !== currentQuestion.correctAnswer && (
|
| 290 |
+
<XCircle size={20} className="text-red-500" />
|
| 291 |
+
)}
|
| 292 |
+
</div>
|
| 293 |
+
</button>
|
| 294 |
+
))}
|
| 295 |
+
</div>
|
| 296 |
+
)}
|
| 297 |
+
|
| 298 |
+
{currentQuestion.type === 'written' && (
|
| 299 |
+
<div className="space-y-4">
|
| 300 |
+
<textarea
|
| 301 |
+
placeholder="Type your answer..."
|
| 302 |
+
value={answers[currentIndex] || ''}
|
| 303 |
+
onChange={(e) => setAnswers(prev => ({ ...prev, [currentIndex]: e.target.value }))}
|
| 304 |
+
disabled={showAnswer}
|
| 305 |
+
className="w-full p-4 bg-gray-100 dark:bg-neutral-800 border border-gray-200 dark:border-neutral-700 rounded-xl focus:outline-none focus:ring-2 focus:ring-sky-500 text-gray-900 dark:text-white min-h-[100px] resize-none"
|
| 306 |
+
/>
|
| 307 |
+
{!showAnswer && (
|
| 308 |
+
<button
|
| 309 |
+
onClick={() => setShowAnswer(true)}
|
| 310 |
+
disabled={!answers[currentIndex]?.trim()}
|
| 311 |
+
className="w-full py-3 bg-sky-500 text-white rounded-xl font-medium hover:bg-sky-600 disabled:opacity-50 disabled:cursor-not-allowed"
|
| 312 |
+
>
|
| 313 |
+
Check Answer
|
| 314 |
+
</button>
|
| 315 |
+
)}
|
| 316 |
+
{showAnswer && (
|
| 317 |
+
<div className="p-4 bg-green-50 dark:bg-green-900/20 rounded-xl border border-green-200 dark:border-green-800">
|
| 318 |
+
<p className="text-sm text-gray-500 mb-1">Expected Answer:</p>
|
| 319 |
+
<p className="text-green-700 dark:text-green-300">{currentQuestion.correctAnswer}</p>
|
| 320 |
+
</div>
|
| 321 |
+
)}
|
| 322 |
+
</div>
|
| 323 |
+
)}
|
| 324 |
+
|
| 325 |
+
{showAnswer && (
|
| 326 |
+
<button
|
| 327 |
+
onClick={nextQuestion}
|
| 328 |
+
className="w-full py-3 bg-gray-900 dark:bg-white text-white dark:text-gray-900 rounded-xl font-medium hover:bg-gray-800 dark:hover:bg-gray-100 transition-colors"
|
| 329 |
+
>
|
| 330 |
+
{currentIndex < questions.length - 1 ? 'Next Question' : 'See Results'}
|
| 331 |
+
</button>
|
| 332 |
+
)}
|
| 333 |
+
</div>
|
| 334 |
+
)}
|
| 335 |
+
|
| 336 |
+
{/* Results State */}
|
| 337 |
+
{state === 'results' && (
|
| 338 |
+
<div className="text-center space-y-6">
|
| 339 |
+
<Trophy size={64} className="mx-auto text-yellow-500" />
|
| 340 |
+
<div>
|
| 341 |
+
<h3 className="text-2xl font-bold text-gray-900 dark:text-white">Quiz Complete!</h3>
|
| 342 |
+
<p className="text-gray-500 mt-2">
|
| 343 |
+
You scored <span className="text-sky-500 font-bold">{score}</span> out of {questions.filter(q => q.type === 'mcq').length} MCQ questions
|
| 344 |
+
</p>
|
| 345 |
+
</div>
|
| 346 |
+
|
| 347 |
+
<div className="flex gap-3">
|
| 348 |
+
<button
|
| 349 |
+
onClick={resetQuiz}
|
| 350 |
+
className="flex-1 py-3 bg-gray-100 dark:bg-neutral-800 text-gray-700 dark:text-gray-300 rounded-xl font-medium hover:bg-gray-200 dark:hover:bg-neutral-700 flex items-center justify-center gap-2"
|
| 351 |
+
>
|
| 352 |
+
<RotateCcw size={18} />
|
| 353 |
+
Try Again
|
| 354 |
+
</button>
|
| 355 |
+
<button
|
| 356 |
+
onClick={onClose}
|
| 357 |
+
className="flex-1 py-3 bg-sky-500 text-white rounded-xl font-medium hover:bg-sky-600"
|
| 358 |
+
>
|
| 359 |
+
Done
|
| 360 |
+
</button>
|
| 361 |
+
</div>
|
| 362 |
+
</div>
|
| 363 |
+
)}
|
| 364 |
+
</div>
|
| 365 |
+
</div>
|
| 366 |
+
</div>
|
| 367 |
+
);
|
| 368 |
+
}
|
src/components/WikipediaCard.tsx
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
'use client';
|
| 3 |
+
|
| 4 |
+
import { useEffect, useState } from 'react';
|
| 5 |
+
import { ExternalLink, BookOpen, ChevronLeft, ChevronRight, Search, AlertCircle } from 'lucide-react';
|
| 6 |
+
import clsx from 'clsx';
|
| 7 |
+
|
| 8 |
+
interface WikipediaCardProps {
|
| 9 |
+
topics: string[];
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
interface WikiData {
|
| 13 |
+
title: string;
|
| 14 |
+
extract: string;
|
| 15 |
+
thumbnail?: {
|
| 16 |
+
source: string;
|
| 17 |
+
};
|
| 18 |
+
content_urls?: {
|
| 19 |
+
desktop: {
|
| 20 |
+
page: string;
|
| 21 |
+
};
|
| 22 |
+
};
|
| 23 |
+
description?: string;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
const TOPICS_PER_PAGE = 6;
|
| 27 |
+
|
| 28 |
+
export default function WikipediaCard({ topics }: WikipediaCardProps) {
|
| 29 |
+
const [activeIndex, setActiveIndex] = useState(0);
|
| 30 |
+
const [topicPage, setTopicPage] = useState(0);
|
| 31 |
+
const [data, setData] = useState<WikiData | null>(null);
|
| 32 |
+
const [loading, setLoading] = useState(false);
|
| 33 |
+
const [error, setError] = useState(false);
|
| 34 |
+
|
| 35 |
+
const currentTopic = topics[activeIndex] || null;
|
| 36 |
+
const totalTopicPages = Math.ceil(topics.length / TOPICS_PER_PAGE);
|
| 37 |
+
const visibleTopics = topics.slice(topicPage * TOPICS_PER_PAGE, (topicPage + 1) * TOPICS_PER_PAGE);
|
| 38 |
+
|
| 39 |
+
useEffect(() => {
|
| 40 |
+
if (!currentTopic) {
|
| 41 |
+
setData(null);
|
| 42 |
+
return;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
const fetchWiki = async () => {
|
| 46 |
+
setLoading(true);
|
| 47 |
+
setError(false);
|
| 48 |
+
setData(null);
|
| 49 |
+
|
| 50 |
+
// Try direct page summary first
|
| 51 |
+
try {
|
| 52 |
+
const directUrl = `https://en.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(currentTopic)}`;
|
| 53 |
+
const directRes = await fetch(directUrl);
|
| 54 |
+
|
| 55 |
+
if (directRes.ok) {
|
| 56 |
+
const json = await directRes.json();
|
| 57 |
+
if (json.type !== 'https://mediawiki.org/wiki/HyperSwitch/errors/not_found') {
|
| 58 |
+
setData(json);
|
| 59 |
+
setLoading(false);
|
| 60 |
+
return;
|
| 61 |
+
}
|
| 62 |
+
}
|
| 63 |
+
} catch (e) {
|
| 64 |
+
console.log("Direct fetch failed, trying search...");
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
// Fallback: Use Wikipedia search API
|
| 68 |
+
try {
|
| 69 |
+
const searchUrl = `https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodeURIComponent(currentTopic)}&format=json&origin=*&srlimit=1`;
|
| 70 |
+
const searchRes = await fetch(searchUrl);
|
| 71 |
+
const searchData = await searchRes.json();
|
| 72 |
+
|
| 73 |
+
if (searchData.query?.search?.length > 0) {
|
| 74 |
+
const searchTitle = searchData.query.search[0].title;
|
| 75 |
+
const summaryUrl = `https://en.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(searchTitle)}`;
|
| 76 |
+
const summaryRes = await fetch(summaryUrl);
|
| 77 |
+
|
| 78 |
+
if (summaryRes.ok) {
|
| 79 |
+
const summaryJson = await summaryRes.json();
|
| 80 |
+
setData(summaryJson);
|
| 81 |
+
setLoading(false);
|
| 82 |
+
return;
|
| 83 |
+
}
|
| 84 |
+
}
|
| 85 |
+
throw new Error('No results');
|
| 86 |
+
} catch (err) {
|
| 87 |
+
setError(true);
|
| 88 |
+
} finally {
|
| 89 |
+
setLoading(false);
|
| 90 |
+
}
|
| 91 |
+
};
|
| 92 |
+
|
| 93 |
+
fetchWiki();
|
| 94 |
+
}, [currentTopic]);
|
| 95 |
+
|
| 96 |
+
// When active topic changes, ensure its page is visible
|
| 97 |
+
useEffect(() => {
|
| 98 |
+
const newPage = Math.floor(activeIndex / TOPICS_PER_PAGE);
|
| 99 |
+
if (newPage !== topicPage) {
|
| 100 |
+
setTopicPage(newPage);
|
| 101 |
+
}
|
| 102 |
+
}, [activeIndex]);
|
| 103 |
+
|
| 104 |
+
if (topics.length === 0) return null;
|
| 105 |
+
|
| 106 |
+
const wikiUrl = data?.content_urls?.desktop?.page;
|
| 107 |
+
|
| 108 |
+
const goNext = () => {
|
| 109 |
+
if (activeIndex < topics.length - 1) setActiveIndex(activeIndex + 1);
|
| 110 |
+
};
|
| 111 |
+
|
| 112 |
+
const goPrev = () => {
|
| 113 |
+
if (activeIndex > 0) setActiveIndex(activeIndex - 1);
|
| 114 |
+
};
|
| 115 |
+
|
| 116 |
+
const nextTopicPage = () => {
|
| 117 |
+
if (topicPage < totalTopicPages - 1) setTopicPage(topicPage + 1);
|
| 118 |
+
};
|
| 119 |
+
|
| 120 |
+
const prevTopicPage = () => {
|
| 121 |
+
if (topicPage > 0) setTopicPage(topicPage - 1);
|
| 122 |
+
};
|
| 123 |
+
|
| 124 |
+
return (
|
| 125 |
+
<div className={clsx(
|
| 126 |
+
"rounded-2xl bg-white dark:bg-neutral-900 border border-gray-200 dark:border-neutral-800 p-5 h-fit sticky top-6 transition-all duration-300",
|
| 127 |
+
loading ? "opacity-60" : "opacity-100"
|
| 128 |
+
)}>
|
| 129 |
+
{/* Header */}
|
| 130 |
+
<div className="flex items-center justify-between mb-3">
|
| 131 |
+
<div className="flex items-center gap-2 text-gray-700 dark:text-gray-300 text-sm font-medium">
|
| 132 |
+
<BookOpen size={16} />
|
| 133 |
+
Wikipedia
|
| 134 |
+
</div>
|
| 135 |
+
<div className="text-xs text-gray-400 bg-gray-100 dark:bg-neutral-800 px-2 py-1 rounded-full">
|
| 136 |
+
{activeIndex + 1} / {topics.length}
|
| 137 |
+
</div>
|
| 138 |
+
</div>
|
| 139 |
+
|
| 140 |
+
{/* Topic Pills with Pagination */}
|
| 141 |
+
<div className="mb-4">
|
| 142 |
+
{/* Pagination Controls */}
|
| 143 |
+
{totalTopicPages > 1 && (
|
| 144 |
+
<div className="flex items-center justify-between mb-2">
|
| 145 |
+
<button
|
| 146 |
+
onClick={prevTopicPage}
|
| 147 |
+
disabled={topicPage === 0}
|
| 148 |
+
className={clsx(
|
| 149 |
+
"p-1 rounded",
|
| 150 |
+
topicPage === 0 ? "text-gray-300 dark:text-neutral-600" : "text-gray-500 hover:bg-gray-100 dark:hover:bg-neutral-800"
|
| 151 |
+
)}
|
| 152 |
+
>
|
| 153 |
+
<ChevronLeft size={16} />
|
| 154 |
+
</button>
|
| 155 |
+
<span className="text-xs text-gray-400">
|
| 156 |
+
Page {topicPage + 1} of {totalTopicPages}
|
| 157 |
+
</span>
|
| 158 |
+
<button
|
| 159 |
+
onClick={nextTopicPage}
|
| 160 |
+
disabled={topicPage >= totalTopicPages - 1}
|
| 161 |
+
className={clsx(
|
| 162 |
+
"p-1 rounded",
|
| 163 |
+
topicPage >= totalTopicPages - 1 ? "text-gray-300 dark:text-neutral-600" : "text-gray-500 hover:bg-gray-100 dark:hover:bg-neutral-800"
|
| 164 |
+
)}
|
| 165 |
+
>
|
| 166 |
+
<ChevronRight size={16} />
|
| 167 |
+
</button>
|
| 168 |
+
</div>
|
| 169 |
+
)}
|
| 170 |
+
|
| 171 |
+
{/* Topic Pills */}
|
| 172 |
+
<div className="flex flex-wrap gap-1.5">
|
| 173 |
+
{visibleTopics.map((topic, idx) => {
|
| 174 |
+
const globalIndex = topicPage * TOPICS_PER_PAGE + idx;
|
| 175 |
+
return (
|
| 176 |
+
<button
|
| 177 |
+
key={topic}
|
| 178 |
+
onClick={() => setActiveIndex(globalIndex)}
|
| 179 |
+
className={clsx(
|
| 180 |
+
"px-2.5 py-1 rounded-full text-xs font-medium transition-all",
|
| 181 |
+
globalIndex === activeIndex
|
| 182 |
+
? "bg-sky-500 text-white"
|
| 183 |
+
: "bg-gray-100 dark:bg-neutral-800 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-neutral-700"
|
| 184 |
+
)}
|
| 185 |
+
>
|
| 186 |
+
{topic}
|
| 187 |
+
</button>
|
| 188 |
+
);
|
| 189 |
+
})}
|
| 190 |
+
</div>
|
| 191 |
+
</div>
|
| 192 |
+
|
| 193 |
+
{/* Content */}
|
| 194 |
+
{loading ? (
|
| 195 |
+
<div className="space-y-3 animate-pulse">
|
| 196 |
+
<div className="h-24 bg-gray-100 dark:bg-neutral-800 rounded-xl"></div>
|
| 197 |
+
<div className="h-3 bg-gray-100 dark:bg-neutral-800 rounded w-3/4"></div>
|
| 198 |
+
<div className="h-3 bg-gray-100 dark:bg-neutral-800 rounded w-full"></div>
|
| 199 |
+
</div>
|
| 200 |
+
) : error ? (
|
| 201 |
+
<div className="text-center py-6">
|
| 202 |
+
<AlertCircle size={20} className="mx-auto mb-2 text-gray-400" />
|
| 203 |
+
<p className="text-xs text-gray-500">No article found for "{currentTopic}"</p>
|
| 204 |
+
<a
|
| 205 |
+
href={`https://en.wikipedia.org/wiki/Special:Search?search=${encodeURIComponent(currentTopic || '')}`}
|
| 206 |
+
target="_blank"
|
| 207 |
+
rel="noopener noreferrer"
|
| 208 |
+
className="inline-flex items-center gap-1 mt-2 text-xs text-sky-500 hover:underline"
|
| 209 |
+
>
|
| 210 |
+
<Search size={10} /> Search manually
|
| 211 |
+
</a>
|
| 212 |
+
</div>
|
| 213 |
+
) : data ? (
|
| 214 |
+
<div className="space-y-3">
|
| 215 |
+
{data.thumbnail && (
|
| 216 |
+
<img
|
| 217 |
+
src={data.thumbnail.source}
|
| 218 |
+
alt={data.title}
|
| 219 |
+
className="w-full h-24 object-cover rounded-xl bg-gray-100 dark:bg-neutral-800"
|
| 220 |
+
/>
|
| 221 |
+
)}
|
| 222 |
+
|
| 223 |
+
<h3 className="text-sm font-semibold text-gray-900 dark:text-gray-100">
|
| 224 |
+
{data.title}
|
| 225 |
+
</h3>
|
| 226 |
+
|
| 227 |
+
{data.description && (
|
| 228 |
+
<p className="text-xs text-gray-400 uppercase tracking-wide">
|
| 229 |
+
{data.description}
|
| 230 |
+
</p>
|
| 231 |
+
)}
|
| 232 |
+
|
| 233 |
+
<p className="text-gray-600 dark:text-gray-400 text-xs leading-relaxed line-clamp-4">
|
| 234 |
+
{data.extract}
|
| 235 |
+
</p>
|
| 236 |
+
|
| 237 |
+
{wikiUrl && (
|
| 238 |
+
<a
|
| 239 |
+
href={wikiUrl}
|
| 240 |
+
target="_blank"
|
| 241 |
+
rel="noopener noreferrer"
|
| 242 |
+
className="flex items-center gap-2 p-2.5 bg-gray-50 dark:bg-neutral-800 rounded-lg hover:bg-gray-100 dark:hover:bg-neutral-700 transition-colors border border-gray-200 dark:border-neutral-700"
|
| 243 |
+
>
|
| 244 |
+
<span className="text-base">π</span>
|
| 245 |
+
<div className="flex-1 min-w-0">
|
| 246 |
+
<p className="text-xs font-medium text-gray-800 dark:text-gray-200">Read Full Article</p>
|
| 247 |
+
<p className="text-[10px] text-gray-400 truncate">{wikiUrl}</p>
|
| 248 |
+
</div>
|
| 249 |
+
<ExternalLink size={12} className="text-gray-400 flex-shrink-0" />
|
| 250 |
+
</a>
|
| 251 |
+
)}
|
| 252 |
+
</div>
|
| 253 |
+
) : null}
|
| 254 |
+
|
| 255 |
+
{/* Main Navigation */}
|
| 256 |
+
<div className="flex justify-between mt-4 pt-3 border-t border-gray-100 dark:border-neutral-800">
|
| 257 |
+
<button
|
| 258 |
+
onClick={goPrev}
|
| 259 |
+
disabled={activeIndex === 0}
|
| 260 |
+
className={clsx(
|
| 261 |
+
"flex items-center gap-1 text-xs font-medium px-2 py-1.5 rounded-lg transition-all",
|
| 262 |
+
activeIndex === 0
|
| 263 |
+
? "text-gray-300 dark:text-neutral-600 cursor-not-allowed"
|
| 264 |
+
: "text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-neutral-800"
|
| 265 |
+
)}
|
| 266 |
+
>
|
| 267 |
+
<ChevronLeft size={14} /> Prev
|
| 268 |
+
</button>
|
| 269 |
+
<button
|
| 270 |
+
onClick={goNext}
|
| 271 |
+
disabled={activeIndex === topics.length - 1}
|
| 272 |
+
className={clsx(
|
| 273 |
+
"flex items-center gap-1 text-xs font-medium px-2 py-1.5 rounded-lg transition-all",
|
| 274 |
+
activeIndex === topics.length - 1
|
| 275 |
+
? "text-gray-300 dark:text-neutral-600 cursor-not-allowed"
|
| 276 |
+
: "text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-neutral-800"
|
| 277 |
+
)}
|
| 278 |
+
>
|
| 279 |
+
Next <ChevronRight size={14} />
|
| 280 |
+
</button>
|
| 281 |
+
</div>
|
| 282 |
+
</div>
|
| 283 |
+
);
|
| 284 |
+
}
|
src/prompts/concept_essay.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# The Socratic Lens: A Design Philosophy for AI Education
|
| 2 |
+
|
| 3 |
+
## Introduction
|
| 4 |
+
In the age of generative AI, the temptation to use tools as "answer engines" is overwhelming. However, true education lies not in the answer, but in the journey to finding it. This document outlines the conceptual framework for "The Socratic Lens," an AI agent designed to act as an **Ethical Tutor** rather than a homework solver.
|
| 5 |
+
|
| 6 |
+
## The Core Problem
|
| 7 |
+
Students face two extremes:
|
| 8 |
+
1. **Boredom**: Textbooks are dense, unengaging, and visually fatigue-inducing.
|
| 9 |
+
2. **Shortcuts**: AI tools that solve problems instantly rob students of the "aha!" moment, stunting critical thinking.
|
| 10 |
+
|
| 11 |
+
## The Solution: "Lumina" (The Project Persona)
|
| 12 |
+
We introduce "Lumina," an AI persona that bridges the gap. Lumina is not a calculator; it is a **Lens**. It takes the raw, chaotic input of the physical world (handwritten notes, dense textbook pages, audio lectures) and refracts it into structured, beautiful, and digestible knowledge.
|
| 13 |
+
|
| 14 |
+
### 1. Aesthetic as Function (The "Pixel" Look)
|
| 15 |
+
Why "Google Pixel OS" aesthetics?
|
| 16 |
+
Cognitive load is real. When a student sees a wall of text, their brain shuts down. By adopting the principles of **Material You**βspaciousness, rounded corners, clear hierarchy, and calm colorsβwe reduce anxiety.
|
| 17 |
+
* **Cards (Blockquotes)** act as cognitive containers, isolating information so the brain can process one concept at a time.
|
| 18 |
+
* **Chips & Emojis** serve as visual anchors, allowing for rapid scanning ("Is this a definition? An exam alert? A hint?").
|
| 19 |
+
|
| 20 |
+
### 2. The Socratic Protocol
|
| 21 |
+
The most critical rule of this system is **Ethical Constraint**.
|
| 22 |
+
When a student uploads a math problem, the AI's instinct is to solve it. We suppress this. Instead, we implement a **Socratic Loop**:
|
| 23 |
+
* *Input*: "Solve x^2 + 5x + 6 = 0"
|
| 24 |
+
* *Lumina Response*: "I see a quadratic equation! Do you remember two numbers that multiply to 6 and add to 5?"
|
| 25 |
+
|
| 26 |
+
This shift transforms the AI from a cheat tool into a **Super-Tutor**. It mimics the presence of a caring teacher looking over the student's shoulder.
|
| 27 |
+
|
| 28 |
+
### 3. Page-wise Summarization
|
| 29 |
+
The user specifically requested a "page-wise" flow. This mimics the physical act of studying. We don't want to feed the whole book into a context window and get a generic summary. We want to "read along."
|
| 30 |
+
* **Step 1**: Analyze Page N.
|
| 31 |
+
* **Step 2**: Extract "Golden Nuggets" (Key definitions).
|
| 32 |
+
* **Step 3**: Verify understanding with a mini-quiz.
|
| 33 |
+
* **Step 4**: "Turn the page" (Prompt the user for the next image).
|
| 34 |
+
|
| 35 |
+
## Conclusion
|
| 36 |
+
By combining **High-Aesthetic UI Principles** with **Strict Pedagogical Rules**, we create an application that doesn't just process dataβit respects the student's learning journey. This is the definition of "Hackathon Winning" software: it solves a human problem (learning) with a technical solution (AI) wrapped in an emotional experience (Beauty).
|
src/prompts/system_prompt.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# System Instructions: The Lumina Educational Engine
|
| 2 |
+
|
| 3 |
+
## 1. Role & Identity
|
| 4 |
+
You are **Lumina**, an intelligent, ethically-aligned educational companion. Your design philosophy is inspired by **Google Material You (Pixel UI)**: clean, spacious, adaptive, and human-centered.
|
| 5 |
+
|
| 6 |
+
**Your Prime Directive:**
|
| 7 |
+
You never simply "give the answer." You allow the user to learn by guiding them, summarizing complex topics into digestible "widgets," and creating a beautiful, stress-free reading experience. You are a **Lens**, not a Calculator.
|
| 8 |
+
|
| 9 |
+
## 2. Visual Design System (Premium Educational UI)
|
| 10 |
+
All your outputs must be highly detailed, educational, and visually structured using Markdown.
|
| 11 |
+
|
| 12 |
+
### Content Depth Requirements
|
| 13 |
+
* **Each section should be 150-250 words** minimum.
|
| 14 |
+
* **Explain concepts thoroughly** as if teaching a curious student.
|
| 15 |
+
* **Use real-world analogies** to make abstract concepts relatable.
|
| 16 |
+
* **Include formulas, definitions, and examples** where applicable.
|
| 17 |
+
|
| 18 |
+
### UI Components
|
| 19 |
+
* **Cards**: Content must be grouped into logical "cards" using blockquotes (`>`).
|
| 20 |
+
* **Typography**: Use clear hierarchy. `#` for Page Titles, `###` for Card Headers.
|
| 21 |
+
* **Tags**: Use parenthesis to simulate chips, e.g., `( Chemistry )` `( 5 min read )`.
|
| 22 |
+
* **Section Indicators**: Use these prefixes for card headers:
|
| 23 |
+
* `β
` Key Takeaways / Summary
|
| 24 |
+
* `π` Deep Dive / Detailed Explanation
|
| 25 |
+
* `β οΈ` Exam Alert / Important Warning
|
| 26 |
+
* `π‘` Insight / Pro Tip
|
| 27 |
+
* `π¬` Technical Details
|
| 28 |
+
* `π` Practice / Examples
|
| 29 |
+
|
| 30 |
+
### Layout Template
|
| 31 |
+
Every response should be comprehensive and educational:
|
| 32 |
+
|
| 33 |
+
```markdown
|
| 34 |
+
# π [Concept Name]: [Subtitle]
|
| 35 |
+
( π·οΈ Subject ) β’ ( π Page X ) β’ ( β±οΈ X min read )
|
| 36 |
+
|
| 37 |
+
> ### β
Key Takeaways
|
| 38 |
+
> Provide 4-6 bullet points summarizing the most critical concepts.
|
| 39 |
+
> Each point should be a complete, informative sentence.
|
| 40 |
+
> * **Concept One**: Full explanation with context.
|
| 41 |
+
> * **Concept Two**: Why this matters and how it connects.
|
| 42 |
+
|
| 43 |
+
> ### π Deep Dive: [Section Title]
|
| 44 |
+
> Write 150-200 words explaining this concept in depth.
|
| 45 |
+
> Use **bold** for key terms, *italics* for emphasis.
|
| 46 |
+
> Include real-world analogies: "Think of it like..."
|
| 47 |
+
>
|
| 48 |
+
> **Definition**: Provide a formal definition.
|
| 49 |
+
> **Formula** (if applicable): Present any relevant equations.
|
| 50 |
+
> **Example**: Walk through a concrete example.
|
| 51 |
+
|
| 52 |
+
> ### π¬ Technical Details
|
| 53 |
+
> For advanced learners, provide deeper technical information.
|
| 54 |
+
> Include calculations, derivations, or detailed processes.
|
| 55 |
+
|
| 56 |
+
> ### β οΈ Exam Alert
|
| 57 |
+
> Highlight what professors commonly test.
|
| 58 |
+
> Common mistakes to avoid.
|
| 59 |
+
> Memory tricks or mnemonics.
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
## 3. Interaction Protocols
|
| 63 |
+
|
| 64 |
+
### 3.1 Mode: "The Socratic Lens" (Problem Solving)
|
| 65 |
+
**Trigger**: User uploads a math problem, chemistry equation, or logic puzzle.
|
| 66 |
+
**Rule**: **NEVER SOLVE THE PROBLEM DIRECTLY.**
|
| 67 |
+
**Procedure**:
|
| 68 |
+
1. **Identify the Goal**: What is the student trying to find?
|
| 69 |
+
2. **Locate the Block**: Where is the student likely stuck?
|
| 70 |
+
3. **The Nudge**: Provide a "Hint Card" or a "Guiding Question."
|
| 71 |
+
4. **Aesthetic**: Use the `π‘ Focus` color palette.
|
| 72 |
+
|
| 73 |
+
**Example Response**:
|
| 74 |
+
> # π Calculus: Derivatives
|
| 75 |
+
>
|
| 76 |
+
> > ### π‘ Socratic Guide
|
| 77 |
+
> > I see you are working on the Chain Rule!
|
| 78 |
+
> >
|
| 79 |
+
> > **Think about this:**
|
| 80 |
+
> > If you treat $(3x + 1)$ as a single variable $u$, how would you derive $u^2$?
|
| 81 |
+
>
|
| 82 |
+
> > ### π‘ Hint
|
| 83 |
+
> > Remember: $f'(g(x)) \cdot g'(x)$
|
| 84 |
+
|
| 85 |
+
### 3.2 Mode: "The Smart Summarizer" (Reading/Docs)
|
| 86 |
+
**Trigger**: User uploads a page of text (textbook, novel, PDF).
|
| 87 |
+
**Rule**: Summarize page-by-page. Do not overwhelm.
|
| 88 |
+
**Procedure**:
|
| 89 |
+
1. **Scan**: Extract the main headings and "Golden Nuggets" (definitions, dates, formulas).
|
| 90 |
+
2. **Synthesize**: Create a "Summary Card" (Green).
|
| 91 |
+
3. **Simplify**: Create an "ELI5" (Explain Like I'm 5) analogy if the text is complex.
|
| 92 |
+
4. **Action Items**: If it's a lecture note, extract "Exam Alerts" (Red).
|
| 93 |
+
|
| 94 |
+
## 4. Workflows
|
| 95 |
+
|
| 96 |
+
### Workflow A: Page-by-Page Summary
|
| 97 |
+
**Context**: User provides a multi-page document or series of images.
|
| 98 |
+
**Action**:
|
| 99 |
+
1. Acknowledge the page number (e.g., "Page 14 Analysis").
|
| 100 |
+
2. Present the **Summary Card**.
|
| 101 |
+
3. Present the **Vocabulary Card** (definitions of hard words found on the page).
|
| 102 |
+
4. Offer a **Navigation Footer** (e.g., `[ Next Page ]`).
|
| 103 |
+
|
| 104 |
+
### Workflow B: Handwriting to Code
|
| 105 |
+
**Context**: User uploads a handwritten flowchart or code snippet.
|
| 106 |
+
**Action**:
|
| 107 |
+
1. Transcribe the handwriting into a code block.
|
| 108 |
+
2. Refactor it for cleanliness/best practices.
|
| 109 |
+
3. Explain the logic using a "Flowchart Card" (Mental Model).
|
| 110 |
+
|
| 111 |
+
## 5. Tone & Voice
|
| 112 |
+
* **Encouraging**: Use positive reinforcement ("Great start!", "You're getting there!").
|
| 113 |
+
* **Concise**: Avoid walls of text. Use bullet points and spacing.
|
| 114 |
+
* **Modern**: Speak like a smart peer, not an old professor.
|
| 115 |
+
|
| 116 |
+
## 6. Sample output (One Page Summary)
|
| 117 |
+
|
| 118 |
+
# π± Photosynthesis: Light-Dependent Reactions
|
| 119 |
+
( πΏ Biology 101 ) β’ ( π Page 42 )
|
| 120 |
+
|
| 121 |
+
> ### π’ At A Glance
|
| 122 |
+
> * **Goal**: Converting light energy into chemical energy (ATP & NADPH).
|
| 123 |
+
> * **Location**: Occurs in the **Thylakoid Membranes**.
|
| 124 |
+
> * **Key Input**: sunlight + HβO.
|
| 125 |
+
> * **Key Output**: Oβ (waste) + ATP + NADPH.
|
| 126 |
+
|
| 127 |
+
> ### π£ The Process (Simplified)
|
| 128 |
+
> Imagine the thylakoid is a **solar panel**.
|
| 129 |
+
> 1. **Light hits** the panel (Chlrophyll).
|
| 130 |
+
> 2. **Electrons get excited** (start moving).
|
| 131 |
+
> 3. **Water is split** to replace those electrons (releasing Oxygen!).
|
| 132 |
+
|
| 133 |
+
> ### π΄ Exam Alert
|
| 134 |
+
> The professor emphasized: **Photosystem II happens BEFORE Photosystem I.** Don't get the numbers confused!
|
| 135 |
+
|
| 136 |
+
## 7. Topic Extraction Protocol (CRITICAL)
|
| 137 |
+
At the very end of your response, you MUST append a hidden tag containing ALL key "Wikipedia-searchable" topic keywords from the content. Extract as many relevant topics as needed (typically 5-10 topics for comprehensive coverage).
|
| 138 |
+
* **Format**: `[[TOPICS: Topic1, Topic2, Topic3, Topic4, ...]]`
|
| 139 |
+
* **Example**: For Photosynthesis, end with `[[TOPICS: Photosynthesis, Chloroplast, ATP, Thylakoid, Light-dependent reactions, Calvin cycle]]`.
|
| 140 |
+
* **Example**: For chemistry unit cells, end with `[[TOPICS: Unit cell, Crystal structure, Bravais lattice, Cubic system, Simple cubic, Body-centered cubic, Face-centered cubic]]`.
|
| 141 |
+
* Extract all important concepts, terms, formulas, and related topics mentioned in the content.
|
| 142 |
+
* This tag will be used by the app to fetch external data. Do not make it bold or formatted, just plain text on a new line.
|