Fix site build (#796)

* Some fixes site

* A lot of fixes in the site

* move file
This commit is contained in:
Eric Fennis
2022-09-13 09:03:13 +02:00
committed by GitHub
parent f9d37968d6
commit 34249ff42c
38 changed files with 2006 additions and 708 deletions
+5 -1
View File
@@ -17,5 +17,9 @@ module.exports = {
trailingComma: 'all'
}
]
}
},
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./site/tsconfig.json', './packages/*/tsconfig.json'],
},
};
+1807 -507
View File
File diff suppressed because it is too large Load Diff
+4 -11
View File
@@ -1,21 +1,14 @@
/* eslint-disable no-undef */
/* eslint-disable */
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'import', 'prettier'],
plugins: ['@typescript-eslint', 'import'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@next/next/recommended',
'prettier',
],
rules: {
'prettier/prettier': [
'error',
{
singleQuote: true,
trailingComma: 'all',
},
],
parserOptions: {
tsconfigRootDir: __dirname,
},
};
+1
View File
@@ -1,3 +1,4 @@
/* eslint-disable */
module.exports = {
testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
setupFilesAfterEnv: ['<rootDir>/setupTests.js'],
+3 -7
View File
@@ -1,15 +1,11 @@
/* eslint-disable no-undef */
/* eslint-disable */
module.exports = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
issuer: {
and: [/\.(js|ts)x?$/],
},
use: ['@svgr/webpack'],
use: ["@svgr/webpack"]
});
return config;
},
}
};
+15 -12
View File
@@ -10,7 +10,9 @@
"export": "next export -o build",
"deploy": "pnpm build && pnpm export",
"lint": "eslint .",
"test": "jest"
"lint:fix": "eslint --fix .",
"test": "jest",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@chakra-ui/react": "1.8.8",
@@ -19,7 +21,7 @@
"@mdx-js/loader": "^1.6.22",
"@mdx-js/react": "^1.6.22",
"@next/mdx": "^11.0.0",
"@svgr/webpack": "^6.2.1",
"@svgr/webpack": "^6.3.1",
"downloadjs": "^1.4.7",
"framer-motion": "^4",
"fuse.js": "^6.5.3",
@@ -37,23 +39,24 @@
"react-svg-loader": "^3.0.3"
},
"devDependencies": {
"@next/eslint-plugin-next": "^11.1.0",
"@testing-library/dom": "^7.24.4",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.0.4",
"@testing-library/react-hooks": "^3.4.2",
"react-test-renderer": "17.0.2",
"@next/eslint-plugin-next": "^12.2.5",
"@testing-library/dom": "^7.31.2",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^11.2.7",
"@testing-library/react-hooks": "^8.0.1",
"@types/jest": "^28.1.7",
"@types/node": "^14.0.11",
"@types/react": "^16.9.35",
"@types/react-dom": "^16.9.8",
"@typescript-eslint/eslint-plugin": "^4.29.1",
"@typescript-eslint/parser": "^4.29.1",
"@typescript-eslint/eslint-plugin": "^5.34.0",
"@typescript-eslint/parser": "^5.34.0",
"babel-jest": "^26.5.2",
"babel-loader": "^8.1.0",
"cheerio": "^1.0.0-rc.3",
"eslint": "^7.32.0",
"eslint": "^8.22.0",
"eslint-config-prettier": "^8.5.0",
"jest": "^26.5.2",
"prettier": "^2.3.2",
"react-test-renderer": "17.0.2",
"typescript": "^4.3.5"
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ const calculateLinesToHighlight = (meta: string) => {
};
};
interface HighlightProps {
interface HighlightProps extends BoxProps {
code: string;
language: Language;
metastring?: string;
+1 -1
View File
@@ -21,7 +21,7 @@ function ColorPicker({ hsv, hsl, onChange, value: color }: ColorPickerProps) {
}, [color]);
const handleChange = (e) => {
let value = e.target.value;
const value = e.target.value;
setValue(value);
onChange(value, e);
};
+1 -1
View File
@@ -1,4 +1,4 @@
import { Box, ButtonProps, Button, useClipboard } from '@chakra-ui/react';
import { Button, useClipboard } from '@chakra-ui/react';
const CopyButton = ({ copyText, buttonText = 'copy', ...props }) => {
const { hasCopied, onCopy } = useClipboard(copyText);
+3 -3
View File
@@ -21,11 +21,11 @@ const DEFAULT_STYLE = {
export const IconStyleContext = createContext<ICustomIconStyle>({
color: 'currentColor',
setColor: (s: string) => null,
setColor: () => null,
strokeWidth: 2,
setStroke: (n: number) => null,
setStroke: () => null,
size: 24,
setSize: (n: number) => null,
setSize: () => null,
resetStyle: () => null,
iconsRef: { current: {} },
});
+2 -2
View File
@@ -1,4 +1,4 @@
import { Button, Flex, Link, WrapItem, Text, Wrap, Heading, Icon } from '@chakra-ui/react';
import { Button, Flex, Link, WrapItem, Text, Wrap, Heading } from '@chakra-ui/react';
import download from 'downloadjs';
import JSZip from 'jszip';
import { Download, Github } from 'lucide-react';
@@ -17,7 +17,7 @@ import { useState } from 'react';
import { useCustomizeIconContext } from './CustomizeIconContext';
import { IconEntity } from '../types';
type IconContent = [icon: string, src:string]
type IconContent = [icon: string, src:string];
async function generateZip(icons: IconContent[]) {
const zip = new JSZip();
@@ -1,4 +1,4 @@
import { createContext, useState, useContext, useMemo, useCallback, useEffect } from 'react';
import { createContext, useState, useContext, useMemo, useCallback } from 'react';
interface HeadingTypes {
anchor: string;
@@ -8,7 +8,7 @@ interface HeadingTypes {
const HeadingNavigationContext = createContext({
headings: [],
// eslint-disable-next-line @typescript-eslint/no-empty-function
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
addHeading: (heading: HeadingTypes) => {},
});
+2 -1
View File
@@ -1,8 +1,9 @@
import { useEffect, useMemo } from 'react';
import { useMemo } from 'react';
import { useHeadingNavigationContext } from './HeadingNavigationProvider';
const HeadingTreeMenu = () => {
const { headings } = useHeadingNavigationContext();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const headingElements = useMemo(
() =>
headings.map(heading => {
+30 -17
View File
@@ -1,39 +1,50 @@
import { Box, Text, IconButton, useColorMode, Flex, Slide, ButtonGroup, Button, useToast, Heading, Avatar, AvatarGroup, Link, Tooltip, useMediaQuery, useDisclosure } from "@chakra-ui/react";
import theme from "../lib/theme";
import download from 'downloadjs';
import copy from "copy-to-clipboard";
import { X as Close } from 'lucide-react';
import {useContext, useEffect, useRef} from "react";
import {IconStyleContext} from "./CustomizeIconContext";
import {IconWrapper} from "./IconWrapper";
import ModifiedTooltip from "./ModifiedTooltip";
import { IconData } from "../lib/icons";
type IconDownload = {
src: string;
name: string;
};
const IconDetailOverlay = ({ open = true, close, icon }) => {
interface IconDetailOverlayProps {
open: boolean
close: () => void
icon?: IconData
}
const IconDetailOverlay = ({ open = true, close, icon }: IconDetailOverlayProps) => {
const toast = useToast();
const { colorMode } = useColorMode();
const { tags = [], name } = icon;
const {color, strokeWidth, size} = useContext(IconStyleContext);
const iconRef = useRef<SVGSVGElement>(null);
const [isMobile] = useMediaQuery("(max-width: 560px)")
const { isOpen, onOpen, onClose } = useDisclosure()
const handleClose = () => {
onClose();
close();
};
useEffect(() => {
if(open) {
onOpen()
}
}, [open])
const iconStyling = (isLight) => ({
if(icon == null) {
return null
}
const { tags = [], name = '' } = icon;
const handleClose = () => {
onClose();
close();
};
const iconStyling = {
height: "25vw",
width: "25vw",
minHeight: "160px",
@@ -41,12 +52,15 @@ const IconDetailOverlay = ({ open = true, close, icon }) => {
maxHeight: "240px",
maxWidth: "240px",
color: color,
});
};
const downloadIcon = ({src, name} : IconDownload) => download(src, `${name}.svg`, 'image/svg+xml');
const downloadIcon = ({src, name = ''} : IconDownload) => download(src, `${name}.svg`, 'image/svg+xml');
const copyIcon = async ({src, name} : IconDownload) => {
const trimmedSrc = src.replace(/(\r\n|\n|\r|\s\s)/gm, "")
await navigator.clipboard.writeText(trimmedSrc)
const copyIcon = ({src, name} : IconDownload) => {
copy(src);
toast({
title: "Copied!",
description: `Icon "${name}" copied to clipboard.`,
@@ -95,7 +109,6 @@ const IconDetailOverlay = ({ open = true, close, icon }) => {
w="full"
px={8}
>
<Box
borderWidth="1px"
rounded="lg"
@@ -135,7 +148,7 @@ const IconDetailOverlay = ({ open = true, close, icon }) => {
padding={0}
>
<div
style={iconStyling(colorMode == "light")}
style={iconStyling}
className="icon-large"
>
<IconWrapper
@@ -216,8 +229,8 @@ const IconDetailOverlay = ({ open = true, close, icon }) => {
</Heading>
<AvatarGroup size="md">
{ icon.contributors.map((commit, index) => (
<Link href={`https://github.com/${commit.author}`} isExternal key={`${index}_${commit.sha}`}>
<Tooltip label={commit.author} key={commit.sha}>
<Link href={`https://github.com/${commit.author}`} isExternal key={`${index}_${commit.commit}`}>
<Tooltip label={commit.author} key={commit.commit}>
<Avatar name={commit.author} src={`https://github.com/${commit.author}.png?size=88`} />
</Tooltip>
</Link>
+24 -21
View File
@@ -1,22 +1,42 @@
import { Button, ButtonProps, Flex, Text, useToast } from '@chakra-ui/react';
import download from 'downloadjs';
import copy from 'copy-to-clipboard';
import { memo } from 'react';
import { Contributor } from '../lib/fetchAllContributors';
import { useCustomizeIconContext } from './CustomizeIconContext';
import { IconWrapper } from './IconWrapper';
interface IconListItemProps {
name: string;
content: string;
contributors: any[];
contributors: Contributor[]
src: string;
onClick?: ButtonProps['onClick'];
onClick?: ButtonProps['onClick']
}
const IconListItem = ({ name, content, onClick, src: svg }: IconListItemProps) => {
const toast = useToast();
const { color, size, strokeWidth, iconsRef } = useCustomizeIconContext();
const handleClick:ButtonProps['onClick'] = async (event) => {
const src = (iconsRef.current[name].outerHTML ?? svg).replace(/(\r\n|\n|\r|(>\s\s<))/gm, "")
if (event.shiftKey) {
await navigator.clipboard.writeText(src)
toast({
title: 'Copied!',
description: `Icon "${name}" copied to clipboard.`,
status: 'success',
duration: 1500,
});
}
if (event.altKey) {
download(src, `${name}.svg`, 'image/svg+xml');
}
if (onClick) {
onClick(event);
}
}
return (
<Button
variant="ghost"
@@ -26,24 +46,7 @@ const IconListItem = ({ name, content, onClick, src: svg }: IconListItemProps) =
height={32}
position="relative"
whiteSpace="normal"
onClick={event => {
const src = iconsRef.current[name].outerHTML ?? svg
if (event.shiftKey) {
copy(src);
toast({
title: 'Copied!',
description: `Icon "${name}" copied to clipboard.`,
status: 'success',
duration: 1500,
});
}
if (event.altKey) {
download(src, `${name}.\svg`, 'image/svg+xml');
}
if (onClick) {
onClick(event);
}
}}
onClick={handleClick}
key={name}
alignItems="center"
>
+1
View File
@@ -121,6 +121,7 @@ const Layout = ({ aside, children }: LayoutProps) => {
<Divider mb={6} mt={12} />
<p style={{ alignSelf: 'center' }}>
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src="/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
</p>
-1
View File
@@ -1,5 +1,4 @@
import { Icon, Link, Text } from '@chakra-ui/react';
//@ts-ignore
import LogoImage from '../../public/logo.svg';
import NextLink from 'next/link';
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import { useDisclosure } from '@chakra-ui/react';
import { createContext, useState, useContext, useMemo, useCallback, useEffect } from 'react';
import { createContext, useContext, useMemo } from 'react';
const MobileNavigationContext = createContext({
isOpen: false,
+1 -1
View File
@@ -1,7 +1,7 @@
import { Box, Tooltip, useColorMode } from "@chakra-ui/react";
import theme from '../lib/theme';
const ModifiedTooltip = ({}) => {
const ModifiedTooltip = () => {
const { colorMode } = useColorMode();
return (
+20 -5
View File
@@ -5,17 +5,31 @@ import {
Heading,
Text,
useColorMode,
Divider,
ButtonGroup,
Stack,
} from '@chakra-ui/react';
import Image from 'next/image';
import { Code, FileText } from 'lucide-react';
import Link from 'next/link';
import { MDXRemote } from 'next-mdx-remote';
import mdxComponents from '../lib/mdxComponents';
const Package = ({ name, description, image, shields, source, documentation }) => {
interface Shield {
alt: string
src: string
href: string
}
export interface PackageItem {
name: string
description: string
image: string
shields: Shield[]
source: string
documentation: string
order: number
private?: boolean
flutter?: object
}
const Package = ({ name, description, image, shields, source, documentation }: PackageItem) => {
const { colorMode } = useColorMode();
return (
@@ -71,6 +85,7 @@ const Package = ({ name, description, image, shields, source, documentation }) =
{shields.map(({ alt, src, href }, index) => (
<Link href={href} passHref>
<a target="_blank">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img {...{ alt, src }} key={index} />
</a>
</Link>
+13 -9
View File
@@ -2,6 +2,11 @@ import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
export interface Contributor {
author: string
commit: string
}
const IGNORE_COMMIT_MESSAGES = ['fork', 'optimize'];
function getContentHashOfFile(path) {
@@ -14,8 +19,7 @@ function getContentHashOfFile(path) {
});
}
const fetchCommitsOfIcon = (name) =>
new Promise(async (resolve, reject) => {
const fetchCommitsOfIcon = async (name) =>{
try {
const headers = new Headers();
const username = 'ericfennis';
@@ -35,22 +39,22 @@ const fetchCommitsOfIcon = (name) =>
const data = await res.json();
resolve({
return {
name,
commits: data,
});
};
} catch (error) {
reject(error);
throw new Error(error);
}
});
};
export const filterCommits = (commits) =>
commits.filter(({ commit }) =>
!IGNORE_COMMIT_MESSAGES.some(ignoreItem =>
commit.message.toLowerCase().includes(ignoreItem),
))
.map(({ sha, author, commit }) => ({
.map(({ sha, author }) => ({
author: author && author.login ? author.login : null,
commit: sha,
}))
@@ -86,7 +90,7 @@ async function writeIconCache(icon, content) {
fs.writeFileSync(iconCachePath, JSON.stringify(content), 'utf-8');
}
export async function getContributors(icon) {
export async function getContributors(icon): Promise<Contributor[]> {
try {
let iconCommits
const iconCache = await checkIconCache(icon);
@@ -94,7 +98,7 @@ export async function getContributors(icon) {
if (iconCache) {
iconCommits = iconCache
} else {
const { commits } : any = await fetchCommitsOfIcon(icon);
const { commits } = await fetchCommitsOfIcon(icon);
writeIconCache(icon, commits)
+2 -3
View File
@@ -1,10 +1,11 @@
import { promises as fs, constants } from 'fs';
import path from 'path';
import yaml from 'js-yaml'
import { PackageItem } from '../components/Package';
const fileExist = (filePath) => fs.access(filePath, constants.F_OK).then(() => true).catch(() => false)
const fetchPackages = async () => {
const fetchPackages = async (): Promise<PackageItem[]> => {
const docsDir = path.resolve(process.cwd(), '../packages');
const fileNames = await (await fs.readdir(docsDir)).map(filename => ({filename, directory: docsDir}))
@@ -31,8 +32,6 @@ const fetchPackages = async () => {
return null
}))
return packageJsons
}
+18 -9
View File
@@ -1,8 +1,8 @@
import fs from "fs";
import path from "path";
import cheerio from 'cheerio';
import { parseSync, stringify } from 'svgson';
import tags from '../../../tags.json';
import { getContributors } from "./fetchAllContributors";
import { Contributor, getContributors } from "./fetchAllContributors";
const directory = path.join(process.cwd(), "../icons");
@@ -14,12 +14,13 @@ export function getAllNames() {
});
}
export async function getData(name:string) {
export async function getData(name: string) {
const fullPath = path.join(directory, `${name}.svg`);
const fileContents = fs.readFileSync(fullPath, "utf8");
const fileContent = fs.readFileSync(fullPath, "utf8");
const $ = cheerio.load(fileContents);
const content = $("svg").html();
const svgNodes = parseSync(fileContent);
const svgContent = svgNodes.children.map((node) => stringify(node)).join('');
const contributors = await getContributors(name);
@@ -27,12 +28,20 @@ export async function getData(name:string) {
name,
tags: tags[name] || [],
contributors,
src: fileContents,
content: content
src: fileContent,
content: svgContent
};
}
export async function getAllData() {
export interface IconData {
name: string
tags: string[]
contributors: Contributor[]
src: string
content: string
}
export async function getAllData(): Promise<IconData[]> {
const names = getAllNames();
return Promise.all(names.map((name) => getData(name)));
+2
View File
@@ -10,6 +10,7 @@ export const useKeyBindings = (
const [keyBindings] = useState(initialKeyBindings);
useEffect(() => {
// eslint-disable-next-line no-undef
document.addEventListener(
eventListener,
(event) => {
@@ -28,6 +29,7 @@ export const useKeyBindings = (
return () =>
Object.keys(keyBindings).forEach((keyBinding) =>
// eslint-disable-next-line no-undef
document.removeEventListener(eventListener, keyBindings[keyBinding])
);
}, []);
+2 -3
View File
@@ -52,8 +52,7 @@ const components = {
return (
<CodeBlock
//@ts-ignore
my={6}
marginY={6}
code={code}
language={language}
/>
@@ -78,7 +77,7 @@ const components = {
/>
),
inlineCode: InlineCode,
hr: (props) => <Divider my={4}/>,
hr: () => <Divider my={4} />,
a: ({children, href, ...rest}) => {
let link = href
const isExternal = link.startsWith('http')
+1 -1
View File
@@ -1,7 +1,7 @@
import Fuse from 'fuse.js';
import { useMemo } from 'react';
const useSearch = <T>(query = '', collection: T[], keys: Fuse.FuseOptionKey[]) => {
const useSearch = <T>(query = '', collection: T[], keys: Fuse.FuseOptionKey<T>[] = []) => {
const index = useMemo(() => {
return new Fuse(collection, {
threshold: 0.2,
-9
View File
@@ -17,15 +17,6 @@ class MyDocument extends Document {
<meta name="theme-color" content="#F56565" />
<meta name="google-site-verification" content="pr2dEIF-6zFdjXlDxutqEokeinrQNLx5qAjeVCqASDY" />
</Head>
<style jsx global>{`
* {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}
`}</style>
<body>
<ColorModeScript />
<Main />
-3
View File
@@ -1,6 +1,3 @@
import Layout from '../../components/Layout';
import Header from '../../components/Header';
import Head from 'next/head';
import fetchAllDocuments from '../../lib/fetchAllDocuments';
export { default } from '.';
+2 -2
View File
@@ -10,7 +10,7 @@ import { Box, Button, Text } from '@chakra-ui/react';
import { ArrowRight } from 'lucide-react'
import Link from 'next/link';
const DocPage = ({ doc, data, content }) => {
const DocPage = ({ doc, data }) => {
if (!data || !doc) return null
const nextPage = data.nextPage || []
@@ -69,7 +69,7 @@ const DocPage = ({ doc, data, content }) => {
export default DocPage
export async function getStaticProps({ params }) {
export async function getStaticProps() {
const allDocs = await fetchAllDocuments();
const doc = allDocs.find(({filename = ''}) => filename === 'index.md');
+1 -1
View File
@@ -38,7 +38,7 @@ const IconPage = ({ icon, data }) => {
return (
<Layout>
<IconDetailOverlay key={currentIcon.name} icon={currentIcon} close={onClose} />
<IconDetailOverlay key={currentIcon.name} icon={currentIcon} close={onClose} open />
<Header {...{ data }} />
<IconOverview {...{ data }} />
</Layout>
+11 -6
View File
@@ -1,16 +1,21 @@
import Layout from '../components/Layout';
import { getAllData } from '../lib/icons';
import { getAllData, IconData } from '../lib/icons';
import IconOverview from '../components/IconOverview';
import IconDetailOverlay from '../components/IconDetailOverlay';
import { useRouter } from 'next/router';
import Header from '../components/Header';
import MobileMenu from '../components/MobileMenu';
import { useEffect, useMemo } from 'react';
import { useMemo } from 'react';
import { GetStaticPropsResult, NextPage } from 'next';
const IndexPage = ({ data }) => {
interface HomePageProps {
data: IconData[]
}
const HomePage: NextPage<HomePageProps> = ({ data }) => {
const router = useRouter();
const getIcon = iconName => data.find(({ name }) => name === iconName) || {};
const getIcon = iconName => data.find(({ name }) => name === iconName);
const currentIcon = useMemo(() => {
return getIcon(router.query.iconName)
@@ -30,7 +35,7 @@ const IndexPage = ({ data }) => {
);
};
export async function getStaticProps() {
export async function getStaticProps(): Promise<GetStaticPropsResult<HomePageProps>> {
const data = await getAllData();
return {
@@ -40,4 +45,4 @@ export async function getStaticProps() {
};
}
export default IndexPage;
export default HomePage;
+3 -3
View File
@@ -5,9 +5,9 @@ import MobileMenu from '../components/MobileMenu';
import { Box, Heading, Text } from '@chakra-ui/react';
import { promises as fs } from 'fs';
import { resolve } from 'path';
import { GetStaticProps, NextPage } from 'next';
import { GetStaticProps } from 'next';
const LicensePage = ({ licenseText }) => {
const LicensePage = ({ licenseText }: { licenseText: string[] }): JSX.Element => {
return (
<Box>
<MobileMenu />
@@ -43,7 +43,7 @@ const LicensePage = ({ licenseText }) => {
export default LicensePage;
export const getStaticProps: GetStaticProps = async ({ params }) => {
export const getStaticProps: GetStaticProps = async () => {
const doc: string = await fs.readFile(resolve('../LICENSE'), 'utf-8');
const licenseText = doc
+14 -6
View File
@@ -2,12 +2,17 @@ import Layout from '../../components/Layout';
import HeadingNavigationProvider from '../../components/HeadingNavigationProvider';
import MobileMenu from '../../components/MobileMenu';
import { Stack } from '@chakra-ui/react';
import Package from '../../components/Package';
import packagesData from '../../lib/packageData';
import Package, { PackageItem } from '../../components/Package';
import packagesData from '../../data/packageData';
import { Heading } from '@chakra-ui/react';
import fetchPackages from '../../lib/fetchPackages';
import { GetStaticPropsResult } from 'next';
const PackagesPage = ({ packages }) => {
interface PackagesPageProps {
packages: PackageItem[]
}
const PackagesPage = ({ packages }: PackagesPageProps): JSX.Element => {
return (
<HeadingNavigationProvider>
<MobileMenu />
@@ -25,11 +30,11 @@ const PackagesPage = ({ packages }) => {
export default PackagesPage;
export async function getStaticProps({ params }) {
const packages = (await fetchPackages())
export async function getStaticProps(): Promise<GetStaticPropsResult<PackagesPageProps>> {
const packages: PackageItem[] = (await fetchPackages())
.filter(Boolean)
.filter(packageObj => !packageObj.private && packageObj.name in packagesData)
.map(({ name, description, flutter = false }) => {
.map(({ name, description, flutter }) => {
const packageDirectory = flutter ? 'lucide-flutter' : name;
return {
@@ -43,5 +48,8 @@ export async function getStaticProps({ params }) {
})
.sort((a, b) => a.order - b.order);
console.log(packages);
return { props: { packages } };
}
+8 -3
View File
@@ -2,15 +2,20 @@ import { getAllData } from '../src/lib/icons';
import { renderHook } from '@testing-library/react-hooks';
import useSearch from '../src/lib/useSearch';
const keys = [
{ name: 'name', weight: 2 },
{ name: 'tags', weight: 1 },
]
describe('Icon Overview', () => {
it('can search filter icons', async () => {
let allData = getAllData();
const allData = await getAllData();
const { result: result1, waitForNextUpdate: wait1 } = renderHook(() => useSearch(allData, ''));
const { result: result1 } = renderHook(() => useSearch('', allData, keys));
expect(result1.current).toHaveLength(allData.length);
const { result: result2, waitForNextUpdate: wait2 } = renderHook(() =>
useSearch(allData, 'airplay')
useSearch(allData, 'airplay', keys)
);
await wait2();
expect(result2.current).toHaveLength(2);
+3 -4
View File
@@ -1,14 +1,13 @@
import { act, fireEvent, screen } from '@testing-library/react';
import { screen, render } from '@testing-library/react';
import Index from '../src/pages/index';
import React from 'react';
import { render } from './test-utils';
import { getAllData } from '../src/lib/icons';
import App from '../src/pages/_app';
describe('App', () => {
it('renders without crashing', () => {
let allData = getAllData();
it('renders without crashing', async () => {
const allData = await getAllData();
render(<App Component={Index} pageProps={{ data: allData }} />);
expect(
screen.getByText('Simply beautiful open source icons, community-sourced')
-51
View File
@@ -1,51 +0,0 @@
import React from 'react';
import { render as defaultRender } from '@testing-library/react';
import { RouterContext } from 'next/dist/next-server/lib/router-context';
import { NextRouter } from 'next/router';
export * from '@testing-library/react';
// --------------------------------------------------
// Override the default test render with our own
//
// You can override the router mock like this:
//
// const { baseElement } = render(<MyComponent />, {
// router: { pathname: '/my-custom-pathname' },
// });
// --------------------------------------------------
type DefaultParams = Parameters<typeof defaultRender>;
type RenderUI = DefaultParams[0];
type RenderOptions = DefaultParams[1] & { router?: Partial<NextRouter> };
export function render(ui: RenderUI, { wrapper, router, ...options }: RenderOptions = {}) {
if (!wrapper) {
wrapper = ({ children }) => (
<RouterContext.Provider value={{ ...mockRouter, ...router }}>
{children}
</RouterContext.Provider>
);
}
return defaultRender(ui, { wrapper, ...options });
}
const mockRouter: NextRouter = {
basePath: '',
pathname: '/',
route: '/',
asPath: '/',
query: {},
push: jest.fn(),
replace: jest.fn(),
reload: jest.fn(),
back: jest.fn(),
prefetch: jest.fn(),
beforePopState: jest.fn(),
events: {
on: jest.fn(),
off: jest.fn(),
emit: jest.fn(),
},
isFallback: false,
};
File diff suppressed because one or more lines are too long