From 3f0212c5c6a63d3a4a096fff31ffdb719c9816e2 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 03:28:06 -0700 Subject: [PATCH 1/8] begin work on protected posts --- client/components/header/controls.tsx | 2 +- client/components/new-post/index.tsx | 94 ++++++++++++------- client/components/new-post/password/index.tsx | 50 ++++++++++ client/components/visibility-badge/index.tsx | 3 +- client/lib/types.d.ts | 12 +++ client/pages/_app.tsx | 6 +- client/pages/index.tsx | 2 +- client/pages/new.tsx | 4 +- client/pages/post/[id].tsx | 2 +- client/pages/signin.tsx | 2 +- client/pages/signup.tsx | 2 +- server/lib/models/Post.ts | 3 + server/src/routes/posts.ts | 2 - server/src/server.ts | 2 +- 14 files changed, 136 insertions(+), 50 deletions(-) create mode 100644 client/components/new-post/password/index.tsx create mode 100644 client/lib/types.d.ts diff --git a/client/components/header/controls.tsx b/client/components/header/controls.tsx index f621c806..ee763129 100644 --- a/client/components/header/controls.tsx +++ b/client/components/header/controls.tsx @@ -2,9 +2,9 @@ import React from 'react' import MoonIcon from '@geist-ui/icons/moon' import SunIcon from '@geist-ui/icons/sun' import { Select } from '@geist-ui/core' -import { ThemeProps } from '../../pages/_app' // import { useAllThemes, useTheme } from '@geist-ui/core' import styles from './header.module.css' +import { ThemeProps } from '@lib/types' const Controls = ({ changeTheme, theme }: ThemeProps) => { const switchThemes = (type: string | string[]) => { diff --git a/client/components/new-post/index.tsx b/client/components/new-post/index.tsx index 65b9f5a1..6b401b4d 100644 --- a/client/components/new-post/index.tsx +++ b/client/components/new-post/index.tsx @@ -1,29 +1,56 @@ -import { Button, ButtonDropdown, useToasts } from '@geist-ui/core' +import { Button, ButtonDropdown, Input, Modal, Note, useModal, useToasts } from '@geist-ui/core' import { useRouter } from 'next/router'; import { useCallback, useState } from 'react' import generateUUID from '@lib/generate-uuid'; -import Document from '../document'; +import DocumentComponent from '../document'; import FileDropzone from './drag-and-drop'; import styles from './post.module.css' import Title from './title'; import Cookies from 'js-cookie' - -export type Document = { - title: string - content: string - id: string -} +import type { PostVisibility, Document as DocumentType } from '@lib/types'; +import PasswordModal from './password'; const Post = () => { const { setToast } = useToasts() - const router = useRouter(); const [title, setTitle] = useState() - const [docs, setDocs] = useState([{ + const [docs, setDocs] = useState([{ title: '', content: '', id: generateUUID() }]) + const [passwordModalVisible, setPasswordModalVisible] = useState(false) + const sendRequest = useCallback(async (url: string, data: { visibility?: PostVisibility, title?: string, files?: DocumentType[], password?: string, userId: string }) => { + const res = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${Cookies.get('drift-token')}` + }, + body: JSON.stringify({ + title, + files: docs, + ...data, + }) + }) + + if (res.ok) { + const json = await res.json() + router.push(`/post/${json.id}`) + } else { + const json = await res.json() + setToast({ + text: json.message, + type: 'error' + }) + } + + }, [docs, router, setToast, title]) + + const closePasswordModel = () => { + setPasswordModalVisible(false) + setSubmitting(false) + } const [isSubmitting, setSubmitting] = useState(false) @@ -31,29 +58,30 @@ const Post = () => { setDocs(docs.filter((doc) => doc.id !== id)) } - const onSubmit = async (visibility: string) => { + const onSubmit = async (visibility: PostVisibility, password?: string) => { setSubmitting(true) - const response = await fetch('/server-api/posts/create', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${Cookies.get("drift-token")}` - }, - body: JSON.stringify({ - title, - files: docs, - visibility, - userId: Cookies.get("drift-userid"), - }) + + if (visibility === 'protected' && !password) { + setPasswordModalVisible(true) + return + } + + await sendRequest('/server-api/posts/create', { + title, + files: docs, + visibility, + password, + userId: Cookies.get('drift-userid') || '' }) - const json = await response.json() + + + setSubmitting(false) + } + + const onClosePasswordModal = () => { + setPasswordModalVisible(false) setSubmitting(false) - if (json.id) - router.push(`/post/${json.id}`) - else { - setToast({ text: json.error.message, type: "error" }) - } } const updateTitle = useCallback((title: string, id: string) => { @@ -64,7 +92,7 @@ const Post = () => { setDocs(docs.map((doc) => doc.id === id ? { ...doc, content } : doc)) }, [docs]) - const uploadDocs = useCallback((files: Document[]) => { + const uploadDocs = useCallback((files: DocumentType[]) => { // if no title is set and the only document is empty, const isFirstDocEmpty = docs.length === 1 && docs[0].title === '' && docs[0].content === '' const shouldSetTitle = !title && isFirstDocEmpty @@ -87,7 +115,7 @@ const Post = () => { { docs.map(({ content, id, title }) => { return ( - remove(id)} key={id} editable={true} @@ -120,10 +148,12 @@ const Post = () => { onSubmit('private')}>Create Private onSubmit('public')} >Create Public onSubmit('unlisted')} >Create Unlisted + onSubmit('protected')} >Create with Password + onSubmit('protected', password)} /> ) } -export default Post \ No newline at end of file +export default Post diff --git a/client/components/new-post/password/index.tsx b/client/components/new-post/password/index.tsx new file mode 100644 index 00000000..2305e945 --- /dev/null +++ b/client/components/new-post/password/index.tsx @@ -0,0 +1,50 @@ +import { Input, Modal, Note, Spacer } from "@geist-ui/core" +import { useState } from "react" + +type Props = { + isOpen: boolean + onClose: () => void + onSubmit: (password: string) => void +} + +const PasswordModal = ({ isOpen, onClose, onSubmit: onSubmitAfterVerify }: Props) => { + const [password, setPassword] = useState() + const [confirmPassword, setConfirmPassword] = useState() + const [error, setError] = useState() + + const onSubmit = () => { + if (!password || !confirmPassword) { + setError('Please enter a password') + return + } + + if (password !== confirmPassword) { + setError("Passwords do not match") + return + } + + onSubmitAfterVerify(password) + } + + return (<> + { + Enter a password + + {!error && + This doesn't protect your post from the server administrator. + } + {error && + {error} + } + + setPassword(e.target.value)} /> + setConfirmPassword(e.target.value)} /> + + Cancel + Submit + } + ) +} + + +export default PasswordModal \ No newline at end of file diff --git a/client/components/visibility-badge/index.tsx b/client/components/visibility-badge/index.tsx index 0e9fa908..fa0dfb22 100644 --- a/client/components/visibility-badge/index.tsx +++ b/client/components/visibility-badge/index.tsx @@ -1,6 +1,5 @@ import { Badge } from "@geist-ui/core" - -type Visibility = "unlisted" | "private" | "public" +import { Visibility } from "@lib/types" type Props = { visibility: Visibility diff --git a/client/lib/types.d.ts b/client/lib/types.d.ts new file mode 100644 index 00000000..c10b748a --- /dev/null +++ b/client/lib/types.d.ts @@ -0,0 +1,12 @@ +export type PostVisibility = "unlisted" | "private" | "public" | "protected" + +export type ThemeProps = { + theme: "light" | "dark" | string, + changeTheme: () => void +} + +export type Document = { + title: string + content: string + id: string +} diff --git a/client/pages/_app.tsx b/client/pages/_app.tsx index 91888263..f0292219 100644 --- a/client/pages/_app.tsx +++ b/client/pages/_app.tsx @@ -7,11 +7,7 @@ import useSharedState from '@lib/hooks/use-shared-state'; import 'react-loading-skeleton/dist/skeleton.css' import { SkeletonTheme } from 'react-loading-skeleton'; import Head from 'next/head'; - -export type ThemeProps = { - theme: "light" | "dark" | string, - changeTheme: () => void -} +import { ThemeProps } from '@lib/types'; type AppProps

= { pageProps: P; diff --git a/client/pages/index.tsx b/client/pages/index.tsx index 771d175b..c8303d83 100644 --- a/client/pages/index.tsx +++ b/client/pages/index.tsx @@ -2,11 +2,11 @@ import styles from '@styles/Home.module.css' import { Page, Spacer, Text } from '@geist-ui/core' import Header from '@components/header' -import { ThemeProps } from './_app' import Document from '@components/document' import Image from 'next/image' import ShiftBy from '@components/shift-by' import PageSeo from '@components/page-seo' +import { ThemeProps } from '@lib/types' export function getStaticProps() { const introDoc = process.env.WELCOME_CONTENT diff --git a/client/pages/new.tsx b/client/pages/new.tsx index b8966fc6..7a6f5948 100644 --- a/client/pages/new.tsx +++ b/client/pages/new.tsx @@ -3,12 +3,10 @@ import NewPost from '@components/new-post' import { Page } from '@geist-ui/core' import useSignedIn from '@lib/hooks/use-signed-in' import Header from '@components/header' -import { ThemeProps } from './_app' -import { useRouter } from 'next/router' import PageSeo from '@components/page-seo' +import { ThemeProps } from '@lib/types' const New = ({ theme, changeTheme }: ThemeProps) => { - const router = useRouter() const isSignedIn = useSignedIn() return ( diff --git a/client/pages/post/[id].tsx b/client/pages/post/[id].tsx index 0bd32738..b4f6da19 100644 --- a/client/pages/post/[id].tsx +++ b/client/pages/post/[id].tsx @@ -6,10 +6,10 @@ import { useEffect, useState } from "react"; import Document from '../../components/document' import Header from "../../components/header"; import VisibilityBadge from "../../components/visibility-badge"; -import { ThemeProps } from "../_app"; import PageSeo from "components/page-seo"; import styles from './styles.module.css'; import Cookies from "js-cookie"; +import { ThemeProps } from "@lib/types"; const Post = ({ theme, changeTheme }: ThemeProps) => { const [post, setPost] = useState() diff --git a/client/pages/signin.tsx b/client/pages/signin.tsx index defc7d5b..0b98aabc 100644 --- a/client/pages/signin.tsx +++ b/client/pages/signin.tsx @@ -2,7 +2,7 @@ import { Page } from "@geist-ui/core"; import PageSeo from "@components/page-seo"; import Auth from "@components/auth"; import Header from "@components/header"; -import { ThemeProps } from "./_app"; +import { ThemeProps } from "@lib/types"; const SignIn = ({ theme, changeTheme }: ThemeProps) => ( diff --git a/client/pages/signup.tsx b/client/pages/signup.tsx index 3628ef6d..9aa7b734 100644 --- a/client/pages/signup.tsx +++ b/client/pages/signup.tsx @@ -2,7 +2,7 @@ import { Page } from "@geist-ui/core"; import Auth from "@components/auth"; import Header from "@components/header"; import PageSeo from '@components/page-seo'; -import { ThemeProps } from "./_app"; +import { ThemeProps } from "@lib/types"; const SignUp = ({ theme, changeTheme }: ThemeProps) => ( diff --git a/server/lib/models/Post.ts b/server/lib/models/Post.ts index 7dab48dd..4bc6dc4b 100644 --- a/server/lib/models/Post.ts +++ b/server/lib/models/Post.ts @@ -48,6 +48,9 @@ export class Post extends Model { @Column visibility!: string; + @Column + password?: string; + @UpdatedAt @Column updatedAt!: Date; diff --git a/server/src/routes/posts.ts b/server/src/routes/posts.ts index a528f310..6456458e 100644 --- a/server/src/routes/posts.ts +++ b/server/src/routes/posts.ts @@ -26,7 +26,6 @@ posts.post('/create', jwt, async (req, res, next) => { throw new Error("Please provide a visibility.") } - // Create the "post" object const newPost = new Post({ title: req.body.title, visibility: req.body.visibility, @@ -35,7 +34,6 @@ posts.post('/create', jwt, async (req, res, next) => { await newPost.save() await newPost.$add('users', req.body.userId); const newFiles = await Promise.all(req.body.files.map(async (file) => { - // Establish a "file" for each file in the request const newFile = new File({ title: file.title, content: file.content, diff --git a/server/src/server.ts b/server/src/server.ts index 2e96ea8d..134ad9af 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -4,7 +4,7 @@ import config from '../lib/config'; import { sequelize } from '../lib/sequelize'; (async () => { - await sequelize.sync(); + await sequelize.sync({ force: true }); createServer(app) .listen( config.port, From dc64972188344e1f62a5d9f01ba3da1784d58100 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 12:45:35 -0700 Subject: [PATCH 2/8] client: tsconfig and next settings --- client/next.config.js | 1 + client/package.json | 3 +- client/pages/_middleware.tsx | 2 +- client/pages/post/[id].tsx | 2 +- client/tsconfig.json | 12 +- client/yarn.lock | 248 ++++++++++++++++++++++++----------- 6 files changed, 191 insertions(+), 77 deletions(-) diff --git a/client/next.config.js b/client/next.config.js index 16eb5923..316e44b2 100644 --- a/client/next.config.js +++ b/client/next.config.js @@ -6,6 +6,7 @@ const nextConfig = { reactStrictMode: true, experimental: { outputStandalone: true, + optimizeCss: true, }, async rewrites() { return [ diff --git a/client/package.json b/client/package.json index 0a61aa98..62c01622 100644 --- a/client/package.json +++ b/client/package.json @@ -15,9 +15,10 @@ "@types/js-cookie": "^3.0.1", "client-zip": "^2.0.0", "comlink": "^4.3.1", + "critters": "^0.0.16", "dotenv": "^16.0.0", "js-cookie": "^3.0.1", - "next": "12.1.0", + "next": "^12.1.1-canary.15", "prismjs": "^1.27.0", "react": "17.0.2", "react-debounce-render": "^8.0.2", diff --git a/client/pages/_middleware.tsx b/client/pages/_middleware.tsx index e31452e4..a6c34478 100644 --- a/client/pages/_middleware.tsx +++ b/client/pages/_middleware.tsx @@ -2,7 +2,7 @@ import { NextFetchEvent, NextRequest, NextResponse } from 'next/server' const PUBLIC_FILE = /.(.*)$/ -export function middleware(req: NextRequest, ev: NextFetchEvent) { +export function middleware(req: NextRequest) { const pathname = req.nextUrl.pathname const signedIn = req.cookies['drift-token'] const getURL = (pageName: string) => new URL(`/${pageName}`, req.url).href diff --git a/client/pages/post/[id].tsx b/client/pages/post/[id].tsx index b4f6da19..0bd32738 100644 --- a/client/pages/post/[id].tsx +++ b/client/pages/post/[id].tsx @@ -6,10 +6,10 @@ import { useEffect, useState } from "react"; import Document from '../../components/document' import Header from "../../components/header"; import VisibilityBadge from "../../components/visibility-badge"; +import { ThemeProps } from "../_app"; import PageSeo from "components/page-seo"; import styles from './styles.module.css'; import Cookies from "js-cookie"; -import { ThemeProps } from "@lib/types"; const Post = ({ theme, changeTheme }: ThemeProps) => { const [post, setPost] = useState() diff --git a/client/tsconfig.json b/client/tsconfig.json index 759858c9..768f8569 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,15 +1,25 @@ { "compilerOptions": { - "target": "es5", + "target": "es2020", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", + "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", diff --git a/client/yarn.lock b/client/yarn.lock index 5c3bd26b..668b5ec7 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -68,10 +68,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== -"@next/env@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.0.tgz#73713399399b34aa5a01771fb73272b55b22c314" - integrity sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ== +"@next/env@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.1-canary.15.tgz#d1c210df31c8865042f2b81ffb37660b9cc70045" + integrity sha512-2r7r5r/+hSgCTeGTMErGwlxiawNX3RGCKrgWGyyIYKGcJ2xunxN3ScDKIAjGa77eOWGm4JccB4T6xXwmPUut5g== "@next/eslint-plugin-next@12.1.0": version "12.1.0" @@ -80,60 +80,65 @@ dependencies: glob "7.1.7" -"@next/swc-android-arm64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.0.tgz#865ba3a9afc204ff2bdeea49dd64d58705007a39" - integrity sha512-/280MLdZe0W03stA69iL+v6I+J1ascrQ6FrXBlXGCsGzrfMaGr7fskMa0T5AhQIVQD4nA/46QQWxG//DYuFBcA== +"@next/swc-android-arm-eabi@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.1-canary.15.tgz#4539e24cc64fe8f76ce48c7e37c4419f9f436566" + integrity sha512-I1ghAtx23GcVi7modLdXLZZgfngcLzgzx/mWVXhWa2Pl8NPippIDMNF10Kf75RnOgkrPAEbVJByXAAEY7OkG6g== -"@next/swc-darwin-arm64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.0.tgz#08e8b411b8accd095009ed12efbc2f1d4d547135" - integrity sha512-R8vcXE2/iONJ1Unf5Ptqjk6LRW3bggH+8drNkkzH4FLEQkHtELhvcmJwkXcuipyQCsIakldAXhRbZmm3YN1vXg== +"@next/swc-android-arm64@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.1-canary.15.tgz#929ca296b7bfb7fdac77645d53199792d631048f" + integrity sha512-qa8M33AUfCW+P8NqGYd77+qhcM+QAP/KD7DBzCoIB08Djf/IQ3xBshM8dvCgWTYYz1ydnlHbMmJk+xiApoEfbQ== -"@next/swc-darwin-x64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.0.tgz#fcd684497a76e8feaca88db3c394480ff0b007cd" - integrity sha512-ieAz0/J0PhmbZBB8+EA/JGdhRHBogF8BWaeqR7hwveb6SYEIJaDNQy0I+ZN8gF8hLj63bEDxJAs/cEhdnTq+ug== +"@next/swc-darwin-arm64@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.1-canary.15.tgz#99764be54f9f9ba9866de18bc23f0fcfc98ac217" + integrity sha512-9L8X49wug00GpM4iIakq1MmsXKvWykwYjQRt++brGA4/rCJlG6WUiM4WDBQr2QqLCTMrfbd5umQ3qbL0F23VkQ== -"@next/swc-linux-arm-gnueabihf@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.0.tgz#9ec6380a27938a5799aaa6035c205b3c478468a7" - integrity sha512-njUd9hpl6o6A5d08dC0cKAgXKCzm5fFtgGe6i0eko8IAdtAPbtHxtpre3VeSxdZvuGFh+hb0REySQP9T1ttkog== +"@next/swc-darwin-x64@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.1-canary.15.tgz#4bdda400c5e542ff3355078a175fa6f74a20e39d" + integrity sha512-SMldDPyrN1GVqLYcXEUs7rwxbRP7ra8OxmRre3MJcUq1TB+mVkasNCDCO6WX1pJ9vDxu5Z5WuiBlp8bioCCp1w== -"@next/swc-linux-arm64-gnu@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.0.tgz#7f4196dff1049cea479607c75b81033ae2dbd093" - integrity sha512-OqangJLkRxVxMhDtcb7Qn1xjzFA3s50EIxY7mljbSCLybU+sByPaWAHY4px97ieOlr2y4S0xdPKkQ3BCAwyo6Q== +"@next/swc-linux-arm-gnueabihf@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.1-canary.15.tgz#f066f295cefe4206093614e2db292ef435ff7734" + integrity sha512-f8YBO686RvqfjIc8gv9gRJFPOSLEdtuJ1Q8FassJ2Jy4GMZdCGJaVFbcavsnd1ksw/KVxC79GaVigSVRmmgArA== -"@next/swc-linux-arm64-musl@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.0.tgz#b445f767569cdc2dddee785ca495e1a88c025566" - integrity sha512-hB8cLSt4GdmOpcwRe2UzI5UWn6HHO/vLkr5OTuNvCJ5xGDwpPXelVkYW/0+C3g5axbDW2Tym4S+MQCkkH9QfWA== +"@next/swc-linux-arm64-gnu@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.1-canary.15.tgz#a176237eedbdf8895c254f207d7e39a64b29c6b2" + integrity sha512-2J8LWInvvm7iNlx/mmH+BqUwLQndHKaFxgoLPqpVnn3XaIsHgSl+d9jU0ECJrp9OtzVgFmFgJYIfRMq9dNRDFw== -"@next/swc-linux-x64-gnu@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz#67610e9be4fbc987de7535f1bcb17e45fe12f90e" - integrity sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A== +"@next/swc-linux-arm64-musl@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.1-canary.15.tgz#235e44bf445e3e2b9dd01e757396520e7f57addf" + integrity sha512-SGEuapk5eheIsCE9tdLL5hxomUSQvETT9KCss8/x/+44009iBXsuKFP6DdF+0GFJzv/rpO+6ijPfnwQnvzTxeQ== -"@next/swc-linux-x64-musl@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz#ea19a23db08a9f2e34ac30401f774cf7d1669d31" - integrity sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw== +"@next/swc-linux-x64-gnu@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.1-canary.15.tgz#a89ca271a575335b6ed385d718792409ae85783c" + integrity sha512-9cgczb1Mr1BNZBxH5a02ermKGLihpBlp1ZVeIYwSGv+WFGCBIirIbZfvWDXpLG2fdA1YbPk1122o2h8ItVLlJw== -"@next/swc-win32-arm64-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.0.tgz#eadf054fc412085659b98e145435bbba200b5283" - integrity sha512-T/3gIE6QEfKIJ4dmJk75v9hhNiYZhQYAoYm4iVo1TgcsuaKLFa+zMPh4056AHiG6n9tn2UQ1CFE8EoybEsqsSw== +"@next/swc-linux-x64-musl@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.1-canary.15.tgz#b8ee5f2cbefedd305da286a2d10633656b85092a" + integrity sha512-nCqi/WVjp0PwQLBE7QPe4wNm6Hontuwh5p8ZIOmiSIGkxvbHdPbXWomKQFCwm2387B1OLGzv9VFJ0cBcfEbjWA== -"@next/swc-win32-ia32-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.0.tgz#68faeae10c89f698bf9d28759172b74c9c21bda1" - integrity sha512-iwnKgHJdqhIW19H9PRPM9j55V6RdcOo6rX+5imx832BCWzkDbyomWnlzBfr6ByUYfhohb8QuH4hSGEikpPqI0Q== +"@next/swc-win32-arm64-msvc@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.1-canary.15.tgz#094dab65bba62d516077539e7fc8edf6dd57ebc2" + integrity sha512-HO7Pcgky002h7xyjFdwbondKUXbDdxDcPQqxH4hUYg3umZr9dW2fTwKh6BTFDODeb9PtST+KaW4erFJPzRPYJw== -"@next/swc-win32-x64-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064" - integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg== +"@next/swc-win32-ia32-msvc@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.1-canary.15.tgz#2015910672229c11b11e3f10941fcee7c3dd2e10" + integrity sha512-llK5rpggUbe2OseHRQ32q8EjQHk8remoKrqlbXTJrEz9Fa6BNx8uI/IAT6tr9oX6VgTBeIFu1kX20yXJFxsL3Q== + +"@next/swc-win32-x64-msvc@12.1.1-canary.15": + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.1-canary.15.tgz#d1b08175419161cc0e4435333f5f7ca3b617708f" + integrity sha512-VcbXco9q82qHqBebHfPZqAgfs6OLek7EJJt28/OaSBnCJGzCl0hkWo3NkHEI4SQwYzTAgMufU3a9WjkEz3Oeew== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -409,6 +414,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -447,7 +457,7 @@ ccount@^2.0.0: resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -542,6 +552,18 @@ core-js@^2.4.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== +critters@^0.0.16: + version "0.0.16" + resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93" + integrity sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A== + dependencies: + chalk "^4.1.0" + css-select "^4.2.0" + parse5 "^6.0.1" + parse5-htmlparser2-tree-adapter "^6.0.1" + postcss "^8.3.7" + pretty-bytes "^5.3.0" + cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -551,6 +573,22 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +css-select@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" + integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== + dependencies: + boolbase "^1.0.0" + css-what "^5.1.0" + domhandler "^4.3.0" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-what@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" + integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== + csstype@^3.0.2: version "3.0.11" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" @@ -640,6 +678,36 @@ dom-helpers@^5.1.3: "@babel/runtime" "^7.8.7" csstype "^3.0.2" +dom-serializer@^1.0.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" + integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== + +domhandler@^4.2.0, domhandler@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + dotenv@^16.0.0: version "16.0.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" @@ -650,6 +718,11 @@ emoji-regex@^9.2.0, emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + es-abstract@^1.19.0, es-abstract@^1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" @@ -2047,7 +2120,7 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nanoid@^3.1.30: +nanoid@^3.1.30, nanoid@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== @@ -2057,28 +2130,36 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -next@12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/next/-/next-12.1.0.tgz#c33d753b644be92fc58e06e5a214f143da61dd5d" - integrity sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q== +next@^12.1.1-canary.15: + version "12.1.1-canary.15" + resolved "https://registry.yarnpkg.com/next/-/next-12.1.1-canary.15.tgz#a31c99a512b29d98aa0f6d837931d5c7f2aa2c35" + integrity sha512-WjD8zIDkLTiGYdnLbmeLmoNZvf7+UZ6oNxDDDNtddUVvej11AB8d+FmcmEuK7L3P8+5HKp1nZEg6oMxmpX/BzQ== dependencies: - "@next/env" "12.1.0" + "@next/env" "12.1.1-canary.15" caniuse-lite "^1.0.30001283" postcss "8.4.5" - styled-jsx "5.0.0" + styled-jsx "5.0.1" use-subscription "1.5.1" optionalDependencies: - "@next/swc-android-arm64" "12.1.0" - "@next/swc-darwin-arm64" "12.1.0" - "@next/swc-darwin-x64" "12.1.0" - "@next/swc-linux-arm-gnueabihf" "12.1.0" - "@next/swc-linux-arm64-gnu" "12.1.0" - "@next/swc-linux-arm64-musl" "12.1.0" - "@next/swc-linux-x64-gnu" "12.1.0" - "@next/swc-linux-x64-musl" "12.1.0" - "@next/swc-win32-arm64-msvc" "12.1.0" - "@next/swc-win32-ia32-msvc" "12.1.0" - "@next/swc-win32-x64-msvc" "12.1.0" + "@next/swc-android-arm-eabi" "12.1.1-canary.15" + "@next/swc-android-arm64" "12.1.1-canary.15" + "@next/swc-darwin-arm64" "12.1.1-canary.15" + "@next/swc-darwin-x64" "12.1.1-canary.15" + "@next/swc-linux-arm-gnueabihf" "12.1.1-canary.15" + "@next/swc-linux-arm64-gnu" "12.1.1-canary.15" + "@next/swc-linux-arm64-musl" "12.1.1-canary.15" + "@next/swc-linux-x64-gnu" "12.1.1-canary.15" + "@next/swc-linux-x64-musl" "12.1.1-canary.15" + "@next/swc-win32-arm64-msvc" "12.1.1-canary.15" + "@next/swc-win32-ia32-msvc" "12.1.1-canary.15" + "@next/swc-win32-x64-msvc" "12.1.1-canary.15" + +nth-check@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" + integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== + dependencies: + boolbase "^1.0.0" object-assign@^4.1.1: version "4.1.1" @@ -2197,7 +2278,14 @@ parse-entities@^2.0.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse5@^6.0.0: +parse5-htmlparser2-tree-adapter@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== + dependencies: + parse5 "^6.0.1" + +parse5@^6.0.0, parse5@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== @@ -2246,11 +2334,25 @@ postcss@8.4.5: picocolors "^1.0.0" source-map-js "^1.0.1" +postcss@^8.3.7: + version "8.4.12" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905" + integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg== + dependencies: + nanoid "^3.3.1" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +pretty-bytes@^5.3.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + prismjs@^1.25.0, prismjs@^1.27.0, prismjs@~1.27.0: version "1.27.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" @@ -2625,7 +2727,7 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-js@^1.0.1: +source-map-js@^1.0.1, source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== @@ -2702,10 +2804,10 @@ style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -styled-jsx@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77" - integrity sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA== +styled-jsx@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.1.tgz#78fecbbad2bf95ce6cd981a08918ce4696f5fc80" + integrity sha512-+PIZ/6Uk40mphiQJJI1202b+/dYeTVd9ZnMPR80pgiWbjIwvN2zIp4r9et0BgqBuShh48I0gttPlAXA7WVvBxw== supports-color@^7.1.0: version "7.2.0" From 1c68aa9765422c4214625236803addd1ee4cf17d Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 14:20:20 -0700 Subject: [PATCH 3/8] client: use cookie for theme, redirect post view in server side props --- .../document/formatting-icons/index.tsx | 10 +- client/components/header/controls.tsx | 4 +- .../new-post/drag-and-drop/index.tsx | 9 +- client/components/new-post/index.tsx | 2 +- client/components/new-post/title/index.tsx | 2 +- client/components/visibility-badge/index.tsx | 4 +- client/next.config.js | 1 - client/package.json | 8 +- client/pages/_app.tsx | 14 +- client/pages/post/[id].tsx | 145 ++-- client/tsconfig.json | 1 + client/yarn.lock | 677 ++++++++++++++---- 12 files changed, 641 insertions(+), 236 deletions(-) diff --git a/client/components/document/formatting-icons/index.tsx b/client/components/document/formatting-icons/index.tsx index d5e15fe1..913c126e 100644 --- a/client/components/document/formatting-icons/index.tsx +++ b/client/components/document/formatting-icons/index.tsx @@ -20,7 +20,7 @@ const FormattingIcons = ({ textareaRef, setText }: { textareaRef?: RefObject { + const handleBoldClick = useCallback(() => { if (textareaRef?.current && setText) { const selectionStart = textareaRef.current.selectionStart const selectionEnd = textareaRef.current.selectionEnd @@ -37,7 +37,7 @@ const FormattingIcons = ({ textareaRef, setText }: { textareaRef?: RefObject { + const handleItalicClick = useCallback(() => { if (textareaRef?.current && setText) { const selectionStart = textareaRef.current.selectionStart const selectionEnd = textareaRef.current.selectionEnd @@ -52,7 +52,7 @@ const FormattingIcons = ({ textareaRef, setText }: { textareaRef?: RefObject { + const handleLinkClick = useCallback(() => { if (textareaRef?.current && setText) { const selectionStart = textareaRef.current.selectionStart const selectionEnd = textareaRef.current.selectionEnd @@ -73,7 +73,7 @@ const FormattingIcons = ({ textareaRef, setText }: { textareaRef?: RefObject { + const handleImageClick = useCallback(() => { if (textareaRef?.current && setText) { const selectionStart = textareaRef.current.selectionStart const selectionEnd = textareaRef.current.selectionEnd @@ -134,4 +134,4 @@ const FormattingIcons = ({ textareaRef, setText }: { textareaRef?: RefObject { const switchThemes = (type: string | string[]) => { changeTheme() - if (typeof window === 'undefined' || !window.localStorage) return - window.localStorage.setItem('drift-theme', Array.isArray(type) ? type[0] : type) + Cookies.set('drift-theme', Array.isArray(type) ? type[0] : type) } diff --git a/client/components/new-post/drag-and-drop/index.tsx b/client/components/new-post/drag-and-drop/index.tsx index dfae57ce..25de2bd7 100644 --- a/client/components/new-post/drag-and-drop/index.tsx +++ b/client/components/new-post/drag-and-drop/index.tsx @@ -1,10 +1,9 @@ -import { Button, Text, useTheme, useToasts } from '@geist-ui/core' -import { memo, useCallback, useEffect } from 'react' +import { Text, useTheme, useToasts } from '@geist-ui/core' +import { memo } from 'react' import { useDropzone } from 'react-dropzone' import styles from './drag-and-drop.module.css' -import { Document } from '../' +import type { Document } from '@lib/types' import generateUUID from '@lib/generate-uuid' -import { XCircle } from '@geist-ui/icons' const allowedFileTypes = [ 'application/json', 'application/x-javascript', @@ -99,7 +98,7 @@ function FileDropzone({ setDocs }: { setDocs: ((docs: Document[]) => void) }) { const { setToast } = useToasts() const onDrop = async (acceptedFiles: File[]) => { const newDocs = await Promise.all(acceptedFiles.map((file) => { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const reader = new FileReader() reader.onabort = () => setToast({ text: 'File reading was aborted', type: 'error' }) diff --git a/client/components/new-post/index.tsx b/client/components/new-post/index.tsx index 6b401b4d..a12cc8fc 100644 --- a/client/components/new-post/index.tsx +++ b/client/components/new-post/index.tsx @@ -1,4 +1,4 @@ -import { Button, ButtonDropdown, Input, Modal, Note, useModal, useToasts } from '@geist-ui/core' +import { Button, ButtonDropdown, useToasts } from '@geist-ui/core' import { useRouter } from 'next/router'; import { useCallback, useState } from 'react' import generateUUID from '@lib/generate-uuid'; diff --git a/client/components/new-post/title/index.tsx b/client/components/new-post/title/index.tsx index d9b2302a..3865c858 100644 --- a/client/components/new-post/title/index.tsx +++ b/client/components/new-post/title/index.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, memo } from 'react' +import { memo } from 'react' import { Text, Input } from '@geist-ui/core' import ShiftBy from '@components/shift-by' import styles from '../post.module.css' diff --git a/client/components/visibility-badge/index.tsx b/client/components/visibility-badge/index.tsx index fa0dfb22..aac799d4 100644 --- a/client/components/visibility-badge/index.tsx +++ b/client/components/visibility-badge/index.tsx @@ -1,8 +1,8 @@ import { Badge } from "@geist-ui/core" -import { Visibility } from "@lib/types" +import { PostVisibility } from "@lib/types" type Props = { - visibility: Visibility + visibility: PostVisibility } const VisibilityBadge = ({ visibility }: Props) => { diff --git a/client/next.config.js b/client/next.config.js index 316e44b2..16eb5923 100644 --- a/client/next.config.js +++ b/client/next.config.js @@ -6,7 +6,6 @@ const nextConfig = { reactStrictMode: true, experimental: { outputStandalone: true, - optimizeCss: true, }, async rewrites() { return [ diff --git a/client/package.json b/client/package.json index 2018adea..f2d66652 100644 --- a/client/package.json +++ b/client/package.json @@ -16,11 +16,11 @@ "@types/js-cookie": "^3.0.1", "client-zip": "^2.0.0", "comlink": "^4.3.1", - "critters": "^0.0.16", "cookie": "^0.4.2", "dotenv": "^16.0.0", "js-cookie": "^3.0.1", "next": "^12.1.1-canary.15", + "prism-react-renderer": "^1.3.1", "prismjs": "^1.27.0", "react": "17.0.2", "react-debounce-render": "^8.0.2", @@ -32,8 +32,8 @@ "react-syntax-highlighter-virtualized-renderer": "^1.1.0", "rehype-autolink-headings": "^6.1.1", "rehype-katex": "^6.0.2", + "rehype-remark": "^9.1.2", "rehype-slug": "^5.0.1", - "rehype-stringify": "^9.0.3", "remark-gfm": "^3.0.1", "remark-math": "^5.1.1", "swr": "^1.2.2" @@ -41,9 +41,11 @@ "devDependencies": { "@types/node": "17.0.21", "@types/react": "17.0.39", + "@types/react-dom": "^17.0.14", "@types/react-syntax-highlighter": "^13.5.2", "eslint": "8.10.0", "eslint-config-next": "12.1.0", - "typescript": "4.6.2" + "typescript": "4.6.2", + "typescript-plugin-css-modules": "^3.4.0" } } diff --git a/client/pages/_app.tsx b/client/pages/_app.tsx index c0499056..809a8834 100644 --- a/client/pages/_app.tsx +++ b/client/pages/_app.tsx @@ -8,12 +8,7 @@ import 'react-loading-skeleton/dist/skeleton.css' import { SkeletonTheme } from 'react-loading-skeleton'; import Head from 'next/head'; import { ThemeProps } from '@lib/types'; - -export type PostProps = { - renderedPost: any | null, // Still don't have an official data type for posts - theme: "light" | "dark" | string, - changeTheme: () => void -} +import Cookies from 'js-cookie'; type AppProps

= { pageProps: P; @@ -22,11 +17,10 @@ type AppProps

= { export type DriftProps = ThemeProps function MyApp({ Component, pageProps }: AppProps) { - const [themeType, setThemeType] = useSharedState('theme', 'light') - const theme = useTheme(); + const [themeType, setThemeType] = useSharedState('theme', Cookies.get('drift-theme') || 'light') + useEffect(() => { - if (typeof window === 'undefined' || !window.localStorage) return - const storedTheme = window.localStorage.getItem('drift-theme') + const storedTheme = Cookies.get('drift-theme') if (storedTheme) setThemeType(storedTheme) // TODO: useReducer? }, [setThemeType, themeType]) diff --git a/client/pages/post/[id].tsx b/client/pages/post/[id].tsx index cddf7947..0289cb00 100644 --- a/client/pages/post/[id].tsx +++ b/client/pages/post/[id].tsx @@ -1,45 +1,36 @@ import { Button, Page, Text } from "@geist-ui/core"; -import Skeleton from 'react-loading-skeleton'; import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; import Document from '../../components/document' import Header from "../../components/header"; import VisibilityBadge from "../../components/visibility-badge"; -import { PostProps } from "../_app"; import PageSeo from "components/page-seo"; import styles from './styles.module.css'; -import Cookies from "js-cookie"; import cookie from "cookie"; import { GetServerSideProps } from "next"; +import { PostVisibility, ThemeProps } from "@lib/types"; +type File = { + id: string + title: string + content: string +} -const Post = ({renderedPost, theme, changeTheme}: PostProps) => { - const [post, setPost] = useState(renderedPost); - const [isLoading, setIsLoading] = useState(true) - const [error, setError] = useState() +type Files = File[] + +export type PostProps = ThemeProps & { + post: { + id: string + title: string + description: string + visibility: PostVisibility + files: Files + } +} + +const Post = ({ post, theme, changeTheme }: PostProps) => { const router = useRouter(); - useEffect(() => { - async function fetchPost() { - setIsLoading(true); - - if (renderedPost) { - setPost(renderedPost) - setIsLoading(false) - - return; - } - - if (!Cookies.get('drift-token')) { - router.push('/signin'); - } else { - setError('Something went wrong fetching the post'); - } - } - fetchPost() - }, [router, router.query.id]) - const download = async () => { const clientZip = require("client-zip") @@ -59,78 +50,88 @@ const Post = ({renderedPost, theme, changeTheme}: PostProps) => { return ( - {!isLoading && ( - - )} +

{/* {!isLoading && } */} - - {error && {error}} - {!error && isLoading && <> - - } - {!isLoading && post && <> -
-
- {post.title} - -
- +
+
+ {post.title} +
- {post.files.map(({ id, content, title }: { id: any, content: string, title: string }) => ( - - ))} - } + +
+ {post.files.map(({ id, content, title }: { id: any, content: string, title: string }) => ( + + ))} ) } export const getServerSideProps: GetServerSideProps = async (context) => { + const headers = context.req.headers + const host = headers.host + const driftToken = cookie.parse(headers.cookie || '')[`drift-token`] + let driftTheme = cookie.parse(headers.cookie || '')[`drift-theme`] + if (driftTheme !== "light" && driftTheme !== "dark") { + driftTheme = "light" + } + - const headers = context.req.headers; - const host = headers.host; - const driftToken = cookie.parse(headers.cookie || '')[`drift-token`]; - - let post; - if (context.query.id) { - post = await fetch('http://' + host + `/server-api/posts/${context.query.id}`, { + const post = await fetch('http://' + host + `/server-api/posts/${context.query.id}`, { method: "GET", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${driftToken}` } - }); + }) + if (!post.ok || post.status !== 200) { + return { + redirect: { + destination: '/', + permanent: false, + }, + } + } try { - post = await post.json(); + const json = await post.json(); + const maxAge = 60 * 60 * 24 * 365; + context.res.setHeader( + 'Cache-Control', + `${json.visibility === "public" ? "public" : "private"}, s-maxage=${maxAge}, max-age=${maxAge}` + ) + return { + props: { + post: json + } + } } catch (e) { - console.log(e); - post = null; + console.log(e) } } return { props: { - renderedPost: post + post: null } } } diff --git a/client/tsconfig.json b/client/tsconfig.json index 768f8569..2088465b 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "plugins": [{ "name": "typescript-plugin-css-modules" }], "target": "es2020", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, diff --git a/client/yarn.lock b/client/yarn.lock index ad5256e3..2d58786e 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -178,6 +178,11 @@ dependencies: "@types/ms" "*" +"@types/extend@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/extend/-/extend-3.0.1.tgz#923dc2d707d944382433e01d6cc0c69030ab2c75" + integrity sha512-R1g/VyKFFI2HLC1QGAeTtCBWCo6n75l41OnsVYNbmKG+kempOESaodf6BeJyUM3Q0rKa/NQcTHbB2+66lNnxLw== + "@types/hast@^2.0.0": version "2.3.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" @@ -232,6 +237,13 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== +"@types/react-dom@^17.0.14": + version "17.0.14" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.14.tgz#c8f917156b652ddf807711f5becbd2ab018dea9f" + integrity sha512-H03xwEP1oXmSfl3iobtmQ/2dHF5aBHr8aUMwyGZya6OW45G+xtdzmq6HkncefiBt5JU8DVyaWl/nWZbjZCnzAQ== + dependencies: + "@types/react" "*" + "@types/react-syntax-highlighter@^13.5.2": version "13.5.2" resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-13.5.2.tgz#357cc03581dc434c57c3b31f70e0eecdbf7b3ab0" @@ -327,6 +339,13 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -334,6 +353,14 @@ ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -386,6 +413,11 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + attr-accept@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b" @@ -419,10 +451,15 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -boolbase@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== brace-expansion@^1.1.7: version "1.1.11" @@ -432,7 +469,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -462,7 +499,16 @@ ccount@^2.0.0: resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== -chalk@^4.0.0, chalk@^4.1.0: +chalk@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -470,21 +516,11 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -character-entities-html4@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" - integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== - character-entities-legacy@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== -character-entities-legacy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" - integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== - character-entities@^1.0.0: version "1.2.4" resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" @@ -500,6 +536,21 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== +"chokidar@>=3.0.0 <4.0.0": + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + client-zip@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/client-zip/-/client-zip-2.0.0.tgz#c93676c92ddb40c858da83517c27297a53874f8d" @@ -510,6 +561,13 @@ clsx@^1.0.4: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -517,6 +575,11 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -552,6 +615,13 @@ cookie@^0.4.2: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== +copy-anything@^2.0.1: + version "2.0.6" + resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.6.tgz#092454ea9584a7b7ad5573062b2a87f5900fc480" + integrity sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw== + dependencies: + is-what "^3.14.1" + core-js-pure@^3.20.2: version "3.21.1" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" @@ -562,18 +632,6 @@ core-js@^2.4.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -critters@^0.0.16: - version "0.0.16" - resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93" - integrity sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A== - dependencies: - chalk "^4.1.0" - css-select "^4.2.0" - parse5 "^6.0.1" - parse5-htmlparser2-tree-adapter "^6.0.1" - postcss "^8.3.7" - pretty-bytes "^5.3.0" - cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -583,21 +641,35 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -css-select@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" - integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== +css-parse@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" + integrity sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q= dependencies: - boolbase "^1.0.0" - css-what "^5.1.0" - domhandler "^4.3.0" - domutils "^2.8.0" - nth-check "^2.0.1" + css "^2.0.0" -css-what@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== +css-selector-tokenizer@^0.7.0: + version "0.7.3" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz#735f26186e67c749aaf275783405cf0661fae8f1" + integrity sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg== + dependencies: + cssesc "^3.0.0" + fastparse "^1.1.2" + +css@^2.0.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" + integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== + dependencies: + inherits "^2.0.3" + source-map "^0.6.1" + source-map-resolve "^0.5.2" + urix "^0.1.0" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== csstype@^3.0.2: version "3.0.11" @@ -616,7 +688,7 @@ debug@^2.6.9: dependencies: ms "2.0.0" -debug@^3.2.7: +debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -630,6 +702,13 @@ debug@^4.0.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: dependencies: ms "2.1.2" +debug@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + decode-named-character-reference@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.1.tgz#57b2bd9112659cacbc449d3577d7dadb8e1f3d1b" @@ -637,6 +716,11 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -688,35 +772,10 @@ dom-helpers@^5.1.3: "@babel/runtime" "^7.8.7" csstype "^3.0.2" -dom-serializer@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^4.2.0, domhandler@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" - integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== - dependencies: - domelementtype "^2.2.0" - -domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== dotenv@^16.0.0: version "16.0.0" @@ -728,10 +787,17 @@ emoji-regex@^9.2.0, emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +errno@^0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" es-abstract@^1.19.0, es-abstract@^1.19.1: version "1.19.1" @@ -768,6 +834,11 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1012,6 +1083,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastparse@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" + integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -1077,6 +1153,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -1092,6 +1173,13 @@ gemoji@^6.1.0: resolved "https://registry.yarnpkg.com/gemoji/-/gemoji-6.1.0.tgz#268fbb0c81d1a8c32a4bcc39bdfdd66080ba7ce9" integrity sha512-MOlX3doQ1fsfzxQX8Y+u6bC5Ssc1pBUBIPVyrS69EzKt+5LIZAOm0G5XGVNhwXFgkBF3r+Yk88ONyrFHo8iNFA== +generic-names@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-1.0.3.tgz#2d786a121aee508876796939e8e3bff836c20917" + integrity sha1-LXhqEhruUIh2eWk56OO/+DbCCRc= + dependencies: + loader-utils "^0.2.16" + get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -1114,7 +1202,7 @@ github-slugger@^1.1.1: resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -1140,7 +1228,7 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.7: +glob@^7.1.3, glob@^7.1.6, glob@^7.1.7: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -1171,11 +1259,21 @@ globby@^11.0.4: merge2 "^1.4.1" slash "^3.0.0" +graceful-fs@^4.1.2: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -1200,6 +1298,13 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hast-util-embedded@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hast-util-embedded/-/hast-util-embedded-2.0.0.tgz#877f4261044854743fc2621f728930ca61c8376f" + integrity sha512-vEr54rDu2CheBM4nLkWbW8Rycf8HhkA/KsrDnlyKnvBTyhyO+vAG6twHnfUbiRGo56YeUBNCI4HFfHg3Wu+tig== + dependencies: + hast-util-is-element "^2.0.0" + hast-util-from-parse5@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-7.1.0.tgz#c129dd3a24dd8a867ab8a029ca47e27aa54864b7" @@ -1246,21 +1351,25 @@ hast-util-parse-selector@^3.0.0: dependencies: "@types/hast" "^2.0.0" -hast-util-to-html@^8.0.0: - version "8.0.3" - resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-8.0.3.tgz#4e37580872e143ea9ce0dba87918b19e4ea997e3" - integrity sha512-/D/E5ymdPYhHpPkuTHOUkSatxr4w1ZKrZsG0Zv/3C2SRVT0JFJG53VS45AMrBtYk0wp5A7ksEhiC8QaOZM95+A== +hast-util-to-mdast@^8.3.0: + version "8.3.1" + resolved "https://registry.yarnpkg.com/hast-util-to-mdast/-/hast-util-to-mdast-8.3.1.tgz#b2e3b666968d3ab96a0e6ec991cca0ca5c79e3b2" + integrity sha512-nxLcom1oW5y/1CyaV24K16LOfYbAIS74BDbCPW6WduzAYTAVDp3g/DM1CY6Ngo+Dx5itLzvmCm7SnUHBZd3NVQ== dependencies: + "@types/extend" "^3.0.0" "@types/hast" "^2.0.0" - ccount "^2.0.0" - comma-separated-tokens "^2.0.0" + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + extend "^3.0.0" + hast-util-has-property "^2.0.0" hast-util-is-element "^2.0.0" - hast-util-whitespace "^2.0.0" - html-void-elements "^2.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - stringify-entities "^4.0.2" + hast-util-to-text "^3.0.0" + mdast-util-phrasing "^3.0.0" + mdast-util-to-string "^3.0.0" + rehype-minify-whitespace "^5.0.0" + trim-trailing-lines "^2.0.0" unist-util-is "^5.0.0" + unist-util-visit "^4.0.0" hast-util-to-string@^2.0.0: version "2.0.0" @@ -1269,7 +1378,7 @@ hast-util-to-string@^2.0.0: dependencies: "@types/hast" "^2.0.0" -hast-util-to-text@^3.1.0: +hast-util-to-text@^3.0.0, hast-util-to-text@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-3.1.1.tgz#b7699a75f7a61af6e0befb67660cd78460d96dc6" integrity sha512-7S3mOBxACy8syL45hCn3J7rHqYaXkxRfsX6LXEU5Shz4nt4GxdjtMUtG+T6G/ZLUHd7kslFAf14kAN71bz30xA== @@ -1322,10 +1431,24 @@ hoist-non-react-statics@^3.3.2: dependencies: react-is "^16.7.0" -html-void-elements@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f" - integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== +iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +icss-utils@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-3.0.1.tgz#ee70d3ae8cac38c6be5ed91e851b27eed343ad0f" + integrity sha1-7nDTroysOMa+XtkehRsn7tNDrQ8= + dependencies: + postcss "^6.0.2" + +icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== ignore@^4.0.6: version "4.0.6" @@ -1337,6 +1460,16 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +image-size@~0.5.0: + version "0.5.5" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" + integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w= + +immutable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -1358,7 +1491,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, inherits@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1397,6 +1530,13 @@ is-bigint@^1.0.1: dependencies: has-bigints "^1.0.1" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -1439,7 +1579,7 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -1507,6 +1647,11 @@ is-weakref@^1.0.1: dependencies: call-bind "^1.0.2" +is-what@^3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" + integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1539,6 +1684,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -1585,6 +1735,23 @@ language-tags@^1.0.5: dependencies: language-subtag-registry "~0.3.2" +less@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/less/-/less-4.1.2.tgz#6099ee584999750c2624b65f80145f8674e4b4b0" + integrity sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA== + dependencies: + copy-anything "^2.0.1" + parse-node-version "^1.0.1" + tslib "^2.3.0" + optionalDependencies: + errno "^0.1.1" + graceful-fs "^4.1.2" + image-size "~0.5.0" + make-dir "^2.1.0" + mime "^1.4.1" + needle "^2.5.2" + source-map "~0.6.0" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -1593,6 +1760,21 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lilconfig@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" + integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== + +loader-utils@^0.2.16: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -1601,6 +1783,11 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -1611,6 +1798,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + longest-streak@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.0.1.tgz#c97315b7afa0e7d9525db9a5a2953651432bdc5d" @@ -1646,6 +1838,14 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + markdown-table@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.2.tgz#9b59eb2c1b22fe71954a65ff512887065a7bb57c" @@ -1759,6 +1959,14 @@ mdast-util-math@^2.0.0: longest-streak "^3.0.0" mdast-util-to-markdown "^1.3.0" +mdast-util-phrasing@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-3.0.0.tgz#c44fcf6be61a3cb8da54ab2df22320e61d4537ce" + integrity sha512-S+QYsDRLkGi8U7o5JF1agKa/sdP+CNGXXLqC17pdTVL8FHHgQEiwFGa9yE5aYtUxNiFGYoaDy9V1kC85Sz86Gg== + dependencies: + "@types/mdast" "^3.0.0" + unist-util-is "^5.0.0" + mdast-util-to-hast@^12.1.0: version "12.1.1" resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.1.1.tgz#89a2bb405eaf3b05eb8bf45157678f35eef5dbca" @@ -2098,6 +2306,11 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" +mime@^1.4.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + minimatch@^3.0.4, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -2110,6 +2323,11 @@ minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +mkdirp@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + mri@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -2140,6 +2358,15 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +needle@^2.5.2: + version "2.9.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684" + integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + next@^12.1.1-canary.15: version "12.1.1-canary.15" resolved "https://registry.yarnpkg.com/next/-/next-12.1.1-canary.15.tgz#a31c99a512b29d98aa0f6d837931d5c7f2aa2c35" @@ -2164,14 +2391,12 @@ next@^12.1.1-canary.15: "@next/swc-win32-ia32-msvc" "12.1.1-canary.15" "@next/swc-win32-x64-msvc" "12.1.1-canary.15" -nth-check@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== - dependencies: - boolbase "^1.0.0" +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -2288,14 +2513,12 @@ parse-entities@^2.0.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse5-htmlparser2-tree-adapter@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" - integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== - dependencies: - parse5 "^6.0.1" +parse-node-version@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" + integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== -parse5@^6.0.0, parse5@^6.0.1: +parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== @@ -2330,11 +2553,56 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +postcss-filter-plugins@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-3.0.1.tgz#9d226e946d56542ab7c26123053459a331df545d" + integrity sha512-tRKbW4wWBEkSSFuJtamV2wkiV9rj6Yy7P3Y13+zaynlPEEZt8EgYKn3y/RBpMeIhNmHXFlSdzofml65hD5OafA== + dependencies: + postcss "^6.0.14" + +postcss-icss-keyframes@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/postcss-icss-keyframes/-/postcss-icss-keyframes-0.2.1.tgz#80c4455e0112b0f2f9c3c05ac7515062bb9ff295" + integrity sha1-gMRFXgESsPL5w8Bax1FQYruf8pU= + dependencies: + icss-utils "^3.0.1" + postcss "^6.0.2" + postcss-value-parser "^3.3.0" + +postcss-icss-selectors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-icss-selectors/-/postcss-icss-selectors-2.0.3.tgz#27fa1afcaab6c602c866cbb298f3218e9bc1c9b3" + integrity sha1-J/oa/Kq2xgLIZsuymPMhjpvBybM= + dependencies: + css-selector-tokenizer "^0.7.0" + generic-names "^1.0.2" + icss-utils "^3.0.1" + lodash "^4.17.4" + postcss "^6.0.2" + +postcss-load-config@^3.0.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.3.tgz#21935b2c43b9a86e6581a576ca7ee1bde2bd1d23" + integrity sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw== + dependencies: + lilconfig "^2.0.4" + yaml "^1.10.2" + +postcss-value-parser@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + postcss@8.4.5: version "8.4.5" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" @@ -2344,7 +2612,16 @@ postcss@8.4.5: picocolors "^1.0.0" source-map-js "^1.0.1" -postcss@^8.3.7: +postcss@^6.0.14, postcss@^6.0.2: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +postcss@^8.3.0: version "8.4.12" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905" integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg== @@ -2358,10 +2635,10 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -pretty-bytes@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" - integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== +prism-react-renderer@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.1.tgz#88fc9d0df6bed06ca2b9097421349f8c2f24e30d" + integrity sha512-xUeDMEz074d0zc5y6rxiMp/dlC7C+5IDDlaEUlcBOFE2wddz7hz5PNupb087mPwTt7T9BrFmewObfCBuf/LKwQ== prismjs@^1.25.0, prismjs@^1.27.0, prismjs@~1.27.0: version "1.27.0" @@ -2389,6 +2666,11 @@ property-information@^6.0.0: resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22" integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w== +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -2513,6 +2795,13 @@ react@17.0.2: loose-envify "^1.1.0" object-assign "^4.1.1" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + refractor@^3.2.0: version "3.6.0" resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" @@ -2572,6 +2861,18 @@ rehype-katex@^6.0.2: unist-util-remove-position "^4.0.0" unist-util-visit "^4.0.0" +rehype-minify-whitespace@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/rehype-minify-whitespace/-/rehype-minify-whitespace-5.0.0.tgz#f3eec0ac94e78adbb868133e64864343ba9fff1f" + integrity sha512-cUkQldYx8jpWM6FZmCkOF/+mev09+5NAtBzUFZgnfXsIoglxo3h6t3S3JbNouiaqIDE6vbpI+GQpOg0xD3Z7kg== + dependencies: + "@types/hast" "^2.0.0" + hast-util-embedded "^2.0.0" + hast-util-is-element "^2.0.0" + hast-util-whitespace "^2.0.0" + unified "^10.0.0" + unist-util-is "^5.0.0" + rehype-parse@^8.0.0: version "8.0.4" resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-8.0.4.tgz#3d17c9ff16ddfef6bbcc8e6a25a99467b482d688" @@ -2582,6 +2883,16 @@ rehype-parse@^8.0.0: parse5 "^6.0.0" unified "^10.0.0" +rehype-remark@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/rehype-remark/-/rehype-remark-9.1.2.tgz#b4ed84d7e692426c3269e72ec477906cec659c05" + integrity sha512-c0fG3/CrJ95zAQ07xqHSkdpZybwdsY7X5dNWvgL2XqLKZuqmG3+vk6kP/4miCnp+R+x/0uKKRSpfXb9aGR8Z5w== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + hast-util-to-mdast "^8.3.0" + unified "^10.0.0" + rehype-slug@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/rehype-slug/-/rehype-slug-5.0.1.tgz#6e732d0c55b3b1e34187e74b7363fb53229e5f52" @@ -2595,15 +2906,6 @@ rehype-slug@^5.0.1: unified "^10.0.0" unist-util-visit "^4.0.0" -rehype-stringify@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/rehype-stringify/-/rehype-stringify-9.0.3.tgz#70e3bd6d4d29e7acf36b802deed350305d2c3c17" - integrity sha512-kWiZ1bgyWlgOxpqD5HnxShKAdXtb2IUljn3hQAhySeak6IOQPPt6DeGnsIh4ixm7yKJWzm8TXFuC/lPfcWHJqw== - dependencies: - "@types/hast" "^2.0.0" - hast-util-to-html "^8.0.0" - unified "^10.0.0" - remark-gfm@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-3.0.1.tgz#0b180f095e3036545e9dddac0e8df3fa5cfee54f" @@ -2643,11 +2945,21 @@ remark-rehype@^10.0.0: mdast-util-to-hast "^12.1.0" unified "^10.0.0" +reserved-words@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/reserved-words/-/reserved-words-0.1.2.tgz#00a0940f98cd501aeaaac316411d9adc52b31ab1" + integrity sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE= + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + resolve@^1.20.0: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" @@ -2691,6 +3003,25 @@ sade@^1.7.3: dependencies: mri "^1.1.0" +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sass@^1.32.13: + version "1.49.9" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.49.9.tgz#b15a189ecb0ca9e24634bae5d1ebc191809712f9" + integrity sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +sax@^1.2.4, sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + scheduler@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" @@ -2699,6 +3030,11 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" +semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -2737,11 +3073,37 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-js@^1.0.1, source-map-js@^1.0.2: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-resolve@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.6.1, source-map@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + space-separated-tokens@^1.0.0: version "1.1.5" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" @@ -2782,14 +3144,6 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -stringify-entities@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.2.tgz#13d113dc7449dc8ae4cb22c28883ee3fff8753e3" - integrity sha512-MTxTVcEkorNtBbNpoFJPEh0kKdM6+QbMjLbaxmvaPMmayOXdr/AIVIIJX7FReUVweRBFJfZepK4A4AKgwuFpMQ== - dependencies: - character-entities-html4 "^2.0.0" - character-entities-legacy "^3.0.0" - strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -2819,6 +3173,27 @@ styled-jsx@5.0.1: resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.1.tgz#78fecbbad2bf95ce6cd981a08918ce4696f5fc80" integrity sha512-+PIZ/6Uk40mphiQJJI1202b+/dYeTVd9ZnMPR80pgiWbjIwvN2zIp4r9et0BgqBuShh48I0gttPlAXA7WVvBxw== +stylus@^0.54.8: + version "0.54.8" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.8.tgz#3da3e65966bc567a7b044bfe0eece653e099d147" + integrity sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg== + dependencies: + css-parse "~2.0.0" + debug "~3.1.0" + glob "^7.1.6" + mkdirp "~1.0.4" + safer-buffer "^2.1.2" + sax "~1.2.4" + semver "^6.3.0" + source-map "^0.7.3" + +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -2848,6 +3223,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +trim-trailing-lines@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-2.0.0.tgz#1fdfbc20db6651bed117bc5c736f6cf052bcf421" + integrity sha512-lyJ/STqmYO8k9aWZbodPTrVkRh/50yFwNZ/HxKp/30eM9zf898MgQCG/NxfMnx7fZSKbaEcuZ1V+QgWrXFH6rg== + trough@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" @@ -2868,7 +3248,7 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3: +tslib@^2.0.3, tslib@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== @@ -2892,6 +3272,25 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +typescript-plugin-css-modules@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/typescript-plugin-css-modules/-/typescript-plugin-css-modules-3.4.0.tgz#4ff6905d88028684d1608c05c62cb6346e5548cc" + integrity sha512-2MdjfSg4MGex1csCWRUwKD+MpgnvcvLLr9bSAMemU/QYGqBsXdez0cc06H/fFhLtRoKJjXg6PSTur3Gy1Umhpw== + dependencies: + dotenv "^10.0.0" + icss-utils "^5.1.0" + less "^4.1.1" + lodash.camelcase "^4.3.0" + postcss "^8.3.0" + postcss-filter-plugins "^3.0.1" + postcss-icss-keyframes "^0.2.1" + postcss-icss-selectors "^2.0.3" + postcss-load-config "^3.0.1" + reserved-words "^0.1.2" + sass "^1.32.13" + stylus "^0.54.8" + tsconfig-paths "^3.9.0" + typescript@4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" @@ -3028,6 +3427,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + use-subscription@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" @@ -3119,6 +3523,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + zwitch@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.2.tgz#91f8d0e901ffa3d66599756dde7f57b17c95dce1" From d06d0ffea295aeb5f0ddf9cfd4a2e14ff4a8b6a4 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 14:54:36 -0700 Subject: [PATCH 4/8] client: remove cache control --- client/pages/post/[id].tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/pages/post/[id].tsx b/client/pages/post/[id].tsx index 0289cb00..4a6cf0d9 100644 --- a/client/pages/post/[id].tsx +++ b/client/pages/post/[id].tsx @@ -29,8 +29,6 @@ export type PostProps = ThemeProps & { } const Post = ({ post, theme, changeTheme }: PostProps) => { - const router = useRouter(); - const download = async () => { const clientZip = require("client-zip") @@ -117,7 +115,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { const maxAge = 60 * 60 * 24 * 365; context.res.setHeader( 'Cache-Control', - `${json.visibility === "public" ? "public" : "private"}, s-maxage=${maxAge}, max-age=${maxAge}` + `${json.visibility === "public" ? "public" : "private"}, s-maxage=${maxAge}` ) return { props: { From 2ec4019ea2636b507c1dffe90883be0f4977bbe9 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 14:56:45 -0700 Subject: [PATCH 5/8] client: fix submitting status on new post --- client/components/new-post/index.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/client/components/new-post/index.tsx b/client/components/new-post/index.tsx index a12cc8fc..64d45cd0 100644 --- a/client/components/new-post/index.tsx +++ b/client/components/new-post/index.tsx @@ -73,15 +73,10 @@ const Post = () => { password, userId: Cookies.get('drift-userid') || '' }) - - - - setSubmitting(false) } const onClosePasswordModal = () => { setPasswordModalVisible(false) - setSubmitting(false) } const updateTitle = useCallback((title: string, id: string) => { From 3efbeb726fc77784e129f246402258352be3f9a1 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 15:55:21 -0700 Subject: [PATCH 6/8] client: tree-shaking improvements --- .../document/formatting-icons/index.tsx | 5 +- client/components/document/index.tsx | 4 +- client/components/header/index.tsx | 18 ++- client/components/new-post/index.tsx | 5 +- .../preview/react-markdown-preview.tsx | 7 +- client/next.config.js | 6 +- client/package.json | 5 +- client/pages/post/[id].tsx | 4 +- client/yarn.lock | 132 +++++++++++------- server/src/server.ts | 2 +- 10 files changed, 120 insertions(+), 68 deletions(-) diff --git a/client/components/document/formatting-icons/index.tsx b/client/components/document/formatting-icons/index.tsx index 913c126e..288e7daa 100644 --- a/client/components/document/formatting-icons/index.tsx +++ b/client/components/document/formatting-icons/index.tsx @@ -1,5 +1,8 @@ import { ButtonGroup, Button } from "@geist-ui/core" -import { Bold, Italic, Link, Image as ImageIcon } from '@geist-ui/icons' +import Bold from '@geist-ui/icons/bold' +import Italic from '@geist-ui/icons/italic' +import Link from '@geist-ui/icons/link' +import ImageIcon from '@geist-ui/icons/image' import { RefObject, useCallback, useMemo } from "react" import styles from '../document.module.css' diff --git a/client/components/document/index.tsx b/client/components/document/index.tsx index 35a4b3ef..55f31066 100644 --- a/client/components/document/index.tsx +++ b/client/components/document/index.tsx @@ -2,7 +2,9 @@ import { Button, ButtonGroup, Card, Input, Spacer, Tabs, Textarea, Tooltip } fro import { ChangeEvent, memo, useCallback, useMemo, useRef, useState } from "react" import styles from './document.module.css' import MarkdownPreview from '../preview' -import { Trash, Download, ExternalLink } from '@geist-ui/icons' +import Trash from '@geist-ui/icons/trash' +import Download from '@geist-ui/icons/download' +import ExternalLink from '@geist-ui/icons/externalLink' import FormattingIcons from "./formatting-icons" import Skeleton from "react-loading-skeleton" // import Link from "next/link" diff --git a/client/components/header/index.tsx b/client/components/header/index.tsx index d5905f22..c90291dc 100644 --- a/client/components/header/index.tsx +++ b/client/components/header/index.tsx @@ -1,11 +1,21 @@ import { Page, ButtonGroup, Button, useBodyScroll, useMediaQuery, Tabs, Spacer } from "@geist-ui/core"; -import { Github as GitHubIcon, UserPlus as SignUpIcon, User as SignInIcon, Home as HomeIcon, Menu as MenuIcon, Tool as SettingsIcon, UserX as SignoutIcon, PlusCircle as NewIcon, List as YourIcon, Moon, Sun } from "@geist-ui/icons"; import { DriftProps } from "../../pages/_app"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useState } from "react"; import styles from './header.module.css'; import { useRouter } from "next/router"; import useSignedIn from "../../lib/hooks/use-signed-in"; +import HomeIcon from '@geist-ui/icons/home'; +import MenuIcon from '@geist-ui/icons/menu'; +import GitHubIcon from '@geist-ui/icons/github'; +import SignOutIcon from '@geist-ui/icons/userX'; +import SignInIcon from '@geist-ui/icons/user'; +import SignUpIcon from '@geist-ui/icons/userPlus'; +import NewIcon from '@geist-ui/icons/plusCircle'; +import YourIcon from '@geist-ui/icons/list' +import MoonIcon from '@geist-ui/icons/moon'; +import SunIcon from '@geist-ui/icons/sun'; + type Tab = { name: string icon: JSX.Element @@ -61,7 +71,7 @@ const Header = ({ changeTheme, theme }: DriftProps) => { { name: "Sign out", href: "/signout", - icon: , + icon: , condition: isSignedIn, value: "signout" }, @@ -94,7 +104,7 @@ const Header = ({ changeTheme, theme }: DriftProps) => { setSelectedTab(''); } }, - icon: theme === 'light' ? : , + icon: theme === 'light' ? : , condition: true, value: "theme", } diff --git a/client/components/new-post/index.tsx b/client/components/new-post/index.tsx index 64d45cd0..cd77a43e 100644 --- a/client/components/new-post/index.tsx +++ b/client/components/new-post/index.tsx @@ -49,7 +49,6 @@ const Post = () => { const closePasswordModel = () => { setPasswordModalVisible(false) - setSubmitting(false) } const [isSubmitting, setSubmitting] = useState(false) @@ -89,7 +88,7 @@ const Post = () => { const uploadDocs = useCallback((files: DocumentType[]) => { // if no title is set and the only document is empty, - const isFirstDocEmpty = docs.length === 1 && docs[0].title === '' && docs[0].content === '' + const isFirstDocEmpty = docs.length <= 1 && docs[0].title === '' && docs[0].content === '' const shouldSetTitle = !title && isFirstDocEmpty if (shouldSetTitle) { if (files.length === 1) { @@ -147,7 +146,7 @@ const Post = () => { onSubmit('protected', password)} />
- + ) } diff --git a/client/components/preview/react-markdown-preview.tsx b/client/components/preview/react-markdown-preview.tsx index 92d9963d..b02ac3e1 100644 --- a/client/components/preview/react-markdown-preview.tsx +++ b/client/components/preview/react-markdown-preview.tsx @@ -5,10 +5,11 @@ import rehypeSlug from 'rehype-slug' import rehypeAutolinkHeadings from 'rehype-autolink-headings' // @ts-ignore because of no types in remark-a11y-emoji -import a11yEmoji from '@fec/remark-a11y-emoji'; +// import a11yEmoji from '@fec/remark-a11y-emoji'; import styles from './preview.module.css' -import { vscDarkPlus as dark, vs as light } from 'react-syntax-highlighter/dist/cjs/styles/prism' +import dark from 'react-syntax-highlighter/dist/cjs/styles/prism/vsc-dark-plus' +import light from 'react-syntax-highlighter/dist/cjs/styles/prism/vs' import useSharedState from "@lib/hooks/use-shared-state"; type Props = { @@ -20,7 +21,7 @@ const ReactMarkdownPreview = ({ content, height }: Props) => { const [themeType] = useSharedState('theme') return (
{ driftTheme = "light" } - if (context.query.id) { const post = await fetch('http://' + host + `/server-api/posts/${context.query.id}`, { method: "GET", @@ -135,3 +134,4 @@ export const getServerSideProps: GetServerSideProps = async (context) => { } export default Post + diff --git a/client/yarn.lock b/client/yarn.lock index 2d58786e..7dbfe7ad 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -32,16 +32,6 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@fec/remark-a11y-emoji@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@fec/remark-a11y-emoji/-/remark-a11y-emoji-3.1.0.tgz#765ead0e26b6f06878f246c6e920a6edf0a5dc08" - integrity sha512-cYjCutvrValbQ2dykKhEE6OBTsEGpAJzeJnDtGKXhk2JYkMNSlKPnUk/kRFHH+PHmrAF+FlNIU28XKD+nYy7jQ== - dependencies: - emoji-regex "^9.2.0" - gemoji "^6.1.0" - mdast-util-find-and-replace "^1.0.0" - unist-util-visit "^2.0.3" - "@geist-ui/core@^2.3.5": version "2.3.5" resolved "https://registry.yarnpkg.com/@geist-ui/core/-/core-2.3.5.tgz#9b9f64f1c26e9fa68eb7e2bc4a2c1022ee353f66" @@ -68,6 +58,13 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@next/bundle-analyzer@^12.1.0": + version "12.1.0" + resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-12.1.0.tgz#9f6d6cda2a26220c936805be407243e22790f4b7" + integrity sha512-pOtWRWaKQXff8A80Ex3E67EH8XuERHxBPn8cQgKzfhRKQwoTEareHe2nWJO1uXTQm6m7ZRhmhb4+uwp+UvmITQ== + dependencies: + webpack-bundle-analyzer "4.3.0" + "@next/env@12.1.1-canary.15": version "12.1.1-canary.15" resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.1-canary.15.tgz#d1c210df31c8865042f2b81ffb37660b9cc70045" @@ -161,6 +158,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@polka/url@^1.0.0-next.20": + version "1.0.0-next.21" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" + integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "@rushstack/eslint-patch@^1.0.8": version "1.1.0" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" @@ -319,7 +321,12 @@ acorn-jsx@^5.3.1: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.7.0: +acorn-walk@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.0.4, acorn@^8.7.0: version "8.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== @@ -508,7 +515,7 @@ chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -600,6 +607,11 @@ comma-separated-tokens@^2.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz#d4c25abb679b7751c880be623c1179780fe1dd98" integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg== +commander@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + commander@^8.0.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" @@ -782,7 +794,12 @@ dotenv@^16.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== -emoji-regex@^9.2.0, emoji-regex@^9.2.2: +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + +emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== @@ -1168,11 +1185,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gemoji@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/gemoji/-/gemoji-6.1.0.tgz#268fbb0c81d1a8c32a4bcc39bdfdd66080ba7ce9" - integrity sha512-MOlX3doQ1fsfzxQX8Y+u6bC5Ssc1pBUBIPVyrS69EzKt+5LIZAOm0G5XGVNhwXFgkBF3r+Yk88ONyrFHo8iNFA== - generic-names@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-1.0.3.tgz#2d786a121aee508876796939e8e3bff836c20917" @@ -1264,6 +1276,13 @@ graceful-fs@^4.1.2: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" @@ -1798,7 +1817,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.4: +lodash@^4.17.20, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -1860,15 +1879,6 @@ mdast-util-definitions@^5.0.0: "@types/unist" "^2.0.0" unist-util-visit "^3.0.0" -mdast-util-find-and-replace@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz#b7db1e873f96f66588c321f1363069abf607d1b5" - integrity sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA== - dependencies: - escape-string-regexp "^4.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - mdast-util-find-and-replace@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.1.0.tgz#69728acd250749f8aac6e150e07d1fd15619e829" @@ -2333,6 +2343,11 @@ mri@^1.1.0: resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== +mrmime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" + integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -2463,6 +2478,11 @@ once@^1.3.0: dependencies: wrappy "1" +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -3068,6 +3088,15 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +sirv@^1.0.7: + version "1.0.19" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" + integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^1.0.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -3223,6 +3252,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +totalist@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" + integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== + trim-trailing-lines@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-2.0.0.tgz#1fdfbc20db6651bed117bc5c736f6cf052bcf421" @@ -3339,11 +3373,6 @@ unist-util-generated@^2.0.0: resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== -unist-util-is@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" - integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== - unist-util-is@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" @@ -3369,14 +3398,6 @@ unist-util-stringify-position@^3.0.0: dependencies: "@types/unist" "^2.0.0" -unist-util-visit-parents@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" - integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz#e83559a4ad7e6048a46b1bdb22614f2f3f4724f2" @@ -3393,15 +3414,6 @@ unist-util-visit-parents@^5.0.0: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" -unist-util-visit@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" - integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - unist-util-visit@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-3.1.0.tgz#9420d285e1aee938c7d9acbafc8e160186dbaf7b" @@ -3485,6 +3497,21 @@ web-namespaces@^2.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== +webpack-bundle-analyzer@4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.3.0.tgz#2f3c0ca9041d5ee47fa418693cf56b4a518b578b" + integrity sha512-J3TPm54bPARx6QG8z4cKBszahnUglcv70+N+8gUqv2I5KOFHJbzBiLx+pAp606so0X004fxM7hqRu10MLjJifA== + dependencies: + acorn "^8.0.4" + acorn-walk "^8.0.0" + chalk "^4.1.0" + commander "^6.2.0" + gzip-size "^6.0.0" + lodash "^4.17.20" + opener "^1.5.2" + sirv "^1.0.7" + ws "^7.3.1" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -3513,6 +3540,11 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +ws@^7.3.1: + version "7.5.7" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" + integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== + xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" diff --git a/server/src/server.ts b/server/src/server.ts index 134ad9af..2e96ea8d 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -4,7 +4,7 @@ import config from '../lib/config'; import { sequelize } from '../lib/sequelize'; (async () => { - await sequelize.sync({ force: true }); + await sequelize.sync(); createServer(app) .listen( config.port, From 90fa28ad6521454b279c501a2493d9d6e74f46c9 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 17:20:41 -0700 Subject: [PATCH 7/8] post generation rework with static paths/props --- README.md | 2 + client/.env.local | 1 + client/components/my-posts/index.tsx | 14 +- client/components/new-post/index.tsx | 3 +- client/components/post-list/list-item.tsx | 3 +- .../preview/react-markdown-preview.tsx | 2 +- client/lib/get-post-path.ts | 13 ++ client/pages/api/raw/[id].ts | 13 +- client/pages/api/revalidate.ts | 24 ++++ client/pages/mine.tsx | 34 ++++- client/pages/post/[id].tsx | 80 +++++------ client/pages/post/private/[id].tsx | 128 ++++++++++++++++++ server/{ => src}/lib/config.ts | 0 server/{ => src}/lib/middleware/jwt.ts | 0 server/src/lib/middleware/secret-key.ts | 14 ++ server/{ => src}/lib/models/File.ts | 0 server/{ => src}/lib/models/Post.ts | 0 server/{ => src}/lib/models/PostAuthor.ts | 0 server/{ => src}/lib/models/User.ts | 0 server/{ => src}/lib/sequelize.ts | 0 server/src/routes/auth.ts | 6 +- server/src/routes/files.ts | 14 +- server/src/routes/posts.ts | 39 ++++-- server/src/routes/users.ts | 8 +- server/src/server.ts | 4 +- server/tsconfig.json | 2 +- 26 files changed, 302 insertions(+), 102 deletions(-) create mode 100644 client/lib/get-post-path.ts create mode 100644 client/pages/api/revalidate.ts create mode 100644 client/pages/post/private/[id].tsx rename server/{ => src}/lib/config.ts (100%) rename server/{ => src}/lib/middleware/jwt.ts (100%) create mode 100644 server/src/lib/middleware/secret-key.ts rename server/{ => src}/lib/models/File.ts (100%) rename server/{ => src}/lib/models/Post.ts (100%) rename server/{ => src}/lib/models/PostAuthor.ts (100%) rename server/{ => src}/lib/models/User.ts (100%) rename server/{ => src}/lib/sequelize.ts (100%) diff --git a/README.md b/README.md index 74a7f5cd..cb12ef79 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ You can change these to your liking. - `API_URL`: defaults to localhost:3001, but allows you to host the front-end separately from the backend on a service like Vercel or Netlify - `WELCOME_CONTENT`: a markdown string (with \n newlines) that's rendered on the home page - `WELCOME_TITLE`: the file title for the post on the homepage. +- `SECRET_KEY`: a secret key used for validating API requests that is never exposed to the browser `server/.env`: @@ -38,6 +39,7 @@ You can change these to your liking. - `JWT_SECRET`: a secure token for JWT tokens. You can generate one [here](https://www.grc.com/passwords.htm). - `MEMORY_DB`: if `true`, a sqlite database will not be created and changes will only exist in memory. Mainly for the demo. - `REGISTRATION_PASSWORD`: if MEMORY_DB is not `true`, the user will be required to provide this password to sign-up, in addition to their username and account password. If it's not set, no password will be required. +- `SECRET_KEY`: the same secret key as the client ## Current status diff --git a/client/.env.local b/client/.env.local index 3bcbece7..a4e28f86 100644 --- a/client/.env.local +++ b/client/.env.local @@ -1,3 +1,4 @@ API_URL=http://localhost:3000 WELCOME_TITLE="Welcome to Drift" WELCOME_CONTENT="### Drift is a self-hostable clone of GitHub Gist. \nIt is a simple way to share code and text snippets with your friends, with support for the following:\n \n - Render GitHub Extended Markdown (including images)\n - User authentication\n - Private, public, and secret posts\n \n If you want to signup, you can join at [/signup](/signup) as long as you have a passcode provided by the administrator (which you don\'t need for this demo).\n **This demo is on a memory-only database, so accounts and pastes can be deleted at any time.**\n You can find the source code on [GitHub](https://github.com/MaxLeiter/drift).\n \n Drift was inspired by [this tweet](https://twitter.com/emilyst/status/1499858264346935297):\n > What is the absolute closest thing to GitHub Gist that can be self-hosted?\n In terms of design and functionality. Hosts images and markdown, rendered. Creates links that can be private or public. Uses/requires registration. I have looked at dozens of pastebin-like things." +SECRET_KEY=secret \ No newline at end of file diff --git a/client/components/my-posts/index.tsx b/client/components/my-posts/index.tsx index 15ea5892..80fbdba3 100644 --- a/client/components/my-posts/index.tsx +++ b/client/components/my-posts/index.tsx @@ -1,17 +1,7 @@ -import useSWR from "swr" import PostList from "../post-list" -import Cookies from "js-cookie" -const fetcher = (url: string) => fetch(url, { - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${Cookies.get("drift-token")}` - }, -}).then(r => r.json()) - -const MyPosts = () => { - const { data, error } = useSWR('/server-api/users/mine', fetcher) - return +const MyPosts = ({ posts, error }: { posts: any, error: any }) => { + return } export default MyPosts diff --git a/client/components/new-post/index.tsx b/client/components/new-post/index.tsx index cd77a43e..a962bb8e 100644 --- a/client/components/new-post/index.tsx +++ b/client/components/new-post/index.tsx @@ -9,6 +9,7 @@ import Title from './title'; import Cookies from 'js-cookie' import type { PostVisibility, Document as DocumentType } from '@lib/types'; import PasswordModal from './password'; +import getPostPath from '@lib/get-post-path'; const Post = () => { const { setToast } = useToasts() @@ -36,7 +37,7 @@ const Post = () => { if (res.ok) { const json = await res.json() - router.push(`/post/${json.id}`) + router.push(getPostPath(json.visibility, json.id)) } else { const json = await res.json() setToast({ diff --git a/client/components/post-list/list-item.tsx b/client/components/post-list/list-item.tsx index 30c37ecd..c034117f 100644 --- a/client/components/post-list/list-item.tsx +++ b/client/components/post-list/list-item.tsx @@ -4,6 +4,7 @@ import { useEffect, useMemo, useState } from "react" import timeAgo from "@lib/time-ago" import ShiftBy from "../shift-by" import VisibilityBadge from "../visibility-badge" +import getPostPath from "@lib/get-post-path" const FilenameInput = ({ title }: { title: string }) => { - + {post.title} diff --git a/client/components/preview/react-markdown-preview.tsx b/client/components/preview/react-markdown-preview.tsx index b02ac3e1..5507aae2 100644 --- a/client/components/preview/react-markdown-preview.tsx +++ b/client/components/preview/react-markdown-preview.tsx @@ -1,6 +1,6 @@ import ReactMarkdown from "react-markdown" import remarkGfm from "remark-gfm" -import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'; +import SyntaxHighlighter from 'react-syntax-highlighter/dist/cjs/prism-async-light'; import rehypeSlug from 'rehype-slug' import rehypeAutolinkHeadings from 'rehype-autolink-headings' diff --git a/client/lib/get-post-path.ts b/client/lib/get-post-path.ts new file mode 100644 index 00000000..47745319 --- /dev/null +++ b/client/lib/get-post-path.ts @@ -0,0 +1,13 @@ +import type { PostVisibility } from "./types" + +export default function getPostPath(visibility: PostVisibility, id: string) { + switch (visibility) { + case "private": + return `/post/private/${id}` + case "protected": + return `/post/protected/${id}` + case "unlisted": + case "public": + return `/post/${id}` + } +} diff --git a/client/pages/api/raw/[id].ts b/client/pages/api/raw/[id].ts index 62ef2745..f8f4d512 100644 --- a/client/pages/api/raw/[id].ts +++ b/client/pages/api/raw/[id].ts @@ -2,13 +2,20 @@ import { NextApiRequest, NextApiResponse } from "next" const getRawFile = async (req: NextApiRequest, res: NextApiResponse) => { const { id, download } = req.query - const file = await fetch(`${process.env.API_URL}/files/raw/${id}`) + const file = await fetch(`${process.env.API_URL}/files/raw/${id}`, { + headers: { + 'Accept': 'text/plain', + 'x-secret-key': process.env.SECRET_KEY || '' + } + }) + res.setHeader("Content-Type", "text/plain") + res.setHeader('Cache-Control', 's-maxage=86400'); + if (file.ok) { const data = await file.json() const { title, content } = data // serve the file raw as plain text - res.setHeader("Content-Type", "text/plain") - res.setHeader('Cache-Control', 's-maxage=86400'); + if (download) { res.setHeader("Content-Disposition", `attachment; filename="${title}"`) } else { diff --git a/client/pages/api/revalidate.ts b/client/pages/api/revalidate.ts new file mode 100644 index 00000000..07c62794 --- /dev/null +++ b/client/pages/api/revalidate.ts @@ -0,0 +1,24 @@ +import { NextApiRequest, NextApiResponse } from "next" + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.headers['x-secret-key'] !== process.env.SECRET_KEY) { + return res.status(401).send('Unauthorized') + } + + const { path } = req.query + + if (!path || typeof path !== 'string') { + return res.status(400).json({ + error: "Missing path" + }) + } + + try { + await res.unstable_revalidate(path) + return res.json({ revalidated: true }) + } catch (err) { + // If there was an error, Next.js will continue + // to show the last successfully generated page + return res.status(500).send('Error revalidating') + } +} diff --git a/client/pages/mine.tsx b/client/pages/mine.tsx index b273d548..9e502c20 100644 --- a/client/pages/mine.tsx +++ b/client/pages/mine.tsx @@ -3,18 +3,48 @@ import { Page } from '@geist-ui/core' import Header from '@components/header' import MyPosts from '@components/my-posts' +import cookie from "cookie"; +import { GetServerSideProps } from 'next'; +import { ThemeProps } from '@lib/types'; -const Home = ({ theme, changeTheme }: { theme: "light" | "dark", changeTheme: () => void }) => { +const Home = ({ posts, error, theme, changeTheme }: ThemeProps & { posts: any; error: any; }) => { return (
- + ) } +// get server side props +export const getServerSideProps: GetServerSideProps = async ({ req }) => { + const driftToken = cookie.parse(req.headers.cookie || '')[`drift-token`] + if (!driftToken) { + return { + redirect: { + destination: '/', + permanent: false, + } + } + } + + const posts = await fetch('http://localhost:3000/server-api/users/mine', { + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${driftToken}` + } + }) + + return { + props: { + posts: await posts.json(), + error: posts.status !== 200, + } + } +} export default Home diff --git a/client/pages/post/[id].tsx b/client/pages/post/[id].tsx index 5ddeb3f8..20c91bc8 100644 --- a/client/pages/post/[id].tsx +++ b/client/pages/post/[id].tsx @@ -1,13 +1,11 @@ import { Button, Page, Text } from "@geist-ui/core"; -import { useRouter } from "next/router"; -import Document from '../../components/document' -import Header from "../../components/header"; -import VisibilityBadge from "../../components/visibility-badge"; +import Document from '@components/document' +import Header from "@components/header"; +import VisibilityBadge from "@components/visibility-badge"; import PageSeo from "components/page-seo"; import styles from './styles.module.css'; -import cookie from "cookie"; -import { GetServerSideProps, GetStaticPaths, GetStaticProps } from "next"; +import type { GetStaticPaths, GetStaticProps } from "next"; import { PostVisibility, ThemeProps } from "@lib/types"; type File = { @@ -51,7 +49,7 @@ const Post = ({ post, theme, changeTheme }: PostProps) => { @@ -83,53 +81,37 @@ const Post = ({ post, theme, changeTheme }: PostProps) => { ) } -export const getServerSideProps: GetServerSideProps = async (context) => { - const headers = context.req.headers - const host = headers.host - const driftToken = cookie.parse(headers.cookie || '')[`drift-token`] - let driftTheme = cookie.parse(headers.cookie || '')[`drift-theme`] - if (driftTheme !== "light" && driftTheme !== "dark") { - driftTheme = "light" - } - - if (context.query.id) { - const post = await fetch('http://' + host + `/server-api/posts/${context.query.id}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - "Authorization": `Bearer ${driftToken}` - } - }) - - if (!post.ok || post.status !== 200) { - return { - redirect: { - destination: '/', - permanent: false, - }, - } +export const getStaticPaths: GetStaticPaths = async () => { + const posts = await fetch(process.env.API_URL + `/posts/`, { + method: "GET", + headers: { + "Content-Type": "application/json", + "x-secret-key": process.env.SECRET_KEY || "", } - try { - const json = await post.json(); - const maxAge = 60 * 60 * 24 * 365; - context.res.setHeader( - 'Cache-Control', - `${json.visibility === "public" ? "public" : "private"}, s-maxage=${maxAge}` - ) - return { - props: { - post: json - } - } - } catch (e) { - console.log(e) + }) + + const json = await posts.json() + const filtered = json.filter((post: any) => post.visibility === "public" || post.visibility === "unlisted") + const paths = filtered.map((post: any) => ({ + params: { id: post.id } + })) + + return { paths, fallback: 'blocking' } +} + +export const getStaticProps: GetStaticProps = async ({ params }) => { + const post = await fetch(process.env.API_URL + `/posts/${params?.id}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + "x-secret-key": process.env.SECRET_KEY || "", } - } + }) return { props: { - post: null - } + post: await post.json() + }, } } diff --git a/client/pages/post/private/[id].tsx b/client/pages/post/private/[id].tsx new file mode 100644 index 00000000..2dfdb3c0 --- /dev/null +++ b/client/pages/post/private/[id].tsx @@ -0,0 +1,128 @@ +import { Button, Page, Text } from "@geist-ui/core"; + +import Document from '@components/document' +import Header from "@components/header"; +import VisibilityBadge from "@components/visibility-badge"; +import PageSeo from "components/page-seo"; +import styles from '../styles.module.css'; +import cookie from "cookie"; +import type { GetServerSideProps } from "next"; +import { PostVisibility, ThemeProps } from "@lib/types"; + +type File = { + id: string + title: string + content: string +} + +type Files = File[] + +export type PostProps = ThemeProps & { + post: { + id: string + title: string + description: string + visibility: PostVisibility + files: Files + } +} + +const Post = ({ post, theme, changeTheme }: PostProps) => { + const download = async () => { + const clientZip = require("client-zip") + + const blob = await clientZip.downloadZip(post.files.map((file: any) => { + return { + name: file.title, + input: file.content, + lastModified: new Date(file.updatedAt) + } + })).blob() + const link = document.createElement("a") + link.href = URL.createObjectURL(blob) + link.download = `${post.title}.zip` + link.click() + link.remove() + } + + return ( + + + + +
+ + + {/* {!isLoading && } */} +
+
+ {post.title} + +
+ +
+ {post.files.map(({ id, content, title }: { id: any, content: string, title: string }) => ( + + ))} +
+ + ) +} + +export const getServerSideProps: GetServerSideProps = async (context) => { + const headers = context.req.headers + const host = headers.host + const driftToken = cookie.parse(headers.cookie || '')[`drift-token`] + + if (context.query.id) { + const post = await fetch('http://' + host + `/server-api/posts/${context.query.id}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${driftToken}` + } + }) + + if (!post.ok || post.status !== 200) { + return { + redirect: { + destination: '/', + permanent: false, + }, + } + } + try { + const json = await post.json(); + + return { + props: { + post: json + } + } + } catch (e) { + console.log(e) + } + } + + return { + props: { + post: null + } + } +} + +export default Post + diff --git a/server/lib/config.ts b/server/src/lib/config.ts similarity index 100% rename from server/lib/config.ts rename to server/src/lib/config.ts diff --git a/server/lib/middleware/jwt.ts b/server/src/lib/middleware/jwt.ts similarity index 100% rename from server/lib/middleware/jwt.ts rename to server/src/lib/middleware/jwt.ts diff --git a/server/src/lib/middleware/secret-key.ts b/server/src/lib/middleware/secret-key.ts new file mode 100644 index 00000000..241fe647 --- /dev/null +++ b/server/src/lib/middleware/secret-key.ts @@ -0,0 +1,14 @@ +import { NextFunction, Request, Response } from 'express'; + +const key = process.env.SECRET_KEY; +if (!key) { + throw new Error('SECRET_KEY is not set.'); +} + +export default function authenticateToken(req: Request, res: Response, next: NextFunction) { + const requestKey = req.headers['x-secret-key'] + if (requestKey !== key) { + return res.sendStatus(401) + } + next() +} diff --git a/server/lib/models/File.ts b/server/src/lib/models/File.ts similarity index 100% rename from server/lib/models/File.ts rename to server/src/lib/models/File.ts diff --git a/server/lib/models/Post.ts b/server/src/lib/models/Post.ts similarity index 100% rename from server/lib/models/Post.ts rename to server/src/lib/models/Post.ts diff --git a/server/lib/models/PostAuthor.ts b/server/src/lib/models/PostAuthor.ts similarity index 100% rename from server/lib/models/PostAuthor.ts rename to server/src/lib/models/PostAuthor.ts diff --git a/server/lib/models/User.ts b/server/src/lib/models/User.ts similarity index 100% rename from server/lib/models/User.ts rename to server/src/lib/models/User.ts diff --git a/server/lib/sequelize.ts b/server/src/lib/sequelize.ts similarity index 100% rename from server/lib/sequelize.ts rename to server/src/lib/sequelize.ts diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 049445c0..9e77a93a 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -1,9 +1,9 @@ import { Router } from 'express' import { genSalt, hash, compare } from "bcrypt" -import { User } from '../../lib/models/User' +import { User } from '../lib/models/User' import { sign } from 'jsonwebtoken' -import config from '../../lib/config' -import jwt from '../../lib/middleware/jwt' +import config from '../lib/config' +import jwt from '../lib/middleware/jwt' const NO_EMPTY_SPACE_REGEX = /^\S*$/ diff --git a/server/src/routes/files.ts b/server/src/routes/files.ts index 7a23751a..13efe551 100644 --- a/server/src/routes/files.ts +++ b/server/src/routes/files.ts @@ -1,10 +1,11 @@ import { Router } from 'express' +import secretKey from '../lib/middleware/secret-key'; // import { Movie } from '../models/Post' -import { File } from '../../lib/models/File' +import { File } from '../lib/models/File' export const files = Router() -files.get("/raw/:id", async (req, res, next) => { +files.get("/raw/:id", secretKey, async (req, res, next) => { try { const file = await File.findOne({ where: { @@ -12,18 +13,9 @@ files.get("/raw/:id", async (req, res, next) => { }, attributes: ["title", "content"], }) - // TODO: fix post inclusion - // if (file?.post.visibility === 'public' || file?.post.visibility === 'unlisted') { - res.setHeader("Cache-Control", "public, max-age=86400"); res.json(file); - // } else { - // TODO: should this be `private, `? - // res.setHeader("Cache-Control", "max-age=86400"); - // res.json(file); - // } } catch (e) { next(e); } }); - diff --git a/server/src/routes/posts.ts b/server/src/routes/posts.ts index 6456458e..70f54bf6 100644 --- a/server/src/routes/posts.ts +++ b/server/src/routes/posts.ts @@ -1,10 +1,11 @@ import { Router } from 'express' // import { Movie } from '../models/Post' -import { File } from '../../lib/models/File' -import { Post } from '../../lib/models/Post'; -import jwt, { UserJwtRequest } from '../../lib/middleware/jwt'; +import { File } from '../lib/models/File' +import { Post } from '../lib/models/Post'; +import jwt, { UserJwtRequest } from '../lib/middleware/jwt'; import * as crypto from "crypto"; -import { User } from '../../lib/models/User'; +import { User } from '../lib/models/User'; +import secretKey from '../lib/middleware/secret-key'; export const posts = Router() @@ -57,7 +58,18 @@ posts.post('/create', jwt, async (req, res, next) => { } }); -posts.get("/:id", async (req: UserJwtRequest, res, next) => { +posts.get("/", secretKey, async (req, res, next) => { + try { + const posts = await Post.findAll({ + attributes: ["id", "title", "visibility", "createdAt"], + }) + res.json(posts); + } catch (e) { + next(e); + } +}); + +posts.get("/:id", secretKey, async (req, res, next) => { try { const post = await Post.findOne({ where: { @@ -76,16 +88,19 @@ posts.get("/:id", async (req: UserJwtRequest, res, next) => { }, ] }) + if (!post) { + throw new Error("Post not found.") + } - if (post?.visibility === 'public' || post?.visibility === 'unlisted') { - res.setHeader("Cache-Control", "public, max-age=86400"); + if (post.visibility === 'public' || post?.visibility === 'unlisted') { res.json(post); - } else { - // TODO: should this be `private, `? - res.setHeader("Cache-Control", "max-age=86400"); - jwt(req, res, () => { + } else if (post.visibility === 'private') { + console.log("here") + jwt(req as UserJwtRequest, res, () => { res.json(post); - }); + }) + } else if (post.visibility === 'protected') { + } } catch (e) { diff --git a/server/src/routes/users.ts b/server/src/routes/users.ts index 3ffefd01..67c793f5 100644 --- a/server/src/routes/users.ts +++ b/server/src/routes/users.ts @@ -1,9 +1,9 @@ import { Router } from 'express' // import { Movie } from '../models/Post' -import { User } from '../../lib/models/User' -import { File } from '../../lib/models/File' -import jwt, { UserJwtRequest } from '../../lib/middleware/jwt' -import { Post } from '../../lib/models/Post' +import { User } from '../lib/models/User' +import { File } from '../lib/models/File' +import jwt, { UserJwtRequest } from '../lib/middleware/jwt' +import { Post } from '../lib/models/Post' export const users = Router() diff --git a/server/src/server.ts b/server/src/server.ts index 2e96ea8d..b3670024 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,7 +1,7 @@ import { createServer } from 'http'; import { app } from './app'; -import config from '../lib/config'; -import { sequelize } from '../lib/sequelize'; +import config from './lib/config'; +import { sequelize } from './lib/sequelize'; (async () => { await sequelize.sync(); diff --git a/server/tsconfig.json b/server/tsconfig.json index e5fbe651..765d8a8c 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -15,6 +15,6 @@ "strictPropertyInitialization": true, "outDir": "dist" }, - "include": ["lib/**/*.ts", "index.ts", "src/**/*.ts"], + "include": ["index.ts", "src/**/*.ts"], "exclude": ["node_modules"] } From d30c34deec50f9648ce993743b5481df1f6faf47 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 17:42:37 -0700 Subject: [PATCH 8/8] Add usage of SECRET_KEY to secure API routes --- client/pages/api/raw/[id].ts | 4 +++- client/pages/api/revalidate.ts | 24 ---------------------- client/pages/mine.tsx | 14 +++++++++++-- client/pages/post/private/[id].tsx | 3 ++- server/src/lib/models/Post.ts | 2 +- server/src/routes/files.ts | 12 +++++++++-- server/src/routes/posts.ts | 31 +++++++++++++++++++++++++++-- server/src/routes/users.ts | 32 +----------------------------- 8 files changed, 58 insertions(+), 64 deletions(-) delete mode 100644 client/pages/api/revalidate.ts diff --git a/client/pages/api/raw/[id].ts b/client/pages/api/raw/[id].ts index f8f4d512..4cfe4e52 100644 --- a/client/pages/api/raw/[id].ts +++ b/client/pages/api/raw/[id].ts @@ -5,9 +5,11 @@ const getRawFile = async (req: NextApiRequest, res: NextApiResponse) => { const file = await fetch(`${process.env.API_URL}/files/raw/${id}`, { headers: { 'Accept': 'text/plain', - 'x-secret-key': process.env.SECRET_KEY || '' + 'x-secret-key': process.env.SECRET_KEY || '', + 'Authorization': `Bearer ${req.cookies['drift-token']}`, } }) + res.setHeader("Content-Type", "text/plain") res.setHeader('Cache-Control', 's-maxage=86400'); diff --git a/client/pages/api/revalidate.ts b/client/pages/api/revalidate.ts deleted file mode 100644 index 07c62794..00000000 --- a/client/pages/api/revalidate.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { NextApiRequest, NextApiResponse } from "next" - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - if (req.headers['x-secret-key'] !== process.env.SECRET_KEY) { - return res.status(401).send('Unauthorized') - } - - const { path } = req.query - - if (!path || typeof path !== 'string') { - return res.status(400).json({ - error: "Missing path" - }) - } - - try { - await res.unstable_revalidate(path) - return res.json({ revalidated: true }) - } catch (err) { - // If there was an error, Next.js will continue - // to show the last successfully generated page - return res.status(500).send('Error revalidating') - } -} diff --git a/client/pages/mine.tsx b/client/pages/mine.tsx index 9e502c20..429c9dc6 100644 --- a/client/pages/mine.tsx +++ b/client/pages/mine.tsx @@ -31,14 +31,24 @@ export const getServerSideProps: GetServerSideProps = async ({ req }) => { } } - const posts = await fetch('http://localhost:3000/server-api/users/mine', { + const posts = await fetch(process.env.API_URL + `/posts/mine`, { method: "GET", headers: { "Content-Type": "application/json", - "Authorization": `Bearer ${driftToken}` + "Authorization": `Bearer ${driftToken}`, + "x-secret-key": process.env.SECRET_KEY || '' } }) + if (!posts.ok || posts.status !== 200) { + return { + redirect: { + destination: '/', + permanent: false, + } + } + } + return { props: { posts: await posts.json(), diff --git a/client/pages/post/private/[id].tsx b/client/pages/post/private/[id].tsx index 2dfdb3c0..c9b43583 100644 --- a/client/pages/post/private/[id].tsx +++ b/client/pages/post/private/[id].tsx @@ -92,7 +92,8 @@ export const getServerSideProps: GetServerSideProps = async (context) => { method: "GET", headers: { "Content-Type": "application/json", - "Authorization": `Bearer ${driftToken}` + "Authorization": `Bearer ${driftToken}`, + "x-secret-key": process.env.SECRET_KEY || "", } }) diff --git a/server/src/lib/models/Post.ts b/server/src/lib/models/Post.ts index 4bc6dc4b..2be1b024 100644 --- a/server/src/lib/models/Post.ts +++ b/server/src/lib/models/Post.ts @@ -38,7 +38,7 @@ export class Post extends Model { @BelongsToMany(() => User, () => PostAuthor) users?: User[]; - @HasMany(() => File) + @HasMany(() => File, { constraints: false }) files?: File[]; @CreatedAt diff --git a/server/src/routes/files.ts b/server/src/routes/files.ts index 13efe551..70a43cde 100644 --- a/server/src/routes/files.ts +++ b/server/src/routes/files.ts @@ -1,6 +1,5 @@ import { Router } from 'express' import secretKey from '../lib/middleware/secret-key'; -// import { Movie } from '../models/Post' import { File } from '../lib/models/File' export const files = Router() @@ -13,7 +12,16 @@ files.get("/raw/:id", secretKey, async (req, res, next) => { }, attributes: ["title", "content"], }) - res.json(file); + + // TODO: JWT-checkraw files + if (file?.post?.visibility === "private") { + // jwt(req as UserJwtRequest, res, () => { + // res.json(file); + // }) + res.json(file); + } else { + res.json(file); + } } catch (e) { next(e); diff --git a/server/src/routes/posts.ts b/server/src/routes/posts.ts index 70f54bf6..fde52b6b 100644 --- a/server/src/routes/posts.ts +++ b/server/src/routes/posts.ts @@ -69,6 +69,35 @@ posts.get("/", secretKey, async (req, res, next) => { } }); +posts.get("/mine", jwt, secretKey, async (req: UserJwtRequest, res, next) => { + if (!req.user) { + return res.status(401).json({ error: "Unauthorized" }) + } + + try { + const user = await User.findByPk(req.user.id, { + include: [ + { + model: Post, + as: "posts", + include: [ + { + model: File, + as: "files" + } + ] + }, + ], + }) + if (!user) { + return res.status(404).json({ error: "User not found" }) + } + return res.json(user.posts?.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())) + } catch (error) { + next(error) + } +}) + posts.get("/:id", secretKey, async (req, res, next) => { try { const post = await Post.findOne({ @@ -95,7 +124,6 @@ posts.get("/:id", secretKey, async (req, res, next) => { if (post.visibility === 'public' || post?.visibility === 'unlisted') { res.json(post); } else if (post.visibility === 'private') { - console.log("here") jwt(req as UserJwtRequest, res, () => { res.json(post); }) @@ -107,4 +135,3 @@ posts.get("/:id", secretKey, async (req, res, next) => { next(e); } }); - diff --git a/server/src/routes/users.ts b/server/src/routes/users.ts index 67c793f5..aedcd1e1 100644 --- a/server/src/routes/users.ts +++ b/server/src/routes/users.ts @@ -1,9 +1,7 @@ import { Router } from 'express' // import { Movie } from '../models/Post' import { User } from '../lib/models/User' -import { File } from '../lib/models/File' -import jwt, { UserJwtRequest } from '../lib/middleware/jwt' -import { Post } from '../lib/models/Post' +import jwt from '../lib/middleware/jwt' export const users = Router() @@ -16,31 +14,3 @@ users.get('/', jwt, async (req, res, next) => { } }) -users.get("/mine", jwt, async (req: UserJwtRequest, res, next) => { - if (!req.user) { - return res.status(401).json({ error: "Unauthorized" }) - } - - try { - const user = await User.findByPk(req.user.id, { - include: [ - { - model: Post, - as: "posts", - include: [ - { - model: File, - as: "files" - } - ] - }, - ], - }) - if (!user) { - return res.status(404).json({ error: "User not found" }) - } - return res.json(user.posts?.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())) - } catch (error) { - next(error) - } -})