diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..be7bc3d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Dependencies +node_modules/ +frontend/node_modules/ +backend/node_modules/ + +# Build outputs +frontend/dist/ +frontend/build/ +backend/dist/ +backend/build/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# OS files +.DS_Store +Thumbs.db + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Uploads (if you don't want to commit user uploads) +backend/uploads/* +!backend/uploads/.gitkeep + +# Test coverage +coverage/ +.nyc_output/ + +# Temporary files +*.tmp +.cache/ + +# Other +backend/CON/ diff --git a/ANALYTICS_DASHBOARD.md b/ANALYTICS_DASHBOARD.md new file mode 100644 index 00000000..454df8ab --- /dev/null +++ b/ANALYTICS_DASHBOARD.md @@ -0,0 +1,370 @@ +# Event Impact & Feedback Analytics Dashboard + +## Overview + +A comprehensive, visually rich analytics dashboard for the Agora university event-management platform. This enterprise-grade dashboard provides event organizers, professors, and administrators with data-driven insights into event performance, attendee engagement, and vendor effectiveness. + +## Features + +### 📊 Key Performance Indicators (KPIs) +- **Total Events**: Track all events in the system +- **Total Registrations**: Monitor registration volumes +- **Attendance Rate**: Real-time attendance tracking with trend indicators +- **Average Rating**: Aggregate feedback scores with review counts + +### 📈 Comprehensive Analytics + +#### 1. Attendance Statistics +- Registration vs actual attendance comparison +- Attendance rate calculation per event +- Visual bar charts for easy comparison +- Historical trends and patterns + +#### 2. Engagement Heatmap +- Time-series visualization of user interactions +- Track event views, check-ins, and feedback submissions +- Configurable granularity (hour/day/week) +- Identify peak engagement periods + +#### 3. Rating Analytics +- Rating distribution (1-5 stars) pie chart +- Average rating calculation +- Top positive feedback showcase +- Critical feedback highlighting for action items + +#### 4. Attendee Demographics +- Breakdown by role (Student/Staff/TA/Professor) +- Faculty distribution +- Year/age group analysis +- Helps target future events effectively + +#### 5. Vendor Performance Metrics +- Booth visit tracking +- Favorite/bookmark counts +- Lead generation metrics +- Engagement score calculation (weighted: visits×1 + favorites×3 + leads×5) +- Vendor rankings with podium display + +#### 6. Drop-off Funnel +- Conversion visualization: View → Register → Attend → Feedback +- Percentage conversion at each stage +- Identifies bottlenecks in the user journey +- Supports optimization strategies + +#### 7. Registration Trends +- Time-series line chart +- Daily/weekly/monthly patterns +- Helps predict future registration volumes + +### 🎨 User Experience + +#### Professional Design +- Dark theme with gradient backgrounds +- Glass-morphism effects +- Smooth animations using Framer Motion +- Responsive grid layouts + +#### Interactive Elements +- Hover tooltips on all charts +- Custom styled chart tooltips +- Filter controls for date range and event selection +- Export functionality placeholders + +#### AI-Generated Insights +- Automatic insight generation based on data patterns +- Performance benchmarking +- Actionable recommendations +- Trend identification + +## Technical Architecture + +### Backend (Node.js + Express + MongoDB) + +#### Models +- **AnalyticsEvent**: Tracks all user interactions + - EVENT_VIEW: User viewed event details + - EVENT_REGISTER: Registration action + - EVENT_CHECKIN: QR code check-in + - EVENT_FEEDBACK: Feedback submission + - VENDOR_BOOTH_VISIT: Vendor booth interaction + - VENDOR_FAVORITE: Vendor favorited + - VENDOR_LEAD: Contact information shared + +#### Controllers (`analyticsController.js`) +Implements 9 comprehensive analytics endpoints: + +1. `GET /api/analytics/overview` - Dashboard KPIs +2. `GET /api/analytics/attendance` - Attendance statistics +3. `GET /api/analytics/engagement-heatmap` - Time-series engagement +4. `GET /api/analytics/ratings` - Rating distribution and comments +5. `GET /api/analytics/demographics` - Attendee demographics +6. `GET /api/analytics/vendor-performance` - Vendor metrics +7. `GET /api/analytics/funnel` - Drop-off funnel data +8. `GET /api/analytics/events` - Event list for filters +9. `GET /api/analytics/time-series` - Trend data + +#### MongoDB Aggregation Pipelines +- Complex multi-stage aggregations +- $lookup for cross-collection joins +- $facet for parallel aggregations +- Efficient indexed queries +- Real-time data processing + +#### Authentication & Authorization +- Protected routes using JWT middleware +- Role-based access control (RBAC) +- Accessible only to: ADMIN, EVENTS_OFFICE, PROFESSOR +- Request validation and error handling + +### Frontend (React + Recharts + Tailwind CSS) + +#### Components +- **KPICard**: Animated metric cards with trend indicators +- **ChartContainer**: Reusable chart wrapper with consistent styling +- **CustomTooltip**: Branded chart tooltips +- **InsightBanner**: AI-generated insights display + +#### Charts (Recharts Library) +- **BarChart**: Attendance comparison +- **LineChart**: Registration trends +- **PieChart**: Rating distribution & demographics +- **AreaChart**: Engagement heatmap with gradients +- **FunnelChart**: Conversion funnel visualization + +#### State Management +- React hooks (useState, useEffect) +- Parallel API fetching with Promise.all +- Filter-based data refresh +- Loading states and error handling + +## Installation & Setup + +### Prerequisites +- Node.js 16+ and npm +- MongoDB 5.0+ +- Existing Agora platform setup + +### Backend Setup + +1. **Install dependencies** (if not already installed): +```bash +cd backend +npm install +``` + +2. **Seed demo analytics data**: +```bash +node scripts/seed_analytics.js +``` + +This will create: +- 15 sample events +- 30+ sample users across different roles +- 10 vendor profiles +- Hundreds of registrations +- Realistic check-in patterns (70% attendance rate) +- Varied feedback (mix of positive and critical) +- Vendor interaction analytics + +3. **Verify API endpoints**: +```bash +# Start the server +npm start + +# Test analytics endpoint (requires authentication) +curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + http://localhost:4000/api/analytics/overview +``` + +### Frontend Setup + +1. **Dependencies are already installed** (Recharts is in package.json) + +2. **Run the development server**: +```bash +cd frontend +npm run dev +``` + +3. **Access the dashboard**: + - Login as Admin: `admin@guc.edu.eg` + - Login as Events Office: Create via admin panel + - Login as Professor: Use existing professor account + - Navigate to: `/analytics` + +## Usage Guide + +### For Event Organizers + +1. **Monitor Event Performance** + - Check attendance rates for past events + - Identify well-performing events to replicate + - Review critical feedback to improve future events + +2. **Filter by Date Range** + - Select start and end dates to analyze specific periods + - Compare performance across semesters + - Generate reports for stakeholders + +3. **Vendor Management** + - Review vendor engagement metrics + - Identify top-performing vendors for future collaboration + - Track lead generation effectiveness + +### For Professors + +1. **Workshop Analytics** + - Filter by your specific workshops + - Review attendee demographics + - Analyze feedback to improve content + +2. **Engagement Insights** + - Identify optimal event timing + - Understand student preferences + - Plan future workshops based on data + +### For Administrators + +1. **Platform-wide Insights** + - Track overall platform usage + - Identify trends across all events + - Make data-driven policy decisions + +2. **Performance Benchmarking** + - Compare events across different faculties + - Identify best practices + - Resource allocation optimization + +## API Reference + +### Query Parameters (All Endpoints) + +- `eventId` (optional): Filter by specific event ID +- `startDate` (optional): Filter start date (ISO 8601) +- `endDate` (optional): Filter end date (ISO 8601) + +### Response Formats + +#### Overview Endpoint +```json +{ + "overview": { + "totalEvents": 15, + "totalRegistrations": 450, + "totalCheckins": 315, + "attendanceRate": 70.0, + "avgRating": 4.2, + "totalFeedback": 189 + }, + "trends": { + "events": 12.5, + "registrations": 8.3, + "attendance": -2.1, + "rating": 5.0 + } +} +``` + +#### Attendance Stats +```json +{ + "data": [ + { + "_id": "event123", + "title": "AI Workshop", + "type": "WORKSHOP", + "startDateTime": "2024-12-10T10:00:00Z", + "registrationCount": 50, + "attendanceCount": 42, + "attendanceRate": 84.0 + } + ] +} +``` + +## Data Privacy & Security + +- **Authentication Required**: All endpoints protected by JWT +- **Role-Based Access**: Only authorized roles can access analytics +- **Data Anonymization**: User PII not exposed in aggregations +- **Audit Logging**: All analytics queries logged for compliance +- **GDPR Compliant**: Data retention policies respected + +## Performance Optimization + +### Backend Optimizations +- MongoDB indexes on frequently queried fields +- Aggregation pipeline optimization +- Caching strategies for expensive queries +- Pagination support for large datasets + +### Frontend Optimizations +- Parallel API requests with Promise.all +- React memo for expensive components +- Lazy loading for chart libraries +- Responsive image handling + +## Troubleshooting + +### Common Issues + +1. **Empty Charts** + - Run seed script: `node scripts/seed_analytics.js` + - Check MongoDB connection + - Verify JWT token is valid + +2. **Slow Loading** + - Add database indexes (see analyticsEventModel.js) + - Reduce date range filter + - Check network tab for slow requests + +3. **Permission Denied** + - Verify user role (must be ADMIN, EVENTS_OFFICE, or PROFESSOR) + - Check JWT token expiration + - Review backend logs for authorization errors + +## Future Enhancements + +### Planned Features +- [ ] PDF/Excel export functionality +- [ ] Email scheduled reports +- [ ] Real-time dashboard updates (WebSockets) +- [ ] Custom date range presets (Last 7 days, Last month, etc.) +- [ ] Event comparison tool (side-by-side) +- [ ] Predictive analytics (ML-based attendance forecasting) +- [ ] Mobile-responsive optimizations +- [ ] Dark/Light theme toggle +- [ ] Custom KPI widgets +- [ ] Advanced filtering (multi-event, multi-faculty) + +### Potential Integrations +- Google Analytics integration +- Power BI/Tableau connectors +- Slack/Teams notifications for anomalies +- Calendar integration for automated reports + +## Contributing + +When adding new analytics features: + +1. **Backend**: Add new aggregation pipeline to `analyticsController.js` +2. **Route**: Register endpoint in `routes/analytics.js` +3. **Model**: Update `analyticsEventModel.js` if new event types needed +4. **Frontend**: Create chart component in `AnalyticsDashboard.jsx` +5. **Seed Data**: Update `seed_analytics.js` to generate test data +6. **Documentation**: Update this README + +## License + +This analytics module is part of the Agora platform. Internal use only. + +## Support + +For issues or questions: +- Backend: Check `backend/controllers/analyticsController.js` inline comments +- Frontend: Review `frontend/src/pages/AnalyticsDashboard.jsx` component documentation +- Seed Data: See `backend/scripts/seed_analytics.js` for data generation logic + +--- + +**Built with ❤️ for data-driven decision making in university event management** diff --git a/CERTIFICATE_FEATURE.md b/CERTIFICATE_FEATURE.md new file mode 100644 index 00000000..0db44ab7 --- /dev/null +++ b/CERTIFICATE_FEATURE.md @@ -0,0 +1,139 @@ +# Workshop Certificate Feature + +## Overview +Automated certificate generation system for workshop attendance with QR code verification. + +## Features + +### 1. Individual Certificate Download +- **Available for:** Workshop events only +- **When:** After workshop end date +- **Who:** Students/Staff/TAs who registered and attended +- **Access:** "My Registrations → Past" section → "Download Certificate" button + +### 2. Combined CV Export +- **Feature:** Export all workshop certificates in one PDF +- **Access:** "Export All Certificates" button in Past registrations section +- **Format:** + - Cover page with total workshops count + - Table of contents + - Individual certificate page for each workshop + +### 3. Certificate Verification +- **Public URL:** `/verify-certificate/{registrationId}` +- **QR Code:** Embedded on each certificate +- **Verification Shows:** + - Workshop name + - Student name + - Date range + - Campus location + - Issue date + - Issuer information + +## Certificate Design + +### Visual Elements +- **Colors:** Gold (#d4af37, #e6c76a) and Indigo (#5b6bd5) matching app theme +- **Layout:** A4 Landscape +- **Branding:** "German University in Cairo" header +- **Security:** QR code for verification (bottom left) +- **Signature:** Authorized signature line (bottom right) +- **Footer:** "This certificate verifies attendance." (small, bottom center) + +### Certificate Content +- Workshop title (centered, prominent) +- Student name (centered, highlighted) +- Date range (formatted) +- Faculty and campus location +- List of instructors/professors +- Unique certificate number +- QR verification code + +## API Endpoints + +### Backend Routes (`/api/certificates`) + +#### `GET /api/certificates/registration/:registrationId` +Generate and download certificate for a single workshop. +- **Auth:** Required (user must own the registration) +- **Response:** PDF file download + +#### `GET /api/certificates/cv` +Generate combined CV with all workshop certificates. +- **Auth:** Required +- **Response:** PDF file download with all certificates + +#### `GET /api/certificates/verify/:registrationId` +Verify certificate authenticity (public endpoint). +- **Auth:** Not required +- **Response:** JSON with certificate details + +#### `GET /api/certificates/available` +List all available certificates for current user. +- **Auth:** Required +- **Response:** Array of certificates with metadata + +## Implementation Details + +### Backend +- **PDF Generation:** PDFKit library +- **QR Codes:** qrcode npm package +- **Controller:** `backend/controllers/certificatesController.js` +- **Utils:** `backend/utils/certificateGenerator.js` +- **Routes:** `backend/routes/certificates.js` + +### Frontend +- **Verification Page:** `frontend/src/pages/CertificateVerification.jsx` +- **Integration:** Student/Staff/TA dashboards +- **Icons:** lucide-react (Download, FileCheck) + +### Database +- **Model:** Uses existing `Registration` model +- **Tracking:** `certificateSentAt` field (timestamp when first generated) + +## Usage Examples + +### For Students +1. Navigate to dashboard → "My Registrations" tab +2. Scroll to "Past" section +3. Find completed workshops (marked with "Workshop" badge) +4. Click "Download Certificate" from dropdown menu +5. PDF downloads automatically + +### For Verification +1. Scan QR code on certificate +2. Opens: `yourapp.com/verify-certificate/{registrationId}` +3. Public page shows certificate details +4. Validates authenticity against database + +## Configuration + +### Environment Variables +```env +FRONTEND_URL=http://localhost:5173 # Used for QR code verification URLs +``` + +### Certificate Number Format +``` +GUC-{eventId}-{registrationId} +Example: GUC-507F1F77-A1B2C3 +``` + +## Notes + +- Certificates only available for `type: 'WORKSHOP'` events +- Workshop must have ended (`endDate < now`) +- Registration must be active (`status: 'REGISTERED'`) +- Certificate generation is idempotent (tracks first generation time) +- QR codes use error correction level 'M' for reliability +- PDF files use A4 landscape for certificates, portrait for CV cover + +## Future Enhancements + +Potential additions: +- Digital signatures +- Blockchain verification +- Email delivery on workshop completion +- Certificate templates for different workshop types +- Multi-language support +- Certificate expiry/renewal system diff --git a/GAMIFICATION_FEATURE.md b/GAMIFICATION_FEATURE.md new file mode 100644 index 00000000..71bebf06 --- /dev/null +++ b/GAMIFICATION_FEATURE.md @@ -0,0 +1,381 @@ +# Gamification System - Implementation Guide + +## Overview +Complete points, badges, and level-up system where users earn rewards for attending events and can redeem them for perks. + +## Features Implemented + +### 1. **Points System** +Users earn points by: +- **Attending Events:** + - Workshops: 50 points + - Trips: 75 points + - Conferences: 100 points + - Bazaars: 30 points + - Booth Setups: 40 points + - Gym Sessions: 20 points +- **Engagement:** + - Submitting reviews: 10 points + - Adding comments: 5 points +- **Streak Bonuses:** + - 3 events in a row: 20 points + - 5 events in a row: 50 points + - 10 events in a row: 100 points + +### 2. **Level System** (6 Levels) +- **Level 1:** Newcomer (0+ points) +- **Level 2:** Explorer (100+ points) +- **Level 3:** Regular (300+ points) +- **Level 4:** Enthusiast (600+ points) +- **Level 5:** Champion (1000+ points) +- **Level 6:** Legend (1500+ points) + +Users automatically level up when reaching point thresholds. Notifications are sent on level-up. + +### 3. **Badge System** (10 Badges) + +#### Attendance Badges: +- **First Steps** 🎯 - Attended first event (COMMON, +25 points) +- **Regular Attendee** ⭐ - Attended 5 events (RARE, +50 points) +- **Social Butterfly** 🦋 - Attended 10 events (EPIC, +100 points) +- **Campus Legend** 👑 - Attended 20 events (LEGENDARY, +200 points) + +#### Engagement Badges: +- **Reviewer** 📝 - Submitted 5 reviews (COMMON, +50 points) +- **Workshop Warrior** 🎓 - Attended 5 workshops (RARE, +75 points) +- **Adventurer** 🗺️ - Attended 3 trips (EPIC, +100 points) + +#### Achievement Badges: +- **Century Club** 💯 - Earned 100 points (RARE, +50 points) +- **High Achiever** 🏆 - Earned 500 points (EPIC, +100 points) +- **Streak Master** 🔥 - 5 event attendance streak (EPIC, +75 points) + +Badges are automatically awarded when requirements are met. Notifications are sent on badge earn. + +### 4. **Perks Marketplace** +- Users can redeem points for loyalty partner perks +- **Point costs:** 50-500 range +- **Redemption limit:** Once per perk per user +- **No expiration dates** +- Unique redemption codes generated for each redemption +- 10 sample loyalty partners created with various categories + +### 5. **Leaderboard** +- Global rankings showing top users +- Displays: rank, name, points, level, badge count +- Shows current user's rank even if not in top 50 +- Medal emojis for top 3 (🥇🥈🥉) + +## Database Structure + +### New Models Created: + +#### **Badge Model** (`badgeModel.js`) +```javascript +{ + name: String, + description: String, + icon: String, + category: String, // ATTENDANCE, ENGAGEMENT, ACHIEVEMENT + requirement: { + type: String, // EVENT_COUNT, POINTS_THRESHOLD, REVIEW_COUNT, STREAK + value: Number, + eventType: String // optional + }, + pointsReward: Number, + rarity: String, // COMMON, RARE, EPIC, LEGENDARY + color: String, + isActive: Boolean +} +``` + +#### **PerkRedemption Model** (`perkRedemptionModel.js`) +```javascript +{ + user: ObjectId, + partner: ObjectId, + pointsCost: Number, + redemptionCode: String, // unique + status: String, // ACTIVE, USED, EXPIRED + usedAt: Date, + metadata: { + userName: String, + userEmail: String, + partnerName: String + } +} +``` + +### Updated Models: + +#### **User Model** - Added gamification field: +```javascript +gamification: { + points: Number, + level: Number, + badges: [{ + badgeId: ObjectId, + earnedAt: Date, + eventId: ObjectId + }], + pointsHistory: [{ + amount: Number, + reason: String, + eventId: ObjectId, + reviewId: ObjectId, + createdAt: Date + }], + redeemedPerks: [{ + partnerId: ObjectId, + redemptionId: ObjectId, + pointsSpent: Number, + redeemedAt: Date + }], + attendanceStreak: Number, + lastAttendanceDate: Date +} +``` + +#### **LoyaltyPartner Model** - Added redemption fields: +```javascript +pointsCost: Number, // 50-500 +maxRedemptionsPerUser: Number, // default 1 +totalRedemptions: Number // tracking +``` + +## Backend Implementation + +### Controllers: + +#### **gamificationController.js** +- `getUserStats()` - Get user's points, level, badges, streak +- `getPointsHistory()` - Detailed points transaction history +- `getLeaderboard()` - Global rankings with pagination +- `getAllBadges()` - All available badges with earned status +- `getUserBadges()` - User's earned badges +- `getLevelInfo()` - Level thresholds and requirements + +#### **perkRedemptionController.js** +- `getAvailablePerks()` - Perks with affordability info +- `redeemPerk()` - Spend points to redeem a perk +- `getUserRedemptions()` - User's redemption history +- `validateRedemptionCode()` - Verify redemption codes +- `markRedemptionUsed()` - Mark as used by vendor + +### Utilities: + +#### **gamificationHelpers.js** +Core logic for: +- Point calculation and awarding +- Level calculation and progression +- Badge requirement checking +- Automatic badge awarding +- Streak tracking +- Event attendance point awarding + +### Routes: + +#### `/api/gamification` +- `GET /stats` - User statistics +- `GET /history` - Points history +- `GET /leaderboard` - Global rankings +- `GET /badges` - All badges +- `GET /badges/user` - User's badges +- `GET /levels` - Level information + +#### `/api/loyalty-partners/perks` +- `GET /available` - Available perks +- `POST /redeem/:partnerId` - Redeem perk +- `GET /my-redemptions` - User's redemptions +- `POST /validate-code` - Validate code +- `PATCH /redemptions/:id/use` - Mark as used + +## Frontend Implementation + +### Pages Created: + +#### **GamificationDashboard.jsx** (`/progress`) +- Overview of user's gamification stats +- Points, level, badges, streak display +- Level progress bar with percentage +- Recent badges showcase +- Points history timeline +- Quick stats summary + +#### **Leaderboard.jsx** (`/leaderboard`) +- Top 3 podium display +- Full rankings list (top 50) +- Current user's rank highlighted +- Medal system for top 3 +- Level and badge count display + +#### **BadgesCollection.jsx** (`/badges`) +- All badges grid view +- Filter: All / Earned / Locked +- Progress bar for collection completion +- Rarity-based styling +- Requirement descriptions +- Category breakdown + +#### **PerksMarketplace.jsx** (`/perks`) +- Two tabs: Available / Redeemed +- Category-based color coding +- Affordability indicators +- Redemption code display +- Success messages with codes +- Locked perks with requirements + +### Components: + +#### **GamificationWidget.jsx** +- Compact navbar widget +- Shows: points, level, badge count +- Dropdown with detailed stats +- Quick links to all gamification pages +- Level progress indicator + +### Routes Added: +All gamification routes accessible to: STUDENT, STAFF, TA, PROFESSOR +- `/progress` - Dashboard +- `/leaderboard` - Rankings +- `/badges` - Badge collection +- `/perks` - Perks marketplace + +## Scripts + +### Seeding Dummy Data: + +#### **Run: `node backend/scripts/seed_gamification.js`** + +This script creates: +1. **10 badges** (all requirements and rarities) +2. **10 loyalty partners** (various categories, point costs 50-250) +3. **Updates up to 50 users** with random gamification data: + - Points: 0-2000 (distributed across all levels) + - Levels: 1-6 based on points + - Random badges based on points + - Random attendance streaks + - Points history entries + +Distribution: +- 40% users: 0-200 points (Levels 1-2) +- 30% users: 200-600 points (Levels 2-4) +- 20% users: 600-1200 points (Levels 4-5) +- 10% users: 1200-2000 points (Levels 5-6) + +### Resetting Data: + +#### **Run: `node backend/scripts/reset_gamification.js`** + +This script: +1. Deletes all badges +2. Deletes all perk redemptions +3. Resets all users' gamification data to zero + +## Integration with Existing Features + +### Automatic Points Awarding: + +To award points when a user attends an event, add this to your event attendance logic: + +```javascript +const { awardEventAttendancePoints } = require('../utils/gamificationHelpers'); + +// After confirming attendance: +await awardEventAttendancePoints(userId, eventId, event.type); +``` + +### Awarding Review Points: + +Add to your review submission logic: + +```javascript +const { awardPoints } = require('../utils/gamificationHelpers'); + +// After review is saved: +await awardPoints(userId, 10, 'Submitted event review', { reviewId }); +``` + +### Notifications: + +The system automatically sends notifications for: +- Level ups +- Badge earning +- Perk redemption + +Uses existing notification system via `notificationHelpers.js` + +## Testing the System + +### 1. Seed the database: +```bash +cd backend +node scripts/seed_gamification.js +``` + +### 2. Check the data: +- View badges at `/badges` +- Check leaderboard at `/leaderboard` +- Browse perks at `/perks` +- See your progress at `/progress` + +### 3. Test redemption: +- Users with enough points can redeem perks +- Redemption codes are displayed +- Points are deducted +- Redemption appears in history + +### 4. Test badge earning: +- Badges are automatically awarded based on activity +- Notifications are sent when earned +- Progress tracked in badge collection + +## Future Enhancements (Not Implemented) + +Potential additions you can build: +- Special level unlocks/perks +- Hidden/secret badges +- Leaderboard filters (by faculty, role) +- Periodic leaderboard resets +- Perk expiration dates +- Multiple redemptions per perk +- Social features (share achievements) +- Badge trading/gifting +- Seasonal events/challenges +- Team competitions +- Achievement animations + +## Files Created/Modified + +### Backend (11 files): +- ✅ `models/badgeModel.js` (new) +- ✅ `models/perkRedemptionModel.js` (new) +- ✅ `models/userModel.js` (modified) +- ✅ `models/loyaltyPartnerModel.js` (modified) +- ✅ `controllers/gamificationController.js` (new) +- ✅ `controllers/perkRedemptionController.js` (new) +- ✅ `routes/gamification.js` (new) +- ✅ `routes/loyaltyPartners.js` (modified) +- ✅ `utils/gamificationHelpers.js` (new) +- ✅ `scripts/seed_gamification.js` (new) +- ✅ `scripts/reset_gamification.js` (new) +- ✅ `server.js` (modified) + +### Frontend (6 files): +- ✅ `pages/GamificationDashboard.jsx` (new) +- ✅ `pages/Leaderboard.jsx` (new) +- ✅ `pages/BadgesCollection.jsx` (new) +- ✅ `pages/PerksMarketplace.jsx` (new) +- ✅ `components/GamificationWidget.jsx` (new) +- ✅ `App.jsx` (modified) + +## Usage Tips + +1. **Navbar Integration**: Add `` to your main navbar component to display points/level +2. **Dashboard Links**: Add quick links to gamification pages from user dashboards +3. **Event Pages**: Show potential points earned on event detail pages +4. **Profile Pages**: Display gamification stats in user profiles + +## Support + +The system is fully functional and ready to use. Run the seed script to populate test data and start exploring! diff --git a/PAYMENT_AND_CERTIFICATES.md b/PAYMENT_AND_CERTIFICATES.md new file mode 100644 index 00000000..0d6206cd --- /dev/null +++ b/PAYMENT_AND_CERTIFICATES.md @@ -0,0 +1,244 @@ +# Payment Receipts and Attendance Certificates + +This document describes the automated email features for payment receipts and attendance certificates. + +## Payment Receipts + +### Overview +When students, staff, TAs, or professors register for a **TRIP** event that has a price, they automatically receive a payment receipt via email. + +### Implementation Details + +#### Backend Changes + +1. **Registration Model** (`backend/models/registrationModel.js`) + - Added `paymentAmount: Number` - stores the amount paid + - Added `paidAt: Date` - stores the payment timestamp + +2. **Email Utility** (`backend/utils/mailer.js`) + - Added `sendEventPaymentReceiptEmail(userEmail, userName, eventDetails)` function + - Professional HTML email template with: + - Gradient header with "Payment Receipt" title + - Event details (title, type, amount, dates) + - Formatted payment amount in green + - Confirmation badge + +3. **Registration Controller** (`backend/controllers/registrationsController.js`) + - Modified `registerToEvent` function to: + - Check if event is a TRIP with a price > 0 + - Store payment amount and timestamp in registration + - Send payment receipt email automatically + - Continue registration even if email fails (logged as error) + +### Email Template +The payment receipt email includes: +- Event title and type +- Amount paid (displayed prominently in green) +- Registration date +- Event start date +- Confirmation badge +- Professional gradient design matching the application theme + +### Usage +No manual action required. When a user registers for a paid trip: +1. Registration is created +2. Payment fields are populated +3. Email is sent automatically +4. User receives professional receipt in their inbox + +--- + +## Attendance Certificates + +### Overview +After a workshop ends, Events Office or Admin can send attendance certificates to all registered participants. + +### Implementation Details + +#### Backend Changes + +1. **Email Utility** (`backend/utils/mailer.js`) + - Added `sendAttendanceCertificateEmail(userEmail, userName, workshopDetails)` function + - Formal certificate-style HTML email template with: + - Large "Certificate of Attendance" header + - Participant name prominently displayed + - Workshop title and details + - Start/end dates and duration + - Instructor names + - "Attendance Verified" badge + - GUC branding + +2. **Events Controller** (`backend/controllers/eventsController.js`) + - Added `sendWorkshopCertificates` function to: + - Validate event is a workshop that has ended + - Fetch all registered participants + - Calculate workshop duration + - Send certificate email to each participant + - Return summary of successful/failed sends + +3. **Routes** (`backend/routes/events.js`) + - Added `POST /events/:id/send-certificates` endpoint + - Restricted to Events Office and Admin roles only + +### Certificate Template +The attendance certificate email includes: +- "German University in Cairo" branding +- Certificate of Attendance header with gradient +- Participant name (large, centered) +- Workshop title (highlighted) +- Start and end dates +- Duration (calculated in days) +- Instructor name(s) +- "Attendance Verified" badge +- Issuance date in footer + +### Usage + +#### Manual Trigger (Current Implementation) +Events Office or Admin can send certificates after a workshop ends: + +```bash +POST /events/:workshopId/send-certificates +Headers: + Authorization: Bearer + +Response: +{ + "message": "Certificates sent: 15 successful, 0 failed", + "results": [ + { "email": "student@guc.edu.eg", "status": "sent" }, + ... + ] +} +``` + +#### Validation +- Only WORKSHOP events can have certificates +- Workshop must have ended (endAt < current time) +- Only Events Office or Admin can trigger +- At least one registered participant must exist + +#### Future Enhancement Options +You could add automated certificate sending by: +1. Creating a cron job that runs daily +2. Finding workshops that ended in the last 24 hours +3. Automatically sending certificates to participants +4. Logging results for admin review + +Example cron implementation (not included): +```javascript +// In a separate cron job file +const cron = require('node-cron'); + +// Run daily at 9 AM +cron.schedule('0 9 * * *', async () => { + const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000); + const workshops = await Event.find({ + type: 'WORKSHOP', + endAt: { $gte: yesterday, $lt: new Date() } + }); + + for (const workshop of workshops) { + // Call sendWorkshopCertificates logic here + } +}); +``` + +--- + +## Testing + +### Testing Payment Receipts + +1. Create a TRIP event with a price: + ```json + { + "type": "TRIP", + "tripDetails": { + "price": 250, + "destination": "Alexandria" + }, + ... + } + ``` + +2. Register for the trip as a student/staff/TA/professor +3. Check email inbox for payment receipt +4. Verify registration in database has `paymentAmount` and `paidAt` fields + +### Testing Attendance Certificates + +1. Create a WORKSHOP event with past end date (for testing): + ```json + { + "type": "WORKSHOP", + "startAt": "2024-01-10T10:00:00Z", + "endAt": "2024-01-10T14:00:00Z", + ... + } + ``` + +2. Register participants for the workshop +3. Wait for workshop to end (or manually set endAt to past) +4. As Events Office/Admin, send certificates: + ``` + POST /events/:workshopId/send-certificates + ``` +5. Check participant email inboxes for certificates + +--- + +## Email Configuration + +Ensure your `.env` file has the correct SMTP settings: + +```env +SMTP_HOST=smtp.gmail.com +SMTP_PORT=587 +SMTP_SECURE=false +SMTP_USER=your-email@gmail.com +SMTP_PASS=your-app-password +MAIL_FROM="Agora Events " +``` + +For Gmail, use an [App Password](https://support.google.com/accounts/answer/185833) instead of your regular password. + +--- + +## Error Handling + +### Payment Receipts +- If email sending fails, registration still completes successfully +- Error is logged to console but doesn't block the user +- User can contact support for manual receipt + +### Certificates +- Each participant's email is sent individually +- If one fails, others continue +- Response includes detailed status for each email +- Failed emails are logged with error messages + +--- + +## Security Considerations + +1. **Payment Receipts**: Automatically sent on registration - no additional permissions needed +2. **Certificates**: Only Events Office and Admin can trigger certificate sending +3. **Email Privacy**: Emails are sent individually (no CC/BCC lists exposed) +4. **Data Validation**: All inputs are validated before processing +5. **Error Handling**: Email failures don't expose sensitive information + +--- + +## Future Enhancements + +1. **Payment Gateway Integration**: Replace automatic payment with actual payment processing +2. **Payment Confirmation**: Add payment status (PENDING, PAID, REFUNDED) +3. **Refund Receipts**: Send refund confirmation emails when canceling paid trips +4. **Certificate Customization**: Allow admins to customize certificate templates +5. **Automated Certificates**: Cron job to send certificates automatically after workshops end +6. **Certificate Downloads**: Add PDF generation and attachment to emails +7. **Attendance Tracking**: Track actual attendance vs registration for more accurate certificates +8. **Multiple Professors**: Support multiple instructors for workshops +9. **Certificate Numbering**: Add unique certificate IDs for verification +10. **QR Code Verification**: Add QR codes to certificates for authenticity verification diff --git a/UNIFIED_EVENT_CALENDAR_FEATURE.md b/UNIFIED_EVENT_CALENDAR_FEATURE.md new file mode 100644 index 00000000..54bbc915 --- /dev/null +++ b/UNIFIED_EVENT_CALENDAR_FEATURE.md @@ -0,0 +1,285 @@ +# Unified Event Calendar Feature - Implementation Guide + +## Overview +This document describes the implementation of the **Unified Event Calendar** feature for the Agora university event platform. This feature provides a centralized calendar view accessible to all user roles (Students, Staff, TAs, Professors, Events Office, Admins, and Vendors). + +## Features Implemented + +### 1. Backend Components + +#### Calendar Controller (`backend/controllers/calendarController.js`) +- **Endpoint**: `GET /api/calendar/events` +- **Functionality**: + - Fetches published events with dynamic filtering + - Supports filters: faculty, event type, mode (online/offline/hybrid), date range + - Returns events with color-coded type identifiers + - Automatically excludes events older than 3 months (unless overridden) + +#### Calendar Routes (`backend/routes/calendar.js`) +- Protected route requiring authentication +- Accessible to all logged-in users regardless of role + +#### Server Integration +- Added calendar routes to `server.js` +- Route prefix: `/api/calendar` + +### 2. Frontend Components + +#### Main Calendar Page (`frontend/src/pages/UnifiedEventCalendarPage.jsx`) +- Full-page calendar view using `react-big-calendar` +- Features: + - **Month and Week views** with toggle capability + - **Color-coded events** by type: + - Workshop: Blue (#3b82f6) + - Trip: Purple (#8b5cf6) + - Bazaar: Orange (#f97316) + - Conference: Green (#10b981) + - Booth Setup: Red (#ef4444) + - Gym Session: Pink (#ec4899) + - **Interactive events** - click to view details + - **Loading states** with spinner + - **Error handling** with retry capability + - **Custom styling** matching the dark theme aesthetic + +#### Calendar Filters (`frontend/src/components/CalendarFilters.jsx`) +- Collapsible filter panel +- Filter options: + - **Faculty**: All faculties or specific (MET, IET, DMET, etc.) + - **Event Type**: All types or specific (Workshop, Trip, Bazaar, etc.) + - **Mode**: All, Online, Offline, or Hybrid + - **Date Range**: Quick presets (This Month, Next 30 Days, Next 90 Days) +- Active filter indicator +- Clear all filters button + +#### Calendar Legend (`frontend/src/components/CalendarLegend.jsx`) +- Visual reference for event type colors +- Displays all event types with corresponding colors + +#### Event Details Modal (`frontend/src/components/CalendarEventModal.jsx`) +- Opens when clicking calendar events +- Displays: + - Event name with color-coded type badge + - Faculty (if applicable) + - Start and end date/time + - Location + - Mode (Online/Offline/Hybrid) +- Actions: + - **View Event Page** - navigates to full event details + - **Add to Google Calendar** - opens Google Calendar with pre-filled event + - **Download ICS** - downloads .ics file for Outlook/iCal import +- Keyboard accessible (ESC to close) +- Click overlay to close + +### 3. Navigation Integration + +#### Sidebar Updates (`frontend/src/components/Sidebar.jsx`) +- Added "Event Calendar" link to all role menus: + - Students + - Staff + - TAs + - Professors + - Events Office + - Admins + - Vendors +- Uses calendar icon (FaCalendarAlt) +- Route: `/calendar` + +#### Routing (`frontend/src/App.jsx`) +- Added calendar route for all protected role sections +- Route: `/calendar` +- Component: `UnifiedEventCalendarPage` +- Protected: Yes (requires authentication) +- Accessible by: All roles + +## Dependencies Added + +### Frontend +```json +{ + "react-big-calendar": "^1.x.x", + "date-fns": "^2.x.x" +} +``` + +Installation: +```bash +cd frontend +npm install react-big-calendar date-fns +``` + +### Backend +No new dependencies required - uses existing Mongoose and Express setup. + +## API Documentation + +### GET /api/calendar/events + +**Authentication**: Required (JWT token) + +**Query Parameters**: +- `startDate` (optional, ISO string): Filter events starting on or after this date +- `endDate` (optional, ISO string): Filter events starting on or before this date +- `faculty` (optional, string): Filter by faculty (or "ALL") +- `type` (optional, string): Filter by event type (or "ALL") +- `mode` (optional, string): Filter by mode - "online", "offline", "hybrid", or "ALL" + +**Response**: +```json +{ + "success": true, + "events": [ + { + "_id": "event123", + "name": "AI Workshop", + "type": "WORKSHOP", + "faculty": "MET", + "mode": "OFFLINE", + "startDate": "2025-12-15T10:00:00.000Z", + "endDate": "2025-12-15T12:00:00.000Z", + "location": "GUC_CAIRO", + "colorKey": "blue", + "createdBy": "user456" + } + ] +} +``` + +**Error Response**: +```json +{ + "success": false, + "message": "Failed to fetch calendar events", + "error": "Error details" +} +``` + +## Usage Instructions + +### For End Users + +1. **Access Calendar**: + - Log in to your dashboard + - Click "Event Calendar" in the sidebar menu + +2. **View Events**: + - Calendar loads with current month view + - Events are color-coded by type (see legend) + - Switch between Month/Week views using toolbar buttons + +3. **Filter Events**: + - Click "Filters" button + - Select desired faculty, event type, mode, or date range + - Clear filters with "Clear All" button + +4. **View Event Details**: + - Click any event on the calendar + - Modal opens with full details + - Click "View Event Page" for complete information + - Add to your personal calendar using Google/iCal buttons + +5. **Navigate Calendar**: + - Use "Today", "Back", "Next" buttons in toolbar + - Click month/week header to change view period + +### For Developers + +#### Extending Filters + +To add new filter options, modify: +1. `CalendarFilters.jsx` - Add UI controls +2. `calendarController.js` - Add query logic + +#### Adding New Event Types + +1. Update `EVENT_TYPES` in Event model +2. Add color mapping in `calendarController.js` (getEventColorKey function) +3. Update `LEGEND_ITEMS` in `CalendarLegend.jsx` +4. Update `EVENT_COLORS` in `CalendarEventModal.jsx` and `UnifiedEventCalendarPage.jsx` + +#### Customizing Calendar Appearance + +Modify the ` + + + +
+
+

All files bitmapper.js

+
+ +
+ 94.37% + Statements + 134/142 +
+ + +
+ 72.41% + Branches + 21/29 +
+ + +
+ 89.47% + Functions + 17/19 +
+ + +
+ 94.16% + Lines + 129/137 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268  +  +1x +  +1x +  +  +  +  +  +  +313632x +  +  +  +313632x +313632x +313632x +313632x +313632x +  +  +  +  +  +8192x +  +  +  +8192x +8192x +8192x +8192x +8192x +  +  +  +  +  +1228160x +  +  +  +1228160x +1228160x +1228160x +1228160x +  +  +  +  +  +272640x +  +  +  +272640x +272640x +272640x +272640x +  +  +  +1x +  +  +  +  +  +  +1193380x +1193380x +1193380x +1193380x +1193380x +  +  +  +  +  +8192x +8192x +8192x +8192x +8192x +  +  +  +  +  +24576x +24576x +24576x +24576x +  +  +  +  +  +8192x +8192x +8192x +8192x +  +  +  +  +209x +209x +  +  +334250x +  +  +334250x +334250x +  +334250x +  +  +  +149504x +149504x +149504x +149504x +  +49612x +49612x +49612x +49612x +  +2968x +2968x +2968x +2968x +2968x +2968x +  +132166x +132166x +132166x +132166x +132166x +132166x +132166x +132166x +132166x +132166x +  +  +  +209x +  +1234340x +334250x +  +1234340x +1234340x +1234340x +  +  +8106x +  +  +209x +  +  +  +  +  +  +  +  +210x +210x +210x +210x +7288x +1822624x +1822624x +1822624x +  +  +210x +  +  +  +  +529x +529x +529x +529x +8106x +1234340x +1234340x +1234340x +  +8106x +  +  +  +1x +335x +335x +335x +335x +335x +  +  +335x +209x +  +  +335x +269x +  +66x +  +335x +335x +  +  +  +335x +72x +72x +  +263x +263x +2732114x +2732114x +2732114x +  +263x +  +  +335x +739x +210x +  +  +  +  +  +  +  +  +529x +  +  +  +  +  +  +  +  +  +335x +126x +  +  +  +209x +  +  +335x +  + 
"use strict";
+ 
+let interlaceUtils = require("./interlace");
+ 
+let pixelBppMapper = [
+  // 0 - dummy entry
+  function () {},
+ 
+  // 1 - L
+  // 0: 0, 1: 0, 2: 0, 3: 0xff
+  function (pxData, data, pxPos, rawPos) {
+    Iif (rawPos === data.length) {
+      throw new Error("Ran out of data");
+    }
+ 
+    let pixel = data[rawPos];
+    pxData[pxPos] = pixel;
+    pxData[pxPos + 1] = pixel;
+    pxData[pxPos + 2] = pixel;
+    pxData[pxPos + 3] = 0xff;
+  },
+ 
+  // 2 - LA
+  // 0: 0, 1: 0, 2: 0, 3: 1
+  function (pxData, data, pxPos, rawPos) {
+    Iif (rawPos + 1 >= data.length) {
+      throw new Error("Ran out of data");
+    }
+ 
+    let pixel = data[rawPos];
+    pxData[pxPos] = pixel;
+    pxData[pxPos + 1] = pixel;
+    pxData[pxPos + 2] = pixel;
+    pxData[pxPos + 3] = data[rawPos + 1];
+  },
+ 
+  // 3 - RGB
+  // 0: 0, 1: 1, 2: 2, 3: 0xff
+  function (pxData, data, pxPos, rawPos) {
+    Iif (rawPos + 2 >= data.length) {
+      throw new Error("Ran out of data");
+    }
+ 
+    pxData[pxPos] = data[rawPos];
+    pxData[pxPos + 1] = data[rawPos + 1];
+    pxData[pxPos + 2] = data[rawPos + 2];
+    pxData[pxPos + 3] = 0xff;
+  },
+ 
+  // 4 - RGBA
+  // 0: 0, 1: 1, 2: 2, 3: 3
+  function (pxData, data, pxPos, rawPos) {
+    Iif (rawPos + 3 >= data.length) {
+      throw new Error("Ran out of data");
+    }
+ 
+    pxData[pxPos] = data[rawPos];
+    pxData[pxPos + 1] = data[rawPos + 1];
+    pxData[pxPos + 2] = data[rawPos + 2];
+    pxData[pxPos + 3] = data[rawPos + 3];
+  },
+];
+ 
+let pixelBppCustomMapper = [
+  // 0 - dummy entry
+  function () {},
+ 
+  // 1 - L
+  // 0: 0, 1: 0, 2: 0, 3: 0xff
+  function (pxData, pixelData, pxPos, maxBit) {
+    let pixel = pixelData[0];
+    pxData[pxPos] = pixel;
+    pxData[pxPos + 1] = pixel;
+    pxData[pxPos + 2] = pixel;
+    pxData[pxPos + 3] = maxBit;
+  },
+ 
+  // 2 - LA
+  // 0: 0, 1: 0, 2: 0, 3: 1
+  function (pxData, pixelData, pxPos) {
+    let pixel = pixelData[0];
+    pxData[pxPos] = pixel;
+    pxData[pxPos + 1] = pixel;
+    pxData[pxPos + 2] = pixel;
+    pxData[pxPos + 3] = pixelData[1];
+  },
+ 
+  // 3 - RGB
+  // 0: 0, 1: 1, 2: 2, 3: 0xff
+  function (pxData, pixelData, pxPos, maxBit) {
+    pxData[pxPos] = pixelData[0];
+    pxData[pxPos + 1] = pixelData[1];
+    pxData[pxPos + 2] = pixelData[2];
+    pxData[pxPos + 3] = maxBit;
+  },
+ 
+  // 4 - RGBA
+  // 0: 0, 1: 1, 2: 2, 3: 3
+  function (pxData, pixelData, pxPos) {
+    pxData[pxPos] = pixelData[0];
+    pxData[pxPos + 1] = pixelData[1];
+    pxData[pxPos + 2] = pixelData[2];
+    pxData[pxPos + 3] = pixelData[3];
+  },
+];
+ 
+function bitRetriever(data, depth) {
+  let leftOver = [];
+  let i = 0;
+ 
+  function split() {
+    Iif (i === data.length) {
+      throw new Error("Ran out of data");
+    }
+    let byte = data[i];
+    i++;
+    let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
+    switch (depth) {
+      default:
+        throw new Error("unrecognised depth");
+      case 16:
+        byte2 = data[i];
+        i++;
+        leftOver.push((byte << 8) + byte2);
+        break;
+      case 4:
+        byte2 = byte & 0x0f;
+        byte1 = byte >> 4;
+        leftOver.push(byte1, byte2);
+        break;
+      case 2:
+        byte4 = byte & 3;
+        byte3 = (byte >> 2) & 3;
+        byte2 = (byte >> 4) & 3;
+        byte1 = (byte >> 6) & 3;
+        leftOver.push(byte1, byte2, byte3, byte4);
+        break;
+      case 1:
+        byte8 = byte & 1;
+        byte7 = (byte >> 1) & 1;
+        byte6 = (byte >> 2) & 1;
+        byte5 = (byte >> 3) & 1;
+        byte4 = (byte >> 4) & 1;
+        byte3 = (byte >> 5) & 1;
+        byte2 = (byte >> 6) & 1;
+        byte1 = (byte >> 7) & 1;
+        leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
+        break;
+    }
+  }
+ 
+  return {
+    get: function (count) {
+      while (leftOver.length < count) {
+        split();
+      }
+      let returner = leftOver.slice(0, count);
+      leftOver = leftOver.slice(count);
+      return returner;
+    },
+    resetAfterLine: function () {
+      leftOver.length = 0;
+    },
+    end: function () {
+      Iif (i !== data.length) {
+        throw new Error("extra data found");
+      }
+    },
+  };
+}
+ 
+function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) {
+  // eslint-disable-line max-params
+  let imageWidth = image.width;
+  let imageHeight = image.height;
+  let imagePass = image.index;
+  for (let y = 0; y < imageHeight; y++) {
+    for (let x = 0; x < imageWidth; x++) {
+      let pxPos = getPxPos(x, y, imagePass);
+      pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
+      rawPos += bpp; //eslint-disable-line no-param-reassign
+    }
+  }
+  return rawPos;
+}
+ 
+function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) {
+  // eslint-disable-line max-params
+  let imageWidth = image.width;
+  let imageHeight = image.height;
+  let imagePass = image.index;
+  for (let y = 0; y < imageHeight; y++) {
+    for (let x = 0; x < imageWidth; x++) {
+      let pixelData = bits.get(bpp);
+      let pxPos = getPxPos(x, y, imagePass);
+      pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
+    }
+    bits.resetAfterLine();
+  }
+}
+ 
+exports.dataToBitMap = function (data, bitmapInfo) {
+  let width = bitmapInfo.width;
+  let height = bitmapInfo.height;
+  let depth = bitmapInfo.depth;
+  let bpp = bitmapInfo.bpp;
+  let interlace = bitmapInfo.interlace;
+  let bits;
+ 
+  if (depth !== 8) {
+    bits = bitRetriever(data, depth);
+  }
+  let pxData;
+  if (depth <= 8) {
+    pxData = Buffer.alloc(width * height * 4);
+  } else {
+    pxData = new Uint16Array(width * height * 4);
+  }
+  let maxBit = Math.pow(2, depth) - 1;
+  let rawPos = 0;
+  let images;
+  let getPxPos;
+ 
+  if (interlace) {
+    images = interlaceUtils.getImagePasses(width, height);
+    getPxPos = interlaceUtils.getInterlaceIterator(width, height);
+  } else {
+    let nonInterlacedPxPos = 0;
+    getPxPos = function () {
+      let returner = nonInterlacedPxPos;
+      nonInterlacedPxPos += 4;
+      return returner;
+    };
+    images = [{ width: width, height: height }];
+  }
+ 
+  for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
+    if (depth === 8) {
+      rawPos = mapImage8Bit(
+        images[imageIndex],
+        pxData,
+        getPxPos,
+        bpp,
+        data,
+        rawPos
+      );
+    } else {
+      mapImageCustomBit(
+        images[imageIndex],
+        pxData,
+        getPxPos,
+        bpp,
+        bits,
+        maxBit
+      );
+    }
+  }
+  if (depth === 8) {
+    Iif (rawPos !== data.length) {
+      throw new Error("extra data found");
+    }
+  } else {
+    bits.end();
+  }
+ 
+  return pxData;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html b/backend/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html new file mode 100644 index 00000000..50cca239 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html @@ -0,0 +1,554 @@ + + + + + + Code coverage report for bitpacker.js + + + + + + + + + +
+
+

All files bitpacker.js

+
+ +
+ 11.36% + Statements + 10/88 +
+ + +
+ 6.12% + Branches + 3/49 +
+ + +
+ 66.67% + Functions + 2/3 +
+ + +
+ 11.63% + Lines + 10/86 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159  +  +1x +  +1x +  +325x +  +  +325x +325x +325x +325x +  +325x +  +  +325x +325x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+ 
+let constants = require("./constants");
+ 
+module.exports = function (dataIn, width, height, options) {
+  let outHasAlpha =
+    [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(
+      options.colorType
+    ) !== -1;
+  Eif (options.colorType === options.inputColorType) {
+    let bigEndian = (function () {
+      let buffer = new ArrayBuffer(2);
+      new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
+      // Int16Array uses the platform's endianness.
+      return new Int16Array(buffer)[0] !== 256;
+    })();
+    // If no need to convert to grayscale and alpha is present/absent in both, take a fast route
+    Eif (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
+      return dataIn;
+    }
+  }
+ 
+  // map to a UInt16 array if data is 16bit, fix endianness below
+  let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
+ 
+  let maxValue = 255;
+  let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
+  if (inBpp === 4 && !options.inputHasAlpha) {
+    inBpp = 3;
+  }
+  let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
+  if (options.bitDepth === 16) {
+    maxValue = 65535;
+    outBpp *= 2;
+  }
+  let outData = Buffer.alloc(width * height * outBpp);
+ 
+  let inIndex = 0;
+  let outIndex = 0;
+ 
+  let bgColor = options.bgColor || {};
+  if (bgColor.red === undefined) {
+    bgColor.red = maxValue;
+  }
+  if (bgColor.green === undefined) {
+    bgColor.green = maxValue;
+  }
+  if (bgColor.blue === undefined) {
+    bgColor.blue = maxValue;
+  }
+ 
+  function getRGBA() {
+    let red;
+    let green;
+    let blue;
+    let alpha = maxValue;
+    switch (options.inputColorType) {
+      case constants.COLORTYPE_COLOR_ALPHA:
+        alpha = data[inIndex + 3];
+        red = data[inIndex];
+        green = data[inIndex + 1];
+        blue = data[inIndex + 2];
+        break;
+      case constants.COLORTYPE_COLOR:
+        red = data[inIndex];
+        green = data[inIndex + 1];
+        blue = data[inIndex + 2];
+        break;
+      case constants.COLORTYPE_ALPHA:
+        alpha = data[inIndex + 1];
+        red = data[inIndex];
+        green = red;
+        blue = red;
+        break;
+      case constants.COLORTYPE_GRAYSCALE:
+        red = data[inIndex];
+        green = red;
+        blue = red;
+        break;
+      default:
+        throw new Error(
+          "input color type:" +
+            options.inputColorType +
+            " is not supported at present"
+        );
+    }
+ 
+    if (options.inputHasAlpha) {
+      if (!outHasAlpha) {
+        alpha /= maxValue;
+        red = Math.min(
+          Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0),
+          maxValue
+        );
+        green = Math.min(
+          Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0),
+          maxValue
+        );
+        blue = Math.min(
+          Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0),
+          maxValue
+        );
+      }
+    }
+    return { red: red, green: green, blue: blue, alpha: alpha };
+  }
+ 
+  for (let y = 0; y < height; y++) {
+    for (let x = 0; x < width; x++) {
+      let rgba = getRGBA(data, inIndex);
+ 
+      switch (options.colorType) {
+        case constants.COLORTYPE_COLOR_ALPHA:
+        case constants.COLORTYPE_COLOR:
+          if (options.bitDepth === 8) {
+            outData[outIndex] = rgba.red;
+            outData[outIndex + 1] = rgba.green;
+            outData[outIndex + 2] = rgba.blue;
+            if (outHasAlpha) {
+              outData[outIndex + 3] = rgba.alpha;
+            }
+          } else {
+            outData.writeUInt16BE(rgba.red, outIndex);
+            outData.writeUInt16BE(rgba.green, outIndex + 2);
+            outData.writeUInt16BE(rgba.blue, outIndex + 4);
+            if (outHasAlpha) {
+              outData.writeUInt16BE(rgba.alpha, outIndex + 6);
+            }
+          }
+          break;
+        case constants.COLORTYPE_ALPHA:
+        case constants.COLORTYPE_GRAYSCALE: {
+          // Convert to grayscale and alpha
+          let grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
+          if (options.bitDepth === 8) {
+            outData[outIndex] = grayscale;
+            if (outHasAlpha) {
+              outData[outIndex + 1] = rgba.alpha;
+            }
+          } else {
+            outData.writeUInt16BE(grayscale, outIndex);
+            if (outHasAlpha) {
+              outData.writeUInt16BE(rgba.alpha, outIndex + 2);
+            }
+          }
+          break;
+        }
+        default:
+          throw new Error("unrecognised color Type " + options.colorType);
+      }
+ 
+      inIndex += inBpp;
+      outIndex += outBpp;
+    }
+  }
+ 
+  return outData;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/block-navigation.js b/backend/node_modules/pngjs/coverage/lcov-report/block-navigation.js new file mode 100644 index 00000000..81d08c06 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/block-navigation.js @@ -0,0 +1,77 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = [".cbranch-no", ".cstat-no", ".fstat-no"]; + + // Elements to highlight in the file listing view + var fileListingElements = ["td.pct.low"]; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ":not(" + missingCoverageClasses.join("):not(") + ") > "; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(", ") + + ", " + + notSelector + + missingCoverageClasses.join(", " + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements.item(currentIndex).classList.remove("highlighted"); + missingCoverageElements.item(index).classList.add("highlighted"); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: "smooth", + block: "center", + inline: "center", + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== "number" || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === "number" && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener("keydown", jumpToCode); diff --git a/backend/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html b/backend/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html new file mode 100644 index 00000000..552ffbaf --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html @@ -0,0 +1,647 @@ + + + + + + Code coverage report for chunkstream.js + + + + + + + + + +
+
+

All files chunkstream.js

+
+ +
+ 90.11% + Statements + 82/91 +
+ + +
+ 81.4% + Branches + 35/43 +
+ + +
+ 100% + Functions + 10/10 +
+ + +
+ 90.11% + Lines + 82/91 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190  +  +1x +1x +  +1x +529x +  +529x +529x +  +529x +529x +  +529x +529x +  +1x +  +1x +13318x +  +  +  +  +  +13318x +  +13318x +  +  +13318x +  +  +  +  +  +  +  +  +1x +943x +  +  +  +  +  +943x +943x +  +  +  +  +943x +943x +  +943x +  +  +943x +346x +  +  +943x +  +  +1x +311x +  +  +  +311x +  +  +311x +  +  +  +  +311x +309x +  +2x +2x +  +  +  +1x +  +1x +311x +3x +  +  +311x +  +  +1x +327x +  +  +  +327x +327x +327x +  +327x +  +  +1x +  +741x +  +  +741x +  +  +741x +568x +568x +  +568x +  +  +173x +173x +  +173x +  +  +  +1x +12408x +  +12408x +12408x +12408x +  +  +12408x +12617x +12617x +  +12617x +12617x +  +  +12617x +11863x +  +  +  +  +12408x +532x +  +  +12408x +  +12408x +  +  +1x +14263x +  +14263x +15656x +  +  +15656x +741x +14915x +  +  +12408x +  +  +  +2507x +  +  +  +14263x +2x +  +  +  +  +  + 
"use strict";
+ 
+let util = require("util");
+let Stream = require("stream");
+ 
+let ChunkStream = (module.exports = function () {
+  Stream.call(this);
+ 
+  this._buffers = [];
+  this._buffered = 0;
+ 
+  this._reads = [];
+  this._paused = false;
+ 
+  this._encoding = "utf8";
+  this.writable = true;
+});
+util.inherits(ChunkStream, Stream);
+ 
+ChunkStream.prototype.read = function (length, callback) {
+  this._reads.push({
+    length: Math.abs(length), // if length < 0 then at most this length
+    allowLess: length < 0,
+    func: callback,
+  });
+ 
+  process.nextTick(
+    function () {
+      this._process();
+ 
+      // its paused and there is not enought data then ask for more
+      Iif (this._paused && this._reads.length > 0) {
+        this._paused = false;
+ 
+        this.emit("drain");
+      }
+    }.bind(this)
+  );
+};
+ 
+ChunkStream.prototype.write = function (data, encoding) {
+  Iif (!this.writable) {
+    this.emit("error", new Error("Stream not writable"));
+    return false;
+  }
+ 
+  let dataBuffer;
+  Eif (Buffer.isBuffer(data)) {
+    dataBuffer = data;
+  } else {
+    dataBuffer = Buffer.from(data, encoding || this._encoding);
+  }
+ 
+  this._buffers.push(dataBuffer);
+  this._buffered += dataBuffer.length;
+ 
+  this._process();
+ 
+  // ok if there are no more read requests
+  if (this._reads && this._reads.length === 0) {
+    this._paused = true;
+  }
+ 
+  return this.writable && !this._paused;
+};
+ 
+ChunkStream.prototype.end = function (data, encoding) {
+  Iif (data) {
+    this.write(data, encoding);
+  }
+ 
+  this.writable = false;
+ 
+  // already destroyed
+  Iif (!this._buffers) {
+    return;
+  }
+ 
+  // enqueue or handle end
+  if (this._buffers.length === 0) {
+    this._end();
+  } else {
+    this._buffers.push(null);
+    this._process();
+  }
+};
+ 
+ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
+ 
+ChunkStream.prototype._end = function () {
+  if (this._reads.length > 0) {
+    this.emit("error", new Error("Unexpected end of input"));
+  }
+ 
+  this.destroy();
+};
+ 
+ChunkStream.prototype.destroy = function () {
+  Iif (!this._buffers) {
+    return;
+  }
+ 
+  this.writable = false;
+  this._reads = null;
+  this._buffers = null;
+ 
+  this.emit("close");
+};
+ 
+ChunkStream.prototype._processReadAllowingLess = function (read) {
+  // ok there is any data so that we can satisfy this request
+  this._reads.shift(); // == read
+ 
+  // first we need to peek into first buffer
+  let smallerBuf = this._buffers[0];
+ 
+  // ok there is more data than we need
+  if (smallerBuf.length > read.length) {
+    this._buffered -= read.length;
+    this._buffers[0] = smallerBuf.slice(read.length);
+ 
+    read.func.call(this, smallerBuf.slice(0, read.length));
+  } else {
+    // ok this is less than maximum length so use it all
+    this._buffered -= smallerBuf.length;
+    this._buffers.shift(); // == smallerBuf
+ 
+    read.func.call(this, smallerBuf);
+  }
+};
+ 
+ChunkStream.prototype._processRead = function (read) {
+  this._reads.shift(); // == read
+ 
+  let pos = 0;
+  let count = 0;
+  let data = Buffer.alloc(read.length);
+ 
+  // create buffer for all data
+  while (pos < read.length) {
+    let buf = this._buffers[count++];
+    let len = Math.min(buf.length, read.length - pos);
+ 
+    buf.copy(data, pos, 0, len);
+    pos += len;
+ 
+    // last buffer wasn't used all so just slice it and leave
+    if (len !== buf.length) {
+      this._buffers[--count] = buf.slice(len);
+    }
+  }
+ 
+  // remove all used buffers
+  if (count > 0) {
+    this._buffers.splice(0, count);
+  }
+ 
+  this._buffered -= read.length;
+ 
+  read.func.call(this, data);
+};
+ 
+ChunkStream.prototype._process = function () {
+  try {
+    // as long as there is any data and read requests
+    while (this._buffered > 0 && this._reads && this._reads.length > 0) {
+      let read = this._reads[0];
+ 
+      // read any data (but no more than length)
+      if (read.allowLess) {
+        this._processReadAllowingLess(read);
+      } else if (this._buffered >= read.length) {
+        // ok we can meet some expectations
+ 
+        this._processRead(read);
+      } else {
+        // not enought data to satisfy first request in queue
+        // so we need to wait for more
+        break;
+      }
+    }
+ 
+    if (this._buffers && !this.writable) {
+      this._end();
+    }
+  } catch (ex) {
+    this.emit("error", ex);
+  }
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/constants.js.html b/backend/node_modules/pngjs/coverage/lcov-report/constants.js.html new file mode 100644 index 00000000..a6edd802 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/constants.js.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for constants.js + + + + + + + + + +
+
+

All files constants.js

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +29 +30 +31 +32 +33  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+ 
+module.exports = {
+  PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
+ 
+  TYPE_IHDR: 0x49484452,
+  TYPE_IEND: 0x49454e44,
+  TYPE_IDAT: 0x49444154,
+  TYPE_PLTE: 0x504c5445,
+  TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase
+  TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase
+ 
+  // color-type bits
+  COLORTYPE_GRAYSCALE: 0,
+  COLORTYPE_PALETTE: 1,
+  COLORTYPE_COLOR: 2,
+  COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha
+ 
+  // color-type combinations
+  COLORTYPE_PALETTE_COLOR: 3,
+  COLORTYPE_COLOR_ALPHA: 6,
+ 
+  COLORTYPE_TO_BPP_MAP: {
+    0: 1,
+    2: 3,
+    3: 1,
+    4: 2,
+    6: 4,
+  },
+ 
+  GAMMA_DIVISION: 100000,
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/crc.js.html b/backend/node_modules/pngjs/coverage/lcov-report/crc.js.html new file mode 100644 index 00000000..53fc72a3 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/crc.js.html @@ -0,0 +1,200 @@ + + + + + + Code coverage report for crc.js + + + + + + + + + +
+
+

All files crc.js

+
+ +
+ 100% + Statements + 26/26 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 100% + Lines + 22/22 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41  +  +1x +  +1x +1x +256x +256x +2048x +1024x +  +1024x +  +  +256x +  +  +  +1x +2461x +  +  +1x +4839x +823519x +  +4839x +  +  +1x +2195x +  +  +1x +1592x +1592x +305287x +  +1592x +  + 
"use strict";
+ 
+let crcTable = [];
+ 
+(function () {
+  for (let i = 0; i < 256; i++) {
+    let currentCrc = i;
+    for (let j = 0; j < 8; j++) {
+      if (currentCrc & 1) {
+        currentCrc = 0xedb88320 ^ (currentCrc >>> 1);
+      } else {
+        currentCrc = currentCrc >>> 1;
+      }
+    }
+    crcTable[i] = currentCrc;
+  }
+})();
+ 
+let CrcCalculator = (module.exports = function () {
+  this._crc = -1;
+});
+ 
+CrcCalculator.prototype.write = function (data) {
+  for (let i = 0; i < data.length; i++) {
+    this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
+  }
+  return true;
+};
+ 
+CrcCalculator.prototype.crc32 = function () {
+  return this._crc ^ -1;
+};
+ 
+CrcCalculator.crc32 = function (buf) {
+  let crc = -1;
+  for (let i = 0; i < buf.length; i++) {
+    crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
+  }
+  return crc ^ -1;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/favicon.png b/backend/node_modules/pngjs/coverage/lcov-report/favicon.png new file mode 100644 index 00000000..66918178 Binary files /dev/null and b/backend/node_modules/pngjs/coverage/lcov-report/favicon.png differ diff --git a/backend/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html b/backend/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html new file mode 100644 index 00000000..e718a1a7 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html @@ -0,0 +1,593 @@ + + + + + + Code coverage report for filter-pack.js + + + + + + + + + +
+
+

All files filter-pack.js

+
+ +
+ 95.83% + Statements + 92/96 +
+ + +
+ 81.82% + Branches + 36/44 +
+ + +
+ 100% + Functions + 11/11 +
+ + +
+ 95.24% + Lines + 80/84 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172  +  +1x +  +  +44x +5136x +  +  +  +  +10490x +10490x +  +10490x +2776736x +  +10490x +  +  +  +637x +107032x +107032x +  +107032x +  +  +  +  +10490x +10490x +2776736x +2776736x +  +2776736x +  +  +10490x +  +  +  +2670x +581344x +581344x +  +581344x +  +  +  +  +10490x +10490x +10490x +2776736x +2776736x +  +2776736x +  +  +10490x +  +  +  +208x +204096x +204096x +204096x +  +204096x +  +  +  +  +10490x +10490x +2776736x +2776736x +2776736x +  +2776736x +  +  +10490x +  +  +  +6931x +1879128x +1879128x +  +1879128x +1879128x +  +1879128x +  +  +  +  +10490x +10490x +2776736x +2776736x +  +2776736x +2776736x +  +2776736x +  +  +10490x +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +325x +325x +  +  +  +  +  +  +325x +  +  +325x +325x +325x +325x +  +325x +  +325x +10490x +  +10490x +  +10490x +52450x +52450x +35370x +35370x +  +  +  +  +10490x +10490x +10490x +10490x +10490x +  +325x +  + 
"use strict";
+ 
+let paethPredictor = require("./paeth-predictor");
+ 
+function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) {
+  for (let x = 0; x < byteWidth; x++) {
+    rawData[rawPos + x] = pxData[pxPos + x];
+  }
+}
+ 
+function filterSumNone(pxData, pxPos, byteWidth) {
+  let sum = 0;
+  let length = pxPos + byteWidth;
+ 
+  for (let i = pxPos; i < length; i++) {
+    sum += Math.abs(pxData[i]);
+  }
+  return sum;
+}
+ 
+function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let val = pxData[pxPos + x] - left;
+ 
+    rawData[rawPos + x] = val;
+  }
+}
+ 
+function filterSumSub(pxData, pxPos, byteWidth, bpp) {
+  let sum = 0;
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let val = pxData[pxPos + x] - left;
+ 
+    sum += Math.abs(val);
+  }
+ 
+  return sum;
+}
+ 
+function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) {
+  for (let x = 0; x < byteWidth; x++) {
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let val = pxData[pxPos + x] - up;
+ 
+    rawData[rawPos + x] = val;
+  }
+}
+ 
+function filterSumUp(pxData, pxPos, byteWidth) {
+  let sum = 0;
+  let length = pxPos + byteWidth;
+  for (let x = pxPos; x < length; x++) {
+    let up = pxPos > 0 ? pxData[x - byteWidth] : 0;
+    let val = pxData[x] - up;
+ 
+    sum += Math.abs(val);
+  }
+ 
+  return sum;
+}
+ 
+function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let val = pxData[pxPos + x] - ((left + up) >> 1);
+ 
+    rawData[rawPos + x] = val;
+  }
+}
+ 
+function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
+  let sum = 0;
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let val = pxData[pxPos + x] - ((left + up) >> 1);
+ 
+    sum += Math.abs(val);
+  }
+ 
+  return sum;
+}
+ 
+function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let upleft =
+      pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
+    let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
+ 
+    rawData[rawPos + x] = val;
+  }
+}
+ 
+function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
+  let sum = 0;
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let upleft =
+      pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
+    let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
+ 
+    sum += Math.abs(val);
+  }
+ 
+  return sum;
+}
+ 
+let filters = {
+  0: filterNone,
+  1: filterSub,
+  2: filterUp,
+  3: filterAvg,
+  4: filterPaeth,
+};
+ 
+let filterSums = {
+  0: filterSumNone,
+  1: filterSumSub,
+  2: filterSumUp,
+  3: filterSumAvg,
+  4: filterSumPaeth,
+};
+ 
+module.exports = function (pxData, width, height, options, bpp) {
+  let filterTypes;
+  Eif (!("filterType" in options) || options.filterType === -1) {
+    filterTypes = [0, 1, 2, 3, 4];
+  } else if (typeof options.filterType === "number") {
+    filterTypes = [options.filterType];
+  } else {
+    throw new Error("unrecognised filter types");
+  }
+ 
+  Iif (options.bitDepth === 16) {
+    bpp *= 2;
+  }
+  let byteWidth = width * bpp;
+  let rawPos = 0;
+  let pxPos = 0;
+  let rawData = Buffer.alloc((byteWidth + 1) * height);
+ 
+  let sel = filterTypes[0];
+ 
+  for (let y = 0; y < height; y++) {
+    Eif (filterTypes.length > 1) {
+      // find best filter for this line (with lowest sum of values)
+      let min = Infinity;
+ 
+      for (let i = 0; i < filterTypes.length; i++) {
+        let sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp);
+        if (sum < min) {
+          sel = filterTypes[i];
+          min = sum;
+        }
+      }
+    }
+ 
+    rawData[rawPos] = sel;
+    rawPos++;
+    filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp);
+    rawPos += byteWidth;
+    pxPos += byteWidth;
+  }
+  return rawData;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html b/backend/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html new file mode 100644 index 00000000..06f25f17 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html @@ -0,0 +1,152 @@ + + + + + + Code coverage report for filter-parse-async.js + + + + + + + + + +
+
+

All files filter-parse-async.js

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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  +  +1x +1x +1x +  +1x +176x +  +176x +176x +176x +  +  +9057x +  +  +173x +  +  +  +176x +  +1x + 
"use strict";
+ 
+let util = require("util");
+let ChunkStream = require("./chunkstream");
+let Filter = require("./filter-parse");
+ 
+let FilterAsync = (module.exports = function (bitmapInfo) {
+  ChunkStream.call(this);
+ 
+  let buffers = [];
+  let that = this;
+  this._filter = new Filter(bitmapInfo, {
+    read: this.read.bind(this),
+    write: function (buffer) {
+      buffers.push(buffer);
+    },
+    complete: function () {
+      that.emit("complete", Buffer.concat(buffers));
+    },
+  });
+ 
+  this._filter.start();
+});
+util.inherits(FilterAsync, ChunkStream);
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html b/backend/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html new file mode 100644 index 00000000..df91a354 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html @@ -0,0 +1,143 @@ + + + + + + Code coverage report for filter-parse-sync.js + + + + + + + + + +
+
+

All files filter-parse-sync.js

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 10/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22  +  +1x +1x +  +1x +162x +162x +162x +  +  +6337x +  +  +  +  +162x +162x +  +162x +  + 
"use strict";
+ 
+let SyncReader = require("./sync-reader");
+let Filter = require("./filter-parse");
+ 
+exports.process = function (inBuffer, bitmapInfo) {
+  let outBuffers = [];
+  let reader = new SyncReader(inBuffer);
+  let filter = new Filter(bitmapInfo, {
+    read: reader.read.bind(reader),
+    write: function (bufferPart) {
+      outBuffers.push(bufferPart);
+    },
+    complete: function () {},
+  });
+ 
+  filter.start();
+  reader.process();
+ 
+  return Buffer.concat(outBuffers);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html b/backend/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html new file mode 100644 index 00000000..945757ce --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html @@ -0,0 +1,611 @@ + + + + + + Code coverage report for filter-parse.js + + + + + + + + + +
+
+

All files filter-parse.js

+
+ +
+ 98.96% + Statements + 95/96 +
+ + +
+ 97.14% + Branches + 34/35 +
+ + +
+ 100% + Functions + 8/8 +
+ + +
+ 98.9% + Lines + 90/91 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178  +  +1x +1x +  +  +742x +742x +531x +  +742x +  +  +1x +338x +338x +338x +338x +338x +  +338x +338x +338x +  +338x +338x +338x +72x +72x +476x +  +  +  +  +  +  +266x +  +  +  +  +  +  +  +  +  +  +338x +127x +211x +66x +  +145x +  +  +  +1x +338x +  +  +  +  +  +1x +  +  +  +  +1939x +1939x +  +1939x +3563504x +3563504x +3563504x +  +  +  +1x +  +  +  +  +800x +  +800x +330256x +330256x +330256x +  +  +  +1x +  +  +  +  +172x +172x +172x +  +172x +9952x +9952x +9952x +9952x +9952x +  +  +  +1x +  +  +  +  +4165x +4165x +4165x +  +4165x +1152544x +1152544x +1152544x +1152544x +1152544x +1152544x +  +  +  +1x +15394x +  +15394x +15394x +  +15394x +8318x +  +7076x +  +7076x +  +1939x +1939x +  +800x +800x +  +172x +172x +  +4165x +4165x +  +  +  +  +  +15394x +  +15394x +15394x +739x +739x +739x +  +14655x +  +  +15394x +  +15059x +  +335x +335x +  +  + 
"use strict";
+ 
+let interlaceUtils = require("./interlace");
+let paethPredictor = require("./paeth-predictor");
+ 
+function getByteWidth(width, bpp, depth) {
+  let byteWidth = width * bpp;
+  if (depth !== 8) {
+    byteWidth = Math.ceil(byteWidth / (8 / depth));
+  }
+  return byteWidth;
+}
+ 
+let Filter = (module.exports = function (bitmapInfo, dependencies) {
+  let width = bitmapInfo.width;
+  let height = bitmapInfo.height;
+  let interlace = bitmapInfo.interlace;
+  let bpp = bitmapInfo.bpp;
+  let depth = bitmapInfo.depth;
+ 
+  this.read = dependencies.read;
+  this.write = dependencies.write;
+  this.complete = dependencies.complete;
+ 
+  this._imageIndex = 0;
+  this._images = [];
+  if (interlace) {
+    let passes = interlaceUtils.getImagePasses(width, height);
+    for (let i = 0; i < passes.length; i++) {
+      this._images.push({
+        byteWidth: getByteWidth(passes[i].width, bpp, depth),
+        height: passes[i].height,
+        lineIndex: 0,
+      });
+    }
+  } else {
+    this._images.push({
+      byteWidth: getByteWidth(width, bpp, depth),
+      height: height,
+      lineIndex: 0,
+    });
+  }
+ 
+  // when filtering the line we look at the pixel to the left
+  // the spec also says it is done on a byte level regardless of the number of pixels
+  // so if the depth is byte compatible (8 or 16) we subtract the bpp in order to compare back
+  // a pixel rather than just a different byte part. However if we are sub byte, we ignore.
+  if (depth === 8) {
+    this._xComparison = bpp;
+  } else if (depth === 16) {
+    this._xComparison = bpp * 2;
+  } else {
+    this._xComparison = 1;
+  }
+});
+ 
+Filter.prototype.start = function () {
+  this.read(
+    this._images[this._imageIndex].byteWidth + 1,
+    this._reverseFilterLine.bind(this)
+  );
+};
+ 
+Filter.prototype._unFilterType1 = function (
+  rawData,
+  unfilteredLine,
+  byteWidth
+) {
+  let xComparison = this._xComparison;
+  let xBiggerThan = xComparison - 1;
+ 
+  for (let x = 0; x < byteWidth; x++) {
+    let rawByte = rawData[1 + x];
+    let f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+    unfilteredLine[x] = rawByte + f1Left;
+  }
+};
+ 
+Filter.prototype._unFilterType2 = function (
+  rawData,
+  unfilteredLine,
+  byteWidth
+) {
+  let lastLine = this._lastLine;
+ 
+  for (let x = 0; x < byteWidth; x++) {
+    let rawByte = rawData[1 + x];
+    let f2Up = lastLine ? lastLine[x] : 0;
+    unfilteredLine[x] = rawByte + f2Up;
+  }
+};
+ 
+Filter.prototype._unFilterType3 = function (
+  rawData,
+  unfilteredLine,
+  byteWidth
+) {
+  let xComparison = this._xComparison;
+  let xBiggerThan = xComparison - 1;
+  let lastLine = this._lastLine;
+ 
+  for (let x = 0; x < byteWidth; x++) {
+    let rawByte = rawData[1 + x];
+    let f3Up = lastLine ? lastLine[x] : 0;
+    let f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+    let f3Add = Math.floor((f3Left + f3Up) / 2);
+    unfilteredLine[x] = rawByte + f3Add;
+  }
+};
+ 
+Filter.prototype._unFilterType4 = function (
+  rawData,
+  unfilteredLine,
+  byteWidth
+) {
+  let xComparison = this._xComparison;
+  let xBiggerThan = xComparison - 1;
+  let lastLine = this._lastLine;
+ 
+  for (let x = 0; x < byteWidth; x++) {
+    let rawByte = rawData[1 + x];
+    let f4Up = lastLine ? lastLine[x] : 0;
+    let f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+    let f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
+    let f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
+    unfilteredLine[x] = rawByte + f4Add;
+  }
+};
+ 
+Filter.prototype._reverseFilterLine = function (rawData) {
+  let filter = rawData[0];
+  let unfilteredLine;
+  let currentImage = this._images[this._imageIndex];
+  let byteWidth = currentImage.byteWidth;
+ 
+  if (filter === 0) {
+    unfilteredLine = rawData.slice(1, byteWidth + 1);
+  } else {
+    unfilteredLine = Buffer.alloc(byteWidth);
+ 
+    switch (filter) {
+      case 1:
+        this._unFilterType1(rawData, unfilteredLine, byteWidth);
+        break;
+      case 2:
+        this._unFilterType2(rawData, unfilteredLine, byteWidth);
+        break;
+      case 3:
+        this._unFilterType3(rawData, unfilteredLine, byteWidth);
+        break;
+      case 4:
+        this._unFilterType4(rawData, unfilteredLine, byteWidth);
+        break;
+      default:
+        throw new Error("Unrecognised filter type - " + filter);
+    }
+  }
+ 
+  this.write(unfilteredLine);
+ 
+  currentImage.lineIndex++;
+  if (currentImage.lineIndex >= currentImage.height) {
+    this._lastLine = null;
+    this._imageIndex++;
+    currentImage = this._images[this._imageIndex];
+  } else {
+    this._lastLine = unfilteredLine;
+  }
+ 
+  if (currentImage) {
+    // read, using the byte width that may be from the new current image
+    this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
+  } else {
+    this._lastLine = null;
+    this.complete();
+  }
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html b/backend/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html new file mode 100644 index 00000000..c61afcfd --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html @@ -0,0 +1,359 @@ + + + + + + Code coverage report for format-normaliser.js + + + + + + + + + +
+
+

All files format-normaliser.js

+
+ +
+ 98.21% + Statements + 55/56 +
+ + +
+ 95.24% + Branches + 20/21 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 97.87% + Lines + 46/47 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94  +  +  +131x +  +131x +4912x +1418436x +  +1418436x +  +  +  +1418436x +5673744x +  +1418436x +  +  +  +  +  +12x +12x +384x +12288x +  +12288x +6144x +2762x +  +6144x +  +  +  +  +2718x +  +12288x +5480x +21920x +  +  +12288x +  +  +  +  +  +106x +106x +106x +  +106x +3392x +108544x +434176x +  +  +  +108544x +  +  +  +  +1x +335x +335x +335x +335x +335x +335x +  +335x +  +335x +  +131x +  +204x +12x +  +  +204x +  +106x +66x +  +106x +  +  +335x +  + 
"use strict";
+ 
+function dePalette(indata, outdata, width, height, palette) {
+  let pxPos = 0;
+  // use values from palette
+  for (let y = 0; y < height; y++) {
+    for (let x = 0; x < width; x++) {
+      let color = palette[indata[pxPos]];
+ 
+      Iif (!color) {
+        throw new Error("index " + indata[pxPos] + " not in palette");
+      }
+ 
+      for (let i = 0; i < 4; i++) {
+        outdata[pxPos + i] = color[i];
+      }
+      pxPos += 4;
+    }
+  }
+}
+ 
+function replaceTransparentColor(indata, outdata, width, height, transColor) {
+  let pxPos = 0;
+  for (let y = 0; y < height; y++) {
+    for (let x = 0; x < width; x++) {
+      let makeTrans = false;
+ 
+      if (transColor.length === 1) {
+        if (transColor[0] === indata[pxPos]) {
+          makeTrans = true;
+        }
+      } else if (
+        transColor[0] === indata[pxPos] &&
+        transColor[1] === indata[pxPos + 1] &&
+        transColor[2] === indata[pxPos + 2]
+      ) {
+        makeTrans = true;
+      }
+      if (makeTrans) {
+        for (let i = 0; i < 4; i++) {
+          outdata[pxPos + i] = 0;
+        }
+      }
+      pxPos += 4;
+    }
+  }
+}
+ 
+function scaleDepth(indata, outdata, width, height, depth) {
+  let maxOutSample = 255;
+  let maxInSample = Math.pow(2, depth) - 1;
+  let pxPos = 0;
+ 
+  for (let y = 0; y < height; y++) {
+    for (let x = 0; x < width; x++) {
+      for (let i = 0; i < 4; i++) {
+        outdata[pxPos + i] = Math.floor(
+          (indata[pxPos + i] * maxOutSample) / maxInSample + 0.5
+        );
+      }
+      pxPos += 4;
+    }
+  }
+}
+ 
+module.exports = function (indata, imageData) {
+  let depth = imageData.depth;
+  let width = imageData.width;
+  let height = imageData.height;
+  let colorType = imageData.colorType;
+  let transColor = imageData.transColor;
+  let palette = imageData.palette;
+ 
+  let outdata = indata; // only different for 16 bits
+ 
+  if (colorType === 3) {
+    // paletted
+    dePalette(indata, outdata, width, height, palette);
+  } else {
+    if (transColor) {
+      replaceTransparentColor(indata, outdata, width, height, transColor);
+    }
+    // if it needs scaling
+    if (depth !== 8) {
+      // if we need to change the buffer size
+      if (depth === 16) {
+        outdata = Buffer.alloc(width * height * 4);
+      }
+      scaleDepth(indata, outdata, width, height, depth);
+    }
+  }
+  return outdata;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/index.html b/backend/node_modules/pngjs/coverage/lcov-report/index.html new file mode 100644 index 00000000..51ecafd0 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/index.html @@ -0,0 +1,426 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 82.72% + Statements + 1034/1250 +
+ + +
+ 67.59% + Branches + 317/469 +
+ + +
+ 90.26% + Functions + 139/154 +
+ + +
+ 82.53% + Lines + 992/1202 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
bitmapper.js +
+
94.37%134/14272.41%21/2989.47%17/1994.16%129/137
bitpacker.js +
+
11.36%10/886.12%3/4966.67%2/311.63%10/86
chunkstream.js +
+
90.11%82/9181.4%35/43100%10/1090.11%82/91
constants.js +
+
100%1/1100%0/0100%0/0100%1/1
crc.js +
+
100%26/26100%2/2100%5/5100%22/22
filter-pack.js +
+
95.83%92/9681.82%36/44100%11/1195.24%80/84
filter-parse-async.js +
+
100%12/12100%0/0100%3/3100%12/12
filter-parse-sync.js +
+
100%10/10100%0/0100%3/3100%10/10
filter-parse.js +
+
98.96%95/9697.14%34/35100%8/898.9%90/91
format-normaliser.js +
+
98.21%55/5695.24%20/21100%4/497.87%46/47
interlace.js +
+
100%32/32100%8/8100%3/3100%29/29
packer-async.js +
+
100%24/2475%3/4100%4/4100%24/24
packer-sync.js +
+
25%6/248.33%1/120%0/125%6/24
packer.js +
+
94.74%54/5767.86%19/28100%9/994.74%54/57
paeth-predictor.js +
+
100%10/10100%6/6100%1/1100%10/10
parser-async.js +
+
88.75%71/8072.73%16/2284.62%11/1388.75%71/80
parser-sync.js +
+
93.33%42/4578.57%11/14100%8/893.33%42/45
parser.js +
+
90.57%144/15985.45%47/55100%20/2090.32%140/155
png-sync.js +
+
83.33%5/6100%2/250%1/283.33%5/6
png.js +
+
54.17%52/9641.18%14/3456.25%9/1656.52%52/92
sync-inflate.js +
+
75.31%61/8162%31/5087.5%7/875.31%61/81
sync-reader.js +
+
88.89%16/1872.73%8/11100%3/388.89%16/18
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/interlace.js.html b/backend/node_modules/pngjs/coverage/lcov-report/interlace.js.html new file mode 100644 index 00000000..d67b0878 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/interlace.js.html @@ -0,0 +1,365 @@ + + + + + + Code coverage report for interlace.js + + + + + + + + + +
+
+

All files interlace.js

+
+ +
+ 100% + Statements + 32/32 +
+ + +
+ 100% + Branches + 8/8 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 29/29 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +144x +144x +144x +144x +144x +144x +1008x +1008x +1008x +1008x +1556x +672x +  +884x +  +  +1008x +1360x +552x +  +808x +  +  +1008x +952x +  +  +144x +  +  +1x +72x +324850x +  +324850x +  +324850x +  +324850x +  +324850x +  +  + 
"use strict";
+ 
+// Adam 7
+//   0 1 2 3 4 5 6 7
+// 0 x 6 4 6 x 6 4 6
+// 1 7 7 7 7 7 7 7 7
+// 2 5 6 5 6 5 6 5 6
+// 3 7 7 7 7 7 7 7 7
+// 4 3 6 4 6 3 6 4 6
+// 5 7 7 7 7 7 7 7 7
+// 6 5 6 5 6 5 6 5 6
+// 7 7 7 7 7 7 7 7 7
+ 
+let imagePasses = [
+  {
+    // pass 1 - 1px
+    x: [0],
+    y: [0],
+  },
+  {
+    // pass 2 - 1px
+    x: [4],
+    y: [0],
+  },
+  {
+    // pass 3 - 2px
+    x: [0, 4],
+    y: [4],
+  },
+  {
+    // pass 4 - 4px
+    x: [2, 6],
+    y: [0, 4],
+  },
+  {
+    // pass 5 - 8px
+    x: [0, 2, 4, 6],
+    y: [2, 6],
+  },
+  {
+    // pass 6 - 16px
+    x: [1, 3, 5, 7],
+    y: [0, 2, 4, 6],
+  },
+  {
+    // pass 7 - 32px
+    x: [0, 1, 2, 3, 4, 5, 6, 7],
+    y: [1, 3, 5, 7],
+  },
+];
+ 
+exports.getImagePasses = function (width, height) {
+  let images = [];
+  let xLeftOver = width % 8;
+  let yLeftOver = height % 8;
+  let xRepeats = (width - xLeftOver) / 8;
+  let yRepeats = (height - yLeftOver) / 8;
+  for (let i = 0; i < imagePasses.length; i++) {
+    let pass = imagePasses[i];
+    let passWidth = xRepeats * pass.x.length;
+    let passHeight = yRepeats * pass.y.length;
+    for (let j = 0; j < pass.x.length; j++) {
+      if (pass.x[j] < xLeftOver) {
+        passWidth++;
+      } else {
+        break;
+      }
+    }
+    for (let j = 0; j < pass.y.length; j++) {
+      if (pass.y[j] < yLeftOver) {
+        passHeight++;
+      } else {
+        break;
+      }
+    }
+    if (passWidth > 0 && passHeight > 0) {
+      images.push({ width: passWidth, height: passHeight, index: i });
+    }
+  }
+  return images;
+};
+ 
+exports.getInterlaceIterator = function (width) {
+  return function (x, y, pass) {
+    let outerXLeftOver = x % imagePasses[pass].x.length;
+    let outerX =
+      ((x - outerXLeftOver) / imagePasses[pass].x.length) * 8 +
+      imagePasses[pass].x[outerXLeftOver];
+    let outerYLeftOver = y % imagePasses[pass].y.length;
+    let outerY =
+      ((y - outerYLeftOver) / imagePasses[pass].y.length) * 8 +
+      imagePasses[pass].y[outerYLeftOver];
+    return outerX * 4 + outerY * width * 4;
+  };
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/packer-async.js.html b/backend/node_modules/pngjs/coverage/lcov-report/packer-async.js.html new file mode 100644 index 00000000..55365c71 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/packer-async.js.html @@ -0,0 +1,230 @@ + + + + + + Code coverage report for packer-async.js + + + + + + + + + +
+
+

All files packer-async.js

+
+ +
+ 100% + Statements + 24/24 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 24/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51  +  +1x +1x +1x +1x +  +1x +353x +  +353x +  +353x +353x +  +353x +  +1x +  +1x +  +325x +325x +  +325x +290x +  +  +325x +  +  +325x +  +325x +  +  +652x +  +  +  +325x +  +  +325x +325x +  +  +  +325x +  + 
"use strict";
+ 
+let util = require("util");
+let Stream = require("stream");
+let constants = require("./constants");
+let Packer = require("./packer");
+ 
+let PackerAsync = (module.exports = function (opt) {
+  Stream.call(this);
+ 
+  let options = opt || {};
+ 
+  this._packer = new Packer(options);
+  this._deflate = this._packer.createDeflate();
+ 
+  this.readable = true;
+});
+util.inherits(PackerAsync, Stream);
+ 
+PackerAsync.prototype.pack = function (data, width, height, gamma) {
+  // Signature
+  this.emit("data", Buffer.from(constants.PNG_SIGNATURE));
+  this.emit("data", this._packer.packIHDR(width, height));
+ 
+  if (gamma) {
+    this.emit("data", this._packer.packGAMA(gamma));
+  }
+ 
+  let filteredData = this._packer.filterData(data, width, height);
+ 
+  // compress it
+  this._deflate.on("error", this.emit.bind(this, "error"));
+ 
+  this._deflate.on(
+    "data",
+    function (compressedData) {
+      this.emit("data", this._packer.packIDAT(compressedData));
+    }.bind(this)
+  );
+ 
+  this._deflate.on(
+    "end",
+    function () {
+      this.emit("data", this._packer.packIEND());
+      this.emit("end");
+    }.bind(this)
+  );
+ 
+  this._deflate.end(filteredData);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html b/backend/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html new file mode 100644 index 00000000..86283b56 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html @@ -0,0 +1,248 @@ + + + + + + Code coverage report for packer-sync.js + + + + + + + + + +
+
+

All files packer-sync.js

+
+ +
+ 25% + Statements + 6/24 +
+ + +
+ 8.33% + Branches + 1/12 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 25% + Lines + 6/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57  +  +1x +1x +1x +  +  +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+ 
+let hasSyncZlib = true;
+let zlib = require("zlib");
+Iif (!zlib.deflateSync) {
+  hasSyncZlib = false;
+}
+let constants = require("./constants");
+let Packer = require("./packer");
+ 
+module.exports = function (metaData, opt) {
+  if (!hasSyncZlib) {
+    throw new Error(
+      "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
+    );
+  }
+ 
+  let options = opt || {};
+ 
+  let packer = new Packer(options);
+ 
+  let chunks = [];
+ 
+  // Signature
+  chunks.push(Buffer.from(constants.PNG_SIGNATURE));
+ 
+  // Header
+  chunks.push(packer.packIHDR(metaData.width, metaData.height));
+ 
+  if (metaData.gamma) {
+    chunks.push(packer.packGAMA(metaData.gamma));
+  }
+ 
+  let filteredData = packer.filterData(
+    metaData.data,
+    metaData.width,
+    metaData.height
+  );
+ 
+  // compress it
+  let compressedData = zlib.deflateSync(
+    filteredData,
+    packer.getDeflateOptions()
+  );
+  filteredData = null;
+ 
+  if (!compressedData || !compressedData.length) {
+    throw new Error("bad png - invalid compressed data response");
+  }
+  chunks.push(packer.packIDAT(compressedData));
+ 
+  // End
+  chunks.push(packer.packIEND());
+ 
+  return Buffer.concat(chunks);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/packer.js.html b/backend/node_modules/pngjs/coverage/lcov-report/packer.js.html new file mode 100644 index 00000000..606e1930 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/packer.js.html @@ -0,0 +1,467 @@ + + + + + + Code coverage report for packer.js + + + + + + + + + +
+
+

All files packer.js

+
+ +
+ 94.74% + Statements + 54/57 +
+ + +
+ 67.86% + Branches + 19/28 +
+ + +
+ 100% + Functions + 9/9 +
+ + +
+ 94.74% + Lines + 54/57 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130  +  +1x +1x +1x +1x +1x +  +1x +353x +  +353x +353x +  +353x +  +353x +  +353x +353x +  +353x +  +  +  +353x +  +  +  +  +353x +  +  +  +  +  +  +  +  +  +  +  +353x +  +  +  +  +  +  +  +  +  +  +  +  +  +353x +  +  +  +  +  +  +1x +353x +  +  +  +  +  +  +1x +353x +  +  +1x +  +325x +  +  +325x +325x +325x +  +  +1x +1592x +1592x +  +1592x +1592x +  +1592x +1267x +  +  +1592x +  +  +  +1592x +  +  +1x +290x +290x +290x +  +  +1x +325x +325x +325x +325x +325x +325x +325x +325x +  +325x +  +  +1x +652x +  +  +1x +325x +  + 
"use strict";
+ 
+let constants = require("./constants");
+let CrcStream = require("./crc");
+let bitPacker = require("./bitpacker");
+let filter = require("./filter-pack");
+let zlib = require("zlib");
+ 
+let Packer = (module.exports = function (options) {
+  this._options = options;
+ 
+  options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
+  options.deflateLevel =
+    options.deflateLevel != null ? options.deflateLevel : 9;
+  options.deflateStrategy =
+    options.deflateStrategy != null ? options.deflateStrategy : 3;
+  options.inputHasAlpha =
+    options.inputHasAlpha != null ? options.inputHasAlpha : true;
+  options.deflateFactory = options.deflateFactory || zlib.createDeflate;
+  options.bitDepth = options.bitDepth || 8;
+  // This is outputColorType
+  options.colorType =
+    typeof options.colorType === "number"
+      ? options.colorType
+      : constants.COLORTYPE_COLOR_ALPHA;
+  options.inputColorType =
+    typeof options.inputColorType === "number"
+      ? options.inputColorType
+      : constants.COLORTYPE_COLOR_ALPHA;
+ 
+  Iif (
+    [
+      constants.COLORTYPE_GRAYSCALE,
+      constants.COLORTYPE_COLOR,
+      constants.COLORTYPE_COLOR_ALPHA,
+      constants.COLORTYPE_ALPHA,
+    ].indexOf(options.colorType) === -1
+  ) {
+    throw new Error(
+      "option color type:" + options.colorType + " is not supported at present"
+    );
+  }
+  Iif (
+    [
+      constants.COLORTYPE_GRAYSCALE,
+      constants.COLORTYPE_COLOR,
+      constants.COLORTYPE_COLOR_ALPHA,
+      constants.COLORTYPE_ALPHA,
+    ].indexOf(options.inputColorType) === -1
+  ) {
+    throw new Error(
+      "option input color type:" +
+        options.inputColorType +
+        " is not supported at present"
+    );
+  }
+  Iif (options.bitDepth !== 8 && options.bitDepth !== 16) {
+    throw new Error(
+      "option bit depth:" + options.bitDepth + " is not supported at present"
+    );
+  }
+});
+ 
+Packer.prototype.getDeflateOptions = function () {
+  return {
+    chunkSize: this._options.deflateChunkSize,
+    level: this._options.deflateLevel,
+    strategy: this._options.deflateStrategy,
+  };
+};
+ 
+Packer.prototype.createDeflate = function () {
+  return this._options.deflateFactory(this.getDeflateOptions());
+};
+ 
+Packer.prototype.filterData = function (data, width, height) {
+  // convert to correct format for filtering (e.g. right bpp and bit depth)
+  let packedData = bitPacker(data, width, height, this._options);
+ 
+  // filter pixel data
+  let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
+  let filteredData = filter(packedData, width, height, this._options, bpp);
+  return filteredData;
+};
+ 
+Packer.prototype._packChunk = function (type, data) {
+  let len = data ? data.length : 0;
+  let buf = Buffer.alloc(len + 12);
+ 
+  buf.writeUInt32BE(len, 0);
+  buf.writeUInt32BE(type, 4);
+ 
+  if (data) {
+    data.copy(buf, 8);
+  }
+ 
+  buf.writeInt32BE(
+    CrcStream.crc32(buf.slice(4, buf.length - 4)),
+    buf.length - 4
+  );
+  return buf;
+};
+ 
+Packer.prototype.packGAMA = function (gamma) {
+  let buf = Buffer.alloc(4);
+  buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
+  return this._packChunk(constants.TYPE_gAMA, buf);
+};
+ 
+Packer.prototype.packIHDR = function (width, height) {
+  let buf = Buffer.alloc(13);
+  buf.writeUInt32BE(width, 0);
+  buf.writeUInt32BE(height, 4);
+  buf[8] = this._options.bitDepth; // Bit depth
+  buf[9] = this._options.colorType; // colorType
+  buf[10] = 0; // compression
+  buf[11] = 0; // filter
+  buf[12] = 0; // interlace
+ 
+  return this._packChunk(constants.TYPE_IHDR, buf);
+};
+ 
+Packer.prototype.packIDAT = function (data) {
+  return this._packChunk(constants.TYPE_IDAT, data);
+};
+ 
+Packer.prototype.packIEND = function () {
+  return this._packChunk(constants.TYPE_IEND, null);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html b/backend/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html new file mode 100644 index 00000000..6385999a --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html @@ -0,0 +1,128 @@ + + + + + + Code coverage report for paeth-predictor.js + + + + + + + + + +
+
+

All files paeth-predictor.js

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 6/6 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 10/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17  +  +1x +5808408x +5808408x +5808408x +5808408x +  +5808408x +5156742x +  +651666x +539893x +  +111773x +  + 
"use strict";
+ 
+module.exports = function paethPredictor(left, above, upLeft) {
+  let paeth = left + above - upLeft;
+  let pLeft = Math.abs(paeth - left);
+  let pAbove = Math.abs(paeth - above);
+  let pUpLeft = Math.abs(paeth - upLeft);
+ 
+  if (pLeft <= pAbove && pLeft <= pUpLeft) {
+    return left;
+  }
+  if (pAbove <= pUpLeft) {
+    return above;
+  }
+  return upLeft;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/parser-async.js.html b/backend/node_modules/pngjs/coverage/lcov-report/parser-async.js.html new file mode 100644 index 00000000..77074ffc --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/parser-async.js.html @@ -0,0 +1,575 @@ + + + + + + Code coverage report for parser-async.js + + + + + + + + + +
+
+

All files parser-async.js

+
+ +
+ 88.75% + Statements + 71/80 +
+ + +
+ 72.73% + Branches + 16/22 +
+ + +
+ 84.62% + Functions + 11/13 +
+ + +
+ 88.75% + Lines + 71/80 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166  +  +1x +1x +1x +1x +1x +1x +1x +  +1x +353x +  +353x +  +  +  +  +  +  +  +  +  +  +  +353x +353x +  +353x +  +1x +  +1x +14x +  +14x +  +14x +  +14x +1x +  +  +14x +2x +  +  +  +2x +  +  +14x +  +  +1x +741x +174x +36x +  +36x +36x +  +36x +  +  +138x +  +  +  +  +  +138x +138x +  +138x +138x +  +138x +138x +  +  +  +  +  +  +138x +  +138x +138x +487x +  +  +  +487x +  +  +  +487x +  +487x +  +  +138x +  +  +741x +  +  +1x +176x +176x +  +176x +  +  +1x +7x +  +  +1x +77x +  +  +1x +15x +  +  +1x +  +  +174x +  +  +1x +173x +  +  +  +173x +1x +  +  +172x +  +  +  +1x +173x +  +  +  +  +  +173x +173x +  +173x +173x +  +  +  +  +  +173x +  + 
"use strict";
+ 
+let util = require("util");
+let zlib = require("zlib");
+let ChunkStream = require("./chunkstream");
+let FilterAsync = require("./filter-parse-async");
+let Parser = require("./parser");
+let bitmapper = require("./bitmapper");
+let formatNormaliser = require("./format-normaliser");
+ 
+let ParserAsync = (module.exports = function (options) {
+  ChunkStream.call(this);
+ 
+  this._parser = new Parser(options, {
+    read: this.read.bind(this),
+    error: this._handleError.bind(this),
+    metadata: this._handleMetaData.bind(this),
+    gamma: this.emit.bind(this, "gamma"),
+    palette: this._handlePalette.bind(this),
+    transColor: this._handleTransColor.bind(this),
+    finished: this._finished.bind(this),
+    inflateData: this._inflateData.bind(this),
+    simpleTransparency: this._simpleTransparency.bind(this),
+    headersFinished: this._headersFinished.bind(this),
+  });
+  this._options = options;
+  this.writable = true;
+ 
+  this._parser.start();
+});
+util.inherits(ParserAsync, ChunkStream);
+ 
+ParserAsync.prototype._handleError = function (err) {
+  this.emit("error", err);
+ 
+  this.writable = false;
+ 
+  this.destroy();
+ 
+  if (this._inflate && this._inflate.destroy) {
+    this._inflate.destroy();
+  }
+ 
+  if (this._filter) {
+    this._filter.destroy();
+    // For backward compatibility with Node 7 and below.
+    // Suppress errors due to _inflate calling write() even after
+    // it's destroy()'ed.
+    this._filter.on("error", function () {});
+  }
+ 
+  this.errord = true;
+};
+ 
+ParserAsync.prototype._inflateData = function (data) {
+  if (!this._inflate) {
+    if (this._bitmapInfo.interlace) {
+      this._inflate = zlib.createInflate();
+ 
+      this._inflate.on("error", this.emit.bind(this, "error"));
+      this._filter.on("complete", this._complete.bind(this));
+ 
+      this._inflate.pipe(this._filter);
+    } else {
+      let rowSize =
+        ((this._bitmapInfo.width *
+          this._bitmapInfo.bpp *
+          this._bitmapInfo.depth +
+          7) >>
+          3) +
+        1;
+      let imageSize = rowSize * this._bitmapInfo.height;
+      let chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK);
+ 
+      this._inflate = zlib.createInflate({ chunkSize: chunkSize });
+      let leftToInflate = imageSize;
+ 
+      let emitError = this.emit.bind(this, "error");
+      this._inflate.on("error", function (err) {
+        if (!leftToInflate) {
+          return;
+        }
+ 
+        emitError(err);
+      });
+      this._filter.on("complete", this._complete.bind(this));
+ 
+      let filterWrite = this._filter.write.bind(this._filter);
+      this._inflate.on("data", function (chunk) {
+        Iif (!leftToInflate) {
+          return;
+        }
+ 
+        Iif (chunk.length > leftToInflate) {
+          chunk = chunk.slice(0, leftToInflate);
+        }
+ 
+        leftToInflate -= chunk.length;
+ 
+        filterWrite(chunk);
+      });
+ 
+      this._inflate.on("end", this._filter.end.bind(this._filter));
+    }
+  }
+  this._inflate.write(data);
+};
+ 
+ParserAsync.prototype._handleMetaData = function (metaData) {
+  this._metaData = metaData;
+  this._bitmapInfo = Object.create(metaData);
+ 
+  this._filter = new FilterAsync(this._bitmapInfo);
+};
+ 
+ParserAsync.prototype._handleTransColor = function (transColor) {
+  this._bitmapInfo.transColor = transColor;
+};
+ 
+ParserAsync.prototype._handlePalette = function (palette) {
+  this._bitmapInfo.palette = palette;
+};
+ 
+ParserAsync.prototype._simpleTransparency = function () {
+  this._metaData.alpha = true;
+};
+ 
+ParserAsync.prototype._headersFinished = function () {
+  // Up until this point, we don't know if we have a tRNS chunk (alpha)
+  // so we can't emit metadata any earlier
+  this.emit("metadata", this._metaData);
+};
+ 
+ParserAsync.prototype._finished = function () {
+  Iif (this.errord) {
+    return;
+  }
+ 
+  if (!this._inflate) {
+    this.emit("error", "No Inflate block");
+  } else {
+    // no more data to inflate
+    this._inflate.end();
+  }
+};
+ 
+ParserAsync.prototype._complete = function (filteredData) {
+  Iif (this.errord) {
+    return;
+  }
+ 
+  let normalisedBitmapData;
+ 
+  try {
+    let bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
+ 
+    normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo);
+    bitmapData = null;
+  } catch (ex) {
+    this._handleError(ex);
+    return;
+  }
+ 
+  this.emit("parsed", normalisedBitmapData);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html b/backend/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html new file mode 100644 index 00000000..6ced1a98 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html @@ -0,0 +1,404 @@ + + + + + + Code coverage report for parser-sync.js + + + + + + + + + +
+
+

All files parser-sync.js

+
+ +
+ 93.33% + Statements + 42/45 +
+ + +
+ 78.57% + Branches + 11/14 +
+ + +
+ 100% + Functions + 8/8 +
+ + +
+ 93.33% + Lines + 42/45 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109  +  +1x +1x +1x +1x +  +  +1x +1x +1x +1x +1x +  +1x +176x +  +  +  +  +  +  +  +13x +  +  +  +  +165x +  +  +  +5x +  +  +  +73x +  +  +  +12x +  +  +  +  +147x +  +  +176x +  +492x +  +  +176x +  +176x +  +  +  +  +  +  +  +  +  +  +176x +176x +  +176x +13x +  +  +  +163x +163x +  +  +163x +36x +  +  +127x +127x +127x +  +  +  +  +162x +  +162x +  +  +  +162x +162x +  +162x +162x +  +162x +  +162x +162x +  +162x +  + 
"use strict";
+ 
+let hasSyncZlib = true;
+let zlib = require("zlib");
+let inflateSync = require("./sync-inflate");
+Iif (!zlib.deflateSync) {
+  hasSyncZlib = false;
+}
+let SyncReader = require("./sync-reader");
+let FilterSync = require("./filter-parse-sync");
+let Parser = require("./parser");
+let bitmapper = require("./bitmapper");
+let formatNormaliser = require("./format-normaliser");
+ 
+module.exports = function (buffer, options) {
+  Iif (!hasSyncZlib) {
+    throw new Error(
+      "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
+    );
+  }
+ 
+  let err;
+  function handleError(_err_) {
+    err = _err_;
+  }
+ 
+  let metaData;
+  function handleMetaData(_metaData_) {
+    metaData = _metaData_;
+  }
+ 
+  function handleTransColor(transColor) {
+    metaData.transColor = transColor;
+  }
+ 
+  function handlePalette(palette) {
+    metaData.palette = palette;
+  }
+ 
+  function handleSimpleTransparency() {
+    metaData.alpha = true;
+  }
+ 
+  let gamma;
+  function handleGamma(_gamma_) {
+    gamma = _gamma_;
+  }
+ 
+  let inflateDataList = [];
+  function handleInflateData(inflatedData) {
+    inflateDataList.push(inflatedData);
+  }
+ 
+  let reader = new SyncReader(buffer);
+ 
+  let parser = new Parser(options, {
+    read: reader.read.bind(reader),
+    error: handleError,
+    metadata: handleMetaData,
+    gamma: handleGamma,
+    palette: handlePalette,
+    transColor: handleTransColor,
+    inflateData: handleInflateData,
+    simpleTransparency: handleSimpleTransparency,
+  });
+ 
+  parser.start();
+  reader.process();
+ 
+  if (err) {
+    throw err;
+  }
+ 
+  //join together the inflate datas
+  let inflateData = Buffer.concat(inflateDataList);
+  inflateDataList.length = 0;
+ 
+  let inflatedData;
+  if (metaData.interlace) {
+    inflatedData = zlib.inflateSync(inflateData);
+  } else {
+    let rowSize =
+      ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1;
+    let imageSize = rowSize * metaData.height;
+    inflatedData = inflateSync(inflateData, {
+      chunkSize: imageSize,
+      maxLength: imageSize,
+    });
+  }
+  inflateData = null;
+ 
+  Iif (!inflatedData || !inflatedData.length) {
+    throw new Error("bad png - invalid inflate data response");
+  }
+ 
+  let unfilteredData = FilterSync.process(inflatedData, metaData);
+  inflateData = null;
+ 
+  let bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData);
+  unfilteredData = null;
+ 
+  let normalisedBitmapData = formatNormaliser(bitmapData, metaData);
+ 
+  metaData.data = normalisedBitmapData;
+  metaData.gamma = gamma || 0;
+ 
+  return metaData;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/parser.js.html b/backend/node_modules/pngjs/coverage/lcov-report/parser.js.html new file mode 100644 index 00000000..efc95044 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/parser.js.html @@ -0,0 +1,950 @@ + + + + + + Code coverage report for parser.js + + + + + + + + + +
+
+

All files parser.js

+
+ +
+ 90.57% + Statements + 144/159 +
+ + +
+ 85.45% + Branches + 47/55 +
+ + +
+ 100% + Functions + 20/20 +
+ + +
+ 90.32% + Lines + 140/155 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291  +  +1x +1x +  +1x +529x +529x +  +529x +529x +529x +  +  +529x +529x +  +529x +529x +529x +529x +529x +529x +529x +  +529x +529x +529x +529x +529x +529x +529x +529x +529x +529x +529x +  +  +1x +529x +  +  +1x +365x +  +365x +2867x +13x +13x +  +  +352x +  +  +1x +  +2461x +  +  +2461x +2461x +2461x +9844x +  +  +  +  +  +2461x +  +  +  +2461x +  +  +  +  +2461x +2461x +  +2461x +2205x +  +  +256x +  +  +  +  +256x +  +  +1x +256x +  +  +1x +2195x +  +  +1x +2195x +2195x +  +  +2195x +4x +4x +  +  +2191x +1855x +  +  +  +1x +351x +  +1x +351x +  +351x +351x +351x +351x +351x +351x +351x +  +  +  +  +  +  +351x +  +  +  +  +  +  +6x +6x +  +345x +4x +4x +  +341x +  +  +  +341x +  +  +  +341x +  +  +  +  +341x +  +341x +  +341x +  +341x +  +  +  +  +  +  +  +  +  +  +  +341x +  +  +1x +135x +  +1x +135x +  +135x +  +  +135x +7350x +  +  +135x +  +135x +  +  +1x +27x +27x +  +1x +27x +  +  +27x +15x +  +  +  +15x +  +  +  +15x +529x +  +15x +  +  +  +  +27x +  +6x +  +27x +6x +  +  +  +  +  +  +27x +  +  +1x +296x +  +1x +296x +296x +  +296x +  +  +1x +1233x +337x +337x +  +1233x +  +1x +1233x +  +1233x +  +  +  +  +  +  +1233x +1233x +  +1233x +173x +  +1060x +  +  +  +1x +336x +  +1x +336x +  +336x +336x +  +336x +173x +  +  + 
"use strict";
+ 
+let constants = require("./constants");
+let CrcCalculator = require("./crc");
+ 
+let Parser = (module.exports = function (options, dependencies) {
+  this._options = options;
+  options.checkCRC = options.checkCRC !== false;
+ 
+  this._hasIHDR = false;
+  this._hasIEND = false;
+  this._emittedHeadersFinished = false;
+ 
+  // input flags/metadata
+  this._palette = [];
+  this._colorType = 0;
+ 
+  this._chunks = {};
+  this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this);
+  this._chunks[constants.TYPE_IEND] = this._handleIEND.bind(this);
+  this._chunks[constants.TYPE_IDAT] = this._handleIDAT.bind(this);
+  this._chunks[constants.TYPE_PLTE] = this._handlePLTE.bind(this);
+  this._chunks[constants.TYPE_tRNS] = this._handleTRNS.bind(this);
+  this._chunks[constants.TYPE_gAMA] = this._handleGAMA.bind(this);
+ 
+  this.read = dependencies.read;
+  this.error = dependencies.error;
+  this.metadata = dependencies.metadata;
+  this.gamma = dependencies.gamma;
+  this.transColor = dependencies.transColor;
+  this.palette = dependencies.palette;
+  this.parsed = dependencies.parsed;
+  this.inflateData = dependencies.inflateData;
+  this.finished = dependencies.finished;
+  this.simpleTransparency = dependencies.simpleTransparency;
+  this.headersFinished = dependencies.headersFinished || function () {};
+});
+ 
+Parser.prototype.start = function () {
+  this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this));
+};
+ 
+Parser.prototype._parseSignature = function (data) {
+  let signature = constants.PNG_SIGNATURE;
+ 
+  for (let i = 0; i < signature.length; i++) {
+    if (data[i] !== signature[i]) {
+      this.error(new Error("Invalid file signature"));
+      return;
+    }
+  }
+  this.read(8, this._parseChunkBegin.bind(this));
+};
+ 
+Parser.prototype._parseChunkBegin = function (data) {
+  // chunk content length
+  let length = data.readUInt32BE(0);
+ 
+  // chunk type
+  let type = data.readUInt32BE(4);
+  let name = "";
+  for (let i = 4; i < 8; i++) {
+    name += String.fromCharCode(data[i]);
+  }
+ 
+  //console.log('chunk ', name, length);
+ 
+  // chunk flags
+  let ancillary = Boolean(data[4] & 0x20); // or critical
+  //    priv = Boolean(data[5] & 0x20), // or public
+  //    safeToCopy = Boolean(data[7] & 0x20); // or unsafe
+ 
+  Iif (!this._hasIHDR && type !== constants.TYPE_IHDR) {
+    this.error(new Error("Expected IHDR on beggining"));
+    return;
+  }
+ 
+  this._crc = new CrcCalculator();
+  this._crc.write(Buffer.from(name));
+ 
+  if (this._chunks[type]) {
+    return this._chunks[type](length);
+  }
+ 
+  Iif (!ancillary) {
+    this.error(new Error("Unsupported critical chunk type " + name));
+    return;
+  }
+ 
+  this.read(length + 4, this._skipChunk.bind(this));
+};
+ 
+Parser.prototype._skipChunk = function (/*data*/) {
+  this.read(8, this._parseChunkBegin.bind(this));
+};
+ 
+Parser.prototype._handleChunkEnd = function () {
+  this.read(4, this._parseChunkEnd.bind(this));
+};
+ 
+Parser.prototype._parseChunkEnd = function (data) {
+  let fileCrc = data.readInt32BE(0);
+  let calcCrc = this._crc.crc32();
+ 
+  // check CRC
+  if (this._options.checkCRC && calcCrc !== fileCrc) {
+    this.error(new Error("Crc error - " + fileCrc + " - " + calcCrc));
+    return;
+  }
+ 
+  if (!this._hasIEND) {
+    this.read(8, this._parseChunkBegin.bind(this));
+  }
+};
+ 
+Parser.prototype._handleIHDR = function (length) {
+  this.read(length, this._parseIHDR.bind(this));
+};
+Parser.prototype._parseIHDR = function (data) {
+  this._crc.write(data);
+ 
+  let width = data.readUInt32BE(0);
+  let height = data.readUInt32BE(4);
+  let depth = data[8];
+  let colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha
+  let compr = data[10];
+  let filter = data[11];
+  let interlace = data[12];
+ 
+  // console.log('    width', width, 'height', height,
+  //     'depth', depth, 'colorType', colorType,
+  //     'compr', compr, 'filter', filter, 'interlace', interlace
+  // );
+ 
+  if (
+    depth !== 8 &&
+    depth !== 4 &&
+    depth !== 2 &&
+    depth !== 1 &&
+    depth !== 16
+  ) {
+    this.error(new Error("Unsupported bit depth " + depth));
+    return;
+  }
+  if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) {
+    this.error(new Error("Unsupported color type"));
+    return;
+  }
+  Iif (compr !== 0) {
+    this.error(new Error("Unsupported compression method"));
+    return;
+  }
+  Iif (filter !== 0) {
+    this.error(new Error("Unsupported filter method"));
+    return;
+  }
+  Iif (interlace !== 0 && interlace !== 1) {
+    this.error(new Error("Unsupported interlace method"));
+    return;
+  }
+ 
+  this._colorType = colorType;
+ 
+  let bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType];
+ 
+  this._hasIHDR = true;
+ 
+  this.metadata({
+    width: width,
+    height: height,
+    depth: depth,
+    interlace: Boolean(interlace),
+    palette: Boolean(colorType & constants.COLORTYPE_PALETTE),
+    color: Boolean(colorType & constants.COLORTYPE_COLOR),
+    alpha: Boolean(colorType & constants.COLORTYPE_ALPHA),
+    bpp: bpp,
+    colorType: colorType,
+  });
+ 
+  this._handleChunkEnd();
+};
+ 
+Parser.prototype._handlePLTE = function (length) {
+  this.read(length, this._parsePLTE.bind(this));
+};
+Parser.prototype._parsePLTE = function (data) {
+  this._crc.write(data);
+ 
+  let entries = Math.floor(data.length / 3);
+  // console.log('Palette:', entries);
+ 
+  for (let i = 0; i < entries; i++) {
+    this._palette.push([data[i * 3], data[i * 3 + 1], data[i * 3 + 2], 0xff]);
+  }
+ 
+  this.palette(this._palette);
+ 
+  this._handleChunkEnd();
+};
+ 
+Parser.prototype._handleTRNS = function (length) {
+  this.simpleTransparency();
+  this.read(length, this._parseTRNS.bind(this));
+};
+Parser.prototype._parseTRNS = function (data) {
+  this._crc.write(data);
+ 
+  // palette
+  if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) {
+    Iif (this._palette.length === 0) {
+      this.error(new Error("Transparency chunk must be after palette"));
+      return;
+    }
+    Iif (data.length > this._palette.length) {
+      this.error(new Error("More transparent colors than palette size"));
+      return;
+    }
+    for (let i = 0; i < data.length; i++) {
+      this._palette[i][3] = data[i];
+    }
+    this.palette(this._palette);
+  }
+ 
+  // for colorType 0 (grayscale) and 2 (rgb)
+  // there might be one gray/color defined as transparent
+  if (this._colorType === constants.COLORTYPE_GRAYSCALE) {
+    // grey, 2 bytes
+    this.transColor([data.readUInt16BE(0)]);
+  }
+  if (this._colorType === constants.COLORTYPE_COLOR) {
+    this.transColor([
+      data.readUInt16BE(0),
+      data.readUInt16BE(2),
+      data.readUInt16BE(4),
+    ]);
+  }
+ 
+  this._handleChunkEnd();
+};
+ 
+Parser.prototype._handleGAMA = function (length) {
+  this.read(length, this._parseGAMA.bind(this));
+};
+Parser.prototype._parseGAMA = function (data) {
+  this._crc.write(data);
+  this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION);
+ 
+  this._handleChunkEnd();
+};
+ 
+Parser.prototype._handleIDAT = function (length) {
+  if (!this._emittedHeadersFinished) {
+    this._emittedHeadersFinished = true;
+    this.headersFinished();
+  }
+  this.read(-length, this._parseIDAT.bind(this, length));
+};
+Parser.prototype._parseIDAT = function (length, data) {
+  this._crc.write(data);
+ 
+  Iif (
+    this._colorType === constants.COLORTYPE_PALETTE_COLOR &&
+    this._palette.length === 0
+  ) {
+    throw new Error("Expected palette not found");
+  }
+ 
+  this.inflateData(data);
+  let leftOverLength = length - data.length;
+ 
+  if (leftOverLength > 0) {
+    this._handleIDAT(leftOverLength);
+  } else {
+    this._handleChunkEnd();
+  }
+};
+ 
+Parser.prototype._handleIEND = function (length) {
+  this.read(length, this._parseIEND.bind(this));
+};
+Parser.prototype._parseIEND = function (data) {
+  this._crc.write(data);
+ 
+  this._hasIEND = true;
+  this._handleChunkEnd();
+ 
+  if (this.finished) {
+    this.finished();
+  }
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/png-sync.js.html b/backend/node_modules/pngjs/coverage/lcov-report/png-sync.js.html new file mode 100644 index 00000000..848f6a6c --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/png-sync.js.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for png-sync.js + + + + + + + + + +
+
+

All files png-sync.js

+
+ +
+ 83.33% + Statements + 5/6 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 83.33% + Lines + 5/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13  +  +1x +1x +  +1x +176x +  +  +1x +  +  + 
"use strict";
+ 
+let parse = require("./parser-sync");
+let pack = require("./packer-sync");
+ 
+exports.read = function (buffer, options) {
+  return parse(buffer, options || {});
+};
+ 
+exports.write = function (png, options) {
+  return pack(png, options);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/png.js.html b/backend/node_modules/pngjs/coverage/lcov-report/png.js.html new file mode 100644 index 00000000..baa88032 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/png.js.html @@ -0,0 +1,662 @@ + + + + + + Code coverage report for png.js + + + + + + + + + +
+
+

All files png.js

+
+ +
+ 54.17% + Statements + 52/96 +
+ + +
+ 41.18% + Branches + 14/34 +
+ + +
+ 56.25% + Functions + 9/16 +
+ + +
+ 56.52% + Lines + 52/92 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195  +  +1x +1x +1x +1x +1x +  +1x +353x +  +353x +  +  +353x +353x +  +353x +  +  +  +  +353x +  +  +  +353x +353x +  +353x +  +353x +353x +353x +353x +353x +  +  +173x +173x +  +  +  +353x +353x +353x +353x +353x +  +1x +  +1x +  +1x +325x +  +  +  +  +325x +  +325x +  +  +  +325x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +412x +412x +  +  +1x +175x +  +  +1x +174x +174x +  +174x +  +  +1x +149x +  +  +1x +378x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  + 
"use strict";
+ 
+let util = require("util");
+let Stream = require("stream");
+let Parser = require("./parser-async");
+let Packer = require("./packer-async");
+let PNGSync = require("./png-sync");
+ 
+let PNG = (exports.PNG = function (options) {
+  Stream.call(this);
+ 
+  options = options || {}; // eslint-disable-line no-param-reassign
+ 
+  // coerce pixel dimensions to integers (also coerces undefined -> 0):
+  this.width = options.width | 0;
+  this.height = options.height | 0;
+ 
+  this.data =
+    this.width > 0 && this.height > 0
+      ? Buffer.alloc(4 * this.width * this.height)
+      : null;
+ 
+  Iif (options.fill && this.data) {
+    this.data.fill(0);
+  }
+ 
+  this.gamma = 0;
+  this.readable = this.writable = true;
+ 
+  this._parser = new Parser(options);
+ 
+  this._parser.on("error", this.emit.bind(this, "error"));
+  this._parser.on("close", this._handleClose.bind(this));
+  this._parser.on("metadata", this._metadata.bind(this));
+  this._parser.on("gamma", this._gamma.bind(this));
+  this._parser.on(
+    "parsed",
+    function (data) {
+      this.data = data;
+      this.emit("parsed", data);
+    }.bind(this)
+  );
+ 
+  this._packer = new Packer(options);
+  this._packer.on("data", this.emit.bind(this, "data"));
+  this._packer.on("end", this.emit.bind(this, "end"));
+  this._parser.on("close", this._handleClose.bind(this));
+  this._packer.on("error", this.emit.bind(this, "error"));
+});
+util.inherits(PNG, Stream);
+ 
+PNG.sync = PNGSync;
+ 
+PNG.prototype.pack = function () {
+  Iif (!this.data || !this.data.length) {
+    this.emit("error", "No data provided");
+    return this;
+  }
+ 
+  process.nextTick(
+    function () {
+      this._packer.pack(this.data, this.width, this.height, this.gamma);
+    }.bind(this)
+  );
+ 
+  return this;
+};
+ 
+PNG.prototype.parse = function (data, callback) {
+  if (callback) {
+    let onParsed, onError;
+ 
+    onParsed = function (parsedData) {
+      this.removeListener("error", onError);
+ 
+      this.data = parsedData;
+      callback(null, this);
+    }.bind(this);
+ 
+    onError = function (err) {
+      this.removeListener("parsed", onParsed);
+ 
+      callback(err, null);
+    }.bind(this);
+ 
+    this.once("parsed", onParsed);
+    this.once("error", onError);
+  }
+ 
+  this.end(data);
+  return this;
+};
+ 
+PNG.prototype.write = function (data) {
+  this._parser.write(data);
+  return true;
+};
+ 
+PNG.prototype.end = function (data) {
+  this._parser.end(data);
+};
+ 
+PNG.prototype._metadata = function (metadata) {
+  this.width = metadata.width;
+  this.height = metadata.height;
+ 
+  this.emit("metadata", metadata);
+};
+ 
+PNG.prototype._gamma = function (gamma) {
+  this.gamma = gamma;
+};
+ 
+PNG.prototype._handleClose = function () {
+  Iif (!this._parser.writable && !this._packer.readable) {
+    this.emit("close");
+  }
+};
+ 
+PNG.bitblt = function (src, dst, srcX, srcY, width, height, deltaX, deltaY) {
+  // eslint-disable-line max-params
+  // coerce pixel dimensions to integers (also coerces undefined -> 0):
+  /* eslint-disable no-param-reassign */
+  srcX |= 0;
+  srcY |= 0;
+  width |= 0;
+  height |= 0;
+  deltaX |= 0;
+  deltaY |= 0;
+  /* eslint-enable no-param-reassign */
+ 
+  if (
+    srcX > src.width ||
+    srcY > src.height ||
+    srcX + width > src.width ||
+    srcY + height > src.height
+  ) {
+    throw new Error("bitblt reading outside image");
+  }
+ 
+  if (
+    deltaX > dst.width ||
+    deltaY > dst.height ||
+    deltaX + width > dst.width ||
+    deltaY + height > dst.height
+  ) {
+    throw new Error("bitblt writing outside image");
+  }
+ 
+  for (let y = 0; y < height; y++) {
+    src.data.copy(
+      dst.data,
+      ((deltaY + y) * dst.width + deltaX) << 2,
+      ((srcY + y) * src.width + srcX) << 2,
+      ((srcY + y) * src.width + srcX + width) << 2
+    );
+  }
+};
+ 
+PNG.prototype.bitblt = function (
+  dst,
+  srcX,
+  srcY,
+  width,
+  height,
+  deltaX,
+  deltaY
+) {
+  // eslint-disable-line max-params
+ 
+  PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
+  return this;
+};
+ 
+PNG.adjustGamma = function (src) {
+  if (src.gamma) {
+    for (let y = 0; y < src.height; y++) {
+      for (let x = 0; x < src.width; x++) {
+        let idx = (src.width * y + x) << 2;
+ 
+        for (let i = 0; i < 3; i++) {
+          let sample = src.data[idx + i] / 255;
+          sample = Math.pow(sample, 1 / 2.2 / src.gamma);
+          src.data[idx + i] = Math.round(sample * 255);
+        }
+      }
+    }
+    src.gamma = 0;
+  }
+};
+ 
+PNG.prototype.adjustGamma = function () {
+  PNG.adjustGamma(this);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/prettify.css b/backend/node_modules/pngjs/coverage/lcov-report/prettify.css new file mode 100644 index 00000000..006492ca --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/prettify.css @@ -0,0 +1,101 @@ +.pln { + color: #000; +} +@media screen { + .str { + color: #080; + } + .kwd { + color: #008; + } + .com { + color: #800; + } + .typ { + color: #606; + } + .lit { + color: #066; + } + .pun, + .opn, + .clo { + color: #660; + } + .tag { + color: #008; + } + .atn { + color: #606; + } + .atv { + color: #080; + } + .dec, + .var { + color: #606; + } + .fun { + color: red; + } +} +@media print, projection { + .str { + color: #060; + } + .kwd { + color: #006; + font-weight: bold; + } + .com { + color: #600; + font-style: italic; + } + .typ { + color: #404; + font-weight: bold; + } + .lit { + color: #044; + } + .pun, + .opn, + .clo { + color: #440; + } + .tag { + color: #006; + font-weight: bold; + } + .atn { + color: #404; + } + .atv { + color: #060; + } +} +pre.prettyprint { + padding: 2px; + border: 1px solid #888; +} +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} +li.L0, +li.L1, +li.L2, +li.L3, +li.L5, +li.L6, +li.L7, +li.L8 { + list-style-type: none; +} +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { + background: #eee; +} diff --git a/backend/node_modules/pngjs/coverage/lcov-report/prettify.js b/backend/node_modules/pngjs/coverage/lcov-report/prettify.js new file mode 100644 index 00000000..7c0a2fe8 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/prettify.js @@ -0,0 +1,1007 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION = true; +(function () { + var h = ["break,continue,do,else,for,if,return,while"]; + var u = [ + h, + "auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile", + ]; + var p = [ + u, + "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof", + ]; + var l = [ + p, + "alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where", + ]; + var x = [ + p, + "abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient", + ]; + var R = [ + x, + "as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var", + ]; + var r = + "all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes"; + var w = [ + p, + "debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN", + ]; + var s = + "caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"; + var I = [ + h, + "and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None", + ]; + var f = [ + h, + "alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END", + ]; + var H = [h, "case,done,elif,esac,eval,fi,function,in,local,set,then,until"]; + var A = [l, R, w, s + I, f, H]; + var e = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/; + var C = "str"; + var z = "kwd"; + var j = "com"; + var O = "typ"; + var G = "lit"; + var L = "pun"; + var F = "pln"; + var m = "tag"; + var E = "dec"; + var J = "src"; + var P = "atn"; + var n = "atv"; + var N = "nocode"; + var M = + "(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*"; + function k(Z) { + var ad = 0; + var S = false; + var ac = false; + for (var V = 0, U = Z.length; V < U; ++V) { + var ae = Z[V]; + if (ae.ignoreCase) { + ac = true; + } else { + if ( + /[a-z]/i.test( + ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, "") + ) + ) { + S = true; + ac = false; + break; + } + } + } + var Y = { b: 8, t: 9, n: 10, v: 11, f: 12, r: 13 }; + function ab(ah) { + var ag = ah.charCodeAt(0); + if (ag !== 92) { + return ag; + } + var af = ah.charAt(1); + ag = Y[af]; + if (ag) { + return ag; + } else { + if ("0" <= af && af <= "7") { + return parseInt(ah.substring(1), 8); + } else { + if (af === "u" || af === "x") { + return parseInt(ah.substring(2), 16); + } else { + return ah.charCodeAt(1); + } + } + } + } + function T(af) { + if (af < 32) { + return (af < 16 ? "\\x0" : "\\x") + af.toString(16); + } + var ag = String.fromCharCode(af); + if (ag === "\\" || ag === "-" || ag === "[" || ag === "]") { + ag = "\\" + ag; + } + return ag; + } + function X(am) { + var aq = am + .substring(1, am.length - 1) + .match( + new RegExp( + "\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]", + "g" + ) + ); + var ak = []; + var af = []; + var ao = aq[0] === "^"; + for (var ar = ao ? 1 : 0, aj = aq.length; ar < aj; ++ar) { + var ah = aq[ar]; + if (/\\[bdsw]/i.test(ah)) { + ak.push(ah); + } else { + var ag = ab(ah); + var al; + if (ar + 2 < aj && "-" === aq[ar + 1]) { + al = ab(aq[ar + 2]); + ar += 2; + } else { + al = ag; + } + af.push([ag, al]); + if (!(al < 65 || ag > 122)) { + if (!(al < 65 || ag > 90)) { + af.push([Math.max(65, ag) | 32, Math.min(al, 90) | 32]); + } + if (!(al < 97 || ag > 122)) { + af.push([Math.max(97, ag) & ~32, Math.min(al, 122) & ~32]); + } + } + } + } + af.sort(function (av, au) { + return av[0] - au[0] || au[1] - av[1]; + }); + var ai = []; + var ap = [NaN, NaN]; + for (var ar = 0; ar < af.length; ++ar) { + var at = af[ar]; + if (at[0] <= ap[1] + 1) { + ap[1] = Math.max(ap[1], at[1]); + } else { + ai.push((ap = at)); + } + } + var an = ["["]; + if (ao) { + an.push("^"); + } + an.push.apply(an, ak); + for (var ar = 0; ar < ai.length; ++ar) { + var at = ai[ar]; + an.push(T(at[0])); + if (at[1] > at[0]) { + if (at[1] + 1 > at[0]) { + an.push("-"); + } + an.push(T(at[1])); + } + } + an.push("]"); + return an.join(""); + } + function W(al) { + var aj = al.source.match( + new RegExp( + "(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)", + "g" + ) + ); + var ah = aj.length; + var an = []; + for (var ak = 0, am = 0; ak < ah; ++ak) { + var ag = aj[ak]; + if (ag === "(") { + ++am; + } else { + if ("\\" === ag.charAt(0)) { + var af = +ag.substring(1); + if (af && af <= am) { + an[af] = -1; + } + } + } + } + for (var ak = 1; ak < an.length; ++ak) { + if (-1 === an[ak]) { + an[ak] = ++ad; + } + } + for (var ak = 0, am = 0; ak < ah; ++ak) { + var ag = aj[ak]; + if (ag === "(") { + ++am; + if (an[am] === undefined) { + aj[ak] = "(?:"; + } + } else { + if ("\\" === ag.charAt(0)) { + var af = +ag.substring(1); + if (af && af <= am) { + aj[ak] = "\\" + an[am]; + } + } + } + } + for (var ak = 0, am = 0; ak < ah; ++ak) { + if ("^" === aj[ak] && "^" !== aj[ak + 1]) { + aj[ak] = ""; + } + } + if (al.ignoreCase && S) { + for (var ak = 0; ak < ah; ++ak) { + var ag = aj[ak]; + var ai = ag.charAt(0); + if (ag.length >= 2 && ai === "[") { + aj[ak] = X(ag); + } else { + if (ai !== "\\") { + aj[ak] = ag.replace(/[a-zA-Z]/g, function (ao) { + var ap = ao.charCodeAt(0); + return "[" + String.fromCharCode(ap & ~32, ap | 32) + "]"; + }); + } + } + } + } + return aj.join(""); + } + var aa = []; + for (var V = 0, U = Z.length; V < U; ++V) { + var ae = Z[V]; + if (ae.global || ae.multiline) { + throw new Error("" + ae); + } + aa.push("(?:" + W(ae) + ")"); + } + return new RegExp(aa.join("|"), ac ? "gi" : "g"); + } + function a(V) { + var U = /(?:^|\s)nocode(?:\s|$)/; + var X = []; + var T = 0; + var Z = []; + var W = 0; + var S; + if (V.currentStyle) { + S = V.currentStyle.whiteSpace; + } else { + if (window.getComputedStyle) { + S = document.defaultView + .getComputedStyle(V, null) + .getPropertyValue("white-space"); + } + } + var Y = S && "pre" === S.substring(0, 3); + function aa(ab) { + switch (ab.nodeType) { + case 1: + if (U.test(ab.className)) { + return; + } + for (var ae = ab.firstChild; ae; ae = ae.nextSibling) { + aa(ae); + } + var ad = ab.nodeName; + if ("BR" === ad || "LI" === ad) { + X[W] = "\n"; + Z[W << 1] = T++; + Z[(W++ << 1) | 1] = ab; + } + break; + case 3: + case 4: + var ac = ab.nodeValue; + if (ac.length) { + if (!Y) { + ac = ac.replace(/[ \t\r\n]+/g, " "); + } else { + ac = ac.replace(/\r\n?/g, "\n"); + } + X[W] = ac; + Z[W << 1] = T; + T += ac.length; + Z[(W++ << 1) | 1] = ab; + } + break; + } + } + aa(V); + return { sourceCode: X.join("").replace(/\n$/, ""), spans: Z }; + } + function B(S, U, W, T) { + if (!U) { + return; + } + var V = { sourceCode: U, basePos: S }; + W(V); + T.push.apply(T, V.decorations); + } + var v = /\S/; + function o(S) { + var V = undefined; + for (var U = S.firstChild; U; U = U.nextSibling) { + var T = U.nodeType; + V = T === 1 ? (V ? S : U) : T === 3 ? (v.test(U.nodeValue) ? S : V) : V; + } + return V === S ? undefined : V; + } + function g(U, T) { + var S = {}; + var V; + (function () { + var ad = U.concat(T); + var ah = []; + var ag = {}; + for (var ab = 0, Z = ad.length; ab < Z; ++ab) { + var Y = ad[ab]; + var ac = Y[3]; + if (ac) { + for (var ae = ac.length; --ae >= 0; ) { + S[ac.charAt(ae)] = Y; + } + } + var af = Y[1]; + var aa = "" + af; + if (!ag.hasOwnProperty(aa)) { + ah.push(af); + ag[aa] = null; + } + } + ah.push(/[\0-\uffff]/); + V = k(ah); + })(); + var X = T.length; + var W = function (ah) { + var Z = ah.sourceCode, + Y = ah.basePos; + var ad = [Y, F]; + var af = 0; + var an = Z.match(V) || []; + var aj = {}; + for (var ae = 0, aq = an.length; ae < aq; ++ae) { + var ag = an[ae]; + var ap = aj[ag]; + var ai = void 0; + var am; + if (typeof ap === "string") { + am = false; + } else { + var aa = S[ag.charAt(0)]; + if (aa) { + ai = ag.match(aa[1]); + ap = aa[0]; + } else { + for (var ao = 0; ao < X; ++ao) { + aa = T[ao]; + ai = ag.match(aa[1]); + if (ai) { + ap = aa[0]; + break; + } + } + if (!ai) { + ap = F; + } + } + am = ap.length >= 5 && "lang-" === ap.substring(0, 5); + if (am && !(ai && typeof ai[1] === "string")) { + am = false; + ap = J; + } + if (!am) { + aj[ag] = ap; + } + } + var ab = af; + af += ag.length; + if (!am) { + ad.push(Y + ab, ap); + } else { + var al = ai[1]; + var ak = ag.indexOf(al); + var ac = ak + al.length; + if (ai[2]) { + ac = ag.length - ai[2].length; + ak = ac - al.length; + } + var ar = ap.substring(5); + B(Y + ab, ag.substring(0, ak), W, ad); + B(Y + ab + ak, al, q(ar, al), ad); + B(Y + ab + ac, ag.substring(ac), W, ad); + } + } + ah.decorations = ad; + }; + return W; + } + function i(T) { + var W = [], + S = []; + if (T.tripleQuotedStrings) { + W.push([ + C, + /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, + null, + "'\"", + ]); + } else { + if (T.multiLineStrings) { + W.push([ + C, + /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, + null, + "'\"`", + ]); + } else { + W.push([ + C, + /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, + null, + "\"'", + ]); + } + } + if (T.verbatimStrings) { + S.push([C, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]); + } + var Y = T.hashComments; + if (Y) { + if (T.cStyleComments) { + if (Y > 1) { + W.push([j, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, "#"]); + } else { + W.push([ + j, + /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/, + null, + "#", + ]); + } + S.push([ + C, + /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/, + null, + ]); + } else { + W.push([j, /^#[^\r\n]*/, null, "#"]); + } + } + if (T.cStyleComments) { + S.push([j, /^\/\/[^\r\n]*/, null]); + S.push([j, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); + } + if (T.regexLiterals) { + var X = + "/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/"; + S.push(["lang-regex", new RegExp("^" + M + "(" + X + ")")]); + } + var V = T.types; + if (V) { + S.push([O, V]); + } + var U = ("" + T.keywords).replace(/^ | $/g, ""); + if (U.length) { + S.push([ + z, + new RegExp("^(?:" + U.replace(/[\s,]+/g, "|") + ")\\b"), + null, + ]); + } + W.push([F, /^\s+/, null, " \r\n\t\xA0"]); + S.push( + [G, /^@[a-z_$][a-z_$@0-9]*/i, null], + [O, /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null], + [F, /^[a-z_$][a-z_$@0-9]*/i, null], + [ + G, + new RegExp( + "^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*", + "i" + ), + null, + "0123456789", + ], + [F, /^\\[\s\S]?/, null], + [L, /^.[^\s\w\.$@\'\"\`\/\#\\]*/, null] + ); + return g(W, S); + } + var K = i({ + keywords: A, + hashComments: true, + cStyleComments: true, + multiLineStrings: true, + regexLiterals: true, + }); + function Q(V, ag) { + var U = /(?:^|\s)nocode(?:\s|$)/; + var ab = /\r\n?|\n/; + var ac = V.ownerDocument; + var S; + if (V.currentStyle) { + S = V.currentStyle.whiteSpace; + } else { + if (window.getComputedStyle) { + S = ac.defaultView + .getComputedStyle(V, null) + .getPropertyValue("white-space"); + } + } + var Z = S && "pre" === S.substring(0, 3); + var af = ac.createElement("LI"); + while (V.firstChild) { + af.appendChild(V.firstChild); + } + var W = [af]; + function ae(al) { + switch (al.nodeType) { + case 1: + if (U.test(al.className)) { + break; + } + if ("BR" === al.nodeName) { + ad(al); + if (al.parentNode) { + al.parentNode.removeChild(al); + } + } else { + for (var an = al.firstChild; an; an = an.nextSibling) { + ae(an); + } + } + break; + case 3: + case 4: + if (Z) { + var am = al.nodeValue; + var aj = am.match(ab); + if (aj) { + var ai = am.substring(0, aj.index); + al.nodeValue = ai; + var ah = am.substring(aj.index + aj[0].length); + if (ah) { + var ak = al.parentNode; + ak.insertBefore(ac.createTextNode(ah), al.nextSibling); + } + ad(al); + if (!ai) { + al.parentNode.removeChild(al); + } + } + } + break; + } + } + function ad(ak) { + while (!ak.nextSibling) { + ak = ak.parentNode; + if (!ak) { + return; + } + } + function ai(al, ar) { + var aq = ar ? al.cloneNode(false) : al; + var ao = al.parentNode; + if (ao) { + var ap = ai(ao, 1); + var an = al.nextSibling; + ap.appendChild(aq); + for (var am = an; am; am = an) { + an = am.nextSibling; + ap.appendChild(am); + } + } + return aq; + } + var ah = ai(ak.nextSibling, 0); + for (var aj; (aj = ah.parentNode) && aj.nodeType === 1; ) { + ah = aj; + } + W.push(ah); + } + for (var Y = 0; Y < W.length; ++Y) { + ae(W[Y]); + } + if (ag === (ag | 0)) { + W[0].setAttribute("value", ag); + } + var aa = ac.createElement("OL"); + aa.className = "linenums"; + var X = Math.max(0, (ag - 1) | 0) || 0; + for (var Y = 0, T = W.length; Y < T; ++Y) { + af = W[Y]; + af.className = "L" + ((Y + X) % 10); + if (!af.firstChild) { + af.appendChild(ac.createTextNode("\xA0")); + } + aa.appendChild(af); + } + V.appendChild(aa); + } + function D(ac) { + var aj = /\bMSIE\b/.test(navigator.userAgent); + var am = /\n/g; + var al = ac.sourceCode; + var an = al.length; + var V = 0; + var aa = ac.spans; + var T = aa.length; + var ah = 0; + var X = ac.decorations; + var Y = X.length; + var Z = 0; + X[Y] = an; + var ar, aq; + for (aq = ar = 0; aq < Y; ) { + if (X[aq] !== X[aq + 2]) { + X[ar++] = X[aq++]; + X[ar++] = X[aq++]; + } else { + aq += 2; + } + } + Y = ar; + for (aq = ar = 0; aq < Y; ) { + var at = X[aq]; + var ab = X[aq + 1]; + var W = aq + 2; + while (W + 2 <= Y && X[W + 1] === ab) { + W += 2; + } + X[ar++] = at; + X[ar++] = ab; + aq = W; + } + Y = X.length = ar; + var ae = null; + while (ah < T) { + var af = aa[ah]; + var S = aa[ah + 2] || an; + var ag = X[Z]; + var ap = X[Z + 2] || an; + var W = Math.min(S, ap); + var ak = aa[ah + 1]; + var U; + if (ak.nodeType !== 1 && (U = al.substring(V, W))) { + if (aj) { + U = U.replace(am, "\r"); + } + ak.nodeValue = U; + var ai = ak.ownerDocument; + var ao = ai.createElement("SPAN"); + ao.className = X[Z + 1]; + var ad = ak.parentNode; + ad.replaceChild(ao, ak); + ao.appendChild(ak); + if (V < S) { + aa[ah + 1] = ak = ai.createTextNode(al.substring(W, S)); + ad.insertBefore(ak, ao.nextSibling); + } + } + V = W; + if (V >= S) { + ah += 2; + } + if (V >= ap) { + Z += 2; + } + } + } + var t = {}; + function c(U, V) { + for (var S = V.length; --S >= 0; ) { + var T = V[S]; + if (!t.hasOwnProperty(T)) { + t[T] = U; + } else { + if (window.console) { + console.warn("cannot override language handler %s", T); + } + } + } + } + function q(T, S) { + if (!(T && t.hasOwnProperty(T))) { + T = /^\s*]*(?:>|$)/], + [j, /^<\!--[\s\S]*?(?:-\->|$)/], + ["lang-", /^<\?([\s\S]+?)(?:\?>|$)/], + ["lang-", /^<%([\s\S]+?)(?:%>|$)/], + [L, /^(?:<[%?]|[%?]>)/], + ["lang-", /^]*>([\s\S]+?)<\/xmp\b[^>]*>/i], + ["lang-js", /^]*>([\s\S]*?)(<\/script\b[^>]*>)/i], + ["lang-css", /^]*>([\s\S]*?)(<\/style\b[^>]*>)/i], + ["lang-in.tag", /^(<\/?[a-z][^<>]*>)/i], + ] + ), + ["default-markup", "htm", "html", "mxml", "xhtml", "xml", "xsl"] + ); + c( + g( + [ + [F, /^[\s]+/, null, " \t\r\n"], + [n, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, "\"'"], + ], + [ + [m, /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i], + [P, /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i], + ["lang-uq.val", /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/], + [L, /^[=<>\/]+/], + ["lang-js", /^on\w+\s*=\s*\"([^\"]+)\"/i], + ["lang-js", /^on\w+\s*=\s*\'([^\']+)\'/i], + ["lang-js", /^on\w+\s*=\s*([^\"\'>\s]+)/i], + ["lang-css", /^style\s*=\s*\"([^\"]+)\"/i], + ["lang-css", /^style\s*=\s*\'([^\']+)\'/i], + ["lang-css", /^style\s*=\s*([^\"\'>\s]+)/i], + ] + ), + ["in.tag"] + ); + c(g([], [[n, /^[\s\S]+/]]), ["uq.val"]); + c(i({ keywords: l, hashComments: true, cStyleComments: true, types: e }), [ + "c", + "cc", + "cpp", + "cxx", + "cyc", + "m", + ]); + c(i({ keywords: "null,true,false" }), ["json"]); + c( + i({ + keywords: R, + hashComments: true, + cStyleComments: true, + verbatimStrings: true, + types: e, + }), + ["cs"] + ); + c(i({ keywords: x, cStyleComments: true }), ["java"]); + c(i({ keywords: H, hashComments: true, multiLineStrings: true }), [ + "bsh", + "csh", + "sh", + ]); + c( + i({ + keywords: I, + hashComments: true, + multiLineStrings: true, + tripleQuotedStrings: true, + }), + ["cv", "py"] + ); + c( + i({ + keywords: s, + hashComments: true, + multiLineStrings: true, + regexLiterals: true, + }), + ["perl", "pl", "pm"] + ); + c( + i({ + keywords: f, + hashComments: true, + multiLineStrings: true, + regexLiterals: true, + }), + ["rb"] + ); + c(i({ keywords: w, cStyleComments: true, regexLiterals: true }), ["js"]); + c( + i({ + keywords: r, + hashComments: 3, + cStyleComments: true, + multilineStrings: true, + tripleQuotedStrings: true, + regexLiterals: true, + }), + ["coffee"] + ); + c(g([], [[C, /^[\s\S]+/]]), ["regex"]); + function d(V) { + var U = V.langExtension; + try { + var S = a(V.sourceNode); + var T = S.sourceCode; + V.sourceCode = T; + V.spans = S.spans; + V.basePos = 0; + q(U, T)(V); + D(V); + } catch (W) { + if ("console" in window) { + console.log(W && W.stack ? W.stack : W); + } + } + } + function y(W, V, U) { + var S = document.createElement("PRE"); + S.innerHTML = W; + if (U) { + Q(S, U); + } + var T = { langExtension: V, numberLines: U, sourceNode: S }; + d(T); + return S.innerHTML; + } + function b(ad) { + function Y(af) { + return document.getElementsByTagName(af); + } + var ac = [Y("pre"), Y("code"), Y("xmp")]; + var T = []; + for (var aa = 0; aa < ac.length; ++aa) { + for (var Z = 0, V = ac[aa].length; Z < V; ++Z) { + T.push(ac[aa][Z]); + } + } + ac = null; + var W = Date; + if (!W.now) { + W = { + now: function () { + return +new Date(); + }, + }; + } + var X = 0; + var S; + var ab = /\blang(?:uage)?-([\w.]+)(?!\S)/; + var ae = /\bprettyprint\b/; + function U() { + var ag = window.PR_SHOULD_USE_CONTINUATION ? W.now() + 250 : Infinity; + for (; X < T.length && W.now() < ag; X++) { + var aj = T[X]; + var ai = aj.className; + if (ai.indexOf("prettyprint") >= 0) { + var ah = ai.match(ab); + var am; + if (!ah && (am = o(aj)) && "CODE" === am.tagName) { + ah = am.className.match(ab); + } + if (ah) { + ah = ah[1]; + } + var al = false; + for (var ak = aj.parentNode; ak; ak = ak.parentNode) { + if ( + (ak.tagName === "pre" || + ak.tagName === "code" || + ak.tagName === "xmp") && + ak.className && + ak.className.indexOf("prettyprint") >= 0 + ) { + al = true; + break; + } + } + if (!al) { + var af = aj.className.match(/\blinenums\b(?::(\d+))?/); + af = af ? (af[1] && af[1].length ? +af[1] : true) : false; + if (af) { + Q(aj, af); + } + S = { langExtension: ah, sourceNode: aj, numberLines: af }; + d(S); + } + } + } + if (X < T.length) { + setTimeout(U, 250); + } else { + if (ad) { + ad(); + } + } + } + U(); + } + window.prettyPrintOne = y; + window.prettyPrint = b; + window.PR = { + createSimpleLexer: g, + registerLangHandler: c, + sourceDecorator: i, + PR_ATTRIB_NAME: P, + PR_ATTRIB_VALUE: n, + PR_COMMENT: j, + PR_DECLARATION: E, + PR_KEYWORD: z, + PR_LITERAL: G, + PR_NOCODE: N, + PR_PLAIN: F, + PR_PUNCTUATION: L, + PR_SOURCE: J, + PR_STRING: C, + PR_TAG: m, + PR_TYPE: O, + }; +})(); +PR.registerLangHandler( + PR.createSimpleLexer( + [], + [ + [PR.PR_DECLARATION, /^]*(?:>|$)/], + [PR.PR_COMMENT, /^<\!--[\s\S]*?(?:-\->|$)/], + [PR.PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/], + ["lang-", /^<\?([\s\S]+?)(?:\?>|$)/], + ["lang-", /^<%([\s\S]+?)(?:%>|$)/], + ["lang-", /^]*>([\s\S]+?)<\/xmp\b[^>]*>/i], + [ + "lang-handlebars", + /^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i, + ], + ["lang-js", /^]*>([\s\S]*?)(<\/script\b[^>]*>)/i], + ["lang-css", /^]*>([\s\S]*?)(<\/style\b[^>]*>)/i], + ["lang-in.tag", /^(<\/?[a-z][^<>]*>)/i], + [PR.PR_DECLARATION, /^{{[#^>/]?\s*[\w.][^}]*}}/], + [PR.PR_DECLARATION, /^{{&?\s*[\w.][^}]*}}/], + [PR.PR_DECLARATION, /^{{{>?\s*[\w.][^}]*}}}/], + [PR.PR_COMMENT, /^{{![^}]*}}/], + ] + ), + ["handlebars", "hbs"] +); +PR.registerLangHandler( + PR.createSimpleLexer( + [[PR.PR_PLAIN, /^[ \t\r\n\f]+/, null, " \t\r\n\f"]], + [ + [ + PR.PR_STRING, + /^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/, + null, + ], + [ + PR.PR_STRING, + /^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/, + null, + ], + ["lang-css-str", /^url\(([^\)\"\']*)\)/i], + [ + PR.PR_KEYWORD, + /^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i, + null, + ], + [ + "lang-css-kw", + /^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i, + ], + [PR.PR_COMMENT, /^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//], + [PR.PR_COMMENT, /^(?:)/], + [PR.PR_LITERAL, /^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i], + [PR.PR_LITERAL, /^#(?:[0-9a-f]{3}){1,2}/i], + [ + PR.PR_PLAIN, + /^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i, + ], + [PR.PR_PUNCTUATION, /^[^\s\w\'\"]+/], + ] + ), + ["css"] +); +PR.registerLangHandler( + PR.createSimpleLexer( + [], + [ + [ + PR.PR_KEYWORD, + /^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i, + ], + ] + ), + ["css-kw"] +); +PR.registerLangHandler( + PR.createSimpleLexer([], [[PR.PR_STRING, /^[^\)\"\']+/]]), + ["css-str"] +); diff --git a/backend/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png b/backend/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 00000000..03f704a6 Binary files /dev/null and b/backend/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/backend/node_modules/pngjs/coverage/lcov-report/sorter.js b/backend/node_modules/pngjs/coverage/lcov-report/sorter.js new file mode 100644 index 00000000..418a5b1b --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/sorter.js @@ -0,0 +1,169 @@ +/* eslint-disable */ +var addSorting = (function () { + "use strict"; + var cols, + currentSort = { + index: 0, + desc: false, + }; + + // returns the summary table element + function getTable() { + return document.querySelector(".coverage-summary"); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector("thead tr"); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector("tbody"); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll("th")[n]; + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll("th"), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute("data-col"), + sortable: !colNode.getAttribute("data-nosort"), + type: colNode.getAttribute("data-type") || "string", + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === "number"; + colNode.innerHTML = colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll("td"), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute("data-value"); + if (col.type === "number") { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll("tr"), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector(".coverage-summary tbody"), + rowNodes = tableBody.querySelectorAll("tr"), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, "").replace(/ sorted-desc$/, ""); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? " sorted-desc" + : " sorted"; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector(".sorter").parentElement; + if (el.addEventListener) { + el.addEventListener("click", ithSorter(i)); + } else { + el.attachEvent("onclick", ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener("load", addSorting); diff --git a/backend/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html b/backend/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html new file mode 100644 index 00000000..9ae5a148 --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html @@ -0,0 +1,584 @@ + + + + + + Code coverage report for sync-inflate.js + + + + + + + + + +
+
+

All files sync-inflate.js

+
+ +
+ 75.31% + Statements + 61/81 +
+ + +
+ 62% + Branches + 31/50 +
+ + +
+ 87.5% + Functions + 7/8 +
+ + +
+ 75.31% + Lines + 61/81 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169  +  +1x +1x +1x +  +1x +  +  +127x +  +  +  +127x +9x +  +  +127x +  +  +127x +127x +  +127x +127x +  +  +  +  +  +  +  +  +126x +  +  +  +  +126x +  +  +  +126x +126x +  +  +1x +127x +  +  +  +127x +  +127x +127x +127x +127x +  +127x +127x +  +  +127x +1x +  +  +  +126x +  +  +  +126x +126x +  +126x +126x +126x +  +126x +9x +  +  +126x +126x +126x +  +126x +126x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +127x +  +127x +127x +  +  +  +  +  +  +  +  +  +127x +  +  +127x +1x +  +  +126x +  +  +  +  +  +  +  +  +126x +126x +  +126x +  +  +1x +  +  +127x +  +  +127x +  +  +  +127x +127x +  +  +  +127x +  +  +  +127x +  +  +1x +1x +1x +1x + 
"use strict";
+ 
+let assert = require("assert").ok;
+let zlib = require("zlib");
+let util = require("util");
+ 
+let kMaxLength = require("buffer").kMaxLength;
+ 
+function Inflate(opts) {
+  Iif (!(this instanceof Inflate)) {
+    return new Inflate(opts);
+  }
+ 
+  if (opts && opts.chunkSize < zlib.Z_MIN_CHUNK) {
+    opts.chunkSize = zlib.Z_MIN_CHUNK;
+  }
+ 
+  zlib.Inflate.call(this, opts);
+ 
+  // Node 8 --> 9 compatibility check
+  this._offset = this._offset === undefined ? this._outOffset : this._offset;
+  this._buffer = this._buffer || this._outBuffer;
+ 
+  Eif (opts && opts.maxLength != null) {
+    this._maxLength = opts.maxLength;
+  }
+}
+ 
+function createInflate(opts) {
+  return new Inflate(opts);
+}
+ 
+function _close(engine, callback) {
+  Iif (callback) {
+    process.nextTick(callback);
+  }
+ 
+  // Caller may invoke .close after a zlib error (which will null _handle).
+  Iif (!engine._handle) {
+    return;
+  }
+ 
+  engine._handle.close();
+  engine._handle = null;
+}
+ 
+Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) {
+  Iif (typeof asyncCb === "function") {
+    return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
+  }
+ 
+  let self = this;
+ 
+  let availInBefore = chunk && chunk.length;
+  let availOutBefore = this._chunkSize - this._offset;
+  let leftToInflate = this._maxLength;
+  let inOff = 0;
+ 
+  let buffers = [];
+  let nread = 0;
+ 
+  let error;
+  this.on("error", function (err) {
+    error = err;
+  });
+ 
+  function handleChunk(availInAfter, availOutAfter) {
+    Iif (self._hadError) {
+      return;
+    }
+ 
+    let have = availOutBefore - availOutAfter;
+    assert(have >= 0, "have should not go down");
+ 
+    Eif (have > 0) {
+      let out = self._buffer.slice(self._offset, self._offset + have);
+      self._offset += have;
+ 
+      if (out.length > leftToInflate) {
+        out = out.slice(0, leftToInflate);
+      }
+ 
+      buffers.push(out);
+      nread += out.length;
+      leftToInflate -= out.length;
+ 
+      Eif (leftToInflate === 0) {
+        return false;
+      }
+    }
+ 
+    if (availOutAfter === 0 || self._offset >= self._chunkSize) {
+      availOutBefore = self._chunkSize;
+      self._offset = 0;
+      self._buffer = Buffer.allocUnsafe(self._chunkSize);
+    }
+ 
+    if (availOutAfter === 0) {
+      inOff += availInBefore - availInAfter;
+      availInBefore = availInAfter;
+ 
+      return true;
+    }
+ 
+    return false;
+  }
+ 
+  assert(this._handle, "zlib binding closed");
+  let res;
+  do {
+    res = this._handle.writeSync(
+      flushFlag,
+      chunk, // in
+      inOff, // in_off
+      availInBefore, // in_len
+      this._buffer, // out
+      this._offset, //out_off
+      availOutBefore
+    ); // out_len
+    // Node 8 --> 9 compatibility check
+    res = res || this._writeState;
+  } while (!this._hadError && handleChunk(res[0], res[1]));
+ 
+  if (this._hadError) {
+    throw error;
+  }
+ 
+  Iif (nread >= kMaxLength) {
+    _close(this);
+    throw new RangeError(
+      "Cannot create final Buffer. It would be larger than 0x" +
+        kMaxLength.toString(16) +
+        " bytes"
+    );
+  }
+ 
+  let buf = Buffer.concat(buffers, nread);
+  _close(this);
+ 
+  return buf;
+};
+ 
+util.inherits(Inflate, zlib.Inflate);
+ 
+function zlibBufferSync(engine, buffer) {
+  Iif (typeof buffer === "string") {
+    buffer = Buffer.from(buffer);
+  }
+  Iif (!(buffer instanceof Buffer)) {
+    throw new TypeError("Not a string or buffer");
+  }
+ 
+  let flushFlag = engine._finishFlushFlag;
+  Iif (flushFlag == null) {
+    flushFlag = zlib.Z_FINISH;
+  }
+ 
+  return engine._processChunk(buffer, flushFlag);
+}
+ 
+function inflateSync(buffer, opts) {
+  return zlibBufferSync(new Inflate(opts), buffer);
+}
+ 
+module.exports = exports = inflateSync;
+exports.Inflate = Inflate;
+exports.createInflate = createInflate;
+exports.inflateSync = inflateSync;
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html b/backend/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html new file mode 100644 index 00000000..576dd88e --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html @@ -0,0 +1,215 @@ + + + + + + Code coverage report for sync-reader.js + + + + + + + + + +
+
+

All files sync-reader.js

+
+ +
+ 88.89% + Statements + 16/18 +
+ + +
+ 72.73% + Branches + 8/11 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 88.89% + Lines + 16/18 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
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 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46  +  +1x +338x +338x +  +  +1x +9900x +  +  +  +  +  +  +1x +  +338x +9900x +  +9900x +  +  +  +  +9900x +  +9900x +  +9900x +  +9900x +  +  +  +  +  +338x +  +  +  +338x +13x +  +  + 
"use strict";
+ 
+let SyncReader = (module.exports = function (buffer) {
+  this._buffer = buffer;
+  this._reads = [];
+});
+ 
+SyncReader.prototype.read = function (length, callback) {
+  this._reads.push({
+    length: Math.abs(length), // if length < 0 then at most this length
+    allowLess: length < 0,
+    func: callback,
+  });
+};
+ 
+SyncReader.prototype.process = function () {
+  // as long as there is any data and read requests
+  while (this._reads.length > 0 && this._buffer.length) {
+    let read = this._reads[0];
+ 
+    Eif (
+      this._buffer.length &&
+      (this._buffer.length >= read.length || read.allowLess)
+    ) {
+      // ok there is any data so that we can satisfy this request
+      this._reads.shift(); // == read
+ 
+      let buf = this._buffer;
+ 
+      this._buffer = buf.slice(read.length);
+ 
+      read.func.call(this, buf.slice(0, read.length));
+    } else {
+      break;
+    }
+  }
+ 
+  Iif (this._reads.length > 0) {
+    return new Error("There are some read requests waitng on finished stream");
+  }
+ 
+  if (this._buffer.length > 0) {
+    return new Error("unrecognised content at end of stream");
+  }
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/backend/node_modules/pngjs/coverage/lcov.info b/backend/node_modules/pngjs/coverage/lcov.info new file mode 100644 index 00000000..1a7a647b --- /dev/null +++ b/backend/node_modules/pngjs/coverage/lcov.info @@ -0,0 +1,2177 @@ +TN: +SF:lib\bitmapper.js +FN:7,(anonymous_0) +FN:11,(anonymous_1) +FN:25,(anonymous_2) +FN:39,(anonymous_3) +FN:52,(anonymous_4) +FN:66,(anonymous_5) +FN:70,(anonymous_6) +FN:80,(anonymous_7) +FN:90,(anonymous_8) +FN:99,(anonymous_9) +FN:107,bitRetriever +FN:111,split +FN:153,(anonymous_12) +FN:161,(anonymous_13) +FN:164,(anonymous_14) +FN:172,mapImage8Bit +FN:187,mapImageCustomBit +FN:202,(anonymous_17) +FN:229,(anonymous_18) +FNF:19 +FNH:17 +FNDA:0,(anonymous_0) +FNDA:313632,(anonymous_1) +FNDA:8192,(anonymous_2) +FNDA:1228160,(anonymous_3) +FNDA:272640,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:1193380,(anonymous_6) +FNDA:8192,(anonymous_7) +FNDA:24576,(anonymous_8) +FNDA:8192,(anonymous_9) +FNDA:209,bitRetriever +FNDA:334250,split +FNDA:1234340,(anonymous_12) +FNDA:8106,(anonymous_13) +FNDA:209,(anonymous_14) +FNDA:210,mapImage8Bit +FNDA:529,mapImageCustomBit +FNDA:335,(anonymous_17) +FNDA:2732114,(anonymous_18) +DA:3,1 +DA:5,1 +DA:12,313632 +DA:13,0 +DA:16,313632 +DA:17,313632 +DA:18,313632 +DA:19,313632 +DA:20,313632 +DA:26,8192 +DA:27,0 +DA:30,8192 +DA:31,8192 +DA:32,8192 +DA:33,8192 +DA:34,8192 +DA:40,1228160 +DA:41,0 +DA:44,1228160 +DA:45,1228160 +DA:46,1228160 +DA:47,1228160 +DA:53,272640 +DA:54,0 +DA:57,272640 +DA:58,272640 +DA:59,272640 +DA:60,272640 +DA:64,1 +DA:71,1193380 +DA:72,1193380 +DA:73,1193380 +DA:74,1193380 +DA:75,1193380 +DA:81,8192 +DA:82,8192 +DA:83,8192 +DA:84,8192 +DA:85,8192 +DA:91,24576 +DA:92,24576 +DA:93,24576 +DA:94,24576 +DA:100,8192 +DA:101,8192 +DA:102,8192 +DA:103,8192 +DA:108,209 +DA:109,209 +DA:112,334250 +DA:113,0 +DA:115,334250 +DA:116,334250 +DA:118,334250 +DA:120,0 +DA:122,149504 +DA:123,149504 +DA:124,149504 +DA:125,149504 +DA:127,49612 +DA:128,49612 +DA:129,49612 +DA:130,49612 +DA:132,2968 +DA:133,2968 +DA:134,2968 +DA:135,2968 +DA:136,2968 +DA:137,2968 +DA:139,132166 +DA:140,132166 +DA:141,132166 +DA:142,132166 +DA:143,132166 +DA:144,132166 +DA:145,132166 +DA:146,132166 +DA:147,132166 +DA:148,132166 +DA:152,209 +DA:154,1234340 +DA:155,334250 +DA:157,1234340 +DA:158,1234340 +DA:159,1234340 +DA:162,8106 +DA:165,209 +DA:166,0 +DA:174,210 +DA:175,210 +DA:176,210 +DA:177,210 +DA:178,7288 +DA:179,1822624 +DA:180,1822624 +DA:181,1822624 +DA:184,210 +DA:189,529 +DA:190,529 +DA:191,529 +DA:192,529 +DA:193,8106 +DA:194,1234340 +DA:195,1234340 +DA:196,1234340 +DA:198,8106 +DA:202,1 +DA:203,335 +DA:204,335 +DA:205,335 +DA:206,335 +DA:207,335 +DA:210,335 +DA:211,209 +DA:214,335 +DA:215,269 +DA:217,66 +DA:219,335 +DA:220,335 +DA:224,335 +DA:225,72 +DA:226,72 +DA:228,263 +DA:229,263 +DA:230,2732114 +DA:231,2732114 +DA:232,2732114 +DA:234,263 +DA:237,335 +DA:238,739 +DA:239,210 +DA:248,529 +DA:258,335 +DA:259,126 +DA:260,0 +DA:263,209 +DA:266,335 +LF:137 +LH:129 +BRDA:12,0,0,0 +BRDA:12,0,1,313632 +BRDA:26,1,0,0 +BRDA:26,1,1,8192 +BRDA:40,2,0,0 +BRDA:40,2,1,1228160 +BRDA:53,3,0,0 +BRDA:53,3,1,272640 +BRDA:112,4,0,0 +BRDA:112,4,1,334250 +BRDA:118,5,0,0 +BRDA:118,5,1,149504 +BRDA:118,5,2,49612 +BRDA:118,5,3,2968 +BRDA:118,5,4,132166 +BRDA:165,6,0,0 +BRDA:165,6,1,209 +BRDA:210,7,0,209 +BRDA:210,7,1,126 +BRDA:214,8,0,269 +BRDA:214,8,1,66 +BRDA:224,9,0,72 +BRDA:224,9,1,263 +BRDA:238,10,0,210 +BRDA:238,10,1,529 +BRDA:258,11,0,126 +BRDA:258,11,1,209 +BRDA:259,12,0,0 +BRDA:259,12,1,126 +BRF:29 +BRH:21 +end_of_record +TN: +SF:lib\bitpacker.js +FN:5,(anonymous_0) +FN:11,(anonymous_1) +FN:52,getRGBA +FNF:3 +FNH:2 +FNDA:325,(anonymous_0) +FNDA:325,(anonymous_1) +FNDA:0,getRGBA +DA:3,1 +DA:5,1 +DA:7,325 +DA:10,325 +DA:11,325 +DA:12,325 +DA:13,325 +DA:15,325 +DA:18,325 +DA:19,325 +DA:24,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:56,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:81,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:95,0 +DA:99,0 +DA:105,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:112,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:130,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:146,0 +DA:149,0 +DA:152,0 +DA:153,0 +DA:157,0 +LF:86 +LH:10 +BRDA:10,0,0,325 +BRDA:10,0,1,0 +BRDA:18,1,0,325 +BRDA:18,1,1,0 +BRDA:18,2,0,325 +BRDA:18,2,1,0 +BRDA:18,2,2,0 +BRDA:24,3,0,0 +BRDA:24,3,1,0 +BRDA:28,4,0,0 +BRDA:28,4,1,0 +BRDA:28,5,0,0 +BRDA:28,5,1,0 +BRDA:32,6,0,0 +BRDA:32,6,1,0 +BRDA:41,7,0,0 +BRDA:41,7,1,0 +BRDA:42,8,0,0 +BRDA:42,8,1,0 +BRDA:45,9,0,0 +BRDA:45,9,1,0 +BRDA:48,10,0,0 +BRDA:48,10,1,0 +BRDA:57,11,0,0 +BRDA:57,11,1,0 +BRDA:57,11,2,0 +BRDA:57,11,3,0 +BRDA:57,11,4,0 +BRDA:88,12,0,0 +BRDA:88,12,1,0 +BRDA:89,13,0,0 +BRDA:89,13,1,0 +BRDA:112,14,0,0 +BRDA:112,14,1,0 +BRDA:112,14,2,0 +BRDA:112,14,3,0 +BRDA:112,14,4,0 +BRDA:115,15,0,0 +BRDA:115,15,1,0 +BRDA:119,16,0,0 +BRDA:119,16,1,0 +BRDA:126,17,0,0 +BRDA:126,17,1,0 +BRDA:135,18,0,0 +BRDA:135,18,1,0 +BRDA:137,19,0,0 +BRDA:137,19,1,0 +BRDA:142,20,0,0 +BRDA:142,20,1,0 +BRF:49 +BRH:3 +end_of_record +TN: +SF:lib\chunkstream.js +FN:6,(anonymous_0) +FN:20,(anonymous_1) +FN:28,(anonymous_2) +FN:41,(anonymous_3) +FN:67,(anonymous_4) +FN:90,(anonymous_5) +FN:98,(anonymous_6) +FN:110,(anonymous_7) +FN:132,(anonymous_8) +FN:163,(anonymous_9) +FNF:10 +FNH:10 +FNDA:529,(anonymous_0) +FNDA:13318,(anonymous_1) +FNDA:13318,(anonymous_2) +FNDA:943,(anonymous_3) +FNDA:311,(anonymous_4) +FNDA:311,(anonymous_5) +FNDA:327,(anonymous_6) +FNDA:741,(anonymous_7) +FNDA:12408,(anonymous_8) +FNDA:14263,(anonymous_9) +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,529 +DA:9,529 +DA:10,529 +DA:12,529 +DA:13,529 +DA:15,529 +DA:16,529 +DA:18,1 +DA:20,1 +DA:21,13318 +DA:27,13318 +DA:29,13318 +DA:32,13318 +DA:33,0 +DA:35,0 +DA:41,1 +DA:42,943 +DA:43,0 +DA:44,0 +DA:48,943 +DA:49,943 +DA:51,0 +DA:54,943 +DA:55,943 +DA:57,943 +DA:60,943 +DA:61,346 +DA:64,943 +DA:67,1 +DA:68,311 +DA:69,0 +DA:72,311 +DA:75,311 +DA:76,0 +DA:80,311 +DA:81,309 +DA:83,2 +DA:84,2 +DA:88,1 +DA:90,1 +DA:91,311 +DA:92,3 +DA:95,311 +DA:98,1 +DA:99,327 +DA:100,0 +DA:103,327 +DA:104,327 +DA:105,327 +DA:107,327 +DA:110,1 +DA:112,741 +DA:115,741 +DA:118,741 +DA:119,568 +DA:120,568 +DA:122,568 +DA:125,173 +DA:126,173 +DA:128,173 +DA:132,1 +DA:133,12408 +DA:135,12408 +DA:136,12408 +DA:137,12408 +DA:140,12408 +DA:141,12617 +DA:142,12617 +DA:144,12617 +DA:145,12617 +DA:148,12617 +DA:149,11863 +DA:154,12408 +DA:155,532 +DA:158,12408 +DA:160,12408 +DA:163,1 +DA:164,14263 +DA:166,14263 +DA:167,15656 +DA:170,15656 +DA:171,741 +DA:172,14915 +DA:175,12408 +DA:179,2507 +DA:183,14263 +DA:184,2 +DA:187,0 +LF:91 +LH:82 +BRDA:32,0,0,0 +BRDA:32,0,1,13318 +BRDA:32,1,0,13318 +BRDA:32,1,1,10215 +BRDA:42,2,0,0 +BRDA:42,2,1,943 +BRDA:48,3,0,943 +BRDA:48,3,1,0 +BRDA:51,4,0,0 +BRDA:51,4,1,0 +BRDA:60,5,0,346 +BRDA:60,5,1,597 +BRDA:60,6,0,943 +BRDA:60,6,1,929 +BRDA:64,7,0,943 +BRDA:64,7,1,929 +BRDA:68,8,0,0 +BRDA:68,8,1,311 +BRDA:75,9,0,0 +BRDA:75,9,1,311 +BRDA:80,10,0,309 +BRDA:80,10,1,2 +BRDA:91,11,0,3 +BRDA:91,11,1,308 +BRDA:99,12,0,0 +BRDA:99,12,1,327 +BRDA:118,13,0,568 +BRDA:118,13,1,173 +BRDA:148,14,0,11863 +BRDA:148,14,1,754 +BRDA:154,15,0,532 +BRDA:154,15,1,11876 +BRDA:166,16,0,27412 +BRDA:166,16,1,15708 +BRDA:166,16,2,15671 +BRDA:170,17,0,741 +BRDA:170,17,1,14915 +BRDA:172,18,0,12408 +BRDA:172,18,1,2507 +BRDA:183,19,0,2 +BRDA:183,19,1,14261 +BRDA:183,20,0,14263 +BRDA:183,20,1,14213 +BRF:43 +BRH:35 +end_of_record +TN: +SF:lib\constants.js +FNF:0 +FNH:0 +DA:3,1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:lib\crc.js +FN:5,(anonymous_0) +FN:19,(anonymous_1) +FN:23,(anonymous_2) +FN:30,(anonymous_3) +FN:34,(anonymous_4) +FNF:5 +FNH:5 +FNDA:1,(anonymous_0) +FNDA:2461,(anonymous_1) +FNDA:4839,(anonymous_2) +FNDA:2195,(anonymous_3) +FNDA:1592,(anonymous_4) +DA:3,1 +DA:5,1 +DA:6,1 +DA:7,256 +DA:8,256 +DA:9,2048 +DA:10,1024 +DA:12,1024 +DA:15,256 +DA:19,1 +DA:20,2461 +DA:23,1 +DA:24,4839 +DA:25,823519 +DA:27,4839 +DA:30,1 +DA:31,2195 +DA:34,1 +DA:35,1592 +DA:36,1592 +DA:37,305287 +DA:39,1592 +LF:22 +LH:22 +BRDA:9,0,0,1024 +BRDA:9,0,1,1024 +BRF:2 +BRH:2 +end_of_record +TN: +SF:lib\filter-pack.js +FN:5,filterNone +FN:11,filterSumNone +FN:21,filterSub +FN:30,filterSumSub +FN:42,filterUp +FN:51,filterSumUp +FN:64,filterAvg +FN:74,filterSumAvg +FN:87,filterPaeth +FN:99,filterSumPaeth +FN:130,(anonymous_10) +FNF:11 +FNH:11 +FNDA:44,filterNone +FNDA:10490,filterSumNone +FNDA:637,filterSub +FNDA:10490,filterSumSub +FNDA:2670,filterUp +FNDA:10490,filterSumUp +FNDA:208,filterAvg +FNDA:10490,filterSumAvg +FNDA:6931,filterPaeth +FNDA:10490,filterSumPaeth +FNDA:325,(anonymous_10) +DA:3,1 +DA:6,44 +DA:7,5136 +DA:12,10490 +DA:13,10490 +DA:15,10490 +DA:16,2776736 +DA:18,10490 +DA:22,637 +DA:23,107032 +DA:24,107032 +DA:26,107032 +DA:31,10490 +DA:32,10490 +DA:33,2776736 +DA:34,2776736 +DA:36,2776736 +DA:39,10490 +DA:43,2670 +DA:44,581344 +DA:45,581344 +DA:47,581344 +DA:52,10490 +DA:53,10490 +DA:54,10490 +DA:55,2776736 +DA:56,2776736 +DA:58,2776736 +DA:61,10490 +DA:65,208 +DA:66,204096 +DA:67,204096 +DA:68,204096 +DA:70,204096 +DA:75,10490 +DA:76,10490 +DA:77,2776736 +DA:78,2776736 +DA:79,2776736 +DA:81,2776736 +DA:84,10490 +DA:88,6931 +DA:89,1879128 +DA:90,1879128 +DA:92,1879128 +DA:93,1879128 +DA:95,1879128 +DA:100,10490 +DA:101,10490 +DA:102,2776736 +DA:103,2776736 +DA:105,2776736 +DA:106,2776736 +DA:108,2776736 +DA:111,10490 +DA:114,1 +DA:122,1 +DA:130,1 +DA:132,325 +DA:133,325 +DA:134,0 +DA:135,0 +DA:137,0 +DA:140,325 +DA:141,0 +DA:143,325 +DA:144,325 +DA:145,325 +DA:146,325 +DA:148,325 +DA:150,325 +DA:151,10490 +DA:153,10490 +DA:155,10490 +DA:156,52450 +DA:157,52450 +DA:158,35370 +DA:159,35370 +DA:164,10490 +DA:165,10490 +DA:166,10490 +DA:167,10490 +DA:168,10490 +DA:170,325 +LF:84 +LH:80 +BRDA:23,0,0,104484 +BRDA:23,0,1,2548 +BRDA:33,1,0,2734776 +BRDA:33,1,1,41960 +BRDA:44,2,0,581344 +BRDA:44,2,1,0 +BRDA:55,3,0,2734120 +BRDA:55,3,1,42616 +BRDA:66,4,0,203264 +BRDA:66,4,1,832 +BRDA:67,5,0,204096 +BRDA:67,5,1,0 +BRDA:77,6,0,2734776 +BRDA:77,6,1,41960 +BRDA:78,7,0,2734120 +BRDA:78,7,1,42616 +BRDA:89,8,0,1851404 +BRDA:89,8,1,27724 +BRDA:90,9,0,1879128 +BRDA:90,9,1,0 +BRDA:92,10,0,1851404 +BRDA:92,10,1,27724 +BRDA:92,11,0,1879128 +BRDA:92,11,1,1879128 +BRDA:102,12,0,2734776 +BRDA:102,12,1,41960 +BRDA:103,13,0,2734120 +BRDA:103,13,1,42616 +BRDA:105,14,0,2693460 +BRDA:105,14,1,83276 +BRDA:105,15,0,2776736 +BRDA:105,15,1,2734120 +BRDA:132,16,0,325 +BRDA:132,16,1,0 +BRDA:132,17,0,325 +BRDA:132,17,1,1 +BRDA:134,18,0,0 +BRDA:134,18,1,0 +BRDA:140,19,0,0 +BRDA:140,19,1,325 +BRDA:151,20,0,10490 +BRDA:151,20,1,0 +BRDA:157,21,0,35370 +BRDA:157,21,1,17080 +BRF:44 +BRH:36 +end_of_record +TN: +SF:lib\filter-parse-async.js +FN:7,(anonymous_0) +FN:14,(anonymous_1) +FN:17,(anonymous_2) +FNF:3 +FNH:3 +FNDA:176,(anonymous_0) +FNDA:9057,(anonymous_1) +FNDA:173,(anonymous_2) +DA:3,1 +DA:4,1 +DA:5,1 +DA:7,1 +DA:8,176 +DA:10,176 +DA:11,176 +DA:12,176 +DA:15,9057 +DA:18,173 +DA:22,176 +DA:24,1 +LF:12 +LH:12 +BRF:0 +BRH:0 +end_of_record +TN: +SF:lib\filter-parse-sync.js +FN:6,(anonymous_0) +FN:11,(anonymous_1) +FN:14,(anonymous_2) +FNF:3 +FNH:3 +FNDA:162,(anonymous_0) +FNDA:6337,(anonymous_1) +FNDA:162,(anonymous_2) +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,162 +DA:8,162 +DA:9,162 +DA:12,6337 +DA:17,162 +DA:18,162 +DA:20,162 +LF:10 +LH:10 +BRF:0 +BRH:0 +end_of_record +TN: +SF:lib\filter-parse.js +FN:6,getByteWidth +FN:14,(anonymous_1) +FN:57,(anonymous_2) +FN:64,(anonymous_3) +FN:79,(anonymous_4) +FN:93,(anonymous_5) +FN:111,(anonymous_6) +FN:130,(anonymous_7) +FNF:8 +FNH:8 +FNDA:742,getByteWidth +FNDA:338,(anonymous_1) +FNDA:338,(anonymous_2) +FNDA:1939,(anonymous_3) +FNDA:800,(anonymous_4) +FNDA:172,(anonymous_5) +FNDA:4165,(anonymous_6) +FNDA:15394,(anonymous_7) +DA:3,1 +DA:4,1 +DA:7,742 +DA:8,742 +DA:9,531 +DA:11,742 +DA:14,1 +DA:15,338 +DA:16,338 +DA:17,338 +DA:18,338 +DA:19,338 +DA:21,338 +DA:22,338 +DA:23,338 +DA:25,338 +DA:26,338 +DA:27,338 +DA:28,72 +DA:29,72 +DA:30,476 +DA:37,266 +DA:48,338 +DA:49,127 +DA:50,211 +DA:51,66 +DA:53,145 +DA:57,1 +DA:58,338 +DA:64,1 +DA:69,1939 +DA:70,1939 +DA:72,1939 +DA:73,3563504 +DA:74,3563504 +DA:75,3563504 +DA:79,1 +DA:84,800 +DA:86,800 +DA:87,330256 +DA:88,330256 +DA:89,330256 +DA:93,1 +DA:98,172 +DA:99,172 +DA:100,172 +DA:102,172 +DA:103,9952 +DA:104,9952 +DA:105,9952 +DA:106,9952 +DA:107,9952 +DA:111,1 +DA:116,4165 +DA:117,4165 +DA:118,4165 +DA:120,4165 +DA:121,1152544 +DA:122,1152544 +DA:123,1152544 +DA:124,1152544 +DA:125,1152544 +DA:126,1152544 +DA:130,1 +DA:131,15394 +DA:133,15394 +DA:134,15394 +DA:136,15394 +DA:137,8318 +DA:139,7076 +DA:141,7076 +DA:143,1939 +DA:144,1939 +DA:146,800 +DA:147,800 +DA:149,172 +DA:150,172 +DA:152,4165 +DA:153,4165 +DA:155,0 +DA:159,15394 +DA:161,15394 +DA:162,15394 +DA:163,739 +DA:164,739 +DA:165,739 +DA:167,14655 +DA:170,15394 +DA:172,15059 +DA:174,335 +DA:175,335 +LF:91 +LH:90 +BRDA:8,0,0,531 +BRDA:8,0,1,211 +BRDA:27,1,0,72 +BRDA:27,1,1,266 +BRDA:48,2,0,127 +BRDA:48,2,1,211 +BRDA:50,3,0,66 +BRDA:50,3,1,145 +BRDA:74,4,0,3557696 +BRDA:74,4,1,5808 +BRDA:88,5,0,330000 +BRDA:88,5,1,256 +BRDA:104,6,0,9536 +BRDA:104,6,1,416 +BRDA:105,7,0,9554 +BRDA:105,7,1,398 +BRDA:122,8,0,1152288 +BRDA:122,8,1,256 +BRDA:123,9,0,1137296 +BRDA:123,9,1,15248 +BRDA:124,10,0,1137048 +BRDA:124,10,1,15496 +BRDA:124,11,0,1152544 +BRDA:124,11,1,1137296 +BRDA:136,12,0,8318 +BRDA:136,12,1,7076 +BRDA:141,13,0,1939 +BRDA:141,13,1,800 +BRDA:141,13,2,172 +BRDA:141,13,3,4165 +BRDA:141,13,4,0 +BRDA:162,14,0,739 +BRDA:162,14,1,14655 +BRDA:170,15,0,15059 +BRDA:170,15,1,335 +BRF:35 +BRH:34 +end_of_record +TN: +SF:lib\format-normaliser.js +FN:3,dePalette +FN:22,replaceTransparentColor +FN:49,scaleDepth +FN:66,(anonymous_3) +FNF:4 +FNH:4 +FNDA:131,dePalette +FNDA:12,replaceTransparentColor +FNDA:106,scaleDepth +FNDA:335,(anonymous_3) +DA:4,131 +DA:6,131 +DA:7,4912 +DA:8,1418436 +DA:10,1418436 +DA:11,0 +DA:14,1418436 +DA:15,5673744 +DA:17,1418436 +DA:23,12 +DA:24,12 +DA:25,384 +DA:26,12288 +DA:28,12288 +DA:29,6144 +DA:30,2762 +DA:32,6144 +DA:37,2718 +DA:39,12288 +DA:40,5480 +DA:41,21920 +DA:44,12288 +DA:50,106 +DA:51,106 +DA:52,106 +DA:54,106 +DA:55,3392 +DA:56,108544 +DA:57,434176 +DA:61,108544 +DA:66,1 +DA:67,335 +DA:68,335 +DA:69,335 +DA:70,335 +DA:71,335 +DA:72,335 +DA:74,335 +DA:76,335 +DA:78,131 +DA:80,204 +DA:81,12 +DA:84,204 +DA:86,106 +DA:87,66 +DA:89,106 +DA:92,335 +LF:47 +LH:46 +BRDA:10,0,0,0 +BRDA:10,0,1,1418436 +BRDA:28,1,0,6144 +BRDA:28,1,1,6144 +BRDA:29,2,0,2762 +BRDA:29,2,1,3382 +BRDA:32,3,0,2718 +BRDA:32,3,1,3426 +BRDA:33,4,0,6144 +BRDA:33,4,1,2718 +BRDA:33,4,2,2718 +BRDA:39,5,0,5480 +BRDA:39,5,1,6808 +BRDA:76,6,0,131 +BRDA:76,6,1,204 +BRDA:80,7,0,12 +BRDA:80,7,1,192 +BRDA:84,8,0,106 +BRDA:84,8,1,98 +BRDA:86,9,0,66 +BRDA:86,9,1,40 +BRF:21 +BRH:20 +end_of_record +TN: +SF:lib\interlace.js +FN:52,(anonymous_0) +FN:83,(anonymous_1) +FN:84,(anonymous_2) +FNF:3 +FNH:3 +FNDA:144,(anonymous_0) +FNDA:72,(anonymous_1) +FNDA:324850,(anonymous_2) +DA:14,1 +DA:52,1 +DA:53,144 +DA:54,144 +DA:55,144 +DA:56,144 +DA:57,144 +DA:58,144 +DA:59,1008 +DA:60,1008 +DA:61,1008 +DA:62,1008 +DA:63,1556 +DA:64,672 +DA:66,884 +DA:69,1008 +DA:70,1360 +DA:71,552 +DA:73,808 +DA:76,1008 +DA:77,952 +DA:80,144 +DA:83,1 +DA:84,72 +DA:85,324850 +DA:87,324850 +DA:89,324850 +DA:91,324850 +DA:93,324850 +LF:29 +LH:29 +BRDA:63,0,0,672 +BRDA:63,0,1,884 +BRDA:70,1,0,552 +BRDA:70,1,1,808 +BRDA:76,2,0,952 +BRDA:76,2,1,56 +BRDA:76,3,0,1008 +BRDA:76,3,1,980 +BRF:8 +BRH:8 +end_of_record +TN: +SF:lib\packer-async.js +FN:8,(anonymous_0) +FN:20,(anonymous_1) +FN:36,(anonymous_2) +FN:43,(anonymous_3) +FNF:4 +FNH:4 +FNDA:353,(anonymous_0) +FNDA:325,(anonymous_1) +FNDA:652,(anonymous_2) +FNDA:325,(anonymous_3) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:8,1 +DA:9,353 +DA:11,353 +DA:13,353 +DA:14,353 +DA:16,353 +DA:18,1 +DA:20,1 +DA:22,325 +DA:23,325 +DA:25,325 +DA:26,290 +DA:29,325 +DA:32,325 +DA:34,325 +DA:37,652 +DA:41,325 +DA:44,325 +DA:45,325 +DA:49,325 +LF:24 +LH:24 +BRDA:11,0,0,353 +BRDA:11,0,1,0 +BRDA:25,1,0,290 +BRDA:25,1,1,35 +BRF:4 +BRH:3 +end_of_record +TN: +SF:lib\packer-sync.js +FN:11,(anonymous_0) +FNF:1 +FNH:0 +FNDA:0,(anonymous_0) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,0 +DA:8,1 +DA:9,1 +DA:11,1 +DA:12,0 +DA:13,0 +DA:18,0 +DA:20,0 +DA:22,0 +DA:25,0 +DA:28,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:41,0 +DA:45,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:53,0 +DA:55,0 +LF:24 +LH:6 +BRDA:5,0,0,0 +BRDA:5,0,1,1 +BRDA:12,1,0,0 +BRDA:12,1,1,0 +BRDA:18,2,0,0 +BRDA:18,2,1,0 +BRDA:30,3,0,0 +BRDA:30,3,1,0 +BRDA:47,4,0,0 +BRDA:47,4,1,0 +BRDA:47,5,0,0 +BRDA:47,5,1,0 +BRF:12 +BRH:1 +end_of_record +TN: +SF:lib\packer.js +FN:9,(anonymous_0) +FN:64,(anonymous_1) +FN:72,(anonymous_2) +FN:76,(anonymous_3) +FN:86,(anonymous_4) +FN:104,(anonymous_5) +FN:110,(anonymous_6) +FN:123,(anonymous_7) +FN:127,(anonymous_8) +FNF:9 +FNH:9 +FNDA:353,(anonymous_0) +FNDA:353,(anonymous_1) +FNDA:353,(anonymous_2) +FNDA:325,(anonymous_3) +FNDA:1592,(anonymous_4) +FNDA:290,(anonymous_5) +FNDA:325,(anonymous_6) +FNDA:652,(anonymous_7) +FNDA:325,(anonymous_8) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:9,1 +DA:10,353 +DA:12,353 +DA:13,353 +DA:15,353 +DA:17,353 +DA:19,353 +DA:20,353 +DA:22,353 +DA:26,353 +DA:31,353 +DA:39,0 +DA:43,353 +DA:51,0 +DA:57,353 +DA:58,0 +DA:64,1 +DA:65,353 +DA:72,1 +DA:73,353 +DA:76,1 +DA:78,325 +DA:81,325 +DA:82,325 +DA:83,325 +DA:86,1 +DA:87,1592 +DA:88,1592 +DA:90,1592 +DA:91,1592 +DA:93,1592 +DA:94,1267 +DA:97,1592 +DA:101,1592 +DA:104,1 +DA:105,290 +DA:106,290 +DA:107,290 +DA:110,1 +DA:111,325 +DA:112,325 +DA:113,325 +DA:114,325 +DA:115,325 +DA:116,325 +DA:117,325 +DA:118,325 +DA:120,325 +DA:123,1 +DA:124,652 +DA:127,1 +DA:128,325 +LF:57 +LH:54 +BRDA:12,0,0,353 +BRDA:12,0,1,353 +BRDA:14,1,0,0 +BRDA:14,1,1,353 +BRDA:16,2,0,0 +BRDA:16,2,1,353 +BRDA:18,3,0,0 +BRDA:18,3,1,353 +BRDA:19,4,0,353 +BRDA:19,4,1,353 +BRDA:20,5,0,353 +BRDA:20,5,1,353 +BRDA:23,6,0,0 +BRDA:23,6,1,353 +BRDA:27,7,0,0 +BRDA:27,7,1,353 +BRDA:31,8,0,0 +BRDA:31,8,1,353 +BRDA:43,9,0,0 +BRDA:43,9,1,353 +BRDA:57,10,0,0 +BRDA:57,10,1,353 +BRDA:57,11,0,353 +BRDA:57,11,1,0 +BRDA:87,12,0,1267 +BRDA:87,12,1,325 +BRDA:93,13,0,1267 +BRDA:93,13,1,325 +BRF:28 +BRH:19 +end_of_record +TN: +SF:lib\paeth-predictor.js +FN:3,paethPredictor +FNF:1 +FNH:1 +FNDA:5808408,paethPredictor +DA:3,1 +DA:4,5808408 +DA:5,5808408 +DA:6,5808408 +DA:7,5808408 +DA:9,5808408 +DA:10,5156742 +DA:12,651666 +DA:13,539893 +DA:15,111773 +LF:10 +LH:10 +BRDA:9,0,0,5156742 +BRDA:9,0,1,651666 +BRDA:9,1,0,5808408 +BRDA:9,1,1,5231305 +BRDA:12,2,0,539893 +BRDA:12,2,1,111773 +BRF:6 +BRH:6 +end_of_record +TN: +SF:lib\parser-async.js +FN:11,(anonymous_0) +FN:33,(anonymous_1) +FN:49,(anonymous_2) +FN:55,(anonymous_3) +FN:79,(anonymous_4) +FN:89,(anonymous_5) +FN:109,(anonymous_6) +FN:116,(anonymous_7) +FN:120,(anonymous_8) +FN:124,(anonymous_9) +FN:128,(anonymous_10) +FN:134,(anonymous_11) +FN:147,(anonymous_12) +FNF:13 +FNH:11 +FNDA:353,(anonymous_0) +FNDA:14,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:741,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:487,(anonymous_5) +FNDA:176,(anonymous_6) +FNDA:7,(anonymous_7) +FNDA:77,(anonymous_8) +FNDA:15,(anonymous_9) +FNDA:174,(anonymous_10) +FNDA:173,(anonymous_11) +FNDA:173,(anonymous_12) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:8,1 +DA:9,1 +DA:11,1 +DA:12,353 +DA:14,353 +DA:26,353 +DA:27,353 +DA:29,353 +DA:31,1 +DA:33,1 +DA:34,14 +DA:36,14 +DA:38,14 +DA:40,14 +DA:41,1 +DA:44,14 +DA:45,2 +DA:49,2 +DA:52,14 +DA:55,1 +DA:56,741 +DA:57,174 +DA:58,36 +DA:60,36 +DA:61,36 +DA:63,36 +DA:66,138 +DA:72,138 +DA:73,138 +DA:75,138 +DA:76,138 +DA:78,138 +DA:79,138 +DA:80,0 +DA:81,0 +DA:84,0 +DA:86,138 +DA:88,138 +DA:89,138 +DA:90,487 +DA:91,0 +DA:94,487 +DA:95,0 +DA:98,487 +DA:100,487 +DA:103,138 +DA:106,741 +DA:109,1 +DA:110,176 +DA:111,176 +DA:113,176 +DA:116,1 +DA:117,7 +DA:120,1 +DA:121,77 +DA:124,1 +DA:125,15 +DA:128,1 +DA:131,174 +DA:134,1 +DA:135,173 +DA:136,0 +DA:139,173 +DA:140,1 +DA:143,172 +DA:147,1 +DA:148,173 +DA:149,0 +DA:154,173 +DA:155,173 +DA:157,173 +DA:158,173 +DA:160,0 +DA:161,0 +DA:164,173 +LF:80 +LH:71 +BRDA:40,0,0,1 +BRDA:40,0,1,13 +BRDA:40,1,0,14 +BRDA:40,1,1,1 +BRDA:44,2,0,2 +BRDA:44,2,1,12 +BRDA:56,3,0,174 +BRDA:56,3,1,567 +BRDA:57,4,0,36 +BRDA:57,4,1,138 +BRDA:80,5,0,0 +BRDA:80,5,1,0 +BRDA:90,6,0,0 +BRDA:90,6,1,487 +BRDA:94,7,0,0 +BRDA:94,7,1,487 +BRDA:135,8,0,0 +BRDA:135,8,1,173 +BRDA:139,9,0,1 +BRDA:139,9,1,172 +BRDA:148,10,0,0 +BRDA:148,10,1,173 +BRF:22 +BRH:16 +end_of_record +TN: +SF:lib\parser-sync.js +FN:15,(anonymous_0) +FN:23,handleError +FN:28,handleMetaData +FN:32,handleTransColor +FN:36,handlePalette +FN:40,handleSimpleTransparency +FN:45,handleGamma +FN:50,handleInflateData +FNF:8 +FNH:8 +FNDA:176,(anonymous_0) +FNDA:13,handleError +FNDA:165,handleMetaData +FNDA:5,handleTransColor +FNDA:73,handlePalette +FNDA:12,handleSimpleTransparency +FNDA:147,handleGamma +FNDA:492,handleInflateData +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,0 +DA:9,1 +DA:10,1 +DA:11,1 +DA:12,1 +DA:13,1 +DA:15,1 +DA:16,176 +DA:17,0 +DA:24,13 +DA:29,165 +DA:33,5 +DA:37,73 +DA:41,12 +DA:46,147 +DA:49,176 +DA:51,492 +DA:54,176 +DA:56,176 +DA:67,176 +DA:68,176 +DA:70,176 +DA:71,13 +DA:75,163 +DA:76,163 +DA:79,163 +DA:80,36 +DA:83,127 +DA:84,127 +DA:85,127 +DA:90,162 +DA:92,162 +DA:93,0 +DA:96,162 +DA:97,162 +DA:99,162 +DA:100,162 +DA:102,162 +DA:104,162 +DA:105,162 +DA:107,162 +LF:45 +LH:42 +BRDA:6,0,0,0 +BRDA:6,0,1,1 +BRDA:16,1,0,0 +BRDA:16,1,1,176 +BRDA:70,2,0,13 +BRDA:70,2,1,163 +BRDA:79,3,0,36 +BRDA:79,3,1,127 +BRDA:92,4,0,0 +BRDA:92,4,1,162 +BRDA:92,5,0,162 +BRDA:92,5,1,162 +BRDA:105,6,0,162 +BRDA:105,6,1,17 +BRF:14 +BRH:11 +end_of_record +TN: +SF:lib\parser.js +FN:6,(anonymous_0) +FN:36,(anonymous_1) +FN:39,(anonymous_2) +FN:43,(anonymous_3) +FN:55,(anonymous_4) +FN:93,(anonymous_5) +FN:97,(anonymous_6) +FN:101,(anonymous_7) +FN:116,(anonymous_8) +FN:119,(anonymous_9) +FN:183,(anonymous_10) +FN:186,(anonymous_11) +FN:201,(anonymous_12) +FN:205,(anonymous_13) +FN:241,(anonymous_14) +FN:244,(anonymous_15) +FN:251,(anonymous_16) +FN:258,(anonymous_17) +FN:278,(anonymous_18) +FN:281,(anonymous_19) +FNF:20 +FNH:20 +FNDA:529,(anonymous_0) +FNDA:163,(anonymous_1) +FNDA:529,(anonymous_2) +FNDA:365,(anonymous_3) +FNDA:2461,(anonymous_4) +FNDA:256,(anonymous_5) +FNDA:2195,(anonymous_6) +FNDA:2195,(anonymous_7) +FNDA:351,(anonymous_8) +FNDA:351,(anonymous_9) +FNDA:135,(anonymous_10) +FNDA:135,(anonymous_11) +FNDA:27,(anonymous_12) +FNDA:27,(anonymous_13) +FNDA:296,(anonymous_14) +FNDA:296,(anonymous_15) +FNDA:1233,(anonymous_16) +FNDA:1233,(anonymous_17) +FNDA:336,(anonymous_18) +FNDA:336,(anonymous_19) +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,529 +DA:8,529 +DA:10,529 +DA:11,529 +DA:12,529 +DA:15,529 +DA:16,529 +DA:18,529 +DA:19,529 +DA:20,529 +DA:21,529 +DA:22,529 +DA:23,529 +DA:24,529 +DA:26,529 +DA:27,529 +DA:28,529 +DA:29,529 +DA:30,529 +DA:31,529 +DA:32,529 +DA:33,529 +DA:34,529 +DA:35,529 +DA:36,529 +DA:39,1 +DA:40,529 +DA:43,1 +DA:44,365 +DA:46,365 +DA:47,2867 +DA:48,13 +DA:49,13 +DA:52,352 +DA:55,1 +DA:57,2461 +DA:60,2461 +DA:61,2461 +DA:62,2461 +DA:63,9844 +DA:69,2461 +DA:73,2461 +DA:74,0 +DA:75,0 +DA:78,2461 +DA:79,2461 +DA:81,2461 +DA:82,2205 +DA:85,256 +DA:86,0 +DA:87,0 +DA:90,256 +DA:93,1 +DA:94,256 +DA:97,1 +DA:98,2195 +DA:101,1 +DA:102,2195 +DA:103,2195 +DA:106,2195 +DA:107,4 +DA:108,4 +DA:111,2191 +DA:112,1855 +DA:116,1 +DA:117,351 +DA:119,1 +DA:120,351 +DA:122,351 +DA:123,351 +DA:124,351 +DA:125,351 +DA:126,351 +DA:127,351 +DA:128,351 +DA:135,351 +DA:142,6 +DA:143,6 +DA:145,345 +DA:146,4 +DA:147,4 +DA:149,341 +DA:150,0 +DA:151,0 +DA:153,341 +DA:154,0 +DA:155,0 +DA:157,341 +DA:158,0 +DA:159,0 +DA:162,341 +DA:164,341 +DA:166,341 +DA:168,341 +DA:180,341 +DA:183,1 +DA:184,135 +DA:186,1 +DA:187,135 +DA:189,135 +DA:192,135 +DA:193,7350 +DA:196,135 +DA:198,135 +DA:201,1 +DA:202,27 +DA:203,27 +DA:205,1 +DA:206,27 +DA:209,27 +DA:210,15 +DA:211,0 +DA:212,0 +DA:214,15 +DA:215,0 +DA:216,0 +DA:218,15 +DA:219,529 +DA:221,15 +DA:226,27 +DA:228,6 +DA:230,27 +DA:231,6 +DA:238,27 +DA:241,1 +DA:242,296 +DA:244,1 +DA:245,296 +DA:246,296 +DA:248,296 +DA:251,1 +DA:252,1233 +DA:253,337 +DA:254,337 +DA:256,1233 +DA:258,1 +DA:259,1233 +DA:261,1233 +DA:265,0 +DA:268,1233 +DA:269,1233 +DA:271,1233 +DA:272,173 +DA:274,1060 +DA:278,1 +DA:279,336 +DA:281,1 +DA:282,336 +DA:284,336 +DA:285,336 +DA:287,336 +DA:288,173 +LF:155 +LH:140 +BRDA:36,0,0,529 +BRDA:36,0,1,176 +BRDA:47,1,0,13 +BRDA:47,1,1,2854 +BRDA:73,2,0,0 +BRDA:73,2,1,2461 +BRDA:73,3,0,2461 +BRDA:73,3,1,351 +BRDA:81,4,0,2205 +BRDA:81,4,1,256 +BRDA:85,5,0,0 +BRDA:85,5,1,256 +BRDA:106,6,0,4 +BRDA:106,6,1,2191 +BRDA:106,7,0,2195 +BRDA:106,7,1,2195 +BRDA:111,8,0,1855 +BRDA:111,8,1,336 +BRDA:135,9,0,6 +BRDA:135,9,1,345 +BRDA:136,10,0,351 +BRDA:136,10,1,219 +BRDA:136,10,2,132 +BRDA:136,10,3,101 +BRDA:136,10,4,72 +BRDA:145,11,0,4 +BRDA:145,11,1,341 +BRDA:149,12,0,0 +BRDA:149,12,1,341 +BRDA:153,13,0,0 +BRDA:153,13,1,341 +BRDA:157,14,0,0 +BRDA:157,14,1,341 +BRDA:157,15,0,341 +BRDA:157,15,1,72 +BRDA:209,16,0,15 +BRDA:209,16,1,12 +BRDA:210,17,0,0 +BRDA:210,17,1,15 +BRDA:214,18,0,0 +BRDA:214,18,1,15 +BRDA:226,19,0,6 +BRDA:226,19,1,21 +BRDA:230,20,0,6 +BRDA:230,20,1,21 +BRDA:252,21,0,337 +BRDA:252,21,1,896 +BRDA:261,22,0,0 +BRDA:261,22,1,1233 +BRDA:262,23,0,1233 +BRDA:262,23,1,131 +BRDA:271,24,0,173 +BRDA:271,24,1,1060 +BRDA:287,25,0,173 +BRDA:287,25,1,163 +BRF:55 +BRH:47 +end_of_record +TN: +SF:lib\png-sync.js +FN:6,(anonymous_0) +FN:10,(anonymous_1) +FNF:2 +FNH:1 +FNDA:176,(anonymous_0) +FNDA:0,(anonymous_1) +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,176 +DA:10,1 +DA:11,0 +LF:6 +LH:5 +BRDA:7,0,0,176 +BRDA:7,0,1,176 +BRF:2 +BRH:2 +end_of_record +TN: +SF:lib\png.js +FN:9,(anonymous_0) +FN:38,(anonymous_1) +FN:54,(anonymous_2) +FN:61,(anonymous_3) +FN:69,(anonymous_4) +FN:73,(anonymous_5) +FN:80,(anonymous_6) +FN:94,(anonymous_7) +FN:99,(anonymous_8) +FN:103,(anonymous_9) +FN:110,(anonymous_10) +FN:114,(anonymous_11) +FN:120,(anonymous_12) +FN:160,(anonymous_13) +FN:175,(anonymous_14) +FN:192,(anonymous_15) +FNF:16 +FNH:9 +FNDA:353,(anonymous_0) +FNDA:173,(anonymous_1) +FNDA:325,(anonymous_2) +FNDA:325,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:412,(anonymous_7) +FNDA:175,(anonymous_8) +FNDA:174,(anonymous_9) +FNDA:149,(anonymous_10) +FNDA:378,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:9,1 +DA:10,353 +DA:12,353 +DA:15,353 +DA:16,353 +DA:18,353 +DA:23,353 +DA:24,0 +DA:27,353 +DA:28,353 +DA:30,353 +DA:32,353 +DA:33,353 +DA:34,353 +DA:35,353 +DA:36,353 +DA:39,173 +DA:40,173 +DA:44,353 +DA:45,353 +DA:46,353 +DA:47,353 +DA:48,353 +DA:50,1 +DA:52,1 +DA:54,1 +DA:55,325 +DA:56,0 +DA:57,0 +DA:60,325 +DA:62,325 +DA:66,325 +DA:69,1 +DA:70,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:86,0 +DA:87,0 +DA:90,0 +DA:91,0 +DA:94,1 +DA:95,412 +DA:96,412 +DA:99,1 +DA:100,175 +DA:103,1 +DA:104,174 +DA:105,174 +DA:107,174 +DA:110,1 +DA:111,149 +DA:114,1 +DA:115,378 +DA:116,0 +DA:120,1 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:132,0 +DA:138,0 +DA:141,0 +DA:147,0 +DA:150,0 +DA:151,0 +DA:160,1 +DA:171,0 +DA:172,0 +DA:175,1 +DA:176,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:188,0 +DA:192,1 +DA:193,0 +LF:92 +LH:52 +BRDA:12,0,0,353 +BRDA:12,0,1,348 +BRDA:19,1,0,1 +BRDA:19,1,1,352 +BRDA:19,2,0,353 +BRDA:19,2,1,1 +BRDA:23,3,0,0 +BRDA:23,3,1,353 +BRDA:23,4,0,353 +BRDA:23,4,1,0 +BRDA:55,5,0,0 +BRDA:55,5,1,325 +BRDA:55,6,0,325 +BRDA:55,6,1,325 +BRDA:70,7,0,0 +BRDA:70,7,1,0 +BRDA:115,8,0,0 +BRDA:115,8,1,378 +BRDA:115,9,0,378 +BRDA:115,9,1,378 +BRDA:132,10,0,0 +BRDA:132,10,1,0 +BRDA:133,11,0,0 +BRDA:133,11,1,0 +BRDA:133,11,2,0 +BRDA:133,11,3,0 +BRDA:141,12,0,0 +BRDA:141,12,1,0 +BRDA:142,13,0,0 +BRDA:142,13,1,0 +BRDA:142,13,2,0 +BRDA:142,13,3,0 +BRDA:176,14,0,0 +BRDA:176,14,1,0 +BRF:34 +BRH:14 +end_of_record +TN: +SF:lib\sync-inflate.js +FN:9,Inflate +FN:29,createInflate +FN:33,_close +FN:47,(anonymous_3) +FN:63,(anonymous_4) +FN:67,handleChunk +FN:145,zlibBufferSync +FN:161,inflateSync +FNF:8 +FNH:7 +FNDA:127,Inflate +FNDA:0,createInflate +FNDA:126,_close +FNDA:127,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:126,handleChunk +FNDA:127,zlibBufferSync +FNDA:127,inflateSync +DA:3,1 +DA:4,1 +DA:5,1 +DA:7,1 +DA:10,127 +DA:11,0 +DA:14,127 +DA:15,9 +DA:18,127 +DA:21,127 +DA:22,127 +DA:24,127 +DA:25,127 +DA:30,0 +DA:34,126 +DA:35,0 +DA:39,126 +DA:40,0 +DA:43,126 +DA:44,126 +DA:47,1 +DA:48,127 +DA:49,0 +DA:52,127 +DA:54,127 +DA:55,127 +DA:56,127 +DA:57,127 +DA:59,127 +DA:60,127 +DA:63,127 +DA:64,1 +DA:68,126 +DA:69,0 +DA:72,126 +DA:73,126 +DA:75,126 +DA:76,126 +DA:77,126 +DA:79,126 +DA:80,9 +DA:83,126 +DA:84,126 +DA:85,126 +DA:87,126 +DA:88,126 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:102,0 +DA:105,0 +DA:108,127 +DA:110,127 +DA:111,127 +DA:121,127 +DA:124,127 +DA:125,1 +DA:128,126 +DA:129,0 +DA:130,0 +DA:137,126 +DA:138,126 +DA:140,126 +DA:143,1 +DA:146,127 +DA:147,0 +DA:149,127 +DA:150,0 +DA:153,127 +DA:154,127 +DA:155,0 +DA:158,127 +DA:162,127 +DA:165,1 +DA:166,1 +DA:167,1 +DA:168,1 +LF:81 +LH:61 +BRDA:10,0,0,0 +BRDA:10,0,1,127 +BRDA:14,1,0,9 +BRDA:14,1,1,118 +BRDA:14,2,0,127 +BRDA:14,2,1,127 +BRDA:21,3,0,127 +BRDA:21,3,1,0 +BRDA:22,4,0,127 +BRDA:22,4,1,127 +BRDA:24,5,0,127 +BRDA:24,5,1,0 +BRDA:24,6,0,127 +BRDA:24,6,1,127 +BRDA:34,7,0,0 +BRDA:34,7,1,126 +BRDA:39,8,0,0 +BRDA:39,8,1,126 +BRDA:48,9,0,0 +BRDA:48,9,1,127 +BRDA:54,10,0,127 +BRDA:54,10,1,127 +BRDA:68,11,0,0 +BRDA:68,11,1,126 +BRDA:75,12,0,126 +BRDA:75,12,1,0 +BRDA:79,13,0,9 +BRDA:79,13,1,117 +BRDA:87,14,0,126 +BRDA:87,14,1,0 +BRDA:92,15,0,0 +BRDA:92,15,1,0 +BRDA:92,16,0,0 +BRDA:92,16,1,0 +BRDA:98,17,0,0 +BRDA:98,17,1,0 +BRDA:122,18,0,127 +BRDA:122,18,1,126 +BRDA:121,19,0,127 +BRDA:121,19,1,127 +BRDA:124,20,0,1 +BRDA:124,20,1,126 +BRDA:128,21,0,0 +BRDA:128,21,1,126 +BRDA:146,22,0,0 +BRDA:146,22,1,127 +BRDA:149,23,0,0 +BRDA:149,23,1,127 +BRDA:154,24,0,0 +BRDA:154,24,1,127 +BRF:50 +BRH:31 +end_of_record +TN: +SF:lib\sync-reader.js +FN:3,(anonymous_0) +FN:8,(anonymous_1) +FN:16,(anonymous_2) +FNF:3 +FNH:3 +FNDA:338,(anonymous_0) +FNDA:9900,(anonymous_1) +FNDA:338,(anonymous_2) +DA:3,1 +DA:4,338 +DA:5,338 +DA:8,1 +DA:9,9900 +DA:16,1 +DA:18,338 +DA:19,9900 +DA:21,9900 +DA:26,9900 +DA:28,9900 +DA:30,9900 +DA:32,9900 +DA:34,0 +DA:38,338 +DA:39,0 +DA:42,338 +DA:43,13 +LF:18 +LH:16 +BRDA:18,0,0,10238 +BRDA:18,0,1,9900 +BRDA:21,1,0,9900 +BRDA:21,1,1,0 +BRDA:22,2,0,9900 +BRDA:22,2,1,9900 +BRDA:22,2,2,0 +BRDA:38,3,0,0 +BRDA:38,3,1,338 +BRDA:42,4,0,13 +BRDA:42,4,1,325 +BRF:11 +BRH:8 +end_of_record diff --git a/backend/node_modules/pngjs/lib/bitmapper.js b/backend/node_modules/pngjs/lib/bitmapper.js new file mode 100644 index 00000000..18378a02 --- /dev/null +++ b/backend/node_modules/pngjs/lib/bitmapper.js @@ -0,0 +1,267 @@ +"use strict"; + +let interlaceUtils = require("./interlace"); + +let pixelBppMapper = [ + // 0 - dummy entry + function () {}, + + // 1 - L + // 0: 0, 1: 0, 2: 0, 3: 0xff + function (pxData, data, pxPos, rawPos) { + if (rawPos === data.length) { + throw new Error("Ran out of data"); + } + + let pixel = data[rawPos]; + pxData[pxPos] = pixel; + pxData[pxPos + 1] = pixel; + pxData[pxPos + 2] = pixel; + pxData[pxPos + 3] = 0xff; + }, + + // 2 - LA + // 0: 0, 1: 0, 2: 0, 3: 1 + function (pxData, data, pxPos, rawPos) { + if (rawPos + 1 >= data.length) { + throw new Error("Ran out of data"); + } + + let pixel = data[rawPos]; + pxData[pxPos] = pixel; + pxData[pxPos + 1] = pixel; + pxData[pxPos + 2] = pixel; + pxData[pxPos + 3] = data[rawPos + 1]; + }, + + // 3 - RGB + // 0: 0, 1: 1, 2: 2, 3: 0xff + function (pxData, data, pxPos, rawPos) { + if (rawPos + 2 >= data.length) { + throw new Error("Ran out of data"); + } + + pxData[pxPos] = data[rawPos]; + pxData[pxPos + 1] = data[rawPos + 1]; + pxData[pxPos + 2] = data[rawPos + 2]; + pxData[pxPos + 3] = 0xff; + }, + + // 4 - RGBA + // 0: 0, 1: 1, 2: 2, 3: 3 + function (pxData, data, pxPos, rawPos) { + if (rawPos + 3 >= data.length) { + throw new Error("Ran out of data"); + } + + pxData[pxPos] = data[rawPos]; + pxData[pxPos + 1] = data[rawPos + 1]; + pxData[pxPos + 2] = data[rawPos + 2]; + pxData[pxPos + 3] = data[rawPos + 3]; + }, +]; + +let pixelBppCustomMapper = [ + // 0 - dummy entry + function () {}, + + // 1 - L + // 0: 0, 1: 0, 2: 0, 3: 0xff + function (pxData, pixelData, pxPos, maxBit) { + let pixel = pixelData[0]; + pxData[pxPos] = pixel; + pxData[pxPos + 1] = pixel; + pxData[pxPos + 2] = pixel; + pxData[pxPos + 3] = maxBit; + }, + + // 2 - LA + // 0: 0, 1: 0, 2: 0, 3: 1 + function (pxData, pixelData, pxPos) { + let pixel = pixelData[0]; + pxData[pxPos] = pixel; + pxData[pxPos + 1] = pixel; + pxData[pxPos + 2] = pixel; + pxData[pxPos + 3] = pixelData[1]; + }, + + // 3 - RGB + // 0: 0, 1: 1, 2: 2, 3: 0xff + function (pxData, pixelData, pxPos, maxBit) { + pxData[pxPos] = pixelData[0]; + pxData[pxPos + 1] = pixelData[1]; + pxData[pxPos + 2] = pixelData[2]; + pxData[pxPos + 3] = maxBit; + }, + + // 4 - RGBA + // 0: 0, 1: 1, 2: 2, 3: 3 + function (pxData, pixelData, pxPos) { + pxData[pxPos] = pixelData[0]; + pxData[pxPos + 1] = pixelData[1]; + pxData[pxPos + 2] = pixelData[2]; + pxData[pxPos + 3] = pixelData[3]; + }, +]; + +function bitRetriever(data, depth) { + let leftOver = []; + let i = 0; + + function split() { + if (i === data.length) { + throw new Error("Ran out of data"); + } + let byte = data[i]; + i++; + let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1; + switch (depth) { + default: + throw new Error("unrecognised depth"); + case 16: + byte2 = data[i]; + i++; + leftOver.push((byte << 8) + byte2); + break; + case 4: + byte2 = byte & 0x0f; + byte1 = byte >> 4; + leftOver.push(byte1, byte2); + break; + case 2: + byte4 = byte & 3; + byte3 = (byte >> 2) & 3; + byte2 = (byte >> 4) & 3; + byte1 = (byte >> 6) & 3; + leftOver.push(byte1, byte2, byte3, byte4); + break; + case 1: + byte8 = byte & 1; + byte7 = (byte >> 1) & 1; + byte6 = (byte >> 2) & 1; + byte5 = (byte >> 3) & 1; + byte4 = (byte >> 4) & 1; + byte3 = (byte >> 5) & 1; + byte2 = (byte >> 6) & 1; + byte1 = (byte >> 7) & 1; + leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8); + break; + } + } + + return { + get: function (count) { + while (leftOver.length < count) { + split(); + } + let returner = leftOver.slice(0, count); + leftOver = leftOver.slice(count); + return returner; + }, + resetAfterLine: function () { + leftOver.length = 0; + }, + end: function () { + if (i !== data.length) { + throw new Error("extra data found"); + } + }, + }; +} + +function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) { + // eslint-disable-line max-params + let imageWidth = image.width; + let imageHeight = image.height; + let imagePass = image.index; + for (let y = 0; y < imageHeight; y++) { + for (let x = 0; x < imageWidth; x++) { + let pxPos = getPxPos(x, y, imagePass); + pixelBppMapper[bpp](pxData, data, pxPos, rawPos); + rawPos += bpp; //eslint-disable-line no-param-reassign + } + } + return rawPos; +} + +function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) { + // eslint-disable-line max-params + let imageWidth = image.width; + let imageHeight = image.height; + let imagePass = image.index; + for (let y = 0; y < imageHeight; y++) { + for (let x = 0; x < imageWidth; x++) { + let pixelData = bits.get(bpp); + let pxPos = getPxPos(x, y, imagePass); + pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit); + } + bits.resetAfterLine(); + } +} + +exports.dataToBitMap = function (data, bitmapInfo) { + let width = bitmapInfo.width; + let height = bitmapInfo.height; + let depth = bitmapInfo.depth; + let bpp = bitmapInfo.bpp; + let interlace = bitmapInfo.interlace; + let bits; + + if (depth !== 8) { + bits = bitRetriever(data, depth); + } + let pxData; + if (depth <= 8) { + pxData = Buffer.alloc(width * height * 4); + } else { + pxData = new Uint16Array(width * height * 4); + } + let maxBit = Math.pow(2, depth) - 1; + let rawPos = 0; + let images; + let getPxPos; + + if (interlace) { + images = interlaceUtils.getImagePasses(width, height); + getPxPos = interlaceUtils.getInterlaceIterator(width, height); + } else { + let nonInterlacedPxPos = 0; + getPxPos = function () { + let returner = nonInterlacedPxPos; + nonInterlacedPxPos += 4; + return returner; + }; + images = [{ width: width, height: height }]; + } + + for (let imageIndex = 0; imageIndex < images.length; imageIndex++) { + if (depth === 8) { + rawPos = mapImage8Bit( + images[imageIndex], + pxData, + getPxPos, + bpp, + data, + rawPos + ); + } else { + mapImageCustomBit( + images[imageIndex], + pxData, + getPxPos, + bpp, + bits, + maxBit + ); + } + } + if (depth === 8) { + if (rawPos !== data.length) { + throw new Error("extra data found"); + } + } else { + bits.end(); + } + + return pxData; +}; diff --git a/backend/node_modules/pngjs/lib/bitpacker.js b/backend/node_modules/pngjs/lib/bitpacker.js new file mode 100644 index 00000000..d7a4e656 --- /dev/null +++ b/backend/node_modules/pngjs/lib/bitpacker.js @@ -0,0 +1,158 @@ +"use strict"; + +let constants = require("./constants"); + +module.exports = function (dataIn, width, height, options) { + let outHasAlpha = + [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf( + options.colorType + ) !== -1; + if (options.colorType === options.inputColorType) { + let bigEndian = (function () { + let buffer = new ArrayBuffer(2); + new DataView(buffer).setInt16(0, 256, true /* littleEndian */); + // Int16Array uses the platform's endianness. + return new Int16Array(buffer)[0] !== 256; + })(); + // If no need to convert to grayscale and alpha is present/absent in both, take a fast route + if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) { + return dataIn; + } + } + + // map to a UInt16 array if data is 16bit, fix endianness below + let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer); + + let maxValue = 255; + let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType]; + if (inBpp === 4 && !options.inputHasAlpha) { + inBpp = 3; + } + let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType]; + if (options.bitDepth === 16) { + maxValue = 65535; + outBpp *= 2; + } + let outData = Buffer.alloc(width * height * outBpp); + + let inIndex = 0; + let outIndex = 0; + + let bgColor = options.bgColor || {}; + if (bgColor.red === undefined) { + bgColor.red = maxValue; + } + if (bgColor.green === undefined) { + bgColor.green = maxValue; + } + if (bgColor.blue === undefined) { + bgColor.blue = maxValue; + } + + function getRGBA() { + let red; + let green; + let blue; + let alpha = maxValue; + switch (options.inputColorType) { + case constants.COLORTYPE_COLOR_ALPHA: + alpha = data[inIndex + 3]; + red = data[inIndex]; + green = data[inIndex + 1]; + blue = data[inIndex + 2]; + break; + case constants.COLORTYPE_COLOR: + red = data[inIndex]; + green = data[inIndex + 1]; + blue = data[inIndex + 2]; + break; + case constants.COLORTYPE_ALPHA: + alpha = data[inIndex + 1]; + red = data[inIndex]; + green = red; + blue = red; + break; + case constants.COLORTYPE_GRAYSCALE: + red = data[inIndex]; + green = red; + blue = red; + break; + default: + throw new Error( + "input color type:" + + options.inputColorType + + " is not supported at present" + ); + } + + if (options.inputHasAlpha) { + if (!outHasAlpha) { + alpha /= maxValue; + red = Math.min( + Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0), + maxValue + ); + green = Math.min( + Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0), + maxValue + ); + blue = Math.min( + Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0), + maxValue + ); + } + } + return { red: red, green: green, blue: blue, alpha: alpha }; + } + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + let rgba = getRGBA(data, inIndex); + + switch (options.colorType) { + case constants.COLORTYPE_COLOR_ALPHA: + case constants.COLORTYPE_COLOR: + if (options.bitDepth === 8) { + outData[outIndex] = rgba.red; + outData[outIndex + 1] = rgba.green; + outData[outIndex + 2] = rgba.blue; + if (outHasAlpha) { + outData[outIndex + 3] = rgba.alpha; + } + } else { + outData.writeUInt16BE(rgba.red, outIndex); + outData.writeUInt16BE(rgba.green, outIndex + 2); + outData.writeUInt16BE(rgba.blue, outIndex + 4); + if (outHasAlpha) { + outData.writeUInt16BE(rgba.alpha, outIndex + 6); + } + } + break; + case constants.COLORTYPE_ALPHA: + case constants.COLORTYPE_GRAYSCALE: { + // Convert to grayscale and alpha + let grayscale = (rgba.red + rgba.green + rgba.blue) / 3; + if (options.bitDepth === 8) { + outData[outIndex] = grayscale; + if (outHasAlpha) { + outData[outIndex + 1] = rgba.alpha; + } + } else { + outData.writeUInt16BE(grayscale, outIndex); + if (outHasAlpha) { + outData.writeUInt16BE(rgba.alpha, outIndex + 2); + } + } + break; + } + default: + throw new Error("unrecognised color Type " + options.colorType); + } + + inIndex += inBpp; + outIndex += outBpp; + } + } + + return outData; +}; diff --git a/backend/node_modules/pngjs/lib/chunkstream.js b/backend/node_modules/pngjs/lib/chunkstream.js new file mode 100644 index 00000000..95b46d48 --- /dev/null +++ b/backend/node_modules/pngjs/lib/chunkstream.js @@ -0,0 +1,189 @@ +"use strict"; + +let util = require("util"); +let Stream = require("stream"); + +let ChunkStream = (module.exports = function () { + Stream.call(this); + + this._buffers = []; + this._buffered = 0; + + this._reads = []; + this._paused = false; + + this._encoding = "utf8"; + this.writable = true; +}); +util.inherits(ChunkStream, Stream); + +ChunkStream.prototype.read = function (length, callback) { + this._reads.push({ + length: Math.abs(length), // if length < 0 then at most this length + allowLess: length < 0, + func: callback, + }); + + process.nextTick( + function () { + this._process(); + + // its paused and there is not enought data then ask for more + if (this._paused && this._reads && this._reads.length > 0) { + this._paused = false; + + this.emit("drain"); + } + }.bind(this) + ); +}; + +ChunkStream.prototype.write = function (data, encoding) { + if (!this.writable) { + this.emit("error", new Error("Stream not writable")); + return false; + } + + let dataBuffer; + if (Buffer.isBuffer(data)) { + dataBuffer = data; + } else { + dataBuffer = Buffer.from(data, encoding || this._encoding); + } + + this._buffers.push(dataBuffer); + this._buffered += dataBuffer.length; + + this._process(); + + // ok if there are no more read requests + if (this._reads && this._reads.length === 0) { + this._paused = true; + } + + return this.writable && !this._paused; +}; + +ChunkStream.prototype.end = function (data, encoding) { + if (data) { + this.write(data, encoding); + } + + this.writable = false; + + // already destroyed + if (!this._buffers) { + return; + } + + // enqueue or handle end + if (this._buffers.length === 0) { + this._end(); + } else { + this._buffers.push(null); + this._process(); + } +}; + +ChunkStream.prototype.destroySoon = ChunkStream.prototype.end; + +ChunkStream.prototype._end = function () { + if (this._reads.length > 0) { + this.emit("error", new Error("Unexpected end of input")); + } + + this.destroy(); +}; + +ChunkStream.prototype.destroy = function () { + if (!this._buffers) { + return; + } + + this.writable = false; + this._reads = null; + this._buffers = null; + + this.emit("close"); +}; + +ChunkStream.prototype._processReadAllowingLess = function (read) { + // ok there is any data so that we can satisfy this request + this._reads.shift(); // == read + + // first we need to peek into first buffer + let smallerBuf = this._buffers[0]; + + // ok there is more data than we need + if (smallerBuf.length > read.length) { + this._buffered -= read.length; + this._buffers[0] = smallerBuf.slice(read.length); + + read.func.call(this, smallerBuf.slice(0, read.length)); + } else { + // ok this is less than maximum length so use it all + this._buffered -= smallerBuf.length; + this._buffers.shift(); // == smallerBuf + + read.func.call(this, smallerBuf); + } +}; + +ChunkStream.prototype._processRead = function (read) { + this._reads.shift(); // == read + + let pos = 0; + let count = 0; + let data = Buffer.alloc(read.length); + + // create buffer for all data + while (pos < read.length) { + let buf = this._buffers[count++]; + let len = Math.min(buf.length, read.length - pos); + + buf.copy(data, pos, 0, len); + pos += len; + + // last buffer wasn't used all so just slice it and leave + if (len !== buf.length) { + this._buffers[--count] = buf.slice(len); + } + } + + // remove all used buffers + if (count > 0) { + this._buffers.splice(0, count); + } + + this._buffered -= read.length; + + read.func.call(this, data); +}; + +ChunkStream.prototype._process = function () { + try { + // as long as there is any data and read requests + while (this._buffered > 0 && this._reads && this._reads.length > 0) { + let read = this._reads[0]; + + // read any data (but no more than length) + if (read.allowLess) { + this._processReadAllowingLess(read); + } else if (this._buffered >= read.length) { + // ok we can meet some expectations + + this._processRead(read); + } else { + // not enought data to satisfy first request in queue + // so we need to wait for more + break; + } + } + + if (this._buffers && !this.writable) { + this._end(); + } + } catch (ex) { + this.emit("error", ex); + } +}; diff --git a/backend/node_modules/pngjs/lib/constants.js b/backend/node_modules/pngjs/lib/constants.js new file mode 100644 index 00000000..21fdad68 --- /dev/null +++ b/backend/node_modules/pngjs/lib/constants.js @@ -0,0 +1,32 @@ +"use strict"; + +module.exports = { + PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], + + TYPE_IHDR: 0x49484452, + TYPE_IEND: 0x49454e44, + TYPE_IDAT: 0x49444154, + TYPE_PLTE: 0x504c5445, + TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase + TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase + + // color-type bits + COLORTYPE_GRAYSCALE: 0, + COLORTYPE_PALETTE: 1, + COLORTYPE_COLOR: 2, + COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha + + // color-type combinations + COLORTYPE_PALETTE_COLOR: 3, + COLORTYPE_COLOR_ALPHA: 6, + + COLORTYPE_TO_BPP_MAP: { + 0: 1, + 2: 3, + 3: 1, + 4: 2, + 6: 4, + }, + + GAMMA_DIVISION: 100000, +}; diff --git a/backend/node_modules/pngjs/lib/crc.js b/backend/node_modules/pngjs/lib/crc.js new file mode 100644 index 00000000..950ec8ae --- /dev/null +++ b/backend/node_modules/pngjs/lib/crc.js @@ -0,0 +1,40 @@ +"use strict"; + +let crcTable = []; + +(function () { + for (let i = 0; i < 256; i++) { + let currentCrc = i; + for (let j = 0; j < 8; j++) { + if (currentCrc & 1) { + currentCrc = 0xedb88320 ^ (currentCrc >>> 1); + } else { + currentCrc = currentCrc >>> 1; + } + } + crcTable[i] = currentCrc; + } +})(); + +let CrcCalculator = (module.exports = function () { + this._crc = -1; +}); + +CrcCalculator.prototype.write = function (data) { + for (let i = 0; i < data.length; i++) { + this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8); + } + return true; +}; + +CrcCalculator.prototype.crc32 = function () { + return this._crc ^ -1; +}; + +CrcCalculator.crc32 = function (buf) { + let crc = -1; + for (let i = 0; i < buf.length; i++) { + crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8); + } + return crc ^ -1; +}; diff --git a/backend/node_modules/pngjs/lib/filter-pack.js b/backend/node_modules/pngjs/lib/filter-pack.js new file mode 100644 index 00000000..32c85c40 --- /dev/null +++ b/backend/node_modules/pngjs/lib/filter-pack.js @@ -0,0 +1,171 @@ +"use strict"; + +let paethPredictor = require("./paeth-predictor"); + +function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) { + for (let x = 0; x < byteWidth; x++) { + rawData[rawPos + x] = pxData[pxPos + x]; + } +} + +function filterSumNone(pxData, pxPos, byteWidth) { + let sum = 0; + let length = pxPos + byteWidth; + + for (let i = pxPos; i < length; i++) { + sum += Math.abs(pxData[i]); + } + return sum; +} + +function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let val = pxData[pxPos + x] - left; + + rawData[rawPos + x] = val; + } +} + +function filterSumSub(pxData, pxPos, byteWidth, bpp) { + let sum = 0; + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let val = pxData[pxPos + x] - left; + + sum += Math.abs(val); + } + + return sum; +} + +function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) { + for (let x = 0; x < byteWidth; x++) { + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let val = pxData[pxPos + x] - up; + + rawData[rawPos + x] = val; + } +} + +function filterSumUp(pxData, pxPos, byteWidth) { + let sum = 0; + let length = pxPos + byteWidth; + for (let x = pxPos; x < length; x++) { + let up = pxPos > 0 ? pxData[x - byteWidth] : 0; + let val = pxData[x] - up; + + sum += Math.abs(val); + } + + return sum; +} + +function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let val = pxData[pxPos + x] - ((left + up) >> 1); + + rawData[rawPos + x] = val; + } +} + +function filterSumAvg(pxData, pxPos, byteWidth, bpp) { + let sum = 0; + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let val = pxData[pxPos + x] - ((left + up) >> 1); + + sum += Math.abs(val); + } + + return sum; +} + +function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let upleft = + pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0; + let val = pxData[pxPos + x] - paethPredictor(left, up, upleft); + + rawData[rawPos + x] = val; + } +} + +function filterSumPaeth(pxData, pxPos, byteWidth, bpp) { + let sum = 0; + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let upleft = + pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0; + let val = pxData[pxPos + x] - paethPredictor(left, up, upleft); + + sum += Math.abs(val); + } + + return sum; +} + +let filters = { + 0: filterNone, + 1: filterSub, + 2: filterUp, + 3: filterAvg, + 4: filterPaeth, +}; + +let filterSums = { + 0: filterSumNone, + 1: filterSumSub, + 2: filterSumUp, + 3: filterSumAvg, + 4: filterSumPaeth, +}; + +module.exports = function (pxData, width, height, options, bpp) { + let filterTypes; + if (!("filterType" in options) || options.filterType === -1) { + filterTypes = [0, 1, 2, 3, 4]; + } else if (typeof options.filterType === "number") { + filterTypes = [options.filterType]; + } else { + throw new Error("unrecognised filter types"); + } + + if (options.bitDepth === 16) { + bpp *= 2; + } + let byteWidth = width * bpp; + let rawPos = 0; + let pxPos = 0; + let rawData = Buffer.alloc((byteWidth + 1) * height); + + let sel = filterTypes[0]; + + for (let y = 0; y < height; y++) { + if (filterTypes.length > 1) { + // find best filter for this line (with lowest sum of values) + let min = Infinity; + + for (let i = 0; i < filterTypes.length; i++) { + let sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp); + if (sum < min) { + sel = filterTypes[i]; + min = sum; + } + } + } + + rawData[rawPos] = sel; + rawPos++; + filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp); + rawPos += byteWidth; + pxPos += byteWidth; + } + return rawData; +}; diff --git a/backend/node_modules/pngjs/lib/filter-parse-async.js b/backend/node_modules/pngjs/lib/filter-parse-async.js new file mode 100644 index 00000000..832b86cd --- /dev/null +++ b/backend/node_modules/pngjs/lib/filter-parse-async.js @@ -0,0 +1,24 @@ +"use strict"; + +let util = require("util"); +let ChunkStream = require("./chunkstream"); +let Filter = require("./filter-parse"); + +let FilterAsync = (module.exports = function (bitmapInfo) { + ChunkStream.call(this); + + let buffers = []; + let that = this; + this._filter = new Filter(bitmapInfo, { + read: this.read.bind(this), + write: function (buffer) { + buffers.push(buffer); + }, + complete: function () { + that.emit("complete", Buffer.concat(buffers)); + }, + }); + + this._filter.start(); +}); +util.inherits(FilterAsync, ChunkStream); diff --git a/backend/node_modules/pngjs/lib/filter-parse-sync.js b/backend/node_modules/pngjs/lib/filter-parse-sync.js new file mode 100644 index 00000000..6924d161 --- /dev/null +++ b/backend/node_modules/pngjs/lib/filter-parse-sync.js @@ -0,0 +1,21 @@ +"use strict"; + +let SyncReader = require("./sync-reader"); +let Filter = require("./filter-parse"); + +exports.process = function (inBuffer, bitmapInfo) { + let outBuffers = []; + let reader = new SyncReader(inBuffer); + let filter = new Filter(bitmapInfo, { + read: reader.read.bind(reader), + write: function (bufferPart) { + outBuffers.push(bufferPart); + }, + complete: function () {}, + }); + + filter.start(); + reader.process(); + + return Buffer.concat(outBuffers); +}; diff --git a/backend/node_modules/pngjs/lib/filter-parse.js b/backend/node_modules/pngjs/lib/filter-parse.js new file mode 100644 index 00000000..3a32e5ee --- /dev/null +++ b/backend/node_modules/pngjs/lib/filter-parse.js @@ -0,0 +1,177 @@ +"use strict"; + +let interlaceUtils = require("./interlace"); +let paethPredictor = require("./paeth-predictor"); + +function getByteWidth(width, bpp, depth) { + let byteWidth = width * bpp; + if (depth !== 8) { + byteWidth = Math.ceil(byteWidth / (8 / depth)); + } + return byteWidth; +} + +let Filter = (module.exports = function (bitmapInfo, dependencies) { + let width = bitmapInfo.width; + let height = bitmapInfo.height; + let interlace = bitmapInfo.interlace; + let bpp = bitmapInfo.bpp; + let depth = bitmapInfo.depth; + + this.read = dependencies.read; + this.write = dependencies.write; + this.complete = dependencies.complete; + + this._imageIndex = 0; + this._images = []; + if (interlace) { + let passes = interlaceUtils.getImagePasses(width, height); + for (let i = 0; i < passes.length; i++) { + this._images.push({ + byteWidth: getByteWidth(passes[i].width, bpp, depth), + height: passes[i].height, + lineIndex: 0, + }); + } + } else { + this._images.push({ + byteWidth: getByteWidth(width, bpp, depth), + height: height, + lineIndex: 0, + }); + } + + // when filtering the line we look at the pixel to the left + // the spec also says it is done on a byte level regardless of the number of pixels + // so if the depth is byte compatible (8 or 16) we subtract the bpp in order to compare back + // a pixel rather than just a different byte part. However if we are sub byte, we ignore. + if (depth === 8) { + this._xComparison = bpp; + } else if (depth === 16) { + this._xComparison = bpp * 2; + } else { + this._xComparison = 1; + } +}); + +Filter.prototype.start = function () { + this.read( + this._images[this._imageIndex].byteWidth + 1, + this._reverseFilterLine.bind(this) + ); +}; + +Filter.prototype._unFilterType1 = function ( + rawData, + unfilteredLine, + byteWidth +) { + let xComparison = this._xComparison; + let xBiggerThan = xComparison - 1; + + for (let x = 0; x < byteWidth; x++) { + let rawByte = rawData[1 + x]; + let f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0; + unfilteredLine[x] = rawByte + f1Left; + } +}; + +Filter.prototype._unFilterType2 = function ( + rawData, + unfilteredLine, + byteWidth +) { + let lastLine = this._lastLine; + + for (let x = 0; x < byteWidth; x++) { + let rawByte = rawData[1 + x]; + let f2Up = lastLine ? lastLine[x] : 0; + unfilteredLine[x] = rawByte + f2Up; + } +}; + +Filter.prototype._unFilterType3 = function ( + rawData, + unfilteredLine, + byteWidth +) { + let xComparison = this._xComparison; + let xBiggerThan = xComparison - 1; + let lastLine = this._lastLine; + + for (let x = 0; x < byteWidth; x++) { + let rawByte = rawData[1 + x]; + let f3Up = lastLine ? lastLine[x] : 0; + let f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0; + let f3Add = Math.floor((f3Left + f3Up) / 2); + unfilteredLine[x] = rawByte + f3Add; + } +}; + +Filter.prototype._unFilterType4 = function ( + rawData, + unfilteredLine, + byteWidth +) { + let xComparison = this._xComparison; + let xBiggerThan = xComparison - 1; + let lastLine = this._lastLine; + + for (let x = 0; x < byteWidth; x++) { + let rawByte = rawData[1 + x]; + let f4Up = lastLine ? lastLine[x] : 0; + let f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0; + let f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0; + let f4Add = paethPredictor(f4Left, f4Up, f4UpLeft); + unfilteredLine[x] = rawByte + f4Add; + } +}; + +Filter.prototype._reverseFilterLine = function (rawData) { + let filter = rawData[0]; + let unfilteredLine; + let currentImage = this._images[this._imageIndex]; + let byteWidth = currentImage.byteWidth; + + if (filter === 0) { + unfilteredLine = rawData.slice(1, byteWidth + 1); + } else { + unfilteredLine = Buffer.alloc(byteWidth); + + switch (filter) { + case 1: + this._unFilterType1(rawData, unfilteredLine, byteWidth); + break; + case 2: + this._unFilterType2(rawData, unfilteredLine, byteWidth); + break; + case 3: + this._unFilterType3(rawData, unfilteredLine, byteWidth); + break; + case 4: + this._unFilterType4(rawData, unfilteredLine, byteWidth); + break; + default: + throw new Error("Unrecognised filter type - " + filter); + } + } + + this.write(unfilteredLine); + + currentImage.lineIndex++; + if (currentImage.lineIndex >= currentImage.height) { + this._lastLine = null; + this._imageIndex++; + currentImage = this._images[this._imageIndex]; + } else { + this._lastLine = unfilteredLine; + } + + if (currentImage) { + // read, using the byte width that may be from the new current image + this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this)); + } else { + this._lastLine = null; + this.complete(); + } +}; diff --git a/backend/node_modules/pngjs/lib/format-normaliser.js b/backend/node_modules/pngjs/lib/format-normaliser.js new file mode 100644 index 00000000..634d566c --- /dev/null +++ b/backend/node_modules/pngjs/lib/format-normaliser.js @@ -0,0 +1,93 @@ +"use strict"; + +function dePalette(indata, outdata, width, height, palette) { + let pxPos = 0; + // use values from palette + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + let color = palette[indata[pxPos]]; + + if (!color) { + throw new Error("index " + indata[pxPos] + " not in palette"); + } + + for (let i = 0; i < 4; i++) { + outdata[pxPos + i] = color[i]; + } + pxPos += 4; + } + } +} + +function replaceTransparentColor(indata, outdata, width, height, transColor) { + let pxPos = 0; + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + let makeTrans = false; + + if (transColor.length === 1) { + if (transColor[0] === indata[pxPos]) { + makeTrans = true; + } + } else if ( + transColor[0] === indata[pxPos] && + transColor[1] === indata[pxPos + 1] && + transColor[2] === indata[pxPos + 2] + ) { + makeTrans = true; + } + if (makeTrans) { + for (let i = 0; i < 4; i++) { + outdata[pxPos + i] = 0; + } + } + pxPos += 4; + } + } +} + +function scaleDepth(indata, outdata, width, height, depth) { + let maxOutSample = 255; + let maxInSample = Math.pow(2, depth) - 1; + let pxPos = 0; + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + for (let i = 0; i < 4; i++) { + outdata[pxPos + i] = Math.floor( + (indata[pxPos + i] * maxOutSample) / maxInSample + 0.5 + ); + } + pxPos += 4; + } + } +} + +module.exports = function (indata, imageData) { + let depth = imageData.depth; + let width = imageData.width; + let height = imageData.height; + let colorType = imageData.colorType; + let transColor = imageData.transColor; + let palette = imageData.palette; + + let outdata = indata; // only different for 16 bits + + if (colorType === 3) { + // paletted + dePalette(indata, outdata, width, height, palette); + } else { + if (transColor) { + replaceTransparentColor(indata, outdata, width, height, transColor); + } + // if it needs scaling + if (depth !== 8) { + // if we need to change the buffer size + if (depth === 16) { + outdata = Buffer.alloc(width * height * 4); + } + scaleDepth(indata, outdata, width, height, depth); + } + } + return outdata; +}; diff --git a/backend/node_modules/pngjs/lib/interlace.js b/backend/node_modules/pngjs/lib/interlace.js new file mode 100644 index 00000000..a035cb15 --- /dev/null +++ b/backend/node_modules/pngjs/lib/interlace.js @@ -0,0 +1,95 @@ +"use strict"; + +// Adam 7 +// 0 1 2 3 4 5 6 7 +// 0 x 6 4 6 x 6 4 6 +// 1 7 7 7 7 7 7 7 7 +// 2 5 6 5 6 5 6 5 6 +// 3 7 7 7 7 7 7 7 7 +// 4 3 6 4 6 3 6 4 6 +// 5 7 7 7 7 7 7 7 7 +// 6 5 6 5 6 5 6 5 6 +// 7 7 7 7 7 7 7 7 7 + +let imagePasses = [ + { + // pass 1 - 1px + x: [0], + y: [0], + }, + { + // pass 2 - 1px + x: [4], + y: [0], + }, + { + // pass 3 - 2px + x: [0, 4], + y: [4], + }, + { + // pass 4 - 4px + x: [2, 6], + y: [0, 4], + }, + { + // pass 5 - 8px + x: [0, 2, 4, 6], + y: [2, 6], + }, + { + // pass 6 - 16px + x: [1, 3, 5, 7], + y: [0, 2, 4, 6], + }, + { + // pass 7 - 32px + x: [0, 1, 2, 3, 4, 5, 6, 7], + y: [1, 3, 5, 7], + }, +]; + +exports.getImagePasses = function (width, height) { + let images = []; + let xLeftOver = width % 8; + let yLeftOver = height % 8; + let xRepeats = (width - xLeftOver) / 8; + let yRepeats = (height - yLeftOver) / 8; + for (let i = 0; i < imagePasses.length; i++) { + let pass = imagePasses[i]; + let passWidth = xRepeats * pass.x.length; + let passHeight = yRepeats * pass.y.length; + for (let j = 0; j < pass.x.length; j++) { + if (pass.x[j] < xLeftOver) { + passWidth++; + } else { + break; + } + } + for (let j = 0; j < pass.y.length; j++) { + if (pass.y[j] < yLeftOver) { + passHeight++; + } else { + break; + } + } + if (passWidth > 0 && passHeight > 0) { + images.push({ width: passWidth, height: passHeight, index: i }); + } + } + return images; +}; + +exports.getInterlaceIterator = function (width) { + return function (x, y, pass) { + let outerXLeftOver = x % imagePasses[pass].x.length; + let outerX = + ((x - outerXLeftOver) / imagePasses[pass].x.length) * 8 + + imagePasses[pass].x[outerXLeftOver]; + let outerYLeftOver = y % imagePasses[pass].y.length; + let outerY = + ((y - outerYLeftOver) / imagePasses[pass].y.length) * 8 + + imagePasses[pass].y[outerYLeftOver]; + return outerX * 4 + outerY * width * 4; + }; +}; diff --git a/backend/node_modules/pngjs/lib/packer-async.js b/backend/node_modules/pngjs/lib/packer-async.js new file mode 100644 index 00000000..f3df73aa --- /dev/null +++ b/backend/node_modules/pngjs/lib/packer-async.js @@ -0,0 +1,50 @@ +"use strict"; + +let util = require("util"); +let Stream = require("stream"); +let constants = require("./constants"); +let Packer = require("./packer"); + +let PackerAsync = (module.exports = function (opt) { + Stream.call(this); + + let options = opt || {}; + + this._packer = new Packer(options); + this._deflate = this._packer.createDeflate(); + + this.readable = true; +}); +util.inherits(PackerAsync, Stream); + +PackerAsync.prototype.pack = function (data, width, height, gamma) { + // Signature + this.emit("data", Buffer.from(constants.PNG_SIGNATURE)); + this.emit("data", this._packer.packIHDR(width, height)); + + if (gamma) { + this.emit("data", this._packer.packGAMA(gamma)); + } + + let filteredData = this._packer.filterData(data, width, height); + + // compress it + this._deflate.on("error", this.emit.bind(this, "error")); + + this._deflate.on( + "data", + function (compressedData) { + this.emit("data", this._packer.packIDAT(compressedData)); + }.bind(this) + ); + + this._deflate.on( + "end", + function () { + this.emit("data", this._packer.packIEND()); + this.emit("end"); + }.bind(this) + ); + + this._deflate.end(filteredData); +}; diff --git a/backend/node_modules/pngjs/lib/packer-sync.js b/backend/node_modules/pngjs/lib/packer-sync.js new file mode 100644 index 00000000..f5ab0b3d --- /dev/null +++ b/backend/node_modules/pngjs/lib/packer-sync.js @@ -0,0 +1,56 @@ +"use strict"; + +let hasSyncZlib = true; +let zlib = require("zlib"); +if (!zlib.deflateSync) { + hasSyncZlib = false; +} +let constants = require("./constants"); +let Packer = require("./packer"); + +module.exports = function (metaData, opt) { + if (!hasSyncZlib) { + throw new Error( + "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0" + ); + } + + let options = opt || {}; + + let packer = new Packer(options); + + let chunks = []; + + // Signature + chunks.push(Buffer.from(constants.PNG_SIGNATURE)); + + // Header + chunks.push(packer.packIHDR(metaData.width, metaData.height)); + + if (metaData.gamma) { + chunks.push(packer.packGAMA(metaData.gamma)); + } + + let filteredData = packer.filterData( + metaData.data, + metaData.width, + metaData.height + ); + + // compress it + let compressedData = zlib.deflateSync( + filteredData, + packer.getDeflateOptions() + ); + filteredData = null; + + if (!compressedData || !compressedData.length) { + throw new Error("bad png - invalid compressed data response"); + } + chunks.push(packer.packIDAT(compressedData)); + + // End + chunks.push(packer.packIEND()); + + return Buffer.concat(chunks); +}; diff --git a/backend/node_modules/pngjs/lib/packer.js b/backend/node_modules/pngjs/lib/packer.js new file mode 100644 index 00000000..4aba12c8 --- /dev/null +++ b/backend/node_modules/pngjs/lib/packer.js @@ -0,0 +1,129 @@ +"use strict"; + +let constants = require("./constants"); +let CrcStream = require("./crc"); +let bitPacker = require("./bitpacker"); +let filter = require("./filter-pack"); +let zlib = require("zlib"); + +let Packer = (module.exports = function (options) { + this._options = options; + + options.deflateChunkSize = options.deflateChunkSize || 32 * 1024; + options.deflateLevel = + options.deflateLevel != null ? options.deflateLevel : 9; + options.deflateStrategy = + options.deflateStrategy != null ? options.deflateStrategy : 3; + options.inputHasAlpha = + options.inputHasAlpha != null ? options.inputHasAlpha : true; + options.deflateFactory = options.deflateFactory || zlib.createDeflate; + options.bitDepth = options.bitDepth || 8; + // This is outputColorType + options.colorType = + typeof options.colorType === "number" + ? options.colorType + : constants.COLORTYPE_COLOR_ALPHA; + options.inputColorType = + typeof options.inputColorType === "number" + ? options.inputColorType + : constants.COLORTYPE_COLOR_ALPHA; + + if ( + [ + constants.COLORTYPE_GRAYSCALE, + constants.COLORTYPE_COLOR, + constants.COLORTYPE_COLOR_ALPHA, + constants.COLORTYPE_ALPHA, + ].indexOf(options.colorType) === -1 + ) { + throw new Error( + "option color type:" + options.colorType + " is not supported at present" + ); + } + if ( + [ + constants.COLORTYPE_GRAYSCALE, + constants.COLORTYPE_COLOR, + constants.COLORTYPE_COLOR_ALPHA, + constants.COLORTYPE_ALPHA, + ].indexOf(options.inputColorType) === -1 + ) { + throw new Error( + "option input color type:" + + options.inputColorType + + " is not supported at present" + ); + } + if (options.bitDepth !== 8 && options.bitDepth !== 16) { + throw new Error( + "option bit depth:" + options.bitDepth + " is not supported at present" + ); + } +}); + +Packer.prototype.getDeflateOptions = function () { + return { + chunkSize: this._options.deflateChunkSize, + level: this._options.deflateLevel, + strategy: this._options.deflateStrategy, + }; +}; + +Packer.prototype.createDeflate = function () { + return this._options.deflateFactory(this.getDeflateOptions()); +}; + +Packer.prototype.filterData = function (data, width, height) { + // convert to correct format for filtering (e.g. right bpp and bit depth) + let packedData = bitPacker(data, width, height, this._options); + + // filter pixel data + let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType]; + let filteredData = filter(packedData, width, height, this._options, bpp); + return filteredData; +}; + +Packer.prototype._packChunk = function (type, data) { + let len = data ? data.length : 0; + let buf = Buffer.alloc(len + 12); + + buf.writeUInt32BE(len, 0); + buf.writeUInt32BE(type, 4); + + if (data) { + data.copy(buf, 8); + } + + buf.writeInt32BE( + CrcStream.crc32(buf.slice(4, buf.length - 4)), + buf.length - 4 + ); + return buf; +}; + +Packer.prototype.packGAMA = function (gamma) { + let buf = Buffer.alloc(4); + buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0); + return this._packChunk(constants.TYPE_gAMA, buf); +}; + +Packer.prototype.packIHDR = function (width, height) { + let buf = Buffer.alloc(13); + buf.writeUInt32BE(width, 0); + buf.writeUInt32BE(height, 4); + buf[8] = this._options.bitDepth; // Bit depth + buf[9] = this._options.colorType; // colorType + buf[10] = 0; // compression + buf[11] = 0; // filter + buf[12] = 0; // interlace + + return this._packChunk(constants.TYPE_IHDR, buf); +}; + +Packer.prototype.packIDAT = function (data) { + return this._packChunk(constants.TYPE_IDAT, data); +}; + +Packer.prototype.packIEND = function () { + return this._packChunk(constants.TYPE_IEND, null); +}; diff --git a/backend/node_modules/pngjs/lib/paeth-predictor.js b/backend/node_modules/pngjs/lib/paeth-predictor.js new file mode 100644 index 00000000..9634497d --- /dev/null +++ b/backend/node_modules/pngjs/lib/paeth-predictor.js @@ -0,0 +1,16 @@ +"use strict"; + +module.exports = function paethPredictor(left, above, upLeft) { + let paeth = left + above - upLeft; + let pLeft = Math.abs(paeth - left); + let pAbove = Math.abs(paeth - above); + let pUpLeft = Math.abs(paeth - upLeft); + + if (pLeft <= pAbove && pLeft <= pUpLeft) { + return left; + } + if (pAbove <= pUpLeft) { + return above; + } + return upLeft; +}; diff --git a/backend/node_modules/pngjs/lib/parser-async.js b/backend/node_modules/pngjs/lib/parser-async.js new file mode 100644 index 00000000..a69d1533 --- /dev/null +++ b/backend/node_modules/pngjs/lib/parser-async.js @@ -0,0 +1,165 @@ +"use strict"; + +let util = require("util"); +let zlib = require("zlib"); +let ChunkStream = require("./chunkstream"); +let FilterAsync = require("./filter-parse-async"); +let Parser = require("./parser"); +let bitmapper = require("./bitmapper"); +let formatNormaliser = require("./format-normaliser"); + +let ParserAsync = (module.exports = function (options) { + ChunkStream.call(this); + + this._parser = new Parser(options, { + read: this.read.bind(this), + error: this._handleError.bind(this), + metadata: this._handleMetaData.bind(this), + gamma: this.emit.bind(this, "gamma"), + palette: this._handlePalette.bind(this), + transColor: this._handleTransColor.bind(this), + finished: this._finished.bind(this), + inflateData: this._inflateData.bind(this), + simpleTransparency: this._simpleTransparency.bind(this), + headersFinished: this._headersFinished.bind(this), + }); + this._options = options; + this.writable = true; + + this._parser.start(); +}); +util.inherits(ParserAsync, ChunkStream); + +ParserAsync.prototype._handleError = function (err) { + this.emit("error", err); + + this.writable = false; + + this.destroy(); + + if (this._inflate && this._inflate.destroy) { + this._inflate.destroy(); + } + + if (this._filter) { + this._filter.destroy(); + // For backward compatibility with Node 7 and below. + // Suppress errors due to _inflate calling write() even after + // it's destroy()'ed. + this._filter.on("error", function () {}); + } + + this.errord = true; +}; + +ParserAsync.prototype._inflateData = function (data) { + if (!this._inflate) { + if (this._bitmapInfo.interlace) { + this._inflate = zlib.createInflate(); + + this._inflate.on("error", this.emit.bind(this, "error")); + this._filter.on("complete", this._complete.bind(this)); + + this._inflate.pipe(this._filter); + } else { + let rowSize = + ((this._bitmapInfo.width * + this._bitmapInfo.bpp * + this._bitmapInfo.depth + + 7) >> + 3) + + 1; + let imageSize = rowSize * this._bitmapInfo.height; + let chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK); + + this._inflate = zlib.createInflate({ chunkSize: chunkSize }); + let leftToInflate = imageSize; + + let emitError = this.emit.bind(this, "error"); + this._inflate.on("error", function (err) { + if (!leftToInflate) { + return; + } + + emitError(err); + }); + this._filter.on("complete", this._complete.bind(this)); + + let filterWrite = this._filter.write.bind(this._filter); + this._inflate.on("data", function (chunk) { + if (!leftToInflate) { + return; + } + + if (chunk.length > leftToInflate) { + chunk = chunk.slice(0, leftToInflate); + } + + leftToInflate -= chunk.length; + + filterWrite(chunk); + }); + + this._inflate.on("end", this._filter.end.bind(this._filter)); + } + } + this._inflate.write(data); +}; + +ParserAsync.prototype._handleMetaData = function (metaData) { + this._metaData = metaData; + this._bitmapInfo = Object.create(metaData); + + this._filter = new FilterAsync(this._bitmapInfo); +}; + +ParserAsync.prototype._handleTransColor = function (transColor) { + this._bitmapInfo.transColor = transColor; +}; + +ParserAsync.prototype._handlePalette = function (palette) { + this._bitmapInfo.palette = palette; +}; + +ParserAsync.prototype._simpleTransparency = function () { + this._metaData.alpha = true; +}; + +ParserAsync.prototype._headersFinished = function () { + // Up until this point, we don't know if we have a tRNS chunk (alpha) + // so we can't emit metadata any earlier + this.emit("metadata", this._metaData); +}; + +ParserAsync.prototype._finished = function () { + if (this.errord) { + return; + } + + if (!this._inflate) { + this.emit("error", "No Inflate block"); + } else { + // no more data to inflate + this._inflate.end(); + } +}; + +ParserAsync.prototype._complete = function (filteredData) { + if (this.errord) { + return; + } + + let normalisedBitmapData; + + try { + let bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo); + + normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo); + bitmapData = null; + } catch (ex) { + this._handleError(ex); + return; + } + + this.emit("parsed", normalisedBitmapData); +}; diff --git a/backend/node_modules/pngjs/lib/parser-sync.js b/backend/node_modules/pngjs/lib/parser-sync.js new file mode 100644 index 00000000..e79796bb --- /dev/null +++ b/backend/node_modules/pngjs/lib/parser-sync.js @@ -0,0 +1,108 @@ +"use strict"; + +let hasSyncZlib = true; +let zlib = require("zlib"); +let inflateSync = require("./sync-inflate"); +if (!zlib.deflateSync) { + hasSyncZlib = false; +} +let SyncReader = require("./sync-reader"); +let FilterSync = require("./filter-parse-sync"); +let Parser = require("./parser"); +let bitmapper = require("./bitmapper"); +let formatNormaliser = require("./format-normaliser"); + +module.exports = function (buffer, options) { + if (!hasSyncZlib) { + throw new Error( + "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0" + ); + } + + let err; + function handleError(_err_) { + err = _err_; + } + + let metaData; + function handleMetaData(_metaData_) { + metaData = _metaData_; + } + + function handleTransColor(transColor) { + metaData.transColor = transColor; + } + + function handlePalette(palette) { + metaData.palette = palette; + } + + function handleSimpleTransparency() { + metaData.alpha = true; + } + + let gamma; + function handleGamma(_gamma_) { + gamma = _gamma_; + } + + let inflateDataList = []; + function handleInflateData(inflatedData) { + inflateDataList.push(inflatedData); + } + + let reader = new SyncReader(buffer); + + let parser = new Parser(options, { + read: reader.read.bind(reader), + error: handleError, + metadata: handleMetaData, + gamma: handleGamma, + palette: handlePalette, + transColor: handleTransColor, + inflateData: handleInflateData, + simpleTransparency: handleSimpleTransparency, + }); + + parser.start(); + reader.process(); + + if (err) { + throw err; + } + + //join together the inflate datas + let inflateData = Buffer.concat(inflateDataList); + inflateDataList.length = 0; + + let inflatedData; + if (metaData.interlace) { + inflatedData = zlib.inflateSync(inflateData); + } else { + let rowSize = + ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1; + let imageSize = rowSize * metaData.height; + inflatedData = inflateSync(inflateData, { + chunkSize: imageSize, + maxLength: imageSize, + }); + } + inflateData = null; + + if (!inflatedData || !inflatedData.length) { + throw new Error("bad png - invalid inflate data response"); + } + + let unfilteredData = FilterSync.process(inflatedData, metaData); + inflateData = null; + + let bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData); + unfilteredData = null; + + let normalisedBitmapData = formatNormaliser(bitmapData, metaData); + + metaData.data = normalisedBitmapData; + metaData.gamma = gamma || 0; + + return metaData; +}; diff --git a/backend/node_modules/pngjs/lib/parser.js b/backend/node_modules/pngjs/lib/parser.js new file mode 100644 index 00000000..51a8f2a5 --- /dev/null +++ b/backend/node_modules/pngjs/lib/parser.js @@ -0,0 +1,290 @@ +"use strict"; + +let constants = require("./constants"); +let CrcCalculator = require("./crc"); + +let Parser = (module.exports = function (options, dependencies) { + this._options = options; + options.checkCRC = options.checkCRC !== false; + + this._hasIHDR = false; + this._hasIEND = false; + this._emittedHeadersFinished = false; + + // input flags/metadata + this._palette = []; + this._colorType = 0; + + this._chunks = {}; + this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this); + this._chunks[constants.TYPE_IEND] = this._handleIEND.bind(this); + this._chunks[constants.TYPE_IDAT] = this._handleIDAT.bind(this); + this._chunks[constants.TYPE_PLTE] = this._handlePLTE.bind(this); + this._chunks[constants.TYPE_tRNS] = this._handleTRNS.bind(this); + this._chunks[constants.TYPE_gAMA] = this._handleGAMA.bind(this); + + this.read = dependencies.read; + this.error = dependencies.error; + this.metadata = dependencies.metadata; + this.gamma = dependencies.gamma; + this.transColor = dependencies.transColor; + this.palette = dependencies.palette; + this.parsed = dependencies.parsed; + this.inflateData = dependencies.inflateData; + this.finished = dependencies.finished; + this.simpleTransparency = dependencies.simpleTransparency; + this.headersFinished = dependencies.headersFinished || function () {}; +}); + +Parser.prototype.start = function () { + this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this)); +}; + +Parser.prototype._parseSignature = function (data) { + let signature = constants.PNG_SIGNATURE; + + for (let i = 0; i < signature.length; i++) { + if (data[i] !== signature[i]) { + this.error(new Error("Invalid file signature")); + return; + } + } + this.read(8, this._parseChunkBegin.bind(this)); +}; + +Parser.prototype._parseChunkBegin = function (data) { + // chunk content length + let length = data.readUInt32BE(0); + + // chunk type + let type = data.readUInt32BE(4); + let name = ""; + for (let i = 4; i < 8; i++) { + name += String.fromCharCode(data[i]); + } + + //console.log('chunk ', name, length); + + // chunk flags + let ancillary = Boolean(data[4] & 0x20); // or critical + // priv = Boolean(data[5] & 0x20), // or public + // safeToCopy = Boolean(data[7] & 0x20); // or unsafe + + if (!this._hasIHDR && type !== constants.TYPE_IHDR) { + this.error(new Error("Expected IHDR on beggining")); + return; + } + + this._crc = new CrcCalculator(); + this._crc.write(Buffer.from(name)); + + if (this._chunks[type]) { + return this._chunks[type](length); + } + + if (!ancillary) { + this.error(new Error("Unsupported critical chunk type " + name)); + return; + } + + this.read(length + 4, this._skipChunk.bind(this)); +}; + +Parser.prototype._skipChunk = function (/*data*/) { + this.read(8, this._parseChunkBegin.bind(this)); +}; + +Parser.prototype._handleChunkEnd = function () { + this.read(4, this._parseChunkEnd.bind(this)); +}; + +Parser.prototype._parseChunkEnd = function (data) { + let fileCrc = data.readInt32BE(0); + let calcCrc = this._crc.crc32(); + + // check CRC + if (this._options.checkCRC && calcCrc !== fileCrc) { + this.error(new Error("Crc error - " + fileCrc + " - " + calcCrc)); + return; + } + + if (!this._hasIEND) { + this.read(8, this._parseChunkBegin.bind(this)); + } +}; + +Parser.prototype._handleIHDR = function (length) { + this.read(length, this._parseIHDR.bind(this)); +}; +Parser.prototype._parseIHDR = function (data) { + this._crc.write(data); + + let width = data.readUInt32BE(0); + let height = data.readUInt32BE(4); + let depth = data[8]; + let colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha + let compr = data[10]; + let filter = data[11]; + let interlace = data[12]; + + // console.log(' width', width, 'height', height, + // 'depth', depth, 'colorType', colorType, + // 'compr', compr, 'filter', filter, 'interlace', interlace + // ); + + if ( + depth !== 8 && + depth !== 4 && + depth !== 2 && + depth !== 1 && + depth !== 16 + ) { + this.error(new Error("Unsupported bit depth " + depth)); + return; + } + if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) { + this.error(new Error("Unsupported color type")); + return; + } + if (compr !== 0) { + this.error(new Error("Unsupported compression method")); + return; + } + if (filter !== 0) { + this.error(new Error("Unsupported filter method")); + return; + } + if (interlace !== 0 && interlace !== 1) { + this.error(new Error("Unsupported interlace method")); + return; + } + + this._colorType = colorType; + + let bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType]; + + this._hasIHDR = true; + + this.metadata({ + width: width, + height: height, + depth: depth, + interlace: Boolean(interlace), + palette: Boolean(colorType & constants.COLORTYPE_PALETTE), + color: Boolean(colorType & constants.COLORTYPE_COLOR), + alpha: Boolean(colorType & constants.COLORTYPE_ALPHA), + bpp: bpp, + colorType: colorType, + }); + + this._handleChunkEnd(); +}; + +Parser.prototype._handlePLTE = function (length) { + this.read(length, this._parsePLTE.bind(this)); +}; +Parser.prototype._parsePLTE = function (data) { + this._crc.write(data); + + let entries = Math.floor(data.length / 3); + // console.log('Palette:', entries); + + for (let i = 0; i < entries; i++) { + this._palette.push([data[i * 3], data[i * 3 + 1], data[i * 3 + 2], 0xff]); + } + + this.palette(this._palette); + + this._handleChunkEnd(); +}; + +Parser.prototype._handleTRNS = function (length) { + this.simpleTransparency(); + this.read(length, this._parseTRNS.bind(this)); +}; +Parser.prototype._parseTRNS = function (data) { + this._crc.write(data); + + // palette + if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) { + if (this._palette.length === 0) { + this.error(new Error("Transparency chunk must be after palette")); + return; + } + if (data.length > this._palette.length) { + this.error(new Error("More transparent colors than palette size")); + return; + } + for (let i = 0; i < data.length; i++) { + this._palette[i][3] = data[i]; + } + this.palette(this._palette); + } + + // for colorType 0 (grayscale) and 2 (rgb) + // there might be one gray/color defined as transparent + if (this._colorType === constants.COLORTYPE_GRAYSCALE) { + // grey, 2 bytes + this.transColor([data.readUInt16BE(0)]); + } + if (this._colorType === constants.COLORTYPE_COLOR) { + this.transColor([ + data.readUInt16BE(0), + data.readUInt16BE(2), + data.readUInt16BE(4), + ]); + } + + this._handleChunkEnd(); +}; + +Parser.prototype._handleGAMA = function (length) { + this.read(length, this._parseGAMA.bind(this)); +}; +Parser.prototype._parseGAMA = function (data) { + this._crc.write(data); + this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION); + + this._handleChunkEnd(); +}; + +Parser.prototype._handleIDAT = function (length) { + if (!this._emittedHeadersFinished) { + this._emittedHeadersFinished = true; + this.headersFinished(); + } + this.read(-length, this._parseIDAT.bind(this, length)); +}; +Parser.prototype._parseIDAT = function (length, data) { + this._crc.write(data); + + if ( + this._colorType === constants.COLORTYPE_PALETTE_COLOR && + this._palette.length === 0 + ) { + throw new Error("Expected palette not found"); + } + + this.inflateData(data); + let leftOverLength = length - data.length; + + if (leftOverLength > 0) { + this._handleIDAT(leftOverLength); + } else { + this._handleChunkEnd(); + } +}; + +Parser.prototype._handleIEND = function (length) { + this.read(length, this._parseIEND.bind(this)); +}; +Parser.prototype._parseIEND = function (data) { + this._crc.write(data); + + this._hasIEND = true; + this._handleChunkEnd(); + + if (this.finished) { + this.finished(); + } +}; diff --git a/backend/node_modules/pngjs/lib/png-sync.js b/backend/node_modules/pngjs/lib/png-sync.js new file mode 100644 index 00000000..68cac9bc --- /dev/null +++ b/backend/node_modules/pngjs/lib/png-sync.js @@ -0,0 +1,12 @@ +"use strict"; + +let parse = require("./parser-sync"); +let pack = require("./packer-sync"); + +exports.read = function (buffer, options) { + return parse(buffer, options || {}); +}; + +exports.write = function (png, options) { + return pack(png, options); +}; diff --git a/backend/node_modules/pngjs/lib/png.js b/backend/node_modules/pngjs/lib/png.js new file mode 100644 index 00000000..0b8af3f7 --- /dev/null +++ b/backend/node_modules/pngjs/lib/png.js @@ -0,0 +1,194 @@ +"use strict"; + +let util = require("util"); +let Stream = require("stream"); +let Parser = require("./parser-async"); +let Packer = require("./packer-async"); +let PNGSync = require("./png-sync"); + +let PNG = (exports.PNG = function (options) { + Stream.call(this); + + options = options || {}; // eslint-disable-line no-param-reassign + + // coerce pixel dimensions to integers (also coerces undefined -> 0): + this.width = options.width | 0; + this.height = options.height | 0; + + this.data = + this.width > 0 && this.height > 0 + ? Buffer.alloc(4 * this.width * this.height) + : null; + + if (options.fill && this.data) { + this.data.fill(0); + } + + this.gamma = 0; + this.readable = this.writable = true; + + this._parser = new Parser(options); + + this._parser.on("error", this.emit.bind(this, "error")); + this._parser.on("close", this._handleClose.bind(this)); + this._parser.on("metadata", this._metadata.bind(this)); + this._parser.on("gamma", this._gamma.bind(this)); + this._parser.on( + "parsed", + function (data) { + this.data = data; + this.emit("parsed", data); + }.bind(this) + ); + + this._packer = new Packer(options); + this._packer.on("data", this.emit.bind(this, "data")); + this._packer.on("end", this.emit.bind(this, "end")); + this._parser.on("close", this._handleClose.bind(this)); + this._packer.on("error", this.emit.bind(this, "error")); +}); +util.inherits(PNG, Stream); + +PNG.sync = PNGSync; + +PNG.prototype.pack = function () { + if (!this.data || !this.data.length) { + this.emit("error", "No data provided"); + return this; + } + + process.nextTick( + function () { + this._packer.pack(this.data, this.width, this.height, this.gamma); + }.bind(this) + ); + + return this; +}; + +PNG.prototype.parse = function (data, callback) { + if (callback) { + let onParsed, onError; + + onParsed = function (parsedData) { + this.removeListener("error", onError); + + this.data = parsedData; + callback(null, this); + }.bind(this); + + onError = function (err) { + this.removeListener("parsed", onParsed); + + callback(err, null); + }.bind(this); + + this.once("parsed", onParsed); + this.once("error", onError); + } + + this.end(data); + return this; +}; + +PNG.prototype.write = function (data) { + this._parser.write(data); + return true; +}; + +PNG.prototype.end = function (data) { + this._parser.end(data); +}; + +PNG.prototype._metadata = function (metadata) { + this.width = metadata.width; + this.height = metadata.height; + + this.emit("metadata", metadata); +}; + +PNG.prototype._gamma = function (gamma) { + this.gamma = gamma; +}; + +PNG.prototype._handleClose = function () { + if (!this._parser.writable && !this._packer.readable) { + this.emit("close"); + } +}; + +PNG.bitblt = function (src, dst, srcX, srcY, width, height, deltaX, deltaY) { + // eslint-disable-line max-params + // coerce pixel dimensions to integers (also coerces undefined -> 0): + /* eslint-disable no-param-reassign */ + srcX |= 0; + srcY |= 0; + width |= 0; + height |= 0; + deltaX |= 0; + deltaY |= 0; + /* eslint-enable no-param-reassign */ + + if ( + srcX > src.width || + srcY > src.height || + srcX + width > src.width || + srcY + height > src.height + ) { + throw new Error("bitblt reading outside image"); + } + + if ( + deltaX > dst.width || + deltaY > dst.height || + deltaX + width > dst.width || + deltaY + height > dst.height + ) { + throw new Error("bitblt writing outside image"); + } + + for (let y = 0; y < height; y++) { + src.data.copy( + dst.data, + ((deltaY + y) * dst.width + deltaX) << 2, + ((srcY + y) * src.width + srcX) << 2, + ((srcY + y) * src.width + srcX + width) << 2 + ); + } +}; + +PNG.prototype.bitblt = function ( + dst, + srcX, + srcY, + width, + height, + deltaX, + deltaY +) { + // eslint-disable-line max-params + + PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY); + return this; +}; + +PNG.adjustGamma = function (src) { + if (src.gamma) { + for (let y = 0; y < src.height; y++) { + for (let x = 0; x < src.width; x++) { + let idx = (src.width * y + x) << 2; + + for (let i = 0; i < 3; i++) { + let sample = src.data[idx + i] / 255; + sample = Math.pow(sample, 1 / 2.2 / src.gamma); + src.data[idx + i] = Math.round(sample * 255); + } + } + } + src.gamma = 0; + } +}; + +PNG.prototype.adjustGamma = function () { + PNG.adjustGamma(this); +}; diff --git a/backend/node_modules/pngjs/lib/sync-inflate.js b/backend/node_modules/pngjs/lib/sync-inflate.js new file mode 100644 index 00000000..4da0d5f0 --- /dev/null +++ b/backend/node_modules/pngjs/lib/sync-inflate.js @@ -0,0 +1,168 @@ +"use strict"; + +let assert = require("assert").ok; +let zlib = require("zlib"); +let util = require("util"); + +let kMaxLength = require("buffer").kMaxLength; + +function Inflate(opts) { + if (!(this instanceof Inflate)) { + return new Inflate(opts); + } + + if (opts && opts.chunkSize < zlib.Z_MIN_CHUNK) { + opts.chunkSize = zlib.Z_MIN_CHUNK; + } + + zlib.Inflate.call(this, opts); + + // Node 8 --> 9 compatibility check + this._offset = this._offset === undefined ? this._outOffset : this._offset; + this._buffer = this._buffer || this._outBuffer; + + if (opts && opts.maxLength != null) { + this._maxLength = opts.maxLength; + } +} + +function createInflate(opts) { + return new Inflate(opts); +} + +function _close(engine, callback) { + if (callback) { + process.nextTick(callback); + } + + // Caller may invoke .close after a zlib error (which will null _handle). + if (!engine._handle) { + return; + } + + engine._handle.close(); + engine._handle = null; +} + +Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) { + if (typeof asyncCb === "function") { + return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb); + } + + let self = this; + + let availInBefore = chunk && chunk.length; + let availOutBefore = this._chunkSize - this._offset; + let leftToInflate = this._maxLength; + let inOff = 0; + + let buffers = []; + let nread = 0; + + let error; + this.on("error", function (err) { + error = err; + }); + + function handleChunk(availInAfter, availOutAfter) { + if (self._hadError) { + return; + } + + let have = availOutBefore - availOutAfter; + assert(have >= 0, "have should not go down"); + + if (have > 0) { + let out = self._buffer.slice(self._offset, self._offset + have); + self._offset += have; + + if (out.length > leftToInflate) { + out = out.slice(0, leftToInflate); + } + + buffers.push(out); + nread += out.length; + leftToInflate -= out.length; + + if (leftToInflate === 0) { + return false; + } + } + + if (availOutAfter === 0 || self._offset >= self._chunkSize) { + availOutBefore = self._chunkSize; + self._offset = 0; + self._buffer = Buffer.allocUnsafe(self._chunkSize); + } + + if (availOutAfter === 0) { + inOff += availInBefore - availInAfter; + availInBefore = availInAfter; + + return true; + } + + return false; + } + + assert(this._handle, "zlib binding closed"); + let res; + do { + res = this._handle.writeSync( + flushFlag, + chunk, // in + inOff, // in_off + availInBefore, // in_len + this._buffer, // out + this._offset, //out_off + availOutBefore + ); // out_len + // Node 8 --> 9 compatibility check + res = res || this._writeState; + } while (!this._hadError && handleChunk(res[0], res[1])); + + if (this._hadError) { + throw error; + } + + if (nread >= kMaxLength) { + _close(this); + throw new RangeError( + "Cannot create final Buffer. It would be larger than 0x" + + kMaxLength.toString(16) + + " bytes" + ); + } + + let buf = Buffer.concat(buffers, nread); + _close(this); + + return buf; +}; + +util.inherits(Inflate, zlib.Inflate); + +function zlibBufferSync(engine, buffer) { + if (typeof buffer === "string") { + buffer = Buffer.from(buffer); + } + if (!(buffer instanceof Buffer)) { + throw new TypeError("Not a string or buffer"); + } + + let flushFlag = engine._finishFlushFlag; + if (flushFlag == null) { + flushFlag = zlib.Z_FINISH; + } + + return engine._processChunk(buffer, flushFlag); +} + +function inflateSync(buffer, opts) { + return zlibBufferSync(new Inflate(opts), buffer); +} + +module.exports = exports = inflateSync; +exports.Inflate = Inflate; +exports.createInflate = createInflate; +exports.inflateSync = inflateSync; diff --git a/backend/node_modules/pngjs/lib/sync-reader.js b/backend/node_modules/pngjs/lib/sync-reader.js new file mode 100644 index 00000000..15cbd4cd --- /dev/null +++ b/backend/node_modules/pngjs/lib/sync-reader.js @@ -0,0 +1,45 @@ +"use strict"; + +let SyncReader = (module.exports = function (buffer) { + this._buffer = buffer; + this._reads = []; +}); + +SyncReader.prototype.read = function (length, callback) { + this._reads.push({ + length: Math.abs(length), // if length < 0 then at most this length + allowLess: length < 0, + func: callback, + }); +}; + +SyncReader.prototype.process = function () { + // as long as there is any data and read requests + while (this._reads.length > 0 && this._buffer.length) { + let read = this._reads[0]; + + if ( + this._buffer.length && + (this._buffer.length >= read.length || read.allowLess) + ) { + // ok there is any data so that we can satisfy this request + this._reads.shift(); // == read + + let buf = this._buffer; + + this._buffer = buf.slice(read.length); + + read.func.call(this, buf.slice(0, read.length)); + } else { + break; + } + } + + if (this._reads.length > 0) { + return new Error("There are some read requests waitng on finished stream"); + } + + if (this._buffer.length > 0) { + return new Error("unrecognised content at end of stream"); + } +}; diff --git a/backend/node_modules/pngjs/package.json b/backend/node_modules/pngjs/package.json new file mode 100644 index 00000000..12a98715 --- /dev/null +++ b/backend/node_modules/pngjs/package.json @@ -0,0 +1,73 @@ +{ + "name": "pngjs", + "version": "5.0.0", + "description": "PNG encoder/decoder in pure JS, supporting any bit size & interlace, async & sync with full test suite.", + "contributors": [ + "Alexandre Paré", + "Gaurav Mali", + "Gusts Kaksis", + "Kuba Niegowski", + "Luke Page", + "Pietajan De Potter", + "Steven Sojka", + "liangzeng", + "Michael Vogt", + "Xin-Xin Wang", + "toriningen", + "Eugene Kulabuhov" + ], + "homepage": "https://github.com/lukeapage/pngjs", + "keywords": [ + "PNG", + "decoder", + "encoder", + "js-png", + "node-png", + "parser", + "png", + "png-js", + "png-parse", + "pngjs" + ], + "engines": { + "node": ">=10.13.0" + }, + "main": "./lib/png.js", + "directories": { + "lib": "lib", + "example": "examples", + "test": "test" + }, + "scripts": { + "build": "yarn prepublish", + "prepublish": "yarn browserify", + "browserify": "browserify lib/png.js --standalone png > browser.js", + "coverage": "nyc --reporter=lcov --reporter=text-summary tape test/*-spec.js nolarge", + "test": "yarn lint && yarn prettier:check && tape test/*-spec.js | tap-dot && node test/run-compare", + "lint": "eslint .", + "prettier:write": "prettier --write .", + "prettier:check": "prettier --check ." + }, + "repository": { + "type": "git", + "url": "git://github.com/lukeapage/pngjs.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/lukeapage/pngjs/issues" + }, + "devDependencies": { + "browserify": "16.5.1", + "buffer-equal": "1.0.0", + "codecov": "3.6.5", + "connect": "3.7.0", + "eslint": "6.8.0", + "eslint-config-prettier": "6.10.1", + "nyc": "15.0.1", + "prettier": "2.0.4", + "puppeteer": "2.1.1", + "serve-static": "1.14.1", + "tap-dot": "2.0.0", + "tape": "4.13.2" + } +} diff --git a/backend/node_modules/prop-types/LICENSE b/backend/node_modules/prop-types/LICENSE new file mode 100644 index 00000000..188fb2b0 --- /dev/null +++ b/backend/node_modules/prop-types/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-present, Facebook, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/backend/node_modules/prop-types/README.md b/backend/node_modules/prop-types/README.md new file mode 100644 index 00000000..e54d435f --- /dev/null +++ b/backend/node_modules/prop-types/README.md @@ -0,0 +1,302 @@ +# prop-types [![Build Status](https://travis-ci.com/facebook/prop-types.svg?branch=main)](https://travis-ci.org/facebook/prop-types) + +Runtime type checking for React props and similar objects. + +You can use prop-types to document the intended types of properties passed to +components. React (and potentially other libraries—see the `checkPropTypes()` +reference below) will check props passed to your components against those +definitions, and warn in development if they don’t match. + +## Installation + +```shell +npm install --save prop-types +``` + +## Importing + +```js +import PropTypes from 'prop-types'; // ES6 +var PropTypes = require('prop-types'); // ES5 with npm +``` + +### CDN + +If you prefer to exclude `prop-types` from your application and use it +globally via `window.PropTypes`, the `prop-types` package provides +single-file distributions, which are hosted on the following CDNs: + +* [**unpkg**](https://unpkg.com/prop-types/) +```html + + + + + +``` + +* [**cdnjs**](https://cdnjs.com/libraries/prop-types) +```html + + + + + +``` + +To load a specific version of `prop-types` replace `15.6.0` with the version number. + +## Usage + +PropTypes was originally exposed as part of the React core module, and is +commonly used with React components. +Here is an example of using PropTypes with a React component, which also +documents the different validators provided: + +```js +import React from 'react'; +import PropTypes from 'prop-types'; + +class MyComponent extends React.Component { + render() { + // ... do things with the props + } +} + +MyComponent.propTypes = { + // You can declare that a prop is a specific JS primitive. By default, these + // are all optional. + optionalArray: PropTypes.array, + optionalBigInt: PropTypes.bigint, + optionalBool: PropTypes.bool, + optionalFunc: PropTypes.func, + optionalNumber: PropTypes.number, + optionalObject: PropTypes.object, + optionalString: PropTypes.string, + optionalSymbol: PropTypes.symbol, + + // Anything that can be rendered: numbers, strings, elements or an array + // (or fragment) containing these types. + // see https://reactjs.org/docs/rendering-elements.html for more info + optionalNode: PropTypes.node, + + // A React element (ie. ). + optionalElement: PropTypes.element, + + // A React element type (eg. MyComponent). + // a function, string, or "element-like" object (eg. React.Fragment, Suspense, etc.) + // see https://github.com/facebook/react/blob/HEAD/packages/shared/isValidElementType.js + optionalElementType: PropTypes.elementType, + + // You can also declare that a prop is an instance of a class. This uses + // JS's instanceof operator. + optionalMessage: PropTypes.instanceOf(Message), + + // You can ensure that your prop is limited to specific values by treating + // it as an enum. + optionalEnum: PropTypes.oneOf(['News', 'Photos']), + + // An object that could be one of many types + optionalUnion: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + PropTypes.instanceOf(Message) + ]), + + // An array of a certain type + optionalArrayOf: PropTypes.arrayOf(PropTypes.number), + + // An object with property values of a certain type + optionalObjectOf: PropTypes.objectOf(PropTypes.number), + + // You can chain any of the above with `isRequired` to make sure a warning + // is shown if the prop isn't provided. + + // An object taking on a particular shape + optionalObjectWithShape: PropTypes.shape({ + optionalProperty: PropTypes.string, + requiredProperty: PropTypes.number.isRequired + }), + + // An object with warnings on extra properties + optionalObjectWithStrictShape: PropTypes.exact({ + optionalProperty: PropTypes.string, + requiredProperty: PropTypes.number.isRequired + }), + + requiredFunc: PropTypes.func.isRequired, + + // A value of any data type + requiredAny: PropTypes.any.isRequired, + + // You can also specify a custom validator. It should return an Error + // object if the validation fails. Don't `console.warn` or throw, as this + // won't work inside `oneOfType`. + customProp: function(props, propName, componentName) { + if (!/matchme/.test(props[propName])) { + return new Error( + 'Invalid prop `' + propName + '` supplied to' + + ' `' + componentName + '`. Validation failed.' + ); + } + }, + + // You can also supply a custom validator to `arrayOf` and `objectOf`. + // It should return an Error object if the validation fails. The validator + // will be called for each key in the array or object. The first two + // arguments of the validator are the array or object itself, and the + // current item's key. + customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) { + if (!/matchme/.test(propValue[key])) { + return new Error( + 'Invalid prop `' + propFullName + '` supplied to' + + ' `' + componentName + '`. Validation failed.' + ); + } + }) +}; +``` + +Refer to the [React documentation](https://facebook.github.io/react/docs/typechecking-with-proptypes.html) for more information. + +## Migrating from React.PropTypes + +Check out [Migrating from React.PropTypes](https://facebook.github.io/react/blog/2017/04/07/react-v15.5.0.html#migrating-from-react.proptypes) for details on how to migrate to `prop-types` from `React.PropTypes`. + +Note that this blog posts **mentions a codemod script that performs the conversion automatically**. + +There are also important notes below. + +## How to Depend on This Package? + +For apps, we recommend putting it in `dependencies` with a caret range. +For example: + +```js + "dependencies": { + "prop-types": "^15.5.7" + } +``` + +For libraries, we *also* recommend leaving it in `dependencies`: + +```js + "dependencies": { + "prop-types": "^15.5.7" + }, + "peerDependencies": { + "react": "^15.5.0" + } +``` + +**Note:** there are known issues in versions before 15.5.7 so we recommend using it as the minimal version. + +Make sure that the version range uses a caret (`^`) and thus is broad enough for npm to efficiently deduplicate packages. + +For UMD bundles of your components, make sure you **don’t** include `PropTypes` in the build. Usually this is done by marking it as an external (the specifics depend on your bundler), just like you do with React. + +## Compatibility + +### React 0.14 + +This package is compatible with **React 0.14.9**. Compared to 0.14.8 (which was released in March of 2016), there are no other changes in 0.14.9, so it should be a painless upgrade. + +```shell +# ATTENTION: Only run this if you still use React 0.14! +npm install --save react@^0.14.9 react-dom@^0.14.9 +``` + +### React 15+ + +This package is compatible with **React 15.3.0** and higher. + +``` +npm install --save react@^15.3.0 react-dom@^15.3.0 +``` + +### What happens on other React versions? + +It outputs warnings with the message below even though the developer doesn’t do anything wrong. Unfortunately there is no solution for this other than updating React to either 15.3.0 or higher, or 0.14.9 if you’re using React 0.14. + +## Difference from `React.PropTypes`: Don’t Call Validator Functions + +First of all, **which version of React are you using**? You might be seeing this message because a component library has updated to use `prop-types` package, but your version of React is incompatible with it. See the [above section](#compatibility) for more details. + +Are you using either React 0.14.9 or a version higher than React 15.3.0? Read on. + +When you migrate components to use the standalone `prop-types`, **all validator functions will start throwing an error if you call them directly**. This makes sure that nobody relies on them in production code, and it is safe to strip their implementations to optimize the bundle size. + +Code like this is still fine: + +```js +MyComponent.propTypes = { + myProp: PropTypes.bool +}; +``` + +However, code like this will not work with the `prop-types` package: + +```js +// Will not work with `prop-types` package! +var errorOrNull = PropTypes.bool(42, 'myProp', 'MyComponent', 'prop'); +``` + +It will throw an error: + +``` +Calling PropTypes validators directly is not supported by the `prop-types` package. +Use PropTypes.checkPropTypes() to call them. +``` + +(If you see **a warning** rather than an error with this message, please check the [above section about compatibility](#compatibility).) + +This is new behavior, and you will only encounter it when you migrate from `React.PropTypes` to the `prop-types` package. For the vast majority of components, this doesn’t matter, and if you didn’t see [this warning](https://facebook.github.io/react/warnings/dont-call-proptypes.html) in your components, your code is safe to migrate. This is not a breaking change in React because you are only opting into this change for a component by explicitly changing your imports to use `prop-types`. If you temporarily need the old behavior, you can keep using `React.PropTypes` until React 16. + +**If you absolutely need to trigger the validation manually**, call `PropTypes.checkPropTypes()`. Unlike the validators themselves, this function is safe to call in production, as it will be replaced by an empty function: + +```js +// Works with standalone PropTypes +PropTypes.checkPropTypes(MyComponent.propTypes, props, 'prop', 'MyComponent'); +``` +See below for more info. + +**If you DO want to use validation in production**, you can choose to use the **development version** by importing/requiring `prop-types/prop-types` instead of `prop-types`. + +**You might also see this error** if you’re calling a `PropTypes` validator from your own custom `PropTypes` validator. In this case, the fix is to make sure that you are passing *all* of the arguments to the inner function. There is a more in-depth explanation of how to fix it [on this page](https://facebook.github.io/react/warnings/dont-call-proptypes.html#fixing-the-false-positive-in-third-party-proptypes). Alternatively, you can temporarily keep using `React.PropTypes` until React 16, as it would still only warn in this case. + +If you use a bundler like Browserify or Webpack, don’t forget to [follow these instructions](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build) to correctly bundle your application in development or production mode. Otherwise you’ll ship unnecessary code to your users. + +## PropTypes.checkPropTypes + +React will automatically check the propTypes you set on the component, but if +you are using PropTypes without React then you may want to manually call +`PropTypes.checkPropTypes`, like so: + +```js +const myPropTypes = { + name: PropTypes.string, + age: PropTypes.number, + // ... define your prop validations +}; + +const props = { + name: 'hello', // is valid + age: 'world', // not valid +}; + +// Let's say your component is called 'MyComponent' + +// Works with standalone PropTypes +PropTypes.checkPropTypes(myPropTypes, props, 'prop', 'MyComponent'); +// This will warn as follows: +// Warning: Failed prop type: Invalid prop `age` of type `string` supplied to +// `MyComponent`, expected `number`. +``` + +## PropTypes.resetWarningCache() + +`PropTypes.checkPropTypes(...)` only `console.error`s a given message once. To reset the error warning cache in tests, call `PropTypes.resetWarningCache()` + +### License + +prop-types is [MIT licensed](./LICENSE). diff --git a/backend/node_modules/prop-types/checkPropTypes.js b/backend/node_modules/prop-types/checkPropTypes.js new file mode 100644 index 00000000..481f2cf9 --- /dev/null +++ b/backend/node_modules/prop-types/checkPropTypes.js @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +var printWarning = function() {}; + +if (process.env.NODE_ENV !== 'production') { + var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); + var loggedTypeFailures = {}; + var has = require('./lib/has'); + + printWarning = function(text) { + var message = 'Warning: ' + text; + if (typeof console !== 'undefined') { + console.error(message); + } + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) { /**/ } + }; +} + +/** + * Assert that the values match with the type specs. + * Error messages are memorized and will only be shown once. + * + * @param {object} typeSpecs Map of name to a ReactPropType + * @param {object} values Runtime values that need to be type-checked + * @param {string} location e.g. "prop", "context", "child context" + * @param {string} componentName Name of the component for error messages. + * @param {?Function} getStack Returns the component stack. + * @private + */ +function checkPropTypes(typeSpecs, values, location, componentName, getStack) { + if (process.env.NODE_ENV !== 'production') { + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error; + // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== 'function') { + var err = Error( + (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.' + ); + err.name = 'Invariant Violation'; + throw err; + } + error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); + } catch (ex) { + error = ex; + } + if (error && !(error instanceof Error)) { + printWarning( + (componentName || 'React class') + ': type specification of ' + + location + ' `' + typeSpecName + '` is invalid; the type checker ' + + 'function must return `null` or an `Error` but returned a ' + typeof error + '. ' + + 'You may have forgotten to pass an argument to the type checker ' + + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + + 'shape all require an argument).' + ); + } + if (error instanceof Error && !(error.message in loggedTypeFailures)) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error.message] = true; + + var stack = getStack ? getStack() : ''; + + printWarning( + 'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '') + ); + } + } + } + } +} + +/** + * Resets warning cache when testing. + * + * @private + */ +checkPropTypes.resetWarningCache = function() { + if (process.env.NODE_ENV !== 'production') { + loggedTypeFailures = {}; + } +} + +module.exports = checkPropTypes; diff --git a/backend/node_modules/prop-types/factory.js b/backend/node_modules/prop-types/factory.js new file mode 100644 index 00000000..abdf8e6d --- /dev/null +++ b/backend/node_modules/prop-types/factory.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +// React 15.5 references this module, and assumes PropTypes are still callable in production. +// Therefore we re-export development-only version with all the PropTypes checks here. +// However if one is migrating to the `prop-types` npm library, they will go through the +// `index.js` entry point, and it will branch depending on the environment. +var factory = require('./factoryWithTypeCheckers'); +module.exports = function(isValidElement) { + // It is still allowed in 15.5. + var throwOnDirectAccess = false; + return factory(isValidElement, throwOnDirectAccess); +}; diff --git a/backend/node_modules/prop-types/factoryWithThrowingShims.js b/backend/node_modules/prop-types/factoryWithThrowingShims.js new file mode 100644 index 00000000..ac882672 --- /dev/null +++ b/backend/node_modules/prop-types/factoryWithThrowingShims.js @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); + +function emptyFunction() {} +function emptyFunctionWithReset() {} +emptyFunctionWithReset.resetWarningCache = emptyFunction; + +module.exports = function() { + function shim(props, propName, componentName, location, propFullName, secret) { + if (secret === ReactPropTypesSecret) { + // It is still safe when called from React. + return; + } + var err = new Error( + 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + + 'Use PropTypes.checkPropTypes() to call them. ' + + 'Read more at http://fb.me/use-check-prop-types' + ); + err.name = 'Invariant Violation'; + throw err; + }; + shim.isRequired = shim; + function getShim() { + return shim; + }; + // Important! + // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. + var ReactPropTypes = { + array: shim, + bigint: shim, + bool: shim, + func: shim, + number: shim, + object: shim, + string: shim, + symbol: shim, + + any: shim, + arrayOf: getShim, + element: shim, + elementType: shim, + instanceOf: getShim, + node: shim, + objectOf: getShim, + oneOf: getShim, + oneOfType: getShim, + shape: getShim, + exact: getShim, + + checkPropTypes: emptyFunctionWithReset, + resetWarningCache: emptyFunction + }; + + ReactPropTypes.PropTypes = ReactPropTypes; + + return ReactPropTypes; +}; diff --git a/backend/node_modules/prop-types/factoryWithTypeCheckers.js b/backend/node_modules/prop-types/factoryWithTypeCheckers.js new file mode 100644 index 00000000..a88068e5 --- /dev/null +++ b/backend/node_modules/prop-types/factoryWithTypeCheckers.js @@ -0,0 +1,610 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +var ReactIs = require('react-is'); +var assign = require('object-assign'); + +var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); +var has = require('./lib/has'); +var checkPropTypes = require('./checkPropTypes'); + +var printWarning = function() {}; + +if (process.env.NODE_ENV !== 'production') { + printWarning = function(text) { + var message = 'Warning: ' + text; + if (typeof console !== 'undefined') { + console.error(message); + } + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) {} + }; +} + +function emptyFunctionThatReturnsNull() { + return null; +} + +module.exports = function(isValidElement, throwOnDirectAccess) { + /* global Symbol */ + var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. + + /** + * Returns the iterator method function contained on the iterable object. + * + * Be sure to invoke the function with the iterable as context: + * + * var iteratorFn = getIteratorFn(myIterable); + * if (iteratorFn) { + * var iterator = iteratorFn.call(myIterable); + * ... + * } + * + * @param {?object} maybeIterable + * @return {?function} + */ + function getIteratorFn(maybeIterable) { + var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); + if (typeof iteratorFn === 'function') { + return iteratorFn; + } + } + + /** + * Collection of methods that allow declaration and validation of props that are + * supplied to React components. Example usage: + * + * var Props = require('ReactPropTypes'); + * var MyArticle = React.createClass({ + * propTypes: { + * // An optional string prop named "description". + * description: Props.string, + * + * // A required enum prop named "category". + * category: Props.oneOf(['News','Photos']).isRequired, + * + * // A prop named "dialog" that requires an instance of Dialog. + * dialog: Props.instanceOf(Dialog).isRequired + * }, + * render: function() { ... } + * }); + * + * A more formal specification of how these methods are used: + * + * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) + * decl := ReactPropTypes.{type}(.isRequired)? + * + * Each and every declaration produces a function with the same signature. This + * allows the creation of custom validation functions. For example: + * + * var MyLink = React.createClass({ + * propTypes: { + * // An optional string or URI prop named "href". + * href: function(props, propName, componentName) { + * var propValue = props[propName]; + * if (propValue != null && typeof propValue !== 'string' && + * !(propValue instanceof URI)) { + * return new Error( + * 'Expected a string or an URI for ' + propName + ' in ' + + * componentName + * ); + * } + * } + * }, + * render: function() {...} + * }); + * + * @internal + */ + + var ANONYMOUS = '<>'; + + // Important! + // Keep this list in sync with production version in `./factoryWithThrowingShims.js`. + var ReactPropTypes = { + array: createPrimitiveTypeChecker('array'), + bigint: createPrimitiveTypeChecker('bigint'), + bool: createPrimitiveTypeChecker('boolean'), + func: createPrimitiveTypeChecker('function'), + number: createPrimitiveTypeChecker('number'), + object: createPrimitiveTypeChecker('object'), + string: createPrimitiveTypeChecker('string'), + symbol: createPrimitiveTypeChecker('symbol'), + + any: createAnyTypeChecker(), + arrayOf: createArrayOfTypeChecker, + element: createElementTypeChecker(), + elementType: createElementTypeTypeChecker(), + instanceOf: createInstanceTypeChecker, + node: createNodeChecker(), + objectOf: createObjectOfTypeChecker, + oneOf: createEnumTypeChecker, + oneOfType: createUnionTypeChecker, + shape: createShapeTypeChecker, + exact: createStrictShapeTypeChecker, + }; + + /** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ + /*eslint-disable no-self-compare*/ + function is(x, y) { + // SameValue algorithm + if (x === y) { + // Steps 1-5, 7-10 + // Steps 6.b-6.e: +0 != -0 + return x !== 0 || 1 / x === 1 / y; + } else { + // Step 6.a: NaN == NaN + return x !== x && y !== y; + } + } + /*eslint-enable no-self-compare*/ + + /** + * We use an Error-like object for backward compatibility as people may call + * PropTypes directly and inspect their output. However, we don't use real + * Errors anymore. We don't inspect their stack anyway, and creating them + * is prohibitively expensive if they are created too often, such as what + * happens in oneOfType() for any type before the one that matched. + */ + function PropTypeError(message, data) { + this.message = message; + this.data = data && typeof data === 'object' ? data: {}; + this.stack = ''; + } + // Make `instanceof Error` still work for returned errors. + PropTypeError.prototype = Error.prototype; + + function createChainableTypeChecker(validate) { + if (process.env.NODE_ENV !== 'production') { + var manualPropTypeCallCache = {}; + var manualPropTypeWarningCount = 0; + } + function checkType(isRequired, props, propName, componentName, location, propFullName, secret) { + componentName = componentName || ANONYMOUS; + propFullName = propFullName || propName; + + if (secret !== ReactPropTypesSecret) { + if (throwOnDirectAccess) { + // New behavior only for users of `prop-types` package + var err = new Error( + 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + + 'Use `PropTypes.checkPropTypes()` to call them. ' + + 'Read more at http://fb.me/use-check-prop-types' + ); + err.name = 'Invariant Violation'; + throw err; + } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') { + // Old behavior for people using React.PropTypes + var cacheKey = componentName + ':' + propName; + if ( + !manualPropTypeCallCache[cacheKey] && + // Avoid spamming the console because they are often not actionable except for lib authors + manualPropTypeWarningCount < 3 + ) { + printWarning( + 'You are manually calling a React.PropTypes validation ' + + 'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' + + 'and will throw in the standalone `prop-types` package. ' + + 'You may be seeing this warning due to a third-party PropTypes ' + + 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.' + ); + manualPropTypeCallCache[cacheKey] = true; + manualPropTypeWarningCount++; + } + } + } + if (props[propName] == null) { + if (isRequired) { + if (props[propName] === null) { + return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.')); + } + return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.')); + } + return null; + } else { + return validate(props, propName, componentName, location, propFullName); + } + } + + var chainedCheckType = checkType.bind(null, false); + chainedCheckType.isRequired = checkType.bind(null, true); + + return chainedCheckType; + } + + function createPrimitiveTypeChecker(expectedType) { + function validate(props, propName, componentName, location, propFullName, secret) { + var propValue = props[propName]; + var propType = getPropType(propValue); + if (propType !== expectedType) { + // `propValue` being instance of, say, date/regexp, pass the 'object' + // check, but we can offer a more precise error message here rather than + // 'of type `object`'. + var preciseType = getPreciseType(propValue); + + return new PropTypeError( + 'Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'), + {expectedType: expectedType} + ); + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createAnyTypeChecker() { + return createChainableTypeChecker(emptyFunctionThatReturnsNull); + } + + function createArrayOfTypeChecker(typeChecker) { + function validate(props, propName, componentName, location, propFullName) { + if (typeof typeChecker !== 'function') { + return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.'); + } + var propValue = props[propName]; + if (!Array.isArray(propValue)) { + var propType = getPropType(propValue); + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.')); + } + for (var i = 0; i < propValue.length; i++) { + var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret); + if (error instanceof Error) { + return error; + } + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createElementTypeChecker() { + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + if (!isValidElement(propValue)) { + var propType = getPropType(propValue); + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.')); + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createElementTypeTypeChecker() { + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + if (!ReactIs.isValidElementType(propValue)) { + var propType = getPropType(propValue); + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.')); + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createInstanceTypeChecker(expectedClass) { + function validate(props, propName, componentName, location, propFullName) { + if (!(props[propName] instanceof expectedClass)) { + var expectedClassName = expectedClass.name || ANONYMOUS; + var actualClassName = getClassName(props[propName]); + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.')); + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createEnumTypeChecker(expectedValues) { + if (!Array.isArray(expectedValues)) { + if (process.env.NODE_ENV !== 'production') { + if (arguments.length > 1) { + printWarning( + 'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' + + 'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).' + ); + } else { + printWarning('Invalid argument supplied to oneOf, expected an array.'); + } + } + return emptyFunctionThatReturnsNull; + } + + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + for (var i = 0; i < expectedValues.length; i++) { + if (is(propValue, expectedValues[i])) { + return null; + } + } + + var valuesString = JSON.stringify(expectedValues, function replacer(key, value) { + var type = getPreciseType(value); + if (type === 'symbol') { + return String(value); + } + return value; + }); + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.')); + } + return createChainableTypeChecker(validate); + } + + function createObjectOfTypeChecker(typeChecker) { + function validate(props, propName, componentName, location, propFullName) { + if (typeof typeChecker !== 'function') { + return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.'); + } + var propValue = props[propName]; + var propType = getPropType(propValue); + if (propType !== 'object') { + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.')); + } + for (var key in propValue) { + if (has(propValue, key)) { + var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); + if (error instanceof Error) { + return error; + } + } + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createUnionTypeChecker(arrayOfTypeCheckers) { + if (!Array.isArray(arrayOfTypeCheckers)) { + process.env.NODE_ENV !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0; + return emptyFunctionThatReturnsNull; + } + + for (var i = 0; i < arrayOfTypeCheckers.length; i++) { + var checker = arrayOfTypeCheckers[i]; + if (typeof checker !== 'function') { + printWarning( + 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' + + 'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.' + ); + return emptyFunctionThatReturnsNull; + } + } + + function validate(props, propName, componentName, location, propFullName) { + var expectedTypes = []; + for (var i = 0; i < arrayOfTypeCheckers.length; i++) { + var checker = arrayOfTypeCheckers[i]; + var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret); + if (checkerResult == null) { + return null; + } + if (checkerResult.data && has(checkerResult.data, 'expectedType')) { + expectedTypes.push(checkerResult.data.expectedType); + } + } + var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': ''; + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.')); + } + return createChainableTypeChecker(validate); + } + + function createNodeChecker() { + function validate(props, propName, componentName, location, propFullName) { + if (!isNode(props[propName])) { + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.')); + } + return null; + } + return createChainableTypeChecker(validate); + } + + function invalidValidatorError(componentName, location, propFullName, key, type) { + return new PropTypeError( + (componentName || 'React class') + ': ' + location + ' type `' + propFullName + '.' + key + '` is invalid; ' + + 'it must be a function, usually from the `prop-types` package, but received `' + type + '`.' + ); + } + + function createShapeTypeChecker(shapeTypes) { + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + var propType = getPropType(propValue); + if (propType !== 'object') { + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); + } + for (var key in shapeTypes) { + var checker = shapeTypes[key]; + if (typeof checker !== 'function') { + return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker)); + } + var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); + if (error) { + return error; + } + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createStrictShapeTypeChecker(shapeTypes) { + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + var propType = getPropType(propValue); + if (propType !== 'object') { + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); + } + // We need to check all keys in case some are required but missing from props. + var allKeys = assign({}, props[propName], shapeTypes); + for (var key in allKeys) { + var checker = shapeTypes[key]; + if (has(shapeTypes, key) && typeof checker !== 'function') { + return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker)); + } + if (!checker) { + return new PropTypeError( + 'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' + + '\nBad object: ' + JSON.stringify(props[propName], null, ' ') + + '\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ') + ); + } + var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); + if (error) { + return error; + } + } + return null; + } + + return createChainableTypeChecker(validate); + } + + function isNode(propValue) { + switch (typeof propValue) { + case 'number': + case 'string': + case 'undefined': + return true; + case 'boolean': + return !propValue; + case 'object': + if (Array.isArray(propValue)) { + return propValue.every(isNode); + } + if (propValue === null || isValidElement(propValue)) { + return true; + } + + var iteratorFn = getIteratorFn(propValue); + if (iteratorFn) { + var iterator = iteratorFn.call(propValue); + var step; + if (iteratorFn !== propValue.entries) { + while (!(step = iterator.next()).done) { + if (!isNode(step.value)) { + return false; + } + } + } else { + // Iterator will provide entry [k,v] tuples rather than values. + while (!(step = iterator.next()).done) { + var entry = step.value; + if (entry) { + if (!isNode(entry[1])) { + return false; + } + } + } + } + } else { + return false; + } + + return true; + default: + return false; + } + } + + function isSymbol(propType, propValue) { + // Native Symbol. + if (propType === 'symbol') { + return true; + } + + // falsy value can't be a Symbol + if (!propValue) { + return false; + } + + // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol' + if (propValue['@@toStringTag'] === 'Symbol') { + return true; + } + + // Fallback for non-spec compliant Symbols which are polyfilled. + if (typeof Symbol === 'function' && propValue instanceof Symbol) { + return true; + } + + return false; + } + + // Equivalent of `typeof` but with special handling for array and regexp. + function getPropType(propValue) { + var propType = typeof propValue; + if (Array.isArray(propValue)) { + return 'array'; + } + if (propValue instanceof RegExp) { + // Old webkits (at least until Android 4.0) return 'function' rather than + // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ + // passes PropTypes.object. + return 'object'; + } + if (isSymbol(propType, propValue)) { + return 'symbol'; + } + return propType; + } + + // This handles more types than `getPropType`. Only used for error messages. + // See `createPrimitiveTypeChecker`. + function getPreciseType(propValue) { + if (typeof propValue === 'undefined' || propValue === null) { + return '' + propValue; + } + var propType = getPropType(propValue); + if (propType === 'object') { + if (propValue instanceof Date) { + return 'date'; + } else if (propValue instanceof RegExp) { + return 'regexp'; + } + } + return propType; + } + + // Returns a string that is postfixed to a warning about an invalid type. + // For example, "undefined" or "of type array" + function getPostfixForTypeWarning(value) { + var type = getPreciseType(value); + switch (type) { + case 'array': + case 'object': + return 'an ' + type; + case 'boolean': + case 'date': + case 'regexp': + return 'a ' + type; + default: + return type; + } + } + + // Returns class name of the object, if any. + function getClassName(propValue) { + if (!propValue.constructor || !propValue.constructor.name) { + return ANONYMOUS; + } + return propValue.constructor.name; + } + + ReactPropTypes.checkPropTypes = checkPropTypes; + ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache; + ReactPropTypes.PropTypes = ReactPropTypes; + + return ReactPropTypes; +}; diff --git a/backend/node_modules/prop-types/index.js b/backend/node_modules/prop-types/index.js new file mode 100644 index 00000000..e9ef51d6 --- /dev/null +++ b/backend/node_modules/prop-types/index.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +if (process.env.NODE_ENV !== 'production') { + var ReactIs = require('react-is'); + + // By explicitly using `prop-types` you are opting into new development behavior. + // http://fb.me/prop-types-in-prod + var throwOnDirectAccess = true; + module.exports = require('./factoryWithTypeCheckers')(ReactIs.isElement, throwOnDirectAccess); +} else { + // By explicitly using `prop-types` you are opting into new production behavior. + // http://fb.me/prop-types-in-prod + module.exports = require('./factoryWithThrowingShims')(); +} diff --git a/backend/node_modules/prop-types/lib/ReactPropTypesSecret.js b/backend/node_modules/prop-types/lib/ReactPropTypesSecret.js new file mode 100644 index 00000000..f54525e7 --- /dev/null +++ b/backend/node_modules/prop-types/lib/ReactPropTypesSecret.js @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; + +module.exports = ReactPropTypesSecret; diff --git a/backend/node_modules/prop-types/lib/has.js b/backend/node_modules/prop-types/lib/has.js new file mode 100644 index 00000000..007bae32 --- /dev/null +++ b/backend/node_modules/prop-types/lib/has.js @@ -0,0 +1 @@ +module.exports = Function.call.bind(Object.prototype.hasOwnProperty); diff --git a/backend/node_modules/prop-types/package.json b/backend/node_modules/prop-types/package.json new file mode 100644 index 00000000..63daf704 --- /dev/null +++ b/backend/node_modules/prop-types/package.json @@ -0,0 +1,60 @@ +{ + "name": "prop-types", + "version": "15.8.1", + "description": "Runtime type checking for React props and similar objects.", + "sideEffects": false, + "main": "index.js", + "license": "MIT", + "files": [ + "LICENSE", + "README.md", + "checkPropTypes.js", + "factory.js", + "factoryWithThrowingShims.js", + "factoryWithTypeCheckers.js", + "index.js", + "prop-types.js", + "prop-types.min.js", + "lib" + ], + "repository": "facebook/prop-types", + "keywords": [ + "react" + ], + "bugs": { + "url": "https://github.com/facebook/prop-types/issues" + }, + "homepage": "https://facebook.github.io/react/", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + }, + "scripts": { + "pretest": "npm run lint", + "lint": "eslint .", + "test": "npm run tests-only", + "tests-only": "jest", + "umd": "NODE_ENV=development browserify index.js -t loose-envify --standalone PropTypes -o prop-types.js", + "umd-min": "NODE_ENV=production browserify index.js -t loose-envify -t uglifyify --standalone PropTypes -p bundle-collapser/plugin -o | uglifyjs --compress unused,dead_code -o prop-types.min.js", + "build": "yarn umd && yarn umd-min", + "prepublish": "not-in-publish || yarn build" + }, + "devDependencies": { + "babel-jest": "^19.0.0", + "babel-preset-react": "^6.24.1", + "browserify": "^16.5.0", + "bundle-collapser": "^1.4.0", + "eslint": "^8.6.0", + "in-publish": "^2.0.1", + "jest": "^19.0.2", + "react": "^15.7.0", + "uglifyify": "^5.0.2", + "uglifyjs": "^2.4.11" + }, + "browserify": { + "transform": [ + "loose-envify" + ] + } +} diff --git a/backend/node_modules/prop-types/prop-types.js b/backend/node_modules/prop-types/prop-types.js new file mode 100644 index 00000000..a5a15ddb --- /dev/null +++ b/backend/node_modules/prop-types/prop-types.js @@ -0,0 +1,1315 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PropTypes = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) { + printWarning( + 'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' + + 'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).' + ); + } else { + printWarning('Invalid argument supplied to oneOf, expected an array.'); + } + } + return emptyFunctionThatReturnsNull; + } + + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + for (var i = 0; i < expectedValues.length; i++) { + if (is(propValue, expectedValues[i])) { + return null; + } + } + + var valuesString = JSON.stringify(expectedValues, function replacer(key, value) { + var type = getPreciseType(value); + if (type === 'symbol') { + return String(value); + } + return value; + }); + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.')); + } + return createChainableTypeChecker(validate); + } + + function createObjectOfTypeChecker(typeChecker) { + function validate(props, propName, componentName, location, propFullName) { + if (typeof typeChecker !== 'function') { + return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.'); + } + var propValue = props[propName]; + var propType = getPropType(propValue); + if (propType !== 'object') { + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.')); + } + for (var key in propValue) { + if (has(propValue, key)) { + var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); + if (error instanceof Error) { + return error; + } + } + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createUnionTypeChecker(arrayOfTypeCheckers) { + if (!Array.isArray(arrayOfTypeCheckers)) { + "development" !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0; + return emptyFunctionThatReturnsNull; + } + + for (var i = 0; i < arrayOfTypeCheckers.length; i++) { + var checker = arrayOfTypeCheckers[i]; + if (typeof checker !== 'function') { + printWarning( + 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' + + 'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.' + ); + return emptyFunctionThatReturnsNull; + } + } + + function validate(props, propName, componentName, location, propFullName) { + var expectedTypes = []; + for (var i = 0; i < arrayOfTypeCheckers.length; i++) { + var checker = arrayOfTypeCheckers[i]; + var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret); + if (checkerResult == null) { + return null; + } + if (checkerResult.data.hasOwnProperty('expectedType')) { + expectedTypes.push(checkerResult.data.expectedType); + } + } + var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': ''; + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.')); + } + return createChainableTypeChecker(validate); + } + + function createNodeChecker() { + function validate(props, propName, componentName, location, propFullName) { + if (!isNode(props[propName])) { + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.')); + } + return null; + } + return createChainableTypeChecker(validate); + } + + function invalidValidatorError(componentName, location, propFullName, key, type) { + return new PropTypeError( + (componentName || 'React class') + ': ' + location + ' type `' + propFullName + '.' + key + '` is invalid; ' + + 'it must be a function, usually from the `prop-types` package, but received `' + type + '`.' + ); + } + + function createShapeTypeChecker(shapeTypes) { + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + var propType = getPropType(propValue); + if (propType !== 'object') { + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); + } + for (var key in shapeTypes) { + var checker = shapeTypes[key]; + if (typeof checker !== 'function') { + return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker)); + } + var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); + if (error) { + return error; + } + } + return null; + } + return createChainableTypeChecker(validate); + } + + function createStrictShapeTypeChecker(shapeTypes) { + function validate(props, propName, componentName, location, propFullName) { + var propValue = props[propName]; + var propType = getPropType(propValue); + if (propType !== 'object') { + return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); + } + // We need to check all keys in case some are required but missing from props. + var allKeys = assign({}, props[propName], shapeTypes); + for (var key in allKeys) { + var checker = shapeTypes[key]; + if (has(shapeTypes, key) && typeof checker !== 'function') { + return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker)); + } + if (!checker) { + return new PropTypeError( + 'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' + + '\nBad object: ' + JSON.stringify(props[propName], null, ' ') + + '\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ') + ); + } + var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); + if (error) { + return error; + } + } + return null; + } + + return createChainableTypeChecker(validate); + } + + function isNode(propValue) { + switch (typeof propValue) { + case 'number': + case 'string': + case 'undefined': + return true; + case 'boolean': + return !propValue; + case 'object': + if (Array.isArray(propValue)) { + return propValue.every(isNode); + } + if (propValue === null || isValidElement(propValue)) { + return true; + } + + var iteratorFn = getIteratorFn(propValue); + if (iteratorFn) { + var iterator = iteratorFn.call(propValue); + var step; + if (iteratorFn !== propValue.entries) { + while (!(step = iterator.next()).done) { + if (!isNode(step.value)) { + return false; + } + } + } else { + // Iterator will provide entry [k,v] tuples rather than values. + while (!(step = iterator.next()).done) { + var entry = step.value; + if (entry) { + if (!isNode(entry[1])) { + return false; + } + } + } + } + } else { + return false; + } + + return true; + default: + return false; + } + } + + function isSymbol(propType, propValue) { + // Native Symbol. + if (propType === 'symbol') { + return true; + } + + // falsy value can't be a Symbol + if (!propValue) { + return false; + } + + // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol' + if (propValue['@@toStringTag'] === 'Symbol') { + return true; + } + + // Fallback for non-spec compliant Symbols which are polyfilled. + if (typeof Symbol === 'function' && propValue instanceof Symbol) { + return true; + } + + return false; + } + + // Equivalent of `typeof` but with special handling for array and regexp. + function getPropType(propValue) { + var propType = typeof propValue; + if (Array.isArray(propValue)) { + return 'array'; + } + if (propValue instanceof RegExp) { + // Old webkits (at least until Android 4.0) return 'function' rather than + // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ + // passes PropTypes.object. + return 'object'; + } + if (isSymbol(propType, propValue)) { + return 'symbol'; + } + return propType; + } + + // This handles more types than `getPropType`. Only used for error messages. + // See `createPrimitiveTypeChecker`. + function getPreciseType(propValue) { + if (typeof propValue === 'undefined' || propValue === null) { + return '' + propValue; + } + var propType = getPropType(propValue); + if (propType === 'object') { + if (propValue instanceof Date) { + return 'date'; + } else if (propValue instanceof RegExp) { + return 'regexp'; + } + } + return propType; + } + + // Returns a string that is postfixed to a warning about an invalid type. + // For example, "undefined" or "of type array" + function getPostfixForTypeWarning(value) { + var type = getPreciseType(value); + switch (type) { + case 'array': + case 'object': + return 'an ' + type; + case 'boolean': + case 'date': + case 'regexp': + return 'a ' + type; + default: + return type; + } + } + + // Returns class name of the object, if any. + function getClassName(propValue) { + if (!propValue.constructor || !propValue.constructor.name) { + return ANONYMOUS; + } + return propValue.constructor.name; + } + + ReactPropTypes.checkPropTypes = checkPropTypes; + ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache; + ReactPropTypes.PropTypes = ReactPropTypes; + + return ReactPropTypes; +}; + +},{"./checkPropTypes":1,"./lib/ReactPropTypesSecret":5,"./lib/has":6,"object-assign":7,"react-is":11}],4:[function(require,module,exports){ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +if ("development" !== 'production') { + var ReactIs = require('react-is'); + + // By explicitly using `prop-types` you are opting into new development behavior. + // http://fb.me/prop-types-in-prod + var throwOnDirectAccess = true; + module.exports = require('./factoryWithTypeCheckers')(ReactIs.isElement, throwOnDirectAccess); +} else { + // By explicitly using `prop-types` you are opting into new production behavior. + // http://fb.me/prop-types-in-prod + module.exports = require('./factoryWithThrowingShims')(); +} + +},{"./factoryWithThrowingShims":2,"./factoryWithTypeCheckers":3,"react-is":11}],5:[function(require,module,exports){ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; + +module.exports = ReactPropTypesSecret; + +},{}],6:[function(require,module,exports){ +module.exports = Function.call.bind(Object.prototype.hasOwnProperty); + +},{}],7:[function(require,module,exports){ +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ + +'use strict'; +/* eslint-disable no-unused-vars */ +var getOwnPropertySymbols = Object.getOwnPropertySymbols; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; + +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + + return Object(val); +} + +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + + // Detect buggy property enumeration order in older V8 versions. + + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line no-new-wrappers + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } + + return true; + } catch (err) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} + +module.exports = shouldUseNative() ? Object.assign : function (target, source) { + var from; + var to = toObject(target); + var symbols; + + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + + if (getOwnPropertySymbols) { + symbols = getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + + return to; +}; + +},{}],8:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],9:[function(require,module,exports){ +(function (process){(function (){ +/** @license React v16.13.1 + * react-is.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + + + +if (process.env.NODE_ENV !== "production") { + (function() { +'use strict'; + +// The Symbol used to tag the ReactElement-like types. If there is no native Symbol +// nor polyfill, then a plain number is used for performance. +var hasSymbol = typeof Symbol === 'function' && Symbol.for; +var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7; +var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca; +var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb; +var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc; +var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2; +var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd; +var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary +// (unstable) APIs that have been removed. Can we remove the symbols? + +var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf; +var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf; +var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0; +var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1; +var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8; +var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3; +var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4; +var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9; +var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5; +var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6; +var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7; + +function isValidElementType(type) { + return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill. + type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE); +} + +function typeOf(object) { + if (typeof object === 'object' && object !== null) { + var $$typeof = object.$$typeof; + + switch ($$typeof) { + case REACT_ELEMENT_TYPE: + var type = object.type; + + switch (type) { + case REACT_ASYNC_MODE_TYPE: + case REACT_CONCURRENT_MODE_TYPE: + case REACT_FRAGMENT_TYPE: + case REACT_PROFILER_TYPE: + case REACT_STRICT_MODE_TYPE: + case REACT_SUSPENSE_TYPE: + return type; + + default: + var $$typeofType = type && type.$$typeof; + + switch ($$typeofType) { + case REACT_CONTEXT_TYPE: + case REACT_FORWARD_REF_TYPE: + case REACT_LAZY_TYPE: + case REACT_MEMO_TYPE: + case REACT_PROVIDER_TYPE: + return $$typeofType; + + default: + return $$typeof; + } + + } + + case REACT_PORTAL_TYPE: + return $$typeof; + } + } + + return undefined; +} // AsyncMode is deprecated along with isAsyncMode + +var AsyncMode = REACT_ASYNC_MODE_TYPE; +var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE; +var ContextConsumer = REACT_CONTEXT_TYPE; +var ContextProvider = REACT_PROVIDER_TYPE; +var Element = REACT_ELEMENT_TYPE; +var ForwardRef = REACT_FORWARD_REF_TYPE; +var Fragment = REACT_FRAGMENT_TYPE; +var Lazy = REACT_LAZY_TYPE; +var Memo = REACT_MEMO_TYPE; +var Portal = REACT_PORTAL_TYPE; +var Profiler = REACT_PROFILER_TYPE; +var StrictMode = REACT_STRICT_MODE_TYPE; +var Suspense = REACT_SUSPENSE_TYPE; +var hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated + +function isAsyncMode(object) { + { + if (!hasWarnedAboutDeprecatedIsAsyncMode) { + hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint + + console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.'); + } + } + + return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE; +} +function isConcurrentMode(object) { + return typeOf(object) === REACT_CONCURRENT_MODE_TYPE; +} +function isContextConsumer(object) { + return typeOf(object) === REACT_CONTEXT_TYPE; +} +function isContextProvider(object) { + return typeOf(object) === REACT_PROVIDER_TYPE; +} +function isElement(object) { + return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; +} +function isForwardRef(object) { + return typeOf(object) === REACT_FORWARD_REF_TYPE; +} +function isFragment(object) { + return typeOf(object) === REACT_FRAGMENT_TYPE; +} +function isLazy(object) { + return typeOf(object) === REACT_LAZY_TYPE; +} +function isMemo(object) { + return typeOf(object) === REACT_MEMO_TYPE; +} +function isPortal(object) { + return typeOf(object) === REACT_PORTAL_TYPE; +} +function isProfiler(object) { + return typeOf(object) === REACT_PROFILER_TYPE; +} +function isStrictMode(object) { + return typeOf(object) === REACT_STRICT_MODE_TYPE; +} +function isSuspense(object) { + return typeOf(object) === REACT_SUSPENSE_TYPE; +} + +exports.AsyncMode = AsyncMode; +exports.ConcurrentMode = ConcurrentMode; +exports.ContextConsumer = ContextConsumer; +exports.ContextProvider = ContextProvider; +exports.Element = Element; +exports.ForwardRef = ForwardRef; +exports.Fragment = Fragment; +exports.Lazy = Lazy; +exports.Memo = Memo; +exports.Portal = Portal; +exports.Profiler = Profiler; +exports.StrictMode = StrictMode; +exports.Suspense = Suspense; +exports.isAsyncMode = isAsyncMode; +exports.isConcurrentMode = isConcurrentMode; +exports.isContextConsumer = isContextConsumer; +exports.isContextProvider = isContextProvider; +exports.isElement = isElement; +exports.isForwardRef = isForwardRef; +exports.isFragment = isFragment; +exports.isLazy = isLazy; +exports.isMemo = isMemo; +exports.isPortal = isPortal; +exports.isProfiler = isProfiler; +exports.isStrictMode = isStrictMode; +exports.isSuspense = isSuspense; +exports.isValidElementType = isValidElementType; +exports.typeOf = typeOf; + })(); +} + +}).call(this)}).call(this,require('_process')) +},{"_process":8}],10:[function(require,module,exports){ +/** @license React v16.13.1 + * react-is.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict';var b="function"===typeof Symbol&&Symbol.for,c=b?Symbol.for("react.element"):60103,d=b?Symbol.for("react.portal"):60106,e=b?Symbol.for("react.fragment"):60107,f=b?Symbol.for("react.strict_mode"):60108,g=b?Symbol.for("react.profiler"):60114,h=b?Symbol.for("react.provider"):60109,k=b?Symbol.for("react.context"):60110,l=b?Symbol.for("react.async_mode"):60111,m=b?Symbol.for("react.concurrent_mode"):60111,n=b?Symbol.for("react.forward_ref"):60112,p=b?Symbol.for("react.suspense"):60113,q=b? +Symbol.for("react.suspense_list"):60120,r=b?Symbol.for("react.memo"):60115,t=b?Symbol.for("react.lazy"):60116,v=b?Symbol.for("react.block"):60121,w=b?Symbol.for("react.fundamental"):60117,x=b?Symbol.for("react.responder"):60118,y=b?Symbol.for("react.scope"):60119; +function z(a){if("object"===typeof a&&null!==a){var u=a.$$typeof;switch(u){case c:switch(a=a.type,a){case l:case m:case e:case g:case f:case p:return a;default:switch(a=a&&a.$$typeof,a){case k:case n:case t:case r:case h:return a;default:return u}}case d:return u}}}function A(a){return z(a)===m}exports.AsyncMode=l;exports.ConcurrentMode=m;exports.ContextConsumer=k;exports.ContextProvider=h;exports.Element=c;exports.ForwardRef=n;exports.Fragment=e;exports.Lazy=t;exports.Memo=r;exports.Portal=d; +exports.Profiler=g;exports.StrictMode=f;exports.Suspense=p;exports.isAsyncMode=function(a){return A(a)||z(a)===l};exports.isConcurrentMode=A;exports.isContextConsumer=function(a){return z(a)===k};exports.isContextProvider=function(a){return z(a)===h};exports.isElement=function(a){return"object"===typeof a&&null!==a&&a.$$typeof===c};exports.isForwardRef=function(a){return z(a)===n};exports.isFragment=function(a){return z(a)===e};exports.isLazy=function(a){return z(a)===t}; +exports.isMemo=function(a){return z(a)===r};exports.isPortal=function(a){return z(a)===d};exports.isProfiler=function(a){return z(a)===g};exports.isStrictMode=function(a){return z(a)===f};exports.isSuspense=function(a){return z(a)===p}; +exports.isValidElementType=function(a){return"string"===typeof a||"function"===typeof a||a===e||a===m||a===g||a===f||a===p||a===q||"object"===typeof a&&null!==a&&(a.$$typeof===t||a.$$typeof===r||a.$$typeof===h||a.$$typeof===k||a.$$typeof===n||a.$$typeof===w||a.$$typeof===x||a.$$typeof===y||a.$$typeof===v)};exports.typeOf=z; + +},{}],11:[function(require,module,exports){ +(function (process){(function (){ +'use strict'; + +if (process.env.NODE_ENV === 'production') { + module.exports = require('./cjs/react-is.production.min.js'); +} else { + module.exports = require('./cjs/react-is.development.js'); +} + +}).call(this)}).call(this,require('_process')) +},{"./cjs/react-is.development.js":9,"./cjs/react-is.production.min.js":10,"_process":8}]},{},[4])(4) +}); diff --git a/backend/node_modules/prop-types/prop-types.min.js b/backend/node_modules/prop-types/prop-types.min.js new file mode 100644 index 00000000..7a746e12 --- /dev/null +++ b/backend/node_modules/prop-types/prop-types.min.js @@ -0,0 +1 @@ +!function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).PropTypes=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var p="function"==typeof require&&require;if(!f&&p)return p(i,!0);if(u)return u(i,!0);throw(p=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",p}p=n[i]={exports:{}},e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i QR code/2d barcode generator. + +[![Travis](https://img.shields.io/travis/soldair/node-qrcode.svg?style=flat-square)](http://travis-ci.org/soldair/node-qrcode) +[![npm](https://img.shields.io/npm/v/qrcode.svg?style=flat-square)](https://www.npmjs.com/package/qrcode) +[![npm](https://img.shields.io/npm/dt/qrcode.svg?style=flat-square)](https://www.npmjs.com/package/qrcode) +[![npm](https://img.shields.io/npm/l/qrcode.svg?style=flat-square)](https://github.com/soldair/node-qrcode/blob/master/license) + +- [Highlights](#highlights) +- [Installation](#installation) +- [Usage](#usage) +- [Error correction level](#error-correction-level) +- [QR Code capacity](#qr-code-capacity) +- [Encoding Modes](#encoding-modes) +- [Binary data](#binary-data) +- [Multibyte characters](#multibyte-characters) +- [API](#api) +- [GS1 QR Codes](#gs1-qr-codes) +- [Credits](#credits) +- [License](#license) + +## Highlights +- Works on server and client (and react native with svg) +- CLI utility +- Save QR code as image +- Support for Numeric, Alphanumeric, Kanji and Byte mode +- Support for mixed modes +- Support for chinese, cyrillic, greek and japanese characters +- Support for multibyte characters (like emojis :smile:) +- Auto generates optimized segments for best data compression and smallest QR Code size +- App agnostic readability, QR Codes by definition are app agnostic + +## Installation +Inside your project folder do: + +```shell +npm install --save qrcode +``` + +or, install it globally to use `qrcode` from the command line to save qrcode images or generate ones you can view in your terminal. + +```shell +npm install -g qrcode +``` + +## Usage +### CLI + +``` +Usage: qrcode [options] + +QR Code options: + -v, --qversion QR Code symbol version (1 - 40) [number] + -e, --error Error correction level [choices: "L", "M", "Q", "H"] + -m, --mask Mask pattern (0 - 7) [number] + +Renderer options: + -t, --type Output type [choices: "png", "svg", "utf8"] + -w, --width Image width (px) [number] + -s, --scale Scale factor [number] + -q, --qzone Quiet zone size [number] + -l, --lightcolor Light RGBA hex color + -d, --darkcolor Dark RGBA hex color + --small Output smaller QR code to terminal [boolean] + +Options: + -o, --output Output file + -h, --help Show help [boolean] + --version Show version number [boolean] + +Examples: + qrcode "some text" Draw in terminal window + qrcode -o out.png "some text" Save as png image + qrcode -d F00 -o out.png "some text" Use red as foreground color +``` +If not specified, output type is guessed from file extension.
+Recognized extensions are `png`, `svg` and `txt`. + +### Browser +`node-qrcode` can be used in browser through module bundlers like [Browserify](https://github.com/substack/node-browserify) and [Webpack](https://github.com/webpack/webpack) or by including the precompiled bundle present in `build/` folder. + +#### Module bundlers +```html + + + + + + + +``` + +```javascript +// index.js -> bundle.js +var QRCode = require('qrcode') +var canvas = document.getElementById('canvas') + +QRCode.toCanvas(canvas, 'sample text', function (error) { + if (error) console.error(error) + console.log('success!'); +}) +``` + +#### Precompiled bundle +```html + + + + +``` + +If you install through `npm`, precompiled files will be available in `node_modules/qrcode/build/` folder. + +The precompiled bundle have support for [Internet Explorer 10+, Safari 5.1+, and all evergreen browsers](https://browserl.ist/?q=defaults%2C+IE+%3E%3D+10%2C+Safari+%3E%3D+5.1). + +### NodeJS +Require the module `qrcode` + +```javascript +var QRCode = require('qrcode') + +QRCode.toDataURL('I am a pony!', function (err, url) { + console.log(url) +}) +``` + +render a qrcode for the terminal +```js +var QRCode = require('qrcode') + +QRCode.toString('I am a pony!',{type:'terminal'}, function (err, url) { + console.log(url) +}) +``` + +### ES6/ES7 +Promises and Async/Await can be used in place of callback function. + +```javascript +import QRCode from 'qrcode' + +// With promises +QRCode.toDataURL('I am a pony!') + .then(url => { + console.log(url) + }) + .catch(err => { + console.error(err) + }) + +// With async/await +const generateQR = async text => { + try { + console.log(await QRCode.toDataURL(text)) + } catch (err) { + console.error(err) + } +} +``` + +## Error correction level +Error correction capability allows to successfully scan a QR Code even if the symbol is dirty or damaged. +Four levels are available to choose according to the operating environment. + +Higher levels offer a better error resistance but reduce the symbol's capacity.
+If the chances that the QR Code symbol may be corrupted are low (for example if it is showed through a monitor) +is possible to safely use a low error level such as `Low` or `Medium`. + +Possible levels are shown below: + +| Level | Error resistance | +|------------------|:----------------:| +| **L** (Low) | **~7%** | +| **M** (Medium) | **~15%** | +| **Q** (Quartile) | **~25%** | +| **H** (High) | **~30%** | + +The percentage indicates the maximum amount of damaged surface after which the symbol becomes unreadable. + +Error level can be set through `options.errorCorrectionLevel` property.
+If not specified, the default value is `M`. + +```javascript +QRCode.toDataURL('some text', { errorCorrectionLevel: 'H' }, function (err, url) { + console.log(url) +}) +``` + +## QR Code capacity +Capacity depends on symbol version and error correction level. Also encoding modes may influence the amount of storable data. + +The QR Code versions range from version **1** to version **40**.
+Each version has a different number of modules (black and white dots), which define the symbol's size. +For version 1 they are `21x21`, for version 2 `25x25` e so on. +Higher is the version, more are the storable data, and of course bigger will be the QR Code symbol. + +The table below shows the maximum number of storable characters in each encoding mode and for each error correction level. + +| Mode | L | M | Q | H | +|--------------|------|------|------|------| +| Numeric | 7089 | 5596 | 3993 | 3057 | +| Alphanumeric | 4296 | 3391 | 2420 | 1852 | +| Byte | 2953 | 2331 | 1663 | 1273 | +| Kanji | 1817 | 1435 | 1024 | 784 | + +**Note:** Maximum characters number can be different when using [Mixed modes](#mixed-modes). + +QR Code version can be set through `options.version` property.
+If no version is specified, the more suitable value will be used. Unless a specific version is required, this option is not needed. + +```javascript +QRCode.toDataURL('some text', { version: 2 }, function (err, url) { + console.log(url) +}) +``` + +## Encoding modes +Modes can be used to encode a string in a more efficient way.
+A mode may be more suitable than others depending on the string content. +A list of supported modes are shown in the table below: + +| Mode | Characters | Compression | +|--------------|-----------------------------------------------------------|-------------------------------------------| +| Numeric | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 | 3 characters are represented by 10 bits | +| Alphanumeric | 0–9, A–Z (upper-case only), space, $, %, *, +, -, ., /, : | 2 characters are represented by 11 bits | +| Kanji | Characters from the Shift JIS system based on JIS X 0208 | 2 kanji are represented by 13 bits | +| Byte | Characters from the ISO/IEC 8859-1 character set | Each characters are represented by 8 bits | + +Choose the right mode may be tricky if the input text is unknown.
+In these cases **Byte** mode is the best choice since all characters can be encoded with it. (See [Multibyte characters](#multibyte-characters))
+However, if the QR Code reader supports mixed modes, using [Auto mode](#auto-mode) may produce better results. + +### Mixed modes +Mixed modes are also possible. A QR code can be generated from a series of segments having different encoding modes to optimize the data compression.
+However, switching from a mode to another has a cost which may lead to a worst result if it's not taken into account. +See [Manual mode](#manual-mode) for an example of how to specify segments with different encoding modes. + +### Auto mode +By **default**, automatic mode selection is used.
+The input string is automatically splitted in various segments optimized to produce the shortest possible bitstream using mixed modes.
+This is the preferred way to generate the QR Code. + +For example, the string **ABCDE12345678?A1A** will be splitted in 3 segments with the following modes: + +| Segment | Mode | +|----------|--------------| +| ABCDE | Alphanumeric | +| 12345678 | Numeric | +| ?A1A | Byte | + +Any other combinations of segments and modes will result in a longer bitstream.
+If you need to keep the QR Code size small, this mode will produce the best results. + +### Manual mode +If auto mode doesn't work for you or you have specific needs, is also possible to manually specify each segment with the relative mode. +In this way no segment optimizations will be applied under the hood.
+Segments list can be passed as an array of object: + +```javascript + var QRCode = require('qrcode') + + var segs = [ + { data: 'ABCDEFG', mode: 'alphanumeric' }, + { data: '0123456', mode: 'numeric' } + ] + + QRCode.toDataURL(segs, function (err, url) { + console.log(url) + }) +``` + +### Kanji mode +With kanji mode is possible to encode characters from the Shift JIS system in an optimized way.
+Unfortunately, there isn't a way to calculate a Shifted JIS values from, for example, a character encoded in UTF-8, for this reason a conversion table from the input characters to the SJIS values is needed.
+This table is not included by default in the bundle to keep the size as small as possible. + +If your application requires kanji support, you will need to pass a function that will take care of converting the input characters to appropriate values. + +An helper method is provided by the lib through an optional file that you can include as shown in the example below. + +**Note:** Support for Kanji mode is only needed if you want to benefit of the data compression, otherwise is still possible to encode kanji using Byte mode (See [Multibyte characters](#multibyte-characters)). + +```javascript + var QRCode = require('qrcode') + var toSJIS = require('qrcode/helper/to-sjis') + + QRCode.toDataURL(kanjiString, { toSJISFunc: toSJIS }, function (err, url) { + console.log(url) + }) +``` + +With precompiled bundle: + +```html + + + + + +``` + +## Binary data +QR Codes can hold arbitrary byte-based binary data. If you attempt to create a binary QR Code by first converting the data to a JavaScript string, it will fail to encode propery because string encoding adds additional bytes. Instead, you must pass a [`Uint8ClampedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray) or compatible array, or a Node [Buffer](https://nodejs.org/api/buffer.html), as follows: + +```javascript +// Regular array example +// WARNING: Element values will be clamped to 0-255 even if your data contains higher values. +const QRCode = require('qrcode') +QRCode.toFile( + 'foo.png', + [{ data: [253,254,255], mode: 'byte' }], + ...options..., + ...callback... +) +``` + +```javascript +// Uint8ClampedArray example +const QRCode = require('qrcode') + +QRCode.toFile( + 'foo.png', + [{ data: new Uint8ClampedArray([253,254,255]), mode: 'byte' }], + ...options..., + ...callback... +) +``` + +```javascript +// Node Buffer example +// WARNING: Element values will be clamped to 0-255 even if your data contains higher values. +const QRCode = require('qrcode') + +QRCode.toFile( + 'foo.png', + [{ data: Buffer.from([253,254,255]), mode: 'byte' }], + ...options..., + ...callback... +) +``` + +TypeScript users: if you are using [@types/qrcode](https://www.npmjs.com/package/@types/qrcode), you will need to add a `// @ts-ignore` above the data segment because it expects `data: string`. + +## Multibyte characters +Support for multibyte characters isn't present in the initial QR Code standard, but is possible to encode UTF-8 characters in Byte mode. + +QR Codes provide a way to specify a different type of character set through ECI (Extended Channel Interpretation), but it's not fully implemented in this lib yet. + +Most QR Code readers, however, are able to recognize multibyte characters even without ECI. + +Note that a single Kanji/Kana or Emoji can take up to 4 bytes. + +## API +Browser: +- [create()](#createtext-options) +- [toCanvas()](#tocanvascanvaselement-text-options-cberror) +- [toDataURL()](#todataurltext-options-cberror-url) +- [toString()](#tostringtext-options-cberror-string) + +Server: +- [create()](#createtext-options) +- [toCanvas()](#tocanvascanvas-text-options-cberror) +- [toDataURL()](#todataurltext-options-cberror-url-1) +- [toString()](#tostringtext-options-cberror-string-1) +- [toFile()](#tofilepath-text-options-cberror) +- [toFileStream()](#tofilestreamstream-text-options) + +### Browser API +#### `create(text, [options])` +Creates QR Code symbol and returns a qrcode object. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [QR Code options](#qr-code-options). + +##### `returns` +Type: `Object` + +```javascript +// QRCode object +{ + modules, // Bitmatrix class with modules data + version, // Calculated QR Code version + errorCorrectionLevel, // Error Correction Level + maskPattern, // Calculated Mask pattern + segments // Generated segments +} +``` + +
+ +#### `toCanvas(canvasElement, text, [options], [cb(error)])` +#### `toCanvas(text, [options], [cb(error, canvas)])` +Draws qr code symbol to canvas.
+If `canvasElement` is omitted a new canvas is returned. + +##### `canvasElement` +Type: `DOMElement` + +Canvas where to draw QR Code. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [Options](#options). + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +QRCode.toCanvas('text', { errorCorrectionLevel: 'H' }, function (err, canvas) { + if (err) throw err + + var container = document.getElementById('container') + container.appendChild(canvas) +}) +``` + +
+ +#### `toDataURL(text, [options], [cb(error, url)])` +#### `toDataURL(canvasElement, text, [options], [cb(error, url)])` +Returns a Data URI containing a representation of the QR Code image.
+If provided, `canvasElement` will be used as canvas to generate the data URI. + +##### `canvasElement` +Type: `DOMElement` + +Canvas where to draw QR Code. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +- ###### `type` + Type: `String`
+ Default: `image/png` + + Data URI format.
+ Possible values are: `image/png`, `image/jpeg`, `image/webp`.
+ +- ###### `rendererOpts.quality` + Type: `Number`
+ Default: `0.92` + + A Number between `0` and `1` indicating image quality if the requested type is `image/jpeg` or `image/webp`. + +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +var opts = { + errorCorrectionLevel: 'H', + type: 'image/jpeg', + quality: 0.3, + margin: 1, + color: { + dark:"#010599FF", + light:"#FFBF60FF" + } +} + +QRCode.toDataURL('text', opts, function (err, url) { + if (err) throw err + + var img = document.getElementById('image') + img.src = url +}) +``` +
+ +#### `toString(text, [options], [cb(error, string)])` + +Returns a string representation of the QR Code.
+ + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +- ###### `type` + Type: `String`
+ Default: `utf8` + + Output format.
+ Possible values are: `terminal`,`utf8`, and `svg`. + +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +QRCode.toString('http://www.google.com', function (err, string) { + if (err) throw err + console.log(string) +}) +``` + +
+ + +### Server API +#### `create(text, [options])` +See [create](#createtext-options). + +
+ +#### `toCanvas(canvas, text, [options], [cb(error)])` +Draws qr code symbol to [node canvas](https://github.com/Automattic/node-canvas). + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [Options](#options). + +##### `cb` +Type: `Function` + +Callback function called on finish. + +
+ +#### `toDataURL(text, [options], [cb(error, url)])` +Returns a Data URI containing a representation of the QR Code image.
+Only works with `image/png` type for now. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +
+ +#### `toString(text, [options], [cb(error, string)])` +Returns a string representation of the QR Code.
+If choosen output format is `svg` it will returns a string containing xml code. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +- ###### `type` + Type: `String`
+ Default: `utf8` + + Output format.
+ Possible values are: `utf8`, `svg`, `terminal`. + +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +QRCode.toString('http://www.google.com', function (err, string) { + if (err) throw err + console.log(string) +}) +``` + +
+ +#### `toFile(path, text, [options], [cb(error)])` +Saves QR Code to image file.
+If `options.type` is not specified, the format will be guessed from file extension.
+Recognized extensions are `png`, `svg`, `txt`. + +##### `path` +Type: `String` + +Path where to save the file. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +- ###### `type` + Type: `String`
+ Default: `png` + + Output format.
+ Possible values are: `png`, `svg`, `utf8`. + +- ###### `rendererOpts.deflateLevel` **(png only)** + Type: `Number`
+ Default: `9` + + Compression level for deflate. + +- ###### `rendererOpts.deflateStrategy` **(png only)** + Type: `Number`
+ Default: `3` + + Compression strategy for deflate. + +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +QRCode.toFile('path/to/filename.png', 'Some text', { + color: { + dark: '#00F', // Blue dots + light: '#0000' // Transparent background + } +}, function (err) { + if (err) throw err + console.log('done') +}) +``` + +
+ +#### `toFileStream(stream, text, [options])` +Writes QR Code image to stream. Only works with `png` format for now. + +##### `stream` +Type: `stream.Writable` + +Node stream. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [Options](#options). + +
+ +### Options + +#### QR Code options +##### `version` + Type: `Number`
+ + QR Code version. If not specified the more suitable value will be calculated. + +##### `errorCorrectionLevel` + Type: `String`
+ Default: `M` + + Error correction level.
+ Possible values are `low, medium, quartile, high` or `L, M, Q, H`. + +##### `maskPattern` + Type: `Number`
+ + Mask pattern used to mask the symbol.
+ Possible values are `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`.
+ If not specified the more suitable value will be calculated. + +##### `toSJISFunc` + Type: `Function`
+ + Helper function used internally to convert a kanji to its Shift JIS value.
+ Provide this function if you need support for Kanji mode. + +#### Renderers options +##### `margin` + Type: `Number`
+ Default: `4` + + Define how much wide the quiet zone should be. + +##### `scale` + Type: `Number`
+ Default: `4` + + Scale factor. A value of `1` means 1px per modules (black dots). + +##### `small` + Type: `Boolean`
+ Default: `false` + + Relevant only for terminal renderer. Outputs smaller QR code. + +##### `width` + Type: `Number`
+ + Forces a specific width for the output image.
+ If width is too small to contain the qr symbol, this option will be ignored.
+ Takes precedence over `scale`. + +##### `color.dark` +Type: `String`
+Default: `#000000ff` + +Color of dark module. Value must be in hex format (RGBA).
+Note: dark color should always be darker than `color.light`. + +##### `color.light` +Type: `String`
+Default: `#ffffffff` + +Color of light module. Value must be in hex format (RGBA).
+ +
+ +## GS1 QR Codes +There was a real good discussion here about them. but in short any qrcode generator will make gs1 compatible qrcodes, but what defines a gs1 qrcode is a header with metadata that describes your gs1 information. + +https://github.com/soldair/node-qrcode/issues/45 + + +## Credits +This lib is based on "QRCode for JavaScript" which Kazuhiko Arase thankfully MIT licensed. + +## License +[MIT](https://github.com/soldair/node-qrcode/blob/master/license) + +The word "QR Code" is registered trademark of:
+DENSO WAVE INCORPORATED diff --git a/backend/node_modules/qrcode/bin/qrcode b/backend/node_modules/qrcode/bin/qrcode new file mode 100644 index 00000000..dd990b63 --- /dev/null +++ b/backend/node_modules/qrcode/bin/qrcode @@ -0,0 +1,159 @@ +#!/usr/bin/env node +var yargs = require('yargs') +var qr = require('../lib') + +function save (file, text, options) { + qr.toFile(file, text, options, function (err, data) { + if (err) { + console.error('Error:', err.message) + process.exit(1) + } + + console.log('saved qrcode to: ' + file + '\n') + }) +} + +function print (text, options) { + options.type = 'terminal' + qr.toString(text, options, function (err, text) { + if (err) { + console.error('Error:', err.message) + process.exit(1) + } + + console.log(text) + }) +} + +function parseOptions (args) { + return { + version: args.qversion, + errorCorrectionLevel: args.error, + type: args.type, + small: !!args.small, + inverse: !!args.inverse, + maskPattern: args.mask, + margin: args.qzone, + width: args.width, + scale: args.scale, + color: { + light: args.lightcolor, + dark: args.darkcolor + } + } +} + +function processInputs (text, opts) { + if (!text.length) { + yargs.showHelp() + process.exit(1) + } + + if (opts.output) { + save(opts.output, text, parseOptions(opts)) + } else { + print(text, parseOptions(opts)) + } +} + +var argv = yargs + .detectLocale(false) + .usage('Usage: $0 [options] ') + .option('v', { + alias: 'qversion', + description: 'QR Code symbol version (1 - 40)', + group: 'QR Code options:', + type: 'number' + }) + .option('e', { + alias: 'error', + description: 'Error correction level', + choices: ['L', 'M', 'Q', 'H'], + group: 'QR Code options:' + }) + .option('m', { + alias: 'mask', + description: 'Mask pattern (0 - 7)', + group: 'QR Code options:', + type: 'number' + }) + .option('t', { + alias: 'type', + description: 'Output type', + choices: ['png', 'svg', 'utf8'], + implies: 'output', + group: 'Renderer options:' + }) + .option('i', { + alias: 'inverse', + type: 'boolean', + description: 'Invert colors', + group: 'Renderer options:' + }) + .option('w', { + alias: 'width', + description: 'Image width (px)', + conflicts: 'scale', + group: 'Renderer options:', + type: 'number' + }) + .option('s', { + alias: 'scale', + description: 'Scale factor', + conflicts: 'width', + group: 'Renderer options:', + type: 'number' + }) + .option('q', { + alias: 'qzone', + description: 'Quiet zone size', + group: 'Renderer options:', + type: 'number' + }) + .option('l', { + alias: 'lightcolor', + description: 'Light RGBA hex color', + group: 'Renderer options:' + }) + .option('d', { + alias: 'darkcolor', + description: 'Dark RGBA hex color', + group: 'Renderer options:' + }) + .option('small', { + type: 'boolean', + description: 'Output smaller QR code to terminal', + conflicts: 'type', + group: 'Renderer options:' + }) + .option('o', { + alias: 'output', + description: 'Output file' + }) + .help('h') + .alias('h', 'help') + .version() + .example('$0 "some text"', 'Draw in terminal window') + .example('$0 -o out.png "some text"', 'Save as png image') + .example('$0 -d F00 -o out.png "some text"', 'Use red as foreground color') + .parserConfiguration({'parse-numbers': false}) + .argv + +if (process.stdin.isTTY) { + processInputs(argv._.join(' '), argv) +} else { + var text = '' + process.stdin.setEncoding('utf8') + process.stdin.on('readable', function () { + var chunk = process.stdin.read() + if (chunk !== null) { + text += chunk + } + }) + + process.stdin.on('end', function () { + // this process can be run as a command outside of a tty so if there was no + // data on stdin read from argv + processInputs(text.length?text:argv._.join(' '), argv) + }) +} diff --git a/backend/node_modules/qrcode/helper/to-sjis-browser.js b/backend/node_modules/qrcode/helper/to-sjis-browser.js new file mode 100644 index 00000000..1c9b3aa7 --- /dev/null +++ b/backend/node_modules/qrcode/helper/to-sjis-browser.js @@ -0,0 +1,2 @@ +/* global QRCode */ +QRCode.toSJIS = require('./to-sjis') diff --git a/backend/node_modules/qrcode/helper/to-sjis.js b/backend/node_modules/qrcode/helper/to-sjis.js new file mode 100644 index 00000000..594c6f7c --- /dev/null +++ b/backend/node_modules/qrcode/helper/to-sjis.js @@ -0,0 +1,105 @@ +const SJIS_UTF8 = [ + [0x8140, ' 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+-±×'], + [0x8180, '÷=≠<>≦≧∞∴♂♀°′″℃'], + [0x818f, '¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼'], + [0x81a6, '※〒→←↑↓〓'], + [0x81b8, '∈∋⊆⊇⊂⊃∪∩'], + [0x81c8, '∧∨¬⇒⇔∀∃'], + [0x81da, '∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬'], + [0x81f0, 'ʼn♯♭♪†‡¶'], + [0x824f, '0123456789'], + [0x8260, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], + [0x8281, 'abcdefghijklmnopqrstuvwxyz'], + [0x829f, 'ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん'], + [0x8340, 'ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミ'], + [0x8380, 'ムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ'], + [0x839f, 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ'], + [0x83bf, 'αβγδεζηθικλμνξοπρστυφχψω'], + [0x8440, 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'], + [0x8470, 'абвгдеёжзийклмн'], + [0x8480, 'опрстуфхцчшщъыьэюя'], + [0x8780, '〝〟'], + [0x889f, '亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣'], + [0x88e0, '謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭'], + [0x8940, '院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円'], + [0x8980, '園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改'], + [0x8a40, '魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫'], + [0x8a80, '橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄'], + [0x8b40, '機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救'], + [0x8b80, '朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈'], + [0x8c40, '掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨'], + [0x8c80, '劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向'], + [0x8d40, '后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降'], + [0x8d80, '項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷'], + [0x8e40, '察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止'], + [0x8e80, '死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周'], + [0x8f40, '宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳'], + [0x8f80, '準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾'], + [0x9040, '拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨'], + [0x9080, '逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線'], + [0x9140, '繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻'], + [0x9180, '操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只'], + [0x9240, '叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄'], + [0x9280, '逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓'], + [0x9340, '邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬'], + [0x9380, '凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入'], + [0x9440, '如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅'], + [0x9480, '楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美'], + [0x9540, '鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷'], + [0x9580, '斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋'], + [0x9640, '法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆'], + [0x9680, '摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒'], + [0x9740, '諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲'], + [0x9780, '沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯'], + [0x9840, '蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕'], + [0x989f, '弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲'], + [0x9940, '僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭'], + [0x9980, '凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨'], + [0x9a40, '咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸'], + [0x9a80, '噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩'], + [0x9b40, '奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀'], + [0x9b80, '它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏'], + [0x9c40, '廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠'], + [0x9c80, '怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛'], + [0x9d40, '戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫'], + [0x9d80, '捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼'], + [0x9e40, '曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎'], + [0x9e80, '梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣'], + [0x9f40, '檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯'], + [0x9f80, '麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌'], + [0xe040, '漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝'], + [0xe080, '烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱'], + [0xe140, '瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿'], + [0xe180, '痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬'], + [0xe240, '磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰'], + [0xe280, '窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆'], + [0xe340, '紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷'], + [0xe380, '縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋'], + [0xe440, '隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤'], + [0xe480, '艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈'], + [0xe540, '蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬'], + [0xe580, '蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞'], + [0xe640, '襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧'], + [0xe680, '諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊'], + [0xe740, '蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜'], + [0xe780, '轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮'], + [0xe840, '錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙'], + [0xe880, '閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰'], + [0xe940, '顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃'], + [0xe980, '騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈'], + [0xea40, '鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯'], + [0xea80, '黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠堯槇遙瑤凜熙'] +] + +module.exports = function toSJIS (utf8Char) { + if (!utf8Char || utf8Char === '') return + + for (let i = 0; i < SJIS_UTF8.length; i++) { + const kanji = SJIS_UTF8[i][1] + + const posIndex = kanji.indexOf(utf8Char) + if (posIndex >= 0) { + return SJIS_UTF8[i][0] + posIndex + } + } +} diff --git a/backend/node_modules/qrcode/lib/browser.js b/backend/node_modules/qrcode/lib/browser.js new file mode 100644 index 00000000..dc8a9998 --- /dev/null +++ b/backend/node_modules/qrcode/lib/browser.js @@ -0,0 +1,76 @@ + +const canPromise = require('./can-promise') + +const QRCode = require('./core/qrcode') +const CanvasRenderer = require('./renderer/canvas') +const SvgRenderer = require('./renderer/svg-tag.js') + +function renderCanvas (renderFunc, canvas, text, opts, cb) { + const args = [].slice.call(arguments, 1) + const argsNum = args.length + const isLastArgCb = typeof args[argsNum - 1] === 'function' + + if (!isLastArgCb && !canPromise()) { + throw new Error('Callback required as last argument') + } + + if (isLastArgCb) { + if (argsNum < 2) { + throw new Error('Too few arguments provided') + } + + if (argsNum === 2) { + cb = text + text = canvas + canvas = opts = undefined + } else if (argsNum === 3) { + if (canvas.getContext && typeof cb === 'undefined') { + cb = opts + opts = undefined + } else { + cb = opts + opts = text + text = canvas + canvas = undefined + } + } + } else { + if (argsNum < 1) { + throw new Error('Too few arguments provided') + } + + if (argsNum === 1) { + text = canvas + canvas = opts = undefined + } else if (argsNum === 2 && !canvas.getContext) { + opts = text + text = canvas + canvas = undefined + } + + return new Promise(function (resolve, reject) { + try { + const data = QRCode.create(text, opts) + resolve(renderFunc(data, canvas, opts)) + } catch (e) { + reject(e) + } + }) + } + + try { + const data = QRCode.create(text, opts) + cb(null, renderFunc(data, canvas, opts)) + } catch (e) { + cb(e) + } +} + +exports.create = QRCode.create +exports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render) +exports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL) + +// only svg for now. +exports.toString = renderCanvas.bind(null, function (data, _, opts) { + return SvgRenderer.render(data, opts) +}) diff --git a/backend/node_modules/qrcode/lib/can-promise.js b/backend/node_modules/qrcode/lib/can-promise.js new file mode 100644 index 00000000..77267f15 --- /dev/null +++ b/backend/node_modules/qrcode/lib/can-promise.js @@ -0,0 +1,7 @@ +// can-promise has a crash in some versions of react native that dont have +// standard global objects +// https://github.com/soldair/node-qrcode/issues/157 + +module.exports = function () { + return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then +} diff --git a/backend/node_modules/qrcode/lib/core/alignment-pattern.js b/backend/node_modules/qrcode/lib/core/alignment-pattern.js new file mode 100644 index 00000000..63c3154e --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/alignment-pattern.js @@ -0,0 +1,83 @@ +/** + * Alignment pattern are fixed reference pattern in defined positions + * in a matrix symbology, which enables the decode software to re-synchronise + * the coordinate mapping of the image modules in the event of moderate amounts + * of distortion of the image. + * + * Alignment patterns are present only in QR Code symbols of version 2 or larger + * and their number depends on the symbol version. + */ + +const getSymbolSize = require('./utils').getSymbolSize + +/** + * Calculate the row/column coordinates of the center module of each alignment pattern + * for the specified QR Code version. + * + * The alignment patterns are positioned symmetrically on either side of the diagonal + * running from the top left corner of the symbol to the bottom right corner. + * + * Since positions are simmetrical only half of the coordinates are returned. + * Each item of the array will represent in turn the x and y coordinate. + * @see {@link getPositions} + * + * @param {Number} version QR Code version + * @return {Array} Array of coordinate + */ +exports.getRowColCoords = function getRowColCoords (version) { + if (version === 1) return [] + + const posCount = Math.floor(version / 7) + 2 + const size = getSymbolSize(version) + const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2 + const positions = [size - 7] // Last coord is always (size - 7) + + for (let i = 1; i < posCount - 1; i++) { + positions[i] = positions[i - 1] - intervals + } + + positions.push(6) // First coord is always 6 + + return positions.reverse() +} + +/** + * Returns an array containing the positions of each alignment pattern. + * Each array's element represent the center point of the pattern as (x, y) coordinates + * + * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords} + * and filtering out the items that overlaps with finder pattern + * + * @example + * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38. + * The alignment patterns, therefore, are to be centered on (row, column) + * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38). + * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns + * and are not therefore used for alignment patterns. + * + * let pos = getPositions(7) + * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]] + * + * @param {Number} version QR Code version + * @return {Array} Array of coordinates + */ +exports.getPositions = function getPositions (version) { + const coords = [] + const pos = exports.getRowColCoords(version) + const posLength = pos.length + + for (let i = 0; i < posLength; i++) { + for (let j = 0; j < posLength; j++) { + // Skip if position is occupied by finder patterns + if ((i === 0 && j === 0) || // top-left + (i === 0 && j === posLength - 1) || // bottom-left + (i === posLength - 1 && j === 0)) { // top-right + continue + } + + coords.push([pos[i], pos[j]]) + } + } + + return coords +} diff --git a/backend/node_modules/qrcode/lib/core/alphanumeric-data.js b/backend/node_modules/qrcode/lib/core/alphanumeric-data.js new file mode 100644 index 00000000..29ddf50c --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/alphanumeric-data.js @@ -0,0 +1,59 @@ +const Mode = require('./mode') + +/** + * Array of characters available in alphanumeric mode + * + * As per QR Code specification, to each character + * is assigned a value from 0 to 44 which in this case coincides + * with the array index + * + * @type {Array} + */ +const ALPHA_NUM_CHARS = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + ' ', '$', '%', '*', '+', '-', '.', '/', ':' +] + +function AlphanumericData (data) { + this.mode = Mode.ALPHANUMERIC + this.data = data +} + +AlphanumericData.getBitsLength = function getBitsLength (length) { + return 11 * Math.floor(length / 2) + 6 * (length % 2) +} + +AlphanumericData.prototype.getLength = function getLength () { + return this.data.length +} + +AlphanumericData.prototype.getBitsLength = function getBitsLength () { + return AlphanumericData.getBitsLength(this.data.length) +} + +AlphanumericData.prototype.write = function write (bitBuffer) { + let i + + // Input data characters are divided into groups of two characters + // and encoded as 11-bit binary codes. + for (i = 0; i + 2 <= this.data.length; i += 2) { + // The character value of the first character is multiplied by 45 + let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45 + + // The character value of the second digit is added to the product + value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]) + + // The sum is then stored as 11-bit binary number + bitBuffer.put(value, 11) + } + + // If the number of input data characters is not a multiple of two, + // the character value of the final character is encoded as a 6-bit binary number. + if (this.data.length % 2) { + bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6) + } +} + +module.exports = AlphanumericData diff --git a/backend/node_modules/qrcode/lib/core/bit-buffer.js b/backend/node_modules/qrcode/lib/core/bit-buffer.js new file mode 100644 index 00000000..5b41d3d9 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/bit-buffer.js @@ -0,0 +1,37 @@ +function BitBuffer () { + this.buffer = [] + this.length = 0 +} + +BitBuffer.prototype = { + + get: function (index) { + const bufIndex = Math.floor(index / 8) + return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1 + }, + + put: function (num, length) { + for (let i = 0; i < length; i++) { + this.putBit(((num >>> (length - i - 1)) & 1) === 1) + } + }, + + getLengthInBits: function () { + return this.length + }, + + putBit: function (bit) { + const bufIndex = Math.floor(this.length / 8) + if (this.buffer.length <= bufIndex) { + this.buffer.push(0) + } + + if (bit) { + this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)) + } + + this.length++ + } +} + +module.exports = BitBuffer diff --git a/backend/node_modules/qrcode/lib/core/bit-matrix.js b/backend/node_modules/qrcode/lib/core/bit-matrix.js new file mode 100644 index 00000000..439138b9 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/bit-matrix.js @@ -0,0 +1,65 @@ +/** + * Helper class to handle QR Code symbol modules + * + * @param {Number} size Symbol size + */ +function BitMatrix (size) { + if (!size || size < 1) { + throw new Error('BitMatrix size must be defined and greater than 0') + } + + this.size = size + this.data = new Uint8Array(size * size) + this.reservedBit = new Uint8Array(size * size) +} + +/** + * Set bit value at specified location + * If reserved flag is set, this bit will be ignored during masking process + * + * @param {Number} row + * @param {Number} col + * @param {Boolean} value + * @param {Boolean} reserved + */ +BitMatrix.prototype.set = function (row, col, value, reserved) { + const index = row * this.size + col + this.data[index] = value + if (reserved) this.reservedBit[index] = true +} + +/** + * Returns bit value at specified location + * + * @param {Number} row + * @param {Number} col + * @return {Boolean} + */ +BitMatrix.prototype.get = function (row, col) { + return this.data[row * this.size + col] +} + +/** + * Applies xor operator at specified location + * (used during masking process) + * + * @param {Number} row + * @param {Number} col + * @param {Boolean} value + */ +BitMatrix.prototype.xor = function (row, col, value) { + this.data[row * this.size + col] ^= value +} + +/** + * Check if bit at specified location is reserved + * + * @param {Number} row + * @param {Number} col + * @return {Boolean} + */ +BitMatrix.prototype.isReserved = function (row, col) { + return this.reservedBit[row * this.size + col] +} + +module.exports = BitMatrix diff --git a/backend/node_modules/qrcode/lib/core/byte-data.js b/backend/node_modules/qrcode/lib/core/byte-data.js new file mode 100644 index 00000000..d562fcc9 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/byte-data.js @@ -0,0 +1,30 @@ +const Mode = require('./mode') + +function ByteData (data) { + this.mode = Mode.BYTE + if (typeof (data) === 'string') { + this.data = new TextEncoder().encode(data) + } else { + this.data = new Uint8Array(data) + } +} + +ByteData.getBitsLength = function getBitsLength (length) { + return length * 8 +} + +ByteData.prototype.getLength = function getLength () { + return this.data.length +} + +ByteData.prototype.getBitsLength = function getBitsLength () { + return ByteData.getBitsLength(this.data.length) +} + +ByteData.prototype.write = function (bitBuffer) { + for (let i = 0, l = this.data.length; i < l; i++) { + bitBuffer.put(this.data[i], 8) + } +} + +module.exports = ByteData diff --git a/backend/node_modules/qrcode/lib/core/error-correction-code.js b/backend/node_modules/qrcode/lib/core/error-correction-code.js new file mode 100644 index 00000000..5f2fcebb --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/error-correction-code.js @@ -0,0 +1,135 @@ +const ECLevel = require('./error-correction-level') + +const EC_BLOCKS_TABLE = [ +// L M Q H + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 2, 2, + 1, 2, 2, 4, + 1, 2, 4, 4, + 2, 4, 4, 4, + 2, 4, 6, 5, + 2, 4, 6, 6, + 2, 5, 8, 8, + 4, 5, 8, 8, + 4, 5, 8, 11, + 4, 8, 10, 11, + 4, 9, 12, 16, + 4, 9, 16, 16, + 6, 10, 12, 18, + 6, 10, 17, 16, + 6, 11, 16, 19, + 6, 13, 18, 21, + 7, 14, 21, 25, + 8, 16, 20, 25, + 8, 17, 23, 25, + 9, 17, 23, 34, + 9, 18, 25, 30, + 10, 20, 27, 32, + 12, 21, 29, 35, + 12, 23, 34, 37, + 12, 25, 34, 40, + 13, 26, 35, 42, + 14, 28, 38, 45, + 15, 29, 40, 48, + 16, 31, 43, 51, + 17, 33, 45, 54, + 18, 35, 48, 57, + 19, 37, 51, 60, + 19, 38, 53, 63, + 20, 40, 56, 66, + 21, 43, 59, 70, + 22, 45, 62, 74, + 24, 47, 65, 77, + 25, 49, 68, 81 +] + +const EC_CODEWORDS_TABLE = [ +// L M Q H + 7, 10, 13, 17, + 10, 16, 22, 28, + 15, 26, 36, 44, + 20, 36, 52, 64, + 26, 48, 72, 88, + 36, 64, 96, 112, + 40, 72, 108, 130, + 48, 88, 132, 156, + 60, 110, 160, 192, + 72, 130, 192, 224, + 80, 150, 224, 264, + 96, 176, 260, 308, + 104, 198, 288, 352, + 120, 216, 320, 384, + 132, 240, 360, 432, + 144, 280, 408, 480, + 168, 308, 448, 532, + 180, 338, 504, 588, + 196, 364, 546, 650, + 224, 416, 600, 700, + 224, 442, 644, 750, + 252, 476, 690, 816, + 270, 504, 750, 900, + 300, 560, 810, 960, + 312, 588, 870, 1050, + 336, 644, 952, 1110, + 360, 700, 1020, 1200, + 390, 728, 1050, 1260, + 420, 784, 1140, 1350, + 450, 812, 1200, 1440, + 480, 868, 1290, 1530, + 510, 924, 1350, 1620, + 540, 980, 1440, 1710, + 570, 1036, 1530, 1800, + 570, 1064, 1590, 1890, + 600, 1120, 1680, 1980, + 630, 1204, 1770, 2100, + 660, 1260, 1860, 2220, + 720, 1316, 1950, 2310, + 750, 1372, 2040, 2430 +] + +/** + * Returns the number of error correction block that the QR Code should contain + * for the specified version and error correction level. + * + * @param {Number} version QR Code version + * @param {Number} errorCorrectionLevel Error correction level + * @return {Number} Number of error correction blocks + */ +exports.getBlocksCount = function getBlocksCount (version, errorCorrectionLevel) { + switch (errorCorrectionLevel) { + case ECLevel.L: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 0] + case ECLevel.M: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 1] + case ECLevel.Q: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 2] + case ECLevel.H: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 3] + default: + return undefined + } +} + +/** + * Returns the number of error correction codewords to use for the specified + * version and error correction level. + * + * @param {Number} version QR Code version + * @param {Number} errorCorrectionLevel Error correction level + * @return {Number} Number of error correction codewords + */ +exports.getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel) { + switch (errorCorrectionLevel) { + case ECLevel.L: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0] + case ECLevel.M: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1] + case ECLevel.Q: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2] + case ECLevel.H: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3] + default: + return undefined + } +} diff --git a/backend/node_modules/qrcode/lib/core/error-correction-level.js b/backend/node_modules/qrcode/lib/core/error-correction-level.js new file mode 100644 index 00000000..07433d6b --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/error-correction-level.js @@ -0,0 +1,50 @@ +exports.L = { bit: 1 } +exports.M = { bit: 0 } +exports.Q = { bit: 3 } +exports.H = { bit: 2 } + +function fromString (string) { + if (typeof string !== 'string') { + throw new Error('Param is not a string') + } + + const lcStr = string.toLowerCase() + + switch (lcStr) { + case 'l': + case 'low': + return exports.L + + case 'm': + case 'medium': + return exports.M + + case 'q': + case 'quartile': + return exports.Q + + case 'h': + case 'high': + return exports.H + + default: + throw new Error('Unknown EC Level: ' + string) + } +} + +exports.isValid = function isValid (level) { + return level && typeof level.bit !== 'undefined' && + level.bit >= 0 && level.bit < 4 +} + +exports.from = function from (value, defaultValue) { + if (exports.isValid(value)) { + return value + } + + try { + return fromString(value) + } catch (e) { + return defaultValue + } +} diff --git a/backend/node_modules/qrcode/lib/core/finder-pattern.js b/backend/node_modules/qrcode/lib/core/finder-pattern.js new file mode 100644 index 00000000..4613c041 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/finder-pattern.js @@ -0,0 +1,22 @@ +const getSymbolSize = require('./utils').getSymbolSize +const FINDER_PATTERN_SIZE = 7 + +/** + * Returns an array containing the positions of each finder pattern. + * Each array's element represent the top-left point of the pattern as (x, y) coordinates + * + * @param {Number} version QR Code version + * @return {Array} Array of coordinates + */ +exports.getPositions = function getPositions (version) { + const size = getSymbolSize(version) + + return [ + // top-left + [0, 0], + // top-right + [size - FINDER_PATTERN_SIZE, 0], + // bottom-left + [0, size - FINDER_PATTERN_SIZE] + ] +} diff --git a/backend/node_modules/qrcode/lib/core/format-info.js b/backend/node_modules/qrcode/lib/core/format-info.js new file mode 100644 index 00000000..11fe9efa --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/format-info.js @@ -0,0 +1,29 @@ +const Utils = require('./utils') + +const G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0) +const G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1) +const G15_BCH = Utils.getBCHDigit(G15) + +/** + * Returns format information with relative error correction bits + * + * The format information is a 15-bit sequence containing 5 data bits, + * with 10 error correction bits calculated using the (15, 5) BCH code. + * + * @param {Number} errorCorrectionLevel Error correction level + * @param {Number} mask Mask pattern + * @return {Number} Encoded format information bits + */ +exports.getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) { + const data = ((errorCorrectionLevel.bit << 3) | mask) + let d = data << 10 + + while (Utils.getBCHDigit(d) - G15_BCH >= 0) { + d ^= (G15 << (Utils.getBCHDigit(d) - G15_BCH)) + } + + // xor final data with mask pattern in order to ensure that + // no combination of Error Correction Level and data mask pattern + // will result in an all-zero data string + return ((data << 10) | d) ^ G15_MASK +} diff --git a/backend/node_modules/qrcode/lib/core/galois-field.js b/backend/node_modules/qrcode/lib/core/galois-field.js new file mode 100644 index 00000000..8125179c --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/galois-field.js @@ -0,0 +1,69 @@ +const EXP_TABLE = new Uint8Array(512) +const LOG_TABLE = new Uint8Array(256) +/** + * Precompute the log and anti-log tables for faster computation later + * + * For each possible value in the galois field 2^8, we will pre-compute + * the logarithm and anti-logarithm (exponential) of this value + * + * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields} + */ +;(function initTables () { + let x = 1 + for (let i = 0; i < 255; i++) { + EXP_TABLE[i] = x + LOG_TABLE[x] = i + + x <<= 1 // multiply by 2 + + // The QR code specification says to use byte-wise modulo 100011101 arithmetic. + // This means that when a number is 256 or larger, it should be XORed with 0x11D. + if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256) + x ^= 0x11D + } + } + + // Optimization: double the size of the anti-log table so that we don't need to mod 255 to + // stay inside the bounds (because we will mainly use this table for the multiplication of + // two GF numbers, no more). + // @see {@link mul} + for (let i = 255; i < 512; i++) { + EXP_TABLE[i] = EXP_TABLE[i - 255] + } +}()) + +/** + * Returns log value of n inside Galois Field + * + * @param {Number} n + * @return {Number} + */ +exports.log = function log (n) { + if (n < 1) throw new Error('log(' + n + ')') + return LOG_TABLE[n] +} + +/** + * Returns anti-log value of n inside Galois Field + * + * @param {Number} n + * @return {Number} + */ +exports.exp = function exp (n) { + return EXP_TABLE[n] +} + +/** + * Multiplies two number inside Galois Field + * + * @param {Number} x + * @param {Number} y + * @return {Number} + */ +exports.mul = function mul (x, y) { + if (x === 0 || y === 0) return 0 + + // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized + // @see {@link initTables} + return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]] +} diff --git a/backend/node_modules/qrcode/lib/core/kanji-data.js b/backend/node_modules/qrcode/lib/core/kanji-data.js new file mode 100644 index 00000000..a1d9a692 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/kanji-data.js @@ -0,0 +1,54 @@ +const Mode = require('./mode') +const Utils = require('./utils') + +function KanjiData (data) { + this.mode = Mode.KANJI + this.data = data +} + +KanjiData.getBitsLength = function getBitsLength (length) { + return length * 13 +} + +KanjiData.prototype.getLength = function getLength () { + return this.data.length +} + +KanjiData.prototype.getBitsLength = function getBitsLength () { + return KanjiData.getBitsLength(this.data.length) +} + +KanjiData.prototype.write = function (bitBuffer) { + let i + + // In the Shift JIS system, Kanji characters are represented by a two byte combination. + // These byte values are shifted from the JIS X 0208 values. + // JIS X 0208 gives details of the shift coded representation. + for (i = 0; i < this.data.length; i++) { + let value = Utils.toSJIS(this.data[i]) + + // For characters with Shift JIS values from 0x8140 to 0x9FFC: + if (value >= 0x8140 && value <= 0x9FFC) { + // Subtract 0x8140 from Shift JIS value + value -= 0x8140 + + // For characters with Shift JIS values from 0xE040 to 0xEBBF + } else if (value >= 0xE040 && value <= 0xEBBF) { + // Subtract 0xC140 from Shift JIS value + value -= 0xC140 + } else { + throw new Error( + 'Invalid SJIS character: ' + this.data[i] + '\n' + + 'Make sure your charset is UTF-8') + } + + // Multiply most significant byte of result by 0xC0 + // and add least significant byte to product + value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff) + + // Convert result to a 13-bit binary string + bitBuffer.put(value, 13) + } +} + +module.exports = KanjiData diff --git a/backend/node_modules/qrcode/lib/core/mask-pattern.js b/backend/node_modules/qrcode/lib/core/mask-pattern.js new file mode 100644 index 00000000..f5f8900e --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/mask-pattern.js @@ -0,0 +1,234 @@ +/** + * Data mask pattern reference + * @type {Object} + */ +exports.Patterns = { + PATTERN000: 0, + PATTERN001: 1, + PATTERN010: 2, + PATTERN011: 3, + PATTERN100: 4, + PATTERN101: 5, + PATTERN110: 6, + PATTERN111: 7 +} + +/** + * Weighted penalty scores for the undesirable features + * @type {Object} + */ +const PenaltyScores = { + N1: 3, + N2: 3, + N3: 40, + N4: 10 +} + +/** + * Check if mask pattern value is valid + * + * @param {Number} mask Mask pattern + * @return {Boolean} true if valid, false otherwise + */ +exports.isValid = function isValid (mask) { + return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7 +} + +/** + * Returns mask pattern from a value. + * If value is not valid, returns undefined + * + * @param {Number|String} value Mask pattern value + * @return {Number} Valid mask pattern or undefined + */ +exports.from = function from (value) { + return exports.isValid(value) ? parseInt(value, 10) : undefined +} + +/** +* Find adjacent modules in row/column with the same color +* and assign a penalty value. +* +* Points: N1 + i +* i is the amount by which the number of adjacent modules of the same color exceeds 5 +*/ +exports.getPenaltyN1 = function getPenaltyN1 (data) { + const size = data.size + let points = 0 + let sameCountCol = 0 + let sameCountRow = 0 + let lastCol = null + let lastRow = null + + for (let row = 0; row < size; row++) { + sameCountCol = sameCountRow = 0 + lastCol = lastRow = null + + for (let col = 0; col < size; col++) { + let module = data.get(row, col) + if (module === lastCol) { + sameCountCol++ + } else { + if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5) + lastCol = module + sameCountCol = 1 + } + + module = data.get(col, row) + if (module === lastRow) { + sameCountRow++ + } else { + if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5) + lastRow = module + sameCountRow = 1 + } + } + + if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5) + if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5) + } + + return points +} + +/** + * Find 2x2 blocks with the same color and assign a penalty value + * + * Points: N2 * (m - 1) * (n - 1) + */ +exports.getPenaltyN2 = function getPenaltyN2 (data) { + const size = data.size + let points = 0 + + for (let row = 0; row < size - 1; row++) { + for (let col = 0; col < size - 1; col++) { + const last = data.get(row, col) + + data.get(row, col + 1) + + data.get(row + 1, col) + + data.get(row + 1, col + 1) + + if (last === 4 || last === 0) points++ + } + } + + return points * PenaltyScores.N2 +} + +/** + * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column, + * preceded or followed by light area 4 modules wide + * + * Points: N3 * number of pattern found + */ +exports.getPenaltyN3 = function getPenaltyN3 (data) { + const size = data.size + let points = 0 + let bitsCol = 0 + let bitsRow = 0 + + for (let row = 0; row < size; row++) { + bitsCol = bitsRow = 0 + for (let col = 0; col < size; col++) { + bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col) + if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++ + + bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row) + if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++ + } + } + + return points * PenaltyScores.N3 +} + +/** + * Calculate proportion of dark modules in entire symbol + * + * Points: N4 * k + * + * k is the rating of the deviation of the proportion of dark modules + * in the symbol from 50% in steps of 5% + */ +exports.getPenaltyN4 = function getPenaltyN4 (data) { + let darkCount = 0 + const modulesCount = data.data.length + + for (let i = 0; i < modulesCount; i++) darkCount += data.data[i] + + const k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10) + + return k * PenaltyScores.N4 +} + +/** + * Return mask value at given position + * + * @param {Number} maskPattern Pattern reference value + * @param {Number} i Row + * @param {Number} j Column + * @return {Boolean} Mask value + */ +function getMaskAt (maskPattern, i, j) { + switch (maskPattern) { + case exports.Patterns.PATTERN000: return (i + j) % 2 === 0 + case exports.Patterns.PATTERN001: return i % 2 === 0 + case exports.Patterns.PATTERN010: return j % 3 === 0 + case exports.Patterns.PATTERN011: return (i + j) % 3 === 0 + case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0 + case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0 + case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0 + case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0 + + default: throw new Error('bad maskPattern:' + maskPattern) + } +} + +/** + * Apply a mask pattern to a BitMatrix + * + * @param {Number} pattern Pattern reference number + * @param {BitMatrix} data BitMatrix data + */ +exports.applyMask = function applyMask (pattern, data) { + const size = data.size + + for (let col = 0; col < size; col++) { + for (let row = 0; row < size; row++) { + if (data.isReserved(row, col)) continue + data.xor(row, col, getMaskAt(pattern, row, col)) + } + } +} + +/** + * Returns the best mask pattern for data + * + * @param {BitMatrix} data + * @return {Number} Mask pattern reference number + */ +exports.getBestMask = function getBestMask (data, setupFormatFunc) { + const numPatterns = Object.keys(exports.Patterns).length + let bestPattern = 0 + let lowerPenalty = Infinity + + for (let p = 0; p < numPatterns; p++) { + setupFormatFunc(p) + exports.applyMask(p, data) + + // Calculate penalty + const penalty = + exports.getPenaltyN1(data) + + exports.getPenaltyN2(data) + + exports.getPenaltyN3(data) + + exports.getPenaltyN4(data) + + // Undo previously applied mask + exports.applyMask(p, data) + + if (penalty < lowerPenalty) { + lowerPenalty = penalty + bestPattern = p + } + } + + return bestPattern +} diff --git a/backend/node_modules/qrcode/lib/core/mode.js b/backend/node_modules/qrcode/lib/core/mode.js new file mode 100644 index 00000000..fd95a6ef --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/mode.js @@ -0,0 +1,167 @@ +const VersionCheck = require('./version-check') +const Regex = require('./regex') + +/** + * Numeric mode encodes data from the decimal digit set (0 - 9) + * (byte values 30HEX to 39HEX). + * Normally, 3 data characters are represented by 10 bits. + * + * @type {Object} + */ +exports.NUMERIC = { + id: 'Numeric', + bit: 1 << 0, + ccBits: [10, 12, 14] +} + +/** + * Alphanumeric mode encodes data from a set of 45 characters, + * i.e. 10 numeric digits (0 - 9), + * 26 alphabetic characters (A - Z), + * and 9 symbols (SP, $, %, *, +, -, ., /, :). + * Normally, two input characters are represented by 11 bits. + * + * @type {Object} + */ +exports.ALPHANUMERIC = { + id: 'Alphanumeric', + bit: 1 << 1, + ccBits: [9, 11, 13] +} + +/** + * In byte mode, data is encoded at 8 bits per character. + * + * @type {Object} + */ +exports.BYTE = { + id: 'Byte', + bit: 1 << 2, + ccBits: [8, 16, 16] +} + +/** + * The Kanji mode efficiently encodes Kanji characters in accordance with + * the Shift JIS system based on JIS X 0208. + * The Shift JIS values are shifted from the JIS X 0208 values. + * JIS X 0208 gives details of the shift coded representation. + * Each two-byte character value is compacted to a 13-bit binary codeword. + * + * @type {Object} + */ +exports.KANJI = { + id: 'Kanji', + bit: 1 << 3, + ccBits: [8, 10, 12] +} + +/** + * Mixed mode will contain a sequences of data in a combination of any of + * the modes described above + * + * @type {Object} + */ +exports.MIXED = { + bit: -1 +} + +/** + * Returns the number of bits needed to store the data length + * according to QR Code specifications. + * + * @param {Mode} mode Data mode + * @param {Number} version QR Code version + * @return {Number} Number of bits + */ +exports.getCharCountIndicator = function getCharCountIndicator (mode, version) { + if (!mode.ccBits) throw new Error('Invalid mode: ' + mode) + + if (!VersionCheck.isValid(version)) { + throw new Error('Invalid version: ' + version) + } + + if (version >= 1 && version < 10) return mode.ccBits[0] + else if (version < 27) return mode.ccBits[1] + return mode.ccBits[2] +} + +/** + * Returns the most efficient mode to store the specified data + * + * @param {String} dataStr Input data string + * @return {Mode} Best mode + */ +exports.getBestModeForData = function getBestModeForData (dataStr) { + if (Regex.testNumeric(dataStr)) return exports.NUMERIC + else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC + else if (Regex.testKanji(dataStr)) return exports.KANJI + else return exports.BYTE +} + +/** + * Return mode name as string + * + * @param {Mode} mode Mode object + * @returns {String} Mode name + */ +exports.toString = function toString (mode) { + if (mode && mode.id) return mode.id + throw new Error('Invalid mode') +} + +/** + * Check if input param is a valid mode object + * + * @param {Mode} mode Mode object + * @returns {Boolean} True if valid mode, false otherwise + */ +exports.isValid = function isValid (mode) { + return mode && mode.bit && mode.ccBits +} + +/** + * Get mode object from its name + * + * @param {String} string Mode name + * @returns {Mode} Mode object + */ +function fromString (string) { + if (typeof string !== 'string') { + throw new Error('Param is not a string') + } + + const lcStr = string.toLowerCase() + + switch (lcStr) { + case 'numeric': + return exports.NUMERIC + case 'alphanumeric': + return exports.ALPHANUMERIC + case 'kanji': + return exports.KANJI + case 'byte': + return exports.BYTE + default: + throw new Error('Unknown mode: ' + string) + } +} + +/** + * Returns mode from a value. + * If value is not a valid mode, returns defaultValue + * + * @param {Mode|String} value Encoding mode + * @param {Mode} defaultValue Fallback value + * @return {Mode} Encoding mode + */ +exports.from = function from (value, defaultValue) { + if (exports.isValid(value)) { + return value + } + + try { + return fromString(value) + } catch (e) { + return defaultValue + } +} diff --git a/backend/node_modules/qrcode/lib/core/numeric-data.js b/backend/node_modules/qrcode/lib/core/numeric-data.js new file mode 100644 index 00000000..5223991c --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/numeric-data.js @@ -0,0 +1,43 @@ +const Mode = require('./mode') + +function NumericData (data) { + this.mode = Mode.NUMERIC + this.data = data.toString() +} + +NumericData.getBitsLength = function getBitsLength (length) { + return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0) +} + +NumericData.prototype.getLength = function getLength () { + return this.data.length +} + +NumericData.prototype.getBitsLength = function getBitsLength () { + return NumericData.getBitsLength(this.data.length) +} + +NumericData.prototype.write = function write (bitBuffer) { + let i, group, value + + // The input data string is divided into groups of three digits, + // and each group is converted to its 10-bit binary equivalent. + for (i = 0; i + 3 <= this.data.length; i += 3) { + group = this.data.substr(i, 3) + value = parseInt(group, 10) + + bitBuffer.put(value, 10) + } + + // If the number of input digits is not an exact multiple of three, + // the final one or two digits are converted to 4 or 7 bits respectively. + const remainingNum = this.data.length - i + if (remainingNum > 0) { + group = this.data.substr(i) + value = parseInt(group, 10) + + bitBuffer.put(value, remainingNum * 3 + 1) + } +} + +module.exports = NumericData diff --git a/backend/node_modules/qrcode/lib/core/polynomial.js b/backend/node_modules/qrcode/lib/core/polynomial.js new file mode 100644 index 00000000..c6ed9c2e --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/polynomial.js @@ -0,0 +1,62 @@ +const GF = require('./galois-field') + +/** + * Multiplies two polynomials inside Galois Field + * + * @param {Uint8Array} p1 Polynomial + * @param {Uint8Array} p2 Polynomial + * @return {Uint8Array} Product of p1 and p2 + */ +exports.mul = function mul (p1, p2) { + const coeff = new Uint8Array(p1.length + p2.length - 1) + + for (let i = 0; i < p1.length; i++) { + for (let j = 0; j < p2.length; j++) { + coeff[i + j] ^= GF.mul(p1[i], p2[j]) + } + } + + return coeff +} + +/** + * Calculate the remainder of polynomials division + * + * @param {Uint8Array} divident Polynomial + * @param {Uint8Array} divisor Polynomial + * @return {Uint8Array} Remainder + */ +exports.mod = function mod (divident, divisor) { + let result = new Uint8Array(divident) + + while ((result.length - divisor.length) >= 0) { + const coeff = result[0] + + for (let i = 0; i < divisor.length; i++) { + result[i] ^= GF.mul(divisor[i], coeff) + } + + // remove all zeros from buffer head + let offset = 0 + while (offset < result.length && result[offset] === 0) offset++ + result = result.slice(offset) + } + + return result +} + +/** + * Generate an irreducible generator polynomial of specified degree + * (used by Reed-Solomon encoder) + * + * @param {Number} degree Degree of the generator polynomial + * @return {Uint8Array} Buffer containing polynomial coefficients + */ +exports.generateECPolynomial = function generateECPolynomial (degree) { + let poly = new Uint8Array([1]) + for (let i = 0; i < degree; i++) { + poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)])) + } + + return poly +} diff --git a/backend/node_modules/qrcode/lib/core/qrcode.js b/backend/node_modules/qrcode/lib/core/qrcode.js new file mode 100644 index 00000000..f76df54b --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/qrcode.js @@ -0,0 +1,495 @@ +const Utils = require('./utils') +const ECLevel = require('./error-correction-level') +const BitBuffer = require('./bit-buffer') +const BitMatrix = require('./bit-matrix') +const AlignmentPattern = require('./alignment-pattern') +const FinderPattern = require('./finder-pattern') +const MaskPattern = require('./mask-pattern') +const ECCode = require('./error-correction-code') +const ReedSolomonEncoder = require('./reed-solomon-encoder') +const Version = require('./version') +const FormatInfo = require('./format-info') +const Mode = require('./mode') +const Segments = require('./segments') + +/** + * QRCode for JavaScript + * + * modified by Ryan Day for nodejs support + * Copyright (c) 2011 Ryan Day + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * +//--------------------------------------------------------------------- +// QRCode for JavaScript +// +// Copyright (c) 2009 Kazuhiko Arase +// +// URL: http://www.d-project.com/ +// +// Licensed under the MIT license: +// http://www.opensource.org/licenses/mit-license.php +// +// The word "QR Code" is registered trademark of +// DENSO WAVE INCORPORATED +// http://www.denso-wave.com/qrcode/faqpatent-e.html +// +//--------------------------------------------------------------------- +*/ + +/** + * Add finder patterns bits to matrix + * + * @param {BitMatrix} matrix Modules matrix + * @param {Number} version QR Code version + */ +function setupFinderPattern (matrix, version) { + const size = matrix.size + const pos = FinderPattern.getPositions(version) + + for (let i = 0; i < pos.length; i++) { + const row = pos[i][0] + const col = pos[i][1] + + for (let r = -1; r <= 7; r++) { + if (row + r <= -1 || size <= row + r) continue + + for (let c = -1; c <= 7; c++) { + if (col + c <= -1 || size <= col + c) continue + + if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) || + (c >= 0 && c <= 6 && (r === 0 || r === 6)) || + (r >= 2 && r <= 4 && c >= 2 && c <= 4)) { + matrix.set(row + r, col + c, true, true) + } else { + matrix.set(row + r, col + c, false, true) + } + } + } + } +} + +/** + * Add timing pattern bits to matrix + * + * Note: this function must be called before {@link setupAlignmentPattern} + * + * @param {BitMatrix} matrix Modules matrix + */ +function setupTimingPattern (matrix) { + const size = matrix.size + + for (let r = 8; r < size - 8; r++) { + const value = r % 2 === 0 + matrix.set(r, 6, value, true) + matrix.set(6, r, value, true) + } +} + +/** + * Add alignment patterns bits to matrix + * + * Note: this function must be called after {@link setupTimingPattern} + * + * @param {BitMatrix} matrix Modules matrix + * @param {Number} version QR Code version + */ +function setupAlignmentPattern (matrix, version) { + const pos = AlignmentPattern.getPositions(version) + + for (let i = 0; i < pos.length; i++) { + const row = pos[i][0] + const col = pos[i][1] + + for (let r = -2; r <= 2; r++) { + for (let c = -2; c <= 2; c++) { + if (r === -2 || r === 2 || c === -2 || c === 2 || + (r === 0 && c === 0)) { + matrix.set(row + r, col + c, true, true) + } else { + matrix.set(row + r, col + c, false, true) + } + } + } + } +} + +/** + * Add version info bits to matrix + * + * @param {BitMatrix} matrix Modules matrix + * @param {Number} version QR Code version + */ +function setupVersionInfo (matrix, version) { + const size = matrix.size + const bits = Version.getEncodedBits(version) + let row, col, mod + + for (let i = 0; i < 18; i++) { + row = Math.floor(i / 3) + col = i % 3 + size - 8 - 3 + mod = ((bits >> i) & 1) === 1 + + matrix.set(row, col, mod, true) + matrix.set(col, row, mod, true) + } +} + +/** + * Add format info bits to matrix + * + * @param {BitMatrix} matrix Modules matrix + * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level + * @param {Number} maskPattern Mask pattern reference value + */ +function setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) { + const size = matrix.size + const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern) + let i, mod + + for (i = 0; i < 15; i++) { + mod = ((bits >> i) & 1) === 1 + + // vertical + if (i < 6) { + matrix.set(i, 8, mod, true) + } else if (i < 8) { + matrix.set(i + 1, 8, mod, true) + } else { + matrix.set(size - 15 + i, 8, mod, true) + } + + // horizontal + if (i < 8) { + matrix.set(8, size - i - 1, mod, true) + } else if (i < 9) { + matrix.set(8, 15 - i - 1 + 1, mod, true) + } else { + matrix.set(8, 15 - i - 1, mod, true) + } + } + + // fixed module + matrix.set(size - 8, 8, 1, true) +} + +/** + * Add encoded data bits to matrix + * + * @param {BitMatrix} matrix Modules matrix + * @param {Uint8Array} data Data codewords + */ +function setupData (matrix, data) { + const size = matrix.size + let inc = -1 + let row = size - 1 + let bitIndex = 7 + let byteIndex = 0 + + for (let col = size - 1; col > 0; col -= 2) { + if (col === 6) col-- + + while (true) { + for (let c = 0; c < 2; c++) { + if (!matrix.isReserved(row, col - c)) { + let dark = false + + if (byteIndex < data.length) { + dark = (((data[byteIndex] >>> bitIndex) & 1) === 1) + } + + matrix.set(row, col - c, dark) + bitIndex-- + + if (bitIndex === -1) { + byteIndex++ + bitIndex = 7 + } + } + } + + row += inc + + if (row < 0 || size <= row) { + row -= inc + inc = -inc + break + } + } + } +} + +/** + * Create encoded codewords from data input + * + * @param {Number} version QR Code version + * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level + * @param {ByteData} data Data input + * @return {Uint8Array} Buffer containing encoded codewords + */ +function createData (version, errorCorrectionLevel, segments) { + // Prepare data buffer + const buffer = new BitBuffer() + + segments.forEach(function (data) { + // prefix data with mode indicator (4 bits) + buffer.put(data.mode.bit, 4) + + // Prefix data with character count indicator. + // The character count indicator is a string of bits that represents the + // number of characters that are being encoded. + // The character count indicator must be placed after the mode indicator + // and must be a certain number of bits long, depending on the QR version + // and data mode + // @see {@link Mode.getCharCountIndicator}. + buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version)) + + // add binary data sequence to buffer + data.write(buffer) + }) + + // Calculate required number of bits + const totalCodewords = Utils.getSymbolTotalCodewords(version) + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) + const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8 + + // Add a terminator. + // If the bit string is shorter than the total number of required bits, + // a terminator of up to four 0s must be added to the right side of the string. + // If the bit string is more than four bits shorter than the required number of bits, + // add four 0s to the end. + if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) { + buffer.put(0, 4) + } + + // If the bit string is fewer than four bits shorter, add only the number of 0s that + // are needed to reach the required number of bits. + + // After adding the terminator, if the number of bits in the string is not a multiple of 8, + // pad the string on the right with 0s to make the string's length a multiple of 8. + while (buffer.getLengthInBits() % 8 !== 0) { + buffer.putBit(0) + } + + // Add pad bytes if the string is still shorter than the total number of required bits. + // Extend the buffer to fill the data capacity of the symbol corresponding to + // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC) + // and 00010001 (0x11) alternately. + const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8 + for (let i = 0; i < remainingByte; i++) { + buffer.put(i % 2 ? 0x11 : 0xEC, 8) + } + + return createCodewords(buffer, version, errorCorrectionLevel) +} + +/** + * Encode input data with Reed-Solomon and return codewords with + * relative error correction bits + * + * @param {BitBuffer} bitBuffer Data to encode + * @param {Number} version QR Code version + * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level + * @return {Uint8Array} Buffer containing encoded codewords + */ +function createCodewords (bitBuffer, version, errorCorrectionLevel) { + // Total codewords for this QR code version (Data + Error correction) + const totalCodewords = Utils.getSymbolTotalCodewords(version) + + // Total number of error correction codewords + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) + + // Total number of data codewords + const dataTotalCodewords = totalCodewords - ecTotalCodewords + + // Total number of blocks + const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel) + + // Calculate how many blocks each group should contain + const blocksInGroup2 = totalCodewords % ecTotalBlocks + const blocksInGroup1 = ecTotalBlocks - blocksInGroup2 + + const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks) + + const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks) + const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1 + + // Number of EC codewords is the same for both groups + const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1 + + // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount + const rs = new ReedSolomonEncoder(ecCount) + + let offset = 0 + const dcData = new Array(ecTotalBlocks) + const ecData = new Array(ecTotalBlocks) + let maxDataSize = 0 + const buffer = new Uint8Array(bitBuffer.buffer) + + // Divide the buffer into the required number of blocks + for (let b = 0; b < ecTotalBlocks; b++) { + const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2 + + // extract a block of data from buffer + dcData[b] = buffer.slice(offset, offset + dataSize) + + // Calculate EC codewords for this data block + ecData[b] = rs.encode(dcData[b]) + + offset += dataSize + maxDataSize = Math.max(maxDataSize, dataSize) + } + + // Create final data + // Interleave the data and error correction codewords from each block + const data = new Uint8Array(totalCodewords) + let index = 0 + let i, r + + // Add data codewords + for (i = 0; i < maxDataSize; i++) { + for (r = 0; r < ecTotalBlocks; r++) { + if (i < dcData[r].length) { + data[index++] = dcData[r][i] + } + } + } + + // Apped EC codewords + for (i = 0; i < ecCount; i++) { + for (r = 0; r < ecTotalBlocks; r++) { + data[index++] = ecData[r][i] + } + } + + return data +} + +/** + * Build QR Code symbol + * + * @param {String} data Input string + * @param {Number} version QR Code version + * @param {ErrorCorretionLevel} errorCorrectionLevel Error level + * @param {MaskPattern} maskPattern Mask pattern + * @return {Object} Object containing symbol data + */ +function createSymbol (data, version, errorCorrectionLevel, maskPattern) { + let segments + + if (Array.isArray(data)) { + segments = Segments.fromArray(data) + } else if (typeof data === 'string') { + let estimatedVersion = version + + if (!estimatedVersion) { + const rawSegments = Segments.rawSplit(data) + + // Estimate best version that can contain raw splitted segments + estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel) + } + + // Build optimized segments + // If estimated version is undefined, try with the highest version + segments = Segments.fromString(data, estimatedVersion || 40) + } else { + throw new Error('Invalid data') + } + + // Get the min version that can contain data + const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel) + + // If no version is found, data cannot be stored + if (!bestVersion) { + throw new Error('The amount of data is too big to be stored in a QR Code') + } + + // If not specified, use min version as default + if (!version) { + version = bestVersion + + // Check if the specified version can contain the data + } else if (version < bestVersion) { + throw new Error('\n' + + 'The chosen QR Code version cannot contain this amount of data.\n' + + 'Minimum version required to store current data is: ' + bestVersion + '.\n' + ) + } + + const dataBits = createData(version, errorCorrectionLevel, segments) + + // Allocate matrix buffer + const moduleCount = Utils.getSymbolSize(version) + const modules = new BitMatrix(moduleCount) + + // Add function modules + setupFinderPattern(modules, version) + setupTimingPattern(modules) + setupAlignmentPattern(modules, version) + + // Add temporary dummy bits for format info just to set them as reserved. + // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask} + // since the masking operation must be performed only on the encoding region. + // These blocks will be replaced with correct values later in code. + setupFormatInfo(modules, errorCorrectionLevel, 0) + + if (version >= 7) { + setupVersionInfo(modules, version) + } + + // Add data codewords + setupData(modules, dataBits) + + if (isNaN(maskPattern)) { + // Find best mask pattern + maskPattern = MaskPattern.getBestMask(modules, + setupFormatInfo.bind(null, modules, errorCorrectionLevel)) + } + + // Apply mask pattern + MaskPattern.applyMask(maskPattern, modules) + + // Replace format info bits with correct values + setupFormatInfo(modules, errorCorrectionLevel, maskPattern) + + return { + modules: modules, + version: version, + errorCorrectionLevel: errorCorrectionLevel, + maskPattern: maskPattern, + segments: segments + } +} + +/** + * QR Code + * + * @param {String | Array} data Input data + * @param {Object} options Optional configurations + * @param {Number} options.version QR Code version + * @param {String} options.errorCorrectionLevel Error correction level + * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis + */ +exports.create = function create (data, options) { + if (typeof data === 'undefined' || data === '') { + throw new Error('No input text') + } + + let errorCorrectionLevel = ECLevel.M + let version + let mask + + if (typeof options !== 'undefined') { + // Use higher error correction level as default + errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M) + version = Version.from(options.version) + mask = MaskPattern.from(options.maskPattern) + + if (options.toSJISFunc) { + Utils.setToSJISFunction(options.toSJISFunc) + } + } + + return createSymbol(data, version, errorCorrectionLevel, mask) +} diff --git a/backend/node_modules/qrcode/lib/core/reed-solomon-encoder.js b/backend/node_modules/qrcode/lib/core/reed-solomon-encoder.js new file mode 100644 index 00000000..c1984227 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/reed-solomon-encoder.js @@ -0,0 +1,56 @@ +const Polynomial = require('./polynomial') + +function ReedSolomonEncoder (degree) { + this.genPoly = undefined + this.degree = degree + + if (this.degree) this.initialize(this.degree) +} + +/** + * Initialize the encoder. + * The input param should correspond to the number of error correction codewords. + * + * @param {Number} degree + */ +ReedSolomonEncoder.prototype.initialize = function initialize (degree) { + // create an irreducible generator polynomial + this.degree = degree + this.genPoly = Polynomial.generateECPolynomial(this.degree) +} + +/** + * Encodes a chunk of data + * + * @param {Uint8Array} data Buffer containing input data + * @return {Uint8Array} Buffer containing encoded data + */ +ReedSolomonEncoder.prototype.encode = function encode (data) { + if (!this.genPoly) { + throw new Error('Encoder not initialized') + } + + // Calculate EC for this data block + // extends data size to data+genPoly size + const paddedData = new Uint8Array(data.length + this.degree) + paddedData.set(data) + + // The error correction codewords are the remainder after dividing the data codewords + // by a generator polynomial + const remainder = Polynomial.mod(paddedData, this.genPoly) + + // return EC data blocks (last n byte, where n is the degree of genPoly) + // If coefficients number in remainder are less than genPoly degree, + // pad with 0s to the left to reach the needed number of coefficients + const start = this.degree - remainder.length + if (start > 0) { + const buff = new Uint8Array(this.degree) + buff.set(remainder, start) + + return buff + } + + return remainder +} + +module.exports = ReedSolomonEncoder diff --git a/backend/node_modules/qrcode/lib/core/regex.js b/backend/node_modules/qrcode/lib/core/regex.js new file mode 100644 index 00000000..9dd13a42 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/regex.js @@ -0,0 +1,31 @@ +const numeric = '[0-9]+' +const alphanumeric = '[A-Z $%*+\\-./:]+' +let kanji = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|' + + '[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|' + + '[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|' + + '[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+' +kanji = kanji.replace(/u/g, '\\u') + +const byte = '(?:(?![A-Z0-9 $%*+\\-./:]|' + kanji + ')(?:.|[\r\n]))+' + +exports.KANJI = new RegExp(kanji, 'g') +exports.BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+\\-./:]+', 'g') +exports.BYTE = new RegExp(byte, 'g') +exports.NUMERIC = new RegExp(numeric, 'g') +exports.ALPHANUMERIC = new RegExp(alphanumeric, 'g') + +const TEST_KANJI = new RegExp('^' + kanji + '$') +const TEST_NUMERIC = new RegExp('^' + numeric + '$') +const TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+\\-./:]+$') + +exports.testKanji = function testKanji (str) { + return TEST_KANJI.test(str) +} + +exports.testNumeric = function testNumeric (str) { + return TEST_NUMERIC.test(str) +} + +exports.testAlphanumeric = function testAlphanumeric (str) { + return TEST_ALPHANUMERIC.test(str) +} diff --git a/backend/node_modules/qrcode/lib/core/segments.js b/backend/node_modules/qrcode/lib/core/segments.js new file mode 100644 index 00000000..ba8be178 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/segments.js @@ -0,0 +1,330 @@ +const Mode = require('./mode') +const NumericData = require('./numeric-data') +const AlphanumericData = require('./alphanumeric-data') +const ByteData = require('./byte-data') +const KanjiData = require('./kanji-data') +const Regex = require('./regex') +const Utils = require('./utils') +const dijkstra = require('dijkstrajs') + +/** + * Returns UTF8 byte length + * + * @param {String} str Input string + * @return {Number} Number of byte + */ +function getStringByteLength (str) { + return unescape(encodeURIComponent(str)).length +} + +/** + * Get a list of segments of the specified mode + * from a string + * + * @param {Mode} mode Segment mode + * @param {String} str String to process + * @return {Array} Array of object with segments data + */ +function getSegments (regex, mode, str) { + const segments = [] + let result + + while ((result = regex.exec(str)) !== null) { + segments.push({ + data: result[0], + index: result.index, + mode: mode, + length: result[0].length + }) + } + + return segments +} + +/** + * Extracts a series of segments with the appropriate + * modes from a string + * + * @param {String} dataStr Input string + * @return {Array} Array of object with segments data + */ +function getSegmentsFromString (dataStr) { + const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr) + const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr) + let byteSegs + let kanjiSegs + + if (Utils.isKanjiModeEnabled()) { + byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr) + kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr) + } else { + byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr) + kanjiSegs = [] + } + + const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs) + + return segs + .sort(function (s1, s2) { + return s1.index - s2.index + }) + .map(function (obj) { + return { + data: obj.data, + mode: obj.mode, + length: obj.length + } + }) +} + +/** + * Returns how many bits are needed to encode a string of + * specified length with the specified mode + * + * @param {Number} length String length + * @param {Mode} mode Segment mode + * @return {Number} Bit length + */ +function getSegmentBitsLength (length, mode) { + switch (mode) { + case Mode.NUMERIC: + return NumericData.getBitsLength(length) + case Mode.ALPHANUMERIC: + return AlphanumericData.getBitsLength(length) + case Mode.KANJI: + return KanjiData.getBitsLength(length) + case Mode.BYTE: + return ByteData.getBitsLength(length) + } +} + +/** + * Merges adjacent segments which have the same mode + * + * @param {Array} segs Array of object with segments data + * @return {Array} Array of object with segments data + */ +function mergeSegments (segs) { + return segs.reduce(function (acc, curr) { + const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null + if (prevSeg && prevSeg.mode === curr.mode) { + acc[acc.length - 1].data += curr.data + return acc + } + + acc.push(curr) + return acc + }, []) +} + +/** + * Generates a list of all possible nodes combination which + * will be used to build a segments graph. + * + * Nodes are divided by groups. Each group will contain a list of all the modes + * in which is possible to encode the given text. + * + * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte. + * The group for '12345' will contain then 3 objects, one for each + * possible encoding mode. + * + * Each node represents a possible segment. + * + * @param {Array} segs Array of object with segments data + * @return {Array} Array of object with segments data + */ +function buildNodes (segs) { + const nodes = [] + for (let i = 0; i < segs.length; i++) { + const seg = segs[i] + + switch (seg.mode) { + case Mode.NUMERIC: + nodes.push([seg, + { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length }, + { data: seg.data, mode: Mode.BYTE, length: seg.length } + ]) + break + case Mode.ALPHANUMERIC: + nodes.push([seg, + { data: seg.data, mode: Mode.BYTE, length: seg.length } + ]) + break + case Mode.KANJI: + nodes.push([seg, + { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) } + ]) + break + case Mode.BYTE: + nodes.push([ + { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) } + ]) + } + } + + return nodes +} + +/** + * Builds a graph from a list of nodes. + * All segments in each node group will be connected with all the segments of + * the next group and so on. + * + * At each connection will be assigned a weight depending on the + * segment's byte length. + * + * @param {Array} nodes Array of object with segments data + * @param {Number} version QR Code version + * @return {Object} Graph of all possible segments + */ +function buildGraph (nodes, version) { + const table = {} + const graph = { start: {} } + let prevNodeIds = ['start'] + + for (let i = 0; i < nodes.length; i++) { + const nodeGroup = nodes[i] + const currentNodeIds = [] + + for (let j = 0; j < nodeGroup.length; j++) { + const node = nodeGroup[j] + const key = '' + i + j + + currentNodeIds.push(key) + table[key] = { node: node, lastCount: 0 } + graph[key] = {} + + for (let n = 0; n < prevNodeIds.length; n++) { + const prevNodeId = prevNodeIds[n] + + if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) { + graph[prevNodeId][key] = + getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - + getSegmentBitsLength(table[prevNodeId].lastCount, node.mode) + + table[prevNodeId].lastCount += node.length + } else { + if (table[prevNodeId]) table[prevNodeId].lastCount = node.length + + graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + + 4 + Mode.getCharCountIndicator(node.mode, version) // switch cost + } + } + } + + prevNodeIds = currentNodeIds + } + + for (let n = 0; n < prevNodeIds.length; n++) { + graph[prevNodeIds[n]].end = 0 + } + + return { map: graph, table: table } +} + +/** + * Builds a segment from a specified data and mode. + * If a mode is not specified, the more suitable will be used. + * + * @param {String} data Input data + * @param {Mode | String} modesHint Data mode + * @return {Segment} Segment + */ +function buildSingleSegment (data, modesHint) { + let mode + const bestMode = Mode.getBestModeForData(data) + + mode = Mode.from(modesHint, bestMode) + + // Make sure data can be encoded + if (mode !== Mode.BYTE && mode.bit < bestMode.bit) { + throw new Error('"' + data + '"' + + ' cannot be encoded with mode ' + Mode.toString(mode) + + '.\n Suggested mode is: ' + Mode.toString(bestMode)) + } + + // Use Mode.BYTE if Kanji support is disabled + if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) { + mode = Mode.BYTE + } + + switch (mode) { + case Mode.NUMERIC: + return new NumericData(data) + + case Mode.ALPHANUMERIC: + return new AlphanumericData(data) + + case Mode.KANJI: + return new KanjiData(data) + + case Mode.BYTE: + return new ByteData(data) + } +} + +/** + * Builds a list of segments from an array. + * Array can contain Strings or Objects with segment's info. + * + * For each item which is a string, will be generated a segment with the given + * string and the more appropriate encoding mode. + * + * For each item which is an object, will be generated a segment with the given + * data and mode. + * Objects must contain at least the property "data". + * If property "mode" is not present, the more suitable mode will be used. + * + * @param {Array} array Array of objects with segments data + * @return {Array} Array of Segments + */ +exports.fromArray = function fromArray (array) { + return array.reduce(function (acc, seg) { + if (typeof seg === 'string') { + acc.push(buildSingleSegment(seg, null)) + } else if (seg.data) { + acc.push(buildSingleSegment(seg.data, seg.mode)) + } + + return acc + }, []) +} + +/** + * Builds an optimized sequence of segments from a string, + * which will produce the shortest possible bitstream. + * + * @param {String} data Input string + * @param {Number} version QR Code version + * @return {Array} Array of segments + */ +exports.fromString = function fromString (data, version) { + const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled()) + + const nodes = buildNodes(segs) + const graph = buildGraph(nodes, version) + const path = dijkstra.find_path(graph.map, 'start', 'end') + + const optimizedSegs = [] + for (let i = 1; i < path.length - 1; i++) { + optimizedSegs.push(graph.table[path[i]].node) + } + + return exports.fromArray(mergeSegments(optimizedSegs)) +} + +/** + * Splits a string in various segments with the modes which + * best represent their content. + * The produced segments are far from being optimized. + * The output of this function is only used to estimate a QR Code version + * which may contain the data. + * + * @param {string} data Input string + * @return {Array} Array of segments + */ +exports.rawSplit = function rawSplit (data) { + return exports.fromArray( + getSegmentsFromString(data, Utils.isKanjiModeEnabled()) + ) +} diff --git a/backend/node_modules/qrcode/lib/core/utils.js b/backend/node_modules/qrcode/lib/core/utils.js new file mode 100644 index 00000000..8a0b87ba --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/utils.js @@ -0,0 +1,63 @@ +let toSJISFunction +const CODEWORDS_COUNT = [ + 0, // Not used + 26, 44, 70, 100, 134, 172, 196, 242, 292, 346, + 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085, + 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185, + 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706 +] + +/** + * Returns the QR Code size for the specified version + * + * @param {Number} version QR Code version + * @return {Number} size of QR code + */ +exports.getSymbolSize = function getSymbolSize (version) { + if (!version) throw new Error('"version" cannot be null or undefined') + if (version < 1 || version > 40) throw new Error('"version" should be in range from 1 to 40') + return version * 4 + 17 +} + +/** + * Returns the total number of codewords used to store data and EC information. + * + * @param {Number} version QR Code version + * @return {Number} Data length in bits + */ +exports.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) { + return CODEWORDS_COUNT[version] +} + +/** + * Encode data with Bose-Chaudhuri-Hocquenghem + * + * @param {Number} data Value to encode + * @return {Number} Encoded value + */ +exports.getBCHDigit = function (data) { + let digit = 0 + + while (data !== 0) { + digit++ + data >>>= 1 + } + + return digit +} + +exports.setToSJISFunction = function setToSJISFunction (f) { + if (typeof f !== 'function') { + throw new Error('"toSJISFunc" is not a valid function.') + } + + toSJISFunction = f +} + +exports.isKanjiModeEnabled = function () { + return typeof toSJISFunction !== 'undefined' +} + +exports.toSJIS = function toSJIS (kanji) { + return toSJISFunction(kanji) +} diff --git a/backend/node_modules/qrcode/lib/core/version-check.js b/backend/node_modules/qrcode/lib/core/version-check.js new file mode 100644 index 00000000..dd32b5ac --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/version-check.js @@ -0,0 +1,9 @@ +/** + * Check if QR Code version is valid + * + * @param {Number} version QR Code version + * @return {Boolean} true if valid version, false otherwise + */ +exports.isValid = function isValid (version) { + return !isNaN(version) && version >= 1 && version <= 40 +} diff --git a/backend/node_modules/qrcode/lib/core/version.js b/backend/node_modules/qrcode/lib/core/version.js new file mode 100644 index 00000000..32b84661 --- /dev/null +++ b/backend/node_modules/qrcode/lib/core/version.js @@ -0,0 +1,163 @@ +const Utils = require('./utils') +const ECCode = require('./error-correction-code') +const ECLevel = require('./error-correction-level') +const Mode = require('./mode') +const VersionCheck = require('./version-check') + +// Generator polynomial used to encode version information +const G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0) +const G18_BCH = Utils.getBCHDigit(G18) + +function getBestVersionForDataLength (mode, length, errorCorrectionLevel) { + for (let currentVersion = 1; currentVersion <= 40; currentVersion++) { + if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) { + return currentVersion + } + } + + return undefined +} + +function getReservedBitsCount (mode, version) { + // Character count indicator + mode indicator bits + return Mode.getCharCountIndicator(mode, version) + 4 +} + +function getTotalBitsFromDataArray (segments, version) { + let totalBits = 0 + + segments.forEach(function (data) { + const reservedBits = getReservedBitsCount(data.mode, version) + totalBits += reservedBits + data.getBitsLength() + }) + + return totalBits +} + +function getBestVersionForMixedData (segments, errorCorrectionLevel) { + for (let currentVersion = 1; currentVersion <= 40; currentVersion++) { + const length = getTotalBitsFromDataArray(segments, currentVersion) + if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) { + return currentVersion + } + } + + return undefined +} + +/** + * Returns version number from a value. + * If value is not a valid version, returns defaultValue + * + * @param {Number|String} value QR Code version + * @param {Number} defaultValue Fallback value + * @return {Number} QR Code version number + */ +exports.from = function from (value, defaultValue) { + if (VersionCheck.isValid(value)) { + return parseInt(value, 10) + } + + return defaultValue +} + +/** + * Returns how much data can be stored with the specified QR code version + * and error correction level + * + * @param {Number} version QR Code version (1-40) + * @param {Number} errorCorrectionLevel Error correction level + * @param {Mode} mode Data mode + * @return {Number} Quantity of storable data + */ +exports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode) { + if (!VersionCheck.isValid(version)) { + throw new Error('Invalid QR Code version') + } + + // Use Byte mode as default + if (typeof mode === 'undefined') mode = Mode.BYTE + + // Total codewords for this QR code version (Data + Error correction) + const totalCodewords = Utils.getSymbolTotalCodewords(version) + + // Total number of error correction codewords + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) + + // Total number of data codewords + const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8 + + if (mode === Mode.MIXED) return dataTotalCodewordsBits + + const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version) + + // Return max number of storable codewords + switch (mode) { + case Mode.NUMERIC: + return Math.floor((usableBits / 10) * 3) + + case Mode.ALPHANUMERIC: + return Math.floor((usableBits / 11) * 2) + + case Mode.KANJI: + return Math.floor(usableBits / 13) + + case Mode.BYTE: + default: + return Math.floor(usableBits / 8) + } +} + +/** + * Returns the minimum version needed to contain the amount of data + * + * @param {Segment} data Segment of data + * @param {Number} [errorCorrectionLevel=H] Error correction level + * @param {Mode} mode Data mode + * @return {Number} QR Code version + */ +exports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel) { + let seg + + const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M) + + if (Array.isArray(data)) { + if (data.length > 1) { + return getBestVersionForMixedData(data, ecl) + } + + if (data.length === 0) { + return 1 + } + + seg = data[0] + } else { + seg = data + } + + return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl) +} + +/** + * Returns version information with relative error correction bits + * + * The version information is included in QR Code symbols of version 7 or larger. + * It consists of an 18-bit sequence containing 6 data bits, + * with 12 error correction bits calculated using the (18, 6) Golay code. + * + * @param {Number} version QR Code version + * @return {Number} Encoded version info bits + */ +exports.getEncodedBits = function getEncodedBits (version) { + if (!VersionCheck.isValid(version) || version < 7) { + throw new Error('Invalid QR Code version') + } + + let d = version << 12 + + while (Utils.getBCHDigit(d) - G18_BCH >= 0) { + d ^= (G18 << (Utils.getBCHDigit(d) - G18_BCH)) + } + + return (version << 12) | d +} diff --git a/backend/node_modules/qrcode/lib/index.js b/backend/node_modules/qrcode/lib/index.js new file mode 100644 index 00000000..57c8f703 --- /dev/null +++ b/backend/node_modules/qrcode/lib/index.js @@ -0,0 +1,12 @@ +/* +*copyright Ryan Day 2012 +* +* Licensed under the MIT license: +* http://www.opensource.org/licenses/mit-license.php +* +* this is the main server side application file for node-qrcode. +* these exports use serverside canvas api methods for file IO and buffers +* +*/ + +module.exports = require('./server') diff --git a/backend/node_modules/qrcode/lib/renderer/canvas.js b/backend/node_modules/qrcode/lib/renderer/canvas.js new file mode 100644 index 00000000..42050cf5 --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/canvas.js @@ -0,0 +1,63 @@ +const Utils = require('./utils') + +function clearCanvas (ctx, canvas, size) { + ctx.clearRect(0, 0, canvas.width, canvas.height) + + if (!canvas.style) canvas.style = {} + canvas.height = size + canvas.width = size + canvas.style.height = size + 'px' + canvas.style.width = size + 'px' +} + +function getCanvasElement () { + try { + return document.createElement('canvas') + } catch (e) { + throw new Error('You need to specify a canvas element') + } +} + +exports.render = function render (qrData, canvas, options) { + let opts = options + let canvasEl = canvas + + if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { + opts = canvas + canvas = undefined + } + + if (!canvas) { + canvasEl = getCanvasElement() + } + + opts = Utils.getOptions(opts) + const size = Utils.getImageWidth(qrData.modules.size, opts) + + const ctx = canvasEl.getContext('2d') + const image = ctx.createImageData(size, size) + Utils.qrToImageData(image.data, qrData, opts) + + clearCanvas(ctx, canvasEl, size) + ctx.putImageData(image, 0, 0) + + return canvasEl +} + +exports.renderToDataURL = function renderToDataURL (qrData, canvas, options) { + let opts = options + + if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { + opts = canvas + canvas = undefined + } + + if (!opts) opts = {} + + const canvasEl = exports.render(qrData, canvas, opts) + + const type = opts.type || 'image/png' + const rendererOpts = opts.rendererOpts || {} + + return canvasEl.toDataURL(type, rendererOpts.quality) +} diff --git a/backend/node_modules/qrcode/lib/renderer/png.js b/backend/node_modules/qrcode/lib/renderer/png.js new file mode 100644 index 00000000..27421608 --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/png.js @@ -0,0 +1,78 @@ +const fs = require('fs') +const PNG = require('pngjs').PNG +const Utils = require('./utils') + +exports.render = function render (qrData, options) { + const opts = Utils.getOptions(options) + const pngOpts = opts.rendererOpts + const size = Utils.getImageWidth(qrData.modules.size, opts) + + pngOpts.width = size + pngOpts.height = size + + const pngImage = new PNG(pngOpts) + Utils.qrToImageData(pngImage.data, qrData, opts) + + return pngImage +} + +exports.renderToDataURL = function renderToDataURL (qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + exports.renderToBuffer(qrData, options, function (err, output) { + if (err) cb(err) + let url = 'data:image/png;base64,' + url += output.toString('base64') + cb(null, url) + }) +} + +exports.renderToBuffer = function renderToBuffer (qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + const png = exports.render(qrData, options) + const buffer = [] + + png.on('error', cb) + + png.on('data', function (data) { + buffer.push(data) + }) + + png.on('end', function () { + cb(null, Buffer.concat(buffer)) + }) + + png.pack() +} + +exports.renderToFile = function renderToFile (path, qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + let called = false + const done = (...args) => { + if (called) return + called = true + cb.apply(null, args) + } + const stream = fs.createWriteStream(path) + + stream.on('error', done) + stream.on('close', done) + + exports.renderToFileStream(stream, qrData, options) +} + +exports.renderToFileStream = function renderToFileStream (stream, qrData, options) { + const png = exports.render(qrData, options) + png.pack().pipe(stream) +} diff --git a/backend/node_modules/qrcode/lib/renderer/svg-tag.js b/backend/node_modules/qrcode/lib/renderer/svg-tag.js new file mode 100644 index 00000000..d0839fe0 --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/svg-tag.js @@ -0,0 +1,81 @@ +const Utils = require('./utils') + +function getColorAttrib (color, attrib) { + const alpha = color.a / 255 + const str = attrib + '="' + color.hex + '"' + + return alpha < 1 + ? str + ' ' + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' + : str +} + +function svgCmd (cmd, x, y) { + let str = cmd + x + if (typeof y !== 'undefined') str += ' ' + y + + return str +} + +function qrToPath (data, size, margin) { + let path = '' + let moveBy = 0 + let newRow = false + let lineLength = 0 + + for (let i = 0; i < data.length; i++) { + const col = Math.floor(i % size) + const row = Math.floor(i / size) + + if (!col && !newRow) newRow = true + + if (data[i]) { + lineLength++ + + if (!(i > 0 && col > 0 && data[i - 1])) { + path += newRow + ? svgCmd('M', col + margin, 0.5 + row + margin) + : svgCmd('m', moveBy, 0) + + moveBy = 0 + newRow = false + } + + if (!(col + 1 < size && data[i + 1])) { + path += svgCmd('h', lineLength) + lineLength = 0 + } + } else { + moveBy++ + } + } + + return path +} + +exports.render = function render (qrData, options, cb) { + const opts = Utils.getOptions(options) + const size = qrData.modules.size + const data = qrData.modules.data + const qrcodesize = size + opts.margin * 2 + + const bg = !opts.color.light.a + ? '' + : '' + + const path = + '' + + const viewBox = 'viewBox="' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '"' + + const width = !opts.width ? '' : 'width="' + opts.width + '" height="' + opts.width + '" ' + + const svgTag = '' + bg + path + '\n' + + if (typeof cb === 'function') { + cb(null, svgTag) + } + + return svgTag +} diff --git a/backend/node_modules/qrcode/lib/renderer/svg.js b/backend/node_modules/qrcode/lib/renderer/svg.js new file mode 100644 index 00000000..ba99d14c --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/svg.js @@ -0,0 +1,19 @@ +const svgTagRenderer = require('./svg-tag') + +exports.render = svgTagRenderer.render + +exports.renderToFile = function renderToFile (path, qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + const fs = require('fs') + const svgTag = exports.render(qrData, options) + + const xmlStr = '' + + '' + + svgTag + + fs.writeFile(path, xmlStr, cb) +} diff --git a/backend/node_modules/qrcode/lib/renderer/terminal.js b/backend/node_modules/qrcode/lib/renderer/terminal.js new file mode 100644 index 00000000..36ddfde7 --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/terminal.js @@ -0,0 +1,9 @@ +const big = require('./terminal/terminal') +const small = require('./terminal/terminal-small') + +exports.render = function (qrData, options, cb) { + if (options && options.small) { + return small.render(qrData, options, cb) + } + return big.render(qrData, options, cb) +} diff --git a/backend/node_modules/qrcode/lib/renderer/terminal/terminal-small.js b/backend/node_modules/qrcode/lib/renderer/terminal/terminal-small.js new file mode 100644 index 00000000..9810d4e1 --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/terminal/terminal-small.js @@ -0,0 +1,85 @@ +const backgroundWhite = '\x1b[47m' +const backgroundBlack = '\x1b[40m' +const foregroundWhite = '\x1b[37m' +const foregroundBlack = '\x1b[30m' +const reset = '\x1b[0m' +const lineSetupNormal = backgroundWhite + foregroundBlack // setup colors +const lineSetupInverse = backgroundBlack + foregroundWhite // setup colors + +const createPalette = function (lineSetup, foregroundWhite, foregroundBlack) { + return { + // 1 ... white, 2 ... black, 0 ... transparent (default) + + '00': reset + ' ' + lineSetup, + '01': reset + foregroundWhite + '▄' + lineSetup, + '02': reset + foregroundBlack + '▄' + lineSetup, + 10: reset + foregroundWhite + '▀' + lineSetup, + 11: ' ', + 12: '▄', + 20: reset + foregroundBlack + '▀' + lineSetup, + 21: '▀', + 22: '█' + } +} + +/** + * Returns code for QR pixel + * @param {boolean[][]} modules + * @param {number} size + * @param {number} x + * @param {number} y + * @return {'0' | '1' | '2'} + */ +const mkCodePixel = function (modules, size, x, y) { + const sizePlus = size + 1 + if ((x >= sizePlus) || (y >= sizePlus) || (y < -1) || (x < -1)) return '0' + if ((x >= size) || (y >= size) || (y < 0) || (x < 0)) return '1' + const idx = (y * size) + x + return modules[idx] ? '2' : '1' +} + +/** + * Returns code for four QR pixels. Suitable as key in palette. + * @param {boolean[][]} modules + * @param {number} size + * @param {number} x + * @param {number} y + * @return {keyof palette} + */ +const mkCode = function (modules, size, x, y) { + return ( + mkCodePixel(modules, size, x, y) + + mkCodePixel(modules, size, x, y + 1) + ) +} + +exports.render = function (qrData, options, cb) { + const size = qrData.modules.size + const data = qrData.modules.data + + const inverse = !!(options && options.inverse) + const lineSetup = options && options.inverse ? lineSetupInverse : lineSetupNormal + const white = inverse ? foregroundBlack : foregroundWhite + const black = inverse ? foregroundWhite : foregroundBlack + + const palette = createPalette(lineSetup, white, black) + const newLine = reset + '\n' + lineSetup + + let output = lineSetup // setup colors + + for (let y = -1; y < size + 1; y += 2) { + for (let x = -1; x < size; x++) { + output += palette[mkCode(data, size, x, y)] + } + + output += palette[mkCode(data, size, size, y)] + newLine + } + + output += reset + + if (typeof cb === 'function') { + cb(null, output) + } + + return output +} diff --git a/backend/node_modules/qrcode/lib/renderer/terminal/terminal.js b/backend/node_modules/qrcode/lib/renderer/terminal/terminal.js new file mode 100644 index 00000000..f15610b5 --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/terminal/terminal.js @@ -0,0 +1,49 @@ +// let Utils = require('./utils') + +exports.render = function (qrData, options, cb) { + const size = qrData.modules.size + const data = qrData.modules.data + + // let opts = Utils.getOptions(options) + + // use same scheme as https://github.com/gtanner/qrcode-terminal because it actually works! =) + const black = '\x1b[40m \x1b[0m' + const white = '\x1b[47m \x1b[0m' + + let output = '' + const hMargin = Array(size + 3).join(white) + const vMargin = Array(2).join(white) + + output += hMargin + '\n' + for (let i = 0; i < size; ++i) { + output += white + for (let j = 0; j < size; j++) { + // let topModule = data[i * size + j] + // let bottomModule = data[(i + 1) * size + j] + + output += data[i * size + j] ? black : white// getBlockChar(topModule, bottomModule) + } + // output += white+'\n' + output += vMargin + '\n' + } + + output += hMargin + '\n' + + if (typeof cb === 'function') { + cb(null, output) + } + + return output +} +/* +exports.renderToFile = function renderToFile (path, qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + let fs = require('fs') + let utf8 = exports.render(qrData, options) + fs.writeFile(path, utf8, cb) +} +*/ diff --git a/backend/node_modules/qrcode/lib/renderer/utf8.js b/backend/node_modules/qrcode/lib/renderer/utf8.js new file mode 100644 index 00000000..d76116e5 --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/utf8.js @@ -0,0 +1,71 @@ +const Utils = require('./utils') + +const BLOCK_CHAR = { + WW: ' ', + WB: '▄', + BB: '█', + BW: '▀' +} + +const INVERTED_BLOCK_CHAR = { + BB: ' ', + BW: '▄', + WW: '█', + WB: '▀' +} + +function getBlockChar (top, bottom, blocks) { + if (top && bottom) return blocks.BB + if (top && !bottom) return blocks.BW + if (!top && bottom) return blocks.WB + return blocks.WW +} + +exports.render = function (qrData, options, cb) { + const opts = Utils.getOptions(options) + let blocks = BLOCK_CHAR + if (opts.color.dark.hex === '#ffffff' || opts.color.light.hex === '#000000') { + blocks = INVERTED_BLOCK_CHAR + } + + const size = qrData.modules.size + const data = qrData.modules.data + + let output = '' + let hMargin = Array(size + (opts.margin * 2) + 1).join(blocks.WW) + hMargin = Array((opts.margin / 2) + 1).join(hMargin + '\n') + + const vMargin = Array(opts.margin + 1).join(blocks.WW) + + output += hMargin + for (let i = 0; i < size; i += 2) { + output += vMargin + for (let j = 0; j < size; j++) { + const topModule = data[i * size + j] + const bottomModule = data[(i + 1) * size + j] + + output += getBlockChar(topModule, bottomModule, blocks) + } + + output += vMargin + '\n' + } + + output += hMargin.slice(0, -1) + + if (typeof cb === 'function') { + cb(null, output) + } + + return output +} + +exports.renderToFile = function renderToFile (path, qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + const fs = require('fs') + const utf8 = exports.render(qrData, options) + fs.writeFile(path, utf8, cb) +} diff --git a/backend/node_modules/qrcode/lib/renderer/utils.js b/backend/node_modules/qrcode/lib/renderer/utils.js new file mode 100644 index 00000000..87239dc5 --- /dev/null +++ b/backend/node_modules/qrcode/lib/renderer/utils.js @@ -0,0 +1,99 @@ +function hex2rgba (hex) { + if (typeof hex === 'number') { + hex = hex.toString() + } + + if (typeof hex !== 'string') { + throw new Error('Color should be defined as hex string') + } + + let hexCode = hex.slice().replace('#', '').split('') + if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) { + throw new Error('Invalid hex color: ' + hex) + } + + // Convert from short to long form (fff -> ffffff) + if (hexCode.length === 3 || hexCode.length === 4) { + hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) { + return [c, c] + })) + } + + // Add default alpha value + if (hexCode.length === 6) hexCode.push('F', 'F') + + const hexValue = parseInt(hexCode.join(''), 16) + + return { + r: (hexValue >> 24) & 255, + g: (hexValue >> 16) & 255, + b: (hexValue >> 8) & 255, + a: hexValue & 255, + hex: '#' + hexCode.slice(0, 6).join('') + } +} + +exports.getOptions = function getOptions (options) { + if (!options) options = {} + if (!options.color) options.color = {} + + const margin = typeof options.margin === 'undefined' || + options.margin === null || + options.margin < 0 + ? 4 + : options.margin + + const width = options.width && options.width >= 21 ? options.width : undefined + const scale = options.scale || 4 + + return { + width: width, + scale: width ? 4 : scale, + margin: margin, + color: { + dark: hex2rgba(options.color.dark || '#000000ff'), + light: hex2rgba(options.color.light || '#ffffffff') + }, + type: options.type, + rendererOpts: options.rendererOpts || {} + } +} + +exports.getScale = function getScale (qrSize, opts) { + return opts.width && opts.width >= qrSize + opts.margin * 2 + ? opts.width / (qrSize + opts.margin * 2) + : opts.scale +} + +exports.getImageWidth = function getImageWidth (qrSize, opts) { + const scale = exports.getScale(qrSize, opts) + return Math.floor((qrSize + opts.margin * 2) * scale) +} + +exports.qrToImageData = function qrToImageData (imgData, qr, opts) { + const size = qr.modules.size + const data = qr.modules.data + const scale = exports.getScale(size, opts) + const symbolSize = Math.floor((size + opts.margin * 2) * scale) + const scaledMargin = opts.margin * scale + const palette = [opts.color.light, opts.color.dark] + + for (let i = 0; i < symbolSize; i++) { + for (let j = 0; j < symbolSize; j++) { + let posDst = (i * symbolSize + j) * 4 + let pxColor = opts.color.light + + if (i >= scaledMargin && j >= scaledMargin && + i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) { + const iSrc = Math.floor((i - scaledMargin) / scale) + const jSrc = Math.floor((j - scaledMargin) / scale) + pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0] + } + + imgData[posDst++] = pxColor.r + imgData[posDst++] = pxColor.g + imgData[posDst++] = pxColor.b + imgData[posDst] = pxColor.a + } + } +} diff --git a/backend/node_modules/qrcode/lib/server.js b/backend/node_modules/qrcode/lib/server.js new file mode 100644 index 00000000..619e398e --- /dev/null +++ b/backend/node_modules/qrcode/lib/server.js @@ -0,0 +1,138 @@ +const canPromise = require('./can-promise') +const QRCode = require('./core/qrcode') +const PngRenderer = require('./renderer/png') +const Utf8Renderer = require('./renderer/utf8') +const TerminalRenderer = require('./renderer/terminal') +const SvgRenderer = require('./renderer/svg') + +function checkParams (text, opts, cb) { + if (typeof text === 'undefined') { + throw new Error('String required as first argument') + } + + if (typeof cb === 'undefined') { + cb = opts + opts = {} + } + + if (typeof cb !== 'function') { + if (!canPromise()) { + throw new Error('Callback required as last argument') + } else { + opts = cb || {} + cb = null + } + } + + return { + opts: opts, + cb: cb + } +} + +function getTypeFromFilename (path) { + return path.slice((path.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase() +} + +function getRendererFromType (type) { + switch (type) { + case 'svg': + return SvgRenderer + + case 'txt': + case 'utf8': + return Utf8Renderer + + case 'png': + case 'image/png': + default: + return PngRenderer + } +} + +function getStringRendererFromType (type) { + switch (type) { + case 'svg': + return SvgRenderer + + case 'terminal': + return TerminalRenderer + + case 'utf8': + default: + return Utf8Renderer + } +} + +function render (renderFunc, text, params) { + if (!params.cb) { + return new Promise(function (resolve, reject) { + try { + const data = QRCode.create(text, params.opts) + return renderFunc(data, params.opts, function (err, data) { + return err ? reject(err) : resolve(data) + }) + } catch (e) { + reject(e) + } + }) + } + + try { + const data = QRCode.create(text, params.opts) + return renderFunc(data, params.opts, params.cb) + } catch (e) { + params.cb(e) + } +} + +exports.create = QRCode.create + +exports.toCanvas = require('./browser').toCanvas + +exports.toString = function toString (text, opts, cb) { + const params = checkParams(text, opts, cb) + const type = params.opts ? params.opts.type : undefined + const renderer = getStringRendererFromType(type) + return render(renderer.render, text, params) +} + +exports.toDataURL = function toDataURL (text, opts, cb) { + const params = checkParams(text, opts, cb) + const renderer = getRendererFromType(params.opts.type) + return render(renderer.renderToDataURL, text, params) +} + +exports.toBuffer = function toBuffer (text, opts, cb) { + const params = checkParams(text, opts, cb) + const renderer = getRendererFromType(params.opts.type) + return render(renderer.renderToBuffer, text, params) +} + +exports.toFile = function toFile (path, text, opts, cb) { + if (typeof path !== 'string' || !(typeof text === 'string' || typeof text === 'object')) { + throw new Error('Invalid argument') + } + + if ((arguments.length < 3) && !canPromise()) { + throw new Error('Too few arguments provided') + } + + const params = checkParams(text, opts, cb) + const type = params.opts.type || getTypeFromFilename(path) + const renderer = getRendererFromType(type) + const renderToFile = renderer.renderToFile.bind(null, path) + + return render(renderToFile, text, params) +} + +exports.toFileStream = function toFileStream (stream, text, opts) { + if (arguments.length < 2) { + throw new Error('Too few arguments provided') + } + + const params = checkParams(text, opts, stream.emit.bind(stream, 'error')) + const renderer = getRendererFromType('png') // Only png support for now + const renderToFileStream = renderer.renderToFileStream.bind(null, stream) + render(renderToFileStream, text, params) +} diff --git a/backend/node_modules/qrcode/license b/backend/node_modules/qrcode/license new file mode 100644 index 00000000..4e2b3b93 --- /dev/null +++ b/backend/node_modules/qrcode/license @@ -0,0 +1,10 @@ +The MIT License (MIT) + +Copyright (c) 2012 Ryan Day + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/backend/node_modules/qrcode/package.json b/backend/node_modules/qrcode/package.json new file mode 100644 index 00000000..6c9ab00d --- /dev/null +++ b/backend/node_modules/qrcode/package.json @@ -0,0 +1,77 @@ +{ + "name": "qrcode", + "description": "QRCode / 2d Barcode api with both server side and client side support using canvas", + "version": "1.5.4", + "author": "Ryan Day ", + "contributors": [ + "Vincenzo Greco ", + "Linus Unnebäck " + ], + "keywords": [ + "qr", + "code", + "canvas", + "qrcode" + ], + "main": "./lib/index.js", + "browser": { + "./lib/index.js": "./lib/browser.js", + "fs": false + }, + "files": [ + "bin", + "build", + "lib", + "helper" + ], + "homepage": "http://github.com/soldair/node-qrcode", + "license": "MIT", + "scripts": { + "lint": "standard", + "pretest": "npm run lint", + "test": "node --throw-deprecation test.js", + "build": "rollup -c", + "prepublish": "npm run build", + "browser": "node examples/clientsideserver.js" + }, + "bin": { + "qrcode": "./bin/qrcode" + }, + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.5", + "@rollup/plugin-commonjs": "^11.1.0", + "@rollup/plugin-node-resolve": "^7.1.3", + "browserify": "^16.5.1", + "canvas": "^2.8.0", + "canvasutil": "0.0.4", + "colors": "^1.4.0", + "express": "^4.17.1", + "htmlparser2": "^4.1.0", + "rollup": "^2.6.1", + "rollup-plugin-babel": "^4.4.0", + "rollup-plugin-terser": "^5.3.0", + "sinon": "^9.0.2", + "standard": "^16.0.4", + "tap": "^16.2.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/soldair/node-qrcode.git" + }, + "engines": { + "node": ">=10.13.0" + }, + "standard": { + "ignore": [ + "build/", + "examples/vendors/", + "lib/core/regex.js" + ] + } +} diff --git a/backend/node_modules/qs/.editorconfig b/backend/node_modules/qs/.editorconfig index 0ea91d99..6adecfbf 100644 --- a/backend/node_modules/qs/.editorconfig +++ b/backend/node_modules/qs/.editorconfig @@ -38,3 +38,9 @@ indent_size = off indent_style = off indent = off max_line_length = off + +[.nycrc] +indent_style = tab + +[tea.yaml] +indent_size = 2 diff --git a/backend/node_modules/qs/.eslintrc b/backend/node_modules/qs/.eslintrc index 6884760e..a89f60e6 100644 --- a/backend/node_modules/qs/.eslintrc +++ b/backend/node_modules/qs/.eslintrc @@ -13,9 +13,10 @@ "func-name-matching": 0, "id-length": [2, { "min": 1, "max": 25, "properties": "never" }], "indent": [2, 4], + "max-lines": 0, "max-lines-per-function": [2, { "max": 150 }], - "max-params": [2, 15], - "max-statements": [2, 52], + "max-params": [2, 18], + "max-statements": [2, 100], "multiline-comment-style": 0, "no-continue": 1, "no-magic-numbers": 0, @@ -32,7 +33,7 @@ "no-buffer-constructor": 0, "no-extend-native": 0, "no-throw-literal": 0, - } - } - ] + }, + }, + ], } diff --git a/backend/node_modules/qs/CHANGELOG.md b/backend/node_modules/qs/CHANGELOG.md index c6b29155..dc8e8794 100644 --- a/backend/node_modules/qs/CHANGELOG.md +++ b/backend/node_modules/qs/CHANGELOG.md @@ -1,3 +1,91 @@ +## **6.14.0** +- [New] `parse`: add `throwOnParameterLimitExceeded` option (#517) +- [Refactor] `parse`: use `utils.combine` more +- [patch] `parse`: add explicit `throwOnLimitExceeded` default +- [actions] use shared action; re-add finishers +- [meta] Fix changelog formatting bug +- [Deps] update `side-channel` +- [Dev Deps] update `es-value-fixtures`, `has-bigints`, `has-proto`, `has-symbols` +- [Tests] increase coverage + +## **6.13.1** +- [Fix] `stringify`: avoid a crash when a `filter` key is `null` +- [Fix] `utils.merge`: functions should not be stringified into keys +- [Fix] `parse`: avoid a crash with interpretNumericEntities: true, comma: true, and iso charset +- [Fix] `stringify`: ensure a non-string `filter` does not crash +- [Refactor] use `__proto__` syntax instead of `Object.create` for null objects +- [Refactor] misc cleanup +- [Tests] `utils.merge`: add some coverage +- [Tests] fix a test case +- [actions] split out node 10-20, and 20+ +- [Dev Deps] update `es-value-fixtures`, `mock-property`, `object-inspect`, `tape` + +## **6.13.0** +- [New] `parse`: add `strictDepth` option (#511) +- [Tests] use `npm audit` instead of `aud` + +## **6.12.3** +- [Fix] `parse`: properly account for `strictNullHandling` when `allowEmptyArrays` +- [meta] fix changelog indentation + +## **6.12.2** +- [Fix] `parse`: parse encoded square brackets (#506) +- [readme] add CII best practices badge + +## **6.12.1** +- [Fix] `parse`: Disable `decodeDotInKeys` by default to restore previous behavior (#501) +- [Performance] `utils`: Optimize performance under large data volumes, reduce memory usage, and speed up processing (#502) +- [Refactor] `utils`: use `+=` +- [Tests] increase coverage + +## **6.12.0** + +- [New] `parse`/`stringify`: add `decodeDotInKeys`/`encodeDotKeys` options (#488) +- [New] `parse`: add `duplicates` option +- [New] `parse`/`stringify`: add `allowEmptyArrays` option to allow [] in object values (#487) +- [Refactor] `parse`/`stringify`: move allowDots config logic to its own variable +- [Refactor] `stringify`: move option-handling code into `normalizeStringifyOptions` +- [readme] update readme, add logos (#484) +- [readme] `stringify`: clarify default `arrayFormat` behavior +- [readme] fix line wrapping +- [readme] remove dead badges +- [Deps] update `side-channel` +- [meta] make the dist build 50% smaller +- [meta] add `sideEffects` flag +- [meta] run build in prepack, not prepublish +- [Tests] `parse`: remove useless tests; add coverage +- [Tests] `stringify`: increase coverage +- [Tests] use `mock-property` +- [Tests] `stringify`: improve coverage +- [Dev Deps] update `@ljharb/eslint-config `, `aud`, `has-override-mistake`, `has-property-descriptors`, `mock-property`, `npmignore`, `object-inspect`, `tape` +- [Dev Deps] pin `glob`, since v10.3.8+ requires a broken `jackspeak` +- [Dev Deps] pin `jackspeak` since 2.1.2+ depends on npm aliases, which kill the install process in npm < 6 + +## **6.11.2** +- [Fix] `parse`: Fix parsing when the global Object prototype is frozen (#473) +- [Tests] add passing test cases with empty keys (#473) + +## **6.11.1** +- [Fix] `stringify`: encode comma values more consistently (#463) +- [readme] add usage of `filter` option for injecting custom serialization, i.e. of custom types (#447) +- [meta] remove extraneous code backticks (#457) +- [meta] fix changelog markdown +- [actions] update checkout action +- [actions] restrict action permissions +- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `object-inspect`, `tape` + +## **6.11.0** +- [New] [Fix] `stringify`: revert 0e903c0; add `commaRoundTrip` option (#442) +- [readme] fix version badge + +## **6.10.5** +- [Fix] `stringify`: with `arrayFormat: comma`, properly include an explicit `[]` on a single-item array (#434) + +## **6.10.4** +- [Fix] `stringify`: with `arrayFormat: comma`, include an explicit `[]` on a single-item array (#441) +- [meta] use `npmignore` to autogenerate an npmignore file +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `has-symbol`, `object-inspect`, `tape` + ## **6.10.3** - [Fix] `parse`: ignore `__proto__` keys (#428) - [Robustness] `stringify`: avoid relying on a global `undefined` (#427) @@ -27,6 +115,18 @@ - [Tests] use `ljharb/actions/node/install` instead of `ljharb/actions/node/run` - [Tests] Revert "[meta] ignore eclint transitive audit warning" +## **6.9.7** +- [Fix] `parse`: ignore `__proto__` keys (#428) +- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424) +- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) +- [readme] remove travis badge; add github actions/codecov badges; update URLs +- [Docs] add note and links for coercing primitive values (#408) +- [Tests] clean up stringify tests slightly +- [meta] fix README.md (#399) +- Revert "[meta] ignore eclint transitive audit warning" +- [actions] backport actions from main +- [Dev Deps] backport updates from main + ## **6.9.6** - [Fix] restore `dist` dir; mistakenly removed in d4f6c32 @@ -75,6 +175,19 @@ - [Tests] up to `node` `v12.10`, `v11.15`, `v10.16`, `v8.16` - [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray +## **6.8.3** +- [Fix] `parse`: ignore `__proto__` keys (#428) +- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) +- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424) +- [readme] remove travis badge; add github actions/codecov badges; update URLs +- [Tests] clean up stringify tests slightly +- [Docs] add note and links for coercing primitive values (#408) +- [meta] fix README.md (#399) +- [actions] backport actions from main +- [Dev Deps] backport updates from main +- [Refactor] `stringify`: reduce branching +- [meta] do not publish workflow files + ## **6.8.2** - [Fix] proper comma parsing of URL-encoded commas (#361) - [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336) @@ -106,6 +219,19 @@ - [meta] add FUNDING.yml - [meta] Clean up license text so it’s properly detected as BSD-3-Clause +## **6.7.3** +- [Fix] `parse`: ignore `__proto__` keys (#428) +- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424) +- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) +- [readme] remove travis badge; add github actions/codecov badges; update URLs +- [Docs] add note and links for coercing primitive values (#408) +- [meta] fix README.md (#399) +- [meta] do not publish workflow files +- [actions] backport actions from main +- [Dev Deps] backport updates from main +- [Tests] use `nyc` for coverage +- [Tests] clean up stringify tests slightly + ## **6.7.2** - [Fix] proper comma parsing of URL-encoded commas (#361) - [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336) @@ -144,6 +270,32 @@ - [Tests] fix Buffer tests to work in node < 4.5 and node < 5.10 - [Tests] temporarily allow coverage to fail +## **6.6.1** +- [Fix] `parse`: ignore `__proto__` keys (#428) +- [Fix] fix for an impossible situation: when the formatter is called with a non-string value +- [Fix] `utils.merge`: avoid a crash with a null target and an array source +- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source +- [Fix] correctly parse nested arrays +- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) +- [Robustness] `stringify`: cache `Object.prototype.hasOwnProperty` +- [Refactor] `formats`: tiny bit of cleanup. +- [Refactor] `utils`: `isBuffer`: small tweak; add tests +- [Refactor]: `stringify`/`utils`: cache `Array.isArray` +- [Refactor] `utils`: reduce observable [[Get]]s +- [Refactor] use cached `Array.isArray` +- [Refactor] `parse`/`stringify`: make a function to normalize the options +- [readme] remove travis badge; add github actions/codecov badges; update URLs +- [Docs] Clarify the need for "arrayLimit" option +- [meta] fix README.md (#399) +- [meta] do not publish workflow files +- [meta] Clean up license text so it’s properly detected as BSD-3-Clause +- [meta] add FUNDING.yml +- [meta] Fixes typo in CHANGELOG.md +- [actions] backport actions from main +- [Tests] fix Buffer tests to work in node < 4.5 and node < 5.10 +- [Tests] always use `String(x)` over `x.toString()` +- [Dev Deps] backport from main + ## **6.6.0** - [New] Add support for iso-8859-1, utf8 "sentinel" and numeric entities (#268) - [New] move two-value combine to a `utils` function (#189) @@ -160,6 +312,30 @@ - [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`, `iconv-lite`, `safe-publish-latest`, `tape` - [Tests] up to `node` `v10.10`, `v9.11`, `v8.12`, `v6.14`, `v4.9`; pin included builds to LTS +## **6.5.3** +- [Fix] `parse`: ignore `__proto__` keys (#428) +- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source +- [Fix] correctly parse nested arrays +- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279) +- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided +- [Fix] when `parseArrays` is false, properly handle keys ending in `[]` +- [Fix] fix for an impossible situation: when the formatter is called with a non-string value +- [Fix] `utils.merge`: avoid a crash with a null target and an array source +- [Refactor] `utils`: reduce observable [[Get]]s +- [Refactor] use cached `Array.isArray` +- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269) +- [Refactor] `parse`: only need to reassign the var once +- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) +- [readme] remove travis badge; add github actions/codecov badges; update URLs +- [Docs] Clean up license text so it’s properly detected as BSD-3-Clause +- [Docs] Clarify the need for "arrayLimit" option +- [meta] fix README.md (#399) +- [meta] add FUNDING.yml +- [actions] backport actions from main +- [Tests] always use `String(x)` over `x.toString()` +- [Tests] remove nonexistent tape option +- [Dev Deps] backport from main + ## **6.5.2** - [Fix] use `safer-buffer` instead of `Buffer` constructor - [Refactor] utils: `module.exports` one thing, instead of mutating `exports` (#230) @@ -186,6 +362,27 @@ - [Tests] up to `node` `v8.1`, `v7.10`, `v6.11`; npm v4.6 breaks on node < v1; npm v5+ breaks on node < v4 - [Tests] add `editorconfig-tools` +## **6.4.1** +- [Fix] `parse`: ignore `__proto__` keys (#428) +- [Fix] fix for an impossible situation: when the formatter is called with a non-string value +- [Fix] use `safer-buffer` instead of `Buffer` constructor +- [Fix] `utils.merge`: avoid a crash with a null target and an array source +- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source +- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279) +- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided +- [Fix] when `parseArrays` is false, properly handle keys ending in `[]` +- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) +- [Refactor] use cached `Array.isArray` +- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269) +- [readme] remove travis badge; add github actions/codecov badges; update URLs +- [Docs] Clarify the need for "arrayLimit" option +- [meta] fix README.md (#399) +- [meta] Clean up license text so it’s properly detected as BSD-3-Clause +- [meta] add FUNDING.yml +- [actions] backport actions from main +- [Tests] remove nonexistent tape option +- [Dev Deps] backport from main + ## **6.4.0** - [New] `qs.stringify`: add `encodeValuesOnly` option - [Fix] follow `allowPrototypes` option during merge (#201, #201) @@ -195,6 +392,26 @@ - [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds - [eslint] reduce warnings +## **6.3.3** +- [Fix] `parse`: ignore `__proto__` keys (#428) +- [Fix] fix for an impossible situation: when the formatter is called with a non-string value +- [Fix] `utils.merge`: avoid a crash with a null target and an array source +- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source +- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279) +- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided +- [Fix] when `parseArrays` is false, properly handle keys ending in `[]` +- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) +- [Refactor] use cached `Array.isArray` +- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269) +- [Docs] Clarify the need for "arrayLimit" option +- [meta] fix README.md (#399) +- [meta] Clean up license text so it’s properly detected as BSD-3-Clause +- [meta] add FUNDING.yml +- [actions] backport actions from main +- [Tests] use `safer-buffer` instead of `Buffer` constructor +- [Tests] remove nonexistent tape option +- [Dev Deps] backport from main + ## **6.3.2** - [Fix] follow `allowPrototypes` option during merge (#201, #200) - [Dev Deps] update `eslint` @@ -228,6 +445,23 @@ - [Tests] skip Object.create tests when null objects are not available - [Tests] Turn on eslint for test files (#175) +## **6.2.4** +- [Fix] `parse`: ignore `__proto__` keys (#428) +- [Fix] `utils.merge`: avoid a crash with a null target and an array source +- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source +- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided +- [Fix] when `parseArrays` is false, properly handle keys ending in `[]` +- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) +- [Refactor] use cached `Array.isArray` +- [Docs] Clarify the need for "arrayLimit" option +- [meta] fix README.md (#399) +- [meta] Clean up license text so it’s properly detected as BSD-3-Clause +- [meta] add FUNDING.yml +- [actions] backport actions from main +- [Tests] use `safer-buffer` instead of `Buffer` constructor +- [Tests] remove nonexistent tape option +- [Dev Deps] backport from main + ## **6.2.3** - [Fix] follow `allowPrototypes` option during merge (#201, #200) - [Fix] chmod a-x @@ -249,7 +483,7 @@ - [New] add "encoder" and "decoder" options, for custom param encoding/decoding (#160) - [Fix] fix compacting of nested sparse arrays (#150) -## **6.1.2 +## **6.1.2** - [Fix] follow `allowPrototypes` option during merge (#201, #200) - [Fix] chmod a-x - [Fix] support keys starting with brackets (#202, #200) diff --git a/backend/node_modules/qs/README.md b/backend/node_modules/qs/README.md index 01263804..22c411df 100644 --- a/backend/node_modules/qs/README.md +++ b/backend/node_modules/qs/README.md @@ -1,11 +1,14 @@ -# qs [![Version Badge][2]][1] +

+ qs +

+ +# qs [![Version Badge][npm-version-svg]][package-url] [![github actions][actions-image]][actions-url] [![coverage][codecov-image]][codecov-url] -[![dependency status][deps-svg]][deps-url] -[![dev dependency status][dev-deps-svg]][dev-deps-url] [![License][license-image]][license-url] [![Downloads][downloads-image]][downloads-url] +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/9058/badge)](https://bestpractices.coreinfrastructure.org/projects/9058) [![npm badge][npm-badge-png]][package-url] @@ -46,14 +49,16 @@ assert.deepEqual(qs.parse('foo[bar]=baz'), { }); ``` -When using the `plainObjects` option the parsed value is returned as a null object, created via `Object.create(null)` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like: +When using the `plainObjects` option the parsed value is returned as a null object, created via `{ __proto__: null }` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like: ```javascript var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true }); assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } }); ``` -By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties. *WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten. Always be careful with this option. +By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties. +*WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten. +Always be careful with this option. ```javascript var protoObject = qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true }); @@ -80,8 +85,8 @@ assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), { }); ``` -By default, when nesting objects **qs** will only parse up to 5 children deep. This means if you attempt to parse a string like -`'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be: +By default, when nesting objects **qs** will only parse up to 5 children deep. +This means if you attempt to parse a string like `'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be: ```javascript var expected = { @@ -110,7 +115,18 @@ var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 }); assert.deepEqual(deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } }); ``` -The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. +You can configure **qs** to throw an error when parsing nested input beyond this depth using the `strictDepth` option (defaulted to false): + +```javascript +try { + qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1, strictDepth: true }); +} catch (err) { + assert(err instanceof RangeError); + assert.strictEqual(err.message, 'Input depth exceeded depth option of 1 and strictDepth is true'); +} +``` + +The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. The strictDepth option adds a layer of protection by throwing an error when the limit is exceeded, allowing you to catch and handle such cases. For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option: @@ -119,6 +135,18 @@ var limited = qs.parse('a=b&c=d', { parameterLimit: 1 }); assert.deepEqual(limited, { a: 'b' }); ``` +If you want an error to be thrown whenever the a limit is exceeded (eg, `parameterLimit`, `arrayLimit`), set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit. +```javascript +try { + qs.parse('a=1&b=2&c=3&d=4', { parameterLimit: 3, throwOnLimitExceeded: true }); +} catch (err) { + assert(err instanceof Error); + assert.strictEqual(err.message, 'Parameter limit exceeded. Only 3 parameters allowed.'); +} +``` + +When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `parameterLimit` and ignore the rest without throwing an error. + To bypass the leading question mark, use `ignoreQueryPrefix`: ```javascript @@ -147,32 +175,44 @@ var withDots = qs.parse('a.b=c', { allowDots: true }); assert.deepEqual(withDots, { a: { b: 'c' } }); ``` -If you have to deal with legacy browsers or services, there's -also support for decoding percent-encoded octets as iso-8859-1: +Option `decodeDotInKeys` can be used to decode dots in keys +Note: it implies `allowDots`, so `parse` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`. + +```javascript +var withDots = qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { decodeDotInKeys: true }); +assert.deepEqual(withDots, { 'name.obj': { first: 'John', last: 'Doe' }}); +``` + +Option `allowEmptyArrays` can be used to allowing empty array values in object +```javascript +var withEmptyArrays = qs.parse('foo[]&bar=baz', { allowEmptyArrays: true }); +assert.deepEqual(withEmptyArrays, { foo: [], bar: 'baz' }); +``` + +Option `duplicates` can be used to change the behavior when duplicate keys are encountered +```javascript +assert.deepEqual(qs.parse('foo=bar&foo=baz'), { foo: ['bar', 'baz'] }); +assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'combine' }), { foo: ['bar', 'baz'] }); +assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'first' }), { foo: 'bar' }); +assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'last' }), { foo: 'baz' }); +``` + +If you have to deal with legacy browsers or services, there's also support for decoding percent-encoded octets as iso-8859-1: ```javascript var oldCharset = qs.parse('a=%A7', { charset: 'iso-8859-1' }); assert.deepEqual(oldCharset, { a: '§' }); ``` -Some services add an initial `utf8=✓` value to forms so that old -Internet Explorer versions are more likely to submit the form as -utf-8. Additionally, the server can check the value against wrong -encodings of the checkmark character and detect that a query string -or `application/x-www-form-urlencoded` body was *not* sent as -utf-8, eg. if the form had an `accept-charset` parameter or the -containing page had a different character set. +Some services add an initial `utf8=✓` value to forms so that old Internet Explorer versions are more likely to submit the form as utf-8. +Additionally, the server can check the value against wrong encodings of the checkmark character and detect that a query string or `application/x-www-form-urlencoded` body was *not* sent as utf-8, eg. if the form had an `accept-charset` parameter or the containing page had a different character set. **qs** supports this mechanism via the `charsetSentinel` option. -If specified, the `utf8` parameter will be omitted from the -returned object. It will be used to switch to `iso-8859-1`/`utf-8` -mode depending on how the checkmark is encoded. +If specified, the `utf8` parameter will be omitted from the returned object. +It will be used to switch to `iso-8859-1`/`utf-8` mode depending on how the checkmark is encoded. -**Important**: When you specify both the `charset` option and the -`charsetSentinel` option, the `charset` will be overridden when -the request contains a `utf8` parameter from which the actual -charset can be deduced. In that sense the `charset` will behave -as the default charset rather than the authoritative charset. +**Important**: When you specify both the `charset` option and the `charsetSentinel` option, the `charset` will be overridden when the request contains a `utf8` parameter from which the actual charset can be deduced. +In that sense the `charset` will behave as the default charset rather than the authoritative charset. ```javascript var detectedAsUtf8 = qs.parse('utf8=%E2%9C%93&a=%C3%B8', { @@ -189,8 +229,7 @@ var detectedAsIso8859_1 = qs.parse('utf8=%26%2310003%3B&a=%F8', { assert.deepEqual(detectedAsIso8859_1, { a: 'ø' }); ``` -If you want to decode the `&#...;` syntax to the actual character, -you can specify the `interpretNumericEntities` option as well: +If you want to decode the `&#...;` syntax to the actual character, you can specify the `interpretNumericEntities` option as well: ```javascript var detectedAsIso8859_1 = qs.parse('a=%26%239786%3B', { @@ -200,8 +239,7 @@ var detectedAsIso8859_1 = qs.parse('a=%26%239786%3B', { assert.deepEqual(detectedAsIso8859_1, { a: '☺' }); ``` -It also works when the charset has been detected in `charsetSentinel` -mode. +It also works when the charset has been detected in `charsetSentinel` mode. ### Parsing Arrays @@ -219,9 +257,8 @@ var withIndexes = qs.parse('a[1]=c&a[0]=b'); assert.deepEqual(withIndexes, { a: ['b', 'c'] }); ``` -Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number -to create an array. When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving -their order: +Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number to create an array. +When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving their order: ```javascript var noSparse = qs.parse('a[1]=b&a[15]=c'); @@ -245,8 +282,9 @@ var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c'); assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] }); ``` -**qs** will also limit specifying indices in an array to a maximum index of `20`. Any array members with an index of greater than `20` will -instead be converted to an object with the index as the key. This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array. +**qs** will also limit specifying indices in an array to a maximum index of `20`. +Any array members with an index of greater than `20` will instead be converted to an object with the index as the key. +This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array. ```javascript var withMaxIndex = qs.parse('a[100]=b'); @@ -260,6 +298,18 @@ var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 }); assert.deepEqual(withArrayLimit, { a: { '1': 'b' } }); ``` +If you want to throw an error whenever the array limit is exceeded, set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit. +```javascript +try { + qs.parse('a[1]=b', { arrayLimit: 0, throwOnLimitExceeded: true }); +} catch (err) { + assert(err instanceof Error); + assert.strictEqual(err.message, 'Array limit exceeded. Only 0 elements allowed in an array.'); +} +``` + +When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `arrayLimit` and if the limit is exceeded, the array will instead be converted to an object with the index as the key + To disable array parsing entirely, set `parseArrays` to `false`. ```javascript @@ -290,7 +340,8 @@ assert.deepEqual(arraysOfObjects, { a: ['b', 'c'] }) ### Parsing primitive/scalar values (numbers, booleans, null, etc) -By default, all values are parsed as strings. This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91). +By default, all values are parsed as strings. +This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91). ```javascript var primitiveValues = qs.parse('a=15&b=true&c=null'); @@ -373,16 +424,17 @@ var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset, }}) ``` -Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage. +Examples beyond this point will be shown as though the output is not URI encoded for clarity. +Please note that the return values in these cases *will* be URI encoded during real usage. -When arrays are stringified, by default they are given explicit indices: +When arrays are stringified, they follow the `arrayFormat` option, which defaults to `indices`: ```javascript qs.stringify({ a: ['b', 'c', 'd'] }); // 'a[0]=b&a[1]=c&a[2]=d' ``` -You may override this by setting the `indices` option to `false`: +You may override this by setting the `indices` option to `false`, or to be more explicit, the `arrayFormat` option to `repeat`: ```javascript qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }); @@ -402,6 +454,8 @@ qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' }) // 'a=b,c' ``` +Note: when using `arrayFormat` set to `'comma'`, you can also pass the `commaRoundTrip` option set to `true` or `false`, to append `[]` on single-item arrays, so that they can round trip through a parse. + When objects are stringified, by default they use bracket notation: ```javascript @@ -416,6 +470,20 @@ qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true }); // 'a.b.c=d&a.b.e=f' ``` +You may encode the dot notation in the keys of object with option `encodeDotInKeys` by setting it to `true`: +Note: it implies `allowDots`, so `stringify` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`. +Caveat: when `encodeValuesOnly` is `true` as well as `encodeDotInKeys`, only dots in keys and nothing else will be encoded. +```javascript +qs.stringify({ "name.obj": { "first": "John", "last": "Doe" } }, { allowDots: true, encodeDotInKeys: true }) +// 'name%252Eobj.first=John&name%252Eobj.last=Doe' +``` + +You may allow empty array values by setting the `allowEmptyArrays` option to `true`: +```javascript +qs.stringify({ foo: [], bar: 'baz' }, { allowEmptyArrays: true }); +// 'foo[]&bar=baz' +``` + Empty strings and null values will omit the value, but the equals sign (=) remains in place: ```javascript @@ -471,8 +539,8 @@ assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort ``` Finally, you can use the `filter` option to restrict which keys will be included in the stringified output. -If you pass a function, it will be called for each key to obtain the replacement value. Otherwise, if you -pass an array, it will be used to select properties and array indices for stringification: +If you pass a function, it will be called for each key to obtain the replacement value. +Otherwise, if you pass an array, it will be used to select properties and array indices for stringification: ```javascript function filterFunc(prefix, value) { @@ -496,6 +564,44 @@ qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] }); // 'a[0]=b&a[2]=d' ``` +You could also use `filter` to inject custom serialization for user defined types. +Consider you're working with some api that expects query strings of the format for ranges: + +``` +https://domain.com/endpoint?range=30...70 +``` + +For which you model as: + +```javascript +class Range { + constructor(from, to) { + this.from = from; + this.to = to; + } +} +``` + +You could _inject_ a custom serializer to handle values of this type: + +```javascript +qs.stringify( + { + range: new Range(30, 70), + }, + { + filter: (prefix, value) => { + if (value instanceof Range) { + return `${value.from}...${value.to}`; + } + // serialize the usual way + return value; + }, + } +); +// range=30...70 +``` + ### Handling of `null` values By default, `null` values are treated like empty strings: @@ -505,7 +611,8 @@ var withNull = qs.stringify({ a: null, b: '' }); assert.equal(withNull, 'a=&b='); ``` -Parsing does not distinguish between parameters with and without equal signs. Both are converted to empty strings. +Parsing does not distinguish between parameters with and without equal signs. +Both are converted to empty strings. ```javascript var equalsInsensitive = qs.parse('a&b='); @@ -534,25 +641,21 @@ var nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true }); assert.equal(nullsSkipped, 'a=b'); ``` -If you're communicating with legacy systems, you can switch to `iso-8859-1` -using the `charset` option: +If you're communicating with legacy systems, you can switch to `iso-8859-1` using the `charset` option: ```javascript var iso = qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' }); assert.equal(iso, '%E6=%E6'); ``` -Characters that don't exist in `iso-8859-1` will be converted to numeric -entities, similar to what browsers do: +Characters that don't exist in `iso-8859-1` will be converted to numeric entities, similar to what browsers do: ```javascript var numeric = qs.stringify({ a: '☺' }, { charset: 'iso-8859-1' }); assert.equal(numeric, 'a=%26%239786%3B'); ``` -You can use the `charsetSentinel` option to announce the character by -including an `utf8=✓` parameter with the proper encoding if the checkmark, -similar to what Ruby on Rails and others do when submitting forms. +You can use the `charsetSentinel` option to announce the character by including an `utf8=✓` parameter with the proper encoding if the checkmark, similar to what Ruby on Rails and others do when submitting forms. ```javascript var sentinel = qs.stringify({ a: '☺' }, { charsetSentinel: true }); @@ -564,8 +667,7 @@ assert.equal(isoSentinel, 'utf8=%26%2310003%3B&a=%E6'); ### Dealing with special character sets -By default the encoding and decoding of characters is done in `utf-8`, -and `iso-8859-1` support is also built in via the `charset` parameter. +By default the encoding and decoding of characters is done in `utf-8`, and `iso-8859-1` support is also built in via the `charset` parameter. If you wish to encode querystrings to a different character set (i.e. [Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the @@ -604,7 +706,9 @@ Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/se Available as part of the Tidelift Subscription -The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) +The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. +Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. +[Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) [package-url]: https://npmjs.org/package/qs [npm-version-svg]: https://versionbadg.es/ljharb/qs.svg @@ -621,3 +725,9 @@ The maintainers of qs and thousands of other packages are working with Tidelift [codecov-url]: https://app.codecov.io/gh/ljharb/qs/ [actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/qs [actions-url]: https://github.com/ljharb/qs/actions + +## Acknowledgements + +qs logo by [NUMI](https://github.com/numi-hq/open-design): + +[NUMI Logo](https://numi.tech/?ref=qs) diff --git a/backend/node_modules/qs/dist/qs.js b/backend/node_modules/qs/dist/qs.js index 94baf8ff..f37989a5 100644 --- a/backend/node_modules/qs/dist/qs.js +++ b/backend/node_modules/qs/dist/qs.js @@ -1,2044 +1,141 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i -1) { - return val.split(','); - } - - return val; -}; - -// This is what browsers will submit when the ✓ character occurs in an -// application/x-www-form-urlencoded body and the encoding of the page containing -// the form is iso-8859-1, or when the submitted form has an accept-charset -// attribute of iso-8859-1. Presumably also with other charsets that do not contain -// the ✓ character, such as us-ascii. -var isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('✓') - -// These are the percent-encoded utf-8 octets representing a checkmark, indicating that the request actually is utf-8 encoded. -var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓') - -var parseValues = function parseQueryStringValues(str, options) { - var obj = {}; - var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str; - var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit; - var parts = cleanStr.split(options.delimiter, limit); - var skipIndex = -1; // Keep track of where the utf8 sentinel was found - var i; - - var charset = options.charset; - if (options.charsetSentinel) { - for (i = 0; i < parts.length; ++i) { - if (parts[i].indexOf('utf8=') === 0) { - if (parts[i] === charsetSentinel) { - charset = 'utf-8'; - } else if (parts[i] === isoSentinel) { - charset = 'iso-8859-1'; - } - skipIndex = i; - i = parts.length; // The eslint settings do not allow break; - } - } - } - - for (i = 0; i < parts.length; ++i) { - if (i === skipIndex) { - continue; - } - var part = parts[i]; - - var bracketEqualsPos = part.indexOf(']='); - var pos = bracketEqualsPos === -1 ? part.indexOf('=') : bracketEqualsPos + 1; - - var key, val; - if (pos === -1) { - key = options.decoder(part, defaults.decoder, charset, 'key'); - val = options.strictNullHandling ? null : ''; - } else { - key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key'); - val = utils.maybeMap( - parseArrayValue(part.slice(pos + 1), options), - function (encodedVal) { - return options.decoder(encodedVal, defaults.decoder, charset, 'value'); - } - ); - } - - if (val && options.interpretNumericEntities && charset === 'iso-8859-1') { - val = interpretNumericEntities(val); - } - - if (part.indexOf('[]=') > -1) { - val = isArray(val) ? [val] : val; - } - - if (has.call(obj, key)) { - obj[key] = utils.combine(obj[key], val); - } else { - obj[key] = val; - } - } - - return obj; -}; - -var parseObject = function (chain, val, options, valuesParsed) { - var leaf = valuesParsed ? val : parseArrayValue(val, options); - - for (var i = chain.length - 1; i >= 0; --i) { - var obj; - var root = chain[i]; - - if (root === '[]' && options.parseArrays) { - obj = [].concat(leaf); - } else { - obj = options.plainObjects ? Object.create(null) : {}; - var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root; - var index = parseInt(cleanRoot, 10); - if (!options.parseArrays && cleanRoot === '') { - obj = { 0: leaf }; - } else if ( - !isNaN(index) - && root !== cleanRoot - && String(index) === cleanRoot - && index >= 0 - && (options.parseArrays && index <= options.arrayLimit) - ) { - obj = []; - obj[index] = leaf; - } else if (cleanRoot !== '__proto__') { - obj[cleanRoot] = leaf; - } - } - - leaf = obj; - } - - return leaf; -}; - -var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) { - if (!givenKey) { - return; - } - - // Transform dot notation to bracket notation - var key = options.allowDots ? givenKey.replace(/\.([^.[]+)/g, '[$1]') : givenKey; - - // The regex chunks - - var brackets = /(\[[^[\]]*])/; - var child = /(\[[^[\]]*])/g; - - // Get the parent - - var segment = options.depth > 0 && brackets.exec(key); - var parent = segment ? key.slice(0, segment.index) : key; - - // Stash the parent if it exists - - var keys = []; - if (parent) { - // If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties - if (!options.plainObjects && has.call(Object.prototype, parent)) { - if (!options.allowPrototypes) { - return; - } - } - - keys.push(parent); - } - - // Loop through children appending to the array until we hit depth - - var i = 0; - while (options.depth > 0 && (segment = child.exec(key)) !== null && i < options.depth) { - i += 1; - if (!options.plainObjects && has.call(Object.prototype, segment[1].slice(1, -1))) { - if (!options.allowPrototypes) { - return; - } - } - keys.push(segment[1]); - } - - // If there's a remainder, just add whatever is left - - if (segment) { - keys.push('[' + key.slice(segment.index) + ']'); - } - - return parseObject(keys, val, options, valuesParsed); -}; - -var normalizeParseOptions = function normalizeParseOptions(opts) { - if (!opts) { - return defaults; - } - - if (opts.decoder !== null && opts.decoder !== undefined && typeof opts.decoder !== 'function') { - throw new TypeError('Decoder has to be a function.'); - } - - if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') { - throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'); - } - var charset = typeof opts.charset === 'undefined' ? defaults.charset : opts.charset; - - return { - allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots, - allowPrototypes: typeof opts.allowPrototypes === 'boolean' ? opts.allowPrototypes : defaults.allowPrototypes, - allowSparse: typeof opts.allowSparse === 'boolean' ? opts.allowSparse : defaults.allowSparse, - arrayLimit: typeof opts.arrayLimit === 'number' ? opts.arrayLimit : defaults.arrayLimit, - charset: charset, - charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel, - comma: typeof opts.comma === 'boolean' ? opts.comma : defaults.comma, - decoder: typeof opts.decoder === 'function' ? opts.decoder : defaults.decoder, - delimiter: typeof opts.delimiter === 'string' || utils.isRegExp(opts.delimiter) ? opts.delimiter : defaults.delimiter, - // eslint-disable-next-line no-implicit-coercion, no-extra-parens - depth: (typeof opts.depth === 'number' || opts.depth === false) ? +opts.depth : defaults.depth, - ignoreQueryPrefix: opts.ignoreQueryPrefix === true, - interpretNumericEntities: typeof opts.interpretNumericEntities === 'boolean' ? opts.interpretNumericEntities : defaults.interpretNumericEntities, - parameterLimit: typeof opts.parameterLimit === 'number' ? opts.parameterLimit : defaults.parameterLimit, - parseArrays: opts.parseArrays !== false, - plainObjects: typeof opts.plainObjects === 'boolean' ? opts.plainObjects : defaults.plainObjects, - strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling - }; -}; - -module.exports = function (str, opts) { - var options = normalizeParseOptions(opts); - - if (str === '' || str === null || typeof str === 'undefined') { - return options.plainObjects ? Object.create(null) : {}; - } - - var tempObj = typeof str === 'string' ? parseValues(str, options) : str; - var obj = options.plainObjects ? Object.create(null) : {}; - - // Iterate over the keys and setup the new object - - var keys = Object.keys(tempObj); - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - var newObj = parseKeys(key, tempObj[key], options, typeof str === 'string'); - obj = utils.merge(obj, newObj, options); - } - - if (options.allowSparse === true) { - return obj; - } - - return utils.compact(obj); -}; - -},{"./utils":5}],4:[function(require,module,exports){ -'use strict'; - -var getSideChannel = require('side-channel'); -var utils = require('./utils'); -var formats = require('./formats'); -var has = Object.prototype.hasOwnProperty; - -var arrayPrefixGenerators = { - brackets: function brackets(prefix) { - return prefix + '[]'; - }, - comma: 'comma', - indices: function indices(prefix, key) { - return prefix + '[' + key + ']'; - }, - repeat: function repeat(prefix) { - return prefix; - } -}; - -var isArray = Array.isArray; -var split = String.prototype.split; -var push = Array.prototype.push; -var pushToArray = function (arr, valueOrArray) { - push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]); -}; - -var toISO = Date.prototype.toISOString; - -var defaultFormat = formats['default']; -var defaults = { - addQueryPrefix: false, - allowDots: false, - charset: 'utf-8', - charsetSentinel: false, - delimiter: '&', - encode: true, - encoder: utils.encode, - encodeValuesOnly: false, - format: defaultFormat, - formatter: formats.formatters[defaultFormat], - // deprecated - indices: false, - serializeDate: function serializeDate(date) { - return toISO.call(date); - }, - skipNulls: false, - strictNullHandling: false -}; - -var isNonNullishPrimitive = function isNonNullishPrimitive(v) { - return typeof v === 'string' - || typeof v === 'number' - || typeof v === 'boolean' - || typeof v === 'symbol' - || typeof v === 'bigint'; -}; - -var sentinel = {}; - -var stringify = function stringify( - object, - prefix, - generateArrayPrefix, - strictNullHandling, - skipNulls, - encoder, - filter, - sort, - allowDots, - serializeDate, - format, - formatter, - encodeValuesOnly, - charset, - sideChannel -) { - var obj = object; - - var tmpSc = sideChannel; - var step = 0; - var findFlag = false; - while ((tmpSc = tmpSc.get(sentinel)) !== void undefined && !findFlag) { - // Where object last appeared in the ref tree - var pos = tmpSc.get(object); - step += 1; - if (typeof pos !== 'undefined') { - if (pos === step) { - throw new RangeError('Cyclic object value'); - } else { - findFlag = true; // Break while - } - } - if (typeof tmpSc.get(sentinel) === 'undefined') { - step = 0; - } - } - - if (typeof filter === 'function') { - obj = filter(prefix, obj); - } else if (obj instanceof Date) { - obj = serializeDate(obj); - } else if (generateArrayPrefix === 'comma' && isArray(obj)) { - obj = utils.maybeMap(obj, function (value) { - if (value instanceof Date) { - return serializeDate(value); - } - return value; - }); - } - - if (obj === null) { - if (strictNullHandling) { - return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix; - } - - obj = ''; - } - - if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) { - if (encoder) { - var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format); - if (generateArrayPrefix === 'comma' && encodeValuesOnly) { - var valuesArray = split.call(String(obj), ','); - var valuesJoined = ''; - for (var i = 0; i < valuesArray.length; ++i) { - valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset, 'value', format)); - } - return [formatter(keyValue) + '=' + valuesJoined]; - } - return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))]; - } - return [formatter(prefix) + '=' + formatter(String(obj))]; - } - - var values = []; - - if (typeof obj === 'undefined') { - return values; - } - - var objKeys; - if (generateArrayPrefix === 'comma' && isArray(obj)) { - // we need to join elements in - objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }]; - } else if (isArray(filter)) { - objKeys = filter; - } else { - var keys = Object.keys(obj); - objKeys = sort ? keys.sort(sort) : keys; - } - - for (var j = 0; j < objKeys.length; ++j) { - var key = objKeys[j]; - var value = typeof key === 'object' && typeof key.value !== 'undefined' ? key.value : obj[key]; - - if (skipNulls && value === null) { - continue; - } - - var keyPrefix = isArray(obj) - ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix - : prefix + (allowDots ? '.' + key : '[' + key + ']'); - - sideChannel.set(object, step); - var valueSideChannel = getSideChannel(); - valueSideChannel.set(sentinel, sideChannel); - pushToArray(values, stringify( - value, - keyPrefix, - generateArrayPrefix, - strictNullHandling, - skipNulls, - encoder, - filter, - sort, - allowDots, - serializeDate, - format, - formatter, - encodeValuesOnly, - charset, - valueSideChannel - )); - } - - return values; -}; - -var normalizeStringifyOptions = function normalizeStringifyOptions(opts) { - if (!opts) { - return defaults; - } - - if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') { - throw new TypeError('Encoder has to be a function.'); - } - - var charset = opts.charset || defaults.charset; - if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') { - throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'); - } - - var format = formats['default']; - if (typeof opts.format !== 'undefined') { - if (!has.call(formats.formatters, opts.format)) { - throw new TypeError('Unknown format option provided.'); - } - format = opts.format; - } - var formatter = formats.formatters[format]; - - var filter = defaults.filter; - if (typeof opts.filter === 'function' || isArray(opts.filter)) { - filter = opts.filter; - } - - return { - addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix, - allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots, - charset: charset, - charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel, - delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter, - encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode, - encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder, - encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly, - filter: filter, - format: format, - formatter: formatter, - serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate, - skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls, - sort: typeof opts.sort === 'function' ? opts.sort : null, - strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling - }; -}; - -module.exports = function (object, opts) { - var obj = object; - var options = normalizeStringifyOptions(opts); - - var objKeys; - var filter; - - if (typeof options.filter === 'function') { - filter = options.filter; - obj = filter('', obj); - } else if (isArray(options.filter)) { - filter = options.filter; - objKeys = filter; - } - - var keys = []; - - if (typeof obj !== 'object' || obj === null) { - return ''; - } - - var arrayFormat; - if (opts && opts.arrayFormat in arrayPrefixGenerators) { - arrayFormat = opts.arrayFormat; - } else if (opts && 'indices' in opts) { - arrayFormat = opts.indices ? 'indices' : 'repeat'; - } else { - arrayFormat = 'indices'; - } - - var generateArrayPrefix = arrayPrefixGenerators[arrayFormat]; - - if (!objKeys) { - objKeys = Object.keys(obj); - } - - if (options.sort) { - objKeys.sort(options.sort); - } - - var sideChannel = getSideChannel(); - for (var i = 0; i < objKeys.length; ++i) { - var key = objKeys[i]; - - if (options.skipNulls && obj[key] === null) { - continue; - } - pushToArray(keys, stringify( - obj[key], - key, - generateArrayPrefix, - options.strictNullHandling, - options.skipNulls, - options.encode ? options.encoder : null, - options.filter, - options.sort, - options.allowDots, - options.serializeDate, - options.format, - options.formatter, - options.encodeValuesOnly, - options.charset, - sideChannel - )); - } - - var joined = keys.join(options.delimiter); - var prefix = options.addQueryPrefix === true ? '?' : ''; - - if (options.charsetSentinel) { - if (options.charset === 'iso-8859-1') { - // encodeURIComponent('✓'), the "numeric entity" representation of a checkmark - prefix += 'utf8=%26%2310003%3B&'; - } else { - // encodeURIComponent('✓') - prefix += 'utf8=%E2%9C%93&'; - } - } - - return joined.length > 0 ? prefix + joined : ''; -}; - -},{"./formats":1,"./utils":5,"side-channel":16}],5:[function(require,module,exports){ -'use strict'; - -var formats = require('./formats'); - -var has = Object.prototype.hasOwnProperty; -var isArray = Array.isArray; - -var hexTable = (function () { - var array = []; - for (var i = 0; i < 256; ++i) { - array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase()); - } - - return array; -}()); - -var compactQueue = function compactQueue(queue) { - while (queue.length > 1) { - var item = queue.pop(); - var obj = item.obj[item.prop]; - - if (isArray(obj)) { - var compacted = []; - - for (var j = 0; j < obj.length; ++j) { - if (typeof obj[j] !== 'undefined') { - compacted.push(obj[j]); - } - } - - item.obj[item.prop] = compacted; - } - } -}; - -var arrayToObject = function arrayToObject(source, options) { - var obj = options && options.plainObjects ? Object.create(null) : {}; - for (var i = 0; i < source.length; ++i) { - if (typeof source[i] !== 'undefined') { - obj[i] = source[i]; - } - } - - return obj; -}; - -var merge = function merge(target, source, options) { - /* eslint no-param-reassign: 0 */ - if (!source) { - return target; - } +"use strict";var stringify=require(4),parse=require(3),formats=require(1);module.exports={formats:formats,parse:parse,stringify:stringify}; - if (typeof source !== 'object') { - if (isArray(target)) { - target.push(source); - } else if (target && typeof target === 'object') { - if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) { - target[source] = true; - } - } else { - return [target, source]; - } +},{"1":1,"3":3,"4":4}],3:[function(require,module,exports){ +"use strict";var utils=require(5),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,defaults={allowDots:!1,allowEmptyArrays:!1,allowPrototypes:!1,allowSparse:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decodeDotInKeys:!1,decoder:utils.decode,delimiter:"&",depth:5,duplicates:"combine",ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictDepth:!1,strictNullHandling:!1,throwOnLimitExceeded:!1},interpretNumericEntities=function(e){return e.replace(/&#(\d+);/g,(function(e,t){return String.fromCharCode(parseInt(t,10))}))},parseArrayValue=function(e,t,r){if(e&&"string"==typeof e&&t.comma&&e.indexOf(",")>-1)return e.split(",");if(t.throwOnLimitExceeded&&r>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return e},isoSentinel="utf8=%26%2310003%3B",charsetSentinel="utf8=%E2%9C%93",parseValues=function parseQueryStringValues(e,t){var r={__proto__:null},i=t.ignoreQueryPrefix?e.replace(/^\?/,""):e;i=i.replace(/%5B/gi,"[").replace(/%5D/gi,"]");var a=t.parameterLimit===1/0?void 0:t.parameterLimit,o=i.split(t.delimiter,t.throwOnLimitExceeded?a+1:a);if(t.throwOnLimitExceeded&&o.length>a)throw new RangeError("Parameter limit exceeded. Only "+a+" parameter"+(1===a?"":"s")+" allowed.");var l,n=-1,s=t.charset;if(t.charsetSentinel)for(l=0;l-1&&(p=isArray(p)?[p]:p);var f=has.call(r,d);f&&"combine"===t.duplicates?r[d]=utils.combine(r[d],p):f&&"last"!==t.duplicates||(r[d]=p)}return r},parseObject=function(e,t,r,i){var a=0;if(e.length>0&&"[]"===e[e.length-1]){var o=e.slice(0,-1).join("");a=Array.isArray(t)&&t[o]?t[o].length:0}for(var l=i?t:parseArrayValue(t,r,a),n=e.length-1;n>=0;--n){var s,d=e[n];if("[]"===d&&r.parseArrays)s=r.allowEmptyArrays&&(""===l||r.strictNullHandling&&null===l)?[]:utils.combine([],l);else{s=r.plainObjects?{__proto__:null}:{};var p="["===d.charAt(0)&&"]"===d.charAt(d.length-1)?d.slice(1,-1):d,c=r.decodeDotInKeys?p.replace(/%2E/g,"."):p,u=parseInt(c,10);r.parseArrays||""!==c?!isNaN(u)&&d!==c&&String(u)===c&&u>=0&&r.parseArrays&&u<=r.arrayLimit?(s=[])[u]=l:"__proto__"!==c&&(s[c]=l):s={0:l}}l=s}return l},parseKeys=function parseQueryStringKeys(e,t,r,i){if(e){var a=r.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e,o=/(\[[^[\]]*])/g,l=r.depth>0&&/(\[[^[\]]*])/.exec(a),n=l?a.slice(0,l.index):a,s=[];if(n){if(!r.plainObjects&&has.call(Object.prototype,n)&&!r.allowPrototypes)return;s.push(n)}for(var d=0;r.depth>0&&null!==(l=o.exec(a))&&d0?g.join(",")||null:void 0}];else if(isArray(f))S=f;else{var N=Object.keys(g);S=u?N.sort(u):N}var T=l?String(r).replace(/\./g,"%2E"):String(r),O=o&&isArray(g)&&1===g.length?T+"[]":T;if(a&&isArray(g)&&0===g.length)return O+"[]";for(var k=0;k0?c+y:""}; - if (!target || typeof target !== 'object') { - return [target].concat(source); - } +},{"1":1,"46":46,"5":5}],5:[function(require,module,exports){ +"use strict";var formats=require(1),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,hexTable=function(){for(var e=[],r=0;r<256;++r)e.push("%"+((r<16?"0":"")+r.toString(16)).toUpperCase());return e}(),compactQueue=function compactQueue(e){for(;e.length>1;){var r=e.pop(),t=r.obj[r.prop];if(isArray(t)){for(var o=[],n=0;n=limit?a.slice(i,i+limit):a,p=[],f=0;f=48&&s<=57||s>=65&&s<=90||s>=97&&s<=122||n===formats.RFC1738&&(40===s||41===s)?p[p.length]=u.charAt(f):s<128?p[p.length]=hexTable[s]:s<2048?p[p.length]=hexTable[192|s>>6]+hexTable[128|63&s]:s<55296||s>=57344?p[p.length]=hexTable[224|s>>12]+hexTable[128|s>>6&63]+hexTable[128|63&s]:(f+=1,s=65536+((1023&s)<<10|1023&u.charCodeAt(f)),p[p.length]=hexTable[240|s>>18]+hexTable[128|s>>12&63]+hexTable[128|s>>6&63]+hexTable[128|63&s])}c+=p.join("")}return c},compact=function compact(e){for(var r=[{obj:{o:e},prop:"o"}],t=[],o=0;o= 0x30 && c <= 0x39) // 0-9 - || (c >= 0x41 && c <= 0x5A) // a-z - || (c >= 0x61 && c <= 0x7A) // A-Z - || (format === formats.RFC1738 && (c === 0x28 || c === 0x29)) // ( ) - ) { - out += string.charAt(i); - continue; - } - - if (c < 0x80) { - out = out + hexTable[c]; - continue; - } - - if (c < 0x800) { - out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]); - continue; - } - - if (c < 0xD800 || c >= 0xE000) { - out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]); - continue; - } - - i += 1; - c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); - /* eslint operator-linebreak: [2, "before"] */ - out += hexTable[0xF0 | (c >> 18)] - + hexTable[0x80 | ((c >> 12) & 0x3F)] - + hexTable[0x80 | ((c >> 6) & 0x3F)] - + hexTable[0x80 | (c & 0x3F)]; - } - - return out; -}; - -var compact = function compact(value) { - var queue = [{ obj: { o: value }, prop: 'o' }]; - var refs = []; - - for (var i = 0; i < queue.length; ++i) { - var item = queue[i]; - var obj = item.obj[item.prop]; - - var keys = Object.keys(obj); - for (var j = 0; j < keys.length; ++j) { - var key = keys[j]; - var val = obj[key]; - if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) { - queue.push({ obj: obj, prop: key }); - refs.push(val); - } - } - } - - compactQueue(queue); - - return value; -}; - -var isRegExp = function isRegExp(obj) { - return Object.prototype.toString.call(obj) === '[object RegExp]'; -}; - -var isBuffer = function isBuffer(obj) { - if (!obj || typeof obj !== 'object') { - return false; - } - - return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); -}; - -var combine = function combine(a, b) { - return [].concat(a, b); -}; - -var maybeMap = function maybeMap(val, fn) { - if (isArray(val)) { - var mapped = []; - for (var i = 0; i < val.length; i += 1) { - mapped.push(fn(val[i])); - } - return mapped; - } - return fn(val); -}; - -module.exports = { - arrayToObject: arrayToObject, - assign: assign, - combine: combine, - compact: compact, - decode: decode, - encode: encode, - isBuffer: isBuffer, - isRegExp: isRegExp, - maybeMap: maybeMap, - merge: merge -}; - -},{"./formats":1}],6:[function(require,module,exports){ +},{"20":20,"42":42,"43":43,"44":44,"45":45}],6:[function(require,module,exports){ },{}],7:[function(require,module,exports){ -'use strict'; - -var GetIntrinsic = require('get-intrinsic'); +"use strict";var bind=require(24),$apply=require(8),$call=require(9),$reflectApply=require(11);module.exports=$reflectApply||bind.call($call,$apply); -var callBind = require('./'); +},{"11":11,"24":24,"8":8,"9":9}],8:[function(require,module,exports){ +"use strict";module.exports=Function.prototype.apply; -var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf')); +},{}],9:[function(require,module,exports){ +"use strict";module.exports=Function.prototype.call; -module.exports = function callBoundIntrinsic(name, allowMissing) { - var intrinsic = GetIntrinsic(name, !!allowMissing); - if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { - return callBind(intrinsic); - } - return intrinsic; -}; +},{}],24:[function(require,module,exports){ +"use strict";var implementation=require(23);module.exports=Function.prototype.bind||implementation; -},{"./":8,"get-intrinsic":11}],8:[function(require,module,exports){ -'use strict'; - -var bind = require('function-bind'); -var GetIntrinsic = require('get-intrinsic'); - -var $apply = GetIntrinsic('%Function.prototype.apply%'); -var $call = GetIntrinsic('%Function.prototype.call%'); -var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply); - -var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true); -var $defineProperty = GetIntrinsic('%Object.defineProperty%', true); -var $max = GetIntrinsic('%Math.max%'); - -if ($defineProperty) { - try { - $defineProperty({}, 'a', { value: 1 }); - } catch (e) { - // IE 8 has a broken defineProperty - $defineProperty = null; - } -} - -module.exports = function callBind(originalFunction) { - var func = $reflectApply(bind, $call, arguments); - if ($gOPD && $defineProperty) { - var desc = $gOPD(func, 'length'); - if (desc.configurable) { - // original length, plus the receiver, minus any additional arguments (after the receiver) - $defineProperty( - func, - 'length', - { value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) } - ); - } - } - return func; -}; - -var applyBind = function applyBind() { - return $reflectApply(bind, $apply, arguments); -}; - -if ($defineProperty) { - $defineProperty(module.exports, 'apply', { value: applyBind }); -} else { - module.exports.apply = applyBind; -} - -},{"function-bind":10,"get-intrinsic":11}],9:[function(require,module,exports){ -'use strict'; - -/* eslint no-invalid-this: 1 */ - -var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible '; -var slice = Array.prototype.slice; -var toStr = Object.prototype.toString; -var funcType = '[object Function]'; - -module.exports = function bind(that) { - var target = this; - if (typeof target !== 'function' || toStr.call(target) !== funcType) { - throw new TypeError(ERROR_MESSAGE + target); - } - var args = slice.call(arguments, 1); - - var bound; - var binder = function () { - if (this instanceof bound) { - var result = target.apply( - this, - args.concat(slice.call(arguments)) - ); - if (Object(result) === result) { - return result; - } - return this; - } else { - return target.apply( - that, - args.concat(slice.call(arguments)) - ); - } - }; - - var boundLength = Math.max(0, target.length - args.length); - var boundArgs = []; - for (var i = 0; i < boundLength; i++) { - boundArgs.push('$' + i); - } - - bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder); - - if (target.prototype) { - var Empty = function Empty() {}; - Empty.prototype = target.prototype; - bound.prototype = new Empty(); - Empty.prototype = null; - } - - return bound; -}; +},{"23":23}],11:[function(require,module,exports){ +"use strict";module.exports="undefined"!=typeof Reflect&&Reflect&&Reflect.apply; },{}],10:[function(require,module,exports){ -'use strict'; - -var implementation = require('./implementation'); - -module.exports = Function.prototype.bind || implementation; - -},{"./implementation":9}],11:[function(require,module,exports){ -'use strict'; - -var undefined; - -var $SyntaxError = SyntaxError; -var $Function = Function; -var $TypeError = TypeError; - -// eslint-disable-next-line consistent-return -var getEvalledConstructor = function (expressionSyntax) { - try { - return $Function('"use strict"; return (' + expressionSyntax + ').constructor;')(); - } catch (e) {} -}; - -var $gOPD = Object.getOwnPropertyDescriptor; -if ($gOPD) { - try { - $gOPD({}, ''); - } catch (e) { - $gOPD = null; // this is IE 8, which has a broken gOPD - } -} - -var throwTypeError = function () { - throw new $TypeError(); -}; -var ThrowTypeError = $gOPD - ? (function () { - try { - // eslint-disable-next-line no-unused-expressions, no-caller, no-restricted-properties - arguments.callee; // IE 8 does not throw here - return throwTypeError; - } catch (calleeThrows) { - try { - // IE 8 throws on Object.getOwnPropertyDescriptor(arguments, '') - return $gOPD(arguments, 'callee').get; - } catch (gOPDthrows) { - return throwTypeError; - } - } - }()) - : throwTypeError; - -var hasSymbols = require('has-symbols')(); - -var getProto = Object.getPrototypeOf || function (x) { return x.__proto__; }; // eslint-disable-line no-proto - -var needsEval = {}; - -var TypedArray = typeof Uint8Array === 'undefined' ? undefined : getProto(Uint8Array); - -var INTRINSICS = { - '%AggregateError%': typeof AggregateError === 'undefined' ? undefined : AggregateError, - '%Array%': Array, - '%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer, - '%ArrayIteratorPrototype%': hasSymbols ? getProto([][Symbol.iterator]()) : undefined, - '%AsyncFromSyncIteratorPrototype%': undefined, - '%AsyncFunction%': needsEval, - '%AsyncGenerator%': needsEval, - '%AsyncGeneratorFunction%': needsEval, - '%AsyncIteratorPrototype%': needsEval, - '%Atomics%': typeof Atomics === 'undefined' ? undefined : Atomics, - '%BigInt%': typeof BigInt === 'undefined' ? undefined : BigInt, - '%Boolean%': Boolean, - '%DataView%': typeof DataView === 'undefined' ? undefined : DataView, - '%Date%': Date, - '%decodeURI%': decodeURI, - '%decodeURIComponent%': decodeURIComponent, - '%encodeURI%': encodeURI, - '%encodeURIComponent%': encodeURIComponent, - '%Error%': Error, - '%eval%': eval, // eslint-disable-line no-eval - '%EvalError%': EvalError, - '%Float32Array%': typeof Float32Array === 'undefined' ? undefined : Float32Array, - '%Float64Array%': typeof Float64Array === 'undefined' ? undefined : Float64Array, - '%FinalizationRegistry%': typeof FinalizationRegistry === 'undefined' ? undefined : FinalizationRegistry, - '%Function%': $Function, - '%GeneratorFunction%': needsEval, - '%Int8Array%': typeof Int8Array === 'undefined' ? undefined : Int8Array, - '%Int16Array%': typeof Int16Array === 'undefined' ? undefined : Int16Array, - '%Int32Array%': typeof Int32Array === 'undefined' ? undefined : Int32Array, - '%isFinite%': isFinite, - '%isNaN%': isNaN, - '%IteratorPrototype%': hasSymbols ? getProto(getProto([][Symbol.iterator]())) : undefined, - '%JSON%': typeof JSON === 'object' ? JSON : undefined, - '%Map%': typeof Map === 'undefined' ? undefined : Map, - '%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols ? undefined : getProto(new Map()[Symbol.iterator]()), - '%Math%': Math, - '%Number%': Number, - '%Object%': Object, - '%parseFloat%': parseFloat, - '%parseInt%': parseInt, - '%Promise%': typeof Promise === 'undefined' ? undefined : Promise, - '%Proxy%': typeof Proxy === 'undefined' ? undefined : Proxy, - '%RangeError%': RangeError, - '%ReferenceError%': ReferenceError, - '%Reflect%': typeof Reflect === 'undefined' ? undefined : Reflect, - '%RegExp%': RegExp, - '%Set%': typeof Set === 'undefined' ? undefined : Set, - '%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols ? undefined : getProto(new Set()[Symbol.iterator]()), - '%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer, - '%String%': String, - '%StringIteratorPrototype%': hasSymbols ? getProto(''[Symbol.iterator]()) : undefined, - '%Symbol%': hasSymbols ? Symbol : undefined, - '%SyntaxError%': $SyntaxError, - '%ThrowTypeError%': ThrowTypeError, - '%TypedArray%': TypedArray, - '%TypeError%': $TypeError, - '%Uint8Array%': typeof Uint8Array === 'undefined' ? undefined : Uint8Array, - '%Uint8ClampedArray%': typeof Uint8ClampedArray === 'undefined' ? undefined : Uint8ClampedArray, - '%Uint16Array%': typeof Uint16Array === 'undefined' ? undefined : Uint16Array, - '%Uint32Array%': typeof Uint32Array === 'undefined' ? undefined : Uint32Array, - '%URIError%': URIError, - '%WeakMap%': typeof WeakMap === 'undefined' ? undefined : WeakMap, - '%WeakRef%': typeof WeakRef === 'undefined' ? undefined : WeakRef, - '%WeakSet%': typeof WeakSet === 'undefined' ? undefined : WeakSet -}; - -var doEval = function doEval(name) { - var value; - if (name === '%AsyncFunction%') { - value = getEvalledConstructor('async function () {}'); - } else if (name === '%GeneratorFunction%') { - value = getEvalledConstructor('function* () {}'); - } else if (name === '%AsyncGeneratorFunction%') { - value = getEvalledConstructor('async function* () {}'); - } else if (name === '%AsyncGenerator%') { - var fn = doEval('%AsyncGeneratorFunction%'); - if (fn) { - value = fn.prototype; - } - } else if (name === '%AsyncIteratorPrototype%') { - var gen = doEval('%AsyncGenerator%'); - if (gen) { - value = getProto(gen.prototype); - } - } - - INTRINSICS[name] = value; - - return value; -}; - -var LEGACY_ALIASES = { - '%ArrayBufferPrototype%': ['ArrayBuffer', 'prototype'], - '%ArrayPrototype%': ['Array', 'prototype'], - '%ArrayProto_entries%': ['Array', 'prototype', 'entries'], - '%ArrayProto_forEach%': ['Array', 'prototype', 'forEach'], - '%ArrayProto_keys%': ['Array', 'prototype', 'keys'], - '%ArrayProto_values%': ['Array', 'prototype', 'values'], - '%AsyncFunctionPrototype%': ['AsyncFunction', 'prototype'], - '%AsyncGenerator%': ['AsyncGeneratorFunction', 'prototype'], - '%AsyncGeneratorPrototype%': ['AsyncGeneratorFunction', 'prototype', 'prototype'], - '%BooleanPrototype%': ['Boolean', 'prototype'], - '%DataViewPrototype%': ['DataView', 'prototype'], - '%DatePrototype%': ['Date', 'prototype'], - '%ErrorPrototype%': ['Error', 'prototype'], - '%EvalErrorPrototype%': ['EvalError', 'prototype'], - '%Float32ArrayPrototype%': ['Float32Array', 'prototype'], - '%Float64ArrayPrototype%': ['Float64Array', 'prototype'], - '%FunctionPrototype%': ['Function', 'prototype'], - '%Generator%': ['GeneratorFunction', 'prototype'], - '%GeneratorPrototype%': ['GeneratorFunction', 'prototype', 'prototype'], - '%Int8ArrayPrototype%': ['Int8Array', 'prototype'], - '%Int16ArrayPrototype%': ['Int16Array', 'prototype'], - '%Int32ArrayPrototype%': ['Int32Array', 'prototype'], - '%JSONParse%': ['JSON', 'parse'], - '%JSONStringify%': ['JSON', 'stringify'], - '%MapPrototype%': ['Map', 'prototype'], - '%NumberPrototype%': ['Number', 'prototype'], - '%ObjectPrototype%': ['Object', 'prototype'], - '%ObjProto_toString%': ['Object', 'prototype', 'toString'], - '%ObjProto_valueOf%': ['Object', 'prototype', 'valueOf'], - '%PromisePrototype%': ['Promise', 'prototype'], - '%PromiseProto_then%': ['Promise', 'prototype', 'then'], - '%Promise_all%': ['Promise', 'all'], - '%Promise_reject%': ['Promise', 'reject'], - '%Promise_resolve%': ['Promise', 'resolve'], - '%RangeErrorPrototype%': ['RangeError', 'prototype'], - '%ReferenceErrorPrototype%': ['ReferenceError', 'prototype'], - '%RegExpPrototype%': ['RegExp', 'prototype'], - '%SetPrototype%': ['Set', 'prototype'], - '%SharedArrayBufferPrototype%': ['SharedArrayBuffer', 'prototype'], - '%StringPrototype%': ['String', 'prototype'], - '%SymbolPrototype%': ['Symbol', 'prototype'], - '%SyntaxErrorPrototype%': ['SyntaxError', 'prototype'], - '%TypedArrayPrototype%': ['TypedArray', 'prototype'], - '%TypeErrorPrototype%': ['TypeError', 'prototype'], - '%Uint8ArrayPrototype%': ['Uint8Array', 'prototype'], - '%Uint8ClampedArrayPrototype%': ['Uint8ClampedArray', 'prototype'], - '%Uint16ArrayPrototype%': ['Uint16Array', 'prototype'], - '%Uint32ArrayPrototype%': ['Uint32Array', 'prototype'], - '%URIErrorPrototype%': ['URIError', 'prototype'], - '%WeakMapPrototype%': ['WeakMap', 'prototype'], - '%WeakSetPrototype%': ['WeakSet', 'prototype'] -}; - -var bind = require('function-bind'); -var hasOwn = require('has'); -var $concat = bind.call(Function.call, Array.prototype.concat); -var $spliceApply = bind.call(Function.apply, Array.prototype.splice); -var $replace = bind.call(Function.call, String.prototype.replace); -var $strSlice = bind.call(Function.call, String.prototype.slice); - -/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */ -var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g; -var reEscapeChar = /\\(\\)?/g; /** Used to match backslashes in property paths. */ -var stringToPath = function stringToPath(string) { - var first = $strSlice(string, 0, 1); - var last = $strSlice(string, -1); - if (first === '%' && last !== '%') { - throw new $SyntaxError('invalid intrinsic syntax, expected closing `%`'); - } else if (last === '%' && first !== '%') { - throw new $SyntaxError('invalid intrinsic syntax, expected opening `%`'); - } - var result = []; - $replace(string, rePropName, function (match, number, quote, subString) { - result[result.length] = quote ? $replace(subString, reEscapeChar, '$1') : number || match; - }); - return result; -}; -/* end adaptation */ - -var getBaseIntrinsic = function getBaseIntrinsic(name, allowMissing) { - var intrinsicName = name; - var alias; - if (hasOwn(LEGACY_ALIASES, intrinsicName)) { - alias = LEGACY_ALIASES[intrinsicName]; - intrinsicName = '%' + alias[0] + '%'; - } - - if (hasOwn(INTRINSICS, intrinsicName)) { - var value = INTRINSICS[intrinsicName]; - if (value === needsEval) { - value = doEval(intrinsicName); - } - if (typeof value === 'undefined' && !allowMissing) { - throw new $TypeError('intrinsic ' + name + ' exists, but is not available. Please file an issue!'); - } - - return { - alias: alias, - name: intrinsicName, - value: value - }; - } - - throw new $SyntaxError('intrinsic ' + name + ' does not exist!'); -}; - -module.exports = function GetIntrinsic(name, allowMissing) { - if (typeof name !== 'string' || name.length === 0) { - throw new $TypeError('intrinsic name must be a non-empty string'); - } - if (arguments.length > 1 && typeof allowMissing !== 'boolean') { - throw new $TypeError('"allowMissing" argument must be a boolean'); - } - - var parts = stringToPath(name); - var intrinsicBaseName = parts.length > 0 ? parts[0] : ''; - - var intrinsic = getBaseIntrinsic('%' + intrinsicBaseName + '%', allowMissing); - var intrinsicRealName = intrinsic.name; - var value = intrinsic.value; - var skipFurtherCaching = false; - - var alias = intrinsic.alias; - if (alias) { - intrinsicBaseName = alias[0]; - $spliceApply(parts, $concat([0, 1], alias)); - } - - for (var i = 1, isOwn = true; i < parts.length; i += 1) { - var part = parts[i]; - var first = $strSlice(part, 0, 1); - var last = $strSlice(part, -1); - if ( - ( - (first === '"' || first === "'" || first === '`') - || (last === '"' || last === "'" || last === '`') - ) - && first !== last - ) { - throw new $SyntaxError('property names with quotes must have matching quotes'); - } - if (part === 'constructor' || !isOwn) { - skipFurtherCaching = true; - } - - intrinsicBaseName += '.' + part; - intrinsicRealName = '%' + intrinsicBaseName + '%'; - - if (hasOwn(INTRINSICS, intrinsicRealName)) { - value = INTRINSICS[intrinsicRealName]; - } else if (value != null) { - if (!(part in value)) { - if (!allowMissing) { - throw new $TypeError('base intrinsic for ' + name + ' exists, but the property is not available.'); - } - return void undefined; - } - if ($gOPD && (i + 1) >= parts.length) { - var desc = $gOPD(value, part); - isOwn = !!desc; - - // By convention, when a data property is converted to an accessor - // property to emulate a data property that does not suffer from - // the override mistake, that accessor's getter is marked with - // an `originalValue` property. Here, when we detect this, we - // uphold the illusion by pretending to see that original data - // property, i.e., returning the value rather than the getter - // itself. - if (isOwn && 'get' in desc && !('originalValue' in desc.get)) { - value = desc.get; - } else { - value = value[part]; - } - } else { - isOwn = hasOwn(value, part); - value = value[part]; - } - - if (isOwn && !skipFurtherCaching) { - INTRINSICS[intrinsicRealName] = value; - } - } - } - return value; -}; - -},{"function-bind":10,"has":14,"has-symbols":12}],12:[function(require,module,exports){ -'use strict'; - -var origSymbol = typeof Symbol !== 'undefined' && Symbol; -var hasSymbolSham = require('./shams'); - -module.exports = function hasNativeSymbols() { - if (typeof origSymbol !== 'function') { return false; } - if (typeof Symbol !== 'function') { return false; } - if (typeof origSymbol('foo') !== 'symbol') { return false; } - if (typeof Symbol('bar') !== 'symbol') { return false; } - - return hasSymbolSham(); -}; - -},{"./shams":13}],13:[function(require,module,exports){ -'use strict'; - -/* eslint complexity: [2, 18], max-statements: [2, 33] */ -module.exports = function hasSymbols() { - if (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; } - if (typeof Symbol.iterator === 'symbol') { return true; } - - var obj = {}; - var sym = Symbol('test'); - var symObj = Object(sym); - if (typeof sym === 'string') { return false; } - - if (Object.prototype.toString.call(sym) !== '[object Symbol]') { return false; } - if (Object.prototype.toString.call(symObj) !== '[object Symbol]') { return false; } - - // temp disabled per https://github.com/ljharb/object.assign/issues/17 - // if (sym instanceof Symbol) { return false; } - // temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4 - // if (!(symObj instanceof Symbol)) { return false; } - - // if (typeof Symbol.prototype.toString !== 'function') { return false; } - // if (String(sym) !== Symbol.prototype.toString.call(sym)) { return false; } - - var symVal = 42; - obj[sym] = symVal; - for (sym in obj) { return false; } // eslint-disable-line no-restricted-syntax, no-unreachable-loop - if (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; } - - if (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; } - - var syms = Object.getOwnPropertySymbols(obj); - if (syms.length !== 1 || syms[0] !== sym) { return false; } - - if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; } - - if (typeof Object.getOwnPropertyDescriptor === 'function') { - var descriptor = Object.getOwnPropertyDescriptor(obj, sym); - if (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; } - } - - return true; -}; - -},{}],14:[function(require,module,exports){ -'use strict'; - -var bind = require('function-bind'); - -module.exports = bind.call(Function.call, Object.prototype.hasOwnProperty); - -},{"function-bind":10}],15:[function(require,module,exports){ -var hasMap = typeof Map === 'function' && Map.prototype; -var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null; -var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === 'function' ? mapSizeDescriptor.get : null; -var mapForEach = hasMap && Map.prototype.forEach; -var hasSet = typeof Set === 'function' && Set.prototype; -var setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, 'size') : null; -var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === 'function' ? setSizeDescriptor.get : null; -var setForEach = hasSet && Set.prototype.forEach; -var hasWeakMap = typeof WeakMap === 'function' && WeakMap.prototype; -var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null; -var hasWeakSet = typeof WeakSet === 'function' && WeakSet.prototype; -var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null; -var hasWeakRef = typeof WeakRef === 'function' && WeakRef.prototype; -var weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null; -var booleanValueOf = Boolean.prototype.valueOf; -var objectToString = Object.prototype.toString; -var functionToString = Function.prototype.toString; -var $match = String.prototype.match; -var $slice = String.prototype.slice; -var $replace = String.prototype.replace; -var $toUpperCase = String.prototype.toUpperCase; -var $toLowerCase = String.prototype.toLowerCase; -var $test = RegExp.prototype.test; -var $concat = Array.prototype.concat; -var $join = Array.prototype.join; -var $arrSlice = Array.prototype.slice; -var $floor = Math.floor; -var bigIntValueOf = typeof BigInt === 'function' ? BigInt.prototype.valueOf : null; -var gOPS = Object.getOwnPropertySymbols; -var symToString = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? Symbol.prototype.toString : null; -var hasShammedSymbols = typeof Symbol === 'function' && typeof Symbol.iterator === 'object'; -// ie, `has-tostringtag/shams -var toStringTag = typeof Symbol === 'function' && Symbol.toStringTag && (typeof Symbol.toStringTag === hasShammedSymbols ? 'object' : 'symbol') - ? Symbol.toStringTag - : null; -var isEnumerable = Object.prototype.propertyIsEnumerable; - -var gPO = (typeof Reflect === 'function' ? Reflect.getPrototypeOf : Object.getPrototypeOf) || ( - [].__proto__ === Array.prototype // eslint-disable-line no-proto - ? function (O) { - return O.__proto__; // eslint-disable-line no-proto - } - : null -); - -function addNumericSeparator(num, str) { - if ( - num === Infinity - || num === -Infinity - || num !== num - || (num && num > -1000 && num < 1000) - || $test.call(/e/, str) - ) { - return str; - } - var sepRegex = /[0-9](?=(?:[0-9]{3})+(?![0-9]))/g; - if (typeof num === 'number') { - var int = num < 0 ? -$floor(-num) : $floor(num); // trunc(num) - if (int !== num) { - var intStr = String(int); - var dec = $slice.call(str, intStr.length + 1); - return $replace.call(intStr, sepRegex, '$&_') + '.' + $replace.call($replace.call(dec, /([0-9]{3})/g, '$&_'), /_$/, ''); - } - } - return $replace.call(str, sepRegex, '$&_'); -} - -var inspectCustom = require('./util.inspect').custom; -var inspectSymbol = inspectCustom && isSymbol(inspectCustom) ? inspectCustom : null; - -module.exports = function inspect_(obj, options, depth, seen) { - var opts = options || {}; - - if (has(opts, 'quoteStyle') && (opts.quoteStyle !== 'single' && opts.quoteStyle !== 'double')) { - throw new TypeError('option "quoteStyle" must be "single" or "double"'); - } - if ( - has(opts, 'maxStringLength') && (typeof opts.maxStringLength === 'number' - ? opts.maxStringLength < 0 && opts.maxStringLength !== Infinity - : opts.maxStringLength !== null - ) - ) { - throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`'); - } - var customInspect = has(opts, 'customInspect') ? opts.customInspect : true; - if (typeof customInspect !== 'boolean' && customInspect !== 'symbol') { - throw new TypeError('option "customInspect", if provided, must be `true`, `false`, or `\'symbol\'`'); - } - - if ( - has(opts, 'indent') - && opts.indent !== null - && opts.indent !== '\t' - && !(parseInt(opts.indent, 10) === opts.indent && opts.indent > 0) - ) { - throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`'); - } - if (has(opts, 'numericSeparator') && typeof opts.numericSeparator !== 'boolean') { - throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`'); - } - var numericSeparator = opts.numericSeparator; - - if (typeof obj === 'undefined') { - return 'undefined'; - } - if (obj === null) { - return 'null'; - } - if (typeof obj === 'boolean') { - return obj ? 'true' : 'false'; - } - - if (typeof obj === 'string') { - return inspectString(obj, opts); - } - if (typeof obj === 'number') { - if (obj === 0) { - return Infinity / obj > 0 ? '0' : '-0'; - } - var str = String(obj); - return numericSeparator ? addNumericSeparator(obj, str) : str; - } - if (typeof obj === 'bigint') { - var bigIntStr = String(obj) + 'n'; - return numericSeparator ? addNumericSeparator(obj, bigIntStr) : bigIntStr; - } - - var maxDepth = typeof opts.depth === 'undefined' ? 5 : opts.depth; - if (typeof depth === 'undefined') { depth = 0; } - if (depth >= maxDepth && maxDepth > 0 && typeof obj === 'object') { - return isArray(obj) ? '[Array]' : '[Object]'; - } - - var indent = getIndent(opts, depth); - - if (typeof seen === 'undefined') { - seen = []; - } else if (indexOf(seen, obj) >= 0) { - return '[Circular]'; - } - - function inspect(value, from, noIndent) { - if (from) { - seen = $arrSlice.call(seen); - seen.push(from); - } - if (noIndent) { - var newOpts = { - depth: opts.depth - }; - if (has(opts, 'quoteStyle')) { - newOpts.quoteStyle = opts.quoteStyle; - } - return inspect_(value, newOpts, depth + 1, seen); - } - return inspect_(value, opts, depth + 1, seen); - } +"use strict";var bind=require(24),$TypeError=require(20),$call=require(9),$actualApply=require(7);module.exports=function callBindBasic(r){if(r.length<1||"function"!=typeof r[0])throw new $TypeError("a function is required");return $actualApply(bind,$call,r)}; - if (typeof obj === 'function') { - var name = nameOf(obj); - var keys = arrObjKeys(obj, inspect); - return '[Function' + (name ? ': ' + name : ' (anonymous)') + ']' + (keys.length > 0 ? ' { ' + $join.call(keys, ', ') + ' }' : ''); - } - if (isSymbol(obj)) { - var symString = hasShammedSymbols ? $replace.call(String(obj), /^(Symbol\(.*\))_[^)]*$/, '$1') : symToString.call(obj); - return typeof obj === 'object' && !hasShammedSymbols ? markBoxed(symString) : symString; - } - if (isElement(obj)) { - var s = '<' + $toLowerCase.call(String(obj.nodeName)); - var attrs = obj.attributes || []; - for (var i = 0; i < attrs.length; i++) { - s += ' ' + attrs[i].name + '=' + wrapQuotes(quote(attrs[i].value), 'double', opts); - } - s += '>'; - if (obj.childNodes && obj.childNodes.length) { s += '...'; } - s += ''; - return s; - } - if (isArray(obj)) { - if (obj.length === 0) { return '[]'; } - var xs = arrObjKeys(obj, inspect); - if (indent && !singleLineValues(xs)) { - return '[' + indentedJoin(xs, indent) + ']'; - } - return '[ ' + $join.call(xs, ', ') + ' ]'; - } - if (isError(obj)) { - var parts = arrObjKeys(obj, inspect); - if ('cause' in obj && !isEnumerable.call(obj, 'cause')) { - return '{ [' + String(obj) + '] ' + $join.call($concat.call('[cause]: ' + inspect(obj.cause), parts), ', ') + ' }'; - } - if (parts.length === 0) { return '[' + String(obj) + ']'; } - return '{ [' + String(obj) + '] ' + $join.call(parts, ', ') + ' }'; - } - if (typeof obj === 'object' && customInspect) { - if (inspectSymbol && typeof obj[inspectSymbol] === 'function') { - return obj[inspectSymbol](); - } else if (customInspect !== 'symbol' && typeof obj.inspect === 'function') { - return obj.inspect(); - } - } - if (isMap(obj)) { - var mapParts = []; - mapForEach.call(obj, function (value, key) { - mapParts.push(inspect(key, obj, true) + ' => ' + inspect(value, obj)); - }); - return collectionOf('Map', mapSize.call(obj), mapParts, indent); - } - if (isSet(obj)) { - var setParts = []; - setForEach.call(obj, function (value) { - setParts.push(inspect(value, obj)); - }); - return collectionOf('Set', setSize.call(obj), setParts, indent); - } - if (isWeakMap(obj)) { - return weakCollectionOf('WeakMap'); - } - if (isWeakSet(obj)) { - return weakCollectionOf('WeakSet'); - } - if (isWeakRef(obj)) { - return weakCollectionOf('WeakRef'); - } - if (isNumber(obj)) { - return markBoxed(inspect(Number(obj))); - } - if (isBigInt(obj)) { - return markBoxed(inspect(bigIntValueOf.call(obj))); - } - if (isBoolean(obj)) { - return markBoxed(booleanValueOf.call(obj)); - } - if (isString(obj)) { - return markBoxed(inspect(String(obj))); - } - if (!isDate(obj) && !isRegExp(obj)) { - var ys = arrObjKeys(obj, inspect); - var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object; - var protoTag = obj instanceof Object ? '' : 'null prototype'; - var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? 'Object' : ''; - var constructorTag = isPlainObject || typeof obj.constructor !== 'function' ? '' : obj.constructor.name ? obj.constructor.name + ' ' : ''; - var tag = constructorTag + (stringTag || protoTag ? '[' + $join.call($concat.call([], stringTag || [], protoTag || []), ': ') + '] ' : ''); - if (ys.length === 0) { return tag + '{}'; } - if (indent) { - return tag + '{' + indentedJoin(ys, indent) + '}'; - } - return tag + '{ ' + $join.call(ys, ', ') + ' }'; - } - return String(obj); -}; +},{"20":20,"24":24,"7":7,"9":9}],20:[function(require,module,exports){ +"use strict";module.exports=TypeError; -function wrapQuotes(s, defaultStyle, opts) { - var quoteChar = (opts.quoteStyle || defaultStyle) === 'double' ? '"' : "'"; - return quoteChar + s + quoteChar; -} +},{}],12:[function(require,module,exports){ +"use strict";var GetIntrinsic=require(25),callBindBasic=require(10),$indexOf=callBindBasic([GetIntrinsic("%String.prototype.indexOf%")]);module.exports=function callBoundIntrinsic(i,n){var t=GetIntrinsic(i,!!n);return"function"==typeof t&&$indexOf(i,".prototype.")>-1?callBindBasic([t]):t}; -function quote(s) { - return $replace.call(String(s), /"/g, '"'); -} +},{"10":10,"25":25}],25:[function(require,module,exports){ +"use strict";var undefined,$Object=require(22),$Error=require(16),$EvalError=require(15),$RangeError=require(17),$ReferenceError=require(18),$SyntaxError=require(19),$TypeError=require(20),$URIError=require(21),abs=require(34),floor=require(35),max=require(37),min=require(38),pow=require(39),round=require(40),sign=require(41),$Function=Function,getEvalledConstructor=function(r){try{return $Function('"use strict"; return ('+r+").constructor;")()}catch(r){}},$gOPD=require(30),$defineProperty=require(14),throwTypeError=function(){throw new $TypeError},ThrowTypeError=$gOPD?function(){try{return throwTypeError}catch(r){try{return $gOPD(arguments,"callee").get}catch(r){return throwTypeError}}}():throwTypeError,hasSymbols=require(31)(),getProto=require(28),$ObjectGPO=require(26),$ReflectGPO=require(27),$apply=require(8),$call=require(9),needsEval={},TypedArray="undefined"!=typeof Uint8Array&&getProto?getProto(Uint8Array):undefined,INTRINSICS={__proto__:null,"%AggregateError%":"undefined"==typeof AggregateError?undefined:AggregateError,"%Array%":Array,"%ArrayBuffer%":"undefined"==typeof ArrayBuffer?undefined:ArrayBuffer,"%ArrayIteratorPrototype%":hasSymbols&&getProto?getProto([][Symbol.iterator]()):undefined,"%AsyncFromSyncIteratorPrototype%":undefined,"%AsyncFunction%":needsEval,"%AsyncGenerator%":needsEval,"%AsyncGeneratorFunction%":needsEval,"%AsyncIteratorPrototype%":needsEval,"%Atomics%":"undefined"==typeof Atomics?undefined:Atomics,"%BigInt%":"undefined"==typeof BigInt?undefined:BigInt,"%BigInt64Array%":"undefined"==typeof BigInt64Array?undefined:BigInt64Array,"%BigUint64Array%":"undefined"==typeof BigUint64Array?undefined:BigUint64Array,"%Boolean%":Boolean,"%DataView%":"undefined"==typeof DataView?undefined:DataView,"%Date%":Date,"%decodeURI%":decodeURI,"%decodeURIComponent%":decodeURIComponent,"%encodeURI%":encodeURI,"%encodeURIComponent%":encodeURIComponent,"%Error%":$Error,"%eval%":eval,"%EvalError%":$EvalError,"%Float32Array%":"undefined"==typeof Float32Array?undefined:Float32Array,"%Float64Array%":"undefined"==typeof Float64Array?undefined:Float64Array,"%FinalizationRegistry%":"undefined"==typeof FinalizationRegistry?undefined:FinalizationRegistry,"%Function%":$Function,"%GeneratorFunction%":needsEval,"%Int8Array%":"undefined"==typeof Int8Array?undefined:Int8Array,"%Int16Array%":"undefined"==typeof Int16Array?undefined:Int16Array,"%Int32Array%":"undefined"==typeof Int32Array?undefined:Int32Array,"%isFinite%":isFinite,"%isNaN%":isNaN,"%IteratorPrototype%":hasSymbols&&getProto?getProto(getProto([][Symbol.iterator]())):undefined,"%JSON%":"object"==typeof JSON?JSON:undefined,"%Map%":"undefined"==typeof Map?undefined:Map,"%MapIteratorPrototype%":"undefined"!=typeof Map&&hasSymbols&&getProto?getProto((new Map)[Symbol.iterator]()):undefined,"%Math%":Math,"%Number%":Number,"%Object%":$Object,"%Object.getOwnPropertyDescriptor%":$gOPD,"%parseFloat%":parseFloat,"%parseInt%":parseInt,"%Promise%":"undefined"==typeof Promise?undefined:Promise,"%Proxy%":"undefined"==typeof Proxy?undefined:Proxy,"%RangeError%":$RangeError,"%ReferenceError%":$ReferenceError,"%Reflect%":"undefined"==typeof Reflect?undefined:Reflect,"%RegExp%":RegExp,"%Set%":"undefined"==typeof Set?undefined:Set,"%SetIteratorPrototype%":"undefined"!=typeof Set&&hasSymbols&&getProto?getProto((new Set)[Symbol.iterator]()):undefined,"%SharedArrayBuffer%":"undefined"==typeof SharedArrayBuffer?undefined:SharedArrayBuffer,"%String%":String,"%StringIteratorPrototype%":hasSymbols&&getProto?getProto(""[Symbol.iterator]()):undefined,"%Symbol%":hasSymbols?Symbol:undefined,"%SyntaxError%":$SyntaxError,"%ThrowTypeError%":ThrowTypeError,"%TypedArray%":TypedArray,"%TypeError%":$TypeError,"%Uint8Array%":"undefined"==typeof Uint8Array?undefined:Uint8Array,"%Uint8ClampedArray%":"undefined"==typeof Uint8ClampedArray?undefined:Uint8ClampedArray,"%Uint16Array%":"undefined"==typeof Uint16Array?undefined:Uint16Array,"%Uint32Array%":"undefined"==typeof Uint32Array?undefined:Uint32Array,"%URIError%":$URIError,"%WeakMap%":"undefined"==typeof WeakMap?undefined:WeakMap,"%WeakRef%":"undefined"==typeof WeakRef?undefined:WeakRef,"%WeakSet%":"undefined"==typeof WeakSet?undefined:WeakSet,"%Function.prototype.call%":$call,"%Function.prototype.apply%":$apply,"%Object.defineProperty%":$defineProperty,"%Object.getPrototypeOf%":$ObjectGPO,"%Math.abs%":abs,"%Math.floor%":floor,"%Math.max%":max,"%Math.min%":min,"%Math.pow%":pow,"%Math.round%":round,"%Math.sign%":sign,"%Reflect.getPrototypeOf%":$ReflectGPO};if(getProto)try{null.error}catch(r){var errorProto=getProto(getProto(r));INTRINSICS["%Error.prototype%"]=errorProto}var doEval=function doEval(r){var e;if("%AsyncFunction%"===r)e=getEvalledConstructor("async function () {}");else if("%GeneratorFunction%"===r)e=getEvalledConstructor("function* () {}");else if("%AsyncGeneratorFunction%"===r)e=getEvalledConstructor("async function* () {}");else if("%AsyncGenerator%"===r){var t=doEval("%AsyncGeneratorFunction%");t&&(e=t.prototype)}else if("%AsyncIteratorPrototype%"===r){var o=doEval("%AsyncGenerator%");o&&getProto&&(e=getProto(o.prototype))}return INTRINSICS[r]=e,e},LEGACY_ALIASES={__proto__:null,"%ArrayBufferPrototype%":["ArrayBuffer","prototype"],"%ArrayPrototype%":["Array","prototype"],"%ArrayProto_entries%":["Array","prototype","entries"],"%ArrayProto_forEach%":["Array","prototype","forEach"],"%ArrayProto_keys%":["Array","prototype","keys"],"%ArrayProto_values%":["Array","prototype","values"],"%AsyncFunctionPrototype%":["AsyncFunction","prototype"],"%AsyncGenerator%":["AsyncGeneratorFunction","prototype"],"%AsyncGeneratorPrototype%":["AsyncGeneratorFunction","prototype","prototype"],"%BooleanPrototype%":["Boolean","prototype"],"%DataViewPrototype%":["DataView","prototype"],"%DatePrototype%":["Date","prototype"],"%ErrorPrototype%":["Error","prototype"],"%EvalErrorPrototype%":["EvalError","prototype"],"%Float32ArrayPrototype%":["Float32Array","prototype"],"%Float64ArrayPrototype%":["Float64Array","prototype"],"%FunctionPrototype%":["Function","prototype"],"%Generator%":["GeneratorFunction","prototype"],"%GeneratorPrototype%":["GeneratorFunction","prototype","prototype"],"%Int8ArrayPrototype%":["Int8Array","prototype"],"%Int16ArrayPrototype%":["Int16Array","prototype"],"%Int32ArrayPrototype%":["Int32Array","prototype"],"%JSONParse%":["JSON","parse"],"%JSONStringify%":["JSON","stringify"],"%MapPrototype%":["Map","prototype"],"%NumberPrototype%":["Number","prototype"],"%ObjectPrototype%":["Object","prototype"],"%ObjProto_toString%":["Object","prototype","toString"],"%ObjProto_valueOf%":["Object","prototype","valueOf"],"%PromisePrototype%":["Promise","prototype"],"%PromiseProto_then%":["Promise","prototype","then"],"%Promise_all%":["Promise","all"],"%Promise_reject%":["Promise","reject"],"%Promise_resolve%":["Promise","resolve"],"%RangeErrorPrototype%":["RangeError","prototype"],"%ReferenceErrorPrototype%":["ReferenceError","prototype"],"%RegExpPrototype%":["RegExp","prototype"],"%SetPrototype%":["Set","prototype"],"%SharedArrayBufferPrototype%":["SharedArrayBuffer","prototype"],"%StringPrototype%":["String","prototype"],"%SymbolPrototype%":["Symbol","prototype"],"%SyntaxErrorPrototype%":["SyntaxError","prototype"],"%TypedArrayPrototype%":["TypedArray","prototype"],"%TypeErrorPrototype%":["TypeError","prototype"],"%Uint8ArrayPrototype%":["Uint8Array","prototype"],"%Uint8ClampedArrayPrototype%":["Uint8ClampedArray","prototype"],"%Uint16ArrayPrototype%":["Uint16Array","prototype"],"%Uint32ArrayPrototype%":["Uint32Array","prototype"],"%URIErrorPrototype%":["URIError","prototype"],"%WeakMapPrototype%":["WeakMap","prototype"],"%WeakSetPrototype%":["WeakSet","prototype"]},bind=require(24),hasOwn=require(33),$concat=bind.call($call,Array.prototype.concat),$spliceApply=bind.call($apply,Array.prototype.splice),$replace=bind.call($call,String.prototype.replace),$strSlice=bind.call($call,String.prototype.slice),$exec=bind.call($call,RegExp.prototype.exec),rePropName=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g,reEscapeChar=/\\(\\)?/g,stringToPath=function stringToPath(r){var e=$strSlice(r,0,1),t=$strSlice(r,-1);if("%"===e&&"%"!==t)throw new $SyntaxError("invalid intrinsic syntax, expected closing `%`");if("%"===t&&"%"!==e)throw new $SyntaxError("invalid intrinsic syntax, expected opening `%`");var o=[];return $replace(r,rePropName,(function(r,e,t,n){o[o.length]=t?$replace(n,reEscapeChar,"$1"):e||r})),o},getBaseIntrinsic=function getBaseIntrinsic(r,e){var t,o=r;if(hasOwn(LEGACY_ALIASES,o)&&(o="%"+(t=LEGACY_ALIASES[o])[0]+"%"),hasOwn(INTRINSICS,o)){var n=INTRINSICS[o];if(n===needsEval&&(n=doEval(o)),void 0===n&&!e)throw new $TypeError("intrinsic "+r+" exists, but is not available. Please file an issue!");return{alias:t,name:o,value:n}}throw new $SyntaxError("intrinsic "+r+" does not exist!")};module.exports=function GetIntrinsic(r,e){if("string"!=typeof r||0===r.length)throw new $TypeError("intrinsic name must be a non-empty string");if(arguments.length>1&&"boolean"!=typeof e)throw new $TypeError('"allowMissing" argument must be a boolean');if(null===$exec(/^%?[^%]*%?$/,r))throw new $SyntaxError("`%` may not be present anywhere but at the beginning and end of the intrinsic name");var t=stringToPath(r),o=t.length>0?t[0]:"",n=getBaseIntrinsic("%"+o+"%",e),a=n.name,i=n.value,y=!1,p=n.alias;p&&(o=p[0],$spliceApply(t,$concat([0,1],p)));for(var s=1,d=!0;s=t.length){var c=$gOPD(i,f);i=(d=!!c)&&"get"in c&&!("originalValue"in c.get)?c.get:i[f]}else d=hasOwn(i,f),i=i[f];d&&!y&&(INTRINSICS[a]=i)}}return i}; -function isArray(obj) { return toStr(obj) === '[object Array]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } -function isDate(obj) { return toStr(obj) === '[object Date]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } -function isRegExp(obj) { return toStr(obj) === '[object RegExp]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } -function isError(obj) { return toStr(obj) === '[object Error]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } -function isString(obj) { return toStr(obj) === '[object String]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } -function isNumber(obj) { return toStr(obj) === '[object Number]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } -function isBoolean(obj) { return toStr(obj) === '[object Boolean]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } +},{"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"24":24,"26":26,"27":27,"28":28,"30":30,"31":31,"33":33,"34":34,"35":35,"37":37,"38":38,"39":39,"40":40,"41":41,"8":8,"9":9}],13:[function(require,module,exports){ +"use strict";var hasProtoAccessor,callBind=require(10),gOPD=require(30);try{hasProtoAccessor=[].__proto__===Array.prototype}catch(t){if(!t||"object"!=typeof t||!("code"in t)||"ERR_PROTO_ACCESS"!==t.code)throw t}var desc=!!hasProtoAccessor&&gOPD&&gOPD(Object.prototype,"__proto__"),$Object=Object,$getPrototypeOf=$Object.getPrototypeOf;module.exports=desc&&"function"==typeof desc.get?callBind([desc.get]):"function"==typeof $getPrototypeOf&&function getDunder(t){return $getPrototypeOf(null==t?t:$Object(t))}; -// Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives -function isSymbol(obj) { - if (hasShammedSymbols) { - return obj && typeof obj === 'object' && obj instanceof Symbol; - } - if (typeof obj === 'symbol') { - return true; - } - if (!obj || typeof obj !== 'object' || !symToString) { - return false; - } - try { - symToString.call(obj); - return true; - } catch (e) {} - return false; -} +},{"10":10,"30":30}],30:[function(require,module,exports){ +"use strict";var $gOPD=require(29);if($gOPD)try{$gOPD([],"length")}catch(g){$gOPD=null}module.exports=$gOPD; -function isBigInt(obj) { - if (!obj || typeof obj !== 'object' || !bigIntValueOf) { - return false; - } - try { - bigIntValueOf.call(obj); - return true; - } catch (e) {} - return false; -} +},{"29":29}],14:[function(require,module,exports){ +"use strict";var $defineProperty=Object.defineProperty||!1;if($defineProperty)try{$defineProperty({},"a",{value:1})}catch(e){$defineProperty=!1}module.exports=$defineProperty; -var hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; }; -function has(obj, key) { - return hasOwn.call(obj, key); -} +},{}],15:[function(require,module,exports){ +"use strict";module.exports=EvalError; -function toStr(obj) { - return objectToString.call(obj); -} +},{}],16:[function(require,module,exports){ +"use strict";module.exports=Error; -function nameOf(f) { - if (f.name) { return f.name; } - var m = $match.call(functionToString.call(f), /^function\s*([\w$]+)/); - if (m) { return m[1]; } - return null; -} +},{}],17:[function(require,module,exports){ +"use strict";module.exports=RangeError; -function indexOf(xs, x) { - if (xs.indexOf) { return xs.indexOf(x); } - for (var i = 0, l = xs.length; i < l; i++) { - if (xs[i] === x) { return i; } - } - return -1; -} +},{}],18:[function(require,module,exports){ +"use strict";module.exports=ReferenceError; -function isMap(x) { - if (!mapSize || !x || typeof x !== 'object') { - return false; - } - try { - mapSize.call(x); - try { - setSize.call(x); - } catch (s) { - return true; - } - return x instanceof Map; // core-js workaround, pre-v2.5.0 - } catch (e) {} - return false; -} +},{}],19:[function(require,module,exports){ +"use strict";module.exports=SyntaxError; -function isWeakMap(x) { - if (!weakMapHas || !x || typeof x !== 'object') { - return false; - } - try { - weakMapHas.call(x, weakMapHas); - try { - weakSetHas.call(x, weakSetHas); - } catch (s) { - return true; - } - return x instanceof WeakMap; // core-js workaround, pre-v2.5.0 - } catch (e) {} - return false; -} +},{}],21:[function(require,module,exports){ +"use strict";module.exports=URIError; -function isWeakRef(x) { - if (!weakRefDeref || !x || typeof x !== 'object') { - return false; - } - try { - weakRefDeref.call(x); - return true; - } catch (e) {} - return false; -} +},{}],22:[function(require,module,exports){ +"use strict";module.exports=Object; -function isSet(x) { - if (!setSize || !x || typeof x !== 'object') { - return false; - } - try { - setSize.call(x); - try { - mapSize.call(x); - } catch (m) { - return true; - } - return x instanceof Set; // core-js workaround, pre-v2.5.0 - } catch (e) {} - return false; -} +},{}],23:[function(require,module,exports){ +"use strict";var ERROR_MESSAGE="Function.prototype.bind called on incompatible ",toStr=Object.prototype.toString,max=Math.max,funcType="[object Function]",concatty=function concatty(t,n){for(var r=[],o=0;o opts.maxStringLength) { - var remaining = str.length - opts.maxStringLength; - var trailer = '... ' + remaining + ' more character' + (remaining > 1 ? 's' : ''); - return inspectString($slice.call(str, 0, opts.maxStringLength), opts) + trailer; - } - // eslint-disable-next-line no-control-regex - var s = $replace.call($replace.call(str, /(['\\])/g, '\\$1'), /[\x00-\x1f]/g, lowbyte); - return wrapQuotes(s, 'single', opts); -} +},{}],39:[function(require,module,exports){ +"use strict";module.exports=Math.pow; -function lowbyte(c) { - var n = c.charCodeAt(0); - var x = { - 8: 'b', - 9: 't', - 10: 'n', - 12: 'f', - 13: 'r' - }[n]; - if (x) { return '\\' + x; } - return '\\x' + (n < 0x10 ? '0' : '') + $toUpperCase.call(n.toString(16)); -} +},{}],34:[function(require,module,exports){ +"use strict";module.exports=Math.abs; -function markBoxed(str) { - return 'Object(' + str + ')'; -} +},{}],40:[function(require,module,exports){ +"use strict";module.exports=Math.round; -function weakCollectionOf(type) { - return type + ' { ? }'; -} +},{}],38:[function(require,module,exports){ +"use strict";module.exports=Math.min; -function collectionOf(type, size, entries, indent) { - var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ', '); - return type + ' (' + size + ') {' + joinedEntries + '}'; -} +},{}],27:[function(require,module,exports){ +"use strict";module.exports="undefined"!=typeof Reflect&&Reflect.getPrototypeOf||null; -function singleLineValues(xs) { - for (var i = 0; i < xs.length; i++) { - if (indexOf(xs[i], '\n') >= 0) { - return false; - } - } - return true; -} +},{}],26:[function(require,module,exports){ +"use strict";var $Object=require(22);module.exports=$Object.getPrototypeOf||null; -function getIndent(opts, depth) { - var baseIndent; - if (opts.indent === '\t') { - baseIndent = '\t'; - } else if (typeof opts.indent === 'number' && opts.indent > 0) { - baseIndent = $join.call(Array(opts.indent + 1), ' '); - } else { - return null; - } - return { - base: baseIndent, - prev: $join.call(Array(depth + 1), baseIndent) - }; -} +},{"22":22}],33:[function(require,module,exports){ +"use strict";var call=Function.prototype.call,$hasOwn=Object.prototype.hasOwnProperty,bind=require(24);module.exports=bind.call(call,$hasOwn); -function indentedJoin(xs, indent) { - if (xs.length === 0) { return ''; } - var lineJoiner = '\n' + indent.prev + indent.base; - return lineJoiner + $join.call(xs, ',' + lineJoiner) + '\n' + indent.prev; -} +},{"24":24}],41:[function(require,module,exports){ +"use strict";var $isNaN=require(36);module.exports=function sign(i){return $isNaN(i)||0===i?i:i<0?-1:1}; -function arrObjKeys(obj, inspect) { - var isArr = isArray(obj); - var xs = []; - if (isArr) { - xs.length = obj.length; - for (var i = 0; i < obj.length; i++) { - xs[i] = has(obj, i) ? inspect(obj[i], obj) : ''; - } - } - var syms = typeof gOPS === 'function' ? gOPS(obj) : []; - var symMap; - if (hasShammedSymbols) { - symMap = {}; - for (var k = 0; k < syms.length; k++) { - symMap['$' + syms[k]] = syms[k]; - } - } +},{"36":36}],31:[function(require,module,exports){ +"use strict";var origSymbol="undefined"!=typeof Symbol&&Symbol,hasSymbolSham=require(32);module.exports=function hasNativeSymbols(){return"function"==typeof origSymbol&&"function"==typeof Symbol&&"symbol"==typeof origSymbol("foo")&&"symbol"==typeof Symbol("bar")&&hasSymbolSham()}; - for (var key in obj) { // eslint-disable-line no-restricted-syntax - if (!has(obj, key)) { continue; } // eslint-disable-line no-restricted-syntax, no-continue - if (isArr && String(Number(key)) === key && key < obj.length) { continue; } // eslint-disable-line no-restricted-syntax, no-continue - if (hasShammedSymbols && symMap['$' + key] instanceof Symbol) { - // this is to prevent shammed Symbols, which are stored as strings, from being included in the string key section - continue; // eslint-disable-line no-restricted-syntax, no-continue - } else if ($test.call(/[^\w$]/, key)) { - xs.push(inspect(key, obj) + ': ' + inspect(obj[key], obj)); - } else { - xs.push(key + ': ' + inspect(obj[key], obj)); - } - } - if (typeof gOPS === 'function') { - for (var j = 0; j < syms.length; j++) { - if (isEnumerable.call(obj, syms[j])) { - xs.push('[' + inspect(syms[j]) + ']: ' + inspect(obj[syms[j]], obj)); - } - } - } - return xs; -} +},{"32":32}],28:[function(require,module,exports){ +"use strict";var reflectGetProto=require(27),originalGetProto=require(26),getDunderProto=require(13);module.exports=reflectGetProto?function getProto(t){return reflectGetProto(t)}:originalGetProto?function getProto(t){if(!t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("getProto: not an object");return originalGetProto(t)}:getDunderProto?function getProto(t){return getDunderProto(t)}:null; -},{"./util.inspect":6}],16:[function(require,module,exports){ -'use strict'; +},{"13":13,"26":26,"27":27}],29:[function(require,module,exports){ +"use strict";module.exports=Object.getOwnPropertyDescriptor; -var GetIntrinsic = require('get-intrinsic'); -var callBound = require('call-bind/callBound'); -var inspect = require('object-inspect'); +},{}],32:[function(require,module,exports){ +"use strict";module.exports=function hasSymbols(){if("function"!=typeof Symbol||"function"!=typeof Object.getOwnPropertySymbols)return!1;if("symbol"==typeof Symbol.iterator)return!0;var t={},e=Symbol("test"),r=Object(e);if("string"==typeof e)return!1;if("[object Symbol]"!==Object.prototype.toString.call(e))return!1;if("[object Symbol]"!==Object.prototype.toString.call(r))return!1;for(var o in t[e]=42,t)return!1;if("function"==typeof Object.keys&&0!==Object.keys(t).length)return!1;if("function"==typeof Object.getOwnPropertyNames&&0!==Object.getOwnPropertyNames(t).length)return!1;var n=Object.getOwnPropertySymbols(t);if(1!==n.length||n[0]!==e)return!1;if(!Object.prototype.propertyIsEnumerable.call(t,e))return!1;if("function"==typeof Object.getOwnPropertyDescriptor){var y=Object.getOwnPropertyDescriptor(t,e);if(42!==y.value||!0!==y.enumerable)return!1}return!0}; -var $TypeError = GetIntrinsic('%TypeError%'); -var $WeakMap = GetIntrinsic('%WeakMap%', true); -var $Map = GetIntrinsic('%Map%', true); +},{}],36:[function(require,module,exports){ +"use strict";module.exports=Number.isNaN||function isNaN(e){return e!=e}; -var $weakMapGet = callBound('WeakMap.prototype.get', true); -var $weakMapSet = callBound('WeakMap.prototype.set', true); -var $weakMapHas = callBound('WeakMap.prototype.has', true); -var $mapGet = callBound('Map.prototype.get', true); -var $mapSet = callBound('Map.prototype.set', true); -var $mapHas = callBound('Map.prototype.has', true); +},{}],42:[function(require,module,exports){ +(function (global){(function (){ +var hasMap="function"==typeof Map&&Map.prototype,mapSizeDescriptor=Object.getOwnPropertyDescriptor&&hasMap?Object.getOwnPropertyDescriptor(Map.prototype,"size"):null,mapSize=hasMap&&mapSizeDescriptor&&"function"==typeof mapSizeDescriptor.get?mapSizeDescriptor.get:null,mapForEach=hasMap&&Map.prototype.forEach,hasSet="function"==typeof Set&&Set.prototype,setSizeDescriptor=Object.getOwnPropertyDescriptor&&hasSet?Object.getOwnPropertyDescriptor(Set.prototype,"size"):null,setSize=hasSet&&setSizeDescriptor&&"function"==typeof setSizeDescriptor.get?setSizeDescriptor.get:null,setForEach=hasSet&&Set.prototype.forEach,hasWeakMap="function"==typeof WeakMap&&WeakMap.prototype,weakMapHas=hasWeakMap?WeakMap.prototype.has:null,hasWeakSet="function"==typeof WeakSet&&WeakSet.prototype,weakSetHas=hasWeakSet?WeakSet.prototype.has:null,hasWeakRef="function"==typeof WeakRef&&WeakRef.prototype,weakRefDeref=hasWeakRef?WeakRef.prototype.deref:null,booleanValueOf=Boolean.prototype.valueOf,objectToString=Object.prototype.toString,functionToString=Function.prototype.toString,$match=String.prototype.match,$slice=String.prototype.slice,$replace=String.prototype.replace,$toUpperCase=String.prototype.toUpperCase,$toLowerCase=String.prototype.toLowerCase,$test=RegExp.prototype.test,$concat=Array.prototype.concat,$join=Array.prototype.join,$arrSlice=Array.prototype.slice,$floor=Math.floor,bigIntValueOf="function"==typeof BigInt?BigInt.prototype.valueOf:null,gOPS=Object.getOwnPropertySymbols,symToString="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?Symbol.prototype.toString:null,hasShammedSymbols="function"==typeof Symbol&&"object"==typeof Symbol.iterator,toStringTag="function"==typeof Symbol&&Symbol.toStringTag&&(Symbol.toStringTag,1)?Symbol.toStringTag:null,isEnumerable=Object.prototype.propertyIsEnumerable,gPO=("function"==typeof Reflect?Reflect.getPrototypeOf:Object.getPrototypeOf)||([].__proto__===Array.prototype?function(t){return t.__proto__}:null);function addNumericSeparator(t,e){if(t===1/0||t===-1/0||t!=t||t&&t>-1e3&&t<1e3||$test.call(/e/,e))return e;var r=/[0-9](?=(?:[0-9]{3})+(?![0-9]))/g;if("number"==typeof t){var n=t<0?-$floor(-t):$floor(t);if(n!==t){var o=String(n),i=$slice.call(e,o.length+1);return $replace.call(o,r,"$&_")+"."+$replace.call($replace.call(i,/([0-9]{3})/g,"$&_"),/_$/,"")}}return $replace.call(e,r,"$&_")}var utilInspect=require(6),inspectCustom=utilInspect.custom,inspectSymbol=isSymbol(inspectCustom)?inspectCustom:null,quotes={__proto__:null,double:'"',single:"'"},quoteREs={__proto__:null,double:/(["\\])/g,single:/(['\\])/g};function wrapQuotes(t,e,r){var n=r.quoteStyle||e,o=quotes[n];return o+t+o}function quote(t){return $replace.call(String(t),/"/g,""")}function isArray(t){return!("[object Array]"!==toStr(t)||toStringTag&&"object"==typeof t&&toStringTag in t)}function isDate(t){return!("[object Date]"!==toStr(t)||toStringTag&&"object"==typeof t&&toStringTag in t)}function isRegExp(t){return!("[object RegExp]"!==toStr(t)||toStringTag&&"object"==typeof t&&toStringTag in t)}function isError(t){return!("[object Error]"!==toStr(t)||toStringTag&&"object"==typeof t&&toStringTag in t)}function isString(t){return!("[object String]"!==toStr(t)||toStringTag&&"object"==typeof t&&toStringTag in t)}function isNumber(t){return!("[object Number]"!==toStr(t)||toStringTag&&"object"==typeof t&&toStringTag in t)}function isBoolean(t){return!("[object Boolean]"!==toStr(t)||toStringTag&&"object"==typeof t&&toStringTag in t)}function isSymbol(t){if(hasShammedSymbols)return t&&"object"==typeof t&&t instanceof Symbol;if("symbol"==typeof t)return!0;if(!t||"object"!=typeof t||!symToString)return!1;try{return symToString.call(t),!0}catch(t){}return!1}function isBigInt(t){if(!t||"object"!=typeof t||!bigIntValueOf)return!1;try{return bigIntValueOf.call(t),!0}catch(t){}return!1}module.exports=function inspect_(t,e,r,n){var o=e||{};if(has(o,"quoteStyle")&&!has(quotes,o.quoteStyle))throw new TypeError('option "quoteStyle" must be "single" or "double"');if(has(o,"maxStringLength")&&("number"==typeof o.maxStringLength?o.maxStringLength<0&&o.maxStringLength!==1/0:null!==o.maxStringLength))throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');var i=!has(o,"customInspect")||o.customInspect;if("boolean"!=typeof i&&"symbol"!==i)throw new TypeError("option \"customInspect\", if provided, must be `true`, `false`, or `'symbol'`");if(has(o,"indent")&&null!==o.indent&&"\t"!==o.indent&&!(parseInt(o.indent,10)===o.indent&&o.indent>0))throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`');if(has(o,"numericSeparator")&&"boolean"!=typeof o.numericSeparator)throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');var a=o.numericSeparator;if(void 0===t)return"undefined";if(null===t)return"null";if("boolean"==typeof t)return t?"true":"false";if("string"==typeof t)return inspectString(t,o);if("number"==typeof t){if(0===t)return 1/0/t>0?"0":"-0";var c=String(t);return a?addNumericSeparator(t,c):c}if("bigint"==typeof t){var l=String(t)+"n";return a?addNumericSeparator(t,l):l}var p=void 0===o.depth?5:o.depth;if(void 0===r&&(r=0),r>=p&&p>0&&"object"==typeof t)return isArray(t)?"[Array]":"[Object]";var u=getIndent(o,r);if(void 0===n)n=[];else if(indexOf(n,t)>=0)return"[Circular]";function inspect(t,e,i){if(e&&(n=$arrSlice.call(n)).push(e),i){var a={depth:o.depth};return has(o,"quoteStyle")&&(a.quoteStyle=o.quoteStyle),inspect_(t,a,r+1,n)}return inspect_(t,o,r+1,n)}if("function"==typeof t&&!isRegExp(t)){var s=nameOf(t),f=arrObjKeys(t,inspect);return"[Function"+(s?": "+s:" (anonymous)")+"]"+(f.length>0?" { "+$join.call(f,", ")+" }":"")}if(isSymbol(t)){var y=hasShammedSymbols?$replace.call(String(t),/^(Symbol\(.*\))_[^)]*$/,"$1"):symToString.call(t);return"object"!=typeof t||hasShammedSymbols?y:markBoxed(y)}if(isElement(t)){for(var S="<"+$toLowerCase.call(String(t.nodeName)),g=t.attributes||[],b=0;b"}if(isArray(t)){if(0===t.length)return"[]";var m=arrObjKeys(t,inspect);return u&&!singleLineValues(m)?"["+indentedJoin(m,u)+"]":"[ "+$join.call(m,", ")+" ]"}if(isError(t)){var h=arrObjKeys(t,inspect);return"cause"in Error.prototype||!("cause"in t)||isEnumerable.call(t,"cause")?0===h.length?"["+String(t)+"]":"{ ["+String(t)+"] "+$join.call(h,", ")+" }":"{ ["+String(t)+"] "+$join.call($concat.call("[cause]: "+inspect(t.cause),h),", ")+" }"}if("object"==typeof t&&i){if(inspectSymbol&&"function"==typeof t[inspectSymbol]&&utilInspect)return utilInspect(t,{depth:p-r});if("symbol"!==i&&"function"==typeof t.inspect)return t.inspect()}if(isMap(t)){var d=[];return mapForEach&&mapForEach.call(t,(function(e,r){d.push(inspect(r,t,!0)+" => "+inspect(e,t))})),collectionOf("Map",mapSize.call(t),d,u)}if(isSet(t)){var j=[];return setForEach&&setForEach.call(t,(function(e){j.push(inspect(e,t))})),collectionOf("Set",setSize.call(t),j,u)}if(isWeakMap(t))return weakCollectionOf("WeakMap");if(isWeakSet(t))return weakCollectionOf("WeakSet");if(isWeakRef(t))return weakCollectionOf("WeakRef");if(isNumber(t))return markBoxed(inspect(Number(t)));if(isBigInt(t))return markBoxed(inspect(bigIntValueOf.call(t)));if(isBoolean(t))return markBoxed(booleanValueOf.call(t));if(isString(t))return markBoxed(inspect(String(t)));if("undefined"!=typeof window&&t===window)return"{ [object Window] }";if("undefined"!=typeof globalThis&&t===globalThis||"undefined"!=typeof global&&t===global)return"{ [object globalThis] }";if(!isDate(t)&&!isRegExp(t)){var O=arrObjKeys(t,inspect),w=gPO?gPO(t)===Object.prototype:t instanceof Object||t.constructor===Object,$=t instanceof Object?"":"null prototype",k=!w&&toStringTag&&Object(t)===t&&toStringTag in t?$slice.call(toStr(t),8,-1):$?"Object":"",v=(w||"function"!=typeof t.constructor?"":t.constructor.name?t.constructor.name+" ":"")+(k||$?"["+$join.call($concat.call([],k||[],$||[]),": ")+"] ":"");return 0===O.length?v+"{}":u?v+"{"+indentedJoin(O,u)+"}":v+"{ "+$join.call(O,", ")+" }"}return String(t)};var hasOwn=Object.prototype.hasOwnProperty||function(t){return t in this};function has(t,e){return hasOwn.call(t,e)}function toStr(t){return objectToString.call(t)}function nameOf(t){if(t.name)return t.name;var e=$match.call(functionToString.call(t),/^function\s*([\w$]+)/);return e?e[1]:null}function indexOf(t,e){if(t.indexOf)return t.indexOf(e);for(var r=0,n=t.length;re.maxStringLength){var r=t.length-e.maxStringLength,n="... "+r+" more character"+(r>1?"s":"");return inspectString($slice.call(t,0,e.maxStringLength),e)+n}var o=quoteREs[e.quoteStyle||"single"];return o.lastIndex=0,wrapQuotes($replace.call($replace.call(t,o,"\\$1"),/[\x00-\x1f]/g,lowbyte),"single",e)}function lowbyte(t){var e=t.charCodeAt(0),r={8:"b",9:"t",10:"n",12:"f",13:"r"}[e];return r?"\\"+r:"\\x"+(e<16?"0":"")+$toUpperCase.call(e.toString(16))}function markBoxed(t){return"Object("+t+")"}function weakCollectionOf(t){return t+" { ? }"}function collectionOf(t,e,r,n){return t+" ("+e+") {"+(n?indentedJoin(r,n):$join.call(r,", "))+"}"}function singleLineValues(t){for(var e=0;e=0)return!1;return!0}function getIndent(t,e){var r;if("\t"===t.indent)r="\t";else{if(!("number"==typeof t.indent&&t.indent>0))return null;r=$join.call(Array(t.indent+1)," ")}return{base:r,prev:$join.call(Array(e+1),r)}}function indentedJoin(t,e){if(0===t.length)return"";var r="\n"+e.prev+e.base;return r+$join.call(t,","+r)+"\n"+e.prev}function arrObjKeys(t,e){var r=isArray(t),n=[];if(r){n.length=t.length;for(var o=0;o -1) { return val.split(','); } + if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) { + throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.'); + } + return val; }; @@ -49,10 +58,21 @@ var isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('✓') var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓') var parseValues = function parseQueryStringValues(str, options) { - var obj = {}; + var obj = { __proto__: null }; + var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str; + cleanStr = cleanStr.replace(/%5B/gi, '[').replace(/%5D/gi, ']'); + var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit; - var parts = cleanStr.split(options.delimiter, limit); + var parts = cleanStr.split( + options.delimiter, + options.throwOnLimitExceeded ? limit + 1 : limit + ); + + if (options.throwOnLimitExceeded && parts.length > limit) { + throw new RangeError('Parameter limit exceeded. Only ' + limit + ' parameter' + (limit === 1 ? '' : 's') + ' allowed.'); + } + var skipIndex = -1; // Keep track of where the utf8 sentinel was found var i; @@ -80,14 +100,20 @@ var parseValues = function parseQueryStringValues(str, options) { var bracketEqualsPos = part.indexOf(']='); var pos = bracketEqualsPos === -1 ? part.indexOf('=') : bracketEqualsPos + 1; - var key, val; + var key; + var val; if (pos === -1) { key = options.decoder(part, defaults.decoder, charset, 'key'); val = options.strictNullHandling ? null : ''; } else { key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key'); + val = utils.maybeMap( - parseArrayValue(part.slice(pos + 1), options), + parseArrayValue( + part.slice(pos + 1), + options, + isArray(obj[key]) ? obj[key].length : 0 + ), function (encodedVal) { return options.decoder(encodedVal, defaults.decoder, charset, 'value'); } @@ -95,16 +121,17 @@ var parseValues = function parseQueryStringValues(str, options) { } if (val && options.interpretNumericEntities && charset === 'iso-8859-1') { - val = interpretNumericEntities(val); + val = interpretNumericEntities(String(val)); } if (part.indexOf('[]=') > -1) { val = isArray(val) ? [val] : val; } - if (has.call(obj, key)) { + var existing = has.call(obj, key); + if (existing && options.duplicates === 'combine') { obj[key] = utils.combine(obj[key], val); - } else { + } else if (!existing || options.duplicates === 'last') { obj[key] = val; } } @@ -113,31 +140,40 @@ var parseValues = function parseQueryStringValues(str, options) { }; var parseObject = function (chain, val, options, valuesParsed) { - var leaf = valuesParsed ? val : parseArrayValue(val, options); + var currentArrayLength = 0; + if (chain.length > 0 && chain[chain.length - 1] === '[]') { + var parentKey = chain.slice(0, -1).join(''); + currentArrayLength = Array.isArray(val) && val[parentKey] ? val[parentKey].length : 0; + } + + var leaf = valuesParsed ? val : parseArrayValue(val, options, currentArrayLength); for (var i = chain.length - 1; i >= 0; --i) { var obj; var root = chain[i]; if (root === '[]' && options.parseArrays) { - obj = [].concat(leaf); + obj = options.allowEmptyArrays && (leaf === '' || (options.strictNullHandling && leaf === null)) + ? [] + : utils.combine([], leaf); } else { - obj = options.plainObjects ? Object.create(null) : {}; + obj = options.plainObjects ? { __proto__: null } : {}; var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root; - var index = parseInt(cleanRoot, 10); - if (!options.parseArrays && cleanRoot === '') { + var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, '.') : cleanRoot; + var index = parseInt(decodedRoot, 10); + if (!options.parseArrays && decodedRoot === '') { obj = { 0: leaf }; } else if ( !isNaN(index) - && root !== cleanRoot - && String(index) === cleanRoot + && root !== decodedRoot + && String(index) === decodedRoot && index >= 0 && (options.parseArrays && index <= options.arrayLimit) ) { obj = []; obj[index] = leaf; - } else if (cleanRoot !== '__proto__') { - obj[cleanRoot] = leaf; + } else if (decodedRoot !== '__proto__') { + obj[decodedRoot] = leaf; } } @@ -192,9 +228,12 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesPars keys.push(segment[1]); } - // If there's a remainder, just add whatever is left + // If there's a remainder, check strictDepth option for throw, else just add whatever is left if (segment) { + if (options.strictDepth === true) { + throw new RangeError('Input depth exceeded depth option of ' + options.depth + ' and strictDepth is true'); + } keys.push('[' + key.slice(segment.index) + ']'); } @@ -206,33 +245,59 @@ var normalizeParseOptions = function normalizeParseOptions(opts) { return defaults; } - if (opts.decoder !== null && opts.decoder !== undefined && typeof opts.decoder !== 'function') { + if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') { + throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided'); + } + + if (typeof opts.decodeDotInKeys !== 'undefined' && typeof opts.decodeDotInKeys !== 'boolean') { + throw new TypeError('`decodeDotInKeys` option can only be `true` or `false`, when provided'); + } + + if (opts.decoder !== null && typeof opts.decoder !== 'undefined' && typeof opts.decoder !== 'function') { throw new TypeError('Decoder has to be a function.'); } if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') { throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'); } + + if (typeof opts.throwOnLimitExceeded !== 'undefined' && typeof opts.throwOnLimitExceeded !== 'boolean') { + throw new TypeError('`throwOnLimitExceeded` option must be a boolean'); + } + var charset = typeof opts.charset === 'undefined' ? defaults.charset : opts.charset; + var duplicates = typeof opts.duplicates === 'undefined' ? defaults.duplicates : opts.duplicates; + + if (duplicates !== 'combine' && duplicates !== 'first' && duplicates !== 'last') { + throw new TypeError('The duplicates option must be either combine, first, or last'); + } + + var allowDots = typeof opts.allowDots === 'undefined' ? opts.decodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots; + return { - allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots, + allowDots: allowDots, + allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays, allowPrototypes: typeof opts.allowPrototypes === 'boolean' ? opts.allowPrototypes : defaults.allowPrototypes, allowSparse: typeof opts.allowSparse === 'boolean' ? opts.allowSparse : defaults.allowSparse, arrayLimit: typeof opts.arrayLimit === 'number' ? opts.arrayLimit : defaults.arrayLimit, charset: charset, charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel, comma: typeof opts.comma === 'boolean' ? opts.comma : defaults.comma, + decodeDotInKeys: typeof opts.decodeDotInKeys === 'boolean' ? opts.decodeDotInKeys : defaults.decodeDotInKeys, decoder: typeof opts.decoder === 'function' ? opts.decoder : defaults.decoder, delimiter: typeof opts.delimiter === 'string' || utils.isRegExp(opts.delimiter) ? opts.delimiter : defaults.delimiter, // eslint-disable-next-line no-implicit-coercion, no-extra-parens depth: (typeof opts.depth === 'number' || opts.depth === false) ? +opts.depth : defaults.depth, + duplicates: duplicates, ignoreQueryPrefix: opts.ignoreQueryPrefix === true, interpretNumericEntities: typeof opts.interpretNumericEntities === 'boolean' ? opts.interpretNumericEntities : defaults.interpretNumericEntities, parameterLimit: typeof opts.parameterLimit === 'number' ? opts.parameterLimit : defaults.parameterLimit, parseArrays: opts.parseArrays !== false, plainObjects: typeof opts.plainObjects === 'boolean' ? opts.plainObjects : defaults.plainObjects, - strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling + strictDepth: typeof opts.strictDepth === 'boolean' ? !!opts.strictDepth : defaults.strictDepth, + strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling, + throwOnLimitExceeded: typeof opts.throwOnLimitExceeded === 'boolean' ? opts.throwOnLimitExceeded : false }; }; @@ -240,11 +305,11 @@ module.exports = function (str, opts) { var options = normalizeParseOptions(opts); if (str === '' || str === null || typeof str === 'undefined') { - return options.plainObjects ? Object.create(null) : {}; + return options.plainObjects ? { __proto__: null } : {}; } var tempObj = typeof str === 'string' ? parseValues(str, options) : str; - var obj = options.plainObjects ? Object.create(null) : {}; + var obj = options.plainObjects ? { __proto__: null } : {}; // Iterate over the keys and setup the new object diff --git a/backend/node_modules/qs/lib/stringify.js b/backend/node_modules/qs/lib/stringify.js index 47ea4b15..2666eaf9 100644 --- a/backend/node_modules/qs/lib/stringify.js +++ b/backend/node_modules/qs/lib/stringify.js @@ -19,7 +19,6 @@ var arrayPrefixGenerators = { }; var isArray = Array.isArray; -var split = String.prototype.split; var push = Array.prototype.push; var pushToArray = function (arr, valueOrArray) { push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]); @@ -31,12 +30,17 @@ var defaultFormat = formats['default']; var defaults = { addQueryPrefix: false, allowDots: false, + allowEmptyArrays: false, + arrayFormat: 'indices', charset: 'utf-8', charsetSentinel: false, + commaRoundTrip: false, delimiter: '&', encode: true, + encodeDotInKeys: false, encoder: utils.encode, encodeValuesOnly: false, + filter: void undefined, format: defaultFormat, formatter: formats.formatters[defaultFormat], // deprecated @@ -62,8 +66,11 @@ var stringify = function stringify( object, prefix, generateArrayPrefix, + commaRoundTrip, + allowEmptyArrays, strictNullHandling, skipNulls, + encodeDotInKeys, encoder, filter, sort, @@ -120,14 +127,6 @@ var stringify = function stringify( if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) { if (encoder) { var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format); - if (generateArrayPrefix === 'comma' && encodeValuesOnly) { - var valuesArray = split.call(String(obj), ','); - var valuesJoined = ''; - for (var i = 0; i < valuesArray.length; ++i) { - valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset, 'value', format)); - } - return [formatter(keyValue) + '=' + valuesJoined]; - } return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))]; } return [formatter(prefix) + '=' + formatter(String(obj))]; @@ -142,6 +141,9 @@ var stringify = function stringify( var objKeys; if (generateArrayPrefix === 'comma' && isArray(obj)) { // we need to join elements in + if (encodeValuesOnly && encoder) { + obj = utils.maybeMap(obj, encoder); + } objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }]; } else if (isArray(filter)) { objKeys = filter; @@ -150,17 +152,28 @@ var stringify = function stringify( objKeys = sort ? keys.sort(sort) : keys; } + var encodedPrefix = encodeDotInKeys ? String(prefix).replace(/\./g, '%2E') : String(prefix); + + var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? encodedPrefix + '[]' : encodedPrefix; + + if (allowEmptyArrays && isArray(obj) && obj.length === 0) { + return adjustedPrefix + '[]'; + } + for (var j = 0; j < objKeys.length; ++j) { var key = objKeys[j]; - var value = typeof key === 'object' && typeof key.value !== 'undefined' ? key.value : obj[key]; + var value = typeof key === 'object' && key && typeof key.value !== 'undefined' + ? key.value + : obj[key]; if (skipNulls && value === null) { continue; } + var encodedKey = allowDots && encodeDotInKeys ? String(key).replace(/\./g, '%2E') : String(key); var keyPrefix = isArray(obj) - ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix - : prefix + (allowDots ? '.' + key : '[' + key + ']'); + ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix + : adjustedPrefix + (allowDots ? '.' + encodedKey : '[' + encodedKey + ']'); sideChannel.set(object, step); var valueSideChannel = getSideChannel(); @@ -169,9 +182,12 @@ var stringify = function stringify( value, keyPrefix, generateArrayPrefix, + commaRoundTrip, + allowEmptyArrays, strictNullHandling, skipNulls, - encoder, + encodeDotInKeys, + generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder, filter, sort, allowDots, @@ -192,6 +208,14 @@ var normalizeStringifyOptions = function normalizeStringifyOptions(opts) { return defaults; } + if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') { + throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided'); + } + + if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') { + throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided'); + } + if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') { throw new TypeError('Encoder has to be a function.'); } @@ -215,13 +239,32 @@ var normalizeStringifyOptions = function normalizeStringifyOptions(opts) { filter = opts.filter; } + var arrayFormat; + if (opts.arrayFormat in arrayPrefixGenerators) { + arrayFormat = opts.arrayFormat; + } else if ('indices' in opts) { + arrayFormat = opts.indices ? 'indices' : 'repeat'; + } else { + arrayFormat = defaults.arrayFormat; + } + + if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') { + throw new TypeError('`commaRoundTrip` must be a boolean, or absent'); + } + + var allowDots = typeof opts.allowDots === 'undefined' ? opts.encodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots; + return { addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix, - allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots, + allowDots: allowDots, + allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays, + arrayFormat: arrayFormat, charset: charset, charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel, + commaRoundTrip: !!opts.commaRoundTrip, delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter, encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode, + encodeDotInKeys: typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys, encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder, encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly, filter: filter, @@ -255,16 +298,8 @@ module.exports = function (object, opts) { return ''; } - var arrayFormat; - if (opts && opts.arrayFormat in arrayPrefixGenerators) { - arrayFormat = opts.arrayFormat; - } else if (opts && 'indices' in opts) { - arrayFormat = opts.indices ? 'indices' : 'repeat'; - } else { - arrayFormat = 'indices'; - } - - var generateArrayPrefix = arrayPrefixGenerators[arrayFormat]; + var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat]; + var commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip; if (!objKeys) { objKeys = Object.keys(obj); @@ -277,16 +312,20 @@ module.exports = function (object, opts) { var sideChannel = getSideChannel(); for (var i = 0; i < objKeys.length; ++i) { var key = objKeys[i]; + var value = obj[key]; - if (options.skipNulls && obj[key] === null) { + if (options.skipNulls && value === null) { continue; } pushToArray(keys, stringify( - obj[key], + value, key, generateArrayPrefix, + commaRoundTrip, + options.allowEmptyArrays, options.strictNullHandling, options.skipNulls, + options.encodeDotInKeys, options.encode ? options.encoder : null, options.filter, options.sort, diff --git a/backend/node_modules/qs/lib/utils.js b/backend/node_modules/qs/lib/utils.js index 1e545381..2905ff01 100644 --- a/backend/node_modules/qs/lib/utils.js +++ b/backend/node_modules/qs/lib/utils.js @@ -34,7 +34,7 @@ var compactQueue = function compactQueue(queue) { }; var arrayToObject = function arrayToObject(source, options) { - var obj = options && options.plainObjects ? Object.create(null) : {}; + var obj = options && options.plainObjects ? { __proto__: null } : {}; for (var i = 0; i < source.length; ++i) { if (typeof source[i] !== 'undefined') { obj[i] = source[i]; @@ -50,11 +50,14 @@ var merge = function merge(target, source, options) { return target; } - if (typeof source !== 'object') { + if (typeof source !== 'object' && typeof source !== 'function') { if (isArray(target)) { target.push(source); } else if (target && typeof target === 'object') { - if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) { + if ( + (options && (options.plainObjects || options.allowPrototypes)) + || !has.call(Object.prototype, source) + ) { target[source] = true; } } else { @@ -108,7 +111,7 @@ var assign = function assignSingleSource(target, source) { }, target); }; -var decode = function (str, decoder, charset) { +var decode = function (str, defaultDecoder, charset) { var strWithoutPlus = str.replace(/\+/g, ' '); if (charset === 'iso-8859-1') { // unescape never throws, no try...catch needed: @@ -122,6 +125,10 @@ var decode = function (str, decoder, charset) { } }; +var limit = 1024; + +/* eslint operator-linebreak: [2, "before"] */ + var encode = function encode(str, defaultEncoder, charset, kind, format) { // This code was originally written by Brian White (mscdex) for the io.js core querystring library. // It has been adapted here for stricter adherence to RFC 3986 @@ -143,45 +150,54 @@ var encode = function encode(str, defaultEncoder, charset, kind, format) { } var out = ''; - for (var i = 0; i < string.length; ++i) { - var c = string.charCodeAt(i); - - if ( - c === 0x2D // - - || c === 0x2E // . - || c === 0x5F // _ - || c === 0x7E // ~ - || (c >= 0x30 && c <= 0x39) // 0-9 - || (c >= 0x41 && c <= 0x5A) // a-z - || (c >= 0x61 && c <= 0x7A) // A-Z - || (format === formats.RFC1738 && (c === 0x28 || c === 0x29)) // ( ) - ) { - out += string.charAt(i); - continue; - } + for (var j = 0; j < string.length; j += limit) { + var segment = string.length >= limit ? string.slice(j, j + limit) : string; + var arr = []; + + for (var i = 0; i < segment.length; ++i) { + var c = segment.charCodeAt(i); + if ( + c === 0x2D // - + || c === 0x2E // . + || c === 0x5F // _ + || c === 0x7E // ~ + || (c >= 0x30 && c <= 0x39) // 0-9 + || (c >= 0x41 && c <= 0x5A) // a-z + || (c >= 0x61 && c <= 0x7A) // A-Z + || (format === formats.RFC1738 && (c === 0x28 || c === 0x29)) // ( ) + ) { + arr[arr.length] = segment.charAt(i); + continue; + } - if (c < 0x80) { - out = out + hexTable[c]; - continue; - } + if (c < 0x80) { + arr[arr.length] = hexTable[c]; + continue; + } - if (c < 0x800) { - out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]); - continue; - } + if (c < 0x800) { + arr[arr.length] = hexTable[0xC0 | (c >> 6)] + + hexTable[0x80 | (c & 0x3F)]; + continue; + } + + if (c < 0xD800 || c >= 0xE000) { + arr[arr.length] = hexTable[0xE0 | (c >> 12)] + + hexTable[0x80 | ((c >> 6) & 0x3F)] + + hexTable[0x80 | (c & 0x3F)]; + continue; + } + + i += 1; + c = 0x10000 + (((c & 0x3FF) << 10) | (segment.charCodeAt(i) & 0x3FF)); - if (c < 0xD800 || c >= 0xE000) { - out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]); - continue; + arr[arr.length] = hexTable[0xF0 | (c >> 18)] + + hexTable[0x80 | ((c >> 12) & 0x3F)] + + hexTable[0x80 | ((c >> 6) & 0x3F)] + + hexTable[0x80 | (c & 0x3F)]; } - i += 1; - c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); - /* eslint operator-linebreak: [2, "before"] */ - out += hexTable[0xF0 | (c >> 18)] - + hexTable[0x80 | ((c >> 12) & 0x3F)] - + hexTable[0x80 | ((c >> 6) & 0x3F)] - + hexTable[0x80 | (c & 0x3F)]; + out += arr.join(''); } return out; diff --git a/backend/node_modules/qs/package.json b/backend/node_modules/qs/package.json index 845e20a2..e4144d08 100644 --- a/backend/node_modules/qs/package.json +++ b/backend/node_modules/qs/package.json @@ -2,7 +2,7 @@ "name": "qs", "description": "A querystring parser that supports nesting and arrays, with a depth limit", "homepage": "https://github.com/ljharb/qs", - "version": "6.10.3", + "version": "6.14.0", "repository": { "type": "git", "url": "https://github.com/ljharb/qs.git" @@ -11,6 +11,7 @@ "url": "https://github.com/sponsors/ljharb" }, "main": "lib/index.js", + "sideEffects": false, "contributors": [ { "name": "Jordan Harband", @@ -30,44 +31,63 @@ "node": ">=0.6" }, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.1.0" }, "devDependencies": { - "@ljharb/eslint-config": "^20.1.0", - "aud": "^1.1.5", + "@browserify/envify": "^6.0.0", + "@browserify/uglifyify": "^6.0.0", + "@ljharb/eslint-config": "^21.1.1", "browserify": "^16.5.2", + "bundle-collapser": "^1.4.0", + "common-shakeify": "~1.0.0", "eclint": "^2.8.1", - "eslint": "^8.6.0", + "es-value-fixtures": "^1.7.0", + "eslint": "=8.8.0", "evalmd": "^0.0.19", "for-each": "^0.3.3", - "has-symbols": "^1.0.2", + "glob": "=10.3.7", + "has-bigints": "^1.1.0", + "has-override-mistake": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "iconv-lite": "^0.5.1", "in-publish": "^2.0.1", + "jackspeak": "=2.1.1", "mkdirp": "^0.5.5", + "mock-property": "^1.1.0", + "module-deps": "^6.2.3", + "npmignore": "^0.3.1", "nyc": "^10.3.2", - "object-inspect": "^1.12.0", + "object-inspect": "^1.13.3", "qs-iconv": "^1.0.4", "safe-publish-latest": "^2.0.0", "safer-buffer": "^2.1.2", - "tape": "^5.4.0" + "tape": "^5.9.0", + "unassertify": "^3.0.1" }, "scripts": { - "prepublishOnly": "safe-publish-latest && npm run dist", + "prepack": "npmignore --auto --commentLines=autogenerated && npm run dist", + "prepublishOnly": "safe-publish-latest", "prepublish": "not-in-publish || npm run prepublishOnly", "pretest": "npm run --silent readme && npm run --silent lint", "test": "npm run tests-only", "tests-only": "nyc tape 'test/**/*.js'", - "posttest": "aud --production", + "posttest": "npx npm@'>=10.2' audit --production", "readme": "evalmd README.md", - "postlint": "eclint check * lib/* test/* !dist/*", - "lint": "eslint .", - "dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js" + "postlint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git' | grep -v dist/)", + "lint": "eslint --ext=js,mjs .", + "dist": "mkdirp dist && browserify --standalone Qs -g unassertify -g @browserify/envify -g [@browserify/uglifyify --mangle.keep_fnames --compress.keep_fnames --format.indent_level=1 --compress.arrows=false --compress.passes=4 --compress.typeofs=false] -p common-shakeify -p bundle-collapser/plugin lib/index.js > dist/qs.js" }, "license": "BSD-3-Clause", - "greenkeeper": { + "publishConfig": { "ignore": [ - "iconv-lite", - "mkdirp" + "!dist/*", + "bower.json", + "component.json", + ".github/workflows", + "logos", + "tea.yaml" ] } } diff --git a/backend/node_modules/qs/test/empty-keys-cases.js b/backend/node_modules/qs/test/empty-keys-cases.js new file mode 100644 index 00000000..2b1190ef --- /dev/null +++ b/backend/node_modules/qs/test/empty-keys-cases.js @@ -0,0 +1,267 @@ +'use strict'; + +module.exports = { + emptyTestCases: [ + { + input: '&', + withEmptyKeys: {}, + stringifyOutput: { + brackets: '', + indices: '', + repeat: '' + }, + noEmptyKeys: {} + }, + { + input: '&&', + withEmptyKeys: {}, + stringifyOutput: { + brackets: '', + indices: '', + repeat: '' + }, + noEmptyKeys: {} + }, + { + input: '&=', + withEmptyKeys: { '': '' }, + stringifyOutput: { + brackets: '=', + indices: '=', + repeat: '=' + }, + noEmptyKeys: {} + }, + { + input: '&=&', + withEmptyKeys: { '': '' }, + stringifyOutput: { + brackets: '=', + indices: '=', + repeat: '=' + }, + noEmptyKeys: {} + }, + { + input: '&=&=', + withEmptyKeys: { '': ['', ''] }, + stringifyOutput: { + brackets: '[]=&[]=', + indices: '[0]=&[1]=', + repeat: '=&=' + }, + noEmptyKeys: {} + }, + { + input: '&=&=&', + withEmptyKeys: { '': ['', ''] }, + stringifyOutput: { + brackets: '[]=&[]=', + indices: '[0]=&[1]=', + repeat: '=&=' + }, + noEmptyKeys: {} + }, + { + input: '=', + withEmptyKeys: { '': '' }, + noEmptyKeys: {}, + stringifyOutput: { + brackets: '=', + indices: '=', + repeat: '=' + } + }, + { + input: '=&', + withEmptyKeys: { '': '' }, + stringifyOutput: { + brackets: '=', + indices: '=', + repeat: '=' + }, + noEmptyKeys: {} + }, + { + input: '=&&&', + withEmptyKeys: { '': '' }, + stringifyOutput: { + brackets: '=', + indices: '=', + repeat: '=' + }, + noEmptyKeys: {} + }, + { + input: '=&=&=&', + withEmptyKeys: { '': ['', '', ''] }, + stringifyOutput: { + brackets: '[]=&[]=&[]=', + indices: '[0]=&[1]=&[2]=', + repeat: '=&=&=' + }, + noEmptyKeys: {} + }, + { + input: '=&a[]=b&a[1]=c', + withEmptyKeys: { '': '', a: ['b', 'c'] }, + stringifyOutput: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c' + }, + noEmptyKeys: { a: ['b', 'c'] } + }, + { + input: '=a', + withEmptyKeys: { '': 'a' }, + noEmptyKeys: {}, + stringifyOutput: { + brackets: '=a', + indices: '=a', + repeat: '=a' + } + }, + { + input: 'a==a', + withEmptyKeys: { a: '=a' }, + noEmptyKeys: { a: '=a' }, + stringifyOutput: { + brackets: 'a==a', + indices: 'a==a', + repeat: 'a==a' + } + }, + { + input: '=&a[]=b', + withEmptyKeys: { '': '', a: ['b'] }, + stringifyOutput: { + brackets: '=&a[]=b', + indices: '=&a[0]=b', + repeat: '=&a=b' + }, + noEmptyKeys: { a: ['b'] } + }, + { + input: '=&a[]=b&a[]=c&a[2]=d', + withEmptyKeys: { '': '', a: ['b', 'c', 'd'] }, + stringifyOutput: { + brackets: '=&a[]=b&a[]=c&a[]=d', + indices: '=&a[0]=b&a[1]=c&a[2]=d', + repeat: '=&a=b&a=c&a=d' + }, + noEmptyKeys: { a: ['b', 'c', 'd'] } + }, + { + input: '=a&=b', + withEmptyKeys: { '': ['a', 'b'] }, + stringifyOutput: { + brackets: '[]=a&[]=b', + indices: '[0]=a&[1]=b', + repeat: '=a&=b' + }, + noEmptyKeys: {} + }, + { + input: '=a&foo=b', + withEmptyKeys: { '': 'a', foo: 'b' }, + noEmptyKeys: { foo: 'b' }, + stringifyOutput: { + brackets: '=a&foo=b', + indices: '=a&foo=b', + repeat: '=a&foo=b' + } + }, + { + input: 'a[]=b&a=c&=', + withEmptyKeys: { '': '', a: ['b', 'c'] }, + stringifyOutput: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c' + }, + noEmptyKeys: { a: ['b', 'c'] } + }, + { + input: 'a[]=b&a=c&=', + withEmptyKeys: { '': '', a: ['b', 'c'] }, + stringifyOutput: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c' + }, + noEmptyKeys: { a: ['b', 'c'] } + }, + { + input: 'a[0]=b&a=c&=', + withEmptyKeys: { '': '', a: ['b', 'c'] }, + stringifyOutput: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c' + }, + noEmptyKeys: { a: ['b', 'c'] } + }, + { + input: 'a=b&a[]=c&=', + withEmptyKeys: { '': '', a: ['b', 'c'] }, + stringifyOutput: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c' + }, + noEmptyKeys: { a: ['b', 'c'] } + }, + { + input: 'a=b&a[0]=c&=', + withEmptyKeys: { '': '', a: ['b', 'c'] }, + stringifyOutput: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c' + }, + noEmptyKeys: { a: ['b', 'c'] } + }, + { + input: '[]=a&[]=b& []=1', + withEmptyKeys: { '': ['a', 'b'], ' ': ['1'] }, + stringifyOutput: { + brackets: '[]=a&[]=b& []=1', + indices: '[0]=a&[1]=b& [0]=1', + repeat: '=a&=b& =1' + }, + noEmptyKeys: { 0: 'a', 1: 'b', ' ': ['1'] } + }, + { + input: '[0]=a&[1]=b&a[0]=1&a[1]=2', + withEmptyKeys: { '': ['a', 'b'], a: ['1', '2'] }, + noEmptyKeys: { 0: 'a', 1: 'b', a: ['1', '2'] }, + stringifyOutput: { + brackets: '[]=a&[]=b&a[]=1&a[]=2', + indices: '[0]=a&[1]=b&a[0]=1&a[1]=2', + repeat: '=a&=b&a=1&a=2' + } + }, + { + input: '[deep]=a&[deep]=2', + withEmptyKeys: { '': { deep: ['a', '2'] } + }, + stringifyOutput: { + brackets: '[deep][]=a&[deep][]=2', + indices: '[deep][0]=a&[deep][1]=2', + repeat: '[deep]=a&[deep]=2' + }, + noEmptyKeys: { deep: ['a', '2'] } + }, + { + input: '%5B0%5D=a&%5B1%5D=b', + withEmptyKeys: { '': ['a', 'b'] }, + stringifyOutput: { + brackets: '[]=a&[]=b', + indices: '[0]=a&[1]=b', + repeat: '=a&=b' + }, + noEmptyKeys: { 0: 'a', 1: 'b' } + } + ] +}; diff --git a/backend/node_modules/qs/test/parse.js b/backend/node_modules/qs/test/parse.js index 7d61023e..32cdfd8e 100644 --- a/backend/node_modules/qs/test/parse.js +++ b/backend/node_modules/qs/test/parse.js @@ -1,10 +1,18 @@ 'use strict'; var test = require('tape'); -var qs = require('../'); -var utils = require('../lib/utils'); +var hasPropertyDescriptors = require('has-property-descriptors')(); var iconv = require('iconv-lite'); +var mockProperty = require('mock-property'); +var hasOverrideMistake = require('has-override-mistake')(); var SaferBuffer = require('safer-buffer').Buffer; +var v = require('es-value-fixtures'); +var inspect = require('object-inspect'); +var emptyTestCases = require('./empty-keys-cases').emptyTestCases; +var hasProto = require('has-proto')(); + +var qs = require('../'); +var utils = require('../lib/utils'); test('parse()', function (t) { t.test('parses a simple string', function (st) { @@ -32,41 +40,156 @@ test('parse()', function (t) { st.end(); }); - t.test('arrayFormat: brackets allows only explicit arrays', function (st) { - st.deepEqual(qs.parse('a[]=b&a[]=c', { arrayFormat: 'brackets' }), { a: ['b', 'c'] }); - st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayFormat: 'brackets' }), { a: ['b', 'c'] }); - st.deepEqual(qs.parse('a=b,c', { arrayFormat: 'brackets' }), { a: 'b,c' }); - st.deepEqual(qs.parse('a=b&a=c', { arrayFormat: 'brackets' }), { a: ['b', 'c'] }); + t.test('comma: false', function (st) { + st.deepEqual(qs.parse('a[]=b&a[]=c'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a[0]=b&a[1]=c'), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a=b,c'), { a: 'b,c' }); + st.deepEqual(qs.parse('a=b&a=c'), { a: ['b', 'c'] }); st.end(); }); - t.test('arrayFormat: indices allows only indexed arrays', function (st) { - st.deepEqual(qs.parse('a[]=b&a[]=c', { arrayFormat: 'indices' }), { a: ['b', 'c'] }); - st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayFormat: 'indices' }), { a: ['b', 'c'] }); - st.deepEqual(qs.parse('a=b,c', { arrayFormat: 'indices' }), { a: 'b,c' }); - st.deepEqual(qs.parse('a=b&a=c', { arrayFormat: 'indices' }), { a: ['b', 'c'] }); + t.test('comma: true', function (st) { + st.deepEqual(qs.parse('a[]=b&a[]=c', { comma: true }), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a[0]=b&a[1]=c', { comma: true }), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a=b,c', { comma: true }), { a: ['b', 'c'] }); + st.deepEqual(qs.parse('a=b&a=c', { comma: true }), { a: ['b', 'c'] }); st.end(); }); - t.test('arrayFormat: comma allows only comma-separated arrays', function (st) { - st.deepEqual(qs.parse('a[]=b&a[]=c', { arrayFormat: 'comma' }), { a: ['b', 'c'] }); - st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayFormat: 'comma' }), { a: ['b', 'c'] }); - st.deepEqual(qs.parse('a=b,c', { arrayFormat: 'comma' }), { a: 'b,c' }); - st.deepEqual(qs.parse('a=b&a=c', { arrayFormat: 'comma' }), { a: ['b', 'c'] }); + t.test('allows enabling dot notation', function (st) { + st.deepEqual(qs.parse('a.b=c'), { 'a.b': 'c' }); + st.deepEqual(qs.parse('a.b=c', { allowDots: true }), { a: { b: 'c' } }); + st.end(); }); - t.test('arrayFormat: repeat allows only repeated values', function (st) { - st.deepEqual(qs.parse('a[]=b&a[]=c', { arrayFormat: 'repeat' }), { a: ['b', 'c'] }); - st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayFormat: 'repeat' }), { a: ['b', 'c'] }); - st.deepEqual(qs.parse('a=b,c', { arrayFormat: 'repeat' }), { a: 'b,c' }); - st.deepEqual(qs.parse('a=b&a=c', { arrayFormat: 'repeat' }), { a: ['b', 'c'] }); + t.test('decode dot keys correctly', function (st) { + st.deepEqual( + qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { allowDots: false, decodeDotInKeys: false }), + { 'name%2Eobj.first': 'John', 'name%2Eobj.last': 'Doe' }, + 'with allowDots false and decodeDotInKeys false' + ); + st.deepEqual( + qs.parse('name.obj.first=John&name.obj.last=Doe', { allowDots: true, decodeDotInKeys: false }), + { name: { obj: { first: 'John', last: 'Doe' } } }, + 'with allowDots false and decodeDotInKeys false' + ); + st.deepEqual( + qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { allowDots: true, decodeDotInKeys: false }), + { 'name%2Eobj': { first: 'John', last: 'Doe' } }, + 'with allowDots true and decodeDotInKeys false' + ); + st.deepEqual( + qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { allowDots: true, decodeDotInKeys: true }), + { 'name.obj': { first: 'John', last: 'Doe' } }, + 'with allowDots true and decodeDotInKeys true' + ); + + st.deepEqual( + qs.parse( + 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe', + { allowDots: false, decodeDotInKeys: false } + ), + { 'name%2Eobj%2Esubobject.first%2Egodly%2Ename': 'John', 'name%2Eobj%2Esubobject.last': 'Doe' }, + 'with allowDots false and decodeDotInKeys false' + ); + st.deepEqual( + qs.parse( + 'name.obj.subobject.first.godly.name=John&name.obj.subobject.last=Doe', + { allowDots: true, decodeDotInKeys: false } + ), + { name: { obj: { subobject: { first: { godly: { name: 'John' } }, last: 'Doe' } } } }, + 'with allowDots true and decodeDotInKeys false' + ); + st.deepEqual( + qs.parse( + 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe', + { allowDots: true, decodeDotInKeys: true } + ), + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + 'with allowDots true and decodeDotInKeys true' + ); + st.deepEqual( + qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe'), + { 'name%2Eobj.first': 'John', 'name%2Eobj.last': 'Doe' }, + 'with allowDots and decodeDotInKeys undefined' + ); + st.end(); }); - t.test('allows enabling dot notation', function (st) { - st.deepEqual(qs.parse('a.b=c'), { 'a.b': 'c' }); - st.deepEqual(qs.parse('a.b=c', { allowDots: true }), { a: { b: 'c' } }); + t.test('decodes dot in key of object, and allow enabling dot notation when decodeDotInKeys is set to true and allowDots is undefined', function (st) { + st.deepEqual( + qs.parse( + 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe', + { decodeDotInKeys: true } + ), + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + 'with allowDots undefined and decodeDotInKeys true' + ); + + st.end(); + }); + + t.test('throws when decodeDotInKeys is not of type boolean', function (st) { + st['throws']( + function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: 'foobar' }); }, + TypeError + ); + + st['throws']( + function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: 0 }); }, + TypeError + ); + st['throws']( + function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: NaN }); }, + TypeError + ); + + st['throws']( + function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: null }); }, + TypeError + ); + + st.end(); + }); + + t.test('allows empty arrays in obj values', function (st) { + st.deepEqual(qs.parse('foo[]&bar=baz', { allowEmptyArrays: true }), { foo: [], bar: 'baz' }); + st.deepEqual(qs.parse('foo[]&bar=baz', { allowEmptyArrays: false }), { foo: [''], bar: 'baz' }); + + st.end(); + }); + + t.test('throws when allowEmptyArrays is not of type boolean', function (st) { + st['throws']( + function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: 'foobar' }); }, + TypeError + ); + + st['throws']( + function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: 0 }); }, + TypeError + ); + st['throws']( + function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: NaN }); }, + TypeError + ); + + st['throws']( + function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: null }); }, + TypeError + ); + + st.end(); + }); + + t.test('allowEmptyArrays + strictNullHandling', function (st) { + st.deepEqual( + qs.parse('testEmptyArray[]', { strictNullHandling: true, allowEmptyArrays: true }), + { testEmptyArray: [] } + ); + st.end(); }); @@ -140,6 +263,9 @@ test('parse()', function (t) { t.test('limits specific array indices to arrayLimit', function (st) { st.deepEqual(qs.parse('a[20]=a', { arrayLimit: 20 }), { a: ['a'] }); st.deepEqual(qs.parse('a[21]=a', { arrayLimit: 20 }), { a: { 21: 'a' } }); + + st.deepEqual(qs.parse('a[20]=a'), { a: ['a'] }); + st.deepEqual(qs.parse('a[21]=a'), { a: { 21: 'a' } }); st.end(); }); @@ -318,15 +444,15 @@ test('parse()', function (t) { st.end(); }); - t.test('should not throw when a native prototype has an enumerable property', function (st) { - Object.prototype.crash = ''; - Array.prototype.crash = ''; + t.test('does not throw when a native prototype has an enumerable property', function (st) { + st.intercept(Object.prototype, 'crash', { value: '' }); + st.intercept(Array.prototype, 'crash', { value: '' }); + st.doesNotThrow(qs.parse.bind(null, 'a=b')); st.deepEqual(qs.parse('a=b'), { a: 'b' }); st.doesNotThrow(qs.parse.bind(null, 'a[][b]=c')); st.deepEqual(qs.parse('a[][b]=c'), { a: [{ b: 'c' }] }); - delete Object.prototype.crash; - delete Array.prototype.crash; + st.end(); }); @@ -357,8 +483,14 @@ test('parse()', function (t) { t.test('allows overriding array limit', function (st) { st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { 0: 'b' } }); + st.deepEqual(qs.parse('a[0]=b', { arrayLimit: 0 }), { a: ['b'] }); + st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: -1 }), { a: { '-1': 'b' } }); + st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: 0 }), { a: { '-1': 'b' } }); + + st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayLimit: -1 }), { a: { 0: 'b', 1: 'c' } }); st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } }); + st.end(); }); @@ -378,6 +510,7 @@ test('parse()', function (t) { st.deepEqual(qs.parse('?foo=bar', { ignoreQueryPrefix: true }), { foo: 'bar' }); st.deepEqual(qs.parse('foo=bar', { ignoreQueryPrefix: true }), { foo: 'bar' }); st.deepEqual(qs.parse('?foo=bar', { ignoreQueryPrefix: false }), { '?foo': 'bar' }); + st.end(); }); @@ -406,6 +539,16 @@ test('parse()', function (t) { st.deepEqual(qs.parse('foo=', { comma: true }), { foo: '' }); st.deepEqual(qs.parse('foo', { comma: true }), { foo: '' }); st.deepEqual(qs.parse('foo', { comma: true, strictNullHandling: true }), { foo: null }); + + // test cases inversed from from stringify tests + st.deepEqual(qs.parse('a[0]=c'), { a: ['c'] }); + st.deepEqual(qs.parse('a[]=c'), { a: ['c'] }); + st.deepEqual(qs.parse('a[]=c', { comma: true }), { a: ['c'] }); + + st.deepEqual(qs.parse('a[0]=c&a[1]=d'), { a: ['c', 'd'] }); + st.deepEqual(qs.parse('a[]=c&a[]=d'), { a: ['c', 'd'] }); + st.deepEqual(qs.parse('a=c,d', { comma: true }), { a: ['c', 'd'] }); + st.end(); }); @@ -438,6 +581,15 @@ test('parse()', function (t) { st.end(); }); + t.test('parses url-encoded brackets holds array of arrays when having two parts of strings with comma as array divider', function (st) { + st.deepEqual(qs.parse('foo%5B%5D=1,2,3&foo%5B%5D=4,5,6', { comma: true }), { foo: [['1', '2', '3'], ['4', '5', '6']] }); + st.deepEqual(qs.parse('foo%5B%5D=1,2,3&foo%5B%5D=', { comma: true }), { foo: [['1', '2', '3'], ''] }); + st.deepEqual(qs.parse('foo%5B%5D=1,2,3&foo%5B%5D=,', { comma: true }), { foo: [['1', '2', '3'], ['', '']] }); + st.deepEqual(qs.parse('foo%5B%5D=1,2,3&foo%5B%5D=a', { comma: true }), { foo: [['1', '2', '3'], 'a'] }); + + st.end(); + }); + t.test('parses comma delimited array while having percent-encoded comma treated as normal text', function (st) { st.deepEqual(qs.parse('foo=a%2Cb', { comma: true }), { foo: 'a,b' }); st.deepEqual(qs.parse('foo=a%2C%20b,d', { comma: true }), { foo: ['a, b', 'd'] }); @@ -485,10 +637,12 @@ test('parse()', function (t) { }); t.test('does not blow up when Buffer global is missing', function (st) { - var tempBuffer = global.Buffer; - delete global.Buffer; + var restore = mockProperty(global, 'Buffer', { 'delete': true }); + var result = qs.parse('a=b&c=d'); - global.Buffer = tempBuffer; + + restore(); + st.deepEqual(result, { a: 'b', c: 'd' }); st.end(); }); @@ -538,9 +692,8 @@ test('parse()', function (t) { st.end(); }); - t.test('parses null objects correctly', { skip: !Object.create }, function (st) { - var a = Object.create(null); - a.b = 'c'; + t.test('parses null objects correctly', { skip: !hasProto }, function (st) { + var a = { __proto__: null, b: 'c' }; st.deepEqual(qs.parse(a), { b: 'c' }); var result = qs.parse({ a: a }); @@ -587,6 +740,34 @@ test('parse()', function (t) { st.end(); }); + t.test('does not crash when the global Object prototype is frozen', { skip: !hasPropertyDescriptors || !hasOverrideMistake }, function (st) { + // We can't actually freeze the global Object prototype as that will interfere with other tests, and once an object is frozen, it + // can't be unfrozen. Instead, we add a new non-writable property to simulate this. + st.teardown(mockProperty(Object.prototype, 'frozenProp', { value: 'foo', nonWritable: true, nonEnumerable: true })); + + st['throws']( + function () { + var obj = {}; + obj.frozenProp = 'bar'; + }, + // node < 6 has a different error message + /^TypeError: Cannot assign to read only property 'frozenProp' of (?:object '#'|#)/, + 'regular assignment of an inherited non-writable property throws' + ); + + var parsed; + st.doesNotThrow( + function () { + parsed = qs.parse('frozenProp', { allowPrototypes: false }); + }, + 'parsing a nonwritable Object.prototype property does not throw' + ); + + st.deepEqual(parsed, {}, 'bare "frozenProp" results in {}'); + + st.end(); + }); + t.test('params starting with a closing bracket', function (st) { st.deepEqual(qs.parse(']=toString'), { ']': 'toString' }); st.deepEqual(qs.parse(']]=toString'), { ']]': 'toString' }); @@ -689,17 +870,25 @@ test('parse()', function (t) { st.end(); }); - t.test('can return null objects', { skip: !Object.create }, function (st) { - var expected = Object.create(null); - expected.a = Object.create(null); - expected.a.b = 'c'; - expected.a.hasOwnProperty = 'd'; + t.test('can return null objects', { skip: !hasProto }, function (st) { + var expected = { + __proto__: null, + a: { + __proto__: null, + b: 'c', + hasOwnProperty: 'd' + } + }; st.deepEqual(qs.parse('a[b]=c&a[hasOwnProperty]=d', { plainObjects: true }), expected); - st.deepEqual(qs.parse(null, { plainObjects: true }), Object.create(null)); - var expectedArray = Object.create(null); - expectedArray.a = Object.create(null); - expectedArray.a[0] = 'b'; - expectedArray.a.c = 'd'; + st.deepEqual(qs.parse(null, { plainObjects: true }), { __proto__: null }); + var expectedArray = { + __proto__: null, + a: { + __proto__: null, + 0: 'b', + c: 'd' + } + }; st.deepEqual(qs.parse('a[]=b&a[c]=d', { plainObjects: true }), expectedArray); st.end(); }); @@ -776,7 +965,7 @@ test('parse()', function (t) { st.end(); }); - t.test('should ignore an utf8 sentinel with an unknown value', function (st) { + t.test('ignores an utf8 sentinel with an unknown value', function (st) { st.deepEqual(qs.parse('utf8=foo&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'utf-8' }), { ø: 'ø' }); st.end(); }); @@ -817,6 +1006,15 @@ test('parse()', function (t) { st.end(); }); + t.test('interpretNumericEntities with comma:true and iso charset does not crash', function (st) { + st.deepEqual( + qs.parse('b&a[]=1,' + urlEncodedNumSmiley, { comma: true, charset: 'iso-8859-1', interpretNumericEntities: true }), + { b: '', a: ['1,☺'] } + ); + + st.end(); + }); + t.test('does not interpret %uXXXX syntax in iso-8859-1 mode', function (st) { st.deepEqual(qs.parse('%u263A=%u263A', { charset: 'iso-8859-1' }), { '%u263A': '%u263A' }); st.end(); @@ -837,5 +1035,242 @@ test('parse()', function (t) { st.end(); }); + t.test('parameter limit tests', function (st) { + st.test('does not throw error when within parameter limit', function (sst) { + var result = qs.parse('a=1&b=2&c=3', { parameterLimit: 5, throwOnLimitExceeded: true }); + sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses without errors'); + sst.end(); + }); + + st.test('throws error when throwOnLimitExceeded is present but not boolean', function (sst) { + sst['throws']( + function () { + qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: 3, throwOnLimitExceeded: 'true' }); + }, + new TypeError('`throwOnLimitExceeded` option must be a boolean'), + 'throws error when throwOnLimitExceeded is present and not boolean' + ); + sst.end(); + }); + + st.test('throws error when parameter limit exceeded', function (sst) { + sst['throws']( + function () { + qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: 3, throwOnLimitExceeded: true }); + }, + new RangeError('Parameter limit exceeded. Only 3 parameters allowed.'), + 'throws error when parameter limit is exceeded' + ); + sst.end(); + }); + + st.test('silently truncates when throwOnLimitExceeded is not given', function (sst) { + var result = qs.parse('a=1&b=2&c=3&d=4&e=5', { parameterLimit: 3 }); + sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses and truncates silently'); + sst.end(); + }); + + st.test('silently truncates when parameter limit exceeded without error', function (sst) { + var result = qs.parse('a=1&b=2&c=3&d=4&e=5', { parameterLimit: 3, throwOnLimitExceeded: false }); + sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses and truncates silently'); + sst.end(); + }); + + st.test('allows unlimited parameters when parameterLimit set to Infinity', function (sst) { + var result = qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: Infinity }); + sst.deepEqual(result, { a: '1', b: '2', c: '3', d: '4', e: '5', f: '6' }, 'parses all parameters without truncation'); + sst.end(); + }); + + st.end(); + }); + + t.test('array limit tests', function (st) { + st.test('does not throw error when array is within limit', function (sst) { + var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 5, throwOnLimitExceeded: true }); + sst.deepEqual(result, { a: ['1', '2', '3'] }, 'parses array without errors'); + sst.end(); + }); + + st.test('throws error when throwOnLimitExceeded is present but not boolean for array limit', function (sst) { + sst['throws']( + function () { + qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: 'true' }); + }, + new TypeError('`throwOnLimitExceeded` option must be a boolean'), + 'throws error when throwOnLimitExceeded is present and not boolean for array limit' + ); + sst.end(); + }); + + st.test('throws error when array limit exceeded', function (sst) { + sst['throws']( + function () { + qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: true }); + }, + new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'), + 'throws error when array limit is exceeded' + ); + sst.end(); + }); + + st.test('converts array to object if length is greater than limit', function (sst) { + var result = qs.parse('a[1]=1&a[2]=2&a[3]=3&a[4]=4&a[5]=5&a[6]=6', { arrayLimit: 5 }); + + sst.deepEqual(result, { a: { 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6' } }, 'parses into object if array length is greater than limit'); + sst.end(); + }); + + st.end(); + }); + + t.end(); +}); + +test('parses empty keys', function (t) { + emptyTestCases.forEach(function (testCase) { + t.test('skips empty string key with ' + testCase.input, function (st) { + st.deepEqual(qs.parse(testCase.input), testCase.noEmptyKeys); + + st.end(); + }); + }); +}); + +test('`duplicates` option', function (t) { + v.nonStrings.concat('not a valid option').forEach(function (invalidOption) { + if (typeof invalidOption !== 'undefined') { + t['throws']( + function () { qs.parse('', { duplicates: invalidOption }); }, + TypeError, + 'throws on invalid option: ' + inspect(invalidOption) + ); + } + }); + + t.deepEqual( + qs.parse('foo=bar&foo=baz'), + { foo: ['bar', 'baz'] }, + 'duplicates: default, combine' + ); + + t.deepEqual( + qs.parse('foo=bar&foo=baz', { duplicates: 'combine' }), + { foo: ['bar', 'baz'] }, + 'duplicates: combine' + ); + + t.deepEqual( + qs.parse('foo=bar&foo=baz', { duplicates: 'first' }), + { foo: 'bar' }, + 'duplicates: first' + ); + + t.deepEqual( + qs.parse('foo=bar&foo=baz', { duplicates: 'last' }), + { foo: 'baz' }, + 'duplicates: last' + ); + t.end(); }); + +test('qs strictDepth option - throw cases', function (t) { + t.test('throws an exception when depth exceeds the limit with strictDepth: true', function (st) { + st['throws']( + function () { + qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1, strictDepth: true }); + }, + RangeError, + 'throws RangeError' + ); + st.end(); + }); + + t.test('throws an exception for multiple nested arrays with strictDepth: true', function (st) { + st['throws']( + function () { + qs.parse('a[0][1][2][3][4]=b', { depth: 3, strictDepth: true }); + }, + RangeError, + 'throws RangeError' + ); + st.end(); + }); + + t.test('throws an exception for nested objects and arrays with strictDepth: true', function (st) { + st['throws']( + function () { + qs.parse('a[b][c][0][d][e]=f', { depth: 3, strictDepth: true }); + }, + RangeError, + 'throws RangeError' + ); + st.end(); + }); + + t.test('throws an exception for different types of values with strictDepth: true', function (st) { + st['throws']( + function () { + qs.parse('a[b][c][d][e]=true&a[b][c][d][f]=42', { depth: 3, strictDepth: true }); + }, + RangeError, + 'throws RangeError' + ); + st.end(); + }); + +}); + +test('qs strictDepth option - non-throw cases', function (t) { + t.test('when depth is 0 and strictDepth true, do not throw', function (st) { + st.doesNotThrow( + function () { + qs.parse('a[b][c][d][e]=true&a[b][c][d][f]=42', { depth: 0, strictDepth: true }); + }, + RangeError, + 'does not throw RangeError' + ); + st.end(); + }); + + t.test('parses successfully when depth is within the limit with strictDepth: true', function (st) { + st.doesNotThrow( + function () { + var result = qs.parse('a[b]=c', { depth: 1, strictDepth: true }); + st.deepEqual(result, { a: { b: 'c' } }, 'parses correctly'); + } + ); + st.end(); + }); + + t.test('does not throw an exception when depth exceeds the limit with strictDepth: false', function (st) { + st.doesNotThrow( + function () { + var result = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 }); + st.deepEqual(result, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } }, 'parses with depth limit'); + } + ); + st.end(); + }); + + t.test('parses successfully when depth is within the limit with strictDepth: false', function (st) { + st.doesNotThrow( + function () { + var result = qs.parse('a[b]=c', { depth: 1 }); + st.deepEqual(result, { a: { b: 'c' } }, 'parses correctly'); + } + ); + st.end(); + }); + + t.test('does not throw when depth is exactly at the limit with strictDepth: true', function (st) { + st.doesNotThrow( + function () { + var result = qs.parse('a[b][c]=d', { depth: 2, strictDepth: true }); + st.deepEqual(result, { a: { b: { c: 'd' } } }, 'parses correctly'); + } + ); + st.end(); + }); +}); diff --git a/backend/node_modules/qs/test/stringify.js b/backend/node_modules/qs/test/stringify.js index a3800aac..72531441 100644 --- a/backend/node_modules/qs/test/stringify.js +++ b/backend/node_modules/qs/test/stringify.js @@ -6,7 +6,10 @@ var utils = require('../lib/utils'); var iconv = require('iconv-lite'); var SaferBuffer = require('safer-buffer').Buffer; var hasSymbols = require('has-symbols'); -var hasBigInt = typeof BigInt === 'function'; +var mockProperty = require('mock-property'); +var emptyTestCases = require('./empty-keys-cases').emptyTestCases; +var hasProto = require('has-proto')(); +var hasBigInt = require('has-bigints')(); test('stringify()', function (t) { t.test('stringifies a querystring object', function (st) { @@ -63,6 +66,138 @@ test('stringify()', function (t) { st.end(); }); + t.test('encodes dot in key of object when encodeDotInKeys and allowDots is provided', function (st) { + st.equal( + qs.stringify( + { 'name.obj': { first: 'John', last: 'Doe' } }, + { allowDots: false, encodeDotInKeys: false } + ), + 'name.obj%5Bfirst%5D=John&name.obj%5Blast%5D=Doe', + 'with allowDots false and encodeDotInKeys false' + ); + st.equal( + qs.stringify( + { 'name.obj': { first: 'John', last: 'Doe' } }, + { allowDots: true, encodeDotInKeys: false } + ), + 'name.obj.first=John&name.obj.last=Doe', + 'with allowDots true and encodeDotInKeys false' + ); + st.equal( + qs.stringify( + { 'name.obj': { first: 'John', last: 'Doe' } }, + { allowDots: false, encodeDotInKeys: true } + ), + 'name%252Eobj%5Bfirst%5D=John&name%252Eobj%5Blast%5D=Doe', + 'with allowDots false and encodeDotInKeys true' + ); + st.equal( + qs.stringify( + { 'name.obj': { first: 'John', last: 'Doe' } }, + { allowDots: true, encodeDotInKeys: true } + ), + 'name%252Eobj.first=John&name%252Eobj.last=Doe', + 'with allowDots true and encodeDotInKeys true' + ); + + st.equal( + qs.stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: false, encodeDotInKeys: false } + ), + 'name.obj.subobject%5Bfirst.godly.name%5D=John&name.obj.subobject%5Blast%5D=Doe', + 'with allowDots false and encodeDotInKeys false' + ); + st.equal( + qs.stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: true, encodeDotInKeys: false } + ), + 'name.obj.subobject.first.godly.name=John&name.obj.subobject.last=Doe', + 'with allowDots false and encodeDotInKeys false' + ); + st.equal( + qs.stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: false, encodeDotInKeys: true } + ), + 'name%252Eobj%252Esubobject%5Bfirst.godly.name%5D=John&name%252Eobj%252Esubobject%5Blast%5D=Doe', + 'with allowDots false and encodeDotInKeys true' + ); + st.equal( + qs.stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: true, encodeDotInKeys: true } + ), + 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe', + 'with allowDots true and encodeDotInKeys true' + ); + + st.end(); + }); + + t.test('should encode dot in key of object, and automatically set allowDots to `true` when encodeDotInKeys is true and allowDots in undefined', function (st) { + st.equal( + qs.stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { encodeDotInKeys: true } + ), + 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe', + 'with allowDots undefined and encodeDotInKeys true' + ); + st.end(); + }); + + t.test('should encode dot in key of object when encodeDotInKeys and allowDots is provided, and nothing else when encodeValuesOnly is provided', function (st) { + st.equal( + qs.stringify({ 'name.obj': { first: 'John', last: 'Doe' } }, { + encodeDotInKeys: true, allowDots: true, encodeValuesOnly: true + }), + 'name%2Eobj.first=John&name%2Eobj.last=Doe' + ); + + st.equal( + qs.stringify({ 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, { allowDots: true, encodeDotInKeys: true, encodeValuesOnly: true }), + 'name%2Eobj%2Esubobject.first%2Egodly%2Ename=John&name%2Eobj%2Esubobject.last=Doe' + ); + + st.end(); + }); + + t.test('throws when `commaRoundTrip` is not a boolean', function (st) { + st['throws']( + function () { qs.stringify({}, { commaRoundTrip: 'not a boolean' }); }, + TypeError, + 'throws when `commaRoundTrip` is not a boolean' + ); + + st.end(); + }); + + t.test('throws when `encodeDotInKeys` is not a boolean', function (st) { + st['throws']( + function () { qs.stringify({ a: [], b: 'zz' }, { encodeDotInKeys: 'foobar' }); }, + TypeError + ); + + st['throws']( + function () { qs.stringify({ a: [], b: 'zz' }, { encodeDotInKeys: 0 }); }, + TypeError + ); + + st['throws']( + function () { qs.stringify({ a: [], b: 'zz' }, { encodeDotInKeys: NaN }); }, + TypeError + ); + + st['throws']( + function () { qs.stringify({ a: [], b: 'zz' }, { encodeDotInKeys: null }); }, + TypeError + ); + + st.end(); + }); + t.test('adds query prefix', function (st) { st.equal(qs.stringify({ a: 'b' }, { addQueryPrefix: true }), '?a=b'); st.end(); @@ -86,7 +221,7 @@ test('stringify()', function (t) { st.end(); }); - t.test('stringifies a nested object with dots notation', function (st) { + t.test('`allowDots` option: stringifies a nested object with dots notation', function (st) { st.equal(qs.stringify({ a: { b: 'c' } }, { allowDots: true }), 'a.b=c'); st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }, { allowDots: true }), 'a.b.c.d=e'); st.end(); @@ -108,6 +243,11 @@ test('stringify()', function (t) { 'a=b%2Cc%2Cd', 'comma => comma' ); + st.equal( + qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'comma', commaRoundTrip: true }), + 'a=b%2Cc%2Cd', + 'comma round trip => comma' + ); st.equal( qs.stringify({ a: ['b', 'c', 'd'] }), 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d', @@ -116,18 +256,118 @@ test('stringify()', function (t) { st.end(); }); - t.test('omits nulls when asked', function (st) { - st.equal(qs.stringify({ a: 'b', c: null }, { skipNulls: true }), 'a=b'); - st.end(); - }); + t.test('`skipNulls` option', function (st) { + st.equal( + qs.stringify({ a: 'b', c: null }, { skipNulls: true }), + 'a=b', + 'omits nulls when asked' + ); + + st.equal( + qs.stringify({ a: { b: 'c', d: null } }, { skipNulls: true }), + 'a%5Bb%5D=c', + 'omits nested nulls when asked' + ); - t.test('omits nested nulls when asked', function (st) { - st.equal(qs.stringify({ a: { b: 'c', d: null } }, { skipNulls: true }), 'a%5Bb%5D=c'); st.end(); }); t.test('omits array indices when asked', function (st) { st.equal(qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }), 'a=b&a=c&a=d'); + + st.end(); + }); + + t.test('omits object key/value pair when value is empty array', function (st) { + st.equal(qs.stringify({ a: [], b: 'zz' }), 'b=zz'); + + st.end(); + }); + + t.test('should not omit object key/value pair when value is empty array and when asked', function (st) { + st.equal(qs.stringify({ a: [], b: 'zz' }), 'b=zz'); + st.equal(qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: false }), 'b=zz'); + st.equal(qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: true }), 'a[]&b=zz'); + + st.end(); + }); + + t.test('should throw when allowEmptyArrays is not of type boolean', function (st) { + st['throws']( + function () { qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: 'foobar' }); }, + TypeError + ); + + st['throws']( + function () { qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: 0 }); }, + TypeError + ); + + st['throws']( + function () { qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: NaN }); }, + TypeError + ); + + st['throws']( + function () { qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: null }); }, + TypeError + ); + + st.end(); + }); + + t.test('allowEmptyArrays + strictNullHandling', function (st) { + st.equal( + qs.stringify( + { testEmptyArray: [] }, + { strictNullHandling: true, allowEmptyArrays: true } + ), + 'testEmptyArray[]' + ); + + st.end(); + }); + + t.test('stringifies an array value with one item vs multiple items', function (st) { + st.test('non-array item', function (s2t) { + s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=c'); + s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a=c'); + s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c'); + s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true }), 'a=c'); + + s2t.end(); + }); + + st.test('array with a single item', function (s2t) { + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c'); + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c'); + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c'); + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), 'a[]=c'); // so it parses back as an array + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true }), 'a[0]=c'); + + s2t.end(); + }); + + st.test('array with multiple items', function (s2t) { + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c&a[1]=d'); + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c&a[]=d'); + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c,d'); + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), 'a=c,d'); + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true }), 'a[0]=c&a[1]=d'); + + s2t.end(); + }); + + st.test('array with multiple items with a comma inside', function (s2t) { + s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c%2Cd,e'); + s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma' }), 'a=c%2Cd%2Ce'); + + s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), 'a=c%2Cd,e'); + s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma', commaRoundTrip: true }), 'a=c%2Cd%2Ce'); + + s2t.end(); + }); + st.end(); }); @@ -139,6 +379,44 @@ test('stringify()', function (t) { st.end(); }); + t.test('stringifies comma and empty array values', function (st) { + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'indices' }), 'a[0]=,&a[1]=&a[2]=c,d%'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'brackets' }), 'a[]=,&a[]=&a[]=c,d%'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'comma' }), 'a=,,,c,d%'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'repeat' }), 'a=,&a=&a=c,d%'); + + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=%2C&a[1]=&a[2]=c%2Cd%25'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=%2C&a[]=&a[]=c%2Cd%25'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=%2C,,c%2Cd%25'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=%2C&a=&a=c%2Cd%25'); + + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), 'a%5B0%5D=%2C&a%5B1%5D=&a%5B2%5D=c%2Cd%25'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }), 'a%5B%5D=%2C&a%5B%5D=&a%5B%5D=c%2Cd%25'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), 'a=%2C%2C%2Cc%2Cd%25'); + st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), 'a=%2C&a=&a=c%2Cd%25'); + + st.end(); + }); + + t.test('stringifies comma and empty non-array values', function (st) { + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'indices' }), 'a=,&b=&c=c,d%'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'brackets' }), 'a=,&b=&c=c,d%'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'comma' }), 'a=,&b=&c=c,d%'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'repeat' }), 'a=,&b=&c=c,d%'); + + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=%2C&b=&c=c%2Cd%25'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a=%2C&b=&c=c%2Cd%25'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=%2C&b=&c=c%2Cd%25'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=%2C&b=&c=c%2Cd%25'); + + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), 'a=%2C&b=&c=c%2Cd%25'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }), 'a=%2C&b=&c=c%2Cd%25'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), 'a=%2C&b=&c=c%2Cd%25'); + st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), 'a=%2C&b=&c=c%2Cd%25'); + + st.end(); + }); + t.test('stringifies a nested array value with dots notation', function (st) { st.equal( qs.stringify( @@ -177,36 +455,44 @@ test('stringify()', function (t) { t.test('stringifies an object inside an array', function (st) { st.equal( - qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'indices' }), - 'a%5B0%5D%5Bb%5D=c', // a[0][b]=c - 'indices => brackets' + qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'indices', encodeValuesOnly: true }), + 'a[0][b]=c', + 'indices => indices' ); st.equal( - qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'brackets' }), - 'a%5B%5D%5Bb%5D=c', // a[][b]=c + qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'repeat', encodeValuesOnly: true }), + 'a[b]=c', + 'repeat => repeat' + ); + st.equal( + qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'brackets', encodeValuesOnly: true }), + 'a[][b]=c', 'brackets => brackets' ); st.equal( - qs.stringify({ a: [{ b: 'c' }] }), - 'a%5B0%5D%5Bb%5D=c', + qs.stringify({ a: [{ b: 'c' }] }, { encodeValuesOnly: true }), + 'a[0][b]=c', 'default => indices' ); st.equal( - qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'indices' }), - 'a%5B0%5D%5Bb%5D%5Bc%5D%5B0%5D=1', + qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'indices', encodeValuesOnly: true }), + 'a[0][b][c][0]=1', 'indices => indices' ); - st.equal( - qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'brackets' }), - 'a%5B%5D%5Bb%5D%5Bc%5D%5B%5D=1', + qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'repeat', encodeValuesOnly: true }), + 'a[b][c]=1', + 'repeat => repeat' + ); + st.equal( + qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'brackets', encodeValuesOnly: true }), + 'a[][b][c][]=1', 'brackets => brackets' ); - st.equal( - qs.stringify({ a: [{ b: { c: [1] } }] }), - 'a%5B0%5D%5Bb%5D%5Bc%5D%5B0%5D=1', + qs.stringify({ a: [{ b: { c: [1] } }] }, { encodeValuesOnly: true }), + 'a[0][b][c][0]=1', 'default => indices' ); @@ -308,17 +594,17 @@ test('stringify()', function (t) { st.end(); }); - t.test('uses indices notation for arrays when no arrayFormat=indices', function (st) { + t.test('uses indices notation for arrays when arrayFormat=indices', function (st) { st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }), 'a%5B0%5D=b&a%5B1%5D=c'); st.end(); }); - t.test('uses repeat notation for arrays when no arrayFormat=repeat', function (st) { + t.test('uses repeat notation for arrays when arrayFormat=repeat', function (st) { st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }), 'a=b&a=c'); st.end(); }); - t.test('uses brackets notation for arrays when no arrayFormat=brackets', function (st) { + t.test('uses brackets notation for arrays when arrayFormat=brackets', function (st) { st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }), 'a%5B%5D=b&a%5B%5D=c'); st.end(); }); @@ -349,11 +635,13 @@ test('stringify()', function (t) { st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets' }), 'b[]=&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat' }), 'b=&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma' }), 'b=&c=c'); + st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', commaRoundTrip: true }), 'b[]=&c=c'); // with strictNullHandling st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', strictNullHandling: true }), 'b[0]&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', strictNullHandling: true }), 'b[]&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat', strictNullHandling: true }), 'b&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', strictNullHandling: true }), 'b&c=c'); + st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', strictNullHandling: true, commaRoundTrip: true }), 'b[]&c=c'); // with skipNulls st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', skipNulls: true }), 'c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', skipNulls: true }), 'c=c'); @@ -363,10 +651,8 @@ test('stringify()', function (t) { st.end(); }); - t.test('stringifies a null object', { skip: !Object.create }, function (st) { - var obj = Object.create(null); - obj.a = 'b'; - st.equal(qs.stringify(obj), 'a=b'); + t.test('stringifies a null object', { skip: !hasProto }, function (st) { + st.equal(qs.stringify({ __proto__: null, a: 'b' }), 'a=b'); st.end(); }); @@ -378,11 +664,8 @@ test('stringify()', function (t) { st.end(); }); - t.test('stringifies an object with a null object as a child', { skip: !Object.create }, function (st) { - var obj = { a: Object.create(null) }; - - obj.a.b = 'c'; - st.equal(qs.stringify(obj), 'a%5Bb%5D=c'); + t.test('stringifies an object with a null object as a child', { skip: !hasProto }, function (st) { + st.equal(qs.stringify({ a: { __proto__: null, b: 'c' } }), 'a%5Bb%5D=c'); st.end(); }); @@ -413,10 +696,11 @@ test('stringify()', function (t) { }); t.test('skips properties that are part of the object prototype', function (st) { - Object.prototype.crash = 'test'; + st.intercept(Object.prototype, 'crash', { value: 'test' }); + st.equal(qs.stringify({ a: 'b' }), 'a=b'); st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c'); - delete Object.prototype.crash; + st.end(); }); @@ -440,10 +724,12 @@ test('stringify()', function (t) { }); t.test('does not blow up when Buffer global is missing', function (st) { - var tempBuffer = global.Buffer; - delete global.Buffer; + var restore = mockProperty(global, 'Buffer', { 'delete': true }); + var result = qs.stringify({ a: 'b', c: 'd' }); - global.Buffer = tempBuffer; + + restore(); + st.equal(result, 'a=b&c=d'); st.end(); }); @@ -492,9 +778,17 @@ test('stringify()', function (t) { }; st.equal( - qs.stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true }), + qs.stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'filters[$and][0][function]=gte&filters[$and][0][arguments][0][function]=hour_of_day&filters[$and][0][arguments][1]=0&filters[$and][1][function]=lte&filters[$and][1][arguments][0][function]=hour_of_day&filters[$and][1][arguments][1]=23' ); + st.equal( + qs.stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + 'filters[$and][][function]=gte&filters[$and][][arguments][][function]=hour_of_day&filters[$and][][arguments][]=0&filters[$and][][function]=lte&filters[$and][][arguments][][function]=hour_of_day&filters[$and][][arguments][]=23' + ); + st.equal( + qs.stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), + 'filters[$and][function]=gte&filters[$and][arguments][function]=hour_of_day&filters[$and][arguments]=0&filters[$and][function]=lte&filters[$and][arguments][function]=hour_of_day&filters[$and][arguments]=23' + ); st.end(); }); @@ -607,13 +901,28 @@ test('stringify()', function (t) { st.end(); }); + t.test('receives the default encoder as a second argument', function (st) { + st.plan(8); + + qs.stringify({ a: 1, b: new Date(), c: true, d: [1] }, { + encoder: function (str) { + st.match(typeof str, /^(?:string|number|boolean)$/); + return ''; + } + }); + + st.end(); + }); + t.test('receives the default encoder as a second argument', function (st) { st.plan(2); + qs.stringify({ a: 1 }, { encoder: function (str, defaultEncoder) { st.equal(defaultEncoder, utils.encode); } }); + st.end(); }); @@ -684,6 +993,18 @@ test('stringify()', function (t) { 'a=' + date.getTime(), 'works with arrayFormat comma' ); + st.equal( + qs.stringify( + { a: [date] }, + { + serializeDate: function (d) { return d.getTime(); }, + arrayFormat: 'comma', + commaRoundTrip: true + } + ), + 'a%5B%5D=' + date.getTime(), + 'works with arrayFormat comma' + ); st.end(); }); @@ -714,16 +1035,14 @@ test('stringify()', function (t) { }); t.test('Edge cases and unknown formats', function (st) { - ['UFO1234', false, 1234, null, {}, []].forEach( - function (format) { - st['throws']( - function () { - qs.stringify({ a: 'b c' }, { format: format }); - }, - new TypeError('Unknown format option provided.') - ); - } - ); + ['UFO1234', false, 1234, null, {}, []].forEach(function (format) { + st['throws']( + function () { + qs.stringify({ a: 'b c' }, { format: format }); + }, + new TypeError('Unknown format option provided.') + ); + }); st.end(); }); @@ -731,16 +1050,53 @@ test('stringify()', function (t) { st.equal( qs.stringify( { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, - { encodeValuesOnly: true } + { encodeValuesOnly: true, arrayFormat: 'indices' } + ), + 'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h', + 'encodeValuesOnly + indices' + ); + st.equal( + qs.stringify( + { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, + { encodeValuesOnly: true, arrayFormat: 'brackets' } + ), + 'a=b&c[]=d&c[]=e%3Df&f[][]=g&f[][]=h', + 'encodeValuesOnly + brackets' + ); + st.equal( + qs.stringify( + { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, + { encodeValuesOnly: true, arrayFormat: 'repeat' } ), - 'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h' + 'a=b&c=d&c=e%3Df&f=g&f=h', + 'encodeValuesOnly + repeat' + ); + + st.equal( + qs.stringify( + { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, + { arrayFormat: 'indices' } + ), + 'a=b&c%5B0%5D=d&c%5B1%5D=e&f%5B0%5D%5B0%5D=g&f%5B1%5D%5B0%5D=h', + 'no encodeValuesOnly + indices' ); st.equal( qs.stringify( - { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] } + { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, + { arrayFormat: 'brackets' } ), - 'a=b&c%5B0%5D=d&c%5B1%5D=e&f%5B0%5D%5B0%5D=g&f%5B1%5D%5B0%5D=h' + 'a=b&c%5B%5D=d&c%5B%5D=e&f%5B%5D%5B%5D=g&f%5B%5D%5B%5D=h', + 'no encodeValuesOnly + brackets' ); + st.equal( + qs.stringify( + { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, + { arrayFormat: 'repeat' } + ), + 'a=b&c=d&c=e&f=g&f=h', + 'no encodeValuesOnly + repeat' + ); + st.end(); }); @@ -777,13 +1133,19 @@ test('stringify()', function (t) { st.end(); }); - t.test('adds the right sentinel when instructed to and the charset is utf-8', function (st) { - st.equal(qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'utf-8' }), 'utf8=%E2%9C%93&a=%C3%A6'); - st.end(); - }); + t.test('`charsetSentinel` option', function (st) { + st.equal( + qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'utf-8' }), + 'utf8=%E2%9C%93&a=%C3%A6', + 'adds the right sentinel when instructed to and the charset is utf-8' + ); + + st.equal( + qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' }), + 'utf8=%26%2310003%3B&a=%E6', + 'adds the right sentinel when instructed to and the charset is iso-8859-1' + ); - t.test('adds the right sentinel when instructed to and the charset is iso-8859-1', function (st) { - st.equal(qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' }), 'utf8=%26%2310003%3B&a=%E6'); st.end(); }); @@ -834,13 +1196,15 @@ test('stringify()', function (t) { var withArray = { a: { b: [{ c: 'd', e: 'f' }] } }; st.equal(qs.stringify(obj, { encode: false }), 'a[b][c]=d&a[b][e]=f', 'no array, no arrayFormat'); - st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'bracket' }), 'a[b][c]=d&a[b][e]=f', 'no array, bracket'); + st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'brackets' }), 'a[b][c]=d&a[b][e]=f', 'no array, bracket'); st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'indices' }), 'a[b][c]=d&a[b][e]=f', 'no array, indices'); + st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'repeat' }), 'a[b][c]=d&a[b][e]=f', 'no array, repeat'); st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'comma' }), 'a[b][c]=d&a[b][e]=f', 'no array, comma'); st.equal(qs.stringify(withArray, { encode: false }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, no arrayFormat'); - st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'bracket' }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, bracket'); + st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'brackets' }), 'a[b][][c]=d&a[b][][e]=f', 'array, bracket'); st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'indices' }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, indices'); + st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'repeat' }), 'a[b][c]=d&a[b][e]=f', 'array, repeat'); st.equal( qs.stringify(withArray, { encode: false, arrayFormat: 'comma' }), '???', @@ -853,13 +1217,90 @@ test('stringify()', function (t) { t.test('stringifies sparse arrays', function (st) { /* eslint no-sparse-arrays: 0 */ - st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true }), 'a[1]=2&a[4]=1'); - st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true }), 'a[1][b][2][c]=1'); - st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true }), 'a[1][2][3][c]=1'); - st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true }), 'a[1][2][3][c][1]=1'); + st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[1]=2&a[4]=1'); + st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=2&a[]=1'); + st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=2&a=1'); + + st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[1][b][2][c]=1'); + st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[][b][][c]=1'); + st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a[b][c]=1'); + + st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[1][2][3][c]=1'); + st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[][][][c]=1'); + st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a[c]=1'); + + st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[1][2][3][c][1]=1'); + st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[][][][c][]=1'); + st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a[c]=1'); + + st.end(); + }); + + t.test('encodes a very long string', function (st) { + var chars = []; + var expected = []; + for (var i = 0; i < 5e3; i++) { + chars.push(' ' + i); + + expected.push('%20' + i); + } + + var obj = { + foo: chars.join('') + }; + + st.equal( + qs.stringify(obj, { arrayFormat: 'brackets', charset: 'utf-8' }), + 'foo=' + expected.join('') + ); st.end(); }); t.end(); }); + +test('stringifies empty keys', function (t) { + emptyTestCases.forEach(function (testCase) { + t.test('stringifies an object with empty string key with ' + testCase.input, function (st) { + st.deepEqual( + qs.stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'indices' }), + testCase.stringifyOutput.indices, + 'test case: ' + testCase.input + ', indices' + ); + st.deepEqual( + qs.stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'brackets' }), + testCase.stringifyOutput.brackets, + 'test case: ' + testCase.input + ', brackets' + ); + st.deepEqual( + qs.stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'repeat' }), + testCase.stringifyOutput.repeat, + 'test case: ' + testCase.input + ', repeat' + ); + + st.end(); + }); + }); + + t.test('edge case with object/arrays', function (st) { + st.deepEqual(qs.stringify({ '': { '': [2, 3] } }, { encode: false }), '[][0]=2&[][1]=3'); + st.deepEqual(qs.stringify({ '': { '': [2, 3], a: 2 } }, { encode: false }), '[][0]=2&[][1]=3&[a]=2'); + st.deepEqual(qs.stringify({ '': { '': [2, 3] } }, { encode: false, arrayFormat: 'indices' }), '[][0]=2&[][1]=3'); + st.deepEqual(qs.stringify({ '': { '': [2, 3], a: 2 } }, { encode: false, arrayFormat: 'indices' }), '[][0]=2&[][1]=3&[a]=2'); + + st.end(); + }); + + t.test('stringifies non-string keys', function (st) { + var actual = qs.stringify({ a: 'b', 'false': {} }, { + filter: ['a', false, null], + allowDots: true, + encodeDotInKeys: true + }); + + st.equal(actual, 'a=b', 'stringifies correctly'); + + st.end(); + }); +}); diff --git a/backend/node_modules/qs/test/utils.js b/backend/node_modules/qs/test/utils.js index aa84dfdc..39335165 100644 --- a/backend/node_modules/qs/test/utils.js +++ b/backend/node_modules/qs/test/utils.js @@ -4,6 +4,8 @@ var test = require('tape'); var inspect = require('object-inspect'); var SaferBuffer = require('safer-buffer').Buffer; var forEach = require('for-each'); +var v = require('es-value-fixtures'); + var utils = require('../lib/utils'); test('merge()', function (t) { @@ -28,6 +30,20 @@ test('merge()', function (t) { var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar'); t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true }); + var func = function f() {}; + t.deepEqual( + utils.merge(func, { foo: 'bar' }), + [func, { foo: 'bar' }], + 'functions can not be merged into' + ); + + func.bar = 'baz'; + t.deepEqual( + utils.merge({ foo: 'bar' }, func), + { foo: 'bar', bar: 'baz' }, + 'functions can be merge sources' + ); + t.test( 'avoids invoking array setters unnecessarily', { skip: typeof Object.defineProperty !== 'function' }, @@ -119,6 +135,104 @@ test('combine()', function (t) { t.end(); }); +test('decode', function (t) { + t.equal( + utils.decode('a+b'), + 'a b', + 'decodes + to space' + ); + + t.equal( + utils.decode('name%2Eobj'), + 'name.obj', + 'decodes a string' + ); + t.equal( + utils.decode('name%2Eobj%2Efoo', null, 'iso-8859-1'), + 'name.obj.foo', + 'decodes a string in iso-8859-1' + ); + + t.end(); +}); + +test('encode', function (t) { + forEach(v.nullPrimitives, function (nullish) { + t['throws']( + function () { utils.encode(nullish); }, + TypeError, + inspect(nullish) + ' is not a string' + ); + }); + + t.equal(utils.encode(''), '', 'empty string returns itself'); + t.deepEqual(utils.encode([]), [], 'empty array returns itself'); + t.deepEqual(utils.encode({ length: 0 }), { length: 0 }, 'empty arraylike returns itself'); + + t.test('symbols', { skip: !v.hasSymbols }, function (st) { + st.equal(utils.encode(Symbol('x')), 'Symbol%28x%29', 'symbol is encoded'); + + st.end(); + }); + + t.equal( + utils.encode('(abc)'), + '%28abc%29', + 'encodes parentheses' + ); + t.equal( + utils.encode({ toString: function () { return '(abc)'; } }), + '%28abc%29', + 'toStrings and encodes parentheses' + ); + + t.equal( + utils.encode('abc 123 💩', null, 'iso-8859-1'), + 'abc%20123%20%26%2355357%3B%26%2356489%3B', + 'encodes in iso-8859-1' + ); + + var longString = ''; + var expectedString = ''; + for (var i = 0; i < 1500; i++) { + longString += ' '; + expectedString += '%20'; + } + + t.equal( + utils.encode(longString), + expectedString, + 'encodes a long string' + ); + + t.equal( + utils.encode('\x28\x29'), + '%28%29', + 'encodes parens normally' + ); + t.equal( + utils.encode('\x28\x29', null, null, null, 'RFC1738'), + '()', + 'does not encode parens in RFC1738' + ); + + // todo RFC1738 format + + t.equal( + utils.encode('Āက豈'), + '%C4%80%E1%80%80%EF%A4%80', + 'encodes multibyte chars' + ); + + t.equal( + utils.encode('\uD83D \uDCA9'), + '%F0%9F%90%A0%F0%BA%90%80', + 'encodes lone surrogates' + ); + + t.end(); +}); + test('isBuffer()', function (t) { forEach([null, undefined, true, false, '', 'abc', 42, 0, NaN, {}, [], function () {}, /a/g], function (x) { t.equal(utils.isBuffer(x), false, inspect(x) + ' is not a buffer'); @@ -134,3 +248,15 @@ test('isBuffer()', function (t) { t.equal(utils.isBuffer(buffer), true, 'real Buffer instance is a buffer'); t.end(); }); + +test('isRegExp()', function (t) { + t.equal(utils.isRegExp(/a/g), true, 'RegExp is a RegExp'); + t.equal(utils.isRegExp(new RegExp('a', 'g')), true, 'new RegExp is a RegExp'); + t.equal(utils.isRegExp(new Date()), false, 'Date is not a RegExp'); + + forEach(v.primitives, function (primitive) { + t.equal(utils.isRegExp(primitive), false, inspect(primitive) + ' is not a RegExp'); + }); + + t.end(); +}); diff --git a/backend/node_modules/raw-body/HISTORY.md b/backend/node_modules/raw-body/HISTORY.md deleted file mode 100644 index 0b6b8373..00000000 --- a/backend/node_modules/raw-body/HISTORY.md +++ /dev/null @@ -1,303 +0,0 @@ -2.5.1 / 2022-02-28 -================== - - * Fix error on early async hooks implementations - -2.5.0 / 2022-02-21 -================== - - * Prevent loss of async hooks context - * Prevent hanging when stream is not readable - * deps: http-errors@2.0.0 - - deps: depd@2.0.0 - - deps: statuses@2.0.1 - -2.4.3 / 2022-02-14 -================== - - * deps: bytes@3.1.2 - -2.4.2 / 2021-11-16 -================== - - * deps: bytes@3.1.1 - * deps: http-errors@1.8.1 - - deps: setprototypeof@1.2.0 - - deps: toidentifier@1.0.1 - -2.4.1 / 2019-06-25 -================== - - * deps: http-errors@1.7.3 - - deps: inherits@2.0.4 - -2.4.0 / 2019-04-17 -================== - - * deps: bytes@3.1.0 - - Add petabyte (`pb`) support - * deps: http-errors@1.7.2 - - Set constructor name when possible - - deps: setprototypeof@1.1.1 - - deps: statuses@'>= 1.5.0 < 2' - * deps: iconv-lite@0.4.24 - - Added encoding MIK - -2.3.3 / 2018-05-08 -================== - - * deps: http-errors@1.6.3 - - deps: depd@~1.1.2 - - deps: setprototypeof@1.1.0 - - deps: statuses@'>= 1.3.1 < 2' - * deps: iconv-lite@0.4.23 - - Fix loading encoding with year appended - - Fix deprecation warnings on Node.js 10+ - -2.3.2 / 2017-09-09 -================== - - * deps: iconv-lite@0.4.19 - - Fix ISO-8859-1 regression - - Update Windows-1255 - -2.3.1 / 2017-09-07 -================== - - * deps: bytes@3.0.0 - * deps: http-errors@1.6.2 - - deps: depd@1.1.1 - * perf: skip buffer decoding on overage chunk - -2.3.0 / 2017-08-04 -================== - - * Add TypeScript definitions - * Use `http-errors` for standard emitted errors - * deps: bytes@2.5.0 - * deps: iconv-lite@0.4.18 - - Add support for React Native - - Add a warning if not loaded as utf-8 - - Fix CESU-8 decoding in Node.js 8 - - Improve speed of ISO-8859-1 encoding - -2.2.0 / 2017-01-02 -================== - - * deps: iconv-lite@0.4.15 - - Added encoding MS-31J - - Added encoding MS-932 - - Added encoding MS-936 - - Added encoding MS-949 - - Added encoding MS-950 - - Fix GBK/GB18030 handling of Euro character - -2.1.7 / 2016-06-19 -================== - - * deps: bytes@2.4.0 - * perf: remove double-cleanup on happy path - -2.1.6 / 2016-03-07 -================== - - * deps: bytes@2.3.0 - - Drop partial bytes on all parsed units - - Fix parsing byte string that looks like hex - -2.1.5 / 2015-11-30 -================== - - * deps: bytes@2.2.0 - * deps: iconv-lite@0.4.13 - -2.1.4 / 2015-09-27 -================== - - * Fix masking critical errors from `iconv-lite` - * deps: iconv-lite@0.4.12 - - Fix CESU-8 decoding in Node.js 4.x - -2.1.3 / 2015-09-12 -================== - - * Fix sync callback when attaching data listener causes sync read - - Node.js 0.10 compatibility issue - -2.1.2 / 2015-07-05 -================== - - * Fix error stack traces to skip `makeError` - * deps: iconv-lite@0.4.11 - - Add encoding CESU-8 - -2.1.1 / 2015-06-14 -================== - - * Use `unpipe` module for unpiping requests - -2.1.0 / 2015-05-28 -================== - - * deps: iconv-lite@0.4.10 - - Improved UTF-16 endianness detection - - Leading BOM is now removed when decoding - - The encoding UTF-16 without BOM now defaults to UTF-16LE when detection fails - -2.0.2 / 2015-05-21 -================== - - * deps: bytes@2.1.0 - - Slight optimizations - -2.0.1 / 2015-05-10 -================== - - * Fix a false-positive when unpiping in Node.js 0.8 - -2.0.0 / 2015-05-08 -================== - - * Return a promise without callback instead of thunk - * deps: bytes@2.0.1 - - units no longer case sensitive when parsing - -1.3.4 / 2015-04-15 -================== - - * Fix hanging callback if request aborts during read - * deps: iconv-lite@0.4.8 - - Add encoding alias UNICODE-1-1-UTF-7 - -1.3.3 / 2015-02-08 -================== - - * deps: iconv-lite@0.4.7 - - Gracefully support enumerables on `Object.prototype` - -1.3.2 / 2015-01-20 -================== - - * deps: iconv-lite@0.4.6 - - Fix rare aliases of single-byte encodings - -1.3.1 / 2014-11-21 -================== - - * deps: iconv-lite@0.4.5 - - Fix Windows-31J and X-SJIS encoding support - -1.3.0 / 2014-07-20 -================== - - * Fully unpipe the stream on error - - Fixes `Cannot switch to old mode now` error on Node.js 0.10+ - -1.2.3 / 2014-07-20 -================== - - * deps: iconv-lite@0.4.4 - - Added encoding UTF-7 - -1.2.2 / 2014-06-19 -================== - - * Send invalid encoding error to callback - -1.2.1 / 2014-06-15 -================== - - * deps: iconv-lite@0.4.3 - - Added encodings UTF-16BE and UTF-16 with BOM - -1.2.0 / 2014-06-13 -================== - - * Passing string as `options` interpreted as encoding - * Support all encodings from `iconv-lite` - -1.1.7 / 2014-06-12 -================== - - * use `string_decoder` module from npm - -1.1.6 / 2014-05-27 -================== - - * check encoding for old streams1 - * support node.js < 0.10.6 - -1.1.5 / 2014-05-14 -================== - - * bump bytes - -1.1.4 / 2014-04-19 -================== - - * allow true as an option - * bump bytes - -1.1.3 / 2014-03-02 -================== - - * fix case when length=null - -1.1.2 / 2013-12-01 -================== - - * be less strict on state.encoding check - -1.1.1 / 2013-11-27 -================== - - * add engines - -1.1.0 / 2013-11-27 -================== - - * add err.statusCode and err.type - * allow for encoding option to be true - * pause the stream instead of dumping on error - * throw if the stream's encoding is set - -1.0.1 / 2013-11-19 -================== - - * dont support streams1, throw if dev set encoding - -1.0.0 / 2013-11-17 -================== - - * rename `expected` option to `length` - -0.2.0 / 2013-11-15 -================== - - * republish - -0.1.1 / 2013-11-15 -================== - - * use bytes - -0.1.0 / 2013-11-11 -================== - - * generator support - -0.0.3 / 2013-10-10 -================== - - * update repo - -0.0.2 / 2013-09-14 -================== - - * dump stream on bad headers - * listen to events after defining received and buffers - -0.0.1 / 2013-09-14 -================== - - * Initial release diff --git a/backend/node_modules/raw-body/README.md b/backend/node_modules/raw-body/README.md index 695c6607..d9b36d61 100644 --- a/backend/node_modules/raw-body/README.md +++ b/backend/node_modules/raw-body/README.md @@ -219,5 +219,5 @@ server.listen(3000); [coveralls-url]: https://coveralls.io/r/stream-utils/raw-body?branch=master [downloads-image]: https://img.shields.io/npm/dm/raw-body.svg [downloads-url]: https://npmjs.org/package/raw-body -[github-actions-ci-image]: https://img.shields.io/github/workflow/status/stream-utils/raw-body/ci/master?label=ci +[github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/stream-utils/raw-body/ci.yml?branch=master&label=ci [github-actions-ci-url]: https://github.com/jshttp/stream-utils/raw-body?query=workflow%3Aci diff --git a/backend/node_modules/raw-body/index.js b/backend/node_modules/raw-body/index.js index a8f537f3..9cdcd122 100644 --- a/backend/node_modules/raw-body/index.js +++ b/backend/node_modules/raw-body/index.js @@ -69,6 +69,13 @@ function getRawBody (stream, options, callback) { var done = callback var opts = options || {} + // light validation + if (stream === undefined) { + throw new TypeError('argument stream is required') + } else if (typeof stream !== 'object' || stream === null || typeof stream.on !== 'function') { + throw new TypeError('argument stream must be a stream') + } + if (options === true || typeof options === 'string') { // short cut for encoding opts = { diff --git a/backend/node_modules/raw-body/package.json b/backend/node_modules/raw-body/package.json index 50fc90ad..d8120afa 100644 --- a/backend/node_modules/raw-body/package.json +++ b/backend/node_modules/raw-body/package.json @@ -1,7 +1,7 @@ { "name": "raw-body", "description": "Get and validate the raw body of a readable stream.", - "version": "2.5.1", + "version": "2.5.3", "author": "Jonathan Ong (http://jongleberry.com)", "contributors": [ "Douglas Christopher Wilson ", @@ -10,21 +10,21 @@ "license": "MIT", "repository": "stream-utils/raw-body", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "devDependencies": { "bluebird": "3.7.2", - "eslint": "7.32.0", - "eslint-config-standard": "14.1.1", - "eslint-plugin-import": "2.25.4", - "eslint-plugin-markdown": "2.2.1", + "eslint": "8.34.0", + "eslint-config-standard": "15.0.1", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-markdown": "3.0.0", "eslint-plugin-node": "11.1.0", - "eslint-plugin-promise": "5.2.0", + "eslint-plugin-promise": "6.1.1", "eslint-plugin-standard": "4.1.0", - "mocha": "9.2.1", + "mocha": "10.2.0", "nyc": "15.1.0", "readable-stream": "2.3.7", "safe-buffer": "5.2.1" @@ -33,10 +33,8 @@ "node": ">= 0.8" }, "files": [ - "HISTORY.md", "LICENSE", "README.md", - "SECURITY.md", "index.d.ts", "index.js" ], diff --git a/backend/node_modules/react-dom/LICENSE b/backend/node_modules/react-dom/LICENSE new file mode 100644 index 00000000..b93be905 --- /dev/null +++ b/backend/node_modules/react-dom/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Meta Platforms, Inc. and affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/backend/node_modules/react-dom/README.md b/backend/node_modules/react-dom/README.md new file mode 100644 index 00000000..b078f194 --- /dev/null +++ b/backend/node_modules/react-dom/README.md @@ -0,0 +1,60 @@ +# `react-dom` + +This package serves as the entry point to the DOM and server renderers for React. It is intended to be paired with the generic React package, which is shipped as `react` to npm. + +## Installation + +```sh +npm install react react-dom +``` + +## Usage + +### In the browser + +```js +import { createRoot } from 'react-dom/client'; + +function App() { + return
Hello World
; +} + +const root = createRoot(document.getElementById('root')); +root.render(); +``` + +### On the server + +```js +import { renderToPipeableStream } from 'react-dom/server'; + +function App() { + return
Hello World
; +} + +function handleRequest(res) { + // ... in your server handler ... + const stream = renderToPipeableStream(, { + onShellReady() { + res.statusCode = 200; + res.setHeader('Content-type', 'text/html'); + stream.pipe(res); + }, + // ... + }); +} +``` + +## API + +### `react-dom` + +See https://react.dev/reference/react-dom + +### `react-dom/client` + +See https://react.dev/reference/react-dom/client + +### `react-dom/server` + +See https://react.dev/reference/react-dom/server diff --git a/backend/node_modules/react-dom/cjs/react-dom-client.development.js b/backend/node_modules/react-dom/cjs/react-dom-client.development.js new file mode 100644 index 00000000..d005d8b9 --- /dev/null +++ b/backend/node_modules/react-dom/cjs/react-dom-client.development.js @@ -0,0 +1,28121 @@ +/** + * @license React + * react-dom-client.development.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* + Modernizr 3.0.0pre (Custom Build) | MIT +*/ +"use strict"; +"production" !== process.env.NODE_ENV && + (function () { + function findHook(fiber, id) { + for (fiber = fiber.memoizedState; null !== fiber && 0 < id; ) + (fiber = fiber.next), id--; + return fiber; + } + function copyWithSetImpl(obj, path, index, value) { + if (index >= path.length) return value; + var key = path[index], + updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj); + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); + return updated; + } + function copyWithRename(obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) + console.warn("copyWithRename() expects paths of the same length"); + else { + for (var i = 0; i < newPath.length - 1; i++) + if (oldPath[i] !== newPath[i]) { + console.warn( + "copyWithRename() expects paths to be the same except for the deepest key" + ); + return; + } + return copyWithRenameImpl(obj, oldPath, newPath, 0); + } + } + function copyWithRenameImpl(obj, oldPath, newPath, index) { + var oldKey = oldPath[index], + updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj); + index + 1 === oldPath.length + ? ((updated[newPath[index]] = updated[oldKey]), + isArrayImpl(updated) + ? updated.splice(oldKey, 1) + : delete updated[oldKey]) + : (updated[oldKey] = copyWithRenameImpl( + obj[oldKey], + oldPath, + newPath, + index + 1 + )); + return updated; + } + function copyWithDeleteImpl(obj, path, index) { + var key = path[index], + updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj); + if (index + 1 === path.length) + return ( + isArrayImpl(updated) ? updated.splice(key, 1) : delete updated[key], + updated + ); + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + } + function shouldSuspendImpl() { + return !1; + } + function shouldErrorImpl() { + return null; + } + function warnInvalidHookAccess() { + console.error( + "Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. You can only call Hooks at the top level of your React function. For more information, see https://react.dev/link/rules-of-hooks" + ); + } + function warnInvalidContextAccess() { + console.error( + "Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo()." + ); + } + function noop() {} + function warnForMissingKey() {} + function setToSortedString(set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + } + function createFiber(tag, pendingProps, key, mode) { + return new FiberNode(tag, pendingProps, key, mode); + } + function scheduleRoot(root, element) { + root.context === emptyContextObject && + (updateContainerImpl(root.current, 2, element, root, null, null), + flushSyncWork$1()); + } + function scheduleRefresh(root, update) { + if (null !== resolveFamily) { + var staleFamilies = update.staleFamilies; + update = update.updatedFamilies; + flushPendingEffects(); + scheduleFibersWithFamiliesRecursively( + root.current, + update, + staleFamilies + ); + flushSyncWork$1(); + } + } + function setRefreshHandler(handler) { + resolveFamily = handler; + } + function isValidContainer(node) { + return !( + !node || + (1 !== node.nodeType && 9 !== node.nodeType && 11 !== node.nodeType) + ); + } + function getNearestMountedFiber(fiber) { + var node = fiber, + nearestMounted = fiber; + if (fiber.alternate) for (; node.return; ) node = node.return; + else { + fiber = node; + do + (node = fiber), + 0 !== (node.flags & 4098) && (nearestMounted = node.return), + (fiber = node.return); + while (fiber); + } + return 3 === node.tag ? nearestMounted : null; + } + function getSuspenseInstanceFromFiber(fiber) { + if (13 === fiber.tag) { + var suspenseState = fiber.memoizedState; + null === suspenseState && + ((fiber = fiber.alternate), + null !== fiber && (suspenseState = fiber.memoizedState)); + if (null !== suspenseState) return suspenseState.dehydrated; + } + return null; + } + function getActivityInstanceFromFiber(fiber) { + if (31 === fiber.tag) { + var activityState = fiber.memoizedState; + null === activityState && + ((fiber = fiber.alternate), + null !== fiber && (activityState = fiber.memoizedState)); + if (null !== activityState) return activityState.dehydrated; + } + return null; + } + function assertIsMounted(fiber) { + if (getNearestMountedFiber(fiber) !== fiber) + throw Error("Unable to find node on an unmounted component."); + } + function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; + if (!alternate) { + alternate = getNearestMountedFiber(fiber); + if (null === alternate) + throw Error("Unable to find node on an unmounted component."); + return alternate !== fiber ? null : fiber; + } + for (var a = fiber, b = alternate; ; ) { + var parentA = a.return; + if (null === parentA) break; + var parentB = parentA.alternate; + if (null === parentB) { + b = parentA.return; + if (null !== b) { + a = b; + continue; + } + break; + } + if (parentA.child === parentB.child) { + for (parentB = parentA.child; parentB; ) { + if (parentB === a) return assertIsMounted(parentA), fiber; + if (parentB === b) return assertIsMounted(parentA), alternate; + parentB = parentB.sibling; + } + throw Error("Unable to find node on an unmounted component."); + } + if (a.return !== b.return) (a = parentA), (b = parentB); + else { + for (var didFindChild = !1, _child = parentA.child; _child; ) { + if (_child === a) { + didFindChild = !0; + a = parentA; + b = parentB; + break; + } + if (_child === b) { + didFindChild = !0; + b = parentA; + a = parentB; + break; + } + _child = _child.sibling; + } + if (!didFindChild) { + for (_child = parentB.child; _child; ) { + if (_child === a) { + didFindChild = !0; + a = parentB; + b = parentA; + break; + } + if (_child === b) { + didFindChild = !0; + b = parentB; + a = parentA; + break; + } + _child = _child.sibling; + } + if (!didFindChild) + throw Error( + "Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue." + ); + } + } + if (a.alternate !== b) + throw Error( + "Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue." + ); + } + if (3 !== a.tag) + throw Error("Unable to find node on an unmounted component."); + return a.stateNode.current === a ? fiber : alternate; + } + function findCurrentHostFiberImpl(node) { + var tag = node.tag; + if (5 === tag || 26 === tag || 27 === tag || 6 === tag) return node; + for (node = node.child; null !== node; ) { + tag = findCurrentHostFiberImpl(node); + if (null !== tag) return tag; + node = node.sibling; + } + return null; + } + function getIteratorFn(maybeIterable) { + if (null === maybeIterable || "object" !== typeof maybeIterable) + return null; + maybeIterable = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable["@@iterator"]; + return "function" === typeof maybeIterable ? maybeIterable : null; + } + function getComponentNameFromType(type) { + if (null == type) return null; + if ("function" === typeof type) + return type.$$typeof === REACT_CLIENT_REFERENCE + ? null + : type.displayName || type.name || null; + if ("string" === typeof type) return type; + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; + case REACT_PROFILER_TYPE: + return "Profiler"; + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; + case REACT_ACTIVITY_TYPE: + return "Activity"; + } + if ("object" === typeof type) + switch ( + ("number" === typeof type.tag && + console.error( + "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue." + ), + type.$$typeof) + ) { + case REACT_PORTAL_TYPE: + return "Portal"; + case REACT_CONTEXT_TYPE: + return type.displayName || "Context"; + case REACT_CONSUMER_TYPE: + return (type._context.displayName || "Context") + ".Consumer"; + case REACT_FORWARD_REF_TYPE: + var innerType = type.render; + type = type.displayName; + type || + ((type = innerType.displayName || innerType.name || ""), + (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef")); + return type; + case REACT_MEMO_TYPE: + return ( + (innerType = type.displayName || null), + null !== innerType + ? innerType + : getComponentNameFromType(type.type) || "Memo" + ); + case REACT_LAZY_TYPE: + innerType = type._payload; + type = type._init; + try { + return getComponentNameFromType(type(innerType)); + } catch (x) {} + } + return null; + } + function getComponentNameFromOwner(owner) { + return "number" === typeof owner.tag + ? getComponentNameFromFiber(owner) + : "string" === typeof owner.name + ? owner.name + : null; + } + function getComponentNameFromFiber(fiber) { + var type = fiber.type; + switch (fiber.tag) { + case 31: + return "Activity"; + case 24: + return "Cache"; + case 9: + return (type._context.displayName || "Context") + ".Consumer"; + case 10: + return type.displayName || "Context"; + case 18: + return "DehydratedFragment"; + case 11: + return ( + (fiber = type.render), + (fiber = fiber.displayName || fiber.name || ""), + type.displayName || + ("" !== fiber ? "ForwardRef(" + fiber + ")" : "ForwardRef") + ); + case 7: + return "Fragment"; + case 26: + case 27: + case 5: + return type; + case 4: + return "Portal"; + case 3: + return "Root"; + case 6: + return "Text"; + case 16: + return getComponentNameFromType(type); + case 8: + return type === REACT_STRICT_MODE_TYPE ? "StrictMode" : "Mode"; + case 22: + return "Offscreen"; + case 12: + return "Profiler"; + case 21: + return "Scope"; + case 13: + return "Suspense"; + case 19: + return "SuspenseList"; + case 25: + return "TracingMarker"; + case 1: + case 0: + case 14: + case 15: + if ("function" === typeof type) + return type.displayName || type.name || null; + if ("string" === typeof type) return type; + break; + case 29: + type = fiber._debugInfo; + if (null != type) + for (var i = type.length - 1; 0 <= i; i--) + if ("string" === typeof type[i].name) return type[i].name; + if (null !== fiber.return) + return getComponentNameFromFiber(fiber.return); + } + return null; + } + function createCursor(defaultValue) { + return { current: defaultValue }; + } + function pop(cursor, fiber) { + 0 > index$jscomp$0 + ? console.error("Unexpected pop.") + : (fiber !== fiberStack[index$jscomp$0] && + console.error("Unexpected Fiber popped."), + (cursor.current = valueStack[index$jscomp$0]), + (valueStack[index$jscomp$0] = null), + (fiberStack[index$jscomp$0] = null), + index$jscomp$0--); + } + function push(cursor, value, fiber) { + index$jscomp$0++; + valueStack[index$jscomp$0] = cursor.current; + fiberStack[index$jscomp$0] = fiber; + cursor.current = value; + } + function requiredContext(c) { + null === c && + console.error( + "Expected host context to exist. This error is likely caused by a bug in React. Please file an issue." + ); + return c; + } + function pushHostContainer(fiber, nextRootInstance) { + push(rootInstanceStackCursor, nextRootInstance, fiber); + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, null, fiber); + var nextRootContext = nextRootInstance.nodeType; + switch (nextRootContext) { + case 9: + case 11: + nextRootContext = 9 === nextRootContext ? "#document" : "#fragment"; + nextRootInstance = (nextRootInstance = + nextRootInstance.documentElement) + ? (nextRootInstance = nextRootInstance.namespaceURI) + ? getOwnHostContext(nextRootInstance) + : HostContextNamespaceNone + : HostContextNamespaceNone; + break; + default: + if ( + ((nextRootContext = nextRootInstance.tagName), + (nextRootInstance = nextRootInstance.namespaceURI)) + ) + (nextRootInstance = getOwnHostContext(nextRootInstance)), + (nextRootInstance = getChildHostContextProd( + nextRootInstance, + nextRootContext + )); + else + switch (nextRootContext) { + case "svg": + nextRootInstance = HostContextNamespaceSvg; + break; + case "math": + nextRootInstance = HostContextNamespaceMath; + break; + default: + nextRootInstance = HostContextNamespaceNone; + } + } + nextRootContext = nextRootContext.toLowerCase(); + nextRootContext = updatedAncestorInfoDev(null, nextRootContext); + nextRootContext = { + context: nextRootInstance, + ancestorInfo: nextRootContext + }; + pop(contextStackCursor, fiber); + push(contextStackCursor, nextRootContext, fiber); + } + function popHostContainer(fiber) { + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + } + function getHostContext() { + return requiredContext(contextStackCursor.current); + } + function pushHostContext(fiber) { + null !== fiber.memoizedState && + push(hostTransitionProviderCursor, fiber, fiber); + var context = requiredContext(contextStackCursor.current); + var type = fiber.type; + var nextContext = getChildHostContextProd(context.context, type); + type = updatedAncestorInfoDev(context.ancestorInfo, type); + nextContext = { context: nextContext, ancestorInfo: type }; + context !== nextContext && + (push(contextFiberStackCursor, fiber, fiber), + push(contextStackCursor, nextContext, fiber)); + } + function popHostContext(fiber) { + contextFiberStackCursor.current === fiber && + (pop(contextStackCursor, fiber), pop(contextFiberStackCursor, fiber)); + hostTransitionProviderCursor.current === fiber && + (pop(hostTransitionProviderCursor, fiber), + (HostTransitionContext._currentValue = NotPendingTransition)); + } + function disabledLog() {} + function disableLogs() { + if (0 === disabledDepth) { + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; + var props = { + configurable: !0, + enumerable: !0, + value: disabledLog, + writable: !0 + }; + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + } + disabledDepth++; + } + function reenableLogs() { + disabledDepth--; + if (0 === disabledDepth) { + var props = { configurable: !0, enumerable: !0, writable: !0 }; + Object.defineProperties(console, { + log: assign({}, props, { value: prevLog }), + info: assign({}, props, { value: prevInfo }), + warn: assign({}, props, { value: prevWarn }), + error: assign({}, props, { value: prevError }), + group: assign({}, props, { value: prevGroup }), + groupCollapsed: assign({}, props, { value: prevGroupCollapsed }), + groupEnd: assign({}, props, { value: prevGroupEnd }) + }); + } + 0 > disabledDepth && + console.error( + "disabledDepth fell below zero. This is a bug in React. Please file an issue." + ); + } + function formatOwnerStack(error) { + var prevPrepareStackTrace = Error.prepareStackTrace; + Error.prepareStackTrace = void 0; + error = error.stack; + Error.prepareStackTrace = prevPrepareStackTrace; + error.startsWith("Error: react-stack-top-frame\n") && + (error = error.slice(29)); + prevPrepareStackTrace = error.indexOf("\n"); + -1 !== prevPrepareStackTrace && + (error = error.slice(prevPrepareStackTrace + 1)); + prevPrepareStackTrace = error.indexOf("react_stack_bottom_frame"); + -1 !== prevPrepareStackTrace && + (prevPrepareStackTrace = error.lastIndexOf( + "\n", + prevPrepareStackTrace + )); + if (-1 !== prevPrepareStackTrace) + error = error.slice(0, prevPrepareStackTrace); + else return ""; + return error; + } + function describeBuiltInComponentFrame(name) { + if (void 0 === prefix) + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = (match && match[1]) || ""; + suffix = + -1 < x.stack.indexOf("\n at") + ? " ()" + : -1 < x.stack.indexOf("@") + ? "@unknown:0:0" + : ""; + } + return "\n" + prefix + name + suffix; + } + function describeNativeComponentFrame(fn, construct) { + if (!fn || reentry) return ""; + var frame = componentFrameCache.get(fn); + if (void 0 !== frame) return frame; + reentry = !0; + frame = Error.prepareStackTrace; + Error.prepareStackTrace = void 0; + var previousDispatcher = null; + previousDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = null; + disableLogs(); + try { + var RunInRootFrame = { + DetermineComponentFrameRoot: function () { + try { + if (construct) { + var Fake = function () { + throw Error(); + }; + Object.defineProperty(Fake.prototype, "props", { + set: function () { + throw Error(); + } + }); + if ("object" === typeof Reflect && Reflect.construct) { + try { + Reflect.construct(Fake, []); + } catch (x) { + var control = x; + } + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x$0) { + control = x$0; + } + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x$1) { + control = x$1; + } + (Fake = fn()) && + "function" === typeof Fake.catch && + Fake.catch(function () {}); + } + } catch (sample) { + if (sample && control && "string" === typeof sample.stack) + return [sample.stack, control.stack]; + } + return [null, null]; + } + }; + RunInRootFrame.DetermineComponentFrameRoot.displayName = + "DetermineComponentFrameRoot"; + var namePropDescriptor = Object.getOwnPropertyDescriptor( + RunInRootFrame.DetermineComponentFrameRoot, + "name" + ); + namePropDescriptor && + namePropDescriptor.configurable && + Object.defineProperty( + RunInRootFrame.DetermineComponentFrameRoot, + "name", + { value: "DetermineComponentFrameRoot" } + ); + var _RunInRootFrame$Deter = + RunInRootFrame.DetermineComponentFrameRoot(), + sampleStack = _RunInRootFrame$Deter[0], + controlStack = _RunInRootFrame$Deter[1]; + if (sampleStack && controlStack) { + var sampleLines = sampleStack.split("\n"), + controlLines = controlStack.split("\n"); + for ( + _RunInRootFrame$Deter = namePropDescriptor = 0; + namePropDescriptor < sampleLines.length && + !sampleLines[namePropDescriptor].includes( + "DetermineComponentFrameRoot" + ); + + ) + namePropDescriptor++; + for ( + ; + _RunInRootFrame$Deter < controlLines.length && + !controlLines[_RunInRootFrame$Deter].includes( + "DetermineComponentFrameRoot" + ); + + ) + _RunInRootFrame$Deter++; + if ( + namePropDescriptor === sampleLines.length || + _RunInRootFrame$Deter === controlLines.length + ) + for ( + namePropDescriptor = sampleLines.length - 1, + _RunInRootFrame$Deter = controlLines.length - 1; + 1 <= namePropDescriptor && + 0 <= _RunInRootFrame$Deter && + sampleLines[namePropDescriptor] !== + controlLines[_RunInRootFrame$Deter]; + + ) + _RunInRootFrame$Deter--; + for ( + ; + 1 <= namePropDescriptor && 0 <= _RunInRootFrame$Deter; + namePropDescriptor--, _RunInRootFrame$Deter-- + ) + if ( + sampleLines[namePropDescriptor] !== + controlLines[_RunInRootFrame$Deter] + ) { + if (1 !== namePropDescriptor || 1 !== _RunInRootFrame$Deter) { + do + if ( + (namePropDescriptor--, + _RunInRootFrame$Deter--, + 0 > _RunInRootFrame$Deter || + sampleLines[namePropDescriptor] !== + controlLines[_RunInRootFrame$Deter]) + ) { + var _frame = + "\n" + + sampleLines[namePropDescriptor].replace( + " at new ", + " at " + ); + fn.displayName && + _frame.includes("") && + (_frame = _frame.replace("", fn.displayName)); + "function" === typeof fn && + componentFrameCache.set(fn, _frame); + return _frame; + } + while (1 <= namePropDescriptor && 0 <= _RunInRootFrame$Deter); + } + break; + } + } + } finally { + (reentry = !1), + (ReactSharedInternals.H = previousDispatcher), + reenableLogs(), + (Error.prepareStackTrace = frame); + } + sampleLines = (sampleLines = fn ? fn.displayName || fn.name : "") + ? describeBuiltInComponentFrame(sampleLines) + : ""; + "function" === typeof fn && componentFrameCache.set(fn, sampleLines); + return sampleLines; + } + function describeFiber(fiber, childFiber) { + switch (fiber.tag) { + case 26: + case 27: + case 5: + return describeBuiltInComponentFrame(fiber.type); + case 16: + return describeBuiltInComponentFrame("Lazy"); + case 13: + return fiber.child !== childFiber && null !== childFiber + ? describeBuiltInComponentFrame("Suspense Fallback") + : describeBuiltInComponentFrame("Suspense"); + case 19: + return describeBuiltInComponentFrame("SuspenseList"); + case 0: + case 15: + return describeNativeComponentFrame(fiber.type, !1); + case 11: + return describeNativeComponentFrame(fiber.type.render, !1); + case 1: + return describeNativeComponentFrame(fiber.type, !0); + case 31: + return describeBuiltInComponentFrame("Activity"); + default: + return ""; + } + } + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = "", + previous = null; + do { + info += describeFiber(workInProgress, previous); + var debugInfo = workInProgress._debugInfo; + if (debugInfo) + for (var i = debugInfo.length - 1; 0 <= i; i--) { + var entry = debugInfo[i]; + if ("string" === typeof entry.name) { + var JSCompiler_temp_const = info; + a: { + var name = entry.name, + env = entry.env, + location = entry.debugLocation; + if (null != location) { + var childStack = formatOwnerStack(location), + idx = childStack.lastIndexOf("\n"), + lastLine = + -1 === idx ? childStack : childStack.slice(idx + 1); + if (-1 !== lastLine.indexOf(name)) { + var JSCompiler_inline_result = "\n" + lastLine; + break a; + } + } + JSCompiler_inline_result = describeBuiltInComponentFrame( + name + (env ? " [" + env + "]" : "") + ); + } + info = JSCompiler_temp_const + JSCompiler_inline_result; + } + } + previous = workInProgress; + workInProgress = workInProgress.return; + } while (workInProgress); + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } + } + function describeFunctionComponentFrameWithoutLineNumber(fn) { + return (fn = fn ? fn.displayName || fn.name : "") + ? describeBuiltInComponentFrame(fn) + : ""; + } + function getCurrentFiberOwnerNameInDevOrNull() { + if (null === current) return null; + var owner = current._debugOwner; + return null != owner ? getComponentNameFromOwner(owner) : null; + } + function getCurrentFiberStackInDev() { + if (null === current) return ""; + var workInProgress = current; + try { + var info = ""; + 6 === workInProgress.tag && (workInProgress = workInProgress.return); + switch (workInProgress.tag) { + case 26: + case 27: + case 5: + info += describeBuiltInComponentFrame(workInProgress.type); + break; + case 13: + info += describeBuiltInComponentFrame("Suspense"); + break; + case 19: + info += describeBuiltInComponentFrame("SuspenseList"); + break; + case 31: + info += describeBuiltInComponentFrame("Activity"); + break; + case 30: + case 0: + case 15: + case 1: + workInProgress._debugOwner || + "" !== info || + (info += describeFunctionComponentFrameWithoutLineNumber( + workInProgress.type + )); + break; + case 11: + workInProgress._debugOwner || + "" !== info || + (info += describeFunctionComponentFrameWithoutLineNumber( + workInProgress.type.render + )); + } + for (; workInProgress; ) + if ("number" === typeof workInProgress.tag) { + var fiber = workInProgress; + workInProgress = fiber._debugOwner; + var debugStack = fiber._debugStack; + if (workInProgress && debugStack) { + var formattedStack = formatOwnerStack(debugStack); + "" !== formattedStack && (info += "\n" + formattedStack); + } + } else if (null != workInProgress.debugStack) { + var ownerStack = workInProgress.debugStack; + (workInProgress = workInProgress.owner) && + ownerStack && + (info += "\n" + formatOwnerStack(ownerStack)); + } else break; + var JSCompiler_inline_result = info; + } catch (x) { + JSCompiler_inline_result = + "\nError generating stack: " + x.message + "\n" + x.stack; + } + return JSCompiler_inline_result; + } + function runWithFiberInDEV(fiber, callback, arg0, arg1, arg2, arg3, arg4) { + var previousFiber = current; + setCurrentFiber(fiber); + try { + return null !== fiber && fiber._debugTask + ? fiber._debugTask.run( + callback.bind(null, arg0, arg1, arg2, arg3, arg4) + ) + : callback(arg0, arg1, arg2, arg3, arg4); + } finally { + setCurrentFiber(previousFiber); + } + throw Error( + "runWithFiberInDEV should never be called in production. This is a bug in React." + ); + } + function setCurrentFiber(fiber) { + ReactSharedInternals.getCurrentStack = + null === fiber ? null : getCurrentFiberStackInDev; + isRendering = !1; + current = fiber; + } + function typeName(value) { + return ( + ("function" === typeof Symbol && + Symbol.toStringTag && + value[Symbol.toStringTag]) || + value.constructor.name || + "Object" + ); + } + function willCoercionThrow(value) { + try { + return testStringCoercion(value), !1; + } catch (e) { + return !0; + } + } + function testStringCoercion(value) { + return "" + value; + } + function checkAttributeStringCoercion(value, attributeName) { + if (willCoercionThrow(value)) + return ( + console.error( + "The provided `%s` attribute is an unsupported type %s. This value must be coerced to a string before using it here.", + attributeName, + typeName(value) + ), + testStringCoercion(value) + ); + } + function checkCSSPropertyStringCoercion(value, propName) { + if (willCoercionThrow(value)) + return ( + console.error( + "The provided `%s` CSS property is an unsupported type %s. This value must be coerced to a string before using it here.", + propName, + typeName(value) + ), + testStringCoercion(value) + ); + } + function checkFormFieldValueStringCoercion(value) { + if (willCoercionThrow(value)) + return ( + console.error( + "Form field values (value, checked, defaultValue, or defaultChecked props) must be strings, not %s. This value must be coerced to a string before using it here.", + typeName(value) + ), + testStringCoercion(value) + ); + } + function injectInternals(internals) { + if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (hook.isDisabled) return !0; + if (!hook.supportsFiber) + return ( + console.error( + "The installed version of React DevTools is too old and will not work with the current version of React. Please update React DevTools. https://react.dev/link/react-devtools" + ), + !0 + ); + try { + (rendererID = hook.inject(internals)), (injectedHook = hook); + } catch (err) { + console.error("React instrumentation encountered an error: %o.", err); + } + return hook.checkDCE ? !0 : !1; + } + function setIsStrictModeForDevtools(newIsStrictMode) { + "function" === typeof log$1 && + unstable_setDisableYieldValue(newIsStrictMode); + if (injectedHook && "function" === typeof injectedHook.setStrictMode) + try { + injectedHook.setStrictMode(rendererID, newIsStrictMode); + } catch (err) { + hasLoggedError || + ((hasLoggedError = !0), + console.error( + "React instrumentation encountered an error: %o", + err + )); + } + } + function clz32Fallback(x) { + x >>>= 0; + return 0 === x ? 32 : (31 - ((log(x) / LN2) | 0)) | 0; + } + function getHighestPriorityLanes(lanes) { + var pendingSyncLanes = lanes & 42; + if (0 !== pendingSyncLanes) return pendingSyncLanes; + switch (lanes & -lanes) { + case 1: + return 1; + case 2: + return 2; + case 4: + return 4; + case 8: + return 8; + case 16: + return 16; + case 32: + return 32; + case 64: + return 64; + case 128: + return 128; + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + return lanes & 261888; + case 262144: + case 524288: + case 1048576: + case 2097152: + return lanes & 3932160; + case 4194304: + case 8388608: + case 16777216: + case 33554432: + return lanes & 62914560; + case 67108864: + return 67108864; + case 134217728: + return 134217728; + case 268435456: + return 268435456; + case 536870912: + return 536870912; + case 1073741824: + return 0; + default: + return ( + console.error( + "Should have found matching lanes. This is a bug in React." + ), + lanes + ); + } + } + function getNextLanes(root, wipLanes, rootHasPendingCommit) { + var pendingLanes = root.pendingLanes; + if (0 === pendingLanes) return 0; + var nextLanes = 0, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes; + root = root.warmLanes; + var nonIdlePendingLanes = pendingLanes & 134217727; + 0 !== nonIdlePendingLanes + ? ((pendingLanes = nonIdlePendingLanes & ~suspendedLanes), + 0 !== pendingLanes + ? (nextLanes = getHighestPriorityLanes(pendingLanes)) + : ((pingedLanes &= nonIdlePendingLanes), + 0 !== pingedLanes + ? (nextLanes = getHighestPriorityLanes(pingedLanes)) + : rootHasPendingCommit || + ((rootHasPendingCommit = nonIdlePendingLanes & ~root), + 0 !== rootHasPendingCommit && + (nextLanes = + getHighestPriorityLanes(rootHasPendingCommit))))) + : ((nonIdlePendingLanes = pendingLanes & ~suspendedLanes), + 0 !== nonIdlePendingLanes + ? (nextLanes = getHighestPriorityLanes(nonIdlePendingLanes)) + : 0 !== pingedLanes + ? (nextLanes = getHighestPriorityLanes(pingedLanes)) + : rootHasPendingCommit || + ((rootHasPendingCommit = pendingLanes & ~root), + 0 !== rootHasPendingCommit && + (nextLanes = getHighestPriorityLanes(rootHasPendingCommit)))); + return 0 === nextLanes + ? 0 + : 0 !== wipLanes && + wipLanes !== nextLanes && + 0 === (wipLanes & suspendedLanes) && + ((suspendedLanes = nextLanes & -nextLanes), + (rootHasPendingCommit = wipLanes & -wipLanes), + suspendedLanes >= rootHasPendingCommit || + (32 === suspendedLanes && 0 !== (rootHasPendingCommit & 4194048))) + ? wipLanes + : nextLanes; + } + function checkIfRootIsPrerendering(root, renderLanes) { + return ( + 0 === + (root.pendingLanes & + ~(root.suspendedLanes & ~root.pingedLanes) & + renderLanes) + ); + } + function computeExpirationTime(lane, currentTime) { + switch (lane) { + case 1: + case 2: + case 4: + case 8: + case 64: + return currentTime + 250; + case 16: + case 32: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + case 262144: + case 524288: + case 1048576: + case 2097152: + return currentTime + 5e3; + case 4194304: + case 8388608: + case 16777216: + case 33554432: + return -1; + case 67108864: + case 134217728: + case 268435456: + case 536870912: + case 1073741824: + return -1; + default: + return ( + console.error( + "Should have found matching lanes. This is a bug in React." + ), + -1 + ); + } + } + function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + 0 === (nextRetryLane & 62914560) && (nextRetryLane = 4194304); + return lane; + } + function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; + } + function markRootUpdated$1(root, updateLane) { + root.pendingLanes |= updateLane; + 268435456 !== updateLane && + ((root.suspendedLanes = 0), + (root.pingedLanes = 0), + (root.warmLanes = 0)); + } + function markRootFinished( + root, + finishedLanes, + remainingLanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes + ) { + var previouslyPendingLanes = root.pendingLanes; + root.pendingLanes = remainingLanes; + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.warmLanes = 0; + root.expiredLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + root.errorRecoveryDisabledLanes &= remainingLanes; + root.shellSuspendCounter = 0; + var entanglements = root.entanglements, + expirationTimes = root.expirationTimes, + hiddenUpdates = root.hiddenUpdates; + for ( + remainingLanes = previouslyPendingLanes & ~remainingLanes; + 0 < remainingLanes; + + ) { + var index = 31 - clz32(remainingLanes), + lane = 1 << index; + entanglements[index] = 0; + expirationTimes[index] = -1; + var hiddenUpdatesForLane = hiddenUpdates[index]; + if (null !== hiddenUpdatesForLane) + for ( + hiddenUpdates[index] = null, index = 0; + index < hiddenUpdatesForLane.length; + index++ + ) { + var update = hiddenUpdatesForLane[index]; + null !== update && (update.lane &= -536870913); + } + remainingLanes &= ~lane; + } + 0 !== spawnedLane && markSpawnedDeferredLane(root, spawnedLane, 0); + 0 !== suspendedRetryLanes && + 0 === updatedLanes && + 0 !== root.tag && + (root.suspendedLanes |= + suspendedRetryLanes & ~(previouslyPendingLanes & ~finishedLanes)); + } + function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { + root.pendingLanes |= spawnedLane; + root.suspendedLanes &= ~spawnedLane; + var spawnedLaneIndex = 31 - clz32(spawnedLane); + root.entangledLanes |= spawnedLane; + root.entanglements[spawnedLaneIndex] = + root.entanglements[spawnedLaneIndex] | + 1073741824 | + (entangledLanes & 261930); + } + function markRootEntangled(root, entangledLanes) { + var rootEntangledLanes = (root.entangledLanes |= entangledLanes); + for (root = root.entanglements; rootEntangledLanes; ) { + var index = 31 - clz32(rootEntangledLanes), + lane = 1 << index; + (lane & entangledLanes) | (root[index] & entangledLanes) && + (root[index] |= entangledLanes); + rootEntangledLanes &= ~lane; + } + } + function getBumpedLaneForHydration(root, renderLanes) { + var renderLane = renderLanes & -renderLanes; + renderLane = + 0 !== (renderLane & 42) + ? 1 + : getBumpedLaneForHydrationByLane(renderLane); + return 0 !== (renderLane & (root.suspendedLanes | renderLanes)) + ? 0 + : renderLane; + } + function getBumpedLaneForHydrationByLane(lane) { + switch (lane) { + case 2: + lane = 1; + break; + case 8: + lane = 4; + break; + case 32: + lane = 16; + break; + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + case 262144: + case 524288: + case 1048576: + case 2097152: + case 4194304: + case 8388608: + case 16777216: + case 33554432: + lane = 128; + break; + case 268435456: + lane = 134217728; + break; + default: + lane = 0; + } + return lane; + } + function addFiberToLanesMap(root, fiber, lanes) { + if (isDevToolsPresent) + for (root = root.pendingUpdatersLaneMap; 0 < lanes; ) { + var index = 31 - clz32(lanes), + lane = 1 << index; + root[index].add(fiber); + lanes &= ~lane; + } + } + function movePendingFibersToMemoized(root, lanes) { + if (isDevToolsPresent) + for ( + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap, + memoizedUpdaters = root.memoizedUpdaters; + 0 < lanes; + + ) { + var index = 31 - clz32(lanes); + root = 1 << index; + index = pendingUpdatersLaneMap[index]; + 0 < index.size && + (index.forEach(function (fiber) { + var alternate = fiber.alternate; + (null !== alternate && memoizedUpdaters.has(alternate)) || + memoizedUpdaters.add(fiber); + }), + index.clear()); + lanes &= ~root; + } + } + function lanesToEventPriority(lanes) { + lanes &= -lanes; + return 0 !== DiscreteEventPriority && DiscreteEventPriority < lanes + ? 0 !== ContinuousEventPriority && ContinuousEventPriority < lanes + ? 0 !== (lanes & 134217727) + ? DefaultEventPriority + : IdleEventPriority + : ContinuousEventPriority + : DiscreteEventPriority; + } + function resolveUpdatePriority() { + var updatePriority = ReactDOMSharedInternals.p; + if (0 !== updatePriority) return updatePriority; + updatePriority = window.event; + return void 0 === updatePriority + ? DefaultEventPriority + : getEventPriority(updatePriority.type); + } + function runWithPriority(priority, fn) { + var previousPriority = ReactDOMSharedInternals.p; + try { + return (ReactDOMSharedInternals.p = priority), fn(); + } finally { + ReactDOMSharedInternals.p = previousPriority; + } + } + function detachDeletedInstance(node) { + delete node[internalInstanceKey]; + delete node[internalPropsKey]; + delete node[internalEventHandlersKey]; + delete node[internalEventHandlerListenersKey]; + delete node[internalEventHandlesSetKey]; + } + function getClosestInstanceFromNode(targetNode) { + var targetInst = targetNode[internalInstanceKey]; + if (targetInst) return targetInst; + for (var parentNode = targetNode.parentNode; parentNode; ) { + if ( + (targetInst = + parentNode[internalContainerInstanceKey] || + parentNode[internalInstanceKey]) + ) { + parentNode = targetInst.alternate; + if ( + null !== targetInst.child || + (null !== parentNode && null !== parentNode.child) + ) + for ( + targetNode = getParentHydrationBoundary(targetNode); + null !== targetNode; + + ) { + if ((parentNode = targetNode[internalInstanceKey])) + return parentNode; + targetNode = getParentHydrationBoundary(targetNode); + } + return targetInst; + } + targetNode = parentNode; + parentNode = targetNode.parentNode; + } + return null; + } + function getInstanceFromNode(node) { + if ( + (node = node[internalInstanceKey] || node[internalContainerInstanceKey]) + ) { + var tag = node.tag; + if ( + 5 === tag || + 6 === tag || + 13 === tag || + 31 === tag || + 26 === tag || + 27 === tag || + 3 === tag + ) + return node; + } + return null; + } + function getNodeFromInstance(inst) { + var tag = inst.tag; + if (5 === tag || 26 === tag || 27 === tag || 6 === tag) + return inst.stateNode; + throw Error("getNodeFromInstance: Invalid argument."); + } + function getResourcesFromRoot(root) { + var resources = root[internalRootNodeResourcesKey]; + resources || + (resources = root[internalRootNodeResourcesKey] = + { hoistableStyles: new Map(), hoistableScripts: new Map() }); + return resources; + } + function markNodeAsHoistable(node) { + node[internalHoistableMarker] = !0; + } + function registerTwoPhaseEvent(registrationName, dependencies) { + registerDirectEvent(registrationName, dependencies); + registerDirectEvent(registrationName + "Capture", dependencies); + } + function registerDirectEvent(registrationName, dependencies) { + registrationNameDependencies[registrationName] && + console.error( + "EventRegistry: More than one plugin attempted to publish the same registration name, `%s`.", + registrationName + ); + registrationNameDependencies[registrationName] = dependencies; + var lowerCasedName = registrationName.toLowerCase(); + possibleRegistrationNames[lowerCasedName] = registrationName; + "onDoubleClick" === registrationName && + (possibleRegistrationNames.ondblclick = registrationName); + for ( + registrationName = 0; + registrationName < dependencies.length; + registrationName++ + ) + allNativeEvents.add(dependencies[registrationName]); + } + function checkControlledValueProps(tagName, props) { + hasReadOnlyValue[props.type] || + props.onChange || + props.onInput || + props.readOnly || + props.disabled || + null == props.value || + ("select" === tagName + ? console.error( + "You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set `onChange`." + ) + : console.error( + "You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`." + )); + props.onChange || + props.readOnly || + props.disabled || + null == props.checked || + console.error( + "You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`." + ); + } + function isAttributeNameSafe(attributeName) { + if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) + return !0; + if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) + return !1; + if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) + return (validatedAttributeNameCache[attributeName] = !0); + illegalAttributeNameCache[attributeName] = !0; + console.error("Invalid attribute name: `%s`", attributeName); + return !1; + } + function getValueForAttributeOnCustomComponent(node, name, expected) { + if (isAttributeNameSafe(name)) { + if (!node.hasAttribute(name)) { + switch (typeof expected) { + case "symbol": + case "object": + return expected; + case "function": + return expected; + case "boolean": + if (!1 === expected) return expected; + } + return void 0 === expected ? void 0 : null; + } + node = node.getAttribute(name); + if ("" === node && !0 === expected) return !0; + checkAttributeStringCoercion(expected, name); + return node === "" + expected ? expected : node; + } + } + function setValueForAttribute(node, name, value) { + if (isAttributeNameSafe(name)) + if (null === value) node.removeAttribute(name); + else { + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + node.removeAttribute(name); + return; + case "boolean": + var prefix = name.toLowerCase().slice(0, 5); + if ("data-" !== prefix && "aria-" !== prefix) { + node.removeAttribute(name); + return; + } + } + checkAttributeStringCoercion(value, name); + node.setAttribute(name, "" + value); + } + } + function setValueForKnownAttribute(node, name, value) { + if (null === value) node.removeAttribute(name); + else { + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + case "boolean": + node.removeAttribute(name); + return; + } + checkAttributeStringCoercion(value, name); + node.setAttribute(name, "" + value); + } + } + function setValueForNamespacedAttribute(node, namespace, name, value) { + if (null === value) node.removeAttribute(name); + else { + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + case "boolean": + node.removeAttribute(name); + return; + } + checkAttributeStringCoercion(value, name); + node.setAttributeNS(namespace, name, "" + value); + } + } + function getToStringValue(value) { + switch (typeof value) { + case "bigint": + case "boolean": + case "number": + case "string": + case "undefined": + return value; + case "object": + return checkFormFieldValueStringCoercion(value), value; + default: + return ""; + } + } + function isCheckable(elem) { + var type = elem.type; + return ( + (elem = elem.nodeName) && + "input" === elem.toLowerCase() && + ("checkbox" === type || "radio" === type) + ); + } + function trackValueOnNode(node, valueField, currentValue) { + var descriptor = Object.getOwnPropertyDescriptor( + node.constructor.prototype, + valueField + ); + if ( + !node.hasOwnProperty(valueField) && + "undefined" !== typeof descriptor && + "function" === typeof descriptor.get && + "function" === typeof descriptor.set + ) { + var get = descriptor.get, + set = descriptor.set; + Object.defineProperty(node, valueField, { + configurable: !0, + get: function () { + return get.call(this); + }, + set: function (value) { + checkFormFieldValueStringCoercion(value); + currentValue = "" + value; + set.call(this, value); + } + }); + Object.defineProperty(node, valueField, { + enumerable: descriptor.enumerable + }); + return { + getValue: function () { + return currentValue; + }, + setValue: function (value) { + checkFormFieldValueStringCoercion(value); + currentValue = "" + value; + }, + stopTracking: function () { + node._valueTracker = null; + delete node[valueField]; + } + }; + } + } + function track(node) { + if (!node._valueTracker) { + var valueField = isCheckable(node) ? "checked" : "value"; + node._valueTracker = trackValueOnNode( + node, + valueField, + "" + node[valueField] + ); + } + } + function updateValueIfChanged(node) { + if (!node) return !1; + var tracker = node._valueTracker; + if (!tracker) return !0; + var lastValue = tracker.getValue(); + var value = ""; + node && + (value = isCheckable(node) + ? node.checked + ? "true" + : "false" + : node.value); + node = value; + return node !== lastValue ? (tracker.setValue(node), !0) : !1; + } + function getActiveElement(doc) { + doc = doc || ("undefined" !== typeof document ? document : void 0); + if ("undefined" === typeof doc) return null; + try { + return doc.activeElement || doc.body; + } catch (e) { + return doc.body; + } + } + function escapeSelectorAttributeValueInsideDoubleQuotes(value) { + return value.replace( + escapeSelectorAttributeValueInsideDoubleQuotesRegex, + function (ch) { + return "\\" + ch.charCodeAt(0).toString(16) + " "; + } + ); + } + function validateInputProps(element, props) { + void 0 === props.checked || + void 0 === props.defaultChecked || + didWarnCheckedDefaultChecked || + (console.error( + "%s contains an input of type %s with both checked and defaultChecked props. Input elements must be either controlled or uncontrolled (specify either the checked prop, or the defaultChecked prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://react.dev/link/controlled-components", + getCurrentFiberOwnerNameInDevOrNull() || "A component", + props.type + ), + (didWarnCheckedDefaultChecked = !0)); + void 0 === props.value || + void 0 === props.defaultValue || + didWarnValueDefaultValue$1 || + (console.error( + "%s contains an input of type %s with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://react.dev/link/controlled-components", + getCurrentFiberOwnerNameInDevOrNull() || "A component", + props.type + ), + (didWarnValueDefaultValue$1 = !0)); + } + function updateInput( + element, + value, + defaultValue, + lastDefaultValue, + checked, + defaultChecked, + type, + name + ) { + element.name = ""; + null != type && + "function" !== typeof type && + "symbol" !== typeof type && + "boolean" !== typeof type + ? (checkAttributeStringCoercion(type, "type"), (element.type = type)) + : element.removeAttribute("type"); + if (null != value) + if ("number" === type) { + if ((0 === value && "" === element.value) || element.value != value) + element.value = "" + getToStringValue(value); + } else + element.value !== "" + getToStringValue(value) && + (element.value = "" + getToStringValue(value)); + else + ("submit" !== type && "reset" !== type) || + element.removeAttribute("value"); + null != value + ? setDefaultValue(element, type, getToStringValue(value)) + : null != defaultValue + ? setDefaultValue(element, type, getToStringValue(defaultValue)) + : null != lastDefaultValue && element.removeAttribute("value"); + null == checked && + null != defaultChecked && + (element.defaultChecked = !!defaultChecked); + null != checked && + (element.checked = + checked && + "function" !== typeof checked && + "symbol" !== typeof checked); + null != name && + "function" !== typeof name && + "symbol" !== typeof name && + "boolean" !== typeof name + ? (checkAttributeStringCoercion(name, "name"), + (element.name = "" + getToStringValue(name))) + : element.removeAttribute("name"); + } + function initInput( + element, + value, + defaultValue, + checked, + defaultChecked, + type, + name, + isHydrating + ) { + null != type && + "function" !== typeof type && + "symbol" !== typeof type && + "boolean" !== typeof type && + (checkAttributeStringCoercion(type, "type"), (element.type = type)); + if (null != value || null != defaultValue) { + if ( + !( + ("submit" !== type && "reset" !== type) || + (void 0 !== value && null !== value) + ) + ) { + track(element); + return; + } + defaultValue = + null != defaultValue ? "" + getToStringValue(defaultValue) : ""; + value = null != value ? "" + getToStringValue(value) : defaultValue; + isHydrating || value === element.value || (element.value = value); + element.defaultValue = value; + } + checked = null != checked ? checked : defaultChecked; + checked = + "function" !== typeof checked && + "symbol" !== typeof checked && + !!checked; + element.checked = isHydrating ? element.checked : !!checked; + element.defaultChecked = !!checked; + null != name && + "function" !== typeof name && + "symbol" !== typeof name && + "boolean" !== typeof name && + (checkAttributeStringCoercion(name, "name"), (element.name = name)); + track(element); + } + function setDefaultValue(node, type, value) { + ("number" === type && getActiveElement(node.ownerDocument) === node) || + node.defaultValue === "" + value || + (node.defaultValue = "" + value); + } + function validateOptionProps(element, props) { + null == props.value && + ("object" === typeof props.children && null !== props.children + ? React.Children.forEach(props.children, function (child) { + null == child || + "string" === typeof child || + "number" === typeof child || + "bigint" === typeof child || + didWarnInvalidChild || + ((didWarnInvalidChild = !0), + console.error( + "Cannot infer the option value of complex children. Pass a `value` prop or use a plain string as children to