mirror of
https://github.com/khairul169/code-share.git
synced 2025-04-29 17:19:37 +07:00
feat: fix panel persist over server rendering, etc
This commit is contained in:
parent
2c9faa332a
commit
efe51a9b5e
@ -50,6 +50,7 @@ const CodeEditor = (props: Props) => {
|
|||||||
parser,
|
parser,
|
||||||
plugins,
|
plugins,
|
||||||
cursorOffset: cursor,
|
cursorOffset: cursor,
|
||||||
|
printWidth: 64,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||||
|
@ -1,24 +1,82 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { GripVertical } from "lucide-react";
|
import { GripVertical } from "lucide-react";
|
||||||
|
import { createContext, forwardRef, useContext } from "react";
|
||||||
import * as ResizablePrimitive from "react-resizable-panels";
|
import * as ResizablePrimitive from "react-resizable-panels";
|
||||||
|
import cookieJs from "cookiejs";
|
||||||
|
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
|
import { usePageContext } from "~/renderer/context";
|
||||||
|
import { useDebounce } from "~/hooks/useDebounce";
|
||||||
|
|
||||||
|
const ResizableContext = createContext<{ initialSize: number[] }>(null!);
|
||||||
|
|
||||||
const ResizablePanelGroup = ({
|
const ResizablePanelGroup = ({
|
||||||
className,
|
className,
|
||||||
|
autoSaveId,
|
||||||
|
direction,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
|
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => {
|
||||||
<ResizablePrimitive.PanelGroup
|
const { cookies } = usePageContext();
|
||||||
className={cn(
|
const [debouncePersistLayout] = useDebounce((sizes: number[]) => {
|
||||||
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
|
if (autoSaveId && typeof window !== "undefined") {
|
||||||
className
|
cookieJs.set(panelKey, JSON.stringify(sizes));
|
||||||
)}
|
}
|
||||||
{...props}
|
}, 500);
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const ResizablePanel = ResizablePrimitive.Panel;
|
const panelKey = ["panel", direction, autoSaveId].join(":");
|
||||||
|
let initialSize: number[] = [];
|
||||||
|
|
||||||
|
if (autoSaveId && cookies && cookies[panelKey]) {
|
||||||
|
initialSize = JSON.parse(cookies[panelKey]) || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const onLayout = (sizes: number[]) => {
|
||||||
|
if (props.onLayout) {
|
||||||
|
props.onLayout(sizes);
|
||||||
|
}
|
||||||
|
debouncePersistLayout(sizes);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ResizableContext.Provider value={{ initialSize }}>
|
||||||
|
<ResizablePrimitive.PanelGroup
|
||||||
|
className={cn(
|
||||||
|
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
direction={direction}
|
||||||
|
onLayout={onLayout}
|
||||||
|
/>
|
||||||
|
</ResizableContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type ResizablePanelProps = React.ComponentProps<
|
||||||
|
typeof ResizablePrimitive.Panel
|
||||||
|
> & {
|
||||||
|
panelId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ResizablePanel = forwardRef((props: ResizablePanelProps, ref: any) => {
|
||||||
|
const { panelId, defaultSize, ...restProps } = props;
|
||||||
|
const ctx = useContext(ResizableContext);
|
||||||
|
let initialSize = defaultSize;
|
||||||
|
|
||||||
|
if (panelId != null) {
|
||||||
|
const size = ctx?.initialSize[panelId];
|
||||||
|
if (size != null) {
|
||||||
|
initialSize = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ResizablePrimitive.Panel
|
||||||
|
ref={ref}
|
||||||
|
defaultSize={initialSize}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const ResizableHandle = ({
|
const ResizableHandle = ({
|
||||||
withHandle,
|
withHandle,
|
||||||
|
5
next-env.d.ts
vendored
Normal file
5
next-env.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
@ -21,6 +21,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@swc/cli": "^0.3.9",
|
"@swc/cli": "^0.3.9",
|
||||||
|
"@types/cookie-parser": "^1.4.6",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/node": "^20.11.19",
|
"@types/node": "^20.11.19",
|
||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
@ -29,7 +30,6 @@
|
|||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"autoprefixer": "^10.0.1",
|
"autoprefixer": "^10.0.1",
|
||||||
"drizzle-kit": "^0.20.14",
|
"drizzle-kit": "^0.20.14",
|
||||||
"postcss": "^8",
|
|
||||||
"tailwindcss": "^3.3.0",
|
"tailwindcss": "^3.3.0",
|
||||||
"tsx": "^4.7.1",
|
"tsx": "^4.7.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
@ -58,13 +58,17 @@
|
|||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.0",
|
"clsx": "^2.1.0",
|
||||||
"console-feed": "^3.5.0",
|
"console-feed": "^3.5.0",
|
||||||
|
"cookie-parser": "^1.4.6",
|
||||||
|
"cookiejs": "^2.1.3",
|
||||||
"copy-to-clipboard": "^3.3.3",
|
"copy-to-clipboard": "^3.3.3",
|
||||||
|
"cssnano": "^6.0.3",
|
||||||
"drizzle-orm": "^0.29.3",
|
"drizzle-orm": "^0.29.3",
|
||||||
"drizzle-zod": "^0.5.1",
|
"drizzle-zod": "^0.5.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"lucide-react": "^0.331.0",
|
"lucide-react": "^0.331.0",
|
||||||
"mime": "^4.0.1",
|
"mime": "^4.0.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
"postcss": "^8",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -8,7 +8,6 @@ import { usePortrait } from "~/hooks/usePortrait";
|
|||||||
import Editor from "./components/editor";
|
import Editor from "./components/editor";
|
||||||
import ProjectContext from "./context/project";
|
import ProjectContext from "./context/project";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
import { withClientOnly } from "~/renderer/client-only";
|
|
||||||
import { useParams, useSearchParams } from "~/renderer/hooks";
|
import { useParams, useSearchParams } from "~/renderer/hooks";
|
||||||
import { BASE_URL } from "~/lib/consts";
|
import { BASE_URL } from "~/lib/consts";
|
||||||
|
|
||||||
@ -29,6 +28,7 @@ const ViewProjectPage = () => {
|
|||||||
className={cn("w-full !h-dvh bg-slate-600", !isCompact ? "md:p-4" : "")}
|
className={cn("w-full !h-dvh bg-slate-600", !isCompact ? "md:p-4" : "")}
|
||||||
>
|
>
|
||||||
<ResizablePanel
|
<ResizablePanel
|
||||||
|
panelId={0}
|
||||||
defaultSize={isPortrait ? 50 : 60}
|
defaultSize={isPortrait ? 50 : 60}
|
||||||
collapsible
|
collapsible
|
||||||
collapsedSize={0}
|
collapsedSize={0}
|
||||||
@ -45,6 +45,7 @@ const ViewProjectPage = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<ResizablePanel
|
<ResizablePanel
|
||||||
|
panelId={1}
|
||||||
defaultSize={isPortrait ? 50 : 40}
|
defaultSize={isPortrait ? 50 : 40}
|
||||||
collapsible
|
collapsible
|
||||||
collapsedSize={0}
|
collapsedSize={0}
|
||||||
@ -57,4 +58,4 @@ const ViewProjectPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withClientOnly(ViewProjectPage);
|
export default ViewProjectPage;
|
||||||
|
12
pages/project/@slug/+data.ts
Normal file
12
pages/project/@slug/+data.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { PageContext } from "vike/types";
|
||||||
|
import trpcServer from "~/server/api/trpc/trpc";
|
||||||
|
|
||||||
|
export const data = async (ctx: PageContext) => {
|
||||||
|
const trpc = await trpcServer(ctx);
|
||||||
|
const pinnedFiles = await trpc.file.getAll({ isPinned: true });
|
||||||
|
const files = await trpc.file.getAll();
|
||||||
|
|
||||||
|
return { files, pinnedFiles };
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Data = Awaited<ReturnType<typeof data>>;
|
@ -9,7 +9,6 @@ import FileViewer from "./file-viewer";
|
|||||||
import trpc from "~/lib/trpc";
|
import trpc from "~/lib/trpc";
|
||||||
import EditorContext from "../context/editor";
|
import EditorContext from "../context/editor";
|
||||||
import type { FileSchema } from "~/server/db/schema/file";
|
import type { FileSchema } from "~/server/db/schema/file";
|
||||||
import { usePortrait } from "~/hooks/usePortrait";
|
|
||||||
import Panel from "~/components/ui/panel";
|
import Panel from "~/components/ui/panel";
|
||||||
import { previewStore } from "../stores/web-preview";
|
import { previewStore } from "../stores/web-preview";
|
||||||
import { useProjectContext } from "../context/project";
|
import { useProjectContext } from "../context/project";
|
||||||
@ -19,27 +18,26 @@ import useCommandKey from "~/hooks/useCommandKey";
|
|||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { FaCompress, FaCompressArrowsAlt } from "react-icons/fa";
|
import { FaCompress, FaCompressArrowsAlt } from "react-icons/fa";
|
||||||
import ConsoleLogger from "./console-logger";
|
import ConsoleLogger from "./console-logger";
|
||||||
|
import { useData } from "~/renderer/hooks";
|
||||||
|
import { Data } from "../+data";
|
||||||
|
|
||||||
const Editor = () => {
|
const Editor = () => {
|
||||||
const isPortrait = usePortrait();
|
const { pinnedFiles } = useData<Data>();
|
||||||
const trpcUtils = trpc.useUtils();
|
const trpcUtils = trpc.useUtils();
|
||||||
const [isMounted, setMounted] = useState(false);
|
|
||||||
const project = useProjectContext();
|
const project = useProjectContext();
|
||||||
const sidebarPanel = useRef<ImperativePanelHandle>(null);
|
const sidebarPanel = useRef<ImperativePanelHandle>(null);
|
||||||
|
|
||||||
const [sidebarExpanded, setSidebarExpanded] = useState(false);
|
const [sidebarExpanded, setSidebarExpanded] = useState(false);
|
||||||
const [curTabIdx, setCurTabIdx] = useState(0);
|
const [curTabIdx, setCurTabIdx] = useState(0);
|
||||||
const [curOpenFiles, setOpenFiles] = useState<number[]>([]);
|
const [curOpenFiles, setOpenFiles] = useState<number[]>(
|
||||||
|
pinnedFiles.map((i) => i.id)
|
||||||
const pinnedFiles = trpc.file.getAll.useQuery(
|
|
||||||
{ isPinned: true },
|
|
||||||
{ enabled: !isMounted }
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const openedFilesData = trpc.file.getAll.useQuery(
|
const openedFilesData = trpc.file.getAll.useQuery(
|
||||||
{ id: curOpenFiles },
|
{ id: curOpenFiles },
|
||||||
{ enabled: curOpenFiles.length > 0 }
|
{ enabled: curOpenFiles.length > 0, initialData: pinnedFiles }
|
||||||
);
|
);
|
||||||
const [openedFiles, setOpenedFiles] = useState<any[]>([]);
|
const [openedFiles, setOpenedFiles] = useState<any[]>(pinnedFiles);
|
||||||
|
|
||||||
const deleteFile = trpc.file.delete.useMutation({
|
const deleteFile = trpc.file.delete.useMutation({
|
||||||
onSuccess: (file) => {
|
onSuccess: (file) => {
|
||||||
@ -53,10 +51,6 @@ const Editor = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const toggleSidebar = useCallback(() => {
|
const toggleSidebar = useCallback(() => {
|
||||||
const sidebar = sidebarPanel.current;
|
const sidebar = sidebarPanel.current;
|
||||||
if (!sidebar) {
|
if (!sidebar) {
|
||||||
@ -74,15 +68,19 @@ const Editor = () => {
|
|||||||
useCommandKey("b", toggleSidebar);
|
useCommandKey("b", toggleSidebar);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!pinnedFiles.data?.length || curOpenFiles.length > 0) {
|
if (!pinnedFiles?.length || curOpenFiles.length > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pinnedFiles.data.forEach((file) => {
|
pinnedFiles.forEach((file) => {
|
||||||
onOpenFile(file.id, false);
|
onOpenFile(file.id, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
setOpenFiles([]);
|
||||||
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [pinnedFiles.data]);
|
}, [pinnedFiles]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (openedFilesData.data) {
|
if (openedFilesData.data) {
|
||||||
@ -170,7 +168,8 @@ const Editor = () => {
|
|||||||
<ResizablePanelGroup autoSaveId="veditor-panel" direction="horizontal">
|
<ResizablePanelGroup autoSaveId="veditor-panel" direction="horizontal">
|
||||||
<ResizablePanel
|
<ResizablePanel
|
||||||
ref={sidebarPanel}
|
ref={sidebarPanel}
|
||||||
defaultSize={isPortrait ? 0 : 25}
|
panelId={0}
|
||||||
|
defaultSize={25}
|
||||||
minSize={10}
|
minSize={10}
|
||||||
collapsible
|
collapsible
|
||||||
collapsedSize={0}
|
collapsedSize={0}
|
||||||
@ -183,12 +182,9 @@ const Editor = () => {
|
|||||||
|
|
||||||
<ResizableHandle className="bg-slate-900" />
|
<ResizableHandle className="bg-slate-900" />
|
||||||
|
|
||||||
<ResizablePanel defaultSize={isPortrait ? 100 : 75}>
|
<ResizablePanel panelId={1} defaultSize={75}>
|
||||||
<ResizablePanelGroup
|
<ResizablePanelGroup autoSaveId="code-editor" direction="vertical">
|
||||||
autoCapitalize="code-editor"
|
<ResizablePanel panelId={0} defaultSize={80} minSize={20}>
|
||||||
direction="vertical"
|
|
||||||
>
|
|
||||||
<ResizablePanel defaultSize={isPortrait ? 100 : 80} minSize={20}>
|
|
||||||
<Tabs
|
<Tabs
|
||||||
tabs={openFileList}
|
tabs={openFileList}
|
||||||
current={curTabIdx}
|
current={curTabIdx}
|
||||||
@ -197,19 +193,16 @@ const Editor = () => {
|
|||||||
/>
|
/>
|
||||||
</ResizablePanel>
|
</ResizablePanel>
|
||||||
|
|
||||||
{!isPortrait ? (
|
<ResizableHandle />
|
||||||
<>
|
<ResizablePanel
|
||||||
<ResizableHandle />
|
panelId={1}
|
||||||
<ResizablePanel
|
defaultSize={20}
|
||||||
defaultSize={20}
|
collapsible
|
||||||
collapsible
|
collapsedSize={0}
|
||||||
collapsedSize={0}
|
minSize={10}
|
||||||
minSize={10}
|
>
|
||||||
>
|
<ConsoleLogger />
|
||||||
<ConsoleLogger />
|
</ResizablePanel>
|
||||||
</ResizablePanel>
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
</ResizablePanelGroup>
|
</ResizablePanelGroup>
|
||||||
</ResizablePanel>
|
</ResizablePanel>
|
||||||
</ResizablePanelGroup>
|
</ResizablePanelGroup>
|
||||||
|
@ -24,12 +24,17 @@ import {
|
|||||||
import { cn, getUrl } from "~/lib/utils";
|
import { cn, getUrl } from "~/lib/utils";
|
||||||
import FileIcon from "~/components/ui/file-icon";
|
import FileIcon from "~/components/ui/file-icon";
|
||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import { useParams } from "~/renderer/hooks";
|
import { useData, useParams } from "~/renderer/hooks";
|
||||||
|
import Spinner from "~/components/ui/spinner";
|
||||||
|
import { Data } from "../+data";
|
||||||
|
|
||||||
const FileListing = () => {
|
const FileListing = () => {
|
||||||
|
const pageData = useData<Data>();
|
||||||
const { onOpenFile, onFileChanged } = useEditorContext();
|
const { onOpenFile, onFileChanged } = useEditorContext();
|
||||||
const createFileDlg = useDisclose<CreateFileSchema>();
|
const createFileDlg = useDisclose<CreateFileSchema>();
|
||||||
const files = trpc.file.getAll.useQuery();
|
const files = trpc.file.getAll.useQuery(undefined, {
|
||||||
|
initialData: pageData.files,
|
||||||
|
});
|
||||||
|
|
||||||
const fileList = useMemo(() => groupFiles(files.data, null), [files.data]);
|
const fileList = useMemo(() => groupFiles(files.data, null), [files.data]);
|
||||||
|
|
||||||
@ -62,11 +67,17 @@ const FileListing = () => {
|
|||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-stretch flex-1 overflow-y-auto">
|
{files.isLoading ? (
|
||||||
{fileList.map((file) => (
|
<div className="flex-1 flex items-center justify-center">
|
||||||
<FileItem key={file.id} file={file} createFileDlg={createFileDlg} />
|
<Spinner />
|
||||||
))}
|
</div>
|
||||||
</div>
|
) : (
|
||||||
|
<div className="flex flex-col items-stretch flex-1 overflow-y-auto">
|
||||||
|
{fileList.map((file) => (
|
||||||
|
<FileItem key={file.id} file={file} createFileDlg={createFileDlg} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<CreateFileDialog
|
<CreateFileDialog
|
||||||
disclose={createFileDlg}
|
disclose={createFileDlg}
|
||||||
|
@ -4,6 +4,10 @@ import { getFileExt } from "~/lib/utils";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import CodeEditor from "../../../../components/ui/code-editor";
|
import CodeEditor from "../../../../components/ui/code-editor";
|
||||||
import trpc from "~/lib/trpc";
|
import trpc from "~/lib/trpc";
|
||||||
|
import { useData } from "~/renderer/hooks";
|
||||||
|
import { Data } from "../+data";
|
||||||
|
import ClientOnly from "~/renderer/client-only";
|
||||||
|
import Spinner from "~/components/ui/spinner";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: number;
|
id: number;
|
||||||
@ -11,7 +15,12 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const FileViewer = ({ id, onFileContentChange }: Props) => {
|
const FileViewer = ({ id, onFileContentChange }: Props) => {
|
||||||
const { data, isLoading, refetch } = trpc.file.getById.useQuery(id);
|
const { pinnedFiles } = useData<Data>();
|
||||||
|
const initialData = pinnedFiles.find((i) => i.id === id);
|
||||||
|
|
||||||
|
const { data, isLoading, refetch } = trpc.file.getById.useQuery(id, {
|
||||||
|
initialData,
|
||||||
|
});
|
||||||
const updateFileContent = trpc.file.update.useMutation({
|
const updateFileContent = trpc.file.update.useMutation({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
if (onFileContentChange) onFileContentChange();
|
if (onFileContentChange) onFileContentChange();
|
||||||
@ -20,8 +29,9 @@ const FileViewer = ({ id, onFileContentChange }: Props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <p>Loading...</p>;
|
return <LoadingLayout />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data || data.isDirectory) {
|
if (!data || data.isDirectory) {
|
||||||
return <p>File not found.</p>;
|
return <p>File not found.</p>;
|
||||||
}
|
}
|
||||||
@ -32,16 +42,36 @@ const FileViewer = ({ id, onFileContentChange }: Props) => {
|
|||||||
const ext = getFileExt(filename);
|
const ext = getFileExt(filename);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CodeEditor
|
<ClientOnly fallback={<SSRCodeEditor value={data?.content} />}>
|
||||||
lang={ext}
|
<CodeEditor
|
||||||
value={data?.content || ""}
|
lang={ext}
|
||||||
formatOnSave
|
value={data?.content || ""}
|
||||||
onChange={(val) => updateFileContent.mutate({ id, content: val })}
|
formatOnSave
|
||||||
/>
|
onChange={(val) => updateFileContent.mutate({ id, content: val })}
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const LoadingLayout = () => {
|
||||||
|
return (
|
||||||
|
<div className="w-full h-full flex items-center justify-center">
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SSRCodeEditor = ({ value }: { value?: string | null }) => {
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
className="w-full h-full py-3 pl-11 pr-2 overflow-x-auto text-nowrap font-mono text-sm md:text-[16px] md:leading-[22px] bg-[#1a1b26] text-[#787c99]"
|
||||||
|
value={value || ""}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default FileViewer;
|
export default FileViewer;
|
||||||
|
@ -31,6 +31,7 @@ const WebPreview = ({ url }: WebPreviewProps) => {
|
|||||||
return (
|
return (
|
||||||
<PanelComponent className="h-full flex flex-col bg-slate-800">
|
<PanelComponent className="h-full flex flex-col bg-slate-800">
|
||||||
<div className="h-10 flex items-center">
|
<div className="h-10 flex items-center">
|
||||||
|
<p className="flex-1 truncate text-xs uppercase pl-4">Preview</p>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="dark:hover:bg-slate-700"
|
className="dark:hover:bg-slate-700"
|
||||||
@ -38,18 +39,6 @@ const WebPreview = ({ url }: WebPreviewProps) => {
|
|||||||
>
|
>
|
||||||
<FaRedo />
|
<FaRedo />
|
||||||
</Button>
|
</Button>
|
||||||
<Input
|
|
||||||
className="flex-1 dark:bg-gray-900 dark:hover:bg-gray-950 h-8 rounded-full"
|
|
||||||
value={url || ""}
|
|
||||||
readOnly
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
className="dark:hover:bg-slate-700"
|
|
||||||
onClick={() => {}}
|
|
||||||
>
|
|
||||||
<FaEllipsisV />
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{url != null ? (
|
{url != null ? (
|
||||||
|
536
pnpm-lock.yaml
generated
536
pnpm-lock.yaml
generated
@ -71,9 +71,18 @@ dependencies:
|
|||||||
console-feed:
|
console-feed:
|
||||||
specifier: ^3.5.0
|
specifier: ^3.5.0
|
||||||
version: 3.5.0(jquery@3.7.1)(react-dom@18.2.0)(react@18.2.0)
|
version: 3.5.0(jquery@3.7.1)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
cookie-parser:
|
||||||
|
specifier: ^1.4.6
|
||||||
|
version: 1.4.6
|
||||||
|
cookiejs:
|
||||||
|
specifier: ^2.1.3
|
||||||
|
version: 2.1.3
|
||||||
copy-to-clipboard:
|
copy-to-clipboard:
|
||||||
specifier: ^3.3.3
|
specifier: ^3.3.3
|
||||||
version: 3.3.3
|
version: 3.3.3
|
||||||
|
cssnano:
|
||||||
|
specifier: ^6.0.3
|
||||||
|
version: 6.0.3(postcss@8.4.35)
|
||||||
drizzle-orm:
|
drizzle-orm:
|
||||||
specifier: ^0.29.3
|
specifier: ^0.29.3
|
||||||
version: 0.29.3(@types/react@18.2.57)(better-sqlite3@9.4.2)(react@18.2.0)
|
version: 0.29.3(@types/react@18.2.57)(better-sqlite3@9.4.2)(react@18.2.0)
|
||||||
@ -92,6 +101,9 @@ dependencies:
|
|||||||
nprogress:
|
nprogress:
|
||||||
specifier: ^0.2.0
|
specifier: ^0.2.0
|
||||||
version: 0.2.0
|
version: 0.2.0
|
||||||
|
postcss:
|
||||||
|
specifier: ^8
|
||||||
|
version: 8.4.35
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.2.5
|
specifier: ^3.2.5
|
||||||
version: 3.2.5
|
version: 3.2.5
|
||||||
@ -133,6 +145,9 @@ devDependencies:
|
|||||||
'@swc/cli':
|
'@swc/cli':
|
||||||
specifier: ^0.3.9
|
specifier: ^0.3.9
|
||||||
version: 0.3.9(@swc/core@1.4.2)
|
version: 0.3.9(@swc/core@1.4.2)
|
||||||
|
'@types/cookie-parser':
|
||||||
|
specifier: ^1.4.6
|
||||||
|
version: 1.4.6
|
||||||
'@types/express':
|
'@types/express':
|
||||||
specifier: ^4.17.21
|
specifier: ^4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
@ -157,9 +172,6 @@ devDependencies:
|
|||||||
drizzle-kit:
|
drizzle-kit:
|
||||||
specifier: ^0.20.14
|
specifier: ^0.20.14
|
||||||
version: 0.20.14
|
version: 0.20.14
|
||||||
postcss:
|
|
||||||
specifier: ^8
|
|
||||||
version: 8.4.35
|
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^3.3.0
|
specifier: ^3.3.0
|
||||||
version: 3.4.1
|
version: 3.4.1
|
||||||
@ -2145,6 +2157,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-HfBVYUShvktA6M78jrCsRLyeE6l2NdaPJxKg095h4vk0bgWVfz0MgEOCQR/hjGdw0EFLEVcZANhqTZaHEzr36w==}
|
resolution: {integrity: sha512-HfBVYUShvktA6M78jrCsRLyeE6l2NdaPJxKg095h4vk0bgWVfz0MgEOCQR/hjGdw0EFLEVcZANhqTZaHEzr36w==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@trysound/sax@0.2.0:
|
||||||
|
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
|
||||||
|
engines: {node: '>=10.13.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/babel__core@7.20.5:
|
/@types/babel__core@7.20.5:
|
||||||
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
|
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -2196,6 +2213,12 @@ packages:
|
|||||||
'@types/node': 20.11.19
|
'@types/node': 20.11.19
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/cookie-parser@1.4.6:
|
||||||
|
resolution: {integrity: sha512-KoooCrD56qlLskXPLGUiJxOMnv5l/8m7cQD2OxJ73NPMhuSz9PmvwRD6EpjDyKBVrdJDdQ4bQK7JFNHnNmax0w==}
|
||||||
|
dependencies:
|
||||||
|
'@types/express': 4.17.21
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/estree@1.0.5:
|
/@types/estree@1.0.5:
|
||||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||||
|
|
||||||
@ -2608,6 +2631,10 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/boolbase@1.0.0:
|
||||||
|
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/brace-expansion@1.1.11:
|
/brace-expansion@1.1.11:
|
||||||
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
|
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -2635,7 +2662,6 @@ packages:
|
|||||||
electron-to-chromium: 1.4.678
|
electron-to-chromium: 1.4.678
|
||||||
node-releases: 2.0.14
|
node-releases: 2.0.14
|
||||||
update-browserslist-db: 1.0.13(browserslist@4.23.0)
|
update-browserslist-db: 1.0.13(browserslist@4.23.0)
|
||||||
dev: true
|
|
||||||
|
|
||||||
/buffer-from@1.1.2:
|
/buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
@ -2700,9 +2726,17 @@ packages:
|
|||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/caniuse-api@3.0.0:
|
||||||
|
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.23.0
|
||||||
|
caniuse-lite: 1.0.30001588
|
||||||
|
lodash.memoize: 4.1.2
|
||||||
|
lodash.uniq: 4.5.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/caniuse-lite@1.0.30001588:
|
/caniuse-lite@1.0.30001588:
|
||||||
resolution: {integrity: sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==}
|
resolution: {integrity: sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/chalk@2.4.2:
|
/chalk@2.4.2:
|
||||||
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
|
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
|
||||||
@ -2809,6 +2843,10 @@ packages:
|
|||||||
hasBin: true
|
hasBin: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/colord@2.9.3:
|
||||||
|
resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/commander@4.1.1:
|
/commander@4.1.1:
|
||||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
@ -2816,7 +2854,6 @@ packages:
|
|||||||
/commander@7.2.0:
|
/commander@7.2.0:
|
||||||
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
|
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/commander@9.5.0:
|
/commander@9.5.0:
|
||||||
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
|
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
|
||||||
@ -2866,15 +2903,32 @@ packages:
|
|||||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/cookie-parser@1.4.6:
|
||||||
|
resolution: {integrity: sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==}
|
||||||
|
engines: {node: '>= 0.8.0'}
|
||||||
|
dependencies:
|
||||||
|
cookie: 0.4.1
|
||||||
|
cookie-signature: 1.0.6
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cookie-signature@1.0.6:
|
/cookie-signature@1.0.6:
|
||||||
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
|
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/cookie@0.4.1:
|
||||||
|
resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cookie@0.5.0:
|
/cookie@0.5.0:
|
||||||
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/cookiejs@2.1.3:
|
||||||
|
resolution: {integrity: sha512-pA/nRQVka2eTXm1/Dq8pNt1PN+e1PJNItah0vL15qwpet81/tUfrAp8e0iiVM8WEAzDcTGK5/1hDyR6BdBZMVg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/copy-anything@3.0.5:
|
/copy-anything@3.0.5:
|
||||||
resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
|
resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
|
||||||
engines: {node: '>=12.13'}
|
engines: {node: '>=12.13'}
|
||||||
@ -2919,11 +2973,116 @@ packages:
|
|||||||
shebang-command: 2.0.0
|
shebang-command: 2.0.0
|
||||||
which: 2.0.2
|
which: 2.0.2
|
||||||
|
|
||||||
|
/css-declaration-sorter@7.1.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-dZ3bVTEEc1vxr3Bek9vGwfB5Z6ESPULhcRvO472mfjVnj8jRcTnKO8/JTczlvxM10Myb+wBM++1MtdO76eWcaQ==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.0.9
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/css-select@5.1.0:
|
||||||
|
resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
|
||||||
|
dependencies:
|
||||||
|
boolbase: 1.0.0
|
||||||
|
css-what: 6.1.0
|
||||||
|
domhandler: 5.0.3
|
||||||
|
domutils: 3.1.0
|
||||||
|
nth-check: 2.1.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/css-tree@2.2.1:
|
||||||
|
resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
|
||||||
|
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
|
||||||
|
dependencies:
|
||||||
|
mdn-data: 2.0.28
|
||||||
|
source-map-js: 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/css-tree@2.3.1:
|
||||||
|
resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
|
||||||
|
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
|
||||||
|
dependencies:
|
||||||
|
mdn-data: 2.0.30
|
||||||
|
source-map-js: 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/css-what@6.1.0:
|
||||||
|
resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cssesc@3.0.0:
|
/cssesc@3.0.0:
|
||||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
/cssnano-preset-default@6.0.3(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-4y3H370aZCkT9Ev8P4SO4bZbt+AExeKhh8wTbms/X7OLDo5E7AYUUy6YPxa/uF5Grf+AJwNcCnxKhZynJ6luBA==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
css-declaration-sorter: 7.1.1(postcss@8.4.35)
|
||||||
|
cssnano-utils: 4.0.1(postcss@8.4.35)
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-calc: 9.0.1(postcss@8.4.35)
|
||||||
|
postcss-colormin: 6.0.2(postcss@8.4.35)
|
||||||
|
postcss-convert-values: 6.0.2(postcss@8.4.35)
|
||||||
|
postcss-discard-comments: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-discard-duplicates: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-discard-empty: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-discard-overridden: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-merge-longhand: 6.0.2(postcss@8.4.35)
|
||||||
|
postcss-merge-rules: 6.0.3(postcss@8.4.35)
|
||||||
|
postcss-minify-font-values: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-minify-gradients: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-minify-params: 6.0.2(postcss@8.4.35)
|
||||||
|
postcss-minify-selectors: 6.0.2(postcss@8.4.35)
|
||||||
|
postcss-normalize-charset: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-normalize-display-values: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-normalize-positions: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-normalize-repeat-style: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-normalize-string: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-normalize-timing-functions: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-normalize-unicode: 6.0.2(postcss@8.4.35)
|
||||||
|
postcss-normalize-url: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-normalize-whitespace: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-ordered-values: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-reduce-initial: 6.0.2(postcss@8.4.35)
|
||||||
|
postcss-reduce-transforms: 6.0.1(postcss@8.4.35)
|
||||||
|
postcss-svgo: 6.0.2(postcss@8.4.35)
|
||||||
|
postcss-unique-selectors: 6.0.2(postcss@8.4.35)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/cssnano-utils@4.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-6qQuYDqsGoiXssZ3zct6dcMxiqfT6epy7x4R0TQJadd4LWO3sPR6JH6ZByOvVLoZ6EdwPGgd7+DR1EmX3tiXQQ==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/cssnano@6.0.3(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-MRq4CIj8pnyZpcI2qs6wswoYoDD1t0aL28n+41c1Ukcpm56m1h6mCexIHBGjfZfnTqtGSSCP4/fB1ovxgjBOiw==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
cssnano-preset-default: 6.0.3(postcss@8.4.35)
|
||||||
|
lilconfig: 3.1.1
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/csso@5.0.5:
|
||||||
|
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
|
||||||
|
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
|
||||||
|
dependencies:
|
||||||
|
css-tree: 2.2.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/csstype@2.6.21:
|
/csstype@2.6.21:
|
||||||
resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
|
resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -3020,6 +3179,33 @@ packages:
|
|||||||
/dlv@1.1.3:
|
/dlv@1.1.3:
|
||||||
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
|
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
|
||||||
|
|
||||||
|
/dom-serializer@2.0.0:
|
||||||
|
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
|
||||||
|
dependencies:
|
||||||
|
domelementtype: 2.3.0
|
||||||
|
domhandler: 5.0.3
|
||||||
|
entities: 4.5.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/domelementtype@2.3.0:
|
||||||
|
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/domhandler@5.0.3:
|
||||||
|
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
||||||
|
engines: {node: '>= 4'}
|
||||||
|
dependencies:
|
||||||
|
domelementtype: 2.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/domutils@3.1.0:
|
||||||
|
resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
|
||||||
|
dependencies:
|
||||||
|
dom-serializer: 2.0.0
|
||||||
|
domelementtype: 2.3.0
|
||||||
|
domhandler: 5.0.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/dreamopt@0.8.0:
|
/dreamopt@0.8.0:
|
||||||
resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==}
|
resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
@ -3144,7 +3330,6 @@ packages:
|
|||||||
|
|
||||||
/electron-to-chromium@1.4.678:
|
/electron-to-chromium@1.4.678:
|
||||||
resolution: {integrity: sha512-NbdGC2p0O5Q5iVhLEsNBSfytaw7wbEFJlIvaF71wi6QDtLAph5/rVogjyOpf/QggJIt8hNK3KdwNJnc2bzckbw==}
|
resolution: {integrity: sha512-NbdGC2p0O5Q5iVhLEsNBSfytaw7wbEFJlIvaF71wi6QDtLAph5/rVogjyOpf/QggJIt8hNK3KdwNJnc2bzckbw==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/emmet@2.4.6:
|
/emmet@2.4.6:
|
||||||
resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==}
|
resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==}
|
||||||
@ -3182,6 +3367,11 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
|
|
||||||
|
/entities@4.5.0:
|
||||||
|
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||||
|
engines: {node: '>=0.12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/env-paths@3.0.0:
|
/env-paths@3.0.0:
|
||||||
resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==}
|
resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
@ -3317,7 +3507,6 @@ packages:
|
|||||||
/escalade@3.1.2:
|
/escalade@3.1.2:
|
||||||
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
|
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/escape-html@1.0.3:
|
/escape-html@1.0.3:
|
||||||
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
||||||
@ -3982,10 +4171,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
|
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/lodash.memoize@4.1.2:
|
||||||
|
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/lodash.throttle@4.1.1:
|
/lodash.throttle@4.1.1:
|
||||||
resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
|
resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/lodash.uniq@4.5.0:
|
||||||
|
resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/loose-envify@1.4.0:
|
/loose-envify@1.4.0:
|
||||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@ -4042,6 +4239,14 @@ packages:
|
|||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/mdn-data@2.0.28:
|
||||||
|
resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/mdn-data@2.0.30:
|
||||||
|
resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/media-typer@0.3.0:
|
/media-typer@0.3.0:
|
||||||
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
|
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@ -4269,7 +4474,6 @@ packages:
|
|||||||
|
|
||||||
/node-releases@2.0.14:
|
/node-releases@2.0.14:
|
||||||
resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
|
resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/nopt@5.0.0:
|
/nopt@5.0.0:
|
||||||
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
||||||
@ -4320,6 +4524,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==}
|
resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/nth-check@2.1.1:
|
||||||
|
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||||
|
dependencies:
|
||||||
|
boolbase: 1.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/object-assign@4.1.1:
|
/object-assign@4.1.1:
|
||||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -4449,6 +4659,77 @@ packages:
|
|||||||
nice-napi: 1.0.2
|
nice-napi: 1.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/postcss-calc@9.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.2.2
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-selector-parser: 6.0.15
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-colormin@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-TXKOxs9LWcdYo5cgmcSHPkyrLAh86hX1ijmyy6J8SbOhyv6ua053M3ZAM/0j44UsnQNIWdl8gb5L7xX2htKeLw==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.23.0
|
||||||
|
caniuse-api: 3.0.0
|
||||||
|
colord: 2.9.3
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-convert-values@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-aeBmaTnGQ+NUSVQT8aY0sKyAD/BaLJenEKZ03YK0JnDE1w1Rr8XShoxdal2V2H26xTJKr3v5haByOhJuyT4UYw==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.23.0
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-discard-comments@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-f1KYNPtqYLUeZGCHQPKzzFtsHaRuECe6jLakf/RjSRqvF5XHLZnM2+fXLhb8Qh/HBFHs3M4cSLb1k3B899RYIg==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-discard-duplicates@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-1hvUs76HLYR8zkScbwyJ8oJEugfPV+WchpnA+26fpJ7Smzs51CzGBHC32RS03psuX/2l0l0UKh2StzNxOrKCYg==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-discard-empty@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-yitcmKwmVWtNsrrRqGJ7/C0YRy53i0mjexBDQ9zYxDwTWVBgbU4+C9jIZLmQlTDT9zhml+u0OMFJh8+31krmOg==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-discard-overridden@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-qs0ehZMMZpSESbRkw1+inkf51kak6OOzNRaoLd/U7Fatp0aN2HQ1rxGOrJvYcRAN9VpX8kUF13R2ofn8OlvFVA==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-import@15.1.0(postcss@8.4.35):
|
/postcss-import@15.1.0(postcss@8.4.35):
|
||||||
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
|
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@ -4485,6 +4766,74 @@ packages:
|
|||||||
postcss: 8.4.35
|
postcss: 8.4.35
|
||||||
yaml: 2.3.4
|
yaml: 2.3.4
|
||||||
|
|
||||||
|
/postcss-merge-longhand@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-+yfVB7gEM8SrCo9w2lCApKIEzrTKl5yS1F4yGhV3kSim6JzbfLGJyhR1B6X+6vOT0U33Mgx7iv4X9MVWuaSAfw==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
stylehacks: 6.0.2(postcss@8.4.35)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-merge-rules@6.0.3(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-yfkDqSHGohy8sGYIJwBmIGDv4K4/WrJPX355XrxQb/CSsT4Kc/RxDi6akqn5s9bap85AWgv21ArcUWwWdGNSHA==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.23.0
|
||||||
|
caniuse-api: 3.0.0
|
||||||
|
cssnano-utils: 4.0.1(postcss@8.4.35)
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-selector-parser: 6.0.15
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-minify-font-values@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-tIwmF1zUPoN6xOtA/2FgVk1ZKrLcCvE0dpZLtzyyte0j9zUeB8RTbCqrHZGjJlxOvNWKMYtunLrrl7HPOiR46w==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-minify-gradients@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-M1RJWVjd6IOLPl1hYiOd5HQHgpp6cvJVLrieQYS9y07Yo8itAr6jaekzJphaJFR0tcg4kRewCk3kna9uHBxn/w==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
colord: 2.9.3
|
||||||
|
cssnano-utils: 4.0.1(postcss@8.4.35)
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-minify-params@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-zwQtbrPEBDj+ApELZ6QylLf2/c5zmASoOuA4DzolyVGdV38iR2I5QRMsZcHkcdkZzxpN8RS4cN7LPskOkTwTZw==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.23.0
|
||||||
|
cssnano-utils: 4.0.1(postcss@8.4.35)
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-minify-selectors@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-0b+m+w7OAvZejPQdN2GjsXLv5o0jqYHX3aoV0e7RBKPCsB7TYG5KKWBFhGnB/iP3213Ts8c5H4wLPLMm7z28Sg==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-selector-parser: 6.0.15
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-nested@6.0.1(postcss@8.4.35):
|
/postcss-nested@6.0.1(postcss@8.4.35):
|
||||||
resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==}
|
resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==}
|
||||||
engines: {node: '>=12.0'}
|
engines: {node: '>=12.0'}
|
||||||
@ -4494,6 +4843,128 @@ packages:
|
|||||||
postcss: 8.4.35
|
postcss: 8.4.35
|
||||||
postcss-selector-parser: 6.0.15
|
postcss-selector-parser: 6.0.15
|
||||||
|
|
||||||
|
/postcss-normalize-charset@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-aW5LbMNRZ+oDV57PF9K+WI1Z8MPnF+A8qbajg/T8PP126YrGX1f9IQx21GI2OlGz7XFJi/fNi0GTbY948XJtXg==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-normalize-display-values@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-mc3vxp2bEuCb4LgCcmG1y6lKJu1Co8T+rKHrcbShJwUmKJiEl761qb/QQCfFwlrvSeET3jksolCR/RZuMURudw==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-normalize-positions@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-HRsq8u/0unKNvm0cvwxcOUEcakFXqZ41fv3FOdPn916XFUrympjr+03oaLkuZENz3HE9RrQE9yU0Xv43ThWjQg==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-normalize-repeat-style@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-Gbb2nmCy6tTiA7Sh2MBs3fj9W8swonk6lw+dFFeQT68B0Pzwp1kvisJQkdV6rbbMSd9brMlS8I8ts52tAGWmGQ==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-normalize-string@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-5Fhx/+xzALJD9EI26Aq23hXwmv97Zfy2VFrt5PLT8lAhnBIZvmaT5pQk+NuJ/GWj/QWaKSKbnoKDGLbV6qnhXg==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-normalize-timing-functions@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-4zcczzHqmCU7L5dqTB9rzeqPWRMc0K2HoR+Bfl+FSMbqGBUcP5LRfgcH4BdRtLuzVQK1/FHdFoGT3F7rkEnY+g==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-normalize-unicode@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-Ff2VdAYCTGyMUwpevTZPZ4w0+mPjbZzLLyoLh/RMpqUqeQKZ+xMm31hkxBavDcGKcxm6ACzGk0nBfZ8LZkStKA==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.23.0
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-normalize-url@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-jEXL15tXSvbjm0yzUV7FBiEXwhIa9H88JOXDGQzmcWoB4mSjZIsmtto066s2iW9FYuIrIF4k04HA2BKAOpbsaQ==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-normalize-whitespace@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-76i3NpWf6bB8UHlVuLRxG4zW2YykF9CTEcq/9LGAiz2qBuX5cBStadkk0jSkg9a9TCIXbMQz7yzrygKoCW9JuA==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-ordered-values@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-XXbb1O/MW9HdEhnBxitZpPFbIvDgbo9NK4c/5bOfiKpnIGZDoL2xd7/e6jW5DYLsWxBbs+1nZEnVgnjnlFViaA==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
cssnano-utils: 4.0.1(postcss@8.4.35)
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-reduce-initial@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-YGKalhNlCLcjcLvjU5nF8FyeCTkCO5UtvJEt0hrPZVCTtRLSOH4z00T1UntQPj4dUmIYZgMj8qK77JbSX95hSw==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.23.0
|
||||||
|
caniuse-api: 3.0.0
|
||||||
|
postcss: 8.4.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-reduce-transforms@6.0.1(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-fUbV81OkUe75JM+VYO1gr/IoA2b/dRiH6HvMwhrIBSUrxq3jNZQZitSnugcTLDi1KkQh1eR/zi+iyxviUNBkcQ==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-selector-parser@6.0.15:
|
/postcss-selector-parser@6.0.15:
|
||||||
resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==}
|
resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@ -4501,6 +4972,27 @@ packages:
|
|||||||
cssesc: 3.0.0
|
cssesc: 3.0.0
|
||||||
util-deprecate: 1.0.2
|
util-deprecate: 1.0.2
|
||||||
|
|
||||||
|
/postcss-svgo@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-IH5R9SjkTkh0kfFOQDImyy1+mTCb+E830+9SV1O+AaDcoHTvfsvt6WwJeo7KwcHbFnevZVCsXhDmjFiGVuwqFQ==}
|
||||||
|
engines: {node: ^14 || ^16 || >= 18}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
svgo: 3.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/postcss-unique-selectors@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-8IZGQ94nechdG7Y9Sh9FlIY2b4uS8/k8kdKRX040XHsS3B6d1HrJAkXrBSsSu4SuARruSsUjW3nlSw8BHkaAYQ==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-selector-parser: 6.0.15
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-value-parser@4.2.0:
|
/postcss-value-parser@4.2.0:
|
||||||
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
|
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
|
||||||
|
|
||||||
@ -5080,6 +5572,17 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==}
|
resolution: {integrity: sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/stylehacks@6.0.2(postcss@8.4.35):
|
||||||
|
resolution: {integrity: sha512-00zvJGnCu64EpMjX8b5iCZ3us2Ptyw8+toEkb92VdmkEaRaSGBNKAoK6aWZckhXxmQP8zWiTaFaiMGIU8Ve8sg==}
|
||||||
|
engines: {node: ^14 || ^16 || >=18.0}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.4.31
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.23.0
|
||||||
|
postcss: 8.4.35
|
||||||
|
postcss-selector-parser: 6.0.15
|
||||||
|
dev: false
|
||||||
|
|
||||||
/sucrase@3.35.0:
|
/sucrase@3.35.0:
|
||||||
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
|
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
|
||||||
engines: {node: '>=16 || 14 >=14.17'}
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
@ -5110,6 +5613,20 @@ packages:
|
|||||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
/svgo@3.2.0:
|
||||||
|
resolution: {integrity: sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
'@trysound/sax': 0.2.0
|
||||||
|
commander: 7.2.0
|
||||||
|
css-select: 5.1.0
|
||||||
|
css-tree: 2.3.1
|
||||||
|
css-what: 6.1.0
|
||||||
|
csso: 5.0.5
|
||||||
|
picocolors: 1.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tailwind-merge@2.2.1:
|
/tailwind-merge@2.2.1:
|
||||||
resolution: {integrity: sha512-o+2GTLkthfa5YUt4JxPfzMIpQzZ3adD1vLVkvKE1Twl9UAhGsEbIZhHHZVRttyW177S8PDJI3bTQNaebyofK3Q==}
|
resolution: {integrity: sha512-o+2GTLkthfa5YUt4JxPfzMIpQzZ3adD1vLVkvKE1Twl9UAhGsEbIZhHHZVRttyW177S8PDJI3bTQNaebyofK3Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -5310,7 +5827,6 @@ packages:
|
|||||||
browserslist: 4.23.0
|
browserslist: 4.23.0
|
||||||
escalade: 3.1.2
|
escalade: 3.1.2
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/use-callback-ref@1.3.1(@types/react@18.2.57)(react@18.2.0):
|
/use-callback-ref@1.3.1(@types/react@18.2.57)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==}
|
resolution: {integrity: sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==}
|
||||||
|
@ -2,7 +2,7 @@ import type { Config } from "vike/types";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
clientRouting: true,
|
clientRouting: true,
|
||||||
passToClient: ["routeParams"],
|
passToClient: ["routeParams", "cookies"],
|
||||||
meta: {
|
meta: {
|
||||||
title: {
|
title: {
|
||||||
env: { server: true, client: true },
|
env: { server: true, client: true },
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
//
|
import type { Request } from "express";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace Vike {
|
namespace Vike {
|
||||||
interface PageContext {
|
interface PageContext {
|
||||||
@ -12,6 +13,8 @@ declare global {
|
|||||||
description?: string;
|
description?: string;
|
||||||
};
|
};
|
||||||
abortReason?: string;
|
abortReason?: string;
|
||||||
|
req: Request;
|
||||||
|
cookies: Record<string, string>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
|
import { type Request, type Response, Router } from "express";
|
||||||
import { getFileExt } from "~/lib/utils";
|
import { getFileExt } from "~/lib/utils";
|
||||||
import db from "~/server/db";
|
import db from "~/server/db";
|
||||||
import { file } from "~/server/db/schema/file";
|
import { file } from "~/server/db/schema/file";
|
||||||
import { and, eq, isNull } from "drizzle-orm";
|
import { and, eq, isNull } from "drizzle-orm";
|
||||||
import { serveHtml } from "./serve-html";
|
import { serveHtml } from "./serve-html";
|
||||||
import { Mime } from "mime/lite";
|
|
||||||
import standardTypes from "mime/types/standard.js";
|
|
||||||
import otherTypes from "mime/types/other.js";
|
|
||||||
import { serveJs } from "./serve-js";
|
import { serveJs } from "./serve-js";
|
||||||
import { type Request, type Response, Router } from "express";
|
import { getMimeType } from "~/server/lib/mime";
|
||||||
|
import { postcss } from "./postcss";
|
||||||
const mime = new Mime(standardTypes, otherTypes);
|
|
||||||
mime.define({ "text/javascript": ["jsx", "tsx"] }, true);
|
|
||||||
|
|
||||||
const get = async (req: Request, res: Response) => {
|
const get = async (req: Request, res: Response) => {
|
||||||
const { slug, ...pathParams } = req.params as any;
|
const { slug, ...pathParams } = req.params as any;
|
||||||
@ -35,10 +31,11 @@ const get = async (req: Request, res: Response) => {
|
|||||||
content = await serveJs(fileData);
|
content = await serveJs(fileData);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setHeader(
|
if (["css"].includes(ext)) {
|
||||||
"Content-Type",
|
content = await postcss(fileData);
|
||||||
mime.getType(fileData.filename) || "application/octet-stream"
|
}
|
||||||
);
|
|
||||||
|
res.setHeader("Content-Type", getMimeType(fileData.filename));
|
||||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
res.setHeader("Access-Control-Allow-Methods", "GET");
|
res.setHeader("Access-Control-Allow-Methods", "GET");
|
||||||
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||||
|
34
server/api/preview/postcss.ts
Normal file
34
server/api/preview/postcss.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import postcssPlugin from "postcss";
|
||||||
|
import tailwindcss from "tailwindcss";
|
||||||
|
import cssnano from "cssnano";
|
||||||
|
import { fileExists, getProjectDir } from "~/server/lib/utils";
|
||||||
|
import { FileSchema } from "~/server/db/schema/file";
|
||||||
|
import { unpackProject } from "~/server/lib/unpack-project";
|
||||||
|
|
||||||
|
export const postcss = async (fileData: FileSchema) => {
|
||||||
|
const content = fileData.content || "";
|
||||||
|
|
||||||
|
const projectDir = getProjectDir();
|
||||||
|
if (!fileExists(projectDir)) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await unpackProject({ ext: "ts,tsx,js,jsx,html" });
|
||||||
|
|
||||||
|
const result = await postcssPlugin([
|
||||||
|
tailwindcss({
|
||||||
|
content: [projectDir + "/**/*.{ts,tsx,js,jsx,html}"],
|
||||||
|
}),
|
||||||
|
cssnano({
|
||||||
|
preset: ["default", { discardComments: { removeAll: true } }],
|
||||||
|
}),
|
||||||
|
]).process(content, {
|
||||||
|
from: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.css;
|
||||||
|
} catch (err) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
};
|
@ -2,6 +2,8 @@ import db from "~/server/db";
|
|||||||
import { FileSchema, file } from "~/server/db/schema/file";
|
import { FileSchema, file } from "~/server/db/schema/file";
|
||||||
import { and, eq, isNull } from "drizzle-orm";
|
import { and, eq, isNull } from "drizzle-orm";
|
||||||
|
|
||||||
|
const preventHtmlDirectAccess = `<script>if (window === window.parent) {window.location.href = '/';}</script>`;
|
||||||
|
|
||||||
export const serveHtml = async (fileData: FileSchema) => {
|
export const serveHtml = async (fileData: FileSchema) => {
|
||||||
const layout = await db.query.file.findFirst({
|
const layout = await db.query.file.findFirst({
|
||||||
where: and(
|
where: and(
|
||||||
@ -14,15 +16,16 @@ export const serveHtml = async (fileData: FileSchema) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let content = fileData.content || "";
|
let content = fileData.content || "";
|
||||||
if (!layout?.content) {
|
if (layout?.content != null) {
|
||||||
return content;
|
content = layout.content.replace("{CONTENT}", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
content = layout.content.replace("{CONTENT}", content);
|
|
||||||
|
|
||||||
const bodyOpeningTagIdx = content.indexOf("<body");
|
const bodyOpeningTagIdx = content.indexOf("<body");
|
||||||
const firstScriptTagIdx = content.indexOf("<script", bodyOpeningTagIdx);
|
const firstScriptTagIdx = content.indexOf("<script", bodyOpeningTagIdx);
|
||||||
const injectScripts = ['<script src="/js/hook-console.js"></script>'];
|
const injectScripts = [
|
||||||
|
'<script src="/js/hook-console.js"></script>',
|
||||||
|
preventHtmlDirectAccess,
|
||||||
|
];
|
||||||
|
|
||||||
const importMaps = [
|
const importMaps = [
|
||||||
{ name: "react", url: "https://esm.sh/react@18.2.0" },
|
{ name: "react", url: "https://esm.sh/react@18.2.0" },
|
||||||
@ -45,7 +48,5 @@ export const serveHtml = async (fileData: FileSchema) => {
|
|||||||
content.substring(firstScriptTagIdx);
|
content.substring(firstScriptTagIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// content = content.replace(/ {2}|\r\n|\n|\r/gm, "");
|
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import { CreateExpressContextOptions } from "@trpc/server/adapters/express";
|
import { Request } from "express";
|
||||||
|
|
||||||
export const createContext = async ({
|
export const createContext = async ({ req }: { req: Request }) => {
|
||||||
req,
|
|
||||||
res,
|
|
||||||
}: CreateExpressContextOptions) => {
|
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import { createContext } from "./context";
|
import { createContext } from "./context";
|
||||||
import { appRouter } from "../../routers/_app";
|
import { appRouter } from "../../routers/_app";
|
||||||
import { createCallerFactory } from ".";
|
import { createCallerFactory } from ".";
|
||||||
|
import { PageContext } from "vike/types";
|
||||||
|
|
||||||
const trpcServer = createCallerFactory(appRouter)(createContext);
|
const trpcServer = async (ctx: PageContext) => {
|
||||||
|
const createCaller = createCallerFactory(appRouter);
|
||||||
|
const context = await createContext({ req: ctx.req });
|
||||||
|
return createCaller(context);
|
||||||
|
};
|
||||||
|
|
||||||
export default trpcServer;
|
export default trpcServer;
|
||||||
|
@ -12,6 +12,52 @@ const main = async () => {
|
|||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
|
// await db
|
||||||
|
// .insert(file)
|
||||||
|
// .values([
|
||||||
|
// {
|
||||||
|
// userId: adminUser.id,
|
||||||
|
// path: "index.html",
|
||||||
|
// filename: "index.html",
|
||||||
|
// content: '<p class="text-lg text-red-500">Hello world!</p>',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// userId: adminUser.id,
|
||||||
|
// path: "styles.css",
|
||||||
|
// filename: "styles.css",
|
||||||
|
// content: "body { padding: 16px; }",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// userId: adminUser.id,
|
||||||
|
// path: "script.js",
|
||||||
|
// filename: "script.js",
|
||||||
|
// content: "console.log('hello world!');",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// userId: adminUser.id,
|
||||||
|
// path: "_layout.html",
|
||||||
|
// filename: "_layout.html",
|
||||||
|
// content: `<!DOCTYPE html>
|
||||||
|
// <html lang="en">
|
||||||
|
// <head>
|
||||||
|
// <meta charset="UTF-8">
|
||||||
|
// <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
// <title>Document</title>
|
||||||
|
|
||||||
|
// <link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
|
// <script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
// </head>
|
||||||
|
// <body>
|
||||||
|
// {CONTENT}
|
||||||
|
// <script src="script.js" type="module" defer></script>
|
||||||
|
// </body>
|
||||||
|
// </html>`,
|
||||||
|
// },
|
||||||
|
// ])
|
||||||
|
// .execute();
|
||||||
|
|
||||||
|
// react template
|
||||||
await db
|
await db
|
||||||
.insert(file)
|
.insert(file)
|
||||||
.values([
|
.values([
|
||||||
@ -19,40 +65,69 @@ const main = async () => {
|
|||||||
userId: adminUser.id,
|
userId: adminUser.id,
|
||||||
path: "index.html",
|
path: "index.html",
|
||||||
filename: "index.html",
|
filename: "index.html",
|
||||||
content: '<p class="text-lg text-red-500">Hello world!</p>',
|
content: `<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0"
|
||||||
|
/>
|
||||||
|
<title>React + Tailwind Template</title>
|
||||||
|
<link rel="stylesheet" href="globals.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script src="index.jsx" type="module" defer></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
userId: adminUser.id,
|
userId: adminUser.id,
|
||||||
path: "styles.css",
|
path: "globals.css",
|
||||||
filename: "styles.css",
|
filename: "globals.css",
|
||||||
content: "body { padding: 16px; }",
|
content: `@tailwind base;
|
||||||
},
|
@tailwind components;
|
||||||
{
|
@tailwind utilities;
|
||||||
userId: adminUser.id,
|
|
||||||
path: "script.js",
|
|
||||||
filename: "script.js",
|
|
||||||
content: "console.log('hello world!');",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
userId: adminUser.id,
|
|
||||||
path: "_layout.html",
|
|
||||||
filename: "_layout.html",
|
|
||||||
content: `<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Document</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="styles.css">
|
body {
|
||||||
|
@apply p-4;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userId: adminUser.id,
|
||||||
|
path: "index.jsx",
|
||||||
|
filename: "index.jsx",
|
||||||
|
content: `import React from "react";
|
||||||
|
import { createRoot } from "react-dom/client";
|
||||||
|
import App from "./App.jsx";
|
||||||
|
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
const root = createRoot(document.getElementById("app"));
|
||||||
</head>
|
root.render(<App />);
|
||||||
<body>
|
`,
|
||||||
{CONTENT}
|
},
|
||||||
<script src="script.js" type="module" defer></script>
|
{
|
||||||
</body>
|
userId: adminUser.id,
|
||||||
</html>`,
|
path: "App.jsx",
|
||||||
|
filename: "App.jsx",
|
||||||
|
isPinned: true,
|
||||||
|
content: `import React from "react";
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 class="text-xl font-medium text-blue-500">
|
||||||
|
React + Tailwind Template!
|
||||||
|
</h1>
|
||||||
|
<p>Open App.jsx to edit this text.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
.execute();
|
.execute();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
import { renderPage } from "vike/server";
|
import { renderPage } from "vike/server";
|
||||||
import { IS_DEV } from "./lib/consts";
|
import { IS_DEV } from "./lib/consts";
|
||||||
|
import cookieParser from "cookie-parser";
|
||||||
import api from "./api";
|
import api from "./api";
|
||||||
|
|
||||||
async function createServer() {
|
async function createServer() {
|
||||||
@ -22,11 +23,13 @@ async function createServer() {
|
|||||||
app.use(express.static(root + "/dist/client"));
|
app.use(express.static(root + "/dist/client"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.use(cookieParser());
|
||||||
|
|
||||||
app.use("/api", api);
|
app.use("/api", api);
|
||||||
|
|
||||||
app.use("*", async (req, res, next) => {
|
app.use("*", async (req, res, next) => {
|
||||||
const url = req.originalUrl;
|
const url = req.originalUrl;
|
||||||
const pageContext = {};
|
const pageContext = { req, cookies: req.cookies };
|
||||||
const ctx = await renderPage({ urlOriginal: url, ...pageContext });
|
const ctx = await renderPage({ urlOriginal: url, ...pageContext });
|
||||||
|
|
||||||
const { httpResponse } = ctx;
|
const { httpResponse } = ctx;
|
||||||
|
11
server/lib/mime.ts
Normal file
11
server/lib/mime.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Mime } from "mime/lite";
|
||||||
|
import standardTypes from "mime/types/standard.js";
|
||||||
|
import otherTypes from "mime/types/other.js";
|
||||||
|
|
||||||
|
const mime = new Mime(standardTypes, otherTypes);
|
||||||
|
mime.define({ "text/javascript": ["jsx", "tsx"] }, true);
|
||||||
|
|
||||||
|
export const getMimeType = (
|
||||||
|
ext: string,
|
||||||
|
defaultMime: string = "application/octet-stream"
|
||||||
|
) => mime.getType(ext) || defaultMime;
|
50
server/lib/unpack-project.ts
Normal file
50
server/lib/unpack-project.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
import { and, eq, isNull } from "drizzle-orm";
|
||||||
|
import db from "../db";
|
||||||
|
import { file } from "../db/schema/file";
|
||||||
|
import { fileExists, getProjectDir } from "./utils";
|
||||||
|
import { getFileExt } from "~/lib/utils";
|
||||||
|
|
||||||
|
type UnpackProjectOptions = {
|
||||||
|
ext: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const unpackProject = async (
|
||||||
|
opt: Partial<UnpackProjectOptions> = {}
|
||||||
|
) => {
|
||||||
|
const files = await db.query.file.findMany({
|
||||||
|
where: and(
|
||||||
|
eq(file.isDirectory, false),
|
||||||
|
eq(file.isFile, false),
|
||||||
|
isNull(file.deletedAt)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const projectDir = getProjectDir();
|
||||||
|
if (!fileExists(projectDir)) {
|
||||||
|
await fs.mkdir(projectDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const ext = getFileExt(file.filename);
|
||||||
|
|
||||||
|
// skip file if not in included extension list
|
||||||
|
if (opt.ext && opt.ext.length > 0 && !opt.ext.split(",").includes(ext)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fpath = path.resolve(
|
||||||
|
projectDir,
|
||||||
|
file.path.replace(/(\.{2})(\/+)/g, "")
|
||||||
|
);
|
||||||
|
const dir = path.dirname(fpath);
|
||||||
|
if (!fileExists(dir)) {
|
||||||
|
await fs.mkdir(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(fpath, file.content || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectDir;
|
||||||
|
};
|
15
server/lib/utils.ts
Normal file
15
server/lib/utils.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
export const fileExists = (path: string) => {
|
||||||
|
try {
|
||||||
|
fs.accessSync(path, fs.constants.F_OK);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProjectDir = () => {
|
||||||
|
return path.resolve(process.cwd(), "storage/tmp/project1");
|
||||||
|
};
|
@ -21,7 +21,7 @@ const fileRouter = router({
|
|||||||
opt?.isPinned ? eq(file.isPinned, true) : undefined
|
opt?.isPinned ? eq(file.isPinned, true) : undefined
|
||||||
),
|
),
|
||||||
orderBy: [desc(file.isDirectory), asc(file.filename)],
|
orderBy: [desc(file.isDirectory), asc(file.filename)],
|
||||||
columns: { content: false },
|
columns: !file.isPinned ? { content: true } : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
|
@ -9,6 +9,11 @@ const config = {
|
|||||||
"~": path.resolve("./"),
|
"~": path.resolve("./"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
server: {
|
||||||
|
watch: {
|
||||||
|
ignored: [path.resolve(__dirname, "storage/**")],
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user