fix: fix errors and reformat code

This commit is contained in:
saicaca
2024-08-03 16:40:20 +08:00
parent 1f93499ece
commit 0ad144add3
44 changed files with 550 additions and 558 deletions

View File

@@ -1,63 +1,68 @@
---
import {getSortedPosts} from "../utils/content-utils";
import {getPostUrlBySlug} from "../utils/url-utils";
import {i18n} from "../i18n/translation";
import I18nKey from "../i18n/i18nKey";
import {UNCATEGORIZED} from "@constants/constants";
import { getSortedPosts } from '../utils/content-utils'
import { getPostUrlBySlug } from '../utils/url-utils'
import { i18n } from '../i18n/translation'
import I18nKey from '../i18n/i18nKey'
import { UNCATEGORIZED } from '@constants/constants'
interface Props {
keyword?: string;
tags?: string[];
categories?: string[];
keyword?: string
tags?: string[]
categories?: string[]
}
const { keyword, tags, categories} = Astro.props;
const { keyword, tags, categories } = Astro.props
let posts = await getSortedPosts()
if (Array.isArray(tags) && tags.length > 0) {
posts = posts.filter(post =>
Array.isArray(post.data.tags) && post.data.tags.some(tag => tags.includes(tag))
);
posts = posts.filter(
post =>
Array.isArray(post.data.tags) &&
post.data.tags.some(tag => tags.includes(tag)),
)
}
if (Array.isArray(categories) && categories.length > 0) {
posts = posts.filter(post =>
(post.data.category && categories.includes(post.data.category)) ||
(!post.data.category && categories.includes(UNCATEGORIZED))
);
posts = posts.filter(
post =>
(post.data.category && categories.includes(post.data.category)) ||
(!post.data.category && categories.includes(UNCATEGORIZED)),
)
}
const groups: {year: number, posts: typeof posts}[] = function () {
const groupedPosts = posts.reduce((grouped: {[year: number]: typeof posts}, post) => {
const year = post.data.published.getFullYear()
if (!grouped[year]) {
grouped[year] = []
}
grouped[year].push(post)
return grouped
}, {})
const groups: { year: number; posts: typeof posts }[] = (function () {
const groupedPosts = posts.reduce(
(grouped: { [year: number]: typeof posts }, post) => {
const year = post.data.published.getFullYear()
if (!grouped[year]) {
grouped[year] = []
}
grouped[year].push(post)
return grouped
},
{},
)
// convert the object to an array
const groupedPostsArray = Object.keys(groupedPosts).map(key => ({
year: parseInt(key),
posts: groupedPosts[parseInt(key)]
}))
// convert the object to an array
const groupedPostsArray = Object.keys(groupedPosts).map(key => ({
year: parseInt(key),
posts: groupedPosts[parseInt(key)],
}))
// sort years by latest first
groupedPostsArray.sort((a, b) => b.year - a.year)
return groupedPostsArray;
}();
// sort years by latest first
groupedPostsArray.sort((a, b) => b.year - a.year)
return groupedPostsArray
})()
function formatDate(date: Date) {
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return `${month}-${day}`;
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
return `${month}-${day}`
}
function formatTag(tag: string[]) {
return tag.map(t => `#${t}`).join(' ');
return tag.map(t => `#${t}`).join(' ')
}
---
<div class="card-base px-8 py-6">

View File

@@ -1,7 +1,6 @@
---
import {siteConfig} from "../config";
import { siteConfig } from '../config'
---
<div id="config-carrier" data-hue={siteConfig.themeColor.hue}>

View File

@@ -1,8 +1,7 @@
---
import {profileConfig} from "../config";
import {url} from "../utils/url-utils";
import { profileConfig } from '../config'
import { url } from '../utils/url-utils'
---
<div class="card-base max-w-[var(--page-width)] min-h-[4.5rem] rounded-b-none mx-auto flex items-center px-6">

View File

@@ -1,10 +1,6 @@
<script lang="ts">
import type { LIGHT_DARK_MODE } from '@/types/config.ts'
import {
AUTO_MODE,
DARK_MODE,
LIGHT_MODE,
} from '@constants/constants.ts'
import { AUTO_MODE, DARK_MODE, LIGHT_MODE } from '@constants/constants.ts'
import I18nKey from '@i18n/i18nKey'
import { i18n } from '@i18n/translation'
import Icon from '@iconify/svelte'
@@ -15,27 +11,18 @@ import {
} from '@utils/setting-utils.ts'
import { onMount } from 'svelte'
const seq: LIGHT_DARK_MODE[] = [
LIGHT_MODE,
DARK_MODE,
AUTO_MODE,
]
const seq: LIGHT_DARK_MODE[] = [LIGHT_MODE, DARK_MODE, AUTO_MODE]
let mode: LIGHT_DARK_MODE = AUTO_MODE
onMount(() => {
mode = getStoredTheme()
const darkModePreference = window.matchMedia(
'(prefers-color-scheme: dark)',
)
const darkModePreference = window.matchMedia('(prefers-color-scheme: dark)')
const changeThemeWhenSchemeChanged: Parameters<
typeof darkModePreference.addEventListener<'change'>
>[1] = e => {
applyThemeToDocument(mode)
}
darkModePreference.addEventListener(
'change',
changeThemeWhenSchemeChanged,
)
darkModePreference.addEventListener('change', changeThemeWhenSchemeChanged)
return () => {
darkModePreference.removeEventListener(
'change',
@@ -50,25 +37,24 @@ function switchScheme(newMode: LIGHT_DARK_MODE) {
}
function toggleScheme() {
let i = 0
for (; i < seq.length; i++) {
if (seq[i] === mode) {
break
}
let i = 0
for (; i < seq.length; i++) {
if (seq[i] === mode) {
break
}
switchScheme(seq[(i + 1) % seq.length])
}
switchScheme(seq[(i + 1) % seq.length])
}
function showPanel() {
const panel = document.querySelector('#light-dark-panel')
panel.classList.remove('float-panel-closed')
const panel = document.querySelector('#light-dark-panel')
panel.classList.remove('float-panel-closed')
}
function hidePanel() {
const panel = document.querySelector('#light-dark-panel')
panel.classList.add('float-panel-closed')
const panel = document.querySelector('#light-dark-panel')
panel.classList.add('float-panel-closed')
}
</script>
<!-- z-50 make the panel higher than other float panels -->

View File

@@ -1,22 +1,23 @@
---
import { Icon } from 'astro-icon/components';
import DisplaySettings from "./widget/DisplaySettings.svelte";
import {LinkPreset, type NavBarLink} from "../types/config";
import {navBarConfig, siteConfig} from "../config";
import NavMenuPanel from "./widget/NavMenuPanel.astro";
import Search from "./Search.svelte";
import {LinkPresets} from "../constants/link-presets";
import LightDarkSwitch from "./LightDarkSwitch.svelte";
import {url} from "../utils/url-utils";
const className = Astro.props.class;
import { Icon } from 'astro-icon/components'
import DisplaySettings from './widget/DisplaySettings.svelte'
import { LinkPreset, type NavBarLink } from '../types/config'
import { navBarConfig, siteConfig } from '../config'
import NavMenuPanel from './widget/NavMenuPanel.astro'
import Search from './Search.svelte'
import { LinkPresets } from '../constants/link-presets'
import LightDarkSwitch from './LightDarkSwitch.svelte'
import { url } from '../utils/url-utils'
const className = Astro.props.class
let links: NavBarLink[] = navBarConfig.links.map((item: NavBarLink | LinkPreset): NavBarLink => {
if (typeof item === "number") {
return LinkPresets[item]
let links: NavBarLink[] = navBarConfig.links.map(
(item: NavBarLink | LinkPreset): NavBarLink => {
if (typeof item === 'number') {
return LinkPresets[item]
}
return item;
});
return item
},
)
---
<div id="navbar" class="sticky top-0 z-50 onload-animation">
<div class="absolute h-8 left-0 right-0 -top-8 bg-[var(--card-bg)] transition"></div> <!-- used for onload animation -->

View File

@@ -1,34 +1,43 @@
---
import path from "path";
import PostMetadata from "./PostMeta.astro";
import ImageWrapper from "./misc/ImageWrapper.astro";
import { Icon } from 'astro-icon/components';
import {i18n} from "../i18n/translation";
import I18nKey from "../i18n/i18nKey";
import {getDir} from "../utils/url-utils";
import path from 'path'
import PostMetadata from './PostMeta.astro'
import ImageWrapper from './misc/ImageWrapper.astro'
import { Icon } from 'astro-icon/components'
import { i18n } from '../i18n/translation'
import I18nKey from '../i18n/i18nKey'
import { getDir } from '../utils/url-utils'
interface Props {
class?: string;
entry: any;
title: string;
url: string;
published: Date;
tags: string[];
category: string;
image: string;
description: string;
draft: boolean;
style: string;
class?: string
entry: any
title: string
url: string
published: Date
tags: string[]
category: string
image: string
description: string
draft: boolean
style: string
}
const { entry, title, url, published, tags, category, image, description, style } = Astro.props;
const className = Astro.props.class;
const {
entry,
title,
url,
published,
tags,
category,
image,
description,
style,
} = Astro.props
const className = Astro.props.class
const hasCover = image !== undefined && image !== null && image !== '';
const hasCover = image !== undefined && image !== null && image !== ''
const coverWidth = "28%";
const { remarkPluginFrontmatter } = await entry.render();
const coverWidth = '28%'
const { remarkPluginFrontmatter } = await entry.render()
---
<div class:list={["card-base flex flex-col-reverse md:flex-col w-full rounded-[var(--radius-large)] overflow-hidden relative", className]} style={style}>
<div class:list={["pl-6 md:pl-9 pr-6 md:pr-2 pt-6 md:pt-7 pb-6 relative", {"w-full md:w-[calc(100%_-_52px_-_12px)]": !hasCover, "w-full md:w-[calc(100%_-_var(--coverWidth)_-_12px)]": hasCover}]}>

View File

@@ -1,19 +1,19 @@
---
import {formatDateToYYYYMMDD} from "../utils/date-utils";
import { Icon } from 'astro-icon/components';
import {i18n} from "../i18n/translation";
import I18nKey from "../i18n/i18nKey";
import {url} from "../utils/url-utils";
import { formatDateToYYYYMMDD } from '../utils/date-utils'
import { Icon } from 'astro-icon/components'
import { i18n } from '../i18n/translation'
import I18nKey from '../i18n/i18nKey'
import { url } from '../utils/url-utils'
interface Props {
class: string;
published: Date;
tags: string[];
category: string;
hideTagsForMobile?: boolean;
class: string
published: Date
tags: string[]
category: string
hideTagsForMobile?: boolean
}
const {published, tags, category, hideTagsForMobile = false} = Astro.props;
const className = Astro.props.class;
const { published, tags, category, hideTagsForMobile = false } = Astro.props
const className = Astro.props.class
---
<div class:list={["flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2", className]}>

View File

@@ -1,8 +1,8 @@
---
import {getPostUrlBySlug} from "@utils/url-utils";
import PostCard from "./PostCard.astro";
import { getPostUrlBySlug } from '@utils/url-utils'
import PostCard from './PostCard.astro'
const {page} = Astro.props;
const { page } = Astro.props
let delay = 0
const interval = 50

View File

@@ -1,65 +1,68 @@
<script lang="ts">
import { onMount } from 'svelte'
import {url} from "@utils/url-utils.ts"
import { i18n } from '@i18n/translation';
import I18nKey from '@i18n/i18nKey';
import { url } from '@utils/url-utils.ts'
import { i18n } from '@i18n/translation'
import I18nKey from '@i18n/i18nKey'
let keywordDesktop = ''
let keywordMobile = ''
let result = []
const fakeResult = [{
const fakeResult = [
{
url: url('/'),
meta: {
title: 'This Is a Fake Search Result'
title: 'This Is a Fake Search Result',
},
excerpt: 'Because the search cannot work in the <mark>dev</mark> environment.'
}, {
excerpt:
'Because the search cannot work in the <mark>dev</mark> environment.',
},
{
url: url('/'),
meta: {
title: 'If You Want to Test the Search'
title: 'If You Want to Test the Search',
},
excerpt: 'Try running <mark>npm build && npm preview</mark> instead.'
}]
excerpt: 'Try running <mark>npm build && npm preview</mark> instead.',
},
]
let search = (keyword: string, isDesktop: boolean) => {}
onMount(() => {
search = async (keyword: string, isDesktop: boolean) => {
let panel = document.getElementById('search-panel')
if (!panel)
return
search = async (keyword: string, isDesktop: boolean) => {
let panel = document.getElementById('search-panel')
if (!panel) return
if (!keyword && isDesktop) {
panel.classList.add("float-panel-closed")
return
}
let arr = [];
if (import.meta.env.PROD) {
const ret = await pagefind.search(keyword)
for (const item of ret.results) {
arr.push(await item.data())
}
} else {
// Mock data for non-production environment
// arr = JSON.parse('[{"url":"/","content":"Simple Guides for Fuwari. Cover image source: Source. This blog template is built with Astro. For the things that are not mentioned in this guide, you may find the answers in the Astro Docs. Front-matter of Posts. --- title: My First Blog Post published: 2023-09-09 description: This is the first post of my new Astro blog. image: ./cover.jpg tags: [Foo, Bar] category: Front-end draft: false ---AttributeDescription title. The title of the post. published. The date the post was published. description. A short description of the post. Displayed on index page. image. The cover image path of the post. 1. Start with http:// or https://: Use web image 2. Start with /: For image in public dir 3. With none of the prefixes: Relative to the markdown file. tags. The tags of the post. category. The category of the post. draft. If this post is still a draft, which wont be displayed. Where to Place the Post Files. Your post files should be placed in src/content/posts/ directory. You can also create sub-directories to better organize your posts and assets. src/content/posts/ ├── post-1.md └── post-2/ ├── cover.png └── index.md.","word_count":187,"filters":{},"meta":{"title":"This Is a Fake Search Result"},"anchors":[{"element":"h2","id":"front-matter-of-posts","text":"Front-matter of Posts","location":34},{"element":"h2","id":"where-to-place-the-post-files","text":"Where to Place the Post Files","location":151}],"weighted_locations":[{"weight":10,"balanced_score":57600,"location":3}],"locations":[3],"raw_content":"Simple Guides for Fuwari. Cover image source: Source. This blog template is built with Astro. For the things that are not mentioned in this guide, you may find the answers in the Astro Docs. Front-matter of Posts. --- title: My First Blog Post published: 2023-09-09 description: This is the first post of my new Astro blog. image: ./cover.jpg tags: [Foo, Bar] category: Front-end draft: false ---AttributeDescription title. The title of the post. published. The date the post was published. description. A short description of the post. Displayed on index page. image. The cover image path of the post. 1. Start with http:// or https://: Use web image 2. Start with /: For image in public dir 3. With none of the prefixes: Relative to the markdown file. tags. The tags of the post. category. The category of the post. draft. If this post is still a draft, which wont be displayed. Where to Place the Post Files. Your post files should be placed in src/content/posts/ directory. You can also create sub-directories to better organize your posts and assets. src/content/posts/ ├── post-1.md └── post-2/ ├── cover.png └── index.md.","raw_url":"/posts/guide/","excerpt":"Because the search cannot work in the <mark>dev</mark> environment.","sub_results":[{"title":"Simple Guides for Fuwari - Fuwari","url":"/posts/guide/","weighted_locations":[{"weight":10,"balanced_score":57600,"location":3}],"locations":[3],"excerpt":"Simple Guides for <mark>Fuwari.</mark> Cover image source: Source. This blog template is built with Astro. For the things that are not mentioned in this guide, you may find the answers"}]},{"url":"/","content":"About. This is the demo site for Fuwari. Sources of images used in this site. Unsplash. 星と少女 by Stella. Rabbit - v1.4 Showcase by Rabbit_YourMajesty.","word_count":25,"filters":{},"meta":{"title":"If You Want to Test the Search"},"anchors":[{"element":"h1","id":"about","text":"About","location":0},{"element":"h3","id":"sources-of-images-used-in-this-site","text":"Sources of images used in this site","location":8}],"weighted_locations":[{"weight":1,"balanced_score":576,"location":7}],"locations":[7],"raw_content":"About. This is the demo site for Fuwari. Sources of images used in this site. Unsplash. 星と少女 by Stella. Rabbit - v1.4 Showcase by Rabbit_YourMajesty.","raw_url":"/about/","excerpt":"Try running <mark>npm build && npm preview</mark> instead.","sub_results":[{"title":"About","url":"/about/#about","anchor":{"element":"h1","id":"about","text":"About","location":0},"weighted_locations":[{"weight":1,"balanced_score":576,"location":7}],"locations":[7],"excerpt":"About. This is the demo site for <mark>Fuwari.</mark>"}]}]')
arr = fakeResult
}
if (!arr.length && isDesktop) {
panel.classList.add("float-panel-closed")
return
}
if (isDesktop) {
panel.classList.remove("float-panel-closed")
}
result = arr
if (!keyword && isDesktop) {
panel.classList.add('float-panel-closed')
return
}
let arr = []
if (import.meta.env.PROD) {
const ret = await pagefind.search(keyword)
for (const item of ret.results) {
arr.push(await item.data())
}
} else {
// Mock data for non-production environment
// arr = JSON.parse('[{"url":"/","content":"Simple Guides for Fuwari. Cover image source: Source. This blog template is built with Astro. For the things that are not mentioned in this guide, you may find the answers in the Astro Docs. Front-matter of Posts. --- title: My First Blog Post published: 2023-09-09 description: This is the first post of my new Astro blog. image: ./cover.jpg tags: [Foo, Bar] category: Front-end draft: false ---AttributeDescription title. The title of the post. published. The date the post was published. description. A short description of the post. Displayed on index page. image. The cover image path of the post. 1. Start with http:// or https://: Use web image 2. Start with /: For image in public dir 3. With none of the prefixes: Relative to the markdown file. tags. The tags of the post. category. The category of the post. draft. If this post is still a draft, which wont be displayed. Where to Place the Post Files. Your post files should be placed in src/content/posts/ directory. You can also create sub-directories to better organize your posts and assets. src/content/posts/ ├── post-1.md └── post-2/ ├── cover.png └── index.md.","word_count":187,"filters":{},"meta":{"title":"This Is a Fake Search Result"},"anchors":[{"element":"h2","id":"front-matter-of-posts","text":"Front-matter of Posts","location":34},{"element":"h2","id":"where-to-place-the-post-files","text":"Where to Place the Post Files","location":151}],"weighted_locations":[{"weight":10,"balanced_score":57600,"location":3}],"locations":[3],"raw_content":"Simple Guides for Fuwari. Cover image source: Source. This blog template is built with Astro. For the things that are not mentioned in this guide, you may find the answers in the Astro Docs. Front-matter of Posts. --- title: My First Blog Post published: 2023-09-09 description: This is the first post of my new Astro blog. image: ./cover.jpg tags: [Foo, Bar] category: Front-end draft: false ---AttributeDescription title. The title of the post. published. The date the post was published. description. A short description of the post. Displayed on index page. image. The cover image path of the post. 1. Start with http:// or https://: Use web image 2. Start with /: For image in public dir 3. With none of the prefixes: Relative to the markdown file. tags. The tags of the post. category. The category of the post. draft. If this post is still a draft, which wont be displayed. Where to Place the Post Files. Your post files should be placed in src/content/posts/ directory. You can also create sub-directories to better organize your posts and assets. src/content/posts/ ├── post-1.md └── post-2/ ├── cover.png └── index.md.","raw_url":"/posts/guide/","excerpt":"Because the search cannot work in the <mark>dev</mark> environment.","sub_results":[{"title":"Simple Guides for Fuwari - Fuwari","url":"/posts/guide/","weighted_locations":[{"weight":10,"balanced_score":57600,"location":3}],"locations":[3],"excerpt":"Simple Guides for <mark>Fuwari.</mark> Cover image source: Source. This blog template is built with Astro. For the things that are not mentioned in this guide, you may find the answers"}]},{"url":"/","content":"About. This is the demo site for Fuwari. Sources of images used in this site. Unsplash. 星と少女 by Stella. Rabbit - v1.4 Showcase by Rabbit_YourMajesty.","word_count":25,"filters":{},"meta":{"title":"If You Want to Test the Search"},"anchors":[{"element":"h1","id":"about","text":"About","location":0},{"element":"h3","id":"sources-of-images-used-in-this-site","text":"Sources of images used in this site","location":8}],"weighted_locations":[{"weight":1,"balanced_score":576,"location":7}],"locations":[7],"raw_content":"About. This is the demo site for Fuwari. Sources of images used in this site. Unsplash. 星と少女 by Stella. Rabbit - v1.4 Showcase by Rabbit_YourMajesty.","raw_url":"/about/","excerpt":"Try running <mark>npm build && npm preview</mark> instead.","sub_results":[{"title":"About","url":"/about/#about","anchor":{"element":"h1","id":"about","text":"About","location":0},"weighted_locations":[{"weight":1,"balanced_score":576,"location":7}],"locations":[7],"excerpt":"About. This is the demo site for <mark>Fuwari.</mark>"}]}]')
arr = fakeResult
}
if (!arr.length && isDesktop) {
panel.classList.add('float-panel-closed')
return
}
if (isDesktop) {
panel.classList.remove('float-panel-closed')
}
result = arr
}
})
const togglePanel = () => {
let panel = document.getElementById('search-panel')
panel?.classList.toggle("float-panel-closed")
let panel = document.getElementById('search-panel')
panel?.classList.toggle('float-panel-closed')
}
$: search(keywordDesktop, true)

View File

@@ -1,5 +1,5 @@
---
import { Icon } from 'astro-icon/components';
import { Icon } from 'astro-icon/components'
---
<!-- There can't be a filter on parent element, or it will break `fixed` -->

View File

@@ -1,8 +1,8 @@
---
interface Props {
badge?: string
url?: string
label?: string
badge?: string
url?: string
label?: string
}
const { badge, url, label } = Astro.props
---

View File

@@ -1,11 +1,11 @@
---
interface Props {
size?: string;
dot?: boolean;
href?: string;
label?: string;
size?: string
dot?: boolean
href?: string
label?: string
}
const { size, dot, href, label }: Props = Astro.props;
const { size, dot, href, label }: Props = Astro.props
---
<a href={href} aria-label={label} class="btn-regular h-8 text-sm px-3 rounded-lg">
{dot && <div class="h-1 w-1 bg-[var(--btn-content)] dark:bg-[var(--card-bg)] transition rounded-md mr-2"></div>}

View File

@@ -1,61 +1,53 @@
---
import type { Page } from "astro";
import { Icon } from 'astro-icon/components';
import {url} from "../../utils/url-utils";
import type { Page } from 'astro'
import { Icon } from 'astro-icon/components'
import { url } from '../../utils/url-utils'
interface Props {
page: Page;
class?: string;
style?: string;
page: Page
class?: string
style?: string
}
const {page, style} = Astro.props;
const { page, style } = Astro.props
const HIDDEN = -1;
const HIDDEN = -1
const className = Astro.props.class;
const className = Astro.props.class
const ADJ_DIST = 2;
const VISIBLE = ADJ_DIST * 2 + 1;
const ADJ_DIST = 2
const VISIBLE = ADJ_DIST * 2 + 1
// for test
let count = 1;
let l = page.currentPage, r = page.currentPage;
let count = 1
let l = page.currentPage,
r = page.currentPage
while (0 < l - 1 && r + 1 <= page.lastPage && count + 2 <= VISIBLE) {
count += 2;
l--;
r++;
count += 2
l--
r++
}
while (0 < l - 1 && count < VISIBLE) {
count++;
l--;
count++
l--
}
while (r + 1 <= page.lastPage && count < VISIBLE) {
count++;
r++;
count++
r++
}
let pages: number[] = [];
if (l > 1)
pages.push(1);
if (l == 3)
pages.push(2);
if (l > 3)
pages.push(HIDDEN);
for (let i = l; i <= r; i++)
pages.push(i);
if (r < page.lastPage - 2)
pages.push(HIDDEN);
if (r == page.lastPage - 2)
pages.push(page.lastPage - 1);
if (r < page.lastPage)
pages.push(page.lastPage);
let pages: number[] = []
if (l > 1) pages.push(1)
if (l == 3) pages.push(2)
if (l > 3) pages.push(HIDDEN)
for (let i = l; i <= r; i++) pages.push(i)
if (r < page.lastPage - 2) pages.push(HIDDEN)
if (r == page.lastPage - 2) pages.push(page.lastPage - 1)
if (r < page.lastPage) pages.push(page.lastPage)
const getPageUrl = (p: number) => {
if (p == 1)
return '/';
return `/${p}/`;
if (p == 1) return '/'
return `/${p}/`
}
---
<div class:list={[className, "flex flex-row gap-3 justify-center"]} style={style}>

View File

@@ -1,35 +1,44 @@
---
import path from "path";
import path from 'path'
interface Props {
id?: string
src: string;
class?: string;
alt?: string
position?: string;
basePath?: string
id?: string
src: string
class?: string
alt?: string
position?: string
basePath?: string
}
import { Image } from 'astro:assets';
import { url } from "../../utils/url-utils";
import { Image } from 'astro:assets'
import { url } from '../../utils/url-utils'
const {id, src, alt, position = 'center', basePath = '/'} = Astro.props;
const className = Astro.props.class;
const { id, src, alt, position = 'center', basePath = '/' } = Astro.props
const className = Astro.props.class
const isLocal = !(src.startsWith('/') || src.startsWith('http') || src.startsWith('https') || src.startsWith('data:'));
const isPublic = src.startsWith('/');
const isLocal = !(
src.startsWith('/') ||
src.startsWith('http') ||
src.startsWith('https') ||
src.startsWith('data:')
)
const isPublic = src.startsWith('/')
// TODO temporary workaround for images dynamic import
// https://github.com/withastro/astro/issues/3373
let img;
let img
if (isLocal) {
const files = import.meta.glob<ImageMetadata>("../../**", { import: 'default' });
let normalizedPath = path.normalize(path.join("../../", basePath, src)).replace(/\\/g, "/");
img = await (files[normalizedPath])();
if (!img) {
console.error(`No image found for path ${normalizedPath}`);
}
const files = import.meta.glob<ImageMetadata>('../../**', {
import: 'default',
})
let normalizedPath = path
.normalize(path.join('../../', basePath, src))
.replace(/\\/g, '/')
img = await files[normalizedPath]()
if (!img) {
console.error(`No image found for path ${normalizedPath}`)
}
}
const imageClass = 'w-full h-full object-cover';
const imageClass = 'w-full h-full object-cover'
const imageStyle = `object-position: ${position}`
---
<div id={id} class:list={[className, 'overflow-hidden relative']}>

View File

@@ -1,23 +1,22 @@
---
import {formatDateToYYYYMMDD} from "../../utils/date-utils";
import { Icon } from 'astro-icon/components';
import {licenseConfig, profileConfig} from "../../config";
import {i18n} from "../../i18n/translation";
import I18nKey from "../../i18n/i18nKey";
import { formatDateToYYYYMMDD } from '../../utils/date-utils'
import { Icon } from 'astro-icon/components'
import { licenseConfig, profileConfig } from '../../config'
import { i18n } from '../../i18n/translation'
import I18nKey from '../../i18n/i18nKey'
interface Props {
title: string;
slug: string;
pubDate: Date;
class: string;
title: string
slug: string
pubDate: Date
class: string
}
const { title, slug, pubDate } = Astro.props;
const className = Astro.props.class;
const profileConf = profileConfig;
const licenseConf = licenseConfig;
const postUrl = decodeURIComponent(Astro.url.toString());
const { title, slug, pubDate } = Astro.props
const className = Astro.props.class
const profileConf = profileConfig
const licenseConf = licenseConfig
const postUrl = decodeURIComponent(Astro.url.toString())
---
<div class=`relative transition overflow-hidden bg-[var(--license-block-bg)] py-5 px-6 ${className}`>
<div class="transition font-bold text-black/75 dark:text-white/75">

View File

@@ -1,11 +1,11 @@
---
import '@fontsource-variable/jetbrains-mono';
import '@fontsource-variable/jetbrains-mono/wght-italic.css';
import '@fontsource-variable/jetbrains-mono'
import '@fontsource-variable/jetbrains-mono/wght-italic.css'
interface Props {
class: string;
class: string
}
const className = Astro.props.class;
const className = Astro.props.class
---
<div data-pagefind-body class=`prose dark:prose-invert prose-base max-w-none custom-md ${className}`>
<!--<div class="prose dark:prose-invert max-w-none custom-md">-->
@@ -46,12 +46,13 @@ const className = Astro.props.class;
wrapper.appendChild(codeBlock);
wrapper.appendChild(copyButton);
let timeout;
let timeout: ReturnType<typeof setTimeout>;
copyButton.addEventListener("click", async () => {
if (timeout) {
clearTimeout(timeout);
}
let text = codeBlock?.querySelector("code")?.innerText;
if (text === undefined) return;
await navigator.clipboard.writeText(text);
copyButton.classList.add("success");
timeout = setTimeout(() => {

View File

@@ -1,26 +1,25 @@
---
import WidgetLayout from "./WidgetLayout.astro";
import WidgetLayout from './WidgetLayout.astro'
import {i18n} from "../../i18n/translation";
import I18nKey from "../../i18n/i18nKey";
import {getCategoryList} from "../../utils/content-utils";
import {getCategoryUrl} from "../../utils/url-utils";
import ButtonLink from "../control/ButtonLink.astro";
import { i18n } from '../../i18n/translation'
import I18nKey from '../../i18n/i18nKey'
import { getCategoryList } from '../../utils/content-utils'
import { getCategoryUrl } from '../../utils/url-utils'
import ButtonLink from '../control/ButtonLink.astro'
const categories = await getCategoryList();
const categories = await getCategoryList()
const COLLAPSED_HEIGHT = "7.5rem";
const COLLAPSE_THRESHOLD = 5;
const COLLAPSED_HEIGHT = '7.5rem'
const COLLAPSE_THRESHOLD = 5
const isCollapsed = categories.length >= COLLAPSE_THRESHOLD;
const isCollapsed = categories.length >= COLLAPSE_THRESHOLD
interface Props {
class?: string;
style?: string;
class?: string
style?: string
}
const className = Astro.props.class
const style = Astro.props.style
---
<WidgetLayout name={i18n(I18nKey.categories)} id="categories" isCollapsed={isCollapsed} collapsedHeight={COLLAPSED_HEIGHT}

View File

@@ -1,17 +1,17 @@
<script lang="ts">
import {i18n} from '@i18n/translation';
import I18nKey from '@i18n/i18nKey';
import {getDefaultHue, getHue, setHue} from '@utils/setting-utils';
import { i18n } from '@i18n/translation'
import I18nKey from '@i18n/i18nKey'
import { getDefaultHue, getHue, setHue } from '@utils/setting-utils'
let hue = getHue()
const defaultHue = getDefaultHue()
function resetHue() {
hue = getDefaultHue()
hue = getDefaultHue()
}
$: if (hue || hue === 0) {
setHue(hue)
setHue(hue)
}
</script>

View File

@@ -1,13 +1,13 @@
---
import {type NavBarLink} from "../../types/config";
import {Icon} from "astro-icon/components";
import {url} from "../../utils/url-utils";
import { type NavBarLink } from '../../types/config'
import { Icon } from 'astro-icon/components'
import { url } from '../../utils/url-utils'
interface Props {
links: NavBarLink[],
links: NavBarLink[]
}
const links = Astro.props.links;
const links = Astro.props.links
---
<div id="nav-menu-panel" class:list={["float-panel float-panel-closed absolute transition-all fixed right-4 px-2 py-2"]}>
{links.map((link) => (

View File

@@ -1,10 +1,10 @@
---
import ImageWrapper from "../misc/ImageWrapper.astro";
import {Icon} from "astro-icon/components";
import {profileConfig} from "../../config";
import {url} from "../../utils/url-utils";
import ImageWrapper from '../misc/ImageWrapper.astro'
import { Icon } from 'astro-icon/components'
import { profileConfig } from '../../config'
import { url } from '../../utils/url-utils'
const config = profileConfig;
const config = profileConfig
---
<div class="card-base p-3">
<a aria-label="Go to About Page" href={url('/about/')}

View File

@@ -1,9 +1,9 @@
---
import Profile from "./Profile.astro";
import Tag from "./Tags.astro";
import Categories from "./Categories.astro";
import Profile from './Profile.astro'
import Tag from './Tags.astro'
import Categories from './Categories.astro'
const className = Astro.props.class;
const className = Astro.props.class
---
<div id="sidebar" class:list={[className, "w-full"]}>
<div class="flex flex-col w-full gap-4 mb-4">

View File

@@ -1,25 +1,24 @@
---
import WidgetLayout from "./WidgetLayout.astro";
import ButtonTag from "../control/ButtonTag.astro";
import {getTagList} from "../../utils/content-utils";
import {i18n} from "../../i18n/translation";
import I18nKey from "../../i18n/i18nKey";
import {url} from "../../utils/url-utils";
import WidgetLayout from './WidgetLayout.astro'
import ButtonTag from '../control/ButtonTag.astro'
import { getTagList } from '../../utils/content-utils'
import { i18n } from '../../i18n/translation'
import I18nKey from '../../i18n/i18nKey'
import { url } from '../../utils/url-utils'
const tags = await getTagList();
const tags = await getTagList()
const COLLAPSED_HEIGHT = "7.5rem";
const COLLAPSED_HEIGHT = '7.5rem'
const isCollapsed = tags.length >= 20;
const isCollapsed = tags.length >= 20
interface Props {
class?: string;
style?: string;
class?: string
style?: string
}
const className = Astro.props.class
const style = Astro.props.style
---
<WidgetLayout name={i18n(I18nKey.tags)} id="tags" isCollapsed={isCollapsed} collapsedHeight={COLLAPSED_HEIGHT} class={className} style={style}>
<div class="flex gap-2 flex-wrap">

View File

@@ -1,25 +1,18 @@
---
import { Icon } from 'astro-icon/components';
import {i18n} from "../../i18n/translation";
import I18nKey from "../../i18n/i18nKey";
import { Icon } from 'astro-icon/components'
import { i18n } from '../../i18n/translation'
import I18nKey from '../../i18n/i18nKey'
interface Props {
id: string;
name?: string;
isCollapsed?: boolean;
collapsedHeight?: string;
class?: string;
style?: string;
id: string
name?: string
isCollapsed?: boolean
collapsedHeight?: string
class?: string
style?: string
}
const props = Astro.props;
const {
id,
name,
isCollapsed,
collapsedHeight,
style,
} = Astro.props
const props = Astro.props
const { id, name, isCollapsed, collapsedHeight, style } = Astro.props
const className = Astro.props.class
---
<widget-layout data-id={id} data-is-collapsed={String(isCollapsed)} class={"pb-4 card-base " + className} style={style}>
<div class="font-bold transition text-lg text-neutral-900 dark:text-neutral-100 relative ml-8 mt-4 mb-2