diff options
24 files changed, 157 insertions, 67 deletions
diff --git a/.eslintrc.js b/.eslintrc.js index bf32149f..75b50972 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,5 @@ module.exports = { + root: true, env: { browser: true, es2021: true, @@ -9,20 +10,23 @@ module.exports = { "plugin:react/recommended", "plugin:react-hooks/recommended", "plugin:@next/next/recommended", + "plugin:tailwindcss/recommended", + "plugin:@typescript-eslint/recommended", "next", "prettier", ], + plugins: ["tailwindcss", "@typescript-eslint"], parserOptions: { ecmaVersion: "latest", sourceType: "module", }, ignorePatterns: ["postcss.config.js"], rules: { - "no-redeclare": "off", "@next/next/no-html-link-for-pages": "off", - "no-undef": "off", - "react/jsx-no-undef": "off", - "no-unused-vars": [ + "tailwindcss/no-custom-classname": "off", + "tailwindcss/migration-from-tailwind-2": "off", + + "@typescript-eslint/no-unused-vars": [ "error", { varsIgnorePattern: "^_", @@ -30,4 +34,10 @@ module.exports = { }, ], }, + overrides: [ + { + files: ["*.ts", "*.tsx"], + parser: "@typescript-eslint/parser", + }, + ], }; diff --git a/.prettierrc b/.prettierrc index 0967ef42..b4bfed35 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1 +1,3 @@ -{} +{ + "plugins": ["prettier-plugin-tailwindcss"] +} @@ -1,7 +1,10 @@ MAKEFLAGS += --always-make format: - yarn prettier . --write && yarn exec 'eslint .' + yarn prettier . --write + +lint: + yarn eslint . prisma: cd packages/db; \ diff --git a/package.json b/package.json index 8df8a09d..3a17a8f7 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,10 @@ "es-errors": "^1.3.0", "eslint": "^8.56.0", "eslint-config-next": "14.1.0", + "eslint-plugin-tailwindcss": "^3.14.2", + "install": "^0.13.0", "prettier": "3.2.5", + "prettier-plugin-tailwindcss": "^0.5.11", "typescript": "^5" }, "packageManager": "yarn@4.1.0" diff --git a/packages/web/app/api/v1/bookmarks/route.ts b/packages/web/app/api/v1/bookmarks/route.ts index b9305ca8..a78535cc 100644 --- a/packages/web/app/api/v1/bookmarks/route.ts +++ b/packages/web/app/api/v1/bookmarks/route.ts @@ -29,7 +29,7 @@ export async function POST(request: NextRequest) { const bookmark = await bookmarkLink(linkRequest.data.url, session.user.id); - let response: ZBookmark = { ...bookmark }; + const response: ZBookmark = { ...bookmark }; return NextResponse.json(response, { status: 201 }); } @@ -42,6 +42,6 @@ export async function GET() { const bookmarks = await getBookmarks(session.user.id); - let response: ZGetBookmarksResponse = { bookmarks }; + const response: ZGetBookmarksResponse = { bookmarks }; return NextResponse.json(response); } diff --git a/packages/web/app/dashboard/bookmarks/components/AddLink.tsx b/packages/web/app/dashboard/bookmarks/components/AddLink.tsx index fb77786c..f99c1655 100644 --- a/packages/web/app/dashboard/bookmarks/components/AddLink.tsx +++ b/packages/web/app/dashboard/bookmarks/components/AddLink.tsx @@ -43,7 +43,7 @@ export default function AddLink() { return ( <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit, onError)}> - <div className="py-4 container flex w-full items-center space-x-2"> + <div className="container flex w-full items-center space-x-2 py-4"> <FormField control={form.control} name="url" diff --git a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx index 2b6b19b6..f52ef910 100644 --- a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx +++ b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx @@ -20,7 +20,7 @@ export default async function BookmarksGrid() { const bookmarks = await getBookmarks(session.user.id); return ( - <div className="container grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4"> + <div className="container grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4"> {bookmarks.map((b) => renderBookmark(b))} </div> ); diff --git a/packages/web/app/dashboard/bookmarks/components/LinkCard.tsx b/packages/web/app/dashboard/bookmarks/components/LinkCard.tsx index 1cbd8865..aeef6bae 100644 --- a/packages/web/app/dashboard/bookmarks/components/LinkCard.tsx +++ b/packages/web/app/dashboard/bookmarks/components/LinkCard.tsx @@ -26,7 +26,7 @@ export function LinkOptions({ linkId }: { linkId: string }) { const router = useRouter(); const unbookmarkLink = async () => { - let [_, error] = await APIClient.deleteBookmark(linkId); + const [_, error] = await APIClient.deleteBookmark(linkId); if (error) { toast({ @@ -51,7 +51,7 @@ export function LinkOptions({ linkId }: { linkId: string }) { </DropdownMenuTrigger> <DropdownMenuContent className="w-fit"> <DropdownMenuItem className="text-destructive" onClick={unbookmarkLink}> - <Trash2 className="mr-2 h-4 w-4" /> + <Trash2 className="mr-2 size-4" /> <span>Delete</span> </DropdownMenuItem> </DropdownMenuContent> @@ -66,7 +66,7 @@ export default function LinkCard({ bookmark }: { bookmark: ZBookmark }) { return ( <ImageCard className={ - "bg-gray-50 duration-300 ease-in border border-grey-100 hover:transition-all hover:border-blue-300" + "border-grey-100 border bg-gray-50 duration-300 ease-in hover:border-blue-300 hover:transition-all" } image={link?.imageUrl ?? undefined} > @@ -75,7 +75,7 @@ export default function LinkCard({ bookmark }: { bookmark: ZBookmark }) { {link?.title ?? parsedUrl.host} </Link> </ImageCardTitle> - <ImageCardBody className="py-2 overflow-clip"> + <ImageCardBody className="overflow-clip py-2"> {bookmark.tags.map((t) => ( <Badge variant="default" diff --git a/packages/web/app/dashboard/components/Sidebar.tsx b/packages/web/app/dashboard/components/Sidebar.tsx index f2ead71a..c2abe1e1 100644 --- a/packages/web/app/dashboard/components/Sidebar.tsx +++ b/packages/web/app/dashboard/components/Sidebar.tsx @@ -31,14 +31,14 @@ export default async function Sidebar() { } return ( - <aside className="flex flex-col h-full w-60 border-r p-4"> - <div className="flex px-1 mb-5 items-center rounded-lg text-slate-900"> + <aside className="flex h-full w-60 flex-col border-r p-4"> + <div className="mb-5 flex items-center rounded-lg px-1 text-slate-900"> <Brain /> <span className="ml-2 text-base font-semibold">Remember</span> </div> <hr /> <div> - <ul className="space-y-2 mt-5 text-sm font-medium"> + <ul className="mt-5 space-y-2 text-sm font-medium"> <SidebarItem logo={<Home />} name="Home" path="#" /> <SidebarItem logo={<Star />} name="Favourites" path="#" /> <SidebarItem logo={<Archive />} name="Archived" path="#" /> @@ -47,7 +47,7 @@ export default async function Sidebar() { </div> <div className="mt-auto flex justify-between"> <div className="my-auto"> {session.user.name} </div> - <Button variant="ghost" className="h-10 w-30"> + <Button variant="ghost" className="h-10"> <MoreHorizontal /> </Button> </div> diff --git a/packages/web/app/dashboard/layout.tsx b/packages/web/app/dashboard/layout.tsx index 9b21271e..220949c7 100644 --- a/packages/web/app/dashboard/layout.tsx +++ b/packages/web/app/dashboard/layout.tsx @@ -3,7 +3,7 @@ import Sidebar from "@/app/dashboard/components/Sidebar"; export default async function Dashboard() { return ( - <div className="flex w-screen h-screen"> + <div className="flex h-screen w-screen"> <div className="flex-none"> <Sidebar /> </div> diff --git a/packages/web/components/ui/badge.tsx b/packages/web/components/ui/badge.tsx index d3d5d604..c30daca1 100644 --- a/packages/web/components/ui/badge.tsx +++ b/packages/web/components/ui/badge.tsx @@ -4,16 +4,16 @@ import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; const badgeVariants = cva( - "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + "focus:ring-ring inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2", { variants: { variant: { default: - "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + "bg-primary text-primary-foreground hover:bg-primary/80 border-transparent", secondary: - "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + "bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent", destructive: - "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + "bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent", outline: "text-foreground", }, }, diff --git a/packages/web/components/ui/button.tsx b/packages/web/components/ui/button.tsx index 57c9fe47..79b45fa0 100644 --- a/packages/web/components/ui/button.tsx +++ b/packages/web/components/ui/button.tsx @@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + "ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { @@ -13,7 +13,7 @@ const buttonVariants = cva( destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: - "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + "border-input bg-background hover:bg-accent hover:text-accent-foreground border", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", @@ -23,7 +23,7 @@ const buttonVariants = cva( default: "h-10 px-4 py-2", sm: "h-9 rounded-md px-3", lg: "h-11 rounded-md px-8", - icon: "h-10 w-10", + icon: "size-10", }, }, defaultVariants: { diff --git a/packages/web/components/ui/card.tsx b/packages/web/components/ui/card.tsx index dc3b01de..f4e57996 100644 --- a/packages/web/components/ui/card.tsx +++ b/packages/web/components/ui/card.tsx @@ -9,7 +9,7 @@ const Card = React.forwardRef< <div ref={ref} className={cn( - "rounded-lg border bg-card text-card-foreground shadow-sm", + "bg-card text-card-foreground rounded-lg border shadow-sm", className, )} {...props} @@ -50,7 +50,7 @@ const CardDescription = React.forwardRef< >(({ className, ...props }, ref) => ( <p ref={ref} - className={cn("text-sm text-muted-foreground", className)} + className={cn("text-muted-foreground text-sm", className)} {...props} /> )); diff --git a/packages/web/components/ui/dropdown-menu.tsx b/packages/web/components/ui/dropdown-menu.tsx index 3a0c7fed..3a9a2ff7 100644 --- a/packages/web/components/ui/dropdown-menu.tsx +++ b/packages/web/components/ui/dropdown-menu.tsx @@ -27,14 +27,14 @@ const DropdownMenuSubTrigger = React.forwardRef< <DropdownMenuPrimitive.SubTrigger ref={ref} className={cn( - "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent", + "focus:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none", inset && "pl-8", className, )} {...props} > {children} - <ChevronRight className="ml-auto h-4 w-4" /> + <ChevronRight className="ml-auto size-4" /> </DropdownMenuPrimitive.SubTrigger> )); DropdownMenuSubTrigger.displayName = @@ -47,7 +47,7 @@ const DropdownMenuSubContent = React.forwardRef< <DropdownMenuPrimitive.SubContent ref={ref} className={cn( - "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg", className, )} {...props} @@ -65,7 +65,7 @@ const DropdownMenuContent = React.forwardRef< ref={ref} sideOffset={sideOffset} className={cn( - "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md", className, )} {...props} @@ -83,7 +83,7 @@ const DropdownMenuItem = React.forwardRef< <DropdownMenuPrimitive.Item ref={ref} className={cn( - "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", className, )} @@ -99,15 +99,15 @@ const DropdownMenuCheckboxItem = React.forwardRef< <DropdownMenuPrimitive.CheckboxItem ref={ref} className={cn( - "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className, )} checked={checked} {...props} > - <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> + <span className="absolute left-2 flex size-3.5 items-center justify-center"> <DropdownMenuPrimitive.ItemIndicator> - <Check className="h-4 w-4" /> + <Check className="size-4" /> </DropdownMenuPrimitive.ItemIndicator> </span> {children} @@ -123,14 +123,14 @@ const DropdownMenuRadioItem = React.forwardRef< <DropdownMenuPrimitive.RadioItem ref={ref} className={cn( - "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className, )} {...props} > - <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> + <span className="absolute left-2 flex size-3.5 items-center justify-center"> <DropdownMenuPrimitive.ItemIndicator> - <Circle className="h-2 w-2 fill-current" /> + <Circle className="size-2 fill-current" /> </DropdownMenuPrimitive.ItemIndicator> </span> {children} @@ -162,7 +162,7 @@ const DropdownMenuSeparator = React.forwardRef< >(({ className, ...props }, ref) => ( <DropdownMenuPrimitive.Separator ref={ref} - className={cn("-mx-1 my-1 h-px bg-muted", className)} + className={cn("bg-muted -mx-1 my-1 h-px", className)} {...props} /> )); diff --git a/packages/web/components/ui/form.tsx b/packages/web/components/ui/form.tsx index 497718a9..e62e10e9 100644 --- a/packages/web/components/ui/form.tsx +++ b/packages/web/components/ui/form.tsx @@ -134,7 +134,7 @@ const FormDescription = React.forwardRef< <p ref={ref} id={formDescriptionId} - className={cn("text-sm text-muted-foreground", className)} + className={cn("text-muted-foreground text-sm", className)} {...props} /> ); @@ -156,7 +156,7 @@ const FormMessage = React.forwardRef< <p ref={ref} id={formMessageId} - className={cn("text-sm font-medium text-destructive", className)} + className={cn("text-destructive text-sm font-medium", className)} {...props} > {body} diff --git a/packages/web/components/ui/imageCard.tsx b/packages/web/components/ui/imageCard.tsx index 1394ae08..dae7da3f 100644 --- a/packages/web/components/ui/imageCard.tsx +++ b/packages/web/components/ui/imageCard.tsx @@ -10,7 +10,7 @@ export function ImageCard({ }: React.HTMLAttributes<HTMLDivElement> & { image?: string }) { return ( <div - className={cn("h-96 rounded-lg overflow-hidden shadow-md", className)} + className={cn("h-96 overflow-hidden rounded-lg shadow-md", className)} {...props} > <div @@ -19,7 +19,7 @@ export function ImageCard({ backgroundImage: image ? `url(${image})` : undefined, }} ></div> - <div className="flex flex-col h-2/5 p-2">{children}</div> + <div className="flex h-2/5 flex-col p-2">{children}</div> </div> ); } @@ -30,7 +30,7 @@ export function ImageCardTitle({ }: React.HTMLAttributes<HTMLDivElement>) { return ( <div - className={cn("order-first flex-none font-bold text-lg", className)} + className={cn("order-first flex-none text-lg font-bold", className)} {...props} /> ); @@ -42,7 +42,7 @@ export function ImageCardBody({ }: React.HTMLAttributes<HTMLDivElement>) { return ( <div - className={cn("grow order-1 font-bold text-lg", className)} + className={cn("order-1 grow text-lg font-bold", className)} {...props} /> ); diff --git a/packages/web/components/ui/input.tsx b/packages/web/components/ui/input.tsx index 9d631e7f..21aac7ad 100644 --- a/packages/web/components/ui/input.tsx +++ b/packages/web/components/ui/input.tsx @@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>( <input type={type} className={cn( - "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", + "border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", className, )} ref={ref} diff --git a/packages/web/components/ui/toast.tsx b/packages/web/components/ui/toast.tsx index 2bc23c1f..0d162dca 100644 --- a/packages/web/components/ui/toast.tsx +++ b/packages/web/components/ui/toast.tsx @@ -23,13 +23,13 @@ const ToastViewport = React.forwardRef< ToastViewport.displayName = ToastPrimitives.Viewport.displayName; const toastVariants = cva( - "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", + "data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none", { variants: { variant: { - default: "border bg-background text-foreground", + default: "bg-background text-foreground border", destructive: - "destructive group border-destructive bg-destructive text-destructive-foreground", + "destructive border-destructive bg-destructive text-destructive-foreground group", }, }, defaultVariants: { @@ -60,7 +60,7 @@ const ToastAction = React.forwardRef< <ToastPrimitives.Action ref={ref} className={cn( - "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive", + "ring-offset-background hover:bg-secondary focus:ring-ring group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", className, )} {...props} @@ -75,13 +75,13 @@ const ToastClose = React.forwardRef< <ToastPrimitives.Close ref={ref} className={cn( - "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600", + "text-foreground/50 hover:text-foreground absolute right-2 top-2 rounded-md p-1 opacity-0 transition-opacity focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600", className, )} toast-close="" {...props} > - <X className="h-4 w-4" /> + <X className="size-4" /> </ToastPrimitives.Close> )); ToastClose.displayName = ToastPrimitives.Close.displayName; diff --git a/packages/web/lib/api.ts b/packages/web/lib/api.ts index 8ee08601..f7942310 100644 --- a/packages/web/lib/api.ts +++ b/packages/web/lib/api.ts @@ -39,7 +39,7 @@ async function doRequest<T>( return [undefined, undefined] as const; } - let parsed = respSchema.safeParse(await res.json()); + const parsed = respSchema.safeParse(await res.json()); if (!parsed.success) { return [ undefined, @@ -48,7 +48,7 @@ async function doRequest<T>( } return [parsed.data, undefined] as const; - } catch (error: any) { + } catch (error) { return [ undefined, { message: `Failed to execute fetch request: ${error}` }, diff --git a/packages/web/lib/auth.ts b/packages/web/lib/auth.ts index cd6404de..df98e6b8 100644 --- a/packages/web/lib/auth.ts +++ b/packages/web/lib/auth.ts @@ -4,7 +4,7 @@ import AuthentikProvider from "next-auth/providers/authentik"; import serverConfig from "@/lib/config"; import prisma from "@remember/db"; -let providers = []; +const providers = []; if (serverConfig.auth.authentik) { providers.push(AuthentikProvider(serverConfig.auth.authentik)); diff --git a/packages/web/lib/config.ts b/packages/web/lib/config.ts index ec042b54..dbf6620e 100644 --- a/packages/web/lib/config.ts +++ b/packages/web/lib/config.ts @@ -1,5 +1,5 @@ function buildAuthentikConfig() { - let { AUTHENTIK_ID, AUTHENTIK_SECRET, AUTHENTIK_ISSUER } = process.env; + const { AUTHENTIK_ID, AUTHENTIK_SECRET, AUTHENTIK_ISSUER } = process.env; if (!AUTHENTIK_ID || !AUTHENTIK_SECRET || !AUTHENTIK_ISSUER) { return undefined; diff --git a/packages/workers/crawler.ts b/packages/workers/crawler.ts index c76b2c42..d5479025 100644 --- a/packages/workers/crawler.ts +++ b/packages/workers/crawler.ts @@ -10,12 +10,18 @@ import prisma from "@remember/db"; import metascraper from "metascraper"; +import metascraperDescription from "metascraper-description"; +import metascraperImage from "metascraper-image"; +import metascraperLogo from "metascraper-logo-favicon"; +import metascraperTitle from "metascraper-title"; +import metascraperUrl from "metascraper-url"; + const metascraperParser = metascraper([ - require("metascraper-description")(), - require("metascraper-image")(), - require("metascraper-logo-favicon")(), - require("metascraper-title")(), - require("metascraper-url")(), + metascraperDescription(), + metascraperImage(), + metascraperLogo(), + metascraperTitle(), + metascraperUrl(), ]); export default async function runCrawler(job: Job<ZCrawlLinkRequest, void>) { diff --git a/packages/workers/openai.ts b/packages/workers/openai.ts index b6044dd3..a2f90c8a 100644 --- a/packages/workers/openai.ts +++ b/packages/workers/openai.ts @@ -46,7 +46,7 @@ async function inferTags(jobId: string, link: BookmarkedLink, openai: OpenAI) { response_format: { type: "json_object" }, }); - let response = chatCompletion.choices[0].message.content; + const response = chatCompletion.choices[0].message.content; if (!response) { throw new Error(`[openai][${jobId}] Got no message content from OpenAI`); } @@ -89,10 +89,10 @@ async function createTags(tags: string[], userId: string) { const existingTagSet = new Set<string>(existingTags.map((t) => t.name)); - let newTags = tags.filter((t) => !existingTagSet.has(t)); + const newTags = tags.filter((t) => !existingTagSet.has(t)); // TODO: Prisma doesn't support createMany in Sqlite - let newTagObjects = await Promise.all( + const newTagObjects = await Promise.all( newTags.map((t) => { return prisma.bookmarkTags.create({ data: { @@ -2931,6 +2931,18 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-tailwindcss@npm:^3.14.2": + version: 3.14.2 + resolution: "eslint-plugin-tailwindcss@npm:3.14.2" + dependencies: + fast-glob: "npm:^3.2.5" + postcss: "npm:^8.4.4" + peerDependencies: + tailwindcss: ^3.4.0 + checksum: 10c0/fbe7d12ff7696b281f7ef5810c49ef276dbc115205437ae0e2a16fa607e7da15029127a8ab855b1616cb58308ed16b812ead2fecd3fa28770b0f6feadbe27cd6 + languageName: node + linkType: hard + "eslint-scope@npm:^7.2.2": version: 7.2.2 resolution: "eslint-scope@npm:7.2.2" @@ -3060,7 +3072,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1": +"fast-glob@npm:^3.2.5, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" dependencies: @@ -5389,7 +5401,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8, postcss@npm:^8.4.23": +"postcss@npm:^8, postcss@npm:^8.4.23, postcss@npm:^8.4.4": version: 8.4.35 resolution: "postcss@npm:8.4.35" dependencies: @@ -5425,6 +5437,57 @@ __metadata: languageName: node linkType: hard +"prettier-plugin-tailwindcss@npm:^0.5.11": + version: 0.5.11 + resolution: "prettier-plugin-tailwindcss@npm:0.5.11" + peerDependencies: + "@ianvs/prettier-plugin-sort-imports": "*" + "@prettier/plugin-pug": "*" + "@shopify/prettier-plugin-liquid": "*" + "@trivago/prettier-plugin-sort-imports": "*" + prettier: ^3.0 + prettier-plugin-astro: "*" + prettier-plugin-css-order: "*" + prettier-plugin-import-sort: "*" + prettier-plugin-jsdoc: "*" + prettier-plugin-marko: "*" + prettier-plugin-organize-attributes: "*" + prettier-plugin-organize-imports: "*" + prettier-plugin-style-order: "*" + prettier-plugin-svelte: "*" + peerDependenciesMeta: + "@ianvs/prettier-plugin-sort-imports": + optional: true + "@prettier/plugin-pug": + optional: true + "@shopify/prettier-plugin-liquid": + optional: true + "@trivago/prettier-plugin-sort-imports": + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-import-sort: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-marko: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-style-order: + optional: true + prettier-plugin-svelte: + optional: true + prettier-plugin-twig-melody: + optional: true + checksum: 10c0/46e095d2a4298820a75a7b36022e8f2bcd1658a289f2ab11e4b9d4b6075272fee003d9959d084dcb33d5d669daf275e978d9a9aed35efe5eb9e77e70070b47f6 + languageName: node + linkType: hard + "prettier@npm:3.2.5, prettier@npm:^3.2.5": version: 3.2.5 resolution: "prettier@npm:3.2.5" @@ -5736,7 +5799,10 @@ __metadata: eslint-config-prettier: "npm:^9.1.0" eslint-plugin-react: "npm:^7.33.2" eslint-plugin-react-hooks: "npm:^4.6.0" + eslint-plugin-tailwindcss: "npm:^3.14.2" + install: "npm:^0.13.0" prettier: "npm:3.2.5" + prettier-plugin-tailwindcss: "npm:^0.5.11" typescript: "npm:^5" languageName: unknown linkType: soft |
