diff options
| author | Pinapelz <yukais@pinapelz.com> | 2026-07-29 22:29:32 -0700 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2026-07-29 23:57:41 -0700 |
| commit | 055b95830ced5ffa440146819f6de5fd8ac1c20d (patch) | |
| tree | 7b09da7566c0d66e596e21fa318e7c5ed0e6bb33 | |
| parent | 291541478b9dcccfdab295f09a59dfae27f57759 (diff) | |
add support for srv3 subtitles
| -rw-r--r-- | modules/VideoPlayer/VideoPlayer2.tsx | 83 | ||||
| -rw-r--r-- | next-env.d.ts | 2 | ||||
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | pages/index.tsx | 57 | ||||
| -rw-r--r-- | pnpm-lock.yaml | 191 |
5 files changed, 216 insertions, 119 deletions
diff --git a/modules/VideoPlayer/VideoPlayer2.tsx b/modules/VideoPlayer/VideoPlayer2.tsx index fe2ffb6..bea101b 100644 --- a/modules/VideoPlayer/VideoPlayer2.tsx +++ b/modules/VideoPlayer/VideoPlayer2.tsx @@ -19,9 +19,76 @@ import { CaptionsRenderer } from "react-srv3"; import MediaSync, { MediaSyncRef, MediaSyncState } from "./MediaSync"; import { NextImage } from "../NextImage"; +type CaptionFormat = "srv3" | "srt"; + type CaptionsTrack = { lang: string; src: string; + format?: CaptionFormat; +}; + +const detectFormat = (src: string): CaptionFormat => { + const clean = src.split("?")[0].split("#")[0].toLowerCase(); + if (clean.endsWith(".srt")) return "srt"; + if (clean.endsWith(".srv3") || clean.endsWith(".xml")) return "srv3"; + return "srv3"; +}; + +const srtToSrv3 = (srt: string): string => { + const timestampToMs = (ts: string): number => { + // HH:MM:SS,mmm or HH:MM:SS.mmm + const m = ts + .replace(",", ".") + .split(":") + .map(Number); + let h = 0; + let mm = 0; + let s = 0; + if (m.length === 3) [h, mm, s] = m; + else if (m.length === 2) [mm, s] = m; + else s = m[0] || 0; + return Math.round((h * 3600 + mm * 60 + s) * 1000); + }; + + const escapeXml = (s: string) => + s + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">"); + + const blocks = srt.replace(/\r\n/g, "\n").replace(/^\uFEFF/, "").trim().split(/\n\s*\n/); + const entries = blocks + .map((block) => { + const lines = block.split("\n").filter((l) => l.trim() !== ""); + if (lines.length < 2) return null; + // Drop the numeric index line if present + const timingLine = /^\d+$/.test(lines[0].trim()) ? lines[1] : lines[0]; + const textStart = /^\d+$/.test(lines[0].trim()) ? 2 : 1; + const text = lines.slice(textStart).join("\n"); + const match = timingLine.match( + /(\d{1,2}:\d{2}:\d{2}[.,]\d{3})\s*-->\s*(\d{1,2}:\d{2}:\d{2}[.,]\d{3})/ + ); + if (!match) return null; + const start = timestampToMs(match[1]); + const end = timestampToMs(match[2]); + const dur = Math.max(0, end - start); + const body = escapeXml(text); + return `<p t="${start}" d="${dur}" wp="1" ws="1" p="1">${body}</p>`; + }) + .filter(Boolean); + + return ( + `<?xml version="1.0" encoding="utf-8" ?><timedtext format="3">\n` + + `<head>\n` + + `<pen id="1" fc="#FFFFFF" fo="255" bc="#000000" bo="191" ec="#000000" et="3"/>\n` + + `<ws id="1" ju="2"/>\n` + + `<wp id="1" ap="7" ah="50" av="100"/>\n` + + `</head>\n` + + `<body>\n` + + entries.join("\n") + + `\n</body>\n` + + `</timedtext>` + ); }; export type VideoPlayerProps = { @@ -138,11 +205,12 @@ const VideoPlayer2 = (props: VideoPlayerProps) => { }; const nudgeTime = (delta: number) => { + if (!refVideo.current) return 0; const newTime = Math.max( 0, Math.min(refVideo.current.currentTime + delta, refVideo.current.duration) ); - refVideo.current.currentTime = newTime; + refMedia.current?.seek(newTime); return newTime; }; @@ -247,16 +315,19 @@ const VideoPlayer2 = (props: VideoPlayerProps) => { } }, []); - const loadCaptions = async (url: string) => { + const loadCaptions = async (url: string, format?: CaptionFormat) => { + const fmt = format || detectFormat(url); await fetch(url) .then((res) => res.text()) - .then((text) => - setSrv3CaptionXMLs((now) => ({ ...now, [activeCaption]: text })) - ); + .then((text) => { + const xml = fmt === "srt" ? srtToSrv3(text) : text; + setSrv3CaptionXMLs((now) => ({ ...now, [activeCaption]: xml })); + }); }; React.useEffect(() => { - if (activeCaption >= 0) loadCaptions(captions[activeCaption].src); + if (activeCaption >= 0) + loadCaptions(captions[activeCaption].src, captions[activeCaption].format); }, [activeCaption]); const controlsVisible = Date.now() - lastActive < 5000; diff --git a/next-env.d.ts b/next-env.d.ts index 4f11a03..a4a7b3f 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -2,4 +2,4 @@ /// <reference types="next/image-types/global" /> // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/package.json b/package.json index eb71ba3..7d9e93e 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "axios": "^1.18.1", "linkify-react": "^4.3.3", "linkifyjs": "^4.3.3", - "next": "13.0.6", + "next": "14.2.35", "pretty-bytes": "^6.1.1", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/pages/index.tsx b/pages/index.tsx index a008fdc..ee80836 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -17,12 +17,13 @@ const CustomPlayerPage = () => { const [urlVideo, setUrlVideo] = React.useState(""); const [urlChat, setUrlChat] = React.useState(""); const [urlYtt, setUrlYtt] = React.useState(""); + const [captionFormat, setCaptionFormat] = React.useState<"srv3" | "srt" | undefined>(undefined); const [infoJson, setInfoJson] = React.useState({} as any); const [showPlayer, setShowPlayer] = React.useState(false); const [dataSet, setDataSet] = React.useState(false); const { query } = router; - const jsonDataUrl = query.jsonData as string; + const jsonDataUrl = query.data as string; const timeSeconds = query.time as string; useEffect(() => { @@ -36,7 +37,7 @@ const CustomPlayerPage = () => { fetch(jsonDataUrl) .then((res) => res.json()) .then((data) => { - const { info, video, chat, srv3, ts } = data; + const { info, video, chat, srv3, srt, captions } = data; if (info) { fetch(info) .then((res) => res.json()) @@ -52,6 +53,16 @@ const CustomPlayerPage = () => { } if (srv3) { setUrlYtt(srv3); + setCaptionFormat("srv3"); + } else if (srt) { + setUrlYtt(srt); + setCaptionFormat("srt"); + } else if (captions) { + const cap = Array.isArray(captions) ? captions[0] : captions; + if (cap?.src) { + setUrlYtt(cap.src); + setCaptionFormat(cap.format || (cap.src.toLowerCase().endsWith(".srt") ? "srt" : "srv3")); + } } setDataSet(true); setShowPlayer(true); @@ -66,7 +77,8 @@ const CustomPlayerPage = () => { const handleFile = ( e: React.ChangeEvent<HTMLInputElement>, - setter: (newValue: string) => any + setter: (newValue: string) => any, + opts?: { onFormat?: (format: "srv3" | "srt") => void } ) => { const file = e.target.files?.[0]; if (!file) { @@ -75,6 +87,10 @@ const CustomPlayerPage = () => { } const url = URL.createObjectURL(file).toString(); console.log(url); + if (opts?.onFormat) { + const name = file.name.toLowerCase(); + opts.onFormat(name.endsWith(".srt") ? "srt" : "srv3"); + } setter(url); }; @@ -84,10 +100,10 @@ const CustomPlayerPage = () => { { infoJson && infoJson.title ? ( <title>{infoJson.title}</title> - ) : + ) : <title>a very nice video</title> } - + </Head> {showPlayer ? ( <div className="mt-2"> @@ -114,6 +130,7 @@ const CustomPlayerPage = () => { { lang: "en", src: urlYtt, + format: captionFormat, }, ] : undefined @@ -177,7 +194,7 @@ const CustomPlayerPage = () => { ) : ( <div> <div className="px-4 pb-8"> - <h1 className="text-3xl mt-16 text-center">Custom Video Player</h1> + <h1 className="text-3xl mt-16 text-center">Moekyun Video Player</h1> <p className="text-lg text-center"> You can play locally-saved video files and chat replay JSON </p> @@ -238,14 +255,19 @@ const CustomPlayerPage = () => { <label className={[buttonStyle, "relative cursor-pointer"].join(" ")} > - <span>Select captions (srv3)</span> + <span>Select captions (srv3 or srt)</span> <span className="ml-auto"> {urlYtt ? <IconCheck width="1em" height="1em" /> : null} </span> <input type="file" + accept=".srv3,.xml,.srt" className="hidden" - onChange={(e) => handleFile(e, setUrlYtt)} + onChange={(e) => + handleFile(e, setUrlYtt, { + onFormat: (fmt) => setCaptionFormat(fmt), + }) + } /> </label> @@ -255,12 +277,29 @@ const CustomPlayerPage = () => { onClick={() => { setShowPlayer(true); setDataSet(false); - }} > Launch player </button> </form> + <div className="mt-6 mx-auto max-w-2xl text-sm text-gray-400 text-left border border-gray-800 rounded p-4"> + <p className="font-bold text-gray-200 mb-2">JSON data format</p> + <p className="mb-2"> + Pass a URL via the <code>?data=</code> query parameter pointing to a JSON file. + All fields are optional. Recognized top-level keys: + </p> + <ul className="list-disc list-inside space-y-1"> + <li><code>info</code> - URL to a YouTube <code>info.json</code> (yt-dlp metadata)</li> + <li><code>video</code> - URL to the video file/stream</li> + <li><code>chat</code> - URL to a chat replay JSON</li> + <li><code>srv3</code> - URL to a YouTube srv3 caption XML file</li> + <li><code>srt</code> - URL to a SubRip (<code>.srt</code>) subtitle file</li> + <li><code>captions</code> - a single object <code>{`{ src, format }`}</code> or an array of them, where <code>format</code> is <code>"srv3"</code> or <code>"srt"</code></li> + </ul> + <p className="mt-2"> + Example: <code>{`?data=https://example.com/session.json`}</code> + </p> + </div> </div> </div> )} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f42cf08..d1739ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: ^4.3.3 version: 4.3.3 next: - specifier: 13.0.6 - version: 13.0.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: 14.2.35 + version: 14.2.35(react-dom@18.2.0(react@18.2.0))(react@18.2.0) pretty-bytes: specifier: ^6.1.1 version: 6.1.1 @@ -176,87 +176,63 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@next/env@13.0.6': - resolution: {integrity: sha512-yceT6DCHKqPRS1cAm8DHvDvK74DLIkDQdm5iV+GnIts8h0QbdHvkUIkdOvQoOODgpr6018skbmSQp12z5OWIQQ==} + '@next/env@14.2.35': + resolution: {integrity: sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==} - '@next/swc-android-arm-eabi@13.0.6': - resolution: {integrity: sha512-FGFSj3v2Bluw8fD/X+1eXIEB0PhoJE0zfutsAauRhmNpjjZshLDgoXMWm1jTRL/04K/o9gwwO2+A8+sPVCH1uw==} - engines: {node: '>= 10'} - cpu: [arm] - os: [android] - - '@next/swc-android-arm64@13.0.6': - resolution: {integrity: sha512-7MgbtU7kimxuovVsd7jSJWMkIHBDBUsNLmmlkrBRHTvgzx5nDBXogP0hzZm7EImdOPwVMPpUHRQMBP9mbsiJYQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - - '@next/swc-darwin-arm64@13.0.6': - resolution: {integrity: sha512-AUVEpVTxbP/fxdFsjVI9d5a0CFn6NVV7A/RXOb0Y+pXKIIZ1V5rFjPwpYfIfyOo2lrqgehMNQcyMRoTrhq04xg==} + '@next/swc-darwin-arm64@14.2.33': + resolution: {integrity: sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@13.0.6': - resolution: {integrity: sha512-SasCDJlshglsPnbzhWaIF6VEGkQy2NECcAOxPwaPr0cwbbt4aUlZ7QmskNzgolr5eAjFS/xTr7CEeKJtZpAAtQ==} + '@next/swc-darwin-x64@14.2.33': + resolution: {integrity: sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-freebsd-x64@13.0.6': - resolution: {integrity: sha512-6Lbxd9gAdXneTkwHyYW/qtX1Tdw7ND9UbiGsGz/SP43ZInNWnW6q0au4hEVPZ9bOWWRKzcVoeTBdoMpQk9Hx9w==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - - '@next/swc-linux-arm-gnueabihf@13.0.6': - resolution: {integrity: sha512-wNdi5A519e1P+ozEuYOhWPzzE6m1y7mkO6NFwn6watUwO0X9nZs7fT9THmnekvmFQpaZ6U+xf2MQ9poQoCh6jQ==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - - '@next/swc-linux-arm64-gnu@13.0.6': - resolution: {integrity: sha512-e8KTRnleQY1KLk5PwGV5hrmvKksCc74QRpHl5ffWnEEAtL2FE0ave5aIkXqErsPdXkiKuA/owp3LjQrP+/AH7Q==} + '@next/swc-linux-arm64-gnu@14.2.33': + resolution: {integrity: sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [glibc] - '@next/swc-linux-arm64-musl@13.0.6': - resolution: {integrity: sha512-/7RF03C3mhjYpHN+pqOolgME3guiHU5T3TsejuyteqyEyzdEyLHod+jcYH6ft7UZ71a6TdOewvmbLOtzHW2O8A==} + '@next/swc-linux-arm64-musl@14.2.33': + resolution: {integrity: sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [musl] - '@next/swc-linux-x64-gnu@13.0.6': - resolution: {integrity: sha512-kxyEXnYHpOEkFnmrlwB1QlzJtjC6sAJytKcceIyFUHbCaD3W/Qb5tnclcnHKTaFccizZRePXvV25Ok/eUSpKTw==} + '@next/swc-linux-x64-gnu@14.2.33': + resolution: {integrity: sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [glibc] - '@next/swc-linux-x64-musl@13.0.6': - resolution: {integrity: sha512-N0c6gubS3WW1oYYgo02xzZnNatfVQP/CiJq2ax+DJ55ePV62IACbRCU99TZNXXg+Kos6vNW4k+/qgvkvpGDeyA==} + '@next/swc-linux-x64-musl@14.2.33': + resolution: {integrity: sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [musl] - '@next/swc-win32-arm64-msvc@13.0.6': - resolution: {integrity: sha512-QjeMB2EBqBFPb/ac0CYr7GytbhUkrG4EwFWbcE0vsRp4H8grt25kYpFQckL4Jak3SUrp7vKfDwZ/SwO7QdO8vw==} + '@next/swc-win32-arm64-msvc@14.2.33': + resolution: {integrity: sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-ia32-msvc@13.0.6': - resolution: {integrity: sha512-EQzXtdqRTcmhT/tCq81rIwE36Y3fNHPInaCuJzM/kftdXfa0F+64y7FAoMO13npX8EG1+SamXgp/emSusKrCXg==} + '@next/swc-win32-ia32-msvc@14.2.33': + resolution: {integrity: sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@next/swc-win32-x64-msvc@13.0.6': - resolution: {integrity: sha512-pSkqZ//UP/f2sS9T7IvHLfEWDPTX0vRyXJnAUNisKvO3eF3e1xdhDX7dix/X3Z3lnN4UjSwOzclAI87JFbOwmQ==} + '@next/swc-win32-x64-msvc@14.2.33': + resolution: {integrity: sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -273,8 +249,11 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@swc/helpers@0.4.14': - resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==} + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/helpers@0.5.5': + resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} '@tailwindcss/custom-forms@0.2.1': resolution: {integrity: sha512-XdP5XY6kxo3x5o50mWUyoYWxOPV16baagLoZ5uM41gh6IhXzhz/vJYzqrTb/lN58maGIKlpkxgVsQUNSsbAS3Q==} @@ -371,6 +350,10 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -606,6 +589,9 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -821,20 +807,20 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - next@13.0.6: - resolution: {integrity: sha512-COvigvms2LRt1rrzfBQcMQ2GZd86Mvk1z+LOLY5pniFtL4VrTmhZ9salrbKfSiXbhsD01TrDdD68ec3ABDyscA==} - engines: {node: '>=14.6.0'} + next@14.2.35: + resolution: {integrity: sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==} + engines: {node: '>=18.17.0'} hasBin: true peerDependencies: - fibers: '>= 3.1.0' - node-sass: ^6.0.0 || ^7.0.0 + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 react: ^18.2.0 react-dom: ^18.2.0 sass: ^1.3.0 peerDependenciesMeta: - fibers: + '@opentelemetry/api': optional: true - node-sass: + '@playwright/test': optional: true sass: optional: true @@ -1114,8 +1100,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.14: - resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} postcss@8.5.24: @@ -1231,6 +1217,10 @@ packages: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + string.prototype.trim@1.2.11: resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} engines: {node: '>= 0.4'} @@ -1246,8 +1236,8 @@ packages: strnum@1.1.2: resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} - styled-jsx@5.1.0: - resolution: {integrity: sha512-/iHaRJt9U7T+5tp6TRelLnqBqiaIT0HsO0+vgyj8hK2KUk7aejFqRrumqPUlAqDwAj8IbS/1hk3IhBAAK/FCUQ==} + styled-jsx@5.1.1: + resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} engines: {node: '>= 12.0.0'} peerDependencies: '@babel/core': '*' @@ -1454,45 +1444,33 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@next/env@13.0.6': {} - - '@next/swc-android-arm-eabi@13.0.6': - optional: true - - '@next/swc-android-arm64@13.0.6': - optional: true - - '@next/swc-darwin-arm64@13.0.6': - optional: true - - '@next/swc-darwin-x64@13.0.6': - optional: true + '@next/env@14.2.35': {} - '@next/swc-freebsd-x64@13.0.6': + '@next/swc-darwin-arm64@14.2.33': optional: true - '@next/swc-linux-arm-gnueabihf@13.0.6': + '@next/swc-darwin-x64@14.2.33': optional: true - '@next/swc-linux-arm64-gnu@13.0.6': + '@next/swc-linux-arm64-gnu@14.2.33': optional: true - '@next/swc-linux-arm64-musl@13.0.6': + '@next/swc-linux-arm64-musl@14.2.33': optional: true - '@next/swc-linux-x64-gnu@13.0.6': + '@next/swc-linux-x64-gnu@14.2.33': optional: true - '@next/swc-linux-x64-musl@13.0.6': + '@next/swc-linux-x64-musl@14.2.33': optional: true - '@next/swc-win32-arm64-msvc@13.0.6': + '@next/swc-win32-arm64-msvc@14.2.33': optional: true - '@next/swc-win32-ia32-msvc@13.0.6': + '@next/swc-win32-ia32-msvc@14.2.33': optional: true - '@next/swc-win32-x64-msvc@13.0.6': + '@next/swc-win32-x64-msvc@14.2.33': optional: true '@nodelib/fs.scandir@2.1.5': @@ -1507,8 +1485,11 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@swc/helpers@0.4.14': + '@swc/counter@0.1.3': {} + + '@swc/helpers@0.5.5': dependencies: + '@swc/counter': 0.1.3 tslib: 2.8.1 '@tailwindcss/custom-forms@0.2.1(tailwindcss@3.4.19)': @@ -1623,6 +1604,10 @@ snapshots: node-releases: 2.0.51 update-browserslist-db: 1.2.3(browserslist@4.28.7) + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -1922,6 +1907,8 @@ snapshots: gopd@1.2.0: {} + graceful-fs@4.2.11: {} + has-bigints@1.1.0: {} has-property-descriptors@1.0.2: @@ -2125,29 +2112,27 @@ snapshots: nanoid@3.3.16: {} - next@13.0.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + next@14.2.35(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: - '@next/env': 13.0.6 - '@swc/helpers': 0.4.14 + '@next/env': 14.2.35 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 caniuse-lite: 1.0.30001806 - postcss: 8.4.14 + graceful-fs: 4.2.11 + postcss: 8.4.31 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.0(react@18.2.0) + styled-jsx: 5.1.1(react@18.2.0) optionalDependencies: - '@next/swc-android-arm-eabi': 13.0.6 - '@next/swc-android-arm64': 13.0.6 - '@next/swc-darwin-arm64': 13.0.6 - '@next/swc-darwin-x64': 13.0.6 - '@next/swc-freebsd-x64': 13.0.6 - '@next/swc-linux-arm-gnueabihf': 13.0.6 - '@next/swc-linux-arm64-gnu': 13.0.6 - '@next/swc-linux-arm64-musl': 13.0.6 - '@next/swc-linux-x64-gnu': 13.0.6 - '@next/swc-linux-x64-musl': 13.0.6 - '@next/swc-win32-arm64-msvc': 13.0.6 - '@next/swc-win32-ia32-msvc': 13.0.6 - '@next/swc-win32-x64-msvc': 13.0.6 + '@next/swc-darwin-arm64': 14.2.33 + '@next/swc-darwin-x64': 14.2.33 + '@next/swc-linux-arm64-gnu': 14.2.33 + '@next/swc-linux-arm64-musl': 14.2.33 + '@next/swc-linux-x64-gnu': 14.2.33 + '@next/swc-linux-x64-musl': 14.2.33 + '@next/swc-win32-arm64-msvc': 14.2.33 + '@next/swc-win32-ia32-msvc': 14.2.33 + '@next/swc-win32-x64-msvc': 14.2.33 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -2418,7 +2403,7 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.14: + postcss@8.4.31: dependencies: nanoid: 3.3.16 picocolors: 1.1.1 @@ -2575,6 +2560,8 @@ snapshots: es-errors: 1.3.0 internal-slot: 1.1.0 + streamsearch@1.1.0: {} + string.prototype.trim@1.2.11: dependencies: call-bind: 1.0.9 @@ -2601,7 +2588,7 @@ snapshots: strnum@1.1.2: {} - styled-jsx@5.1.0(react@18.2.0): + styled-jsx@5.1.1(react@18.2.0): dependencies: client-only: 0.0.1 react: 18.2.0 |
