aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules/VideoPlayer/VideoPlayer2.tsx83
-rw-r--r--next-env.d.ts2
-rw-r--r--package.json2
-rw-r--r--pages/index.tsx57
-rw-r--r--pnpm-lock.yaml191
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, "&lt;")
+ .replace(/>/g, "&gt;");
+
+ 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
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage