Compare commits

..

11 Commits

Author SHA1 Message Date
rei
f15a1fb167 yt fix
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-24 18:30:28 +02:00
rei
bab35fbfce bg fix 2023-04-24 18:27:42 +02:00
rei
84cc6d64db upgrade to next 13
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-24 18:13:50 +02:00
rei
63245d9afd WIP: c9f5dfc Update 'content/projects/RE-Chess.md' 2023-03-13 23:43:17 +01:00
9b8b59d4e6 add Blur
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-24 13:16:50 +01:00
Rei
dc7e82b143 kollors
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-15 18:46:29 +01:00
Rei
703b611dfd sorted
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-15 18:29:52 +01:00
Rei
dd4f848071 divider
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-15 17:57:47 +01:00
Rei
46097b8390 style changes 2023-02-15 16:43:14 +01:00
e78bc12c49 merge
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-11 21:03:17 +01:00
aa3bb66d5e add custom directives 2023-02-11 21:00:28 +01:00
17 changed files with 2278 additions and 2119 deletions

41
components/ImageSlide.tsx Normal file
View File

@@ -0,0 +1,41 @@
import React, { useState } from "react";
import { AiFillLeftCircle } from "react-icons/ai";
export const ImageSlide = ({ children }: any) => {
const [current, setCurrent] = useState(0);
const length = children.length;
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 2);
};
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 2);
};
if (children.length <= 0) {
return null;
}
return (
<section className="slider">
<AiFillLeftCircle className="left-arrow" onClick={prevSlide} />
<AiFillLeftCircle className="right-arrow" onClick={nextSlide} />
{children.map((slide: any, index: any) => {
return (
<div
className={index === current ? "slide active" : "slide"}
key={index}
>
{index === current && (
<img
src={slide.props.children[0]}
alt="travel image"
className="image"
/>
)}
</div>
);
})}
</section>
);
};

View File

@@ -13,7 +13,7 @@ export const Navbar = () => {
const [showMenu, setShowMenu] = useState(false); const [showMenu, setShowMenu] = useState(false);
return ( return (
<nav className="py-4 xl:px-10 px-4 flex flex-row justify-between sticky top-0 bg-slate-100 dark:bg-gradient-dark z-50 border-b dark:border-gradient-light border-gray-200"> <nav className="py-4 xl:px-10 px-4 flex flex-row justify-between sticky top-0 z-50 bg-gradient-to-b from-black/50 to-black/30">
<Link <Link
href="/" href="/"
id="logo" id="logo"
@@ -28,7 +28,7 @@ export const Navbar = () => {
<div className="hidden xl:flex flex-row gap-10 items-center font-medium font-mono"> <div className="hidden xl:flex flex-row gap-10 items-center font-medium font-mono">
{links.map(({ name, href }) => ( {links.map(({ name, href }) => (
<Link href={href} key={name}> <Link href={href} key={name}>
<button className="px-10 py-1 rounded-sm bg-primary hover:bg-primary/50 transition-all duration-150 ease-out text-white"> <button className="px-10 py-1 rounded-sm bg-gradient-to-r from-indigo-500/30 to-fuchsia-500/20 hover:bg-primary/50 transition-all duration-150 ease-out text-white">
{name} {name}
</button> </button>
</Link> </Link>

View File

@@ -1,8 +1,8 @@
import { useRef, useMemo } from 'react' import { useRef, useMemo } from "react";
import { Canvas, useFrame } from '@react-three/fiber' import { Canvas, useFrame } from "@react-three/fiber";
import { BufferGeometry, Material, MathUtils, Mesh } from "three"; import { BufferGeometry, Material, MathUtils, Mesh } from "three";
import { vertexShader } from './Shaders/Background/vertex'; import { vertexShader } from "./Shaders/Background/vertex";
import { fragmentShader } from './Shaders/Background/fragment'; import { fragmentShader } from "./Shaders/Background/fragment";
const Fragment = () => { const Fragment = () => {
// This reference will give us direct access to the mesh // This reference will give us direct access to the mesh
@@ -21,12 +21,13 @@ const Fragment = () => {
); );
useFrame((state) => { useFrame((state) => {
if(!meshRef.current){ if (!meshRef.current) {
return; return;
} }
const { clock } = state; const { clock } = state;
//@ts-ignore //@ts-ignore
meshRef.current.material.uniforms.u_time.value = 0.4 * clock.getElapsedTime()/5; meshRef.current.material.uniforms.u_time.value =
(0.4 * clock.getElapsedTime()) / 5;
//@ts-ignore //@ts-ignore
meshRef.current.material.uniforms.u_intensity.value = MathUtils.lerp( meshRef.current.material.uniforms.u_intensity.value = MathUtils.lerp(
//@ts-ignore //@ts-ignore
@@ -37,7 +38,12 @@ const Fragment = () => {
}); });
return ( return (
<mesh ref={meshRef} position={[0, 0, 0]} rotation={[-Math.PI/17, Math.PI/20, 0]} scale={1.5}> <mesh
ref={meshRef}
position={[0, 0, 0]}
rotation={[-Math.PI / 17, Math.PI / 20, 0]}
scale={1.5}
>
<planeGeometry args={[30, 30, 200, 200]} /> <planeGeometry args={[30, 30, 200, 200]} />
<shaderMaterial <shaderMaterial
fragmentShader={fragmentShader} fragmentShader={fragmentShader}
@@ -49,10 +55,9 @@ const Fragment = () => {
); );
}; };
export const R3Gradient = () => { export const R3Gradient = () => {
return ( return (
<div className='-z-40 h-screen w-screen fixed bg-black opacity-60'> <div className="-z-40 h-screen w-screen fixed bg-black opacity-60 top-0 left-0 blur">
<Canvas camera={{ position: [0.0, 0.0, 5.0] }}> <Canvas camera={{ position: [0.0, 0.0, 5.0] }}>
<Fragment /> <Fragment />
</Canvas> </Canvas>

View File

@@ -17,7 +17,10 @@ import smartypants from "remark-smartypants";
import rehypeRaw from "rehype-raw"; import rehypeRaw from "rehype-raw";
import emoji from "remark-emoji"; import emoji from "remark-emoji";
import oembed from "@agentofuser/remark-oembed"; import oembed from "@agentofuser/remark-oembed";
import YouTube from "react-youtube"; import remarkDirective from "remark-directive";
import remarkDirectiveRehype from "remark-directive-rehype";
import { YouTubeVideo } from "./Youtube";
import { ImageSlide } from "./ImageSlide";
//import rehypeSanitize from "rehype-sanitize"; //import rehypeSanitize from "rehype-sanitize";
SyntaxHighlighter.registerLanguage("tsx", tsx); SyntaxHighlighter.registerLanguage("tsx", tsx);
@@ -27,28 +30,8 @@ SyntaxHighlighter.registerLanguage("bash", bash);
SyntaxHighlighter.registerLanguage("markdown", markdown); SyntaxHighlighter.registerLanguage("markdown", markdown);
SyntaxHighlighter.registerLanguage("json", json); SyntaxHighlighter.registerLanguage("json", json);
export const StyledMarkdown = ({ html }: { html: string }) => { export const StyledMarkdown = ({ html }: { html: string }) => {
const MarkdownComponents: Components = { const MarkdownComponents: Components = {
a: (props : any) => {
try {
const url = new URL(props.href);
if (
url.origin.includes("youtube.com") &&
props.node.position.start.column === 1
){
return (
<YouTube videoId={url.searchParams.get("v") || "dQw4w9WgXcQ"} />
);
}
} catch (e) {
//console.log(e);
}
return <a {...props} />;
},
h1: (props: any) => { h1: (props: any) => {
const arr = props.children; const arr = props.children;
let heading = ""; let heading = "";
@@ -126,11 +109,9 @@ export const StyledMarkdown = ({ html }: { html: string }) => {
); );
}, },
code({ node, inline, className, ...props }: any) { code({ node, inline, className, ...props }: any) {
const match = /language-(\w+)/.exec(className || ""); const match = /language-(\w+)/.exec(className || "");
const hasMeta = node?.data?.meta; const hasMeta = node?.data?.meta;
const applyHighlights: object = (applyHighlights: number) => { const applyHighlights: object = (applyHighlights: number) => {
if (hasMeta) { if (hasMeta) {
const RE = /{([\d,-]+)}/; const RE = /{([\d,-]+)}/;
@@ -170,7 +151,6 @@ export const StyledMarkdown = ({ html }: { html: string }) => {
return "Code"; return "Code";
}; };
return match ? ( return match ? (
<div> <div>
<div className="w-full flex flex-row items-center gap-4"> <div className="w-full flex flex-row items-center gap-4">
@@ -199,16 +179,20 @@ export const StyledMarkdown = ({ html }: { html: string }) => {
<code className={className} {...props} /> <code className={className} {...props} />
); );
}, },
//custom directives
//@ts-ignore
yt: YouTubeVideo,
"img-slide": ImageSlide,
}; };
return ( return (
<div <div
className=" className="
prose prose
prose-code:font-mono prose-code:text-gray-100 prose-code:bg-gray-700 prose-code:p-1 prose-code:m-1 prose-code:rounded-md prose-code:font-mono prose-code:text-gray-100 prose-code:bg-black/20 prose-code:p-1 prose-code:m-1 prose-code:rounded-md
prose-headings:text-gray-800 dark:prose-headings:text-gray-100 prose-p:text-gray-600 dark:prose-p:text-gray-300 prose-headings:text-gray-800 dark:prose-headings:text-gray-100 prose-p:text-gray-600 dark:prose-p:text-gray-300
prose-img:w-full prose-img:h-auto prose-img:object-cover prose-img:w-full prose-img:h-auto prose-img:object-cover
prose-li:text-gray-600 dark:prose-li:text-gray-300 prose-td:text-gray-600 dark:prose-td:text-gray-400 prose-li:text-gray-600 dark:prose-li:text-gray-200 prose-td:text-gray-600 dark:prose-td:text-gray-300
prose-a:text-primary prose-strong:text-gray-900 dark:prose-strong:text-gray-50 prose-a:text-primary prose-strong:text-gray-900 dark:prose-strong:text-gray-50
dark:prose-hr:bg-gray-200 prose-hr:bg-gray-400 dark:prose-hr:bg-gray-200 prose-hr:bg-gray-400
" "
@@ -216,7 +200,15 @@ export const StyledMarkdown = ({ html }: { html: string }) => {
<ReactMarkdown <ReactMarkdown
components={MarkdownComponents} components={MarkdownComponents}
rehypePlugins={[rehypeRaw]} rehypePlugins={[rehypeRaw]}
remarkPlugins={[oembed, remarkGfm, remarkTypograf, smartypants, emoji]} remarkPlugins={[
remarkDirective,
remarkDirectiveRehype,
oembed,
remarkGfm,
smartypants,
emoji,
remarkTypograf,
]}
children={html} children={html}
/> />
</div> </div>

5
components/Youtube.tsx Normal file
View File

@@ -0,0 +1,5 @@
export const YouTubeVideo = ({ id, children }: any) => (
<iframe src={'https://www.youtube.com/embed/' + id} className="w-full xl:h-96 md:h-80 h-64">
{children}
</iframe>
)

View File

@@ -12,20 +12,13 @@ From concept drawing to modeling to game engine. A neo-noir Game Concept inspire
### Sketches ### Sketches
#### Character Concept #### Character Concept
![](https://wiki.tum.de/download/attachments/1030785260/Character%20Design%201%20rework.png?version=1&modificationDate=1642430318357&api=v2) ::img-slide[https://wiki.tum.de/download/attachments/1030785260/Character%20Design%201%20rework.png?version=1&modificationDate=1642430318357&api=v2 https://wiki.tum.de/download/attachments/1030785260/Character%20Design%202.png?version=1&modificationDate=1642430320190&api=v2]{}
![](https://wiki.tum.de/download/attachments/1030785260/Character%20Design%202.png?version=1&modificationDate=1642430320190&api=v2)
#### Environment Concept #### Environment Concept
![](https://wiki.tum.de/download/attachments/1030785260/Env-Design%20Skizze.png?version=1&modificationDate=1642430334223&api=v2) ::img-slide[https://wiki.tum.de/download/attachments/1030785260/Env-Design%20Skizze.png?version=1&modificationDate=1642430334223&api=v2 https://wiki.tum.de/download/attachments/1030785260/Env-Design%20Final.png?version=1&modificationDate=1642430333137&api=v2]{}
![](https://wiki.tum.de/download/attachments/1030785260/Env-Design%20Final.png?version=1&modificationDate=1642430333137&api=v2)
### Models ### Models
![](https://docs.peroxy.dev/uploads/251bda2e-05e2-4fe4-828c-e3a747e5c9e8.png) ::img-slide[https://docs.peroxy.dev/uploads/251bda2e-05e2-4fe4-828c-e3a747e5c9e8.png https://docs.peroxy.dev/uploads/7a9e94b3-cb00-43bb-85ad-7fdf25e047fd.png https://docs.peroxy.dev/uploads/b8c07d01-11d6-4771-af21-4f208e443216.png https://docs.peroxy.dev/uploads/99cec6be-6239-46f3-a350-9ef9bfb60932.png https://docs.peroxy.dev/uploads/a3f69410-3e32-41a0-9f9a-c87f35d4cbfa.png https://docs.peroxy.dev/uploads/8b4cf730-48e4-422c-8cf5-590efd3e79b7.png]{}
![](https://docs.peroxy.dev/uploads/7a9e94b3-cb00-43bb-85ad-7fdf25e047fd.png)
![](https://docs.peroxy.dev/uploads/b8c07d01-11d6-4771-af21-4f208e443216.png)
![](https://docs.peroxy.dev/uploads/99cec6be-6239-46f3-a350-9ef9bfb60932.png)
![](https://docs.peroxy.dev/uploads/a3f69410-3e32-41a0-9f9a-c87f35d4cbfa.png)
![](https://docs.peroxy.dev/uploads/8b4cf730-48e4-422c-8cf5-590efd3e79b7.png)
### Final Render ### Final Render
![](https://wiki.tum.de/download/attachments/1030785260/render_third.png?version=1&modificationDate=1642430351370&api=v2) ![](https://wiki.tum.de/download/attachments/1030785260/render_third.png?version=1&modificationDate=1642430351370&api=v2)

View File

@@ -36,8 +36,7 @@ A Challenging mobile endless space shooter game.
### Gameplay Video ### Gameplay Video
::yt[Video of a cat in a box]{#1qquNEJrA10}
https://www.youtube.com/watch?v=1qquNEJrA10
## Links ## Links

View File

@@ -1,13 +1,12 @@
import { PropsWithChildren } from "react"; import { PropsWithChildren } from 'react'
import { R3Gradient } from '../components/R3Background'; import { R3Gradient } from '../components/R3Background'
import { Navbar } from "../components/Navbar"; import { Navbar } from '../components/Navbar'
export const MainLayout = ({ children }: PropsWithChildren) => { export const MainLayout = ({ children }: PropsWithChildren) => {
return ( return (
<div className="w-full"> <div className="w-full">
<Navbar /> <Navbar />
<R3Gradient />
<main className="xl:p-5 p-4 px-5 xl:mx-0">{children}</main> <main className="xl:p-5 p-4 px-5 xl:mx-0">{children}</main>
</div> </div>
); )
}; }

View File

@@ -20,10 +20,10 @@
"@types/three": "^0.149.0", "@types/three": "^0.149.0",
"framer-motion": "^8.0.2", "framer-motion": "^8.0.2",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"next": "13.0.6", "next": "^13.3.1",
"parse-numeric-range": "^1.3.0", "parse-numeric-range": "^1.3.0",
"react": "18.2.0", "react": "^18.2.0",
"react-dom": "18.2.0", "react-dom": "^18.2.0",
"react-icons": "^4.7.1", "react-icons": "^4.7.1",
"react-markdown": "^8.0.4", "react-markdown": "^8.0.4",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",

View File

@@ -1,6 +1,12 @@
import { R3Gradient } from '../components/R3Background'
import '../styles/globals.css' import '../styles/globals.css'
import type { AppProps } from 'next/app' import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) { export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} /> return (
<>
<R3Gradient />
<Component {...pageProps} />
</>
)
} }

View File

@@ -36,7 +36,7 @@ const Blog = ({ posts }: { posts: Post[] }) => {
<h1 className="text-3xl font-bold text-gray-800 dark:text-gray-200"> <h1 className="text-3xl font-bold text-gray-800 dark:text-gray-200">
Blog Blog
</h1> </h1>
<div className="w-full h-0.5 bg-violet-200 dark:bg-violet-700 my-4 rounded-full" /> <div className="w-full h-0.5 bg-violet-200 dark:bg-white/20 my-4 rounded-full" />
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{posts.map((post, index) => ( {posts.map((post, index) => (
<BlogCard <BlogCard

View File

@@ -3,7 +3,7 @@ export default function Home() {
return ( return (
<MainLayout> <MainLayout>
<div className="grid lg:grid-cols-2 grid-cols-1 xl:mt-10 gap-10 items-center"> <div className="grid lg:grid-cols-2 grid-cols-1 xl:mt-10 gap-10 items-center">
<div className="bg-primary-dark p-10 rounded-lg flex flex-col gap-10 h-fit 3xl:w-2/3 w-full text-lg text-primary-text/90 shadow-lg shadow-gradient-dark/20"> <div className="bg-primary-dark/30 border-white/30 border p-10 rounded-lg flex flex-col gap-10 h-fit 3xl:w-2/3 w-full text-lg text-primary-text/90 shadow-lg shadow-gradient-dark/20">
<div> <div>
<span className="font-bold text-xl text-primary-text"> <span className="font-bold text-xl text-primary-text">
Lorem ipsum dolor{" "} Lorem ipsum dolor{" "}

View File

@@ -1,7 +1,11 @@
import { GetStaticPaths, GetStaticProps } from "next"; import { GetStaticPaths, GetStaticProps } from "next";
import fs from "fs"; import fs from "fs";
import { ParsedUrlQuery } from "querystring"; import { ParsedUrlQuery } from "querystring";
import { getProjectContentBySlug, PROJECTS_PATH } from "../../utils/markdown"; import {
getHeadings,
getProjectContentBySlug,
PROJECTS_PATH,
} from "../../utils/markdown";
import { MarkdownRenderingResult } from "../../types/types"; import { MarkdownRenderingResult } from "../../types/types";
import { MainLayout } from "../../layouts/MainLayout"; import { MainLayout } from "../../layouts/MainLayout";
import Link from "next/link"; import Link from "next/link";
@@ -52,6 +56,9 @@ export const getStaticProps: GetStaticProps<MarkdownRenderingResult> = async ({
params, params,
}) => { }) => {
const markdownContent = getProjectContentBySlug(params?.slug as string); const markdownContent = getProjectContentBySlug(params?.slug as string);
console.log(getHeadings(markdownContent.content));
return { return {
props: { props: {
frontMatter: markdownContent.frontMatter, frontMatter: markdownContent.frontMatter,

View File

@@ -1,27 +1,17 @@
import { GetServerSideProps } from "next"; import { GetServerSideProps } from 'next'
import { MainLayout } from "../../layouts/MainLayout"; import { MainLayout } from '../../layouts/MainLayout'
import { Post, getAllProjectsFrontMatter } from "../../utils/markdown"; import { Post, getAllProjectsFrontMatter } from '../../utils/markdown'
import Link from "next/link"; import Link from 'next/link'
import { formatDate } from "../../utils/general"; import { formatDate } from '../../utils/general'
import { BasicArticleProps } from "../../components/PostHeader"; import { BasicArticleProps } from '../../components/PostHeader'
const ProjectCard = ({ const ProjectCard = ({ project, slug }: { project: BasicArticleProps; slug: string }) => {
project,
slug,
}: {
project: BasicArticleProps;
slug: string;
}) => {
return ( return (
<div className="p-4 rounded-md border border-gray-200 shadow-md shadow-gray-200 dark:shadow-gray-900 dark:border-gray-700 grid grid-cols-1 xl:grid-cols-2 items-center gap-4 bg-black bg-opacity-60"> <div className="p-4 rounded-md border border-gray-200 shadow-md shadow-gray-200 dark:shadow-gray-900 dark:border-gray-700 grid grid-cols-1 xl:grid-cols-2 items-center gap-4 bg-black bg-opacity-60">
<div className="order-last xl:order-1"> <div className="order-last xl:order-1">
<div className="text-sm font-medium text-gray-500"> <div className="text-sm font-medium text-gray-500">{formatDate(project.date)}</div>
{formatDate(project.date)}
</div>
<h2 className="text-2xl font-bold">{project.title}</h2> <h2 className="text-2xl font-bold">{project.title}</h2>
<p className="text-gray-600 dark:text-gray-400 text-sm"> <p className="text-gray-600 dark:text-gray-400 text-sm">{project.description}</p>
{project.description}
</p>
<Link href={`project/${slug}`}> <Link href={`project/${slug}`}>
<button className="bg-action px-2 py-1 rounded-md mt-4 hover:bg-action/60 transition-all ease-in duration-100 font-bold text-white"> <button className="bg-action px-2 py-1 rounded-md mt-4 hover:bg-action/60 transition-all ease-in duration-100 font-bold text-white">
Read more Read more
@@ -36,36 +26,30 @@ const ProjectCard = ({
/> />
)} )}
</div> </div>
); )
}; }
const Projects = ({ posts }: { posts: Post[] }) => { const Projects = ({ posts }: { posts: Post[] }) => {
return ( return (
<MainLayout> <MainLayout>
<h1 className="text-3xl font-bold text-gray-800 dark:text-gray-100"> <h1 className="text-3xl font-bold text-gray-800 dark:text-gray-100">Projects</h1>
Projects <div className="w-full h-0.5 bg-violet-200 dark:bg-white/20 my-4 rounded-full" />
</h1>
<div className="w-full h-0.5 bg-violet-200 dark:bg-violet-700 my-4 rounded-full" />
<div className="grid grid-cols-1 gap-4"> <div className="grid grid-cols-1 gap-4">
{posts.map((post, index) => ( {posts.map((post, index) => (
<ProjectCard <ProjectCard key={index} project={post.frontMatter as BasicArticleProps} slug={post.slug} />
key={index}
project={post.frontMatter as BasicArticleProps}
slug={post.slug}
/>
))} ))}
</div> </div>
</MainLayout> </MainLayout>
); )
}; }
export const getServerSideProps: GetServerSideProps = async () => { export const getServerSideProps: GetServerSideProps = async () => {
const posts = getAllProjectsFrontMatter(); const posts = getAllProjectsFrontMatter()
return { return {
props: { props: {
posts, posts,
}, },
}; }
}; }
export default Projects; export default Projects

View File

@@ -19,22 +19,25 @@ main {
} }
pre { pre {
@apply dark:bg-slate-800 bg-slate-200 text-slate-800 dark:text-slate-200 !important; @apply dark:bg-black/30 bg-slate-200 text-slate-800 dark:text-slate-200 !important;
} }
pre > code { pre > code {
@apply bg-transparent text-gray-700 dark:text-slate-300 !important; @apply bg-transparent text-gray-700 dark:text-slate-300 !important;
} }
.codeStyle > code { .codeStyle {
background: transparent; @apply bg-transparent !important;
} }
pre > div > div > button > svg:hover { pre > div > div > button > svg:hover {
@apply hover:text-action transition-all ease-in-out duration-100 !important; @apply hover:text-action transition-all ease-in-out duration-100 !important;
} }
h1 > a, h2 > a, h3 > a, h4 > a { h1 > a,
h2 > a,
h3 > a,
h4 > a {
@apply cursor-pointer relative text-gray-800 dark:text-gray-100 decoration-transparent font-bold !important; @apply cursor-pointer relative text-gray-800 dark:text-gray-100 decoration-transparent font-bold !important;
} }
@@ -42,9 +45,69 @@ h1 > a:hover::before,
h2 > a:hover::before, h2 > a:hover::before,
h3 > a:hover::before, h3 > a:hover::before,
h4 > a:hover::before { h4 > a:hover::before {
@apply content-['#'] absolute -left-8 text-gray-300 dark:text-gray-600; @apply content-['#'] absolute -left-8 text-gray-300 dark:text-gray-400;
} }
div > code, pre > code { h2 > a:hover::before {
@apply p-0 m-0 !important @apply -left-6;
}
h3 > a:hover::before {
@apply -left-5;
}
h4 > a:hover::before {
@apply -left-4;
}
div > code,
pre > code {
@apply p-0 m-0 !important;
}
.slider {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.image {
width: 1000px;
height: 600px;
border-radius: 10px;
}
.right-arrow {
position: absolute;
top: 50%;
right: 0%;
font-size: 2rem;
rotate: 180deg;
color: #bdbdbd;
z-index: 10;
cursor: pointer;
user-select: none;
}
.left-arrow {
position: absolute;
top: 50%;
left: -5%;
font-size: 2rem;
color: #bdbdbd;
z-index: 10;
cursor: pointer;
user-select: none;
}
.slide {
opacity: 0;
transition-duration: 0.5s ease;
}
.slide.active {
opacity: 1;
transition-duration: 0.5s;
transform: scale(0.8);
} }

View File

@@ -4,8 +4,6 @@ import fs from "fs";
import { FrontMatter, MarkdownDocument } from "../types/types"; import { FrontMatter, MarkdownDocument } from "../types/types";
import { remark } from "remark"; import { remark } from "remark";
import html from "remark-html"; import html from "remark-html";
import remarkGfm from "remark-gfm";
export const BLOGS_PATH = join(process.cwd(), "content/blogs"); export const BLOGS_PATH = join(process.cwd(), "content/blogs");
export const PROJECTS_PATH = join(process.cwd(), "content/projects"); export const PROJECTS_PATH = join(process.cwd(), "content/projects");
@@ -14,6 +12,14 @@ export interface Post {
slug: string; slug: string;
} }
const getDate = (date: string) => {
if (typeof date === "string") {
const d = date.split(".").map((v) => +v);
return new Date(d[2], d[1] - 1, d[0]);
}
return new Date();
};
export const getBlogContentBySlug = (slug: string): MarkdownDocument => { export const getBlogContentBySlug = (slug: string): MarkdownDocument => {
const filepath = join(BLOGS_PATH, `${slug}.md` || `${slug}.mdx`); const filepath = join(BLOGS_PATH, `${slug}.md` || `${slug}.mdx`);
const filecontents = fs.readFileSync(filepath); const filecontents = fs.readFileSync(filepath);
@@ -40,22 +46,50 @@ export const getProjectContentBySlug = (slug: string): MarkdownDocument => {
export const getAllBlogsFrontMatter = (): Post[] => { export const getAllBlogsFrontMatter = (): Post[] => {
const files = fs.readdirSync(BLOGS_PATH); const files = fs.readdirSync(BLOGS_PATH);
return files.reduce((allPosts: Post[], postSlug: string) => { const blogs = files.reduce((allPosts: Post[], postSlug: string) => {
const slug = postSlug.replace(".md", ""); const slug = postSlug.replace(".md", "");
const post = getBlogContentBySlug(slug); const post = getBlogContentBySlug(slug);
return [{ frontMatter: post.frontMatter, slug }, ...allPosts]; return [{ frontMatter: post.frontMatter, slug }, ...allPosts];
}, []); }, []);
return blogs.sort(
//@ts-ignore
(a, b) => getDate(b.frontMatter.date) - getDate(a.frontMatter.date)
);
}; };
export const getAllProjectsFrontMatter = (): Post[] => { export const getAllProjectsFrontMatter = (): Post[] => {
const files = fs.readdirSync(PROJECTS_PATH); const files = fs.readdirSync(PROJECTS_PATH);
return files.reduce((allPosts: Post[], postSlug: string) => { const projects = files.reduce((allPosts: Post[], postSlug: string) => {
const slug = postSlug.replace(".md", ""); const slug = postSlug.replace(".md", "");
const post = getProjectContentBySlug(slug); const post = getProjectContentBySlug(slug);
return [{ frontMatter: post.frontMatter, slug }, ...allPosts]; return [{ frontMatter: post.frontMatter, slug }, ...allPosts];
}, []); }, []);
return projects.sort(
//@ts-ignore
(a, b) => getDate(b.frontMatter.date) - getDate(a.frontMatter.date)
);
};
export const getHeadings = (markdown: string): any => {
const headingOne = markdown.match(/^(#{1})\s(.*)/gm);
const headingTwo = markdown.match(/^(#{2})\s(.*)/gm);
const headingThree = markdown.match(/^(#{3})\s(.*)/gm);
const headingFour = markdown.match(/^(#{4})\s(.*)/gm);
const headings = markdown.match(/^(#{1,4})\s(.*)/gm);
var tree: any[] = [];
var prev = "";
headings?.forEach((heading) => {
if (headingOne?.includes(heading)) {
tree.push(heading);
}
});
return tree;
}; };
export async function markdownToHtml(markdown: any) { export async function markdownToHtml(markdown: any) {

3975
yarn.lock

File diff suppressed because it is too large Load Diff