diff --git a/.gitignore b/.gitignore index 45abffa..dc35995 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ yarn-debug.log* yarn-error.log* # local env files +.env .env.local .env.development.local .env.test.local diff --git a/README.md b/README.md index 904072d..c93b420 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - [x] 归档页面 - [x] 关于页面 -- [ ] PGP页面 +- [x] PGP页面 - [ ] 其他 ### 其他功能 @@ -19,6 +19,12 @@ - [x] NProgress - [ ] 暗色模式代码高亮 +## Todo + +- [ ] 提高文章页面加载速度 +- [ ] 图片懒加载占位问题 +- [ ] algolia 搜索样式 + ## ❤️ * Markdown 样式:[https://github.com/mingluosunyi/typora-theme-ava-diana](https://github.com/mingluosunyi/typora-theme-ava-diana) diff --git a/components/NavBar.tsx b/components/NavBar.tsx index 9abf859..ca2bf0e 100644 --- a/components/NavBar.tsx +++ b/components/NavBar.tsx @@ -14,9 +14,17 @@ import { } from '@chakra-ui/react'; import UseAnimations from 'react-useanimations'; import menu3 from 'react-useanimations/lib/menu3'; -import { FiHome, FiArchive, FiUser, FiSun, FiMoon } from 'react-icons/fi'; +import { + FiHome, + FiArchive, + FiUser, + FiSun, + FiMoon, + FiSearch, +} from 'react-icons/fi'; import useGetColors from '../lib/hooks/useGetColors'; import { useRouter } from 'next/router'; +import Search from './search'; const menu = [ { @@ -31,12 +39,29 @@ const menu = [ path: '/archive', icon: FiArchive, }, + // { + // id: 2, + // name: '闲言', + // path: '/message', + // icon: FiMessageSquare, + // }, + // { + // id: 3, + // name: '密语', + // path: '/pgp', + // icon: FiLock, + // }, { - id: 3, + id: 4, name: '关于', path: '/about', icon: FiUser, }, + { + id: 5, + name: '搜索', + icon: FiSearch, + }, ]; interface MenuListProps { @@ -45,7 +70,7 @@ interface MenuListProps { // eslint-disable-next-line no-unused-vars e: MouseEvent, // eslint-disable-next-line no-unused-vars - path: string + path?: string ) => void; } const MenuList: FC = ({ boxBg, handleMenuClick }) => { @@ -62,7 +87,7 @@ const MenuList: FC = ({ boxBg, handleMenuClick }) => { {menu.map((item) => { return ( handleMenuClick(e, item.path)} + onClick={(e) => handleMenuClick(e, item?.path)} href={item.path} key={item.id} as="a" @@ -85,7 +110,14 @@ const NavBar: FC = () => { const router = useRouter(); const [isLargerThan768] = useMediaQuery('(min-width: 768px)'); + // Menu toggle const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: false }); + // Modal toggle + const { + isOpen: isModalOpen, + onOpen: onModalOpen, + onClose: onModalClose, + } = useDisclosure(); const { colorMode, toggleColorMode } = useColorMode(); @@ -95,30 +127,35 @@ const NavBar: FC = () => { // Switch pages const handleMenuClick = ( e: MouseEvent, - path: string + path?: string ) => { e.preventDefault(); - !isLargerThan768 && - // Click the animate icon. - (iconRef.current?.children[0] as HTMLDivElement).click(); - router.push(path); + + if (path) { + !isLargerThan768 && + // Click the animate icon. + (iconRef.current?.children[0] as HTMLDivElement).click(); + router.push(path); + } else { + onModalOpen(); + } }; return ( <> - + {/* avatar */} Avatar { + {/* Mobile menu icon */} { /> + + ); }; diff --git a/components/search/CustomHighlight.tsx b/components/search/CustomHighlight.tsx new file mode 100644 index 0000000..126b8fb --- /dev/null +++ b/components/search/CustomHighlight.tsx @@ -0,0 +1,39 @@ +import { FC } from 'react'; +import { HighlightProvided } from 'react-instantsearch-core'; +import { connectHighlight } from 'react-instantsearch-dom'; +import type { PostHits } from './CustomHits'; + +type Props = { + attribute: string; + hit: PostHits; +}; + +const Highlight: FC = ({ + highlight, + attribute, + hit, +}) => { + const parsedHit = highlight({ + highlightProperty: '_highlightResult', + attribute, + hit, + }); + + return ( + <> + + {parsedHit.map((part, index) => + part.isHighlighted ? ( + {part.value} + ) : ( + {part.value} + ) + )} + + + ); +}; + +const CustomHighlight = connectHighlight(Highlight as any); + +export default CustomHighlight; diff --git a/components/search/CustomHits.tsx b/components/search/CustomHits.tsx new file mode 100644 index 0000000..72c7877 --- /dev/null +++ b/components/search/CustomHits.tsx @@ -0,0 +1,37 @@ +import { FC } from 'react'; +import { HitsProvided } from 'react-instantsearch-core'; +import { connectHits } from 'react-instantsearch-dom'; +import CustomHighlight from './CustomHighlight'; + +export interface PostHits { + objectID: string; + title: string; + id: string; + desc: string; + date: Date; + tags: string | string[]; + categories: string; + url: string; + index_img: string; +} + +const Hits: FC> = ({ hits }) => { + return ( + <> +
    + {hits.map((item) => { + return ( +
  1. + + +
  2. + ); + })} +
+ + ); +}; + +const CustomHits = connectHits(Hits); + +export default CustomHits; diff --git a/components/search/CustomSearchBox.tsx b/components/search/CustomSearchBox.tsx new file mode 100644 index 0000000..0e1f9ac --- /dev/null +++ b/components/search/CustomSearchBox.tsx @@ -0,0 +1,31 @@ +import { FC } from 'react'; +import { connectSearchBox } from 'react-instantsearch-dom'; +import { SearchBoxProvided } from 'react-instantsearch-core'; +import { + InputGroup, + Input, + InputRightElement, + CloseButton, +} from '@chakra-ui/react'; + +const SearchBox: FC = ({ currentRefinement, refine }) => { + return ( + <> + + refine(event.currentTarget.value)} + autoFocus + placeholder="Seach posts..." + /> + + {currentRefinement && refine('')} />} + + + + ); +}; + +const CustomSearchBox = connectSearchBox(SearchBox); + +export default CustomSearchBox; diff --git a/components/search/index.tsx b/components/search/index.tsx new file mode 100644 index 0000000..e810f4c --- /dev/null +++ b/components/search/index.tsx @@ -0,0 +1,50 @@ +import { FC } from 'react'; +import algoliasearch from 'algoliasearch/lite'; +import { InstantSearch } from 'react-instantsearch-dom'; +import { + Flex, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalOverlay, +} from '@chakra-ui/react'; +import CustomSearchBox from './CustomSearchBox'; +import CustomHits from './CustomHits'; + +const searchClient = algoliasearch( + process.env.NEXT_PUBLIC_ALGOLIA_APP_ID ?? '', + process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY ?? '' +); + +interface Props { + isModalOpen: boolean; + onModalClose: () => void; +} + +const Search: FC = ({ isModalOpen, onModalClose }) => { + return ( + <> + + + + + + + + + + + + + + + + + ); +}; + +export default Search; diff --git a/lib/hooks/useLazyload.ts b/lib/hooks/useLazyload.ts index 7191ac9..b430eca 100644 --- a/lib/hooks/useLazyload.ts +++ b/lib/hooks/useLazyload.ts @@ -1,8 +1,14 @@ import { useEffect, useRef, useState } from 'react'; -const useLazyLoad = (src: string) => { +/** + * Use IntersectionObserver API to lazy load taget DOM. + * @param src src path + * @param blurPx blur px + * @returns + */ +const useLazyLoad = (src: string, blurPx = '10px') => { const targetRef = useRef(null); - const [blur, setBlur] = useState('blur(20px)'); + const [blur, setBlur] = useState(`blur(${blurPx})`); const [initSrc, setInitSrc] = useState( 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' diff --git a/next.config.js b/next.config.js index 8b61df4..3dd7ef1 100644 --- a/next.config.js +++ b/next.config.js @@ -1,4 +1,4 @@ /** @type {import('next').NextConfig} */ module.exports = { reactStrictMode: true, -} +}; diff --git a/package.json b/package.json index cc98cfb..6a3885c 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "build": "next build", "start": "next start", "build:export": "next build && next export", + "postbuild": "node ./scripts/build-search.mjs", "lint": "next lint", "cypress": "cypress open", "cypress:headless": "cypress run", @@ -21,8 +22,10 @@ "@giscus/react": "^1.0.1", "@reduxjs/toolkit": "^1.6.2", "ahooks": "^2.10.12", + "algoliasearch": "^4.11.0", "autoprefixer": "^10.3.7", "date-fns": "^2.25.0", + "dotenv": "^10.0.0", "framer-motion": "^5.0.2", "gray-matter": "^4.0.3", "highlight.js": "^11.3.1", @@ -32,6 +35,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "react-icons": "^4.3.1", + "react-instantsearch-dom": "^6.16.0", "react-medium-image-zoom": "^4.3.5", "react-redux": "^7.2.6", "react-useanimations": "^2.0.6", @@ -51,6 +55,7 @@ "devDependencies": { "@types/nprogress": "^0.2.0", "@types/react": "17.0.31", + "@types/react-instantsearch-dom": "^6.12.0", "@types/react-redux": "^7.1.20", "cypress": "^9.0.0", "eslint": "7.32.0", diff --git a/pages/message.module.css b/pages/message.module.css new file mode 100644 index 0000000..1af81e2 --- /dev/null +++ b/pages/message.module.css @@ -0,0 +1,5 @@ +.wrapper h2 { + font-size: 1.6rem; + line-height: 2rem; + margin: 1rem 0; +} diff --git a/pages/message.tsx b/pages/message.tsx new file mode 100644 index 0000000..c81fa04 --- /dev/null +++ b/pages/message.tsx @@ -0,0 +1,37 @@ +import { ReactElement } from 'react'; +import useGetColors from '../lib/hooks/useGetColors'; +import Head from 'next/head'; +import { Box, Heading } from '@chakra-ui/react'; +import style from './message.module.css'; +import HomeLayout from '../layouts/HomeLayout'; + +const message = () => { + const { boxBg } = useGetColors(); + + return ( + <> + + RUA - Message + + + + Hi, there 👋 + + + ); +}; + +message.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default message; diff --git a/pages/pgp.module.css b/pages/pgp.module.css new file mode 100644 index 0000000..1af81e2 --- /dev/null +++ b/pages/pgp.module.css @@ -0,0 +1,5 @@ +.wrapper h2 { + font-size: 1.6rem; + line-height: 2rem; + margin: 1rem 0; +} diff --git a/pages/pgp.tsx b/pages/pgp.tsx new file mode 100644 index 0000000..9cac3a6 --- /dev/null +++ b/pages/pgp.tsx @@ -0,0 +1,37 @@ +import { ReactElement } from 'react'; +import useGetColors from '../lib/hooks/useGetColors'; +import Head from 'next/head'; +import { Box, Heading } from '@chakra-ui/react'; +import style from './pgp.module.css'; +import HomeLayout from '../layouts/HomeLayout'; + +const pgp = () => { + const { boxBg } = useGetColors(); + + return ( + <> + + RUA - Message + + + + Hi, there 👋 + + + ); +}; + +pgp.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default pgp; diff --git a/pages/posts/[slug].tsx b/pages/posts/[slug].tsx index 9af4670..690c659 100644 --- a/pages/posts/[slug].tsx +++ b/pages/posts/[slug].tsx @@ -13,7 +13,6 @@ import { import { getAllPostSlugs, getPostData } from '../../lib/posts'; import { GetStaticProps, InferGetStaticPropsType } from 'next'; import Head from 'next/head'; -import Date from '../../components/DateFormater'; import remarkToc from 'remark-toc'; import rehypeSlug from 'rehype-slug'; import rehypeReact from 'rehype-react'; @@ -31,15 +30,18 @@ import rehypeRaw from 'rehype-raw'; import 'react-medium-image-zoom/dist/styles.css'; import { FiCalendar } from 'react-icons/fi'; import { useRouter } from 'next/router'; -import Footer from '../../components/Footer'; import { Giscus } from '@giscus/react'; import { RootState } from '../../app/store'; import { cleanFromPath } from '../../features/router/routerSlice'; -import CopyButton from '../../components/post/CopyButton'; import useGetColors from '../../lib/hooks/useGetColors'; import Zoom from 'react-medium-image-zoom'; import useLazyLoad from '../../lib/hooks/useLazyload'; import { useAppSelector, useAppDispatch } from '../../app/hooks'; +import dynamic from 'next/dynamic'; + +const CopyButton = dynamic(() => import('../../components/post/CopyButton')); +const Footer = dynamic(() => import('../../components/Footer')); +const Date = dynamic(() => import('../../components/DateFormater')); export async function getStaticPaths() { const paths = await getAllPostSlugs(); @@ -90,18 +92,13 @@ const Post = ({ postData }: InferGetStaticPropsType) => { createElement, components: { img: (props: any) => { - const { initSrc, blur, targetRef } = useLazyLoad(props.src); + const { initSrc, blur, targetRef } = useLazyLoad(props.src, '20px'); return ( - + Post image) => { filter={blur} w="100%" transitionDuration="slower" - ratio={16 / 9} + ratio={isLargerThan768 ? 16 / 9 : 1} > {props.child} diff --git a/public/images/img/placeholder-1200x1000.webp:Zone.Identifier b/public/images/img/placeholder-1200x1000.webp:Zone.Identifier deleted file mode 100644 index d8e544c..0000000 --- a/public/images/img/placeholder-1200x1000.webp:Zone.Identifier +++ /dev/null @@ -1,4 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=https://cloudconvert.com/ -HostUrl=https://storage.cloudconvert.com/tasks/26da36ae-4f65-40e0-9cfd-cacdae9421f8/default%20%281%29.webp?AWSAccessKeyId=cloudconvert-production&Expires=1637766629&Signature=YV2hGzZxW7vZKjg2JOI3jAZMIi4%3D&response-content-disposition=attachment%3B%20filename%3D%22default%20%281%29.webp%22&response-content-type=image%2Fwebp diff --git a/public/images/img/placeholder-600x500.webp:Zone.Identifier b/public/images/img/placeholder-600x500.webp:Zone.Identifier deleted file mode 100644 index 3d89cd3..0000000 --- a/public/images/img/placeholder-600x500.webp:Zone.Identifier +++ /dev/null @@ -1,4 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=https://cloudconvert.com/ -HostUrl=https://storage.cloudconvert.com/tasks/5cc2ab54-b332-4ded-af05-5ed4e8dc8cba/default2%20%281%29.webp?AWSAccessKeyId=cloudconvert-production&Expires=1637766757&Signature=LsEjK9%2BKehCwLMPFpEmV1wFV2wc%3D&response-content-disposition=attachment%3B%20filename%3D%22default2%20%281%29.webp%22&response-content-type=image%2Fwebp diff --git a/scripts/build-search.mjs b/scripts/build-search.mjs new file mode 100644 index 0000000..e6e3bbe --- /dev/null +++ b/scripts/build-search.mjs @@ -0,0 +1,91 @@ +import { config } from 'dotenv'; +import algoliasearch from 'algoliasearch/lite.js'; +import { readdir, readFile } from 'fs/promises'; +import { join } from 'path'; +import matter from 'gray-matter'; +import { remark } from 'remark'; +import strip from 'strip-markdown'; + +const postsDirectory = join(process.cwd(), 'public/posts'); + +/** + * Get all sorted posts + * @returns + */ +async function getSortedPostsData() { + // Get file names under /posts + const fileNames = await readdir(postsDirectory); + const allPostsData = await Promise.all( + fileNames.map(async (fileName) => { + // Remove ".md" from file name to get id + const id = fileName.replace(/\.md$/, ''); + + // Read markdown file as string + const fullPath = join(postsDirectory, fileName); + const fileContents = await readFile(fullPath, 'utf8'); + + // Use gray-matter to parse the post metadata section + const matterResult = matter(fileContents); + + // Process markdown to plain text + const contentText = await remark() + .use(strip) + .process(matterResult.content); + + // Combine the data with the id + return { + objectID: id, + id, + // Add post description + desc: `${contentText.toString().slice(0, 100)}...`, + ...{ + ...matterResult.data, + date: matterResult.data.date.toISOString(), + }, + }; + }) + ); + + // Sort posts by date + return allPostsData.sort(({ date: a }, { date: b }) => { + if (a < b) { + return 1; + } else if (a > b) { + return -1; + } else { + return 0; + } + }); +} + +(async function () { + // initialize environment variables + config(); + + try { + const posts = await getSortedPostsData(); + + // initialize the client with your environment variables + const client = algoliasearch( + process.env.NEXT_PUBLIC_ALGOLIA_APP_ID, + process.env.ALGOLIA_SEARCH_ADMIN_KEY + ); + + // initialize the index with your index name + const index = client.initIndex('rua'); + + // save the objects! + const algoliaResponse = await index.saveObjects(posts); + + // check the output of the response in the console + console.log( + `🎉 Sucessfully added ${ + algoliaResponse.objectIDs.length + } records to Algolia search. Object IDs:\n${algoliaResponse.objectIDs.join( + '\n' + )}` + ); + } catch (e) { + console.log(e); + } +})(); diff --git a/tsconfig.json b/tsconfig.json index 4fa631c..4565103 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,6 +14,18 @@ "isolatedModules": true, "jsx": "preserve" }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "ts-node": { + "compilerOptions": { + "esModuleInterop": true, + "module": "CommonJS" + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + "lib/build-search.js", + "scripts/build-search.mjs" + ], "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index cfcbfd3..7e7ea08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,6 +10,110 @@ lodash.debounce "^4.0.8" lodash.throttle "^4.1.1" +"@algolia/cache-browser-local-storage@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.11.0.tgz#1c168add00b398a860db6c86039e33b2843a9425" + integrity sha512-4sr9vHIG1fVA9dONagdzhsI/6M5mjs/qOe2xUP0yBmwsTsuwiZq3+Xu6D3dsxsuFetcJgC6ydQoCW8b7fDJHYQ== + dependencies: + "@algolia/cache-common" "4.11.0" + +"@algolia/cache-common@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.11.0.tgz#066fe6d58b18e4b028dbef9bb8de07c5e22a3594" + integrity sha512-lODcJRuPXqf+6mp0h6bOxPMlbNoyn3VfjBVcQh70EDP0/xExZbkpecgHyyZK4kWg+evu+mmgvTK3GVHnet/xKw== + +"@algolia/cache-in-memory@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.11.0.tgz#763c8cb655e6fd2261588e04214fca0959ac07c1" + integrity sha512-aBz+stMSTBOBaBEQ43zJXz2DnwS7fL6dR0e2myehAgtfAWlWwLDHruc/98VOy1ZAcBk1blE2LCU02bT5HekGxQ== + dependencies: + "@algolia/cache-common" "4.11.0" + +"@algolia/client-account@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.11.0.tgz#67fadd3b0802b013ebaaa4b47bb7babae892374e" + integrity sha512-jwmFBoUSzoMwMqgD3PmzFJV/d19p1RJXB6C1ADz4ju4mU7rkaQLtqyZroQpheLoU5s5Tilmn/T8/0U2XLoJCRQ== + dependencies: + "@algolia/client-common" "4.11.0" + "@algolia/client-search" "4.11.0" + "@algolia/transporter" "4.11.0" + +"@algolia/client-analytics@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.11.0.tgz#cbdc8128205e2da749cafc79e54708d14c413974" + integrity sha512-v5U9585aeEdYml7JqggHAj3E5CQ+jPwGVztPVhakBk8H/cmLyPS2g8wvmIbaEZCHmWn4TqFj3EBHVYxAl36fSA== + dependencies: + "@algolia/client-common" "4.11.0" + "@algolia/client-search" "4.11.0" + "@algolia/requester-common" "4.11.0" + "@algolia/transporter" "4.11.0" + +"@algolia/client-common@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.11.0.tgz#9a2d1f6f8eaad25ba5d6d4ce307ba5bd84e6f999" + integrity sha512-Qy+F+TZq12kc7tgfC+FM3RvYH/Ati7sUiUv/LkvlxFwNwNPwWGoZO81AzVSareXT/ksDDrabD4mHbdTbBPTRmQ== + dependencies: + "@algolia/requester-common" "4.11.0" + "@algolia/transporter" "4.11.0" + +"@algolia/client-personalization@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.11.0.tgz#d3bf0e760f85df876b4baf5b81996f0aa3a59940" + integrity sha512-mI+X5IKiijHAzf9fy8VSl/GTT67dzFDnJ0QAM8D9cMPevnfX4U72HRln3Mjd0xEaYUOGve8TK/fMg7d3Z5yG6g== + dependencies: + "@algolia/client-common" "4.11.0" + "@algolia/requester-common" "4.11.0" + "@algolia/transporter" "4.11.0" + +"@algolia/client-search@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.11.0.tgz#c1105d715a2a04ba27231eca86f5d6620f68f4ae" + integrity sha512-iovPLc5YgiXBdw2qMhU65sINgo9umWbHFzInxoNErWnYoTQWfXsW6P54/NlKx5uscoLVjSf+5RUWwFu5BX+lpw== + dependencies: + "@algolia/client-common" "4.11.0" + "@algolia/requester-common" "4.11.0" + "@algolia/transporter" "4.11.0" + +"@algolia/logger-common@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.11.0.tgz#bac1c2d59d29dee378b57412c8edd435b97de663" + integrity sha512-pRMJFeOY8hoWKIxWuGHIrqnEKN/kqKh7UilDffG/+PeEGxBuku+Wq5CfdTFG0C9ewUvn8mAJn5BhYA5k8y0Jqg== + +"@algolia/logger-console@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.11.0.tgz#ced19e3abb22eb782ed5268d51efb5aa9ef109ef" + integrity sha512-wXztMk0a3VbNmYP8Kpc+F7ekuvaqZmozM2eTLok0XIshpAeZ/NJDHDffXK2Pw+NF0wmHqurptLYwKoikjBYvhQ== + dependencies: + "@algolia/logger-common" "4.11.0" + +"@algolia/requester-browser-xhr@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.11.0.tgz#f9e1ad56f185432aa8dde8cad53ae271fd5d6181" + integrity sha512-Fp3SfDihAAFR8bllg8P5ouWi3+qpEVN5e7hrtVIYldKBOuI/qFv80Zv/3/AMKNJQRYglS4zWyPuqrXm58nz6KA== + dependencies: + "@algolia/requester-common" "4.11.0" + +"@algolia/requester-common@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.11.0.tgz#d16de98d3ff72434bac39e4d915eab08035946a9" + integrity sha512-+cZGe/9fuYgGuxjaBC+xTGBkK7OIYdfapxhfvEf03dviLMPmhmVYFJtJlzAjQ2YmGDJpHrGgAYj3i/fbs8yhiA== + +"@algolia/requester-node-http@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.11.0.tgz#beb2b6b68d5f4ce15aec80ede623f0ac96991368" + integrity sha512-qJIk9SHRFkKDi6dMT9hba8X1J1z92T5AZIgl+tsApjTGIRQXJLTIm+0q4yOefokfu4CoxYwRZ9QAq+ouGwfeOg== + dependencies: + "@algolia/requester-common" "4.11.0" + +"@algolia/transporter@4.11.0": + version "4.11.0" + resolved "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.11.0.tgz#a8de3c173093ceceb02b26b577395ce3b3d4b96f" + integrity sha512-k4dyxiaEfYpw4UqybK9q7lrFzehygo6KV3OCYJMMdX0IMWV0m4DXdU27c1zYRYtthaFYaBzGF4Kjcl8p8vxCKw== + dependencies: + "@algolia/cache-common" "4.11.0" + "@algolia/logger-common" "4.11.0" + "@algolia/requester-common" "4.11.0" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.npmmirror.com/@babel/code-frame/download/@babel/code-frame-7.12.11.tgz?cache=0&sync_timestamp=1633554562995&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -1153,6 +1257,23 @@ resolved "https://registry.nlark.com/@types/prop-types/download/@types/prop-types-15.7.4.tgz?cache=0&sync_timestamp=1629708737049&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fprop-types%2Fdownload%2F%40types%2Fprop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" integrity sha1-/PcgXCXf95Xuea8eMNosl5CAjxE= +"@types/react-instantsearch-core@*": + version "6.10.5" + resolved "https://registry.npmjs.org/@types/react-instantsearch-core/-/react-instantsearch-core-6.10.5.tgz#909870ad8bbdbd8ba501b34df8f952d983c3d8ce" + integrity sha512-VjXJFUfsPdWMSiugJiQc950G9ZRjCEIzqQ9/K915d1f1BsVE2TE57PcfHSxAy1pGDDR8FT5uAgAaOMyKJ66NJQ== + dependencies: + "@types/react" "*" + algoliasearch ">=4" + algoliasearch-helper ">=3" + +"@types/react-instantsearch-dom@^6.12.0": + version "6.12.0" + resolved "https://registry.npmjs.org/@types/react-instantsearch-dom/-/react-instantsearch-dom-6.12.0.tgz#716be1b48193bbb65271205a9bd112a65d8a2661" + integrity sha512-O08H+ye4e4kEnYHmMrov9FPNRDJwfCWthNZf4aztqahpU8LSbAiuFQGVy84SHUvg/jfNcG4333SsVnAQLtbS7A== + dependencies: + "@types/react" "*" + "@types/react-instantsearch-core" "*" + "@types/react-redux@^7.1.20": version "7.1.20" resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.20.tgz#42f0e61ababb621e12c66c96dda94c58423bd7df" @@ -1334,6 +1455,33 @@ ajv@^8.0.1: require-from-string "^2.0.2" uri-js "^4.2.2" +algoliasearch-helper@>=3, algoliasearch-helper@^3.6.2: + version "3.6.2" + resolved "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.6.2.tgz#45e19b12589cfa0c611b573287f65266ea2cc14a" + integrity sha512-Xx0NOA6k4ySn+R2l3UMSONAaMkyfmrZ3AP1geEMo32MxDJQJesZABZYsldO9fa6FKQxH91afhi4hO1G0Zc2opg== + dependencies: + events "^1.1.1" + +algoliasearch@>=4, algoliasearch@^4.11.0: + version "4.11.0" + resolved "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.11.0.tgz#234befb3ac355c094077f0edf3777240b1ee013c" + integrity sha512-IXRj8kAP2WrMmj+eoPqPc6P7Ncq1yZkFiyDrjTBObV1ADNL8Z/KdZ+dWC5MmYcBLAbcB/mMCpak5N/D1UIZvsA== + dependencies: + "@algolia/cache-browser-local-storage" "4.11.0" + "@algolia/cache-common" "4.11.0" + "@algolia/cache-in-memory" "4.11.0" + "@algolia/client-account" "4.11.0" + "@algolia/client-analytics" "4.11.0" + "@algolia/client-common" "4.11.0" + "@algolia/client-personalization" "4.11.0" + "@algolia/client-search" "4.11.0" + "@algolia/logger-common" "4.11.0" + "@algolia/logger-console" "4.11.0" + "@algolia/requester-browser-xhr" "4.11.0" + "@algolia/requester-common" "4.11.0" + "@algolia/requester-node-http" "4.11.0" + "@algolia/transporter" "4.11.0" + anser@1.4.9: version "1.4.9" resolved "https://registry.npmmirror.com/anser/download/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760" @@ -1870,6 +2018,11 @@ classnames@2.2.6: resolved "https://registry.npm.taobao.org/classnames/download/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha1-Q5Nb/90pHzJtrQogUwmzjQD2UM4= +classnames@^2.2.5: + version "2.3.1" + resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.nlark.com/clean-stack/download/clean-stack-2.2.0.tgz?cache=0&sync_timestamp=1621915044030&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fclean-stack%2Fdownload%2Fclean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -2322,6 +2475,11 @@ domain-browser@^1.1.1: resolved "https://registry.nlark.com/domain-browser/download/domain-browser-1.2.0.tgz?cache=0&sync_timestamp=1627591557212&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdomain-browser%2Fdownload%2Fdomain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto= +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + duplexer@~0.1.1: version "0.1.2" resolved "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fduplexer%2Fdownload%2Fduplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -2709,6 +2867,11 @@ eventemitter2@^6.4.3: resolved "https://registry.npmmirror.com/eventemitter2/download/eventemitter2-6.4.5.tgz?cache=0&sync_timestamp=1633287607262&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Feventemitter2%2Fdownload%2Feventemitter2-6.4.5.tgz#97380f758ae24ac15df8353e0cc27f8b95644655" integrity sha1-lzgPdYriSsFd+DU+DMJ/i5VkRlU= +events@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= + events@^3.0.0: version "3.3.0" resolved "https://registry.nlark.com/events/download/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -5306,7 +5469,7 @@ react-dom@17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" -react-fast-compare@3.2.0: +react-fast-compare@3.2.0, react-fast-compare@^3.0.0: version "3.2.0" resolved "https://registry.npm.taobao.org/react-fast-compare/download/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha1-ZBqdqBtqYyDycOiXJPtFoLOeQ7s= @@ -5328,6 +5491,28 @@ react-icons@^4.3.1: resolved "https://registry.npmmirror.com/react-icons/download/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca" integrity sha1-L6kq67vHH0PS2y7RrtBzYRJOkco= +react-instantsearch-core@^6.16.0: + version "6.16.0" + resolved "https://registry.npmjs.org/react-instantsearch-core/-/react-instantsearch-core-6.16.0.tgz#6e64fb81628605073d247331959ef9f3978c0046" + integrity sha512-urtTbVWafrW5XqAVDW6LntU0yK4WF5L6Ms+P6SIKhYXq9FX3i3JtKWKR+9ebJU/0x7CDvfBr9f45EHD9SiX1hw== + dependencies: + "@babel/runtime" "^7.1.2" + algoliasearch-helper "^3.6.2" + prop-types "^15.6.2" + react-fast-compare "^3.0.0" + +react-instantsearch-dom@^6.16.0: + version "6.16.0" + resolved "https://registry.npmjs.org/react-instantsearch-dom/-/react-instantsearch-dom-6.16.0.tgz#db179c0be48f4e85ba179339be75bf58f68696d2" + integrity sha512-fciP0/XRk0/Hi0E4db6zrwC1mW/4Gui9X1q/pBUxDivQtUGGd3RHfhjv9pYHca3ha+251bzcUgjvgJpty+xJ5A== + dependencies: + "@babel/runtime" "^7.1.2" + algoliasearch-helper "^3.6.2" + classnames "^2.2.5" + prop-types "^15.6.2" + react-fast-compare "^3.0.0" + react-instantsearch-core "^6.16.0" + react-is@17.0.2, react-is@^17.0.2: version "17.0.2" resolved "https://registry.npmmirror.com/react-is/download/react-is-17.0.2.tgz?cache=0&sync_timestamp=1634892328318&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Freact-is%2Fdownload%2Freact-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"