refactor: remove portfolio

This commit is contained in:
Kim, Jimin 2024-03-23 14:13:13 +09:00
parent 565297c9b3
commit 584b4a60da
Signed by: pomp
GPG key ID: 77DAC7BB5CA8C7AA
54 changed files with 28 additions and 1085 deletions

View file

@ -12,7 +12,6 @@
- `apps`
- `main` - https://developomp.com
- `blog` - https://blog.developomp.com
- `portfolio` - https://portfolio.developomp.com
- `packages` - shared stuff used across different packages
- `content` - Shared content
- `eslint-config` - ESLint configuration files
@ -46,7 +45,6 @@
- `pnpm dev` - Run all apps and packages locally
- blog - http://localhost:3000
- main - http://localhost:5173
- portfolio - http://localhost:5174
- `pnpm lint` - Lint all apps and packages
- `pnpm clean` - Remove all auto-generated content such as `node_modules` and `dist`.

View file

@ -46,6 +46,7 @@
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.9",
"react": "18.2.0",
"react-collapse": "^5.1.1",
"react-dom": "18.2.0",
"serve": "^14.2.0",
"tailwindcss": "^3.4.0",

View file

@ -75,13 +75,6 @@ export function parsePageData(
order: [],
length: 0,
// portfolio (unused)
image: "",
overview: "",
badges: [],
repo: "",
}
// load and parse content differently depending on the content type

View file

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en" class="dark">
<head>
<meta charset="utf-8" />
@ -8,7 +8,7 @@
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="About developomp - socials, links, discord server, contact, blog, portfolio, resume, etc."
content="About developomp - socials, links, discord server, contact, blog, resume, etc."
/>
<title>developomp</title>
@ -17,7 +17,7 @@
<meta property="og:site_name" content="developomp" />
<meta
property="og:description"
content="About developomp - socials, links, discord server, contact, blog, portfolio, resume, etc."
content="About developomp - socials, links, discord server, contact, blog, resume, etc."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://developomp.com" />

View file

@ -1,34 +0,0 @@
<script>
import { page } from "$app/stores"
</script>
<nav
class="mx-auto flex h-14 max-w-screen-mobile flex-col items-center justify-between px-4 xs:flex-row"
>
<!-- only show home button when not in home -->
<a
href="/"
aria-current={$page.url.pathname === "/" ? "page" : undefined}
class="left-0"
style={$page.url.pathname === "/" ? "visibility: hidden;" : ""}
>
Home
</a>
<ul class="flex list-none gap-4 no-underline">
<li aria-current={$page.url.pathname === "/" ? "page" : undefined}>
<a target="_blank" href="https://blog.developomp.com">Blog</a>
</li>
<li aria-current={$page.url.pathname === "/about" ? "page" : undefined}>
<a target="_blank" href="https://portfolio.developomp.com">
Portfolio
</a>
</li>
</ul>
</nav>
<style lang="postcss">
li {
@apply inline;
}
</style>

View file

@ -1,10 +1,7 @@
<script>
import "./app.css"
import Navbar from "$/components/Navbar.svelte"
</script>
<Navbar />
<main
class="mx-auto my-0 flex w-full max-w-5xl flex-col items-center px-8 py-0 text-center font-normal"
>

View file

@ -1,23 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://developomp.com</loc>
<changefreq>always</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://blog.developomp.com</loc>
<changefreq>always</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://portfolio.developomp.com</loc>
<changefreq>always</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>https://developomp.com/resume</loc>
<changefreq>always</changefreq>
<priority>0.4</priority>
</url>
<url>
<loc>https://developomp.com</loc>
<changefreq>always</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://blog.developomp.com</loc>
<changefreq>always</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://developomp.com/resume</loc>
<changefreq>always</changefreq>
<priority>0.4</priority>
</url>
</urlset>

View file

@ -1,8 +0,0 @@
module.exports = {
root: true,
extends: ["next/core-web-vitals", "@developomp-site/eslint-config"],
rules: {
"react-hooks/exhaustive-deps": "off",
"react/no-unescaped-entities": "off",
},
}

View file

@ -1,36 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
/test-results
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View file

@ -1,5 +0,0 @@
/** @type {import("prettier").Options} */
module.exports = {
...require("@developomp-site/prettier-config"),
plugins: ["prettier-plugin-tailwindcss"],
}

View file

@ -1,6 +0,0 @@
import { expect, test } from "@playwright/test"
test("Should return 404 for invalid routes", async ({ page }) => {
const response = await page.goto("/path/that/does/not/exist")
expect(response?.status()).toEqual(404)
})

View file

@ -1,14 +0,0 @@
import { expect, test } from "@playwright/test"
const prefix = "pomp's portfolio | "
test("should have proper title", async ({ page }) => {
await page.goto("/")
await expect(page).toHaveTitle(`${prefix}Home`)
await page.goto("/project/developomp-site")
await expect(page).toHaveTitle(`${prefix}developomp-site`)
await page.goto("/404")
await expect(page).toHaveTitle(`${prefix}Page Not Found`)
})

View file

@ -1,8 +0,0 @@
// https://next-sitemap.iamvishnusankar.com/docs/documentation/configuration
/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: "https://portfolio.developomp.com",
generateRobotsTxt: true,
outDir: "dist",
priority: 0.8,
}

View file

@ -1,11 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "export",
distDir: "dist",
images: { unoptimized: true },
experimental: {
externalDir: true,
},
}
module.exports = nextConfig

View file

@ -1,55 +0,0 @@
{
"name": "@developomp-site/portfolio",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "open-cli http://localhost:5174 && next dev -p 5174",
"build": "next build",
"postbuild": "next-sitemap",
"serve": "serve dist --listen 5174",
"test:e2e": "playwright test",
"lint": "next lint",
"clean": "rm -rf .next .turbo dist node_modules test-results"
},
"devDependencies": {
"@developomp-site/blog": "workspace:*",
"@developomp-site/content": "workspace:*",
"@developomp-site/eslint-config": "workspace:*",
"@developomp-site/playwright-config": "workspace:*",
"@developomp-site/prettier-config": "workspace:*",
"@developomp-site/tailwind-config": "workspace:*",
"@fontsource/noto-sans-kr": "^5.0.5",
"@fontsource/source-code-pro": "^5.0.5",
"@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@kunukn/react-collapse": "^2.2.10",
"@playwright/test": "^1.36.2",
"@types/highlight.js": "^10.1.0",
"@types/katex": "^0.16.7",
"@types/node": "^20.10.5",
"@types/react": "18.2.17",
"@types/react-collapse": "^5.0.1",
"@types/react-dom": "18.2.7",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
"autoprefixer": "^10.4.16",
"eslint": "^8.56.0",
"eslint-config-next": "13.4.12",
"highlight.js": "^11.8.0",
"katex": "^0.16.8",
"next": "13.4.12",
"next-sitemap": "^4.1.8",
"open-cli": "^7.2.0",
"postcss": "^8.4.32",
"postcss-load-config": "^4.0.1",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.9",
"react": "18.2.0",
"react-collapse": "^5.1.1",
"react-dom": "18.2.0",
"serve": "^14.2.0",
"tailwindcss": "^3.4.0",
"typescript": "^5.3.3"
}
}

View file

@ -1,5 +0,0 @@
import { createConfig } from "@developomp-site/playwright-config"
export default createConfig({
port: 5174,
})

View file

@ -1,7 +0,0 @@
/** @type {import('postcss-load-config').Config} */
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -1,22 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
* {
@apply scroll-m-16 leading-8;
}
html {
@apply bg-dark-ui-bg font-noto-sans text-dark-text-default;
}
body {
@apply m-0 flex h-full min-h-screen w-full scroll-m-16 flex-col items-center p-0;
}
ul,
ol {
list-style: circle;
padding-left: 2.5rem;
list-style-position: inside;
}

View file

@ -1,86 +0,0 @@
import "@fortawesome/fontawesome-svg-core/styles.css"
import "@fontsource/noto-sans-kr/400.css"
import "@fontsource/noto-sans-kr/700.css"
import "@fontsource/source-code-pro"
import "@developomp-site/blog/src/styles/anchor.scss"
import "@developomp-site/blog/src/styles/blockQuote.scss"
import "@developomp-site/blog/src/styles/button.scss"
import "@developomp-site/blog/src/styles/callout.scss"
import "@developomp-site/blog/src/styles/checkbox.scss"
import "@developomp-site/blog/src/styles/code.scss"
import "@developomp-site/blog/src/styles/colorChip.scss"
import "@developomp-site/blog/src/styles/heading.scss"
import "@developomp-site/blog/src/styles/hr.scss"
import "@developomp-site/blog/src/styles/img.scss"
import "@developomp-site/blog/src/styles/katex.scss"
import "@developomp-site/blog/src/styles/kbd.scss"
import "@developomp-site/blog/src/styles/list.scss"
import "@developomp-site/blog/src/styles/mark.scss"
import "@developomp-site/blog/src/styles/scrollbar.scss"
import "@developomp-site/blog/src/styles/subSup.scss"
import "@developomp-site/blog/src/styles/table.scss"
import "@developomp-site/blog/src/styles/theme-visibility.scss"
import "./global.scss"
import { type Metadata } from "next"
import Image from "next/image"
import Header from "@/components/Header"
export const metadata: Metadata = {
metadataBase: new URL("https://portfolio.developomp.com"),
title: {
template: "pomp's portfolio | %s",
default: "",
},
description: "developomp's portfolio",
openGraph: {
title: "pomp's portfolio",
siteName: "developomp's portfolio",
description: "developomp's portfolio",
type: "website",
url: "https://portfolio.developomp.com",
images: "https://portfolio.developomp.com/favicon.svg",
},
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className="dark">
<head>
<link
rel="shortcut icon"
type="image/svg+xml"
href="/favicon.svg"
/>
<meta name="theme-color" content="#000000" />
</head>
<body>
<noscript>
<figure>
<Image
src="/img/nojs.avif"
height={500}
width={544}
alt="No javascript?"
/>
<figcaption>
Image compressed down to 4.5kB because you probably
have potato internet :D
</figcaption>
</figure>
</noscript>
<Header />
<div className="mb-10 mt-20 w-full max-w-screen-md px-4">
{children}
</div>
</body>
</html>
)
}

View file

@ -1,21 +0,0 @@
import { type Metadata } from "next"
export const metadata: Metadata = {
metadataBase: new URL("https://portfolio.developomp.com"),
title: "pomp's portfolio | Page Not Found",
openGraph: {
title: "pomp's portfolio | Page Not Found",
},
}
export default function NotFound() {
return (
<>
<h1 className="w-fit px-4 py-2 text-5xl dark:bg-dark-text-default dark:text-dark-ui-bg">
404
</h1>
<h2 className="glitch layers text-5xl">Page Not Found</h2>
</>
)
}

View file

@ -1,40 +0,0 @@
import type { ProjectKey } from "@developomp-site/content/exports/portfolio"
import portfolio from "@developomp-site/content/exports/portfolio"
import type { Metadata } from "next"
import Badge from "@/components/Badge"
import ProjectCard from "@/components/ProjectCard"
function getSkills(): JSX.Element[] {
return portfolio.skills.map((slug) => {
return <Badge key={slug} slug={slug} />
})
}
function getProjects(): JSX.Element[] {
return (Object.keys(portfolio.projects) as ProjectKey[]).map(
(projectID) => (
<ProjectCard
key={projectID}
projectID={projectID}
project={portfolio.projects[projectID]}
/>
),
)
}
export const metadata: Metadata = {
metadataBase: new URL("https://blog.developomp.com"),
title: "pomp's portfolio | Home",
}
export default function Page() {
return (
<>
<h1 className="mb-8">developomp's Portfolio</h1>
<hr />
<div className="my-4 flex flex-wrap gap-2">{getSkills()}</div>
<div className="projects">{getProjects()}</div>
</>
)
}

View file

@ -1,98 +0,0 @@
import "./style.scss"
import Toc from "@developomp-site/blog/src/app/[category]/[[...slug]]/Toc"
import type { ProjectKey } from "@developomp-site/content/exports/portfolio"
import portfolio from "@developomp-site/content/exports/portfolio"
import { faGithub } from "@fortawesome/free-brands-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { type Metadata } from "next"
import Link from "next/link"
import Badge from "@/components/Badge"
interface Data {
title: string
toc?: string
content: string
image: string // image url
overview: string
badges: string[]
repo: string
}
interface Params {
id: ProjectKey
}
interface Props {
params: Params
}
async function getData(id: ProjectKey): Promise<Data> {
const content = await import(
`@developomp-site/content/dist/content/projects/${id}.json`
)
const data = portfolio.projects[id]
return {
content: content.content,
toc: content.toc,
title: data.name,
image: data.image,
overview: data.overview,
badges: data.badges,
repo: data.repo,
}
}
export async function generateStaticParams(): Promise<Params[]> {
return (Object.keys(portfolio.projects) as ProjectKey[]).map((id) => ({
id,
}))
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const data = await getData(params.id)
return {
metadataBase: new URL("https://portfolio.developomp.com"),
title: data.title,
openGraph: {
title: `pomp's portfolio | ${data.title}`,
},
}
}
export default async function Project({ params }: Props) {
const data = await getData(params.id)
return (
<>
<div className="flex items-center justify-between">
<h1 className="mb-4 text-4xl">{data.title}</h1>
<Link
href={data.repo}
className="text-dark-text-default duration-100 hover:text-gray-400"
>
<FontAwesomeIcon className="h-12" icon={faGithub} />
</Link>
</div>
<div className="flex flex-wrap gap-2">
{data.badges.map((slug) => {
return <Badge key={slug} slug={slug} />
})}
</div>
<hr />
<Toc data={data.toc} />
{/* page content */}
<div
className="project-description"
dangerouslySetInnerHTML={{
__html: data.content,
}}
/>
</>
)
}

View file

@ -1,29 +0,0 @@
.project-description {
h2,
h3,
h4,
h5,
h6 {
@apply mb-2;
}
h2 {
@apply mt-10 text-3xl;
}
h3 {
@apply mt-6 indent-2 text-xl;
}
h4 {
@apply mt-6 indent-4 text-base;
}
h5 {
@apply mt-6 indent-6 text-base;
}
h6 {
@apply mt-6 indent-8 text-base;
}
}

View file

@ -1,35 +0,0 @@
import "./style.scss"
import { type Badge as BadgeType } from "@developomp-site/content/src/types/types"
interface BadgeProps {
slug: string
}
export default async function Badge({ slug }: BadgeProps) {
const badgeData: BadgeType = await import(
`@developomp-site/content/dist/icons/${slug}.json`
)
if (!badgeData)
throw `"@developomp-site/content/dist/icons/${slug}.json" does not exist`
return (
<div
style={{ backgroundColor: badgeData.hex }}
className={`flex w-fit items-center px-2 py-1 text-xs ${
badgeData.isDark
? "text-dark-text-default"
: "text-light-text-default"
}`}
>
<div
className={`badge mr-1 inline-block w-6 align-middle ${
badgeData.isDark ? "dark-badge" : "light-badge"
}`}
dangerouslySetInnerHTML={{ __html: badgeData.svg }}
/>
<span>{badgeData.title}</span>
</div>
)
}

View file

@ -1,3 +0,0 @@
import Badge from "./Badge"
export default Badge

View file

@ -1,11 +0,0 @@
.light-badge {
svg {
@apply dark:fill-light-text-default;
}
}
.dark-badge {
svg {
@apply dark:fill-dark-text-default;
}
}

View file

@ -1,25 +0,0 @@
import Link from "next/link"
import { type FC } from "react"
const Header: FC = () => {
return (
<header className="fixed top-0 z-50 flex w-screen justify-center dark:bg-dark-ui dark:text-dark-text-default">
<div className="my-0 flex h-16 w-full max-w-5xl items-center">
<Link
className="flex items-center"
href="/"
aria-label="homepage"
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
className="m-4 block h-10 cursor-pointer"
src="/favicon.svg"
alt="logo"
/>
</Link>
</div>
</header>
)
}
export default Header

View file

@ -1,3 +0,0 @@
import Header from "./Header"
export default Header

View file

@ -1,39 +0,0 @@
import "./style.scss"
import type { PortfolioProject } from "@developomp-site/content/src/types/types"
import Link from "next/link"
import Badge from "@/components/Badge"
interface ProjectCardProps {
projectID: string
project: PortfolioProject
}
export default function ProjectCard({ projectID, project }: ProjectCardProps) {
return (
<Link href={`/project/${projectID}`}>
<div className="project">
<h2 className="mb-4">{project.name}</h2>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
className="mb-4 w-full object-cover"
src={project.image}
alt="project thumbnail"
/>
<div className="flex flex-wrap gap-2">
{project.badges.map((badge) => (
<Badge key={badge} slug={badge} />
))}
</div>
<hr className="my-1" />
<div
dangerouslySetInnerHTML={{
__html: project.overview,
}}
/>
</div>
</Link>
)
}

View file

@ -1,3 +0,0 @@
import ProjectCard from "./ProjectCard"
export default ProjectCard

View file

@ -1,17 +0,0 @@
.project {
// general
@apply cursor-pointer rounded-md;
// spacing
@apply m-auto mb-8 p-8;
// color
@apply bg-dark-card-bg dark:text-dark-text-default;
// glow
@apply duration-75 hover:shadow-glow dark:hover:shadow-dark-text-default;
h2 {
@apply text-3xl;
}
}

View file

@ -1,9 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
presets: [require("@developomp-site/tailwind-config/tailwind.config.js")],
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
}

View file

@ -1,35 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"build/types/**/*.ts",
"dist/types/**/*.ts"
],
"exclude": ["node_modules"]
}

View file

@ -14,7 +14,6 @@ module.exports = {
// apps
"blog",
"main",
"portfolio",
// packages
"content",

View file

@ -13,13 +13,6 @@
"trailingSlash": false,
"public": "apps/blog/build",
"ignore": ["**/.*"]
},
{
"target": "portfolio",
"cleanUrls": true,
"trailingSlash": false,
"public": "apps/portfolio/dist",
"ignore": ["**/.*"]
}
]
}

20
main.tf
View file

@ -57,23 +57,3 @@ resource "aws_route53_record" "blog_acme_challenge" {
ttl = 60
records = ["RXaOhzFg2U4ZtEU_Dj_2ylAX3D8xXpdRCq1KjoaB9Sc"]
}
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record
resource "aws_route53_record" "portfolio" {
allow_overwrite = true
zone_id = data.aws_route53_zone.developomp_com.zone_id
name = "portfolio.${data.aws_route53_zone.developomp_com.name}"
type = "A"
ttl = 60
records = ["199.36.158.100"]
}
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record
resource "aws_route53_record" "portfolio_acme_challenge" {
allow_overwrite = true
zone_id = data.aws_route53_zone.developomp_com.zone_id
name = "_acme-challenge.portfolio.${data.aws_route53_zone.developomp_com.name}"
type = "TXT"
ttl = 60
records = ["YxFtDJ-Qf1yE8KX2mzf4cbfkPBR74IbbWX_0l5gGnLg"]
}

View file

@ -1,14 +0,0 @@
import portfolio from "../dist/portfolio.json" assert { type: "json" }
import type { PortfolioProject } from "../src/types/types"
export type ProjectKey = keyof typeof portfolio.projects
// sort of like src/types/types.ts > PortfolioData but exported
export default portfolio as {
// waiting for https://github.com/microsoft/TypeScript/issues/32063
skills: string[]
projects: {
[key in ProjectKey]: PortfolioProject
}
}

View file

@ -1,30 +0,0 @@
---
name: developomp-site
overview: my websites for blogging, portfolio, resume, etc.
image: /img/portfolio/developomp-site.avif
repo: https://github.com/developomp/developomp-site
badges:
- typescript
- tailwindcss
- react
- svelte
- nextdotjs
- firebase
- terraform
---
## Introduction
developomp-site is a monorepo managed by [turborepo](https://turbo.build/repo)
and pnpm workspace.
- https://developomp.com - about me, built with **Svelte with SvelteKit**
- https://blog.developomp.com - Blogging site, built with **React with NextJS**
- https://portfolio.developomp.com - Portfolio, built with **React with NextJS**
## Interesting Stuff
- [markdown parsing][markdown-parsing]
- [test post](https://blog.developomp.com/posts/test-post)
[markdown-parsing]: https://github.com/developomp/developomp-site/tree/081855a4ecb6f5bf74b76758c358ea54b465b2b7/packages/blog-content

View file

@ -1,38 +0,0 @@
---
name: War Brokers Mods
overview: A game mod for a unity game. Provides in-game UI and OBS overlays.
image: /img/portfolio/wbm.avif
repo: https://github.com/War-Brokers-Mods
badges:
- rust
- csharp
- svelte
- tailwindcss
- unity
- tauri
---
## Introduction
The War Brokers Mods (WBM) is a mod for the game
[War Brokers](https://warbrokers.io) consisting of 3 sub-projects:
- [mod][mod] - Built with C#, it uses the [BepInEx][bepinex] framework to patch
different aspects of the game
- [OBS overlay][overlays] - Customizable overlays for [OBS studio](https://github.com/obsproject/obs-studio)
![Overlay image](/img/portfolio/wbm-overlays.avif "Overlay image")
- [installer][installer] - Utility for installing updating the mod. Built with [tauri][tauri],
[rust][rust], [svelte][svelte], and [tailwind css][tailwindcss].
![Installer image](/img/portfolio/wbm-installer.avif "Installer image")
[mod]: https://github.com/War-Brokers-Mods/WBM
[overlays]: https://github.com/War-Brokers-Mods/WBM-Overlays
[installer]: https://github.com/War-Brokers-Mods/WBM-installer
[bepinex]: https://github.com/BepInEx/BepInEx
[tauri]: https://github.com/tauri-apps/tauri
[rust]: https://github.com/rust-lang/rust
[svelte]: https://github.com/sveltejs/svelte
[tailwindcss]: https://github.com/tailwindlabs/tailwindcss

View file

@ -1,23 +0,0 @@
---
name: War Brokers Projects
overview: An attempt to bring together community projects related to War Brokers with the goal of making them more visible and making collaboration easier.
image: /img/portfolio/wbp.avif
repo: https://github.com/War-Brokers
badges:
- csharp
- typescript
- express
- swagger
- firebase
---
## Introduction
WBP (War Brokers Projects) is an attempt to bring together community projects
related to War Brokers with the goal of making them more visible and making
collaboration easier.
You can find more information in their [homepage][homepage] or in their [GitHub organization][github]
[Homepage]: https://war-brokers-projects.notion.site/War-Brokers-Projects-0ab13d7077a843e79b99a328e00d2008
[github]: https://github.com/orgs/War-Brokers/repositories

View file

@ -4,5 +4,4 @@ export const outPath = "./dist" // path to the json database
export const contentDirectoryPath = `${outPath}/content`
export const iconsDirectoryPath = `${outPath}/icons`
export const mapFilePath = `${outPath}/map.json`
export const portfolioFilePath = `${outPath}/portfolio.json`
export const searchIndexFilePath = `${outPath}/search.json`

View file

@ -8,11 +8,11 @@
import fs from "fs"
import { mapFilePath, markdownPath, outPath, portfolioFilePath } from "./config"
import { mapFilePath, markdownPath, outPath } from "./config"
import { fillTags, parseSeries, sortDates } from "./postProcess"
import { recursiveParse } from "./recursiveParse"
import { saveIndex } from "./searchIndex"
import type { ContentMap, PortfolioData, SeriesMap } from "./types/types"
import type { ContentMap, SeriesMap } from "./types/types"
import { ParseMode } from "./types/types"
export const contentMap: ContentMap = {
@ -25,10 +25,6 @@ export const contentMap: ContentMap = {
series: {},
}
export const seriesMap: SeriesMap = {}
export const portfolioData: PortfolioData = {
skills: new Set(),
projects: {},
}
async function main() {
/**
@ -60,7 +56,6 @@ async function main() {
// parse markdown
await recursiveParse(ParseMode.POSTS, markdownPath + "/posts")
await recursiveParse(ParseMode.SERIES, markdownPath + "/series")
await recursiveParse(ParseMode.PORTFOLIO, markdownPath + "/projects")
sortDates()
fillTags()
@ -71,14 +66,6 @@ async function main() {
*/
fs.writeFileSync(mapFilePath, JSON.stringify(contentMap))
fs.writeFileSync(
portfolioFilePath,
JSON.stringify({
...portfolioData,
skills: Array.from(portfolioData.skills),
}),
)
saveIndex()
}

View file

@ -23,7 +23,6 @@ import supersub from "remark-supersub"
import { unified } from "unified"
import type { MarkdownData } from "./types/types"
import { ParseMode } from "./types/types"
import { nthIndex } from "./util"
const processor = unified() // interface for remark and rehype
@ -50,12 +49,10 @@ const processor = unified() // interface for remark and rehype
*
* @param {string} markdownRaw - raw unparsed text data of the markdown file
* @param {string} path - filename of the markdown file
* @param {ParseMode} mode
*/
export default async function parseMarkdown(
markdownRaw: string,
path: string,
mode: ParseMode,
): Promise<MarkdownData> {
const fileHasFrontMatter = markdownRaw.startsWith("---")
@ -64,21 +61,11 @@ export default async function parseMarkdown(
: {}
if (fileHasFrontMatter) {
if (mode != ParseMode.PORTFOLIO) {
if (!frontMatter.title)
throw Error(`Title is not defined in file: ${path}`)
if (!frontMatter.title)
throw Error(`Title is not defined in file: ${path}`)
if (!frontMatter.date)
throw Error(`Date is not defined in file: ${path}`)
}
if (mode === ParseMode.PORTFOLIO) {
if (frontMatter.overview) {
frontMatter.overview = String(
processor.processSync(frontMatter.overview),
)
}
}
if (!frontMatter.date)
throw Error(`Date is not defined in file: ${path}`)
}
frontMatter.content = touchupHTML(

View file

@ -5,7 +5,6 @@ import parseMarkdown from "../parseMarkdown"
import { ParseMode } from "../types/types"
import { path2FileOrFolderName, path2URL } from "../util"
import parsePost from "./parsePost"
import parseProjects from "./parseProjects"
import parseSeries from "./parseSeries"
/**
@ -98,9 +97,5 @@ async function parseFile(mode: ParseMode, path: string): Promise<void> {
case ParseMode.SERIES:
await parseSeries(dataToPass)
break
case ParseMode.PORTFOLIO:
await parseProjects(dataToPass)
break
}
}

View file

@ -1,57 +0,0 @@
import type { SimpleIcon } from "simple-icons"
import * as icons from "simple-icons"
import tinycolor from "tinycolor2"
import { portfolioData } from ".."
import { contentDirectoryPath, iconsDirectoryPath } from "../config"
import { generateToc } from "../parseMarkdown"
import { writeToFile } from "../util"
import type { DataToPass } from "."
export default async function parseProjects({
urlPath,
markdownRaw,
markdownData,
}: DataToPass): Promise<void> {
if (markdownData.badges) {
;(markdownData.badges as string[]).forEach((slug) => {
// todo: handle cases when icon is not on simple-icons
const icon: SimpleIcon =
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icons["si" + slug[0].toUpperCase() + slug.slice(1)]
portfolioData.skills.add(slug)
const color = tinycolor(icon.hex).lighten(5).desaturate(5)
// save svg icon
writeToFile(
`${iconsDirectoryPath}/${icon.slug}.json`,
JSON.stringify({
svg: icon.svg,
hex: color.toHexString(),
isDark: color.isDark(),
title: icon.title,
}),
)
})
}
// remove /projects/ prefix
portfolioData.projects[urlPath.replace("/projects/", "")] = {
name: markdownData.name as string,
image: markdownData.image as string,
overview: markdownData.overview as string,
badges: (markdownData.badges as string[]) || [],
repo: (markdownData.repo as string) || "",
}
writeToFile(
`${contentDirectoryPath}${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
toc: await generateToc(markdownRaw),
}),
)
}

View file

@ -32,7 +32,6 @@ export interface ContentMap {
export enum ParseMode {
POSTS,
SERIES,
PORTFOLIO,
}
export interface MarkdownData {
@ -67,13 +66,6 @@ export interface PageData {
order: string[]
length: number
// portfolio
image: string // image url
overview: string
badges: string[]
repo: string
}
export interface Badge {
@ -106,31 +98,3 @@ export interface SeriesEntry {
index: number
url: string
}
/**
* Portfolio
*/
export interface PortfolioData {
// a set of valid simple icons slug
skills: Set<string>
// key: url
projects: {
[key: string]: PortfolioProject
}
}
export interface PortfolioOverview {
// link to my github
github: string
description: string
}
export interface PortfolioProject {
name: string
image: string // url to the image
overview: string
badges: string[] // array of valid simpleIcons slug
repo: string // url of the git repository
}

123
pnpm-lock.yaml generated
View file

@ -140,6 +140,9 @@ importers:
react:
specifier: 18.2.0
version: 18.2.0
react-collapse:
specifier: ^5.1.1
version: 5.1.1(react@18.2.0)
react-dom:
specifier: 18.2.0
version: 18.2.0(react@18.2.0)
@ -261,126 +264,6 @@ importers:
specifier: ^5.0.10
version: 5.0.10(@types/node@18.19.3)(sass@1.69.5)
apps/portfolio:
devDependencies:
'@developomp-site/blog':
specifier: workspace:*
version: link:../blog
'@developomp-site/content':
specifier: workspace:*
version: link:../../packages/content
'@developomp-site/eslint-config':
specifier: workspace:*
version: link:../../packages/eslint-config
'@developomp-site/playwright-config':
specifier: workspace:*
version: link:../../packages/playwright-config
'@developomp-site/prettier-config':
specifier: workspace:*
version: link:../../packages/prettier-config
'@developomp-site/tailwind-config':
specifier: workspace:*
version: link:../../packages/tailwind-config
'@fontsource/noto-sans-kr':
specifier: ^5.0.5
version: 5.0.5
'@fontsource/source-code-pro':
specifier: ^5.0.5
version: 5.0.5
'@fortawesome/free-brands-svg-icons':
specifier: ^6.4.0
version: 6.4.0
'@fortawesome/free-solid-svg-icons':
specifier: ^6.4.0
version: 6.4.0
'@fortawesome/react-fontawesome':
specifier: ^0.2.0
version: 0.2.0(@fortawesome/fontawesome-svg-core@6.5.1)(react@18.2.0)
'@kunukn/react-collapse':
specifier: ^2.2.10
version: 2.2.10(react-dom@18.2.0)(react@18.2.0)
'@playwright/test':
specifier: ^1.36.2
version: 1.36.2
'@types/highlight.js':
specifier: ^10.1.0
version: 10.1.0
'@types/katex':
specifier: ^0.16.7
version: 0.16.7
'@types/node':
specifier: ^20.10.5
version: 20.10.5
'@types/react':
specifier: 18.2.17
version: 18.2.17
'@types/react-collapse':
specifier: ^5.0.1
version: 5.0.1
'@types/react-dom':
specifier: 18.2.7
version: 18.2.7
'@typescript-eslint/eslint-plugin':
specifier: ^6.15.0
version: 6.15.0(@typescript-eslint/parser@6.15.0)(eslint@8.56.0)(typescript@5.3.3)
'@typescript-eslint/parser':
specifier: ^6.15.0
version: 6.15.0(eslint@8.56.0)(typescript@5.3.3)
autoprefixer:
specifier: ^10.4.16
version: 10.4.16(postcss@8.4.32)
eslint:
specifier: ^8.56.0
version: 8.56.0
eslint-config-next:
specifier: 13.4.12
version: 13.4.12(eslint@8.56.0)(typescript@5.3.3)
highlight.js:
specifier: ^11.8.0
version: 11.8.0
katex:
specifier: ^0.16.8
version: 0.16.8
next:
specifier: 13.4.12
version: 13.4.12(react-dom@18.2.0)(react@18.2.0)
next-sitemap:
specifier: ^4.1.8
version: 4.1.8(next@13.4.12)
open-cli:
specifier: ^7.2.0
version: 7.2.0
postcss:
specifier: ^8.4.32
version: 8.4.32
postcss-load-config:
specifier: ^4.0.1
version: 4.0.1(postcss@8.4.32)
prettier:
specifier: ^3.2.5
version: 3.2.5
prettier-plugin-tailwindcss:
specifier: ^0.5.9
version: 0.5.9(prettier-plugin-svelte@3.1.2)(prettier@3.2.5)
react:
specifier: 18.2.0
version: 18.2.0
react-collapse:
specifier: ^5.1.1
version: 5.1.1(react@18.2.0)
react-dom:
specifier: 18.2.0
version: 18.2.0(react@18.2.0)
serve:
specifier: ^14.2.0
version: 14.2.0
tailwindcss:
specifier: ^3.4.0
version: 3.4.0
typescript:
specifier: ^5.3.3
version: 5.3.3
packages/content:
dependencies:
'@developomp-site/eslint-config':