feat: i18n, page title
(cherry picked from commit 0d9fc72bee009c591400055725680a6a0f5a9c83)
This commit is contained in:
parent
52959f230f
commit
2c4cc28e1f
|
@ -2,7 +2,22 @@
|
||||||
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";
|
import DisplaySetting from "./widget/DisplaySetting.astro";
|
||||||
|
import {getConfig} from "../utils/config-utils";
|
||||||
|
import I18nKey from "../i18n/i18nKey";
|
||||||
|
import {i18n} from "../i18n/translation";
|
||||||
const className = Astro.props.class;
|
const className = Astro.props.class;
|
||||||
|
|
||||||
|
function isI18nKey(key: string): key is I18nKey {
|
||||||
|
return Object.values(I18nKey).includes(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLinkName(name: string) {
|
||||||
|
if (isI18nKey(name)) {
|
||||||
|
return i18n(name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
<div class:list={[
|
<div class:list={[
|
||||||
className,
|
className,
|
||||||
|
@ -10,13 +25,13 @@ const className = Astro.props.class;
|
||||||
<a href="/"><Button height="52px" class="px-5 font-bold rounded-lg" 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
|
{getConfig().title}
|
||||||
</div>
|
</div>
|
||||||
</Button></a>
|
</Button></a>
|
||||||
<div>
|
<div>
|
||||||
<a href="/"><Button light class="font-bold px-5 rounded-lg">Home</Button></a>
|
{Object.keys(getConfig().menu).map((key) => {
|
||||||
<a href="/archive"><Button light class="font-bold px-5 rounded-lg">Archive</Button></a>
|
return <a href={getConfig().menu[key]}><Button light class="font-bold px-5 rounded-lg">{getLinkName(key)}</Button></a>
|
||||||
<a href="/about"><Button light class="font-bold px-5 rounded-lg">About</Button></a>
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
---
|
---
|
||||||
import {formatDateToYYYYMMDD} from "../utils/date-utils";
|
import {formatDateToYYYYMMDD} from "../utils/date-utils";
|
||||||
import { Icon } from 'astro-icon/components';
|
import { Icon } from 'astro-icon/components';
|
||||||
|
import {i18n} from "../i18n/translation";
|
||||||
|
import I18nKey from "../i18n/i18nKey";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
class: string;
|
class: string;
|
||||||
|
@ -38,7 +40,7 @@ const className = Astro.props.class;
|
||||||
{category}
|
{category}
|
||||||
</a>
|
</a>
|
||||||
</div>)}
|
</div>)}
|
||||||
{!categories && <div class="transition text-black/50 dark:text-white/50 text-sm font-medium">Uncategorized</div>}
|
{!categories && <div class="transition text-black/50 dark:text-white/50 text-sm font-medium">{i18n(I18nKey.uncategorized)}</div>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -49,7 +51,7 @@ const className = Astro.props.class;
|
||||||
<Icon name="material-symbols:tag-rounded" class="text-xl"></Icon>
|
<Icon name="material-symbols:tag-rounded" class="text-xl"></Icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row">
|
<div class="flex flex-row">
|
||||||
{tags.map(tag => <div
|
{tags && tags.map(tag => <div
|
||||||
class="with-divider"
|
class="with-divider"
|
||||||
>
|
>
|
||||||
<a href=`/archive/tag/${tag}`
|
<a href=`/archive/tag/${tag}`
|
||||||
|
@ -58,6 +60,7 @@ const className = Astro.props.class;
|
||||||
{tag}
|
{tag}
|
||||||
</a>
|
</a>
|
||||||
</div>)}
|
</div>)}
|
||||||
|
{!tags && <div class="transition text-black/50 dark:text-white/50 text-sm font-medium">{i18n(I18nKey.noTags)}</div>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -19,6 +19,8 @@ import ImageBox from "./misc/ImageBox.astro";
|
||||||
import ButtonTag from "./control/ButtonTag.astro";
|
import ButtonTag from "./control/ButtonTag.astro";
|
||||||
import { Icon } from 'astro-icon/components';
|
import { Icon } from 'astro-icon/components';
|
||||||
import Button from "./control/Button.astro";
|
import Button from "./control/Button.astro";
|
||||||
|
import {i18n} from "../i18n/translation";
|
||||||
|
import I18nKey from "../i18n/i18nKey";
|
||||||
|
|
||||||
// tags = ['Foo', 'Bar', 'Baz', 'Qux', 'Quux'];
|
// tags = ['Foo', 'Bar', 'Baz', 'Qux', 'Quux'];
|
||||||
|
|
||||||
|
@ -51,9 +53,9 @@ const { remarkPluginFrontmatter } = await entry.render();
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition">
|
<div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition">
|
||||||
<div>{remarkPluginFrontmatter.words} words</div>
|
<div>{remarkPluginFrontmatter.words} {" " + i18n(I18nKey.wordsCount)}</div>
|
||||||
<div>|</div>
|
<div>|</div>
|
||||||
<div>{remarkPluginFrontmatter.minutes} minutes</div>
|
<div>{remarkPluginFrontmatter.minutes} {" " + i18n(I18nKey.minutesCount)}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
---
|
---
|
||||||
import {getConfig} from "../../utils/config-utils";
|
import {getConfig} from "../../utils/config-utils";
|
||||||
|
import {i18n} from "../../i18n/translation";
|
||||||
|
import I18nKey from "../../i18n/i18nKey";
|
||||||
const hueSet: number[] = [0, 30, 60, 180, 250, 270, 300, 330, 345];
|
const hueSet: number[] = [0, 30, 60, 180, 250, 270, 300, 330, 345];
|
||||||
|
|
||||||
const enableBanner = getConfig().banner.enable;
|
const enableBanner = getConfig().banner.enable;
|
||||||
|
@ -13,7 +15,7 @@ const enableBanner = getConfig().banner.enable;
|
||||||
before:w-1 before:h-4 before:rounded-md before:bg-[var(--primary)]
|
before:w-1 before:h-4 before:rounded-md before:bg-[var(--primary)]
|
||||||
before:absolute before:left-[-12px] before:top-[5.5px]"
|
before:absolute before:left-[-12px] before:top-[5.5px]"
|
||||||
>
|
>
|
||||||
Primary Color
|
{i18n(I18nKey.primaryColor)}
|
||||||
</div>
|
</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)]">
|
<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}
|
{0}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
import WidgetLayout from "./WidgetLayout.astro";
|
import WidgetLayout from "./WidgetLayout.astro";
|
||||||
import ButtonLink from "../control/ButtonLink.astro";
|
import ButtonLink from "../control/ButtonLink.astro";
|
||||||
import {getPostUrlBySlug, getSortedPosts} from "../../utils/content-utils";
|
import {getPostUrlBySlug, getSortedPosts} from "../../utils/content-utils";
|
||||||
|
import {i18n} from "../../i18n/translation";
|
||||||
|
import I18nKey from "../../i18n/i18nKey";
|
||||||
|
|
||||||
let posts = await getSortedPosts()
|
let posts = await getSortedPosts()
|
||||||
|
|
||||||
|
@ -11,7 +13,7 @@ posts = posts.slice(0, LIMIT)
|
||||||
|
|
||||||
// console.log(posts)
|
// console.log(posts)
|
||||||
---
|
---
|
||||||
<WidgetLayout name="Recent Posts">
|
<WidgetLayout name={i18n(I18nKey.recentPosts)}>
|
||||||
{posts.map(post =>
|
{posts.map(post =>
|
||||||
<ButtonLink url={getPostUrlBySlug(post.slug)}>{post.data.title}</ButtonLink>
|
<ButtonLink url={getPostUrlBySlug(post.slug)}>{post.data.title}</ButtonLink>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
import WidgetLayout from "./WidgetLayout.astro";
|
import WidgetLayout from "./WidgetLayout.astro";
|
||||||
import ButtonTag from "../control/ButtonTag.astro";
|
import ButtonTag from "../control/ButtonTag.astro";
|
||||||
import {getTagList} from "../../utils/content-utils";
|
import {getTagList} from "../../utils/content-utils";
|
||||||
|
import {i18n} from "../../i18n/translation";
|
||||||
|
import I18nKey from "../../i18n/i18nKey";
|
||||||
|
|
||||||
const tags = await getTagList();
|
const tags = await getTagList();
|
||||||
|
|
||||||
---
|
---
|
||||||
<WidgetLayout name="Tags">
|
<WidgetLayout name={i18n(I18nKey.tags)}>
|
||||||
<div class="flex gap-2 flex-wrap">
|
<div class="flex gap-2 flex-wrap">
|
||||||
{tags.map(t => (
|
{tags.map(t => (
|
||||||
<ButtonTag href={`/archive/tag/${t.name}`}>
|
<ButtonTag href={`/archive/tag/${t.name}`}>
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
enum I18nKey {
|
||||||
|
home = "home",
|
||||||
|
about = "about",
|
||||||
|
archive = "archive",
|
||||||
|
|
||||||
|
tags = "tags",
|
||||||
|
categories = "categories",
|
||||||
|
recentPosts = "recentPosts",
|
||||||
|
|
||||||
|
comments = "comments",
|
||||||
|
|
||||||
|
untitled = "untitled",
|
||||||
|
uncategorized = "uncategorized",
|
||||||
|
noTags = "noTags",
|
||||||
|
|
||||||
|
wordCount = "wordCount",
|
||||||
|
wordsCount = "wordsCount",
|
||||||
|
minuteCount = "minuteCount",
|
||||||
|
minutesCount = "minutesCount",
|
||||||
|
postCount = "postCount",
|
||||||
|
postsCount = "postsCount",
|
||||||
|
|
||||||
|
primaryColor = "primaryColor",
|
||||||
|
}
|
||||||
|
|
||||||
|
export default I18nKey;
|
|
@ -0,0 +1,27 @@
|
||||||
|
import type { Translation } from "../translation.ts";
|
||||||
|
import Key from "../i18nKey.ts";
|
||||||
|
|
||||||
|
export const en: Translation = {
|
||||||
|
[Key.home]: "Home",
|
||||||
|
[Key.about]: "About",
|
||||||
|
[Key.archive]: "Archive",
|
||||||
|
|
||||||
|
[Key.tags]: "Tags",
|
||||||
|
[Key.categories]: "Categories",
|
||||||
|
[Key.recentPosts]: "Recent Posts",
|
||||||
|
|
||||||
|
[Key.comments]: "Comments",
|
||||||
|
|
||||||
|
[Key.untitled]: "Untitled",
|
||||||
|
[Key.uncategorized]: "Uncategorized",
|
||||||
|
[Key.noTags]: "No Tags",
|
||||||
|
|
||||||
|
[Key.wordCount]: "word",
|
||||||
|
[Key.wordsCount]: "words",
|
||||||
|
[Key.minuteCount]: "minute",
|
||||||
|
[Key.minutesCount]: "minutes",
|
||||||
|
[Key.postCount]: "post",
|
||||||
|
[Key.postsCount]: "posts",
|
||||||
|
|
||||||
|
[Key.primaryColor]: "Primary Color",
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
import type { Translation } from "../translation.ts";
|
||||||
|
import Key from "../i18nKey.ts";
|
||||||
|
|
||||||
|
export const zh_CN: Translation = {
|
||||||
|
[Key.home]: "主页",
|
||||||
|
[Key.about]: "关于",
|
||||||
|
[Key.archive]: "归档",
|
||||||
|
|
||||||
|
[Key.tags]: "标签",
|
||||||
|
[Key.categories]: "分类",
|
||||||
|
[Key.recentPosts]: "最新文章",
|
||||||
|
|
||||||
|
[Key.comments]: "评论",
|
||||||
|
|
||||||
|
[Key.untitled]: "无标题",
|
||||||
|
[Key.uncategorized]: "未分类",
|
||||||
|
[Key.noTags]: "无标签",
|
||||||
|
|
||||||
|
[Key.wordCount]: "字",
|
||||||
|
[Key.wordsCount]: "字",
|
||||||
|
[Key.minuteCount]: "分钟",
|
||||||
|
[Key.minutesCount]: "分钟",
|
||||||
|
[Key.postCount]: "篇文章",
|
||||||
|
[Key.postsCount]: "篇文章",
|
||||||
|
|
||||||
|
[Key.primaryColor]: "主题色",
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
import type { Translation } from "../translation.ts";
|
||||||
|
import Key from "../i18nKey.ts";
|
||||||
|
|
||||||
|
export const zh_TW: Translation = {
|
||||||
|
[Key.home]: "首頁",
|
||||||
|
[Key.about]: "關於",
|
||||||
|
[Key.archive]: "彙整",
|
||||||
|
|
||||||
|
[Key.tags]: "標籤",
|
||||||
|
[Key.categories]: "分類",
|
||||||
|
[Key.recentPosts]: "最新文章",
|
||||||
|
|
||||||
|
[Key.comments]: "評論",
|
||||||
|
|
||||||
|
[Key.untitled]: "無標題",
|
||||||
|
[Key.uncategorized]: "未分類",
|
||||||
|
[Key.noTags]: "無標籤",
|
||||||
|
|
||||||
|
[Key.wordCount]: "字",
|
||||||
|
[Key.wordsCount]: "字",
|
||||||
|
[Key.minuteCount]: "分鐘",
|
||||||
|
[Key.minutesCount]: "分鐘",
|
||||||
|
[Key.postCount]: "篇文章",
|
||||||
|
[Key.postsCount]: "篇文章",
|
||||||
|
|
||||||
|
[Key.primaryColor]: "主題色",
|
||||||
|
};
|
|
@ -0,0 +1,30 @@
|
||||||
|
import {en} from "./languages/en.ts";
|
||||||
|
import {zh_TW} from "./languages/zh_TW.ts";
|
||||||
|
import {zh_CN} from "./languages/zh_CN.ts";
|
||||||
|
import type I18nKey from "./i18nKey.ts";
|
||||||
|
import {getConfig} from "../utils/config-utils.ts";
|
||||||
|
|
||||||
|
export type Translation = {
|
||||||
|
[K in I18nKey]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultTranslation = en;
|
||||||
|
|
||||||
|
const map: { [key: string]: Translation } = {
|
||||||
|
"en": en,
|
||||||
|
"en_us": en,
|
||||||
|
"en_gb": en,
|
||||||
|
"en_au": en,
|
||||||
|
"zh_cn": zh_CN,
|
||||||
|
"zh_tw": zh_TW,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTranslation(lang: string): Translation {
|
||||||
|
lang = lang.toLowerCase();
|
||||||
|
return map[lang] || defaultTranslation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function i18n(key: I18nKey): string {
|
||||||
|
const lang = getConfig().lang || "en";
|
||||||
|
return getTranslation(lang)[key];
|
||||||
|
}
|
|
@ -54,6 +54,11 @@ if (!banner || typeof banner !== 'string' || banner.trim() === '') {
|
||||||
// TODO don't use post cover as banner for now
|
// TODO don't use post cover as banner for now
|
||||||
banner = viConf.banner.url;
|
banner = viConf.banner.url;
|
||||||
|
|
||||||
|
let pageTitle = getConfig().title;
|
||||||
|
if (title) {
|
||||||
|
pageTitle = `${title} - ${pageTitle}`;
|
||||||
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
@ -61,6 +66,8 @@ banner = viConf.banner.url;
|
||||||
<head>
|
<head>
|
||||||
<ViewTransitions />
|
<ViewTransitions />
|
||||||
|
|
||||||
|
<title>{pageTitle}</title>
|
||||||
|
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="description" content="Astro description">
|
<meta name="description" content="Astro description">
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
|
|
@ -3,13 +3,15 @@
|
||||||
import MainGridLayout from "../layouts/MainGridLayout.astro";
|
import MainGridLayout from "../layouts/MainGridLayout.astro";
|
||||||
|
|
||||||
import { getEntry } from 'astro:content'
|
import { getEntry } from 'astro:content'
|
||||||
|
import {i18n} from "../i18n/translation";
|
||||||
|
import I18nKey from "../i18n/i18nKey";
|
||||||
|
|
||||||
const aboutPost = await getEntry('spec', 'about')
|
const aboutPost = await getEntry('spec', 'about')
|
||||||
|
|
||||||
const { Content } = await aboutPost.render()
|
const { Content } = await aboutPost.render()
|
||||||
|
|
||||||
---
|
---
|
||||||
<MainGridLayout>
|
<MainGridLayout title={i18n(I18nKey.about)}>
|
||||||
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative min-h-[120px]">
|
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative min-h-[120px]">
|
||||||
<div class="card-base z-10 px-9 py-6 relative w-full ">
|
<div class="card-base z-10 px-9 py-6 relative w-full ">
|
||||||
<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">
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import {getSortedPosts} from "../../../utils/content-utils";
|
import {getSortedPosts} from "../../../utils/content-utils";
|
||||||
import MainGridLayout from "../../../layouts/MainGridLayout.astro";
|
import MainGridLayout from "../../../layouts/MainGridLayout.astro";
|
||||||
import ArchivePanel from "../../../components/ArchivePanel.astro";
|
import ArchivePanel from "../../../components/ArchivePanel.astro";
|
||||||
|
import {i18n} from "../../../i18n/translation";
|
||||||
|
import I18nKey from "../../../i18n/i18nKey";
|
||||||
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
|
@ -30,6 +32,6 @@ const { category } = Astro.params;
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainGridLayout>
|
<MainGridLayout title={i18n(I18nKey.archive)}>
|
||||||
<ArchivePanel categories={[category]}></ArchivePanel>
|
<ArchivePanel categories={[category]}></ArchivePanel>
|
||||||
</MainGridLayout>
|
</MainGridLayout>
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
import { getCollection, getEntry } from "astro:content";
|
import { getCollection, getEntry } from "astro:content";
|
||||||
import MainGridLayout from "../../layouts/MainGridLayout.astro";
|
import MainGridLayout from "../../layouts/MainGridLayout.astro";
|
||||||
import ArchivePanel from "../../components/ArchivePanel.astro";
|
import ArchivePanel from "../../components/ArchivePanel.astro";
|
||||||
|
import {i18n} from "../../i18n/translation";
|
||||||
|
import I18nKey from "../../i18n/i18nKey";
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainGridLayout>
|
<MainGridLayout title={i18n(I18nKey.archive)}>
|
||||||
<ArchivePanel></ArchivePanel>
|
<ArchivePanel></ArchivePanel>
|
||||||
</MainGridLayout>
|
</MainGridLayout>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
import {getSortedPosts} from "../../../utils/content-utils";
|
import {getSortedPosts} from "../../../utils/content-utils";
|
||||||
import MainGridLayout from "../../../layouts/MainGridLayout.astro";
|
import MainGridLayout from "../../../layouts/MainGridLayout.astro";
|
||||||
import ArchivePanel from "../../../components/ArchivePanel.astro";
|
import ArchivePanel from "../../../components/ArchivePanel.astro";
|
||||||
|
import {i18n} from "../../../i18n/translation";
|
||||||
|
import I18nKey from "../../../i18n/i18nKey";
|
||||||
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
|
@ -29,6 +30,6 @@ const { tag } = Astro.params;
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<MainGridLayout>
|
<MainGridLayout title={i18n(I18nKey.archive)}>
|
||||||
<ArchivePanel tags={[tag]}></ArchivePanel>
|
<ArchivePanel tags={[tag]}></ArchivePanel>
|
||||||
</MainGridLayout>
|
</MainGridLayout>
|
||||||
|
|
|
@ -9,6 +9,8 @@ import PostMetadata from "../../components/PostMetadata.astro";
|
||||||
import {getPostUrlBySlug} from "../../utils/content-utils";
|
import {getPostUrlBySlug} from "../../utils/content-utils";
|
||||||
import Button from "../../components/control/Button.astro";
|
import Button from "../../components/control/Button.astro";
|
||||||
import {getConfig} from "../../utils/config-utils";
|
import {getConfig} from "../../utils/config-utils";
|
||||||
|
import {i18n} from "../../i18n/translation";
|
||||||
|
import I18nKey from "../../i18n/i18nKey";
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const blogEntries = await getCollection('posts');
|
const blogEntries = await getCollection('posts');
|
||||||
|
@ -25,7 +27,7 @@ const { remarkPluginFrontmatter } = await entry.render();
|
||||||
const enableBanner = getConfig().banner.enable;
|
const enableBanner = getConfig().banner.enable;
|
||||||
|
|
||||||
---
|
---
|
||||||
<MainGridLayout banner={entry.data.cover}>
|
<MainGridLayout banner={entry.data.cover} title={entry.data.title}>
|
||||||
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative mb-4">
|
<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 ",
|
||||||
{}
|
{}
|
||||||
|
@ -36,13 +38,13 @@ const enableBanner = getConfig().banner.enable;
|
||||||
<div class="transition h-6 w-6 rounded-md bg-black/5 dark:bg-white/10 text-black/50 dark:text-white/50 flex items-center justify-center mr-2">
|
<div class="transition h-6 w-6 rounded-md bg-black/5 dark:bg-white/10 text-black/50 dark:text-white/50 flex items-center justify-center mr-2">
|
||||||
<Icon name="material-symbols:notes-rounded"></Icon>
|
<Icon name="material-symbols:notes-rounded"></Icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm">{remarkPluginFrontmatter.words} words</div>
|
<div class="text-sm">{remarkPluginFrontmatter.words} {" " + i18n(I18nKey.wordsCount)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row items-center">
|
<div class="flex flex-row items-center">
|
||||||
<div class="transition h-6 w-6 rounded-md bg-black/5 dark:bg-white/10 text-black/50 dark:text-white/50 flex items-center justify-center mr-2">
|
<div class="transition h-6 w-6 rounded-md bg-black/5 dark:bg-white/10 text-black/50 dark:text-white/50 flex items-center justify-center mr-2">
|
||||||
<Icon name="material-symbols:schedule-outline-rounded"></Icon>
|
<Icon name="material-symbols:schedule-outline-rounded"></Icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm">{remarkPluginFrontmatter.minutes} minutes</div>
|
<div class="text-sm">{remarkPluginFrontmatter.minutes} {" " + i18n(I18nKey.minutesCount)}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
// @ts-ignore
|
||||||
import _config from '../../vivia.config.yml';
|
import _config from '../../vivia.config.yml';
|
||||||
|
|
||||||
interface ViviaConfig {
|
interface ViviaConfig {
|
||||||
|
title: string;
|
||||||
menu: {
|
menu: {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
};
|
};
|
||||||
|
lang: string;
|
||||||
appearance: {
|
appearance: {
|
||||||
hue: number;
|
hue: number;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
|
title: Fuwari
|
||||||
|
menu:
|
||||||
|
home: /
|
||||||
|
archive: /archive
|
||||||
|
about: /about
|
||||||
|
|
||||||
appearance:
|
appearance:
|
||||||
hue: 250
|
hue: 250
|
||||||
|
|
||||||
|
lang: en
|
||||||
|
|
||||||
banner:
|
banner:
|
||||||
enable: true
|
enable: true
|
||||||
url: https://saicaca.github.io/vivia-preview/assets/banner.jpg
|
url: https://saicaca.github.io/vivia-preview/assets/banner.jpg
|
||||||
|
|
Loading…
Reference in New Issue