From 090abbfcca354cf79ca59d5f09c891286121b3e5 Mon Sep 17 00:00:00 2001 From: Minh Duong Date: Tue, 10 Sep 2024 00:15:22 -0500 Subject: [PATCH] Globalize more components, wip fall ctf events page --- _global/components/BaseHead.astro | 5 +- .../src => _global}/components/Mdx/img.astro | 0 .../components/Mdx/index.astro | 0 .../components/Mdx/table.astro | 0 _global/content/events/fallctf/2024/index.mdx | 10 --- {sigpwny.com/src => _global}/styles/md.css | 22 ++++- fallctf.com/package-lock.json | 29 ++++++- fallctf.com/package.json | 1 + fallctf.com/src/components/Event/Card.astro | 58 ------------- fallctf.com/src/components/FallCTFLogo.tsx | 15 ++++ fallctf.com/src/components/Nav.tsx | 0 fallctf.com/src/layouts/Base.astro | 2 + fallctf.com/src/layouts/Event.astro | 70 ++++++++++++++++ fallctf.com/src/pages/2024.astro | 34 ++++++++ fallctf.com/src/pages/[...slug].astro | 49 +++++++++++ fallctf.com/src/pages/[...year].astro | 24 ------ fallctf.com/src/pages/index.astro | 35 ++------ fallctf.com/src/styles/fallctf.css | 83 +++++++++++++++++++ sigpwny.com/src/layouts/Base.astro | 2 +- sigpwny.com/src/layouts/Meeting.astro | 2 +- sigpwny.com/src/pages/[...slug]/index.astro | 2 +- .../src/pages/meetings/[...slug]/index.astro | 2 +- .../pages/publications/[...slug]/index.astro | 2 +- 23 files changed, 317 insertions(+), 130 deletions(-) rename {sigpwny.com/src => _global}/components/Mdx/img.astro (100%) rename {sigpwny.com/src => _global}/components/Mdx/index.astro (100%) rename {sigpwny.com/src => _global}/components/Mdx/table.astro (100%) rename {sigpwny.com/src => _global}/styles/md.css (86%) delete mode 100644 fallctf.com/src/components/Event/Card.astro create mode 100644 fallctf.com/src/components/FallCTFLogo.tsx create mode 100644 fallctf.com/src/components/Nav.tsx create mode 100644 fallctf.com/src/layouts/Event.astro create mode 100644 fallctf.com/src/pages/2024.astro create mode 100644 fallctf.com/src/pages/[...slug].astro delete mode 100644 fallctf.com/src/pages/[...year].astro diff --git a/_global/components/BaseHead.astro b/_global/components/BaseHead.astro index 78f28d27f..459f5ab19 100644 --- a/_global/components/BaseHead.astro +++ b/_global/components/BaseHead.astro @@ -3,7 +3,7 @@ import { ViewTransitions } from 'astro:transitions'; import { type SiteName, getSiteConfig } from '../configs'; export interface HeadProps { - site_name: SiteName; + site_name?: SiteName; title?: string; description?: string; image?: string; @@ -16,6 +16,9 @@ export interface HeadProps { const props = Astro.props as HeadProps; +if (!props.site_name) { + throw new Error("site_name is required in BaseHead"); +} const siteConfig = getSiteConfig(props.site_name); const siteName = siteConfig.title; diff --git a/sigpwny.com/src/components/Mdx/img.astro b/_global/components/Mdx/img.astro similarity index 100% rename from sigpwny.com/src/components/Mdx/img.astro rename to _global/components/Mdx/img.astro diff --git a/sigpwny.com/src/components/Mdx/index.astro b/_global/components/Mdx/index.astro similarity index 100% rename from sigpwny.com/src/components/Mdx/index.astro rename to _global/components/Mdx/index.astro diff --git a/sigpwny.com/src/components/Mdx/table.astro b/_global/components/Mdx/table.astro similarity index 100% rename from sigpwny.com/src/components/Mdx/table.astro rename to _global/components/Mdx/table.astro diff --git a/_global/content/events/fallctf/2024/index.mdx b/_global/content/events/fallctf/2024/index.mdx index 64953cb6b..48cd1eb86 100644 --- a/_global/content/events/fallctf/2024/index.mdx +++ b/_global/content/events/fallctf/2024/index.mdx @@ -66,14 +66,4 @@ The beginner division is intended for underclassmen students who do not have muc If either you or your teammate have taken CS 341 (previously CS 241), ECE 391, or have played in three or more CTFs, then your team should be registered in the Advanced division. If you have some experience or would like to compete in the Advanced Division, teams can opt into the Advanced division! Otherwise, teams will play in the Beginner division. ## Frequently Asked Questions -**Q:** What is a CTF? -**A:** CTF is an acronym for "capture-the-flag," which in the context of the cybersecurity field are competitions where teams solve security-related challenges to find a flag (usually a string of text). The flag can then be submitted to the competition platform for points, and the teams compete against each other for the most points! -**Q:** How are tie-breakers determined? -**A:** The leaderboard is sorted first by the team with the most points. If teams have the same number of points, then the team who submitted their most recent flag earlier wins the tie-break. - -**Q:** How do I form a team? -**A:** By the day before the competition, we will be opening team registration on our competition platform. Feel free to find your team partner beforehand. We will also have multiple opportunities before and during the event to find and form teams! - -**Q:** I heard that there will be companies present. Do I need to dress up or prepare a resume? -**A:** We do not require a dress code and the expectation is that most people will be dressed casually. We will be offering a resume book to our sponsors and a resume PDF upload form will be provided during the event. If you need help preparing a resume, feel free to ask for advice in our Discord or take advantage of campus career resources! diff --git a/sigpwny.com/src/styles/md.css b/_global/styles/md.css similarity index 86% rename from sigpwny.com/src/styles/md.css rename to _global/styles/md.css index 3afba3531..f00eba9dd 100644 --- a/sigpwny.com/src/styles/md.css +++ b/_global/styles/md.css @@ -7,6 +7,25 @@ padding-top: 1rem; padding-bottom: 0.25rem; } +.md-root h1, +.md-root h2, +.md-root h3 { + font-weight: bold; +} +.md-root h1 { + font-size: 2.25rem; + line-height: 2.5rem; + margin-bottom: 0.5rem; +} +.md-root h2 { + font-size: 1.875rem; + line-height: 2.25rem; + margin-bottom: 0.5rem; +} +.md-root h3 { + font-size: 1.5rem; + line-height: 2rem; +} .md-root h1:first-child, .md-root h2:first-child, .md-root h3:first-child, @@ -84,7 +103,4 @@ } .md-root tbody tr:last-child td:last-child { border-radius: 0 0 0.75rem 0; -} -.md-root .gatsby-resp-image-wrapper { - @apply mb-2; } \ No newline at end of file diff --git a/fallctf.com/package-lock.json b/fallctf.com/package-lock.json index 4407ac7bb..6daa8822c 100644 --- a/fallctf.com/package-lock.json +++ b/fallctf.com/package-lock.json @@ -19,6 +19,7 @@ "@floating-ui/react": "^0.26.23", "astro": "^4.14.3", "dayjs": "^1.11.13", + "framer-motion": "^11.5.4", "rehype-katex": "^7.0.1", "remark-math": "^6.0.0", "tailwindcss": "^3.4.10", @@ -4267,6 +4268,31 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "11.5.4", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.5.4.tgz", + "integrity": "sha512-E+tb3/G6SO69POkdJT+3EpdMuhmtCh9EWuK4I1DnIC23L7tFPrl8vxP+LSovwaw6uUr73rUbpb4FgK011wbRJQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -8631,8 +8657,7 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "license": "0BSD", - "optional": true + "license": "0BSD" }, "node_modules/type-fest": { "version": "2.19.0", diff --git a/fallctf.com/package.json b/fallctf.com/package.json index 67d922014..ebd68737d 100644 --- a/fallctf.com/package.json +++ b/fallctf.com/package.json @@ -28,6 +28,7 @@ "@floating-ui/react": "^0.26.23", "astro": "^4.14.3", "dayjs": "^1.11.13", + "framer-motion": "^11.5.4", "rehype-katex": "^7.0.1", "remark-math": "^6.0.0", "tailwindcss": "^3.4.10", diff --git a/fallctf.com/src/components/Event/Card.astro b/fallctf.com/src/components/Event/Card.astro deleted file mode 100644 index c8c8e6c71..000000000 --- a/fallctf.com/src/components/Event/Card.astro +++ /dev/null @@ -1,58 +0,0 @@ ---- -import { Picture } from 'astro:assets'; -import type { ImageMetadata } from 'astro'; -import type { CollectionEntry } from 'astro:content'; - -interface Props { - input: CollectionEntry<'events'>; - size?: 'small' | 'large'; -}; - -const { input, size } = Astro.props; -const event = input.data as CollectionEntry<'events'>['data']; -const { title, card_image } = event; - -const colRowSpan = (size: Props['size']) => { - switch (size) { - case 'small': - return 'col-span-1 row-span-1'; - case 'large': - return 'col-span-2 row-span-2'; - default: - return 'col-span-1 row-span-1'; - } -}; - -// heading, title, image, overlay_image, card_image, link ---- -
-
- {card_image?.background && ( -
- -
- )} - { - card_image?.background_color && ( -
- ) - } - {card_image?.foreground && -
- -
- } -
-
\ No newline at end of file diff --git a/fallctf.com/src/components/FallCTFLogo.tsx b/fallctf.com/src/components/FallCTFLogo.tsx new file mode 100644 index 000000000..78c590278 --- /dev/null +++ b/fallctf.com/src/components/FallCTFLogo.tsx @@ -0,0 +1,15 @@ +interface Props { + year?: number; + color?: string; +} + +export default function FallCTFLogo({ year, color }: Props) { + return ( + <> +

+ Fall CTF + {year ?  {year} : null} +

+ + ) +} \ No newline at end of file diff --git a/fallctf.com/src/components/Nav.tsx b/fallctf.com/src/components/Nav.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/fallctf.com/src/layouts/Base.astro b/fallctf.com/src/layouts/Base.astro index 85a7336d3..970665f71 100644 --- a/fallctf.com/src/layouts/Base.astro +++ b/fallctf.com/src/layouts/Base.astro @@ -1,6 +1,8 @@ --- import '@/styles/fallctf.css'; +import '$/styles/md.css'; import '$/styles/prism-one-dark.css'; +import 'katex/dist/katex.min.css'; import type { HeadProps } from '$/components/BaseHead.astro'; import BaseHead from '$/components/BaseHead.astro'; diff --git a/fallctf.com/src/layouts/Event.astro b/fallctf.com/src/layouts/Event.astro new file mode 100644 index 000000000..b34c35b39 --- /dev/null +++ b/fallctf.com/src/layouts/Event.astro @@ -0,0 +1,70 @@ +--- +import Layout from '@/layouts/Base.astro'; +import Link from '$/components/Link.astro'; +import { type CollectionEntry } from 'astro:content'; +import { type HeadProps } from '$/components/BaseHead.astro'; +import FallCTFLogo from '@/components/FallCTFLogo'; + +type Event = CollectionEntry<'events'>['data']; + +interface Props extends HeadProps { + event: Event; +}; + +const props: Props = Astro.props; +const event = props.event; + +// const rawMeetings = (await getMeetings()).sort( +// (a, b) => b.data.time_start.valueOf() - a.data.time_start.valueOf() +// ); + +// type MeetingType = typeof rawMeetings[0]; + +// const meetingsBySemester = rawMeetings.reduce( +// (acc, meeting) => { +// const semester = meeting.data.semester; +// if (acc[semester]) { +// acc[semester].push(meeting); +// } else { +// acc[semester] = [meeting]; +// } +// return acc; +// }, {} as {[semester: string]: MeetingType[]} +// ); + +// const meetingSidebarItems = Object.keys(meetingsBySemester).map((semester) => ({ +// name: formatSemester(semester), +// items: meetingsBySemester[semester].map((meeting) => ({ +// name: meeting.data.week_number != null ? `Week ${weekNumber(meeting.data.week_number)}: ${meeting.data.title}` : meeting.data.title, +// url: meeting.slug, +// active: meeting.slug === Astro.url.pathname, +// })), +// active: false +// })); + +// // If a meeting is set as active, we also want to set the parent semester as active +// meetingSidebarItems.forEach((semester) => { +// semester.active = semester.items.some((meeting) => meeting.active); +// }); +--- + + +
+
+ + + {event.links.map((link) => ( + + {link.name} + + ))} + +
+
+
+ +
+
\ No newline at end of file diff --git a/fallctf.com/src/pages/2024.astro b/fallctf.com/src/pages/2024.astro new file mode 100644 index 000000000..b2c397913 --- /dev/null +++ b/fallctf.com/src/pages/2024.astro @@ -0,0 +1,34 @@ +--- +import Layout from '@/layouts/Event.astro'; +import { getCollection } from 'astro:content'; + +const page = (await getCollection('events', (event) => event.data.title === "Fall CTF 2024"))[0]; +if (!page) { + return Astro.error(404, 'Event not found'); +} +const event = page.data; +--- + +
+
+ What is a CTF? + CTF is an acronym for "capture-the-flag," which in the context of the cybersecurity field are competitions where teams solve security-related challenges to find a flag (usually a string of text). The flag can then be submitted to the competition platform for points, and the teams compete against each other for the most points! +
+
+ How are tie-breakers determined? + The leaderboard is sorted first by the team with the most points. If teams have the same number of points, then the team who submitted their most recent flag earlier wins the tie-break. +
+
+ How do I form a team? + By the day before the competition, we will be opening team registration on our competition platform. Feel free to find your team partner beforehand. We will also have multiple opportunities before and during the event to find and form teams! +
+
+ I heard that there will be companies present. Do I need to dress up or prepare a resume? + We do not require a dress code and the expectation is that most people will be dressed casually. We will be offering a resume book to our sponsors and a resume PDF upload form will be provided during the event. If you need help preparing a resume, feel free to ask for advice in our Discord or take advantage of campus career resources! +
+
+
\ No newline at end of file diff --git a/fallctf.com/src/pages/[...slug].astro b/fallctf.com/src/pages/[...slug].astro new file mode 100644 index 000000000..9f83a39b3 --- /dev/null +++ b/fallctf.com/src/pages/[...slug].astro @@ -0,0 +1,49 @@ +--- +import Layout from '@/layouts/Event.astro'; +import { getCollection, render } from 'astro:content'; +import Link from '$/components/Link.astro'; +import { MdxComponents } from '$/components/Mdx/index.astro'; +import FallCTFLogo from '@/components/FallCTFLogo'; + +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import timezone from 'dayjs/plugin/timezone'; +import duration from 'dayjs/plugin/duration'; +import advanced from 'dayjs/plugin/advancedFormat'; +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(duration); +dayjs.extend(advanced); + +export async function getStaticPaths() { + // filter to only fallctf events + const events = (await getCollection('events', (event) => event.data.series === "fallctf")).sort( + (a, b) => b.data.time_start.valueOf() - a.data.time_start.valueOf() + ); + return events.map((event) => ({ + params: { slug: dayjs(event.data.time_start).format('YYYY') }, + props: { page: event }, + })); +}; + +const { page } = Astro.props; +const { Content } = await render(page); +const event = page.data; + +// const fallEvents = rawEvents +// .filter(e => e.data.series === 'fallctf') +// .sort((a, b) => new Date(b.data.time_start).getTime() - new Date(a.data.time_start).getTime()); + +// const [latestEvent, ...previousEvents] = fallEvents; + +const flavor = 'Fall CTF is a beginner-friendly CTF competition for UIUC students, designed to introduce students to cybersecurity topics.' +--- + +
+ +
+
\ No newline at end of file diff --git a/fallctf.com/src/pages/[...year].astro b/fallctf.com/src/pages/[...year].astro deleted file mode 100644 index 3dd915b8a..000000000 --- a/fallctf.com/src/pages/[...year].astro +++ /dev/null @@ -1,24 +0,0 @@ ---- -import { getCollection, type CollectionEntry } from 'astro:content'; - -interface Props { - input: CollectionEntry<'events'>; -} - -const { input } = Astro.props; - -export async function getStaticPaths() { - const rawEvents = await getCollection('events') as CollectionEntry<'events'>[]; - - const fallEvents = rawEvents - .filter(e => e.data.series === 'fallctf') - - return fallEvents.map((event) => ({ - params: { year: event.data.time_start.getFullYear().toString() }, - props: { input: event }, - })); -} ---- -
- {input.data.title} -
\ No newline at end of file diff --git a/fallctf.com/src/pages/index.astro b/fallctf.com/src/pages/index.astro index a4b4fe121..e13cc9e1d 100644 --- a/fallctf.com/src/pages/index.astro +++ b/fallctf.com/src/pages/index.astro @@ -1,30 +1,11 @@ --- -import Layout from '@/layouts/Base.astro'; -import { getCollection, type CollectionEntry } from "astro:content"; -import EventCard from '@/components/Event/Card.astro'; +import { getCollection } from 'astro:content'; +import dayjs from 'dayjs'; -const rawEvents = await getCollection('events') as CollectionEntry<'events'>[]; +const events = (await getCollection('events', (event) => event.data.series === "fallctf")).sort( + (a, b) => b.data.time_start.valueOf() - a.data.time_start.valueOf() +); -const fallEvents = rawEvents -.filter(e => e.data.series === 'fallctf') -.sort((a, b) => new Date(b.data.time_start).getTime() - new Date(a.data.time_start).getTime()); - -const [latestEvent, ...previousEvents] = fallEvents; - -const flavor = 'Fall CTF is a beginner-friendly CTF competition for UIUC students, designed to introduce students to cybersecurity topics.' - ---- - - -
-

Fall CTF

-

{flavor}

-
-
- - {previousEvents.map((event) => ( - - ))} -
-
-
\ No newline at end of file +// TODO: ensure that canonical URL points to year of latest event +return Astro.rewrite(`/${dayjs(events[0].data.time_start).format('YYYY')}/`); +--- \ No newline at end of file diff --git a/fallctf.com/src/styles/fallctf.css b/fallctf.com/src/styles/fallctf.css index 1e2647e88..82854a518 100644 --- a/fallctf.com/src/styles/fallctf.css +++ b/fallctf.com/src/styles/fallctf.css @@ -38,4 +38,87 @@ body { color: rgb(var(--rgb-text)); height: 100%; width: 100%; +} +a, +a:active { + color: rgb(var(--rgb-primary)); + text-decoration: none; +} +a:hover { + color: rgb(var(--rgb-secondary)); + text-decoration: none; +} +.container { + @apply md:px-8 px-4; +} +.panel { + @apply bg-surface-100 rounded-xl p-4; +} +.panel-p-0 { + @apply bg-surface-100 rounded-xl; +} +.btn-primary { + @apply bg-primary text-surface-000 px-3 py-1 rounded-full cursor-pointer; +} +.btn-primary:hover { + background-color: rgb(var(--rgb-secondary)); + color: rgb(var(--rgb-surface-000)); +} +.button { + @apply flex flex-row items-center gap-1 px-3 py-1 cursor-pointer rounded-md; +} +.custom-scrollbar::-webkit-scrollbar-thumb { + background-color: rgb(var(--rgb-primary)); + border-radius: 4px; +} +.custom-scrollbar::-webkit-scrollbar-thumb:active { + background-color: rgb(var(--rgb-secondary)); +} +.custom-scrollbar::-webkit-scrollbar-track { + background-color: transparent; +} +.custom-scrollbar::-webkit-scrollbar-corner { + background-color: transparent; +} +.custom-scrollbar::-webkit-scrollbar { + width: 4px; + height: 8px; +} +.custom-scrollbar { + -ms-overflow-style: auto; + scrollbar-color: rgb(var(--rgb-primary)) transparent; + scrollbar-width: thin; +} +/* Hide scrollbar for Chrome, Safari and Opera */ +.no-scrollbar::-webkit-scrollbar { + display: none; +} +/* Hide scrollbar for IE, Edge and Firefox */ +.no-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ +} +/* Skeleton shimmer effect */ +.skeleton-shimmer { + position: relative; + overflow: hidden; + isolation: isolate; + display: flex; +} +.skeleton-shimmer::before { + content: ""; + background: linear-gradient(90deg, transparent, rgb(var(--rgb-surface-250) / 10), transparent) no-repeat; + background-size: 100% 100%; + animation: shimmer 1s infinite; + position: absolute; + transform: translateX(-100%); + inset: 0; +} +.skeleton-shimmer > * { + position: relative; +} +@keyframes shimmer { + 100% { + transform: translateX(100%); + } } \ No newline at end of file diff --git a/sigpwny.com/src/layouts/Base.astro b/sigpwny.com/src/layouts/Base.astro index 21cb402b9..665bb6523 100644 --- a/sigpwny.com/src/layouts/Base.astro +++ b/sigpwny.com/src/layouts/Base.astro @@ -1,6 +1,6 @@ --- import '@/styles/main.css'; -import '@/styles/md.css'; +import '$/styles/md.css'; import '$/styles/prism-one-dark.css'; import type { HeadProps } from '$/components/BaseHead.astro'; diff --git a/sigpwny.com/src/layouts/Meeting.astro b/sigpwny.com/src/layouts/Meeting.astro index f93b25511..eea284e68 100644 --- a/sigpwny.com/src/layouts/Meeting.astro +++ b/sigpwny.com/src/layouts/Meeting.astro @@ -1,6 +1,6 @@ --- import Layout from '@/layouts/Base.astro'; -import type { HeadProps } from '@/components/BaseHead.astro'; +import type { HeadProps } from '$/components/BaseHead.astro'; import Sidebar from '@/components/Sidebar'; import { getMeetings, formatSemester, weekNumber } from '@/utils/meetings'; import 'katex/dist/katex.min.css'; diff --git a/sigpwny.com/src/pages/[...slug]/index.astro b/sigpwny.com/src/pages/[...slug]/index.astro index 841b7f596..4d41e0b9c 100644 --- a/sigpwny.com/src/pages/[...slug]/index.astro +++ b/sigpwny.com/src/pages/[...slug]/index.astro @@ -1,7 +1,7 @@ --- import Layout from '@/layouts/Base.astro'; import { getCollection, render } from 'astro:content'; -import { MdxComponents } from '@/components/Mdx/index.astro'; +import { MdxComponents } from '$/components/Mdx/index.astro'; export async function getStaticPaths() { const pages = await getCollection('pages'); diff --git a/sigpwny.com/src/pages/meetings/[...slug]/index.astro b/sigpwny.com/src/pages/meetings/[...slug]/index.astro index fa6605d9f..6da73a26d 100644 --- a/sigpwny.com/src/pages/meetings/[...slug]/index.astro +++ b/sigpwny.com/src/pages/meetings/[...slug]/index.astro @@ -6,12 +6,12 @@ import { LiveRegular, LocationRegular } from '@/components/Icons/fluentui'; +import { MdxComponents } from '$/components/Mdx/index.astro'; import Avatar from '@/components/Profile/Avatar.astro'; import Layout from '@/layouts/Meeting.astro'; import Persona from '@/components/Profile/Persona'; import ProfileCard from '@/components/Profile/ProfileCard.astro'; import { PdfSvg, YouTubeSvg } from '@/components/Icons'; -import { MdxComponents } from '@/components/Mdx/index.astro'; import { CountdownBadge } from '@/components/ReactMigration/Countdown'; import { TagGroup } from '@/components/ReactMigration/Tag'; import { diff --git a/sigpwny.com/src/pages/publications/[...slug]/index.astro b/sigpwny.com/src/pages/publications/[...slug]/index.astro index 65473f02b..e2ce94e90 100644 --- a/sigpwny.com/src/pages/publications/[...slug]/index.astro +++ b/sigpwny.com/src/pages/publications/[...slug]/index.astro @@ -2,11 +2,11 @@ import Layout from '@/layouts/Base.astro'; import { getCollection, render } from 'astro:content'; import Link from '$/components/Link.astro'; +import { MdxComponents } from '$/components/Mdx/index.astro'; import Card from '@/components/Card.astro'; import Avatar from '@/components/Profile/Avatar.astro'; import Persona from '@/components/Profile/Persona'; import ProfileCard from '@/components/Profile/ProfileCard.astro'; -import { MdxComponents } from '@/components/Mdx/index.astro'; import { TagGroup } from '@/components/ReactMigration/Tag'; import { getProfilesFromNames } from '@/utils/profiles';