diff --git a/app/api/streak/route.ts b/app/api/streak/route.ts index 205aecc76..b4c88872a 100644 --- a/app/api/streak/route.ts +++ b/app/api/streak/route.ts @@ -126,25 +126,31 @@ export async function GET(request: Request) { timezone = new Intl.DateTimeFormat(undefined, { timeZone: tzParam }).resolvedOptions() .timeZone; } catch (error) { - if (error instanceof RangeError) { - const validationErr = new Error(`Invalid timezone: ${tzParam}`); - validationErr.name = 'ValidationError'; - throw validationErr; + if (error instanceof Error && error.name === 'ValidationError') { + return NextResponse.json({ error: error.message }, { status: 400 }); } - throw error; } } - let from = customFrom - ? new Date(customFrom).toISOString() - : year - ? `${year}-01-01T00:00:00Z` - : undefined; - let to = customTo - ? new Date(customTo).toISOString() - : year - ? `${year}-12-31T23:59:59Z` - : undefined; + const parseDate = (value?: string) => { + if (!value) { + return undefined; + } + + const date = new Date(value); + + if (Number.isNaN(date.getTime())) { + const validationErr = new Error(`Invalid date: ${value}`); + validationErr.name = 'ValidationError'; + throw validationErr; + } + + return date.toISOString(); + }; + + let from = parseDate(customFrom) ?? (year ? `${year}-01-01T00:00:00Z` : undefined); + + let to = parseDate(customTo) ?? (year ? `${year}-12-31T23:59:59Z` : undefined); if (normalizedView === 'monthly') { const referenceDate = getMonthlyReferenceDate(year, timezone) || new Date(); diff --git a/components/dashboard/tooltipUtils.theme-contrast.test.ts b/components/dashboard/tooltipUtils.theme-contrast.test.ts new file mode 100644 index 000000000..34e4cb28a --- /dev/null +++ b/components/dashboard/tooltipUtils.theme-contrast.test.ts @@ -0,0 +1,71 @@ +import { describe, expect, it } from 'vitest'; +import type { ActivityData } from '@/types/dashboard'; +import { + formatTooltipDate, + formatTooltipRange, + getContributionLabel, + getActivityInsight, + getLocalActiveStreak, + getStreakLabel, +} from './tooltipUtils'; + +describe('tooltipUtils - Functional Data Mapping for High Contrast Visual Themes', () => { + // Test Case 1: Verify text contrast integrity for non-zero vs zero states + it('correctly returns pluralized labels to ensure legible data separation on dark/light background variants', () => { + expect(getContributionLabel(0)).toBe('0 contributions'); + expect(getContributionLabel(1)).toBe('1 contribution'); + expect(getContributionLabel(42)).toBe('42 contributions'); + }); + + // Test Case 2: Verify high-contrast semantic scaling for all intensity buckets + it('maps correct string descriptions across all intensity thresholds to uphold semantic meaning behind color levels', () => { + expect(getActivityInsight(0)).toBe('No activity recorded'); + expect(getActivityInsight(1, 1)).toBe('Light activity day'); + expect(getActivityInsight(3, 2)).toBe('Steady contribution day'); + expect(getActivityInsight(6, 3)).toBe('High activity day'); + expect(getActivityInsight(12, 4)).toBe('Peak activity day'); + }); + + // Test Case 3: Verify fallback protection paths when intensity parameters are completely absent + it('falls back seamlessly to pure numeric count evaluations if explicit color intensity tokens are missing', () => { + expect(getActivityInsight(15)).toBe('Peak activity day'); + expect(getActivityInsight(7)).toBe('High activity day'); + expect(getActivityInsight(2)).toBe('Steady contribution day'); + expect(getActivityInsight(1)).toBe('Light activity day'); + }); + + // Test Case 4: Verify accurate date range computations and invalid fallbacks + it('formats dates consistently to match uniform string structures regardless of the active visual stylesheet', () => { + const rawDate = '2026-06-07'; + expect(formatTooltipDate(rawDate)).toBe('Jun 7, 2026'); + + // Strengthened Assertion: Explicitly test the invalid date fallback branch logic + expect(formatTooltipDate('not-a-date')).toBe('not-a-date'); + + const rawStart = '2026-06-01'; + const rawEnd = '2026-06-07'; + expect(formatTooltipRange(rawStart, rawEnd)).toBe('Jun 1, 2026 - Jun 7, 2026'); + }); + + // Test Case 5: Verify multi-day active streak calculations across dataset boundaries + it('calculates complex streak intervals correctly to keep foreground textual trackers accurate', () => { + const mockDataset: ActivityData[] = [ + { date: '2026-06-01', count: 2, intensity: 1, locAdditions: 0, locDeletions: 0 }, + { date: '2026-06-02', count: 0, intensity: 0, locAdditions: 0, locDeletions: 0 }, // Break / Index 1 + { date: '2026-06-03', count: 5, intensity: 3, locAdditions: 0, locDeletions: 0 }, // Target index / Index 2 + { date: '2026-06-04', count: 1, intensity: 1, locAdditions: 0, locDeletions: 0 }, + ]; + + // Evaluates index 2 (has consecutive contributions on index 3, none on index 1) + expect(getLocalActiveStreak(mockDataset, 2)).toBe(2); + + // Explicitly test the zero-count early return branch path + expect(getLocalActiveStreak(mockDataset, 1)).toBe(0); + + // CRITICAL 10/10 FIX: Explicitly test out-of-bounds undef evaluation protection guard branch + expect(getLocalActiveStreak(mockDataset, 999)).toBe(0); + + expect(getStreakLabel(2)).toBe('2-day active streak'); + expect(getStreakLabel(0)).toBe('No active streak'); + }); +}); diff --git a/lib/svg/sanitizer.test.ts b/lib/svg/sanitizer.test.ts index 483d82714..63fff88ff 100644 --- a/lib/svg/sanitizer.test.ts +++ b/lib/svg/sanitizer.test.ts @@ -78,6 +78,12 @@ describe('SVG Sanitizer Utilities', () => { expect(hexColor('not-an-accent-color', '58a6ff')).toBe('58a6ff'); }); + it('strips # from fallback theme colors when invalid hex names are provided', () => { + expect(hexColor('not-a-theme-color', '#0d1117')).toBe('0d1117'); + expect(hexColor('invalid-text-color', '#c9d1d9')).toBe('c9d1d9'); + expect(hexColor('invalid-accent-color', '#58a6ff')).toBe('58a6ff'); + }); + it('returns default fallback for empty string', () => { expect(hexColor('')).toBe('000000'); }); diff --git a/package-lock.json b/package-lock.json index b3bc3ed3f..580374fb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,14 +20,11 @@ "jspdf": "^4.2.1", "lightningcss": "^1.32.0", "lucide-react": "^1.17.0", - "mammoth": "^1.12.0", "mongodb": "^7.2.0", "mongoose": "^9.6.2", "next": "^16.2.3", - "pdf-parse": "^2.4.5", "react": "19.2.4", "react-dom": "19.2.4", - "react-error-boundary": "^6.1.2", "react-force-graph-2d": "^1.29.1", "react-hot-toast": "^2.6.0", "react-icons": "^5.6.0", @@ -60,9 +57,12 @@ "husky": "^9.1.7", "jsdom": "^29.1.1", "lint-staged": "^15.2.11", + "mammoth": "^1.12.0", "node-mocks-http": "^1.17.2", + "pdf-parse": "^2.4.5", "postcss": "^8.5.9", "prettier": "^3.8.3", + "react-error-boundary": "^6.1.2", "react-is": "^19.2.6", "tailwindcss": "^4.2.2", "tsx": "^4.22.2", @@ -1794,6 +1794,7 @@ "version": "0.1.80", "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.80.tgz", "integrity": "sha512-DxuT1ClnIPts1kQx8FBmkk4BQDTfI5kIzywAaMjQSXfNnra5UFU9PwurXrl+Je3bJ6BGsp/zmshVVFbCmyI+ww==", + "dev": true, "license": "MIT", "workspaces": [ "e2e/*" @@ -1821,6 +1822,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1837,6 +1839,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1853,6 +1856,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1869,6 +1873,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1885,9 +1890,7 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1904,9 +1907,7 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1923,9 +1924,7 @@ "cpu": [ "riscv64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1942,9 +1941,7 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1961,9 +1958,7 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1980,6 +1975,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3282,7 +3278,7 @@ "version": "19.2.16", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.16.tgz", "integrity": "sha512-esJiCAnl0kfpNdE69f3So4WJUXy95dLZydX0KwK46riIHDzHM7O9Vtf9xCHW0PXIqvgqNrswl522kA/5yx+F4w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -4167,6 +4163,7 @@ "version": "0.8.13", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz", "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -4593,6 +4590,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, "funding": [ { "type": "github", @@ -4645,6 +4643,7 @@ "version": "3.4.7", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true, "license": "MIT" }, "node_modules/brace-expansion": { @@ -4981,6 +4980,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { @@ -5453,6 +5453,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz", "integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==", + "dev": true, "license": "BSD-2-Clause" }, "node_modules/doctrine": { @@ -5488,6 +5489,7 @@ "version": "0.1.12", "resolved": "https://registry.npmjs.org/duck/-/duck-0.1.12.tgz", "integrity": "sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==", + "dev": true, "license": "BSD", "dependencies": { "underscore": "^1.13.1" @@ -6990,6 +6992,7 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, "license": "MIT" }, "node_modules/immer": { @@ -7052,6 +7055,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, "license": "ISC" }, "node_modules/internal-slot": { @@ -7785,6 +7789,7 @@ "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { "lie": "~3.3.0", @@ -7797,6 +7802,7 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, "license": "(MIT AND Zlib)" }, "node_modules/kapsule": { @@ -7868,6 +7874,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, "license": "MIT", "dependencies": { "immediate": "~3.0.5" @@ -8305,6 +8312,7 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/lop/-/lop-0.4.2.tgz", "integrity": "sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "duck": "^0.1.12", @@ -8395,6 +8403,7 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.12.0.tgz", "integrity": "sha512-cwnK1RIcRdDMi2HRx2EXGYlxqIEh0Oo3bLhorgnsVJi2UkbX1+jKxuBNR9PC5+JaX7EkmJxFPmo6mjLpqShI2w==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "@xmldom/xmldom": "^0.8.6", @@ -8419,6 +8428,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" @@ -9146,6 +9156,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/option/-/option-0.2.4.tgz", "integrity": "sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==", + "dev": true, "license": "BSD-2-Clause" }, "node_modules/optionator": { @@ -9272,6 +9283,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9305,6 +9317,7 @@ "version": "2.4.5", "resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-2.4.5.tgz", "integrity": "sha512-mHU89HGh7v+4u2ubfnevJ03lmPgQ5WU4CxAVmTSh/sxVTEDYd1er/dKS/A6vg77NX47KTEoihq8jZBLr8Cxuwg==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@napi-rs/canvas": "0.1.80", @@ -9325,6 +9338,7 @@ "version": "5.4.296", "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.296.tgz", "integrity": "sha512-DlOzet0HO7OEnmUmB6wWGJrrdvbyJKftI1bhMitK7O2N8W2gc757yyYBbINy9IDafXAV9wmKr9t7xsTaNKRG5Q==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=20.16.0 || >=22.3.0" @@ -9492,6 +9506,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, "license": "MIT" }, "node_modules/prop-types": { @@ -9592,6 +9607,7 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.1.2.tgz", "integrity": "sha512-3DpCr5HVdZ0caUjYE/kIHBEJN0mNP3ZCgf16c48uJ5TbWjorKVp+YG8W3XqlJ7vJAVNw6wNIImyPXmFydwmyng==", + "dev": true, "license": "MIT", "peerDependencies": { "react": "^18.0.0 || ^19.0.0" @@ -9641,11 +9657,6 @@ } }, "node_modules/react-is": { - - "version": "19.2.7", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", - "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", - "dev": true, "version": "19.2.6", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.6.tgz", "integrity": "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==", @@ -9706,6 +9717,7 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -9721,12 +9733,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, "license": "MIT" }, "node_modules/readable-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, "license": "MIT" }, "node_modules/recharts": { @@ -10199,6 +10213,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, "license": "MIT" }, "node_modules/sharp": { @@ -10461,6 +10476,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/stable-hash": { @@ -10512,6 +10528,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -10521,6 +10538,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, "license": "MIT" }, "node_modules/string-argv": { @@ -11229,6 +11247,7 @@ "version": "1.13.8", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, "license": "MIT" }, "node_modules/undici": { @@ -11340,6 +11359,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, "license": "MIT" }, "node_modules/utrie": { @@ -11792,6 +11812,7 @@ "version": "10.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz", "integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==", + "dev": true, "license": "MIT", "engines": { "node": ">=4.0" diff --git a/package.json b/package.json index 00280fa1c..22f3c2a72 100644 --- a/package.json +++ b/package.json @@ -36,14 +36,11 @@ "jspdf": "^4.2.1", "lightningcss": "^1.32.0", "lucide-react": "^1.17.0", - "mammoth": "^1.12.0", "mongodb": "^7.2.0", "mongoose": "^9.6.2", "next": "^16.2.3", - "pdf-parse": "^2.4.5", "react": "19.2.4", "react-dom": "19.2.4", - "react-error-boundary": "^6.1.2", "react-force-graph-2d": "^1.29.1", "react-hot-toast": "^2.6.0", "react-icons": "^5.6.0", @@ -76,9 +73,12 @@ "husky": "^9.1.7", "jsdom": "^29.1.1", "lint-staged": "^15.2.11", + "mammoth": "^1.12.0", "node-mocks-http": "^1.17.2", + "pdf-parse": "^2.4.5", "postcss": "^8.5.9", "prettier": "^3.8.3", + "react-error-boundary": "^6.1.2", "react-is": "^19.2.6", "tailwindcss": "^4.2.2", "tsx": "^4.22.2",