chore: remove junk
This commit is contained in:
parent
f6dcc302d4
commit
8f6872f739
96 changed files with 1002 additions and 2485 deletions
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import type { CollectionEntry } from 'astro:content'
|
||||
|
||||
type Props = {
|
||||
entry: CollectionEntry<"blog">;
|
||||
};
|
||||
entry: CollectionEntry<'blog'>
|
||||
}
|
||||
|
||||
const { entry } = Astro.props as {
|
||||
entry: CollectionEntry<"blog">;
|
||||
};
|
||||
entry: CollectionEntry<'blog'>
|
||||
}
|
||||
---
|
||||
|
||||
<a
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
type Props = {
|
||||
href: string;
|
||||
};
|
||||
href: string
|
||||
}
|
||||
|
||||
const { href } = Astro.props;
|
||||
const { href } = Astro.props
|
||||
---
|
||||
|
||||
<a
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
---
|
||||
export interface Props {
|
||||
institution: string;
|
||||
time: string;
|
||||
job_title: string;
|
||||
location: string;
|
||||
description: string
|
||||
}
|
||||
|
||||
const { institution, time, job_title, location, description } = Astro.props;
|
||||
institution: string
|
||||
time: string
|
||||
job_title: string
|
||||
location: string
|
||||
description: string
|
||||
}
|
||||
|
||||
const { institution, time, job_title, location, description } = Astro.props
|
||||
---
|
||||
|
||||
<div class="py-5 px-8">
|
||||
<div class="flex justify-between text-sm font-bold md:text-lg">
|
||||
<div>{institution}</div>
|
||||
<div>{location}</div>
|
||||
</div>
|
||||
<div class="flex justify-between text-xs md:text-base">
|
||||
<div class="italic">{job_title}</div>
|
||||
<div>{time}</div>
|
||||
</div>
|
||||
<p class="text-xs mt-2">{description}</p>
|
||||
</div>
|
||||
<div class="px-8 py-5">
|
||||
<div class="flex justify-between text-sm font-bold md:text-lg">
|
||||
<div>{institution}</div>
|
||||
<div>{location}</div>
|
||||
</div>
|
||||
<div class="flex justify-between text-xs md:text-base">
|
||||
<div class="italic">{job_title}</div>
|
||||
<div>{time}</div>
|
||||
</div>
|
||||
<p class="mt-2 text-xs">{description}</p>
|
||||
</div>
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
---
|
||||
interface Component {
|
||||
type: "default" | "info" | "warning" | "error";
|
||||
type: 'default' | 'info' | 'warning' | 'error'
|
||||
}
|
||||
|
||||
const { type = "default" } = Astro.props;
|
||||
const { type = 'default' } = Astro.props
|
||||
|
||||
let emoji = "💡";
|
||||
let emoji = '💡'
|
||||
|
||||
if (type === "info") {
|
||||
emoji = "ℹ️";
|
||||
} else if (type === "warning") {
|
||||
emoji = "⚠️";
|
||||
} else if (type === "error") {
|
||||
emoji = "🚨";
|
||||
if (type === 'info') {
|
||||
emoji = 'ℹ️'
|
||||
} else if (type === 'warning') {
|
||||
emoji = '⚠️'
|
||||
} else if (type === 'error') {
|
||||
emoji = '🚨'
|
||||
}
|
||||
---
|
||||
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
import Container from "@components/Container.astro";
|
||||
import { SITE } from "@consts";
|
||||
import BackToTop from "@components/BackToTop.astro";
|
||||
import SocialIcons from "./SocialIcons.astro";
|
||||
import Container from '@components/Container.astro'
|
||||
import { SITE } from '@consts'
|
||||
import BackToTop from '@components/BackToTop.astro'
|
||||
import SocialIcons from './SocialIcons.astro'
|
||||
---
|
||||
|
||||
<footer class="animate">
|
||||
<Container>
|
||||
<div class="flex justify-between my-2">
|
||||
<div class="my-2 flex justify-between">
|
||||
<SocialIcons icon_size={'text-xl'} />
|
||||
<BackToTop />
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>© {new Date().getFullYear()} • {SITE.TITLE} 👀<br>
|
||||
Built with Astro
|
||||
<div>
|
||||
© {new Date().getFullYear()} • {SITE.TITLE} 👀<br />
|
||||
Built with Astro
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-1.5">
|
||||
<button
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
interface Props {
|
||||
date: Date;
|
||||
date: Date
|
||||
}
|
||||
|
||||
const { date } = Astro.props;
|
||||
const { date } = Astro.props
|
||||
---
|
||||
|
||||
<time datetime={date.toISOString()}>
|
||||
{
|
||||
date.toLocaleDateString("en-US", {
|
||||
month: "long",
|
||||
day: "2-digit",
|
||||
year: "numeric",
|
||||
date.toLocaleDateString('en-US', {
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
year: 'numeric',
|
||||
})
|
||||
}
|
||||
</time>
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
---
|
||||
import "../styles/global.css";
|
||||
import { ViewTransitions } from "astro:transitions";
|
||||
import '../styles/global.css'
|
||||
import { ViewTransitions } from 'astro:transitions'
|
||||
|
||||
import "@fontsource/geist-sans";
|
||||
import "@fontsource/geist-mono";
|
||||
import '@fontsource/geist-sans'
|
||||
import '@fontsource/geist-mono'
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
image?: string;
|
||||
title: string
|
||||
description: string
|
||||
image?: string
|
||||
}
|
||||
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site)
|
||||
|
||||
const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
|
||||
const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props
|
||||
---
|
||||
|
||||
<!-- Global Metadata -->
|
||||
|
@ -48,116 +48,112 @@ const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
|
|||
<meta property="twitter:description" content={description} />
|
||||
<meta property="twitter:image" content={new URL(image, Astro.url)} />
|
||||
|
||||
<!-- PageFind -->
|
||||
<link href="/pagefind/pagefind-ui.css" rel="stylesheet" />
|
||||
<script is:inline src="/pagefind/pagefind-ui.js"></script>
|
||||
|
||||
<ViewTransitions />
|
||||
|
||||
<script is:inline>
|
||||
function init() {
|
||||
preloadTheme();
|
||||
onScroll();
|
||||
animate();
|
||||
updateThemeButtons();
|
||||
addCopyCodeButtons();
|
||||
setGiscusTheme();
|
||||
preloadTheme()
|
||||
onScroll()
|
||||
animate()
|
||||
updateThemeButtons()
|
||||
addCopyCodeButtons()
|
||||
setGiscusTheme()
|
||||
|
||||
const backToTop = document.getElementById("back-to-top");
|
||||
backToTop?.addEventListener("click", (event) => scrollToTop(event));
|
||||
const backToTop = document.getElementById('back-to-top')
|
||||
backToTop?.addEventListener('click', (event) => scrollToTop(event))
|
||||
|
||||
const backToPrev = document.getElementById("back-to-prev");
|
||||
backToPrev?.addEventListener("click", () => window.history.back());
|
||||
const backToPrev = document.getElementById('back-to-prev')
|
||||
backToPrev?.addEventListener('click', () => window.history.back())
|
||||
|
||||
const lightThemeButton = document.getElementById("light-theme-button");
|
||||
lightThemeButton?.addEventListener("click", () => {
|
||||
localStorage.setItem("theme", "light");
|
||||
toggleTheme(false);
|
||||
updateThemeButtons();
|
||||
});
|
||||
const lightThemeButton = document.getElementById('light-theme-button')
|
||||
lightThemeButton?.addEventListener('click', () => {
|
||||
localStorage.setItem('theme', 'light')
|
||||
toggleTheme(false)
|
||||
updateThemeButtons()
|
||||
})
|
||||
|
||||
const darkThemeButton = document.getElementById("dark-theme-button");
|
||||
darkThemeButton?.addEventListener("click", () => {
|
||||
localStorage.setItem("theme", "dark");
|
||||
toggleTheme(true);
|
||||
updateThemeButtons();
|
||||
});
|
||||
const darkThemeButton = document.getElementById('dark-theme-button')
|
||||
darkThemeButton?.addEventListener('click', () => {
|
||||
localStorage.setItem('theme', 'dark')
|
||||
toggleTheme(true)
|
||||
updateThemeButtons()
|
||||
})
|
||||
|
||||
const systemThemeButton = document.getElementById("system-theme-button");
|
||||
systemThemeButton?.addEventListener("click", () => {
|
||||
localStorage.setItem("theme", "system");
|
||||
toggleTheme(window.matchMedia("(prefers-color-scheme: dark)").matches);
|
||||
updateThemeButtons();
|
||||
});
|
||||
const systemThemeButton = document.getElementById('system-theme-button')
|
||||
systemThemeButton?.addEventListener('click', () => {
|
||||
localStorage.setItem('theme', 'system')
|
||||
toggleTheme(window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
updateThemeButtons()
|
||||
})
|
||||
|
||||
window
|
||||
.matchMedia("(prefers-color-scheme: dark)")
|
||||
.addEventListener("change", (event) => {
|
||||
if (localStorage.theme === "system") {
|
||||
toggleTheme(event.matches);
|
||||
.matchMedia('(prefers-color-scheme: dark)')
|
||||
.addEventListener('change', (event) => {
|
||||
if (localStorage.theme === 'system') {
|
||||
toggleTheme(event.matches)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
document.addEventListener("scroll", onScroll);
|
||||
document.addEventListener('scroll', onScroll)
|
||||
}
|
||||
|
||||
function updateThemeButtons() {
|
||||
const theme = localStorage.getItem("theme");
|
||||
const lightThemeButton = document.getElementById("light-theme-button");
|
||||
const darkThemeButton = document.getElementById("dark-theme-button");
|
||||
const systemThemeButton = document.getElementById("system-theme-button");
|
||||
const theme = localStorage.getItem('theme')
|
||||
const lightThemeButton = document.getElementById('light-theme-button')
|
||||
const darkThemeButton = document.getElementById('dark-theme-button')
|
||||
const systemThemeButton = document.getElementById('system-theme-button')
|
||||
|
||||
function removeActiveButtonTheme(button) {
|
||||
button?.classList.remove("bg-black/5");
|
||||
button?.classList.remove("dark:bg-white/5");
|
||||
button?.classList.remove('bg-black/5')
|
||||
button?.classList.remove('dark:bg-white/5')
|
||||
}
|
||||
|
||||
function addActiveButtonTheme(button) {
|
||||
button?.classList.add("bg-black/5");
|
||||
button?.classList.add("dark:bg-white/5");
|
||||
button?.classList.add('bg-black/5')
|
||||
button?.classList.add('dark:bg-white/5')
|
||||
}
|
||||
|
||||
removeActiveButtonTheme(lightThemeButton);
|
||||
removeActiveButtonTheme(darkThemeButton);
|
||||
removeActiveButtonTheme(systemThemeButton);
|
||||
removeActiveButtonTheme(lightThemeButton)
|
||||
removeActiveButtonTheme(darkThemeButton)
|
||||
removeActiveButtonTheme(systemThemeButton)
|
||||
|
||||
if (theme === "light") {
|
||||
addActiveButtonTheme(lightThemeButton);
|
||||
} else if (theme === "dark") {
|
||||
addActiveButtonTheme(darkThemeButton);
|
||||
if (theme === 'light') {
|
||||
addActiveButtonTheme(lightThemeButton)
|
||||
} else if (theme === 'dark') {
|
||||
addActiveButtonTheme(darkThemeButton)
|
||||
} else {
|
||||
addActiveButtonTheme(systemThemeButton);
|
||||
addActiveButtonTheme(systemThemeButton)
|
||||
}
|
||||
}
|
||||
|
||||
function animate() {
|
||||
const animateElements = document.querySelectorAll(".animate");
|
||||
const animateElements = document.querySelectorAll('.animate')
|
||||
|
||||
animateElements.forEach((element, index) => {
|
||||
setTimeout(() => {
|
||||
element.classList.add("show");
|
||||
}, index * 100);
|
||||
});
|
||||
element.classList.add('show')
|
||||
}, index * 100)
|
||||
})
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
if (window.scrollY > 0) {
|
||||
document.documentElement.classList.add("scrolled");
|
||||
document.documentElement.classList.add('scrolled')
|
||||
} else {
|
||||
document.documentElement.classList.remove("scrolled");
|
||||
document.documentElement.classList.remove('scrolled')
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToTop(event) {
|
||||
event.preventDefault();
|
||||
event.preventDefault()
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: "smooth",
|
||||
});
|
||||
behavior: 'smooth',
|
||||
})
|
||||
}
|
||||
|
||||
function toggleTheme(dark) {
|
||||
const css = document.createElement("style");
|
||||
const css = document.createElement('style')
|
||||
|
||||
css.appendChild(
|
||||
document.createTextNode(
|
||||
|
@ -168,84 +164,84 @@ const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
|
|||
-ms-transition: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
`
|
||||
)
|
||||
);
|
||||
`,
|
||||
),
|
||||
)
|
||||
|
||||
document.head.appendChild(css);
|
||||
document.head.appendChild(css)
|
||||
|
||||
if (dark) {
|
||||
document.documentElement.classList.add("dark");
|
||||
document.documentElement.classList.add('dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
|
||||
window.getComputedStyle(css).opacity;
|
||||
document.head.removeChild(css);
|
||||
window.getComputedStyle(css).opacity
|
||||
document.head.removeChild(css)
|
||||
|
||||
setGiscusTheme();
|
||||
setGiscusTheme()
|
||||
}
|
||||
|
||||
function preloadTheme() {
|
||||
const userTheme = localStorage.theme;
|
||||
const userTheme = localStorage.theme
|
||||
|
||||
if (userTheme === "light" || userTheme === "dark") {
|
||||
toggleTheme(true); // set default to dark theme
|
||||
if (userTheme === 'light' || userTheme === 'dark') {
|
||||
toggleTheme(true) // set default to dark theme
|
||||
} else {
|
||||
toggleTheme(window.matchMedia("(prefers-color-scheme: dark)").matches);
|
||||
toggleTheme(window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
}
|
||||
}
|
||||
|
||||
function addCopyCodeButtons() {
|
||||
let copyButtonLabel = "📋";
|
||||
let codeBlocks = Array.from(document.querySelectorAll("pre"));
|
||||
let copyButtonLabel = '📋'
|
||||
let codeBlocks = Array.from(document.querySelectorAll('pre'))
|
||||
|
||||
async function copyCode(codeBlock, copyButton) {
|
||||
const codeText = codeBlock.innerText;
|
||||
const buttonText = copyButton.innerText;
|
||||
const textToCopy = codeText.replace(buttonText, "");
|
||||
const codeText = codeBlock.innerText
|
||||
const buttonText = copyButton.innerText
|
||||
const textToCopy = codeText.replace(buttonText, '')
|
||||
|
||||
await navigator.clipboard.writeText(textToCopy);
|
||||
copyButton.innerText = "✅";
|
||||
await navigator.clipboard.writeText(textToCopy)
|
||||
copyButton.innerText = '✅'
|
||||
|
||||
setTimeout(() => {
|
||||
copyButton.innerText = copyButtonLabel;
|
||||
}, 2000);
|
||||
copyButton.innerText = copyButtonLabel
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
for (let codeBlock of codeBlocks) {
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.style.position = "relative";
|
||||
const wrapper = document.createElement('div')
|
||||
wrapper.style.position = 'relative'
|
||||
|
||||
const copyButton = document.createElement("button");
|
||||
copyButton.innerText = copyButtonLabel;
|
||||
copyButton.classList = "copy-code";
|
||||
const copyButton = document.createElement('button')
|
||||
copyButton.innerText = copyButtonLabel
|
||||
copyButton.classList = 'copy-code'
|
||||
|
||||
codeBlock.setAttribute("tabindex", "0");
|
||||
codeBlock.appendChild(copyButton);
|
||||
codeBlock.setAttribute('tabindex', '0')
|
||||
codeBlock.appendChild(copyButton)
|
||||
|
||||
codeBlock.parentNode.insertBefore(wrapper, codeBlock);
|
||||
wrapper.appendChild(codeBlock);
|
||||
codeBlock.parentNode.insertBefore(wrapper, codeBlock)
|
||||
wrapper.appendChild(codeBlock)
|
||||
|
||||
copyButton?.addEventListener("click", async () => {
|
||||
await copyCode(codeBlock, copyButton);
|
||||
});
|
||||
copyButton?.addEventListener('click', async () => {
|
||||
await copyCode(codeBlock, copyButton)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const setGiscusTheme = () => {
|
||||
const giscus = document.querySelector(".giscus-frame");
|
||||
const giscus = document.querySelector('.giscus-frame')
|
||||
|
||||
const isDark = document.documentElement.classList.contains("dark");
|
||||
const isDark = document.documentElement.classList.contains('dark')
|
||||
|
||||
if (giscus) {
|
||||
const url = new URL(giscus.src);
|
||||
url.searchParams.set("theme", isDark ? "dark" : "light");
|
||||
giscus.src = url.toString();
|
||||
const url = new URL(giscus.src)
|
||||
url.searchParams.set('theme', isDark ? 'dark' : 'light')
|
||||
giscus.src = url.toString()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => init());
|
||||
document.addEventListener("astro:after-swap", () => init());
|
||||
preloadTheme();
|
||||
document.addEventListener('DOMContentLoaded', () => init())
|
||||
document.addEventListener('astro:after-swap', () => init())
|
||||
preloadTheme()
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
import Container from "@components/Container.astro";
|
||||
import Link from "@components/Link.astro";
|
||||
import { SITE } from "@consts";
|
||||
import ProgressBar from "./ProgressBar.astro";
|
||||
import Container from '@components/Container.astro'
|
||||
import Link from '@components/Link.astro'
|
||||
import { SITE } from '@consts'
|
||||
import ProgressBar from './ProgressBar.astro'
|
||||
---
|
||||
|
||||
<header transition:persist>
|
||||
|
|
|
@ -1,29 +1,23 @@
|
|||
---
|
||||
import { cn } from "@lib/utils";
|
||||
import { cn } from '@lib/utils'
|
||||
|
||||
type Props = {
|
||||
href: string;
|
||||
external?: boolean;
|
||||
underline?: boolean;
|
||||
group?: boolean;
|
||||
};
|
||||
href: string
|
||||
external?: boolean
|
||||
underline?: boolean
|
||||
group?: boolean
|
||||
}
|
||||
|
||||
const {
|
||||
href,
|
||||
external,
|
||||
underline = true,
|
||||
group = false,
|
||||
...rest
|
||||
} = Astro.props;
|
||||
const { href, external, underline = true, group = false, ...rest } = Astro.props
|
||||
---
|
||||
|
||||
<a
|
||||
href={href}
|
||||
target={external ? "_blank" : "_self"}
|
||||
target={external ? '_blank' : '_self'}
|
||||
class={cn(
|
||||
"inline-block decoration-black/30 hover:decoration-black/50 focus-visible:decoration-black/50 dark:decoration-white/30 dark:hover:decoration-white/50 dark:focus-visible:decoration-white/50 hover:text-cyan-500 focus-visible:text-black dark:hover:text-orange-500 dark:focus-visible:text-white transition-colors duration-300 ease-in-out",
|
||||
underline && "underline underline-offset-[3px]",
|
||||
group && "group"
|
||||
'inline-block decoration-black/30 hover:decoration-black/50 focus-visible:decoration-black/50 dark:decoration-white/30 dark:hover:decoration-white/50 dark:focus-visible:decoration-white/50 hover:text-cyan-500 focus-visible:text-black dark:hover:text-orange-500 dark:focus-visible:text-white transition-colors duration-300 ease-in-out',
|
||||
underline && 'underline underline-offset-[3px]',
|
||||
group && 'group',
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
---
|
||||
import Search from "astro-pagefind/components/Search";
|
||||
---
|
||||
|
||||
<aside data-pagefind-ignore>
|
||||
<div
|
||||
transition:persist
|
||||
id="backdrop"
|
||||
class="bg-[rgba(0, 0, 0, 0.5] invisible fixed left-0 top-0 z-50 flex h-screen w-full justify-center p-6 backdrop-blur-sm"
|
||||
>
|
||||
<div
|
||||
id="pagefind-container"
|
||||
class="m-0 flex h-fit max-h-[80%] w-full max-w-screen-sm flex-col overflow-auto rounded border border-black/15 bg-neutral-100 p-2 px-4 py-3 shadow-lg dark:border-white/20 dark:bg-neutral-900"
|
||||
>
|
||||
<Search
|
||||
id="search"
|
||||
className="pagefind-ui"
|
||||
uiOptions={{
|
||||
showImages: false,
|
||||
excerptLength: 15,
|
||||
resetStyles: false,
|
||||
}}
|
||||
/>
|
||||
<div class="mr-2 pb-1 pt-4 text-right text-xs dark:prose-invert">
|
||||
Press <span class="prose text-xs dark:prose-invert"
|
||||
><kbd class="">Esc</kbd></span
|
||||
> or click anywhere to close
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<script is:inline>
|
||||
const magnifyingGlass = document.getElementById("magnifying-glass");
|
||||
const backdrop = document.getElementById("backdrop");
|
||||
|
||||
function openPagefind() {
|
||||
const searchDiv = document.getElementById("search");
|
||||
const search = searchDiv.querySelector("input");
|
||||
setTimeout(() => {
|
||||
search.focus();
|
||||
}, 0);
|
||||
backdrop?.classList.remove("invisible");
|
||||
backdrop?.classList.add("visible");
|
||||
}
|
||||
|
||||
function closePagefind() {
|
||||
const search = document.getElementById("search");
|
||||
search.value = "";
|
||||
backdrop?.classList.remove("visible");
|
||||
backdrop?.classList.add("invisible");
|
||||
}
|
||||
|
||||
// open pagefind
|
||||
magnifyingGlass?.addEventListener("click", () => {
|
||||
openPagefind();
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "/") {
|
||||
e.preventDefault();
|
||||
openPagefind();
|
||||
} else if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
||||
e.preventDefault();
|
||||
openPagefind();
|
||||
}
|
||||
});
|
||||
|
||||
// close pagefind
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape" || e.keyCode === 27) {
|
||||
closePagefind();
|
||||
}
|
||||
});
|
||||
|
||||
// close pagefind when searched result(link) clicked
|
||||
document.addEventListener("click", (event) => {
|
||||
if (event.target.classList.contains("pagefind-ui__result-link")) {
|
||||
closePagefind();
|
||||
}
|
||||
});
|
||||
|
||||
backdrop?.addEventListener("click", (event) => {
|
||||
if (!event.target.closest("#pagefind-container")) {
|
||||
closePagefind();
|
||||
}
|
||||
});
|
||||
|
||||
// prevent form submission
|
||||
const form = document.getElementById("form");
|
||||
form?.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style is:global>
|
||||
:root {
|
||||
--pagefind-ui-scale: 0.75;
|
||||
--pagefind-ui-border-width: 1px;
|
||||
--pagefind-ui-border-radius: 3px;
|
||||
--pagefind-ui-font: "Geist", sans-serif;
|
||||
--pagefind-ui-primary: #3d3d3d;
|
||||
--pagefind-ui-text: #3d3d3d;
|
||||
--pagefind-ui-background: #ffffff;
|
||||
--pagefind-ui-border: #d0d0d0;
|
||||
--pagefind-ui-tag: #f5f5f5;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--pagefind-ui-primary: #d4d4d4;
|
||||
--pagefind-ui-text: #d4d4d4;
|
||||
--pagefind-ui-background: #171717;
|
||||
--pagefind-ui-border: #404040;
|
||||
}
|
||||
|
||||
#search input {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#search p {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#search .pagefind-ui__result-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#search .pagefind-ui__message {
|
||||
padding: 0;
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
</style>
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
const { prevPost, nextPost } = Astro.props;
|
||||
const { prevPost, nextPost } = Astro.props
|
||||
---
|
||||
|
||||
<div class="grid grid-cols-2 gap-1.5 sm:gap-3">
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<div class="fixed w-full h-[2px] bg-neutral-300 dark:bg-slate-900 z-50">
|
||||
<div class="bg-cyan-500 dark:bg-orange-500 h-full"></div>
|
||||
<div class="fixed z-50 h-[2px] w-full bg-neutral-300 dark:bg-slate-900">
|
||||
<div class="h-full bg-cyan-500 dark:bg-orange-500"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { initializeProgressBar } from '../scripts/progress-bar.js';
|
||||
initializeProgressBar();
|
||||
import { initializeProgressBar } from '../scripts/progress-bar.js'
|
||||
initializeProgressBar()
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,74 +1,118 @@
|
|||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { Image } from "astro:assets";
|
||||
import { HIGHLIGHTAUTHOR } from "@consts";
|
||||
import type { CollectionEntry } from 'astro:content'
|
||||
import { Image } from 'astro:assets'
|
||||
import { HIGHLIGHTAUTHOR } from '@consts'
|
||||
|
||||
type Props = {
|
||||
entry: CollectionEntry<"publications">;
|
||||
};
|
||||
entry: CollectionEntry<'publications'>
|
||||
}
|
||||
|
||||
const { entry } = Astro.props as {
|
||||
entry: CollectionEntry<"publications">;
|
||||
};
|
||||
entry: CollectionEntry<'publications'>
|
||||
}
|
||||
|
||||
const splitStr = (authors: string | undefined, targetAuthor: string) => {
|
||||
if (!authors) return [];
|
||||
const parts = authors.split(new RegExp(`(${targetAuthor})`, 'g'));
|
||||
return parts;
|
||||
};
|
||||
if (!authors) return []
|
||||
const parts = authors.split(new RegExp(`(${targetAuthor})`, 'g'))
|
||||
return parts
|
||||
}
|
||||
const decomposeURL = (URL: string | undefined) => {
|
||||
if (!URL) return { text: '', url: '' };
|
||||
const parts = URL.split(": ");
|
||||
return { text: parts[0], url: parts[1] };
|
||||
};
|
||||
|
||||
const dataLink = decomposeURL(entry.data.dataURL);
|
||||
const paperLink = decomposeURL(entry.data.paperURL);
|
||||
const codeLink = decomposeURL(entry.data.codeURL);
|
||||
const webLink = decomposeURL(entry.data.webURL);
|
||||
const authorsParts = splitStr(entry.data.authors, HIGHLIGHTAUTHOR);
|
||||
if (!URL) return { text: '', url: '' }
|
||||
const parts = URL.split(': ')
|
||||
return { text: parts[0], url: parts[1] }
|
||||
}
|
||||
|
||||
const dataLink = decomposeURL(entry.data.dataURL)
|
||||
const paperLink = decomposeURL(entry.data.paperURL)
|
||||
const codeLink = decomposeURL(entry.data.codeURL)
|
||||
const webLink = decomposeURL(entry.data.webURL)
|
||||
const authorsParts = splitStr(entry.data.authors, HIGHLIGHTAUTHOR)
|
||||
---
|
||||
|
||||
<div
|
||||
class="w-full not-prose group relative grid grid-cols-auto md:grid-cols-[204px_auto] gap-4 rounded-lg items-center border border-black/15 px-4 py-3 transition-colors duration-300 ease-in-out hover:bg-black/5 hover:text-black focus-visible:bg-black/5 focus-visible:text-black dark:border-white/20 dark:hover:bg-white/5 dark:hover:text-white dark:focus-visible:bg-white/5 dark:focus-visible:text-white"
|
||||
class="not-prose grid-cols-auto group relative grid w-full items-center gap-4 rounded-lg border border-black/15 px-4 py-3 transition-colors duration-300 ease-in-out hover:bg-black/5 hover:text-black focus-visible:bg-black/5 focus-visible:text-black dark:border-white/20 dark:hover:bg-white/5 dark:hover:text-white dark:focus-visible:bg-white/5 dark:focus-visible:text-white md:grid-cols-[204px_auto]"
|
||||
>
|
||||
<Image
|
||||
src={entry.data.img ?? ''}
|
||||
alt={entry.data.imgAlt ?? ''}
|
||||
width={640}
|
||||
height={480}
|
||||
class="sm:w-[240px] sm:h-[135px] shadow-sm rounded-md sm:mr-6 hover:opacity-80 transition hidden md:flex"
|
||||
loading="eager"
|
||||
src={entry.data.img ?? ''}
|
||||
alt={entry.data.imgAlt ?? ''}
|
||||
width={640}
|
||||
height={480}
|
||||
class="hidden rounded-md shadow-sm transition hover:opacity-80 sm:mr-6 sm:h-[135px] sm:w-[240px] md:flex"
|
||||
loading="eager"
|
||||
/>
|
||||
|
||||
|
||||
<div class="flex items-center h-full">
|
||||
<div class="flex h-full items-center">
|
||||
<div class="flex flex-col">
|
||||
<div class="w-full">
|
||||
<div class="text-md font-semibold w-full">
|
||||
<div class="text-md w-full font-semibold">
|
||||
{entry.data.title}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
{authorsParts.map((part:any) =>
|
||||
part === HIGHLIGHTAUTHOR ? <u><strong>{part}</strong></u> : part
|
||||
)}
|
||||
<div class="w-full text-sm">
|
||||
{
|
||||
authorsParts.map((part: any) =>
|
||||
part === HIGHLIGHTAUTHOR ? (
|
||||
<u>
|
||||
<strong>{part}</strong>
|
||||
</u>
|
||||
) : (
|
||||
part
|
||||
),
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
{paperLink.url!="" && <a class="underline hover:text-cyan-500 text-orange-500 dark:hover:text-cyan-500 transition-colors duration-300 ease-in-out visited:text-indigo-400" target="_blank" href={paperLink.url}>{paperLink.text}</a>}
|
||||
{codeLink.url!="" && <a class="underline hover:text-cyan-500 text-orange-500 dark:hover:text-cyan-500 transition-colors duration-300 ease-in-out visited:text-indigo-400" target="_blank" href={codeLink.url}>{codeLink.text}</a>}
|
||||
{webLink.url!="" && <a class="underline hover:text-cyan-500 text-orange-500 dark:hover:text-cyan-500 transition-colors duration-300 ease-in-out visited:text-indigo-400" target="_blank" href={webLink.url}>{webLink.text}</a>}
|
||||
{dataLink.url!="" && <a class="underline hover:text-cyan-500 text-orange-500 dark:hover:text-cyan-500 transition-colors duration-300 ease-in-out visited:text-indigo-400" target="_blank" href={dataLink.url}>{dataLink.text}</a>}
|
||||
<div class="w-full text-sm">
|
||||
{
|
||||
paperLink.url != '' && (
|
||||
<a
|
||||
class="text-orange-500 underline transition-colors duration-300 ease-in-out visited:text-indigo-400 hover:text-cyan-500 dark:hover:text-cyan-500"
|
||||
target="_blank"
|
||||
href={paperLink.url}
|
||||
>
|
||||
{paperLink.text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
{
|
||||
codeLink.url != '' && (
|
||||
<a
|
||||
class="text-orange-500 underline transition-colors duration-300 ease-in-out visited:text-indigo-400 hover:text-cyan-500 dark:hover:text-cyan-500"
|
||||
target="_blank"
|
||||
href={codeLink.url}
|
||||
>
|
||||
{codeLink.text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
{
|
||||
webLink.url != '' && (
|
||||
<a
|
||||
class="text-orange-500 underline transition-colors duration-300 ease-in-out visited:text-indigo-400 hover:text-cyan-500 dark:hover:text-cyan-500"
|
||||
target="_blank"
|
||||
href={webLink.url}
|
||||
>
|
||||
{webLink.text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
{
|
||||
dataLink.url != '' && (
|
||||
<a
|
||||
class="text-orange-500 underline transition-colors duration-300 ease-in-out visited:text-indigo-400 hover:text-cyan-500 dark:hover:text-cyan-500"
|
||||
target="_blank"
|
||||
href={dataLink.url}
|
||||
>
|
||||
{dataLink.text}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="text-sm">
|
||||
In <div class="inline italic">{entry.data.pub}</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm mt-2 break-words">
|
||||
<p class="mt-2 break-words text-sm">
|
||||
{entry.data.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
---
|
||||
import 'bootstrap-icons/font/bootstrap-icons.css';
|
||||
import 'bootstrap-icons/font/bootstrap-icons.css'
|
||||
|
||||
export interface Props {
|
||||
URL: string;
|
||||
icon: string;
|
||||
icon_size: string
|
||||
URL: string
|
||||
icon: string
|
||||
icon_size: string
|
||||
}
|
||||
|
||||
const { URL, icon, icon_size } = Astro.props;
|
||||
|
||||
const { URL, icon, icon_size } = Astro.props
|
||||
---
|
||||
|
||||
<a
|
||||
href={URL}
|
||||
target={"_blank"}
|
||||
class={
|
||||
`inline-block ${icon_size} decoration-black/30 dark:decoration-white/30 hover:decoration-black/50 focus-visible:decoration-black/50 dark:hover:decoration-white/50 dark:focus-visible:decoration-white/50 text-current hover:text-cyan-500 focus-visible:text-black dark:hover:text-orange-500 dark:focus-visible:text-white transition-colors duration-300 ease-in-out`}>
|
||||
<i class={`bi bi-${icon}`}></i>
|
||||
</a>
|
||||
href={URL}
|
||||
target={'_blank'}
|
||||
class={`inline-block ${icon_size} decoration-black/30 dark:decoration-white/30 hover:decoration-black/50 focus-visible:decoration-black/50 dark:hover:decoration-white/50 dark:focus-visible:decoration-white/50 text-current hover:text-cyan-500 focus-visible:text-black dark:hover:text-orange-500 dark:focus-visible:text-white transition-colors duration-300 ease-in-out`}
|
||||
>
|
||||
<i class={`bi bi-${icon}`}></i>
|
||||
</a>
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
---
|
||||
import SocialIcon from "@components/SocialIcon.astro";
|
||||
import { SITE } from "@consts";
|
||||
import SocialIcon from '@components/SocialIcon.astro'
|
||||
import { SITE } from '@consts'
|
||||
|
||||
export interface Props {
|
||||
icon_size: string
|
||||
icon_size: string
|
||||
}
|
||||
|
||||
const { icon_size } = Astro.props;
|
||||
|
||||
const { icon_size } = Astro.props
|
||||
---
|
||||
|
||||
<ul class="not-prose flex flex-wrap gap-2">
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="twitter-x"/>
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="github"/>
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="linkedin"/>
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="envelope-fill"/>
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="mortarboard-fill"/>
|
||||
<SocialIcon icon_size={icon_size} URL={`${SITE.SITEURL}/rss.xml`} icon="rss-fill"/>
|
||||
</ul>
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="twitter-x" />
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="github" />
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="linkedin" />
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="envelope-fill" />
|
||||
<SocialIcon icon_size={icon_size} URL="#" icon="mortarboard-fill" />
|
||||
<SocialIcon
|
||||
icon_size={icon_size}
|
||||
URL={`${SITE.SITEURL}/rss.xml`}
|
||||
icon="rss-fill"
|
||||
/>
|
||||
</ul>
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
---
|
||||
import TableOfContentsHeading from "./TableOfContentsHeading.astro";
|
||||
import TableOfContentsHeading from './TableOfContentsHeading.astro'
|
||||
|
||||
// https://kld.dev/building-table-of-contents/
|
||||
const { headings } = Astro.props;
|
||||
const toc = buildToc(headings);
|
||||
const { headings } = Astro.props
|
||||
const toc = buildToc(headings)
|
||||
|
||||
export interface Heading {
|
||||
depth: number;
|
||||
slug: string;
|
||||
text: string;
|
||||
depth: number
|
||||
slug: string
|
||||
text: string
|
||||
}
|
||||
|
||||
function buildToc(headings: Heading[]) {
|
||||
const toc: Heading[] = [];
|
||||
const parentHeadings = new Map();
|
||||
const toc: Heading[] = []
|
||||
const parentHeadings = new Map()
|
||||
headings.forEach((h) => {
|
||||
const heading = { ...h, subheadings: [] };
|
||||
parentHeadings.set(heading.depth, heading);
|
||||
const heading = { ...h, subheadings: [] }
|
||||
parentHeadings.set(heading.depth, heading)
|
||||
if (heading.depth === 2) {
|
||||
toc.push(heading);
|
||||
toc.push(heading)
|
||||
} else {
|
||||
parentHeadings.get(heading.depth - 1).subheadings.push(heading);
|
||||
parentHeadings.get(heading.depth - 1).subheadings.push(heading)
|
||||
}
|
||||
});
|
||||
return toc;
|
||||
})
|
||||
return toc
|
||||
}
|
||||
---
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
import type { Heading } from "./TableOfContents.astro";
|
||||
import Link from "./Link.astro";
|
||||
import type { Heading } from './TableOfContents.astro'
|
||||
import Link from './Link.astro'
|
||||
|
||||
// https://kld.dev/building-table-of-contents/
|
||||
|
||||
const { heading } = Astro.props;
|
||||
const { heading } = Astro.props
|
||||
---
|
||||
|
||||
<li class="list-inside list-disc px-6 py-1.5 text-sm">
|
||||
<Link href={"#" + heading.slug} underline>
|
||||
<Link href={'#' + heading.slug} underline>
|
||||
{heading.text}
|
||||
</Link>
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue