feat: post styles, next/prev post btn, display-settings, etc.
(cherry picked from commit b7ddd92729d52a8c43d72010b743f7e3477f1001)
This commit is contained in:
parent
8ed0aa071f
commit
26408b0b7e
|
@ -12,7 +12,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.2.0",
|
"@astrojs/check": "^0.2.0",
|
||||||
"@astrojs/tailwind": "^4.0.0",
|
"@astrojs/tailwind": "^4.0.0",
|
||||||
"@astrojs/ts-plugin": "^1.1.3",
|
|
||||||
"@fontsource/roboto": "^5.0.8",
|
"@fontsource/roboto": "^5.0.8",
|
||||||
"astro": "^3.0.10",
|
"astro": "^3.0.10",
|
||||||
"astro-icon": "^1.0.0-next.2",
|
"astro-icon": "^1.0.0-next.2",
|
||||||
|
@ -23,6 +22,7 @@
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@astrojs/ts-plugin": "^1.1.3",
|
||||||
"@iconify-json/fa6-brands": "^1.1.13",
|
"@iconify-json/fa6-brands": "^1.1.13",
|
||||||
"@iconify-json/material-symbols": "^1.1.57",
|
"@iconify-json/material-symbols": "^1.1.57",
|
||||||
"@rollup/plugin-yaml": "^4.1.1",
|
"@rollup/plugin-yaml": "^4.1.1",
|
||||||
|
|
|
@ -11,9 +11,6 @@ dependencies:
|
||||||
'@astrojs/tailwind':
|
'@astrojs/tailwind':
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.0.0(astro@3.0.10)(tailwindcss@3.3.3)
|
version: 4.0.0(astro@3.0.10)(tailwindcss@3.3.3)
|
||||||
'@astrojs/ts-plugin':
|
|
||||||
specifier: ^1.1.3
|
|
||||||
version: 1.1.3
|
|
||||||
'@fontsource/roboto':
|
'@fontsource/roboto':
|
||||||
specifier: ^5.0.8
|
specifier: ^5.0.8
|
||||||
version: 5.0.8
|
version: 5.0.8
|
||||||
|
@ -40,6 +37,9 @@ dependencies:
|
||||||
version: 5.2.2
|
version: 5.2.2
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@astrojs/ts-plugin':
|
||||||
|
specifier: ^1.1.3
|
||||||
|
version: 1.1.3
|
||||||
'@iconify-json/fa6-brands':
|
'@iconify-json/fa6-brands':
|
||||||
specifier: ^1.1.13
|
specifier: ^1.1.13
|
||||||
version: 1.1.13
|
version: 1.1.13
|
||||||
|
@ -103,7 +103,6 @@ packages:
|
||||||
|
|
||||||
/@astrojs/compiler@1.5.7:
|
/@astrojs/compiler@1.5.7:
|
||||||
resolution: {integrity: sha512-dFU7GAMbpTUGPkRoCoMQrGFlTe3qIiQMSOxIXp/nB1Do4My9uogjEmBHdR5Cwr4i6rc5/1R3Od9v8kU/pkHXGQ==}
|
resolution: {integrity: sha512-dFU7GAMbpTUGPkRoCoMQrGFlTe3qIiQMSOxIXp/nB1Do4My9uogjEmBHdR5Cwr4i6rc5/1R3Od9v8kU/pkHXGQ==}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@astrojs/compiler@2.0.1:
|
/@astrojs/compiler@2.0.1:
|
||||||
resolution: {integrity: sha512-DfBR7Cf+tOgQ4n7TIgTtU5x5SEA/08DNshpEPcT+91A0KbBlmUOYMBM/O6qAaHkmVo1KIoXQYhAmfdTT1zx9PQ==}
|
resolution: {integrity: sha512-DfBR7Cf+tOgQ4n7TIgTtU5x5SEA/08DNshpEPcT+91A0KbBlmUOYMBM/O6qAaHkmVo1KIoXQYhAmfdTT1zx9PQ==}
|
||||||
|
@ -216,7 +215,7 @@ packages:
|
||||||
'@volar/language-core': 1.10.1
|
'@volar/language-core': 1.10.1
|
||||||
'@volar/typescript': 1.10.1
|
'@volar/typescript': 1.10.1
|
||||||
vscode-languageserver-textdocument: 1.0.8
|
vscode-languageserver-textdocument: 1.0.8
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/@babel/code-frame@7.22.13:
|
/@babel/code-frame@7.22.13:
|
||||||
resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
|
resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
|
||||||
|
@ -1117,7 +1116,6 @@ packages:
|
||||||
resolution: {integrity: sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==}
|
resolution: {integrity: sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@volar/source-map': 1.10.1
|
'@volar/source-map': 1.10.1
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@volar/language-server@1.10.1:
|
/@volar/language-server@1.10.1:
|
||||||
resolution: {integrity: sha512-UXgRMAPKoy4EZBcBT1SFp8YIb5AJqe7Is1/TnqRUq0LBBV2M7HpEeHHI8E4fy05Eg4TlSVRcrlZtiTrY9fRjJg==}
|
resolution: {integrity: sha512-UXgRMAPKoy4EZBcBT1SFp8YIb5AJqe7Is1/TnqRUq0LBBV2M7HpEeHHI8E4fy05Eg4TlSVRcrlZtiTrY9fRjJg==}
|
||||||
|
@ -1148,13 +1146,11 @@ packages:
|
||||||
resolution: {integrity: sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==}
|
resolution: {integrity: sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
muggle-string: 0.3.1
|
muggle-string: 0.3.1
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@volar/typescript@1.10.1:
|
/@volar/typescript@1.10.1:
|
||||||
resolution: {integrity: sha512-+iiO9yUSRHIYjlteT+QcdRq8b44qH19/eiUZtjNtuh6D9ailYM7DVR0zO2sEgJlvCaunw/CF9Ov2KooQBpR4VQ==}
|
resolution: {integrity: sha512-+iiO9yUSRHIYjlteT+QcdRq8b44qH19/eiUZtjNtuh6D9ailYM7DVR0zO2sEgJlvCaunw/CF9Ov2KooQBpR4VQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@volar/language-core': 1.10.1
|
'@volar/language-core': 1.10.1
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@vscode/emmet-helper@2.9.2:
|
/@vscode/emmet-helper@2.9.2:
|
||||||
resolution: {integrity: sha512-MaGuyW+fa13q3aYsluKqclmh62Hgp0BpKIqS66fCxfOaBcVQ1OnMQxRRgQUYnCkxFISAQlkJ0qWWPyXjro1Qrg==}
|
resolution: {integrity: sha512-MaGuyW+fa13q3aYsluKqclmh62Hgp0BpKIqS66fCxfOaBcVQ1OnMQxRRgQUYnCkxFISAQlkJ0qWWPyXjro1Qrg==}
|
||||||
|
@ -3029,7 +3025,6 @@ packages:
|
||||||
|
|
||||||
/muggle-string@0.3.1:
|
/muggle-string@0.3.1:
|
||||||
resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
|
resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/mz@2.7.0:
|
/mz@2.7.0:
|
||||||
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
||||||
|
@ -4328,7 +4323,6 @@ packages:
|
||||||
|
|
||||||
/vscode-languageserver-textdocument@1.0.8:
|
/vscode-languageserver-textdocument@1.0.8:
|
||||||
resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==}
|
resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/vscode-languageserver-types@3.17.3:
|
/vscode-languageserver-types@3.17.3:
|
||||||
resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==}
|
resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==}
|
||||||
|
|
|
@ -69,7 +69,7 @@ function formatDate(date: Date) {
|
||||||
</div>
|
</div>
|
||||||
{group.posts.map(post => (
|
{group.posts.map(post => (
|
||||||
<a href={getPostUrlBySlug(post.slug)} class="group">
|
<a href={getPostUrlBySlug(post.slug)} class="group">
|
||||||
<Button light height="40px" class="w-full hover:text-[initial]">
|
<Button light height="40px" class="w-full rounded-lg hover:text-[initial]">
|
||||||
<div class="flex flex-row justify-start items-center h-full">
|
<div class="flex flex-row justify-start items-center h-full">
|
||||||
<!-- date -->
|
<!-- date -->
|
||||||
<div class="w-[10%] transition text-sm text-right text-black/50 dark:text-white/50">{formatDate(post.data.pubDate)}</div>
|
<div class="w-[10%] transition text-sm text-right text-black/50 dark:text-white/50">{formatDate(post.data.pubDate)}</div>
|
||||||
|
|
|
@ -43,6 +43,9 @@ color_set(colors)
|
||||||
if length(value) > 1
|
if length(value) > 1
|
||||||
{key}: oklch_fallback(value[1])
|
{key}: oklch_fallback(value[1])
|
||||||
|
|
||||||
|
rainbow-light = linear-gradient(to right, oklch(0.80 0.10 0), oklch(0.80 0.10 30), oklch(0.80 0.10 60), oklch(0.80 0.10 90), oklch(0.80 0.10 120), oklch(0.80 0.10 150), oklch(0.80 0.10 180), oklch(0.80 0.10 210), oklch(0.80 0.10 240), oklch(0.80 0.10 270), oklch(0.80 0.10 300), oklch(0.80 0.10 330), oklch(0.80 0.10 360))
|
||||||
|
rainbow-dark = linear-gradient(to right, oklch(0.70 0.10 0), oklch(0.70 0.10 30), oklch(0.70 0.10 60), oklch(0.70 0.10 90), oklch(0.70 0.10 120), oklch(0.70 0.10 150), oklch(0.70 0.10 180), oklch(0.70 0.10 210), oklch(0.70 0.10 240), oklch(0.70 0.10 270), oklch(0.70 0.10 300), oklch(0.70 0.10 330), oklch(0.70 0.10 360))
|
||||||
|
|
||||||
:root
|
:root
|
||||||
--radius-large 16px
|
--radius-large 16px
|
||||||
|
|
||||||
|
@ -53,7 +56,7 @@ color_set({
|
||||||
--primary: oklch(0.70 0.14 var(--hue))
|
--primary: oklch(0.70 0.14 var(--hue))
|
||||||
--card-bg: white oklch(0.25 0.02 var(--hue))
|
--card-bg: white oklch(0.25 0.02 var(--hue))
|
||||||
|
|
||||||
--btn-content: oklch(0.55 0.12 var(--hue))
|
--btn-content: oklch(0.55 0.12 var(--hue)) oklch(0.75 0.1 var(--hue))
|
||||||
|
|
||||||
--btn-regular-bg: oklch(0.95 0.025 var(--hue)) oklch(0.38 0.04 var(--hue))
|
--btn-regular-bg: oklch(0.95 0.025 var(--hue)) oklch(0.38 0.04 var(--hue))
|
||||||
|
|
||||||
|
@ -70,6 +73,8 @@ color_set({
|
||||||
--line-color: black(0.1) white(0.1)
|
--line-color: black(0.1) white(0.1)
|
||||||
--meta-divider: black(0.2) white(0.2)
|
--meta-divider: black(0.2) white(0.2)
|
||||||
--selection-bg: oklch(0.90 0.05 var(--hue)) oklch(0.40 0.08 var(--hue))
|
--selection-bg: oklch(0.90 0.05 var(--hue)) oklch(0.40 0.08 var(--hue))
|
||||||
|
|
||||||
|
--color-selection-bar: rainbow-light rainbow-dark
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,32 @@
|
||||||
---
|
---
|
||||||
import Button from "./control/Button.astro";
|
import Button from "./control/Button.astro";
|
||||||
import { Icon } from 'astro-icon/components';
|
import { Icon } from 'astro-icon/components';
|
||||||
|
import DisplaySetting from "./widget/DisplaySetting.astro";
|
||||||
const className = Astro.props.class;
|
const className = Astro.props.class;
|
||||||
---
|
---
|
||||||
<div class:list={[
|
<div class:list={[
|
||||||
className,
|
className,
|
||||||
"card-base max-w-[var(--page-width)] h-[72px] rounded-t-none mx-auto flex items-center justify-between px-4"]}>
|
"card-base max-w-[var(--page-width)] h-[72px] rounded-t-none mx-auto flex items-center justify-between px-4"]}>
|
||||||
<a href="/"><Button height="52px" class="px-5 font-bold" light>
|
<a href="/"><Button height="52px" class="px-5 font-bold rounded-lg" light>
|
||||||
<div class="flex flex-row text-[var(--primary)] items-center text-md">
|
<div class="flex flex-row text-[var(--primary)] items-center text-md">
|
||||||
<Icon name="material-symbols:home-outline-rounded" size={28} class="mb-1 mr-2" />
|
<Icon name="material-symbols:home-outline-rounded" size={28} class="mb-1 mr-2" />
|
||||||
<div class="top-2"></div>Vivia Preview
|
<div class="top-2"></div>Vivia Preview
|
||||||
</div>
|
</div>
|
||||||
</Button></a>
|
</Button></a>
|
||||||
<div>
|
<div>
|
||||||
<a href="/"><Button light class="font-bold px-5">Home</Button></a>
|
<a href="/"><Button light class="font-bold px-5 rounded-lg">Home</Button></a>
|
||||||
<a href="/archive"><Button light class="font-bold px-5">Archive</Button></a>
|
<a href="/archive"><Button light class="font-bold px-5 rounded-lg">Archive</Button></a>
|
||||||
<a href="/about"><Button light class="font-bold px-5">About</Button></a>
|
<a href="/about"><Button light class="font-bold px-5 rounded-lg">About</Button></a>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<div>
|
||||||
|
<Button class="rounded-lg" id="display-settings-switch" iconName="material-symbols:palette-outline" iconSize={20} isIcon light></Button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button id="scheme-switch" iconName="material-symbols:wb-sunny-outline-rounded" iconSize={20} isIcon light></Button>
|
<Button class="rounded-lg" id="scheme-switch" iconName="material-symbols:wb-sunny-outline-rounded" iconSize={20} isIcon light></Button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<DisplaySetting></DisplaySetting>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -40,13 +47,15 @@ function switchTheme() {
|
||||||
|
|
||||||
function loadThemeSwitchScript() {
|
function loadThemeSwitchScript() {
|
||||||
let switchBtn = document.getElementById("scheme-switch");
|
let switchBtn = document.getElementById("scheme-switch");
|
||||||
if (switchBtn === null) {
|
|
||||||
console.log("test")
|
|
||||||
}
|
|
||||||
switchBtn.addEventListener("click", function () {
|
switchBtn.addEventListener("click", function () {
|
||||||
console.log("test")
|
|
||||||
switchTheme()
|
switchTheme()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let settingBtn = document.getElementById("display-settings-switch");
|
||||||
|
settingBtn.addEventListener("click", function () {
|
||||||
|
let settingPanel = document.getElementById("display-setting");
|
||||||
|
settingPanel.classList.toggle("closed");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadThemeSwitchScript();
|
loadThemeSwitchScript();
|
||||||
|
|
|
@ -68,7 +68,7 @@ const className = Astro.props.class;
|
||||||
@layer components {
|
@layer components {
|
||||||
.meta-icon {
|
.meta-icon {
|
||||||
@apply w-8 h-8 transition rounded-md flex items-center justify-center bg-[var(--btn-regular-bg)]
|
@apply w-8 h-8 transition rounded-md flex items-center justify-center bg-[var(--btn-regular-bg)]
|
||||||
text-[var(--btn-content)] dark:text-[var(--primary)] mr-2
|
text-[var(--btn-content)] mr-2
|
||||||
}
|
}
|
||||||
.with-divider {
|
.with-divider {
|
||||||
@apply before:content-['/'] before:mx-[6px] before:text-[var(--meta-divider)] before:text-sm
|
@apply before:content-['/'] before:mx-[6px] before:text-[var(--meta-divider)] before:text-sm
|
||||||
|
|
|
@ -43,7 +43,7 @@ const { remarkPluginFrontmatter } = await entry.render();
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- metadata -->
|
<!-- metadata -->
|
||||||
<PostMetadata pubDate={pubDate} tags={tags} categories={categories} class="mb-4"></PostMetadata>
|
<PostMetadata pubDate={pubDate} tags={tags} categories={categories} class:list={{"mb-4": description, "mb-6": !description}}></PostMetadata>
|
||||||
|
|
||||||
<div class="transition text-black/75 dark:text-white/75 mb-4">
|
<div class="transition text-black/75 dark:text-white/75 mb-4">
|
||||||
{ description }
|
{ description }
|
||||||
|
@ -67,7 +67,7 @@ const { remarkPluginFrontmatter } = await entry.render();
|
||||||
<Icon name="material-symbols:chevron-right-rounded"
|
<Icon name="material-symbols:chevron-right-rounded"
|
||||||
class="transition opacity-0 group-hover:opacity-100 text-white text-5xl"></Icon>
|
class="transition opacity-0 group-hover:opacity-100 text-white text-5xl"></Icon>
|
||||||
</div>
|
</div>
|
||||||
<ImageBox src="https://saicaca.github.io/vivia-preview/assets/79905307_p0.jpg"
|
<ImageBox src={cover}
|
||||||
class="w-full h-full">
|
class="w-full h-full">
|
||||||
</ImageBox>
|
</ImageBox>
|
||||||
</a>}
|
</a>}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Button from "./Button.astro";
|
||||||
|
|
||||||
<!-- There can't be a filter on parent element, or it will break `fixed` -->
|
<!-- There can't be a filter on parent element, or it will break `fixed` -->
|
||||||
<div class="back-to-top-wrapper" transition:persist>
|
<div class="back-to-top-wrapper" transition:persist>
|
||||||
<div id="back-to-top-btn" class="back-to-top-btn hide flex items-center rounded-2xl overflow-hidden" onclick="topFunction()">
|
<div id="back-to-top-btn" class="back-to-top-btn hide flex items-center rounded-2xl overflow-hidden transition" onclick="topFunction()">
|
||||||
<Button card height="60px" width="60px">
|
<Button card height="60px" width="60px">
|
||||||
<Icon name="material-symbols:keyboard-arrow-up-rounded" class="mx-auto"></Icon>
|
<Icon name="material-symbols:keyboard-arrow-up-rounded" class="mx-auto"></Icon>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -34,7 +34,6 @@ import { Icon } from 'astro-icon/components';
|
||||||
class:list={[
|
class:list={[
|
||||||
className,
|
className,
|
||||||
`
|
`
|
||||||
rounded-lg
|
|
||||||
transition
|
transition
|
||||||
h-[var(--height)]
|
h-[var(--height)]
|
||||||
`,
|
`,
|
||||||
|
@ -60,7 +59,7 @@ import { Icon } from 'astro-icon/components';
|
||||||
'dark:hover:bg-[oklch(0.45_0.045_var(--hue))]': regular,
|
'dark:hover:bg-[oklch(0.45_0.045_var(--hue))]': regular,
|
||||||
'dark:active:bg-[oklch(0.5_0.05_var(--hue))]': regular,
|
'dark:active:bg-[oklch(0.5_0.05_var(--hue))]': regular,
|
||||||
|
|
||||||
'card-base': card,
|
'bg-[var(--card-bg)]': card,
|
||||||
'enabled:hover:bg-[var(--btn-card-bg-hover)]': card,
|
'enabled:hover:bg-[var(--btn-card-bg-hover)]': card,
|
||||||
'enabled:active:bg-[var(--btn-card-bg-active)]': card,
|
'enabled:active:bg-[var(--btn-card-bg-active)]': card,
|
||||||
'disabled:text-black/10': card,
|
'disabled:text-black/10': card,
|
||||||
|
|
|
@ -8,7 +8,7 @@ interface Props {
|
||||||
const { size, dot, href }: Props = Astro.props;
|
const { size, dot, href }: Props = Astro.props;
|
||||||
---
|
---
|
||||||
<a href={href}>
|
<a href={href}>
|
||||||
<Button regular height="32px" class="text-[15px] px-3 flex flex-row items-center">
|
<Button regular height="32px" class="text-[15px] px-3 flex flex-row items-center rounded-lg">
|
||||||
{dot && <div class="h-1 w-1 bg-[var(--btn-content)] dark:bg-[var(--card-bg)] transition rounded-md mr-2"></div>}
|
{dot && <div class="h-1 w-1 bg-[var(--btn-content)] dark:bg-[var(--card-bg)] transition rounded-md mr-2"></div>}
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -55,7 +55,7 @@ const commonUrl: string = parts.slice(0, -1).join('/') + '/';
|
||||||
|
|
||||||
<div class:list={[className, "flex flex-row gap-3 justify-center"]}>
|
<div class:list={[className, "flex flex-row gap-3 justify-center"]}>
|
||||||
<a href={page.url.prev}>
|
<a href={page.url.prev}>
|
||||||
<Button isIcon card iconName="material-symbols:chevron-left-rounded" class="text-[var(--primary)]" iconSize={28}
|
<Button isIcon card iconName="material-symbols:chevron-left-rounded" class="text-[var(--primary)] rounded-lg" iconSize={28}
|
||||||
disabled = {page.url.prev == undefined}
|
disabled = {page.url.prev == undefined}
|
||||||
></Button>
|
></Button>
|
||||||
</a>
|
</a>
|
||||||
|
@ -70,14 +70,14 @@ const commonUrl: string = parts.slice(0, -1).join('/') + '/';
|
||||||
{p}
|
{p}
|
||||||
</div>
|
</div>
|
||||||
return <a href={commonUrl + p}>
|
return <a href={commonUrl + p}>
|
||||||
<Button card iconName="material-symbols:chevron-left-rounded" height="44px" width="44px">
|
<Button card iconName="material-symbols:chevron-left-rounded" class="rounded-lg" height="44px" width="44px">
|
||||||
{p}
|
{p}
|
||||||
</Button>
|
</Button>
|
||||||
</a>
|
</a>
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<a href={page.url.next}>
|
<a href={page.url.next}>
|
||||||
<Button isIcon card iconName="material-symbols:chevron-right-rounded" class="text-[var(--primary)]" iconSize={28}
|
<Button isIcon card iconName="material-symbols:chevron-right-rounded" class="text-[var(--primary)] rounded-lg" iconSize={28}
|
||||||
disabled = {page.url.next == undefined}
|
disabled = {page.url.next == undefined}
|
||||||
></Button>
|
></Button>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
---
|
||||||
|
import {getConfig} from "../../utils/config-utils";
|
||||||
|
const hueSet: number[] = [0, 30, 60, 180, 250, 270, 300, 330, 345];
|
||||||
|
|
||||||
|
const enableBanner = getConfig().banner.enable;
|
||||||
|
|
||||||
|
---
|
||||||
|
<div id="display-setting" class:list={["card-base closed absolute transition-all w-[320px] fixed right-4 border-[var(--primary)] px-4 py-4",
|
||||||
|
{"border-[3px]": !enableBanner}
|
||||||
|
]}>
|
||||||
|
<div class="flex flex-row gap-2 mb-3 items-center justify-between">
|
||||||
|
<div class="font-bold text-lg text-neutral-900 dark:text-neutral-100 transition relative ml-3
|
||||||
|
before:w-1 before:h-4 before:rounded-md before:bg-[var(--primary)]
|
||||||
|
before:absolute before:left-[-12px] before:top-[5.5px]"
|
||||||
|
>
|
||||||
|
Primary Color
|
||||||
|
</div>
|
||||||
|
<div id="hueValue" class="transition bg-[var(--btn-regular-bg)] w-10 h-7 rounded-md flex justify-center font-bold transition text-sm items-center text-[var(--btn-content)]">
|
||||||
|
{0}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="preset-list" class="flex flex-row gap-1 mb-4 hidden">
|
||||||
|
{hueSet.map((hue) => <div
|
||||||
|
class="h-7 w-8 rounded-md cursor-pointer
|
||||||
|
bg-[oklch(0.75_0.14_var(--hue))]
|
||||||
|
hover:bg-[oklch(0.70_0.12_var(--hue))]
|
||||||
|
active:bg-[oklch(0.65_0.11_var(--hue))]
|
||||||
|
"
|
||||||
|
style=`--hue: ${hue}` data-hue={hue}
|
||||||
|
>
|
||||||
|
|
||||||
|
</div>)}
|
||||||
|
</div>
|
||||||
|
<div class="w-full h-6 px-1 bg-[oklch(0.80_0.10_0)] dark:bg-[oklch(0.70_0.10_0)] rounded select-none">
|
||||||
|
<input type="range" min="0" max="360" value="0" class="slider" id="colorSlider" step="5" style="width: 100%;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script is:raw>
|
||||||
|
(function () {
|
||||||
|
let presetList = document.getElementById("preset-list");
|
||||||
|
let output = document.getElementById("hueValue");
|
||||||
|
let slider = document.getElementById("colorSlider");
|
||||||
|
output.innerHTML = slider.value; // Display the default slider value
|
||||||
|
|
||||||
|
let r = document.querySelector(':root');
|
||||||
|
function setHue(hue) {
|
||||||
|
localStorage.setItem('hue', hue);
|
||||||
|
output.innerHTML = hue;
|
||||||
|
slider.value = hue;
|
||||||
|
|
||||||
|
r.style.setProperty(`--hue`, hue);
|
||||||
|
}
|
||||||
|
|
||||||
|
let storedHue = localStorage.getItem('hue');
|
||||||
|
if (storedHue) {
|
||||||
|
setHue(storedHue);
|
||||||
|
}
|
||||||
|
|
||||||
|
presetList.onclick = function(event) {
|
||||||
|
let hue = event.target.dataset.hue;
|
||||||
|
if (hue) {
|
||||||
|
setHue(hue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slider.oninput = function() {
|
||||||
|
let hue = this.value;
|
||||||
|
output.innerHTML = this.value;
|
||||||
|
setHue(hue);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("click", event => {
|
||||||
|
var cDom = document.getElementById("display-setting");
|
||||||
|
let settingBtn = document.getElementById("display-settings-switch");
|
||||||
|
var tDom = event.target;
|
||||||
|
if (cDom == tDom || cDom.contains(tDom) || settingBtn == tDom || settingBtn.contains(tDom)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cDom.classList.add("closed");
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" is:global>
|
||||||
|
#display-setting
|
||||||
|
input[type="range"]
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 24px;
|
||||||
|
background-image: var(--color-selection-bar)
|
||||||
|
transition: background-image 0.15s ease-in-out
|
||||||
|
|
||||||
|
/* Input Thumb */
|
||||||
|
::-webkit-slider-thumb
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 16px;
|
||||||
|
width: 8px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
::-moz-range-thumb
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 24px;
|
||||||
|
width: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
&::-ms-thumb
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 24px;
|
||||||
|
width: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
box-shadow: none;
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
#display-setting {
|
||||||
|
@apply top-[84px]
|
||||||
|
}
|
||||||
|
#display-setting.closed {
|
||||||
|
@apply top-[76px] opacity-0 pointer-events-none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import ImageBox from "../misc/ImageBox.astro";
|
import ImageBox from "../misc/ImageBox.astro";
|
||||||
import ButtonLight from "../control/Button.astro";
|
import Button from "../control/Button.astro";
|
||||||
import {getConfig} from "../../utils/config-utils";
|
import {getConfig} from "../../utils/config-utils";
|
||||||
interface props {
|
interface props {
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ const vConf = getConfig();
|
||||||
<div class="flex gap-2 mx-2 justify-center mb-4">
|
<div class="flex gap-2 mx-2 justify-center mb-4">
|
||||||
{vConf.profile.links.map(item =>
|
{vConf.profile.links.map(item =>
|
||||||
<a href={item.url} target="_blank">
|
<a href={item.url} target="_blank">
|
||||||
<ButtonLight isIcon iconName={item.icon} regular height="40px"></ButtonLight>
|
<Button isIcon iconName={item.icon} regular height="40px" class="rounded-lg"></Button>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -46,11 +46,14 @@ const myFade = {
|
||||||
// defines global css variables
|
// defines global css variables
|
||||||
// why doing this in Layout instead of GlobalStyles: https://github.com/withastro/astro/issues/6728#issuecomment-1502203757
|
// why doing this in Layout instead of GlobalStyles: https://github.com/withastro/astro/issues/6728#issuecomment-1502203757
|
||||||
const viConf = getConfig();
|
const viConf = getConfig();
|
||||||
const hue = viConf.appearance.hue;
|
const configHue = viConf.appearance.hue;
|
||||||
if (!banner || typeof banner !== 'string' || banner.trim() === '') {
|
if (!banner || typeof banner !== 'string' || banner.trim() === '') {
|
||||||
banner = viConf.banner.url;
|
banner = viConf.banner.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO don't use post cover as banner for now
|
||||||
|
banner = viConf.banner.url;
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
@ -71,7 +74,7 @@ if (!banner || typeof banner !== 'string' || banner.trim() === '') {
|
||||||
<link rel="icon" media="(prefers-color-scheme: dark)" href="/favicon/favicon-dark-180.png" sizes="180x180">
|
<link rel="icon" media="(prefers-color-scheme: dark)" href="/favicon/favicon-dark-180.png" sizes="180x180">
|
||||||
<link rel="icon" media="(prefers-color-scheme: dark)" href="/favicon/favicon-dark-192.png" sizes="192x192">
|
<link rel="icon" media="(prefers-color-scheme: dark)" href="/favicon/favicon-dark-192.png" sizes="192x192">
|
||||||
|
|
||||||
<style define:vars={{ hue }}></style> <!-- defines global css variables -->
|
<style define:vars={{ configHue }}></style> <!-- defines global css variables. This will be applied to <html> <body> and some other elements idk why -->
|
||||||
|
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
</head>
|
</head>
|
||||||
|
@ -82,7 +85,7 @@ if (!banner || typeof banner !== 'string' || banner.trim() === '') {
|
||||||
id="banner-wrapper"
|
id="banner-wrapper"
|
||||||
>
|
>
|
||||||
<!-- TODO the transition here is not correct -->
|
<!-- TODO the transition here is not correct -->
|
||||||
<ImageBox id="boxtest" class="object-center object-cover h-full"
|
<ImageBox id="boxtest" class:list={["object-center object-cover h-full", {"hidden": !viConf.banner.enable}]}
|
||||||
src={banner} transition:animate="fade"
|
src={banner} transition:animate="fade"
|
||||||
>
|
>
|
||||||
</ImageBox>
|
</ImageBox>
|
||||||
|
@ -93,6 +96,7 @@ if (!banner || typeof banner !== 'string' || banner.trim() === '') {
|
||||||
</html>
|
</html>
|
||||||
<style is:global>
|
<style is:global>
|
||||||
:root {
|
:root {
|
||||||
|
--hue: var(--configHue);
|
||||||
--accent: 136, 58, 234;
|
--accent: 136, 58, 234;
|
||||||
--accent-light: 224, 204, 250;
|
--accent-light: 224, 204, 250;
|
||||||
--accent-dark: 49, 10, 101;
|
--accent-dark: 49, 10, 101;
|
||||||
|
@ -169,7 +173,13 @@ function loadTheme() {
|
||||||
document.documentElement.classList.remove('dark');
|
document.documentElement.classList.remove('dark');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadTheme();
|
|
||||||
|
function loadHue() {
|
||||||
|
const hue = localStorage.hue;
|
||||||
|
if (hue) {
|
||||||
|
document.documentElement.style.setProperty('--hue', hue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setBannerHeight() {
|
function setBannerHeight() {
|
||||||
const banner = document.getElementById('banner-wrapper');
|
const banner = document.getElementById('banner-wrapper');
|
||||||
|
@ -182,10 +192,15 @@ function setBannerHeight() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load light/dark mode setting */
|
/* Load settings when entering the site */
|
||||||
|
loadTheme();
|
||||||
|
loadHue();
|
||||||
|
|
||||||
|
/* Load settings before swapping */
|
||||||
/* astro:after-swap event happened before swap animation */
|
/* astro:after-swap event happened before swap animation */
|
||||||
document.addEventListener('astro:after-swap', () => {
|
document.addEventListener('astro:after-swap', () => {
|
||||||
setBannerHeight();
|
setBannerHeight();
|
||||||
loadTheme();
|
loadTheme();
|
||||||
|
loadHue();
|
||||||
}, { once: false });
|
}, { once: false });
|
||||||
</script>
|
</script>
|
|
@ -5,10 +5,12 @@ import SideBar from "../components/widget/SideBar.astro";
|
||||||
import {pathsEqual} from "../utils/url-utils";
|
import {pathsEqual} from "../utils/url-utils";
|
||||||
import Footer from "../components/Footer.astro";
|
import Footer from "../components/Footer.astro";
|
||||||
import BackToTop from "../components/control/BackToTop.astro";
|
import BackToTop from "../components/control/BackToTop.astro";
|
||||||
|
import DisplaySetting from "../components/widget/DisplaySetting.astro";
|
||||||
|
import {getConfig} from "../utils/config-utils";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
banner: string;
|
banner?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title, banner } = Astro.props;
|
const { title, banner } = Astro.props;
|
||||||
|
@ -18,14 +20,16 @@ const isHomePage = pathsEqual(Astro.url.pathname, '/') || pathsEqual(Astro.url.p
|
||||||
const pageWidth = "1200px";
|
const pageWidth = "1200px";
|
||||||
const sidebarWidth = "280px";
|
const sidebarWidth = "280px";
|
||||||
|
|
||||||
|
const enableBanner = getConfig().banner.enable;
|
||||||
|
|
||||||
---
|
---
|
||||||
<Layout title={title} banner={banner}>
|
<Layout title={title} banner={banner}>
|
||||||
<div class=`max-w-[1200px] min-h-screen grid grid-cols-[280px_auto] grid-rows-[auto_auto_1fr_auto] lg:grid-rows-[auto_1fr_auto] mx-auto gap-4 relative overflow-hidden `
|
<div class=`max-w-[1200px] min-h-screen grid grid-cols-[280px_auto] grid-rows-[auto_auto_1fr_auto] lg:grid-rows-[auto_1fr_auto] mx-auto gap-4 relative overflow-hidden `
|
||||||
transition:animate="none"
|
transition:animate="none"
|
||||||
>
|
>
|
||||||
<div id="top-row" class="col-span-2 grid-rows-1" class:list={{
|
<div id="top-row" class="col-span-2 grid-rows-1 z-50" class:list={{
|
||||||
'min-h-[calc(var(--banner-height-home)_-_72px)]': isHomePage,
|
'min-h-[calc(var(--banner-height-home)_-_72px)]': enableBanner && isHomePage,
|
||||||
'min-h-[calc(var(--banner-height)_-_72px)]': !isHomePage}}
|
'min-h-[calc(var(--banner-height)_-_72px)]': enableBanner && !isHomePage,}}
|
||||||
>
|
>
|
||||||
<Navbar transition:animate="fade" transition:persist></Navbar>
|
<Navbar transition:animate="fade" transition:persist></Navbar>
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,8 +41,8 @@ const sidebarWidth = "280px";
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-rows-3 col-span-2 mt-4" transition:persist>
|
<div class="grid-rows-3 col-span-2 mt-4" transition:persist transition:animate="fade">
|
||||||
<Footer></Footer>
|
<Footer transition:persist></Footer>
|
||||||
</div>
|
</div>
|
||||||
<BackToTop></BackToTop>
|
<BackToTop></BackToTop>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,8 +6,9 @@ import ImageBox from "../../components/misc/ImageBox.astro";
|
||||||
import {Icon} from "astro-icon/components";
|
import {Icon} from "astro-icon/components";
|
||||||
import {formatDateToYYYYMMDD} from "../../utils/date-utils";
|
import {formatDateToYYYYMMDD} from "../../utils/date-utils";
|
||||||
import PostMetadata from "../../components/PostMetadata.astro";
|
import PostMetadata from "../../components/PostMetadata.astro";
|
||||||
// 1. 为每个集合条目生成一个新路径
|
import {getPostUrlBySlug} from "../../utils/content-utils";
|
||||||
|
import Button from "../../components/control/Button.astro";
|
||||||
|
import {getConfig} from "../../utils/config-utils";
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const blogEntries = await getCollection('posts');
|
const blogEntries = await getCollection('posts');
|
||||||
|
@ -15,16 +16,17 @@ export async function getStaticPaths() {
|
||||||
params: { slug: entry.slug }, props: { entry },
|
params: { slug: entry.slug }, props: { entry },
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
// 2. 当渲染的时候,你可以直接从属性中得到条目
|
|
||||||
const { entry } = Astro.props;
|
const { entry } = Astro.props;
|
||||||
const { Content } = await entry.render();
|
const { Content } = await entry.render();
|
||||||
|
|
||||||
const { remarkPluginFrontmatter } = await entry.render();
|
const { remarkPluginFrontmatter } = await entry.render();
|
||||||
|
|
||||||
|
const enableBanner = getConfig().banner.enable;
|
||||||
|
|
||||||
---
|
---
|
||||||
<MainGridLayout banner={entry.data.cover}>
|
<MainGridLayout banner={entry.data.cover}>
|
||||||
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative">
|
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative mb-4">
|
||||||
<div class:list={["card-base z-10 px-9 py-6 relative w-full ",
|
<div class:list={["card-base z-10 px-9 py-6 relative w-full ",
|
||||||
{}
|
{}
|
||||||
]}>
|
]}>
|
||||||
|
@ -59,15 +61,39 @@ const { remarkPluginFrontmatter } = await entry.render();
|
||||||
categories={entry.data.categories}
|
categories={entry.data.categories}
|
||||||
></PostMetadata>
|
></PostMetadata>
|
||||||
|
|
||||||
<div class="border-[var(--line-divider)] border-dashed border-b-[1px] mb-5"></div>
|
<!-- always show cover as long as it has one -->
|
||||||
|
|
||||||
|
{entry.data.cover &&
|
||||||
|
<ImageBox src={entry.data.cover} class="mb-8 rounded-xl"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
{!entry.data.cover && <div class="border-[var(--line-divider)] border-dashed border-b-[1px] mb-5"></div>}
|
||||||
|
|
||||||
<div class="prose dark:prose-invert max-w-none prose-h1:text-3xl">
|
<div class="prose dark:prose-invert max-w-none prose-h1:text-3xl">
|
||||||
<Content />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-between gap-4 overflow-hidden w-full">
|
||||||
|
<a href={getPostUrlBySlug(entry.data.prevSlug)} class="w-full font-bold overflow-hidden">
|
||||||
|
{entry.data.prevSlug && <Button class="w-full max-w-full h-10 px-4 rounded-2xl flex items-center justify-start gap-4" card height="60px">
|
||||||
|
<Icon name="material-symbols:chevron-left-rounded" size={32} class="text-[var(--primary)]" />
|
||||||
|
<div class="overflow-hidden overflow-ellipsis whitespace-nowrap max-w-[calc(100%_-_48px)] text-black/75 dark:text-white/75">
|
||||||
|
{entry.data.prevTitle}
|
||||||
|
</div>
|
||||||
|
</Button>}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href={getPostUrlBySlug(entry.data.nextSlug)} class="w-full font-bold overflow-hidden">
|
||||||
|
{entry.data.nextSlug && <Button class="w-full max-w-full h-10 px-4 rounded-2xl flex items-center justify-end gap-4" card height="60px">
|
||||||
|
<div class="overflow-hidden overflow-ellipsis whitespace-nowrap max-w-[calc(100%_-_48px)] text-black/75 dark:text-white/75">
|
||||||
|
{entry.data.nextTitle}
|
||||||
|
</div>
|
||||||
|
<Icon name="material-symbols:chevron-right-rounded" size={32} class="text-[var(--primary)]" />
|
||||||
|
</Button>}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</MainGridLayout>
|
</MainGridLayout>
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
import {getCollection} from "astro:content";
|
import {CollectionEntry, getCollection} from "astro:content";
|
||||||
|
|
||||||
export async function getSortedPosts() {
|
export async function getSortedPosts() {
|
||||||
const allBlogPosts = await getCollection("posts");
|
const allBlogPosts = await getCollection("posts");
|
||||||
return allBlogPosts.sort((a, b) => {
|
const sorted = allBlogPosts.sort((a, b) => {
|
||||||
const dateA = new Date(a.data.pubDate);
|
const dateA = new Date(a.data.pubDate);
|
||||||
const dateB = new Date(b.data.pubDate);
|
const dateB = new Date(b.data.pubDate);
|
||||||
return dateA > dateB ? -1 : 1;
|
return dateA > dateB ? -1 : 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (let i = 1; i < sorted.length; i++) {
|
||||||
|
sorted[i].data.nextSlug = sorted[i - 1].slug;
|
||||||
|
sorted[i].data.nextTitle = sorted[i - 1].data.title;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < sorted.length - 1; i++) {
|
||||||
|
sorted[i].data.prevSlug = sorted[i + 1].slug;
|
||||||
|
sorted[i].data.prevTitle = sorted[i + 1].data.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPostUrlBySlug(slug: string): string {
|
export function getPostUrlBySlug(slug: string): string {
|
||||||
|
|
|
@ -8,5 +8,9 @@
|
||||||
"name": "@astrojs/ts-plugin"
|
"name": "@astrojs/ts-plugin"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/**",
|
||||||
|
"src/**/**/**",
|
||||||
|
]
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ appearance:
|
||||||
hue: 250
|
hue: 250
|
||||||
|
|
||||||
banner:
|
banner:
|
||||||
|
enable: true
|
||||||
url: https://saicaca.github.io/vivia-preview/assets/banner.jpg
|
url: https://saicaca.github.io/vivia-preview/assets/banner.jpg
|
||||||
|
|
||||||
profile:
|
profile:
|
||||||
|
|
Loading…
Reference in New Issue