Merge remote-tracking branch 'origin/main' into feat/organized-content

This commit is contained in:
William Tran 2021-07-24 19:15:09 -04:00
commit 965093b6d0
41 changed files with 1388 additions and 158 deletions

36
.drone.yml Normal file
View File

@ -0,0 +1,36 @@
---
kind: pipeline
type: docker
name: node14
steps:
- name: install-deps
image: node:14
commands:
- npm install
- name: lint
image: node:14
depends_on:
- install-deps
commands:
- npm run lint
- name: build
image: node:14
depends_on:
- install-deps
commands:
- npm run build
- name: export
image: node:14
depends_on:
- build
commands:
- npm run export
trigger:
event:
exclude:
- pull_request #avoid double build on PRs

View File

@ -1,49 +0,0 @@
default:
image: node:14
cache:
paths:
- node_modules/
- .next
stages:
- build
- staging
variables:
NEXT_PUBLIC_BASE_PATH: '/~a3thakra/csc'
install_deps:
stage: .pre
script:
- npm install
lint:
stage: build
script:
- npm run lint
build:
stage: build
script:
- npm run build
staging:
stage: staging
script:
- npm run export
artifacts:
paths:
- out
only:
refs:
- main
deploy_staging:
stage: .post
needs: ["staging"]
script:
- 'curl -XPOST -H "Authorization: Basic $STAGING_SECRET" "https://csclub.uwaterloo.ca/~a3thakra/csc/"'
only:
refs:
- main

View File

@ -0,0 +1,7 @@
.bubble {
padding: calc(36rem / 16) 0;
}
.bubble:nth-child(odd) {
background-color: var(--blue-1-20);
}

11
components/Bubble.tsx Normal file
View File

@ -0,0 +1,11 @@
import React from "react";
import { DefaultLayout } from "./DefaultLayout";
import styles from "./Bubble.module.css";
export default function Bubble(props: { children: React.ReactNode }) {
return (
<div className={styles.bubble}>
<DefaultLayout>{props.children}</DefaultLayout>
</div>
);
}

View File

@ -0,0 +1,21 @@
.header {
color: var(--blue-2);
font-weight: 600;
font-size: calc(36rem / 16);
margin-bottom: calc(12rem / 16);
}
.socialLinks {
margin: calc(36rem / 16) 0;
line-height: 0;
}
@media only screen and (max-width: calc(768rem / 16)) {
.header {
font-size: calc(24rem / 16);
}
.socialLinks {
margin: 1rem 0;
}
}

View File

@ -0,0 +1,25 @@
import React from "react";
import styles from "./ConnectWithUs.module.css";
import { SocialLinks } from "./SocialLinks";
import { Link } from "./Link";
export function ConnectWithUs() {
return (
<section>
<h1 className={styles.header}>Connect with us!</h1>
<p>
Drop by any of our social media outlets to learn more about us, keep
up-to-date with our upcoming events, or to chat with our members!
</p>
<div className={styles.socialLinks}>
<SocialLinks color="gradient" size="big" />
</div>
{/* TODO: fix feedback form link */}
<p>
Send feedback through our <Link href="#">Feedback Form</Link>
</p>
</section>
);
}

View File

@ -0,0 +1,6 @@
.defaultLayout {
margin: 0 auto;
max-width: calc(800rem / 16);
padding: 0 calc(20rem / 16);
padding-bottom: calc(20rem / 16);
}

View File

@ -0,0 +1,6 @@
import React from "react";
import styles from "./DefaultLayout.module.css";
export function DefaultLayout(props: { children: React.ReactNode }) {
return <div className={styles.defaultLayout}>{props.children}</div>;
}

View File

@ -0,0 +1,25 @@
.container form {
box-sizing: border-box;
}
.header {
color: var(--blue-2);
font-weight: 600;
font-size: calc(36rem / 16);
margin-bottom: calc(12rem / 16);
}
.button {
margin-top: calc(34rem / 16);
display: block;
}
@media only screen and (max-width: calc(768rem / 16)) {
.header {
font-size: calc(24rem / 16);
}
.button {
margin-top: calc(20rem / 16);
}
}

View File

@ -0,0 +1,19 @@
import React from "react";
import styles from "./EmailSignup.module.css";
import { Button } from "./Button";
import { Input } from "./Input";
export function EmailSignup() {
return (
<section className={styles.container}>
<h1 className={styles.header}>Join Our Mailing List!</h1>
<form className={styles.form} action="">
<Input type="text" placeholder="Full Name*" required />
<Input type="email" placeholder="Email*" required />
<Button type="submit" className={styles.button}>
Subscribe
</Button>
</form>
</section>
);
}

View File

@ -0,0 +1,37 @@
.input {
display: block;
width: 100%;
margin: calc(21rem / 16) 0;
padding: calc(10rem / 16) calc(32rem / 16);
box-sizing: border-box;
border: 0;
border-radius: calc(20rem / 16);
background-color: var(--grey-1-24);
font-size: calc(18rem / 16);
line-height: calc(30rem / 16);
color: var(--grey-3);
}
.input::placeholder {
color: var(--grey-2);
font-weight: 700;
}
.input:is(:active, :hover, :focus) {
box-sizing: border-box;
border: calc(3rem / 16) solid var(--blue-1);
border-radius: calc(20rem / 16);
outline: none;
padding: calc(7rem / 16) calc(28rem / 16);
}
/* TODO: make this only happen if the form is clicked on? */
/* .form input:invalid {
box-sizing: border-box;
border: calc(3rem / 16) solid var(--red);
border-radius: calc(20rem / 16);
outline: none;
padding: calc(7rem / 16) calc(28rem / 16);
} */

8
components/Input.tsx Normal file
View File

@ -0,0 +1,8 @@
import React, { InputHTMLAttributes } from "react";
import styles from "./Input.module.css";
export function Input(props: InputHTMLAttributes<HTMLInputElement>) {
return (
<input {...props} className={`${styles.input} ${props.className ?? ""}`} />
);
}

View File

@ -13,26 +13,36 @@
justify-content: space-between;
align-items: center;
width: stretch;
width: 100%;
max-width: calc(1440rem / 16);
height: auto;
padding: calc(28rem / 16) calc(136rem / 16);
}
.logo {
.logo,
.logoMobile {
display: flex;
justify-content: center;
align-items: center;
}
.logo:hover {
.logo:hover,
.logoMobile:hover {
cursor: pointer;
}
.logoMobile {
display: none;
}
.logo img {
width: calc(96rem / 16);
}
.hamburger {
display: none;
}
.navMenu {
display: inline-flex;
flex-direction: row;
@ -60,7 +70,7 @@
color: var(--blue-2);
}
.navMenu > li:hover > a {
.navMenu > li > a:hover {
color: var(--blue-2);
font-weight: 600;
}
@ -79,15 +89,19 @@
padding: 1rem;
}
.dropdownWrapper {
.itemWrapper {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.dropdownIcon {
display: none;
}
.dropdown {
visibility: visible;
visibility: hidden;
display: flex;
flex-direction: column;
@ -107,37 +121,33 @@
font-size: calc(14rem / 16);
}
.dropdown > li {
.dropdown li {
width: 100%;
}
.dropdown > li > a {
.dropdown li a {
padding: calc(8rem / 16);
width: 100%;
box-sizing: border-box;
}
.dropdown > li:hover > a,
.dropdown > li > a:focus {
.dropdown li:hover a,
.dropdown li a:focus {
background-color: var(--blue-1-20);
}
.dropdown > li:first-child > a {
.dropdown li:first-child a {
padding-top: 1rem;
border-radius: calc(8rem / 16) calc(8rem / 16) 0 0;
}
.dropdown > li:last-child > a {
.dropdown li:last-child a {
padding-bottom: 1rem;
border-radius: 0 0 calc(8rem / 16) calc(8rem / 16);
}
.navMenu > li .dropdown {
visibility: hidden;
}
.navMenu > li:hover .dropdown,
.navMenu > li:focus-within .dropdown {
.navMenu li:hover .dropdown,
.navMenu li:focus-within .dropdown {
visibility: visible;
}
@ -149,3 +159,214 @@
padding: calc(28rem / 16) calc(64rem / 16);
}
}
@media screen and (max-width: calc(768rem / 16)) {
.navContent {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: ". logo hamburger";
column-gap: 0;
justify-items: end;
align-items: center;
padding: calc(20rem / 16);
}
.logo {
grid-area: logo;
justify-self: center;
}
.logoMobile {
display: inline-flex;
justify-content: center;
align-items: center;
margin-bottom: calc(20rem / 16);
}
.logo img,
.logoMobile img {
width: calc(80rem / 16);
}
.logoMobile img {
padding: 1rem;
}
.hamburger {
grid-area: hamburger;
display: flex;
justify-content: center;
align-items: center;
padding: calc(12rem / 16);
width: calc(36rem / 16);
box-sizing: content-box;
border: none;
background: none;
}
.hamburger:hover {
cursor: pointer;
}
.navMobileBackground {
position: fixed;
visibility: hidden;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 20;
background-color: var(--navbar-gray);
opacity: 0;
transition: 0.5s;
}
.navMenuWrapper {
position: fixed;
width: calc(288rem / 16);
box-sizing: border-box;
height: 100%;
top: 0;
right: 0;
overflow: auto;
z-index: 30;
padding: calc(calc(64rem / 16) - 1rem);
padding-left: calc(calc(78rem / 16) - 1rem);
background-color: var(--off-white);
transform: translateX(100vw);
transition: 0.5s;
}
.navMenu {
display: flex;
flex-direction: column;
gap: calc(4rem / 16);
width: auto;
font-size: calc(18rem / 16);
font-weight: 500;
text-align: left;
}
.navMenu > .itemWrapper {
display: grid;
grid-template-columns: 1fr auto;
grid-template-areas:
"link button"
"dropdown dropdown";
column-gap: 0;
row-gap: 0;
justify-items: start;
align-items: center;
width: 100%;
}
.navMenu > .itemWrapper > a {
grid-area: link;
}
.dropdownIcon {
grid-area: button;
justify-self: end;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
box-sizing: content-box;
border: none;
background: none;
}
.dropdownIcon:hover {
cursor: pointer;
}
.dropdown {
grid-area: dropdown;
display: none;
visibility: visible;
justify-content: space-between;
align-items: start;
position: static;
margin: 0;
margin-left: calc(18rem / 16);
margin-bottom: calc(18rem / 16);
border-radius: 0;
background: none;
box-shadow: none;
font-size: 1rem;
}
.dropdown > .itemWrapper {
align-items: start;
}
.dropdown li {
width: auto;
text-align: left;
}
.dropdown li a {
width: auto;
}
.dropdown li:hover a,
.dropdown li a:focus {
background: none;
}
.dropdown li:hover a {
color: default;
font-weight: default;
}
.dropdown li:first-child a {
padding-top: calc(8rem / 16);
border-radius: 0;
}
.dropdown li:last-child a {
padding-bottom: calc(8rem / 16);
border-radius: 0;
}
.show {
display: block;
}
.show.navMobileBackground {
visibility: visible;
opacity: 100%;
}
.show.navMobileBackground + .navMenuWrapper {
transform: translateX(0);
}
.rotate {
transform: rotate(180deg);
}
}

View File

@ -1,19 +1,19 @@
import React from "react";
import React, { useReducer } from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import { Image } from "./Image";
import styles from "./Navbar.module.css";
interface NavLink {
type Menu = {
name: string;
route: string;
submenu?: {
name: string;
route: string;
}[];
}
}[];
const menu: NavLink[] = [
const menu: Menu = [
{
name: "Home",
route: "/",
@ -66,28 +66,146 @@ const menu: NavLink[] = [
},
{
name: "CS Club Wiki",
route: "https://wiki.csclub.uwaterloo.ca/",
route: "https://wiki.csclub.uwaterloo.ca",
},
],
},
];
function NavItem(props: NavLink) {
export function Navbar() {
const router = useRouter();
const externalLink =
const [state, dispatch] = useReducer(reducer, initialState);
return (
<nav className={styles.navbar}>
<div className={styles.navContent}>
<Link href="/">
<a className={styles.logo}>
<Image src="/images/logo-icon.svg" alt="CSC Logo" />
</a>
</Link>
<button
className={styles.hamburger}
onClick={() => dispatch({ type: "open", route: router.pathname })}
>
<Image src="/images/hamburger.svg" alt="Menu" />
</button>
<div
className={
state.isNavOpen
? `${styles.navMobileBackground} ${styles.show}`
: styles.navMobileBackground
}
onClick={() => dispatch({ type: "close" })}
/>
<div className={styles.navMenuWrapper}>
<Link href="/">
<a
className={styles.logoMobile}
onClick={() => dispatch({ type: "close" })}
>
<Image src="/images/logo-icon.svg" alt="CSC Logo" />
</a>
</Link>
<ul className={styles.navMenu}>
{menu.map((item) => {
return (
<li className={styles.itemWrapper} key={item.name}>
<NavItem
name={item.name}
route={item.route}
submenu={item.submenu}
mainRouteActive={state.activeSubmenus.has(
getMainRoute(item.route)
)}
onClose={() => dispatch({ type: "close" })}
onToggle={(route) => dispatch({ type: "toggle", route })}
/>
</li>
);
})}
</ul>
</div>
</div>
</nav>
);
}
interface MobileState {
isNavOpen: boolean;
activeSubmenus: Set<string>; // strings are NavLink routes
}
type MobileAction =
| { type: "open"; route: string }
| { type: "toggle"; route: string }
| { type: "close" };
const initialState: MobileState = {
isNavOpen: false,
activeSubmenus: new Set(),
};
function reducer(state: MobileState, action: MobileAction): MobileState {
switch (action.type) {
case "open":
return {
isNavOpen: true,
activeSubmenus: new Set([getMainRoute(action.route)]),
};
case "toggle": {
const newSet = new Set(state.activeSubmenus);
if (state.activeSubmenus.has(getMainRoute(action.route))) {
newSet.delete(getMainRoute(action.route));
} else {
newSet.add(getMainRoute(action.route));
}
return {
isNavOpen: state.isNavOpen,
activeSubmenus: newSet,
};
}
case "close":
return initialState;
}
}
interface NavItemProps {
name: string;
route: string;
submenu?: {
name: string;
route: string;
}[];
mainRouteActive: boolean;
onToggle(route: string): void;
onClose(): void;
}
function NavItem(props: NavItemProps) {
const router = useRouter();
const isCurrentPage =
router.pathname === props.route ||
(props.submenu != null &&
router.pathname.startsWith(getMainRoute(props.route)));
const isExternalLink =
props.route.includes("http://") || props.route.includes("https://");
function handleClick() {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
props.onClose();
}
return (
<>
{externalLink ? (
{isExternalLink ? (
<a
href={props.route}
target="_blank"
rel="noopener noreferrer"
onClick={() => {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
}}
onClick={handleClick}
>
{props.name}
</a>
@ -95,61 +213,57 @@ function NavItem(props: NavLink) {
<Link href={props.route}>
<a
title={props.name}
className={
router.pathname === props.route ||
((props.submenu?.length ?? 0) > 0 &&
router.pathname.startsWith(props.route))
? styles.currentPage
: ""
}
onClick={() => {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
}}
className={isCurrentPage ? styles.currentPage : ""}
onClick={handleClick}
>
{props.name}
</a>
</Link>
)}
{(props.submenu?.length ?? 0) > 0 ? (
<ul className={styles.dropdown}>
{props.submenu?.map((item) => {
return (
<li className={styles.dropdownWrapper} key={item.name}>
<NavItem name={item.name} route={item.route} />
</li>
);
})}
</ul>
<>
<button
className={
props.mainRouteActive
? `${styles.dropdownIcon} ${styles.rotate}`
: styles.dropdownIcon
}
onClick={() => props.onToggle(props.route)}
>
<Image src="/images/dropdown-icon.svg" alt="Dropdown Icon" />
</button>
<ul
className={
props.mainRouteActive
? `${styles.dropdown} ${styles.show}`
: styles.dropdown
}
>
{props.submenu?.map((item) => {
return (
<li className={styles.itemWrapper} key={item.name}>
<NavItem
name={item.name}
route={item.route}
mainRouteActive={props.mainRouteActive}
onClose={() => props.onClose()}
onToggle={(route) => props.onToggle(route)}
/>
</li>
);
})}
</ul>
</>
) : null}
</>
);
}
export function Navbar() {
return (
<nav className={styles.navbar}>
<div className={styles.navContent}>
<Link href="/">
<a className={styles.logo}>
<Image src="/images/logo-icon.png" alt="CSC Logo" />
</a>
</Link>
<ul className={styles.navMenu}>
{menu.map((item) => {
return (
<li className={styles.dropdownWrapper} key={item.name}>
<NavItem
name={item.name}
route={item.route}
submenu={item.submenu}
/>
</li>
);
})}
</ul>
</div>
</nav>
);
function getMainRoute(route: string) {
if (route === "/") {
return "/";
} else if (route.startsWith("http://") || route.startsWith("https://")) {
return route;
}
return "/" + route.split("/")[1];
}

View File

@ -1,12 +1,15 @@
.link,
.links {
display: flex;
display: inline-flex;
align-items: center;
justify-content: center;
}
.links > * {
margin: 0 calc(10rem / 16);
.link {
margin-left: calc(20rem / 16);
}
.link:first-child {
margin-left: 0;
}
.big > * {

89
content/about/index.mdx Normal file
View File

@ -0,0 +1,89 @@
import Bubble from "./../../components/Bubble";
<Bubble>
CS Club is working towards bridging the gap between each and every CS student,
to support their undergraduate experience and to provide a community that
students can belong to and identify with. With hundreds of CS students joining
Waterloo every year, CS Club aims to run events that encourage students to
connect and socialize, to increase technical and academic interest with
workshops and talks, and to provide a safe environment for academic learning and
growth.
</Bubble>
<Bubble>
## Our <span>Vision</span>
1. Academic: Promoting the knowledge and interest of Computer Science, as well
as supporting students throughout their academic experiences.
2. Career: Providing career guidance and resources to help students gain
experience and knowledge for their own job search.
3. Community: Encouraging interpersonal relationships through community building
and social events for all computing students.
</Bubble>
<Bubble>
## Our <span>Story</span>
We are students ourselves, coming from all computing backgrounds —
Computer Science, Software Engineering, CFM, Mechatronics Engineering, and more.
CS Club was born from an unfulfilled need; we felt that although there are so
many students at UW that are interested in CS, there wasn't a proper support
network in place. We lacked the cohorts provided to engineers, and we felt
disconnected from one another.
By recreating what CS Club means for our community, we're passionate about
helping students redefine their university experience here at Waterloo.
</Bubble>
<Bubble>
## Our <span>Mission</span>
The CS Club team is devoted to providing you with all the resources you could
need as a student. We want to create a community that members can call home, to
make it a place where you can reach out for career advice, for academic help, or
even just to socialize. To fulfil this mission, we'll be running events and
initiatives throughout the term, so please check out our [Events](/events/current)
page to stay updated!
</Bubble>
<Bubble>
## Our <span>Office</span>
The CS Club office is located at room **MC 3036/3037**, in the Math & Computer
Building of the University of Waterloo.
- An office favorite is our $0.50 pop for members. We have a fridge in the
office which is stocked with many different kinds of pop.
- We have lots of informative books, 5 computer terminals, and an array of
knowledgeable people to talk to.
Come visit us on campus in our office! Meet new members and find out what's new
in the club.
<address>
Computer Science Club <br />
Math & Computer 3036/3037 <br />
University of Waterloo <br />
200 University Avenue West <br />
Waterloo, ON N2L 3G1 <br />
Canada
Our office phone number is [(519) 888-4567 x33870](tel:+15198884567,33870)
</address>
</Bubble>

85
content/get-involved.mdx Normal file
View File

@ -0,0 +1,85 @@
**Everyone at the University of Waterloo is welcome to come to our events and to
use our resources!** Feel free to join our communities and chat with our
members. However, if you wanted to officially become a member or support our
vision of creating a supportive environment for all computing students, there's
a bunch of ways you can join and help out.
## How to Join
### General Membership
<details>
<summary>In-person Term</summary>
1. Drop by our office in **MC 3036/3037** with
- your WatCard, and
- $2 for term that you would like to pay for
2. Sign our [Machine Usage Agreement](https://csclub.uwaterloo.ca/services/machine_usage)
That's all! After your account created, you'll have access to all the
[services](https://csclub.uwaterloo.ca/services/) available to members.
#### Membership Renewal
If you are already a member of the CSC and want to renew your membership, you
can do so by coming in person to our office.
</details>
<details>
<summary>Online Term</summary>
Email the CSC Systems Committee at
[syscom@csclub.uwaterloo.ca](mailto:syscom@csclub.uwaterloo.ca) from your
University of Waterloo email address with the following:
1. a scan or photograph copy of your **WatCard**,
2. your **WatIAM userid**, and
3. your acknowledgement of having read, understood, and agreeing with our 
[Machine Usage Agreement](https://csclub.uwaterloo.ca/services/machine_usage).
#### Membership Renewal
For this online term, you do not need to pay the $2 fee to renew your
membership. We have extended the memberships of all members who had already
previously paid for membership or have joined CS Club during an online term.
</details>
### Executive Committees
Are you interested in using your skills to get involved with CSC? We have
committees covering everything from design to development, so no matter your
interests, weve got a place for you.
**CSC hires at the end of every term**, so make sure to stay connected through
social media to keep up to date on when applications open!
#### Programme Committee
- In charge of planning, advertising, and running all events hosted by CSC.
- Voices concerns/ideas on behalf of the CS community.
#### Website Committee
- Creates functional and modern design for the CSC website.
- Builds and maintains the static website, updating content for events and news.
#### Systems Committee
- Maintaining all services that CSC provides which includes file share, DNS,
mail, configuration for IRC, Mattermost, Git hosting.
- Managing mirrors used by large public organizations and 1000s of people
internationally.
### Elected Roles
Each term the CSC holds elections to determine the executive council.
- President
- Vice-President
- Assistant Vice-President
- Treasurer
To find out when and where the next elections will be held, keep an eye on on the [News](/).
For details on the elections, see the [Constitution](https://csclub.uwaterloo.ca/about/constitution).

164
package-lock.json generated
View File

@ -11,8 +11,8 @@
"@mdx-js/react": "^1.6.22",
"@next/mdx": "^10.1.3",
"date-fns": "^2.11.1",
"gray-matter": "^4.0.2",
"next": "^10.0.0",
"next-mdx-remote": "^3.0.2",
"prettier": "^2.3.0",
"react": "17.0.1",
"react-dom": "17.0.1",
@ -30,6 +30,7 @@
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",
"gray-matter": "^4.0.3",
"postcss": "^8.3.0",
"postcss-calc": "^8.0.0",
"postcss-flexbugs-fixes": "^5.0.2",
@ -1371,6 +1372,7 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"dependencies": {
"sprintf-js": "~1.0.2"
}
@ -2574,6 +2576,15 @@
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw="
},
"node_modules/esbuild": {
"version": "0.11.23",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.11.23.tgz",
"integrity": "sha512-iaiZZ9vUF5wJV8ob1tl+5aJTrwDczlvGP0JoMmnpC2B0ppiMCu8n8gmy5ZTGl5bcG081XBVn+U+jP+mPFm5T5Q==",
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
}
},
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -2908,6 +2919,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true,
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
@ -3009,6 +3021,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"dependencies": {
"is-extendable": "^0.1.0"
},
@ -3307,6 +3320,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
"integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==",
"dev": true,
"dependencies": {
"js-yaml": "^3.13.1",
"kind-of": "^6.0.2",
@ -3821,6 +3835,7 @@
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -4068,6 +4083,7 @@
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"dev": true,
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@ -4127,6 +4143,7 @@
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -4529,6 +4546,75 @@
}
}
},
"node_modules/next-mdx-remote": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-3.0.2.tgz",
"integrity": "sha512-imLrrw6c/Hi1BKRyJE9yLhk45N5zzw+/CxSQRHOAByYUSOhd+DNjUaqm2jtd+/GgxJeYB1d3fJPXmvUZTez1MQ==",
"dependencies": {
"@mdx-js/mdx": "^1.6.22",
"@mdx-js/react": "^1.6.22",
"esbuild": "^0.11.12",
"pkg-dir": "^5.0.0"
},
"peerDependencies": {
"react": ">=16.x <=17.x",
"react-dom": ">=16.x <=17.x"
}
},
"node_modules/next-mdx-remote/node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/next-mdx-remote/node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dependencies": {
"p-locate": "^5.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/next-mdx-remote/node_modules/p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dependencies": {
"p-limit": "^3.0.2"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/next-mdx-remote/node_modules/pkg-dir": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz",
"integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==",
"dependencies": {
"find-up": "^5.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/next/node_modules/postcss": {
"version": "8.1.7",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.1.7.tgz",
@ -7312,6 +7398,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
"integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==",
"dev": true,
"dependencies": {
"extend-shallow": "^2.0.1",
"kind-of": "^6.0.0"
@ -7481,7 +7568,8 @@
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"node_modules/stacktrace-parser": {
"version": "0.1.10",
@ -7637,6 +7725,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
"integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -9386,6 +9475,7 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
}
@ -10327,6 +10417,11 @@
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw="
},
"esbuild": {
"version": "0.11.23",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.11.23.tgz",
"integrity": "sha512-iaiZZ9vUF5wJV8ob1tl+5aJTrwDczlvGP0JoMmnpC2B0ppiMCu8n8gmy5ZTGl5bcG081XBVn+U+jP+mPFm5T5Q=="
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -10566,7 +10661,8 @@
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
},
"esquery": {
"version": "1.4.0",
@ -10641,6 +10737,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -10876,6 +10973,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
"integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==",
"dev": true,
"requires": {
"js-yaml": "^3.13.1",
"kind-of": "^6.0.2",
@ -11221,7 +11319,8 @@
"is-extendable": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
"dev": true
},
"is-extglob": {
"version": "2.1.1",
@ -11378,6 +11477,7 @@
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@ -11421,7 +11521,8 @@
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true
},
"levn": {
"version": "0.4.1",
@ -11750,6 +11851,52 @@
}
}
},
"next-mdx-remote": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-3.0.2.tgz",
"integrity": "sha512-imLrrw6c/Hi1BKRyJE9yLhk45N5zzw+/CxSQRHOAByYUSOhd+DNjUaqm2jtd+/GgxJeYB1d3fJPXmvUZTez1MQ==",
"requires": {
"@mdx-js/mdx": "^1.6.22",
"@mdx-js/react": "^1.6.22",
"esbuild": "^0.11.12",
"pkg-dir": "^5.0.0"
},
"dependencies": {
"find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"requires": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
}
},
"locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"requires": {
"p-locate": "^5.0.0"
}
},
"p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"requires": {
"p-limit": "^3.0.2"
}
},
"pkg-dir": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz",
"integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==",
"requires": {
"find-up": "^5.0.0"
}
}
}
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
@ -13825,6 +13972,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
"integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==",
"dev": true,
"requires": {
"extend-shallow": "^2.0.1",
"kind-of": "^6.0.0"
@ -13950,7 +14098,8 @@
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"stacktrace-parser": {
"version": "0.1.10",
@ -14076,7 +14225,8 @@
"strip-bom-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
"integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI="
"integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=",
"dev": true
},
"strip-json-comments": {
"version": "3.1.1",

View File

@ -6,16 +6,16 @@
"build": "next build",
"start": "next start",
"export": "next export",
"lint": "eslint \"{pages,components}/**/*.{js,ts,tsx,jsx}\" --quiet",
"lint:fix": "eslint \"{pages,components}/**/*.{js,ts,tsx,jsx}\" --quiet --fix"
"lint": "eslint \"{pages,components,lib}/**/*.{js,ts,tsx,jsx}\" --quiet",
"lint:fix": "eslint \"{pages,components,lib}/**/*.{js,ts,tsx,jsx}\" --quiet --fix"
},