mirror of
https://github.com/10h30/astroplate.git
synced 2026-07-16 13:13:26 +09:00
remove multilingual and create a new multilingual branch
This commit is contained in:
+11
-15
@@ -9,7 +9,6 @@ import "@/styles/main.scss";
|
||||
import { AstroFont } from "astro-font";
|
||||
import { ViewTransitions } from "astro:transitions";
|
||||
import SearchModal from "./helpers/SearchModal";
|
||||
import { getLangFromUrl } from "@/lib/utils/languageParser";
|
||||
|
||||
// font families
|
||||
const pf = theme.fonts.font_family.primary;
|
||||
@@ -19,12 +18,12 @@ let fontPrimary, fontSecondary;
|
||||
if (theme.fonts.font_family.primary) {
|
||||
fontPrimary = theme.fonts.font_family.primary
|
||||
.replace(/\+/g, " ")
|
||||
.replace(/:[ital,]*[ital@]*[wght@]*[0-9,;]+/gi, "");
|
||||
.replace(/:[ital,]*[ital@]*[wght@]*[0-9,;.]+/gi, "");
|
||||
}
|
||||
if (theme.fonts.font_family.secondary) {
|
||||
fontSecondary = theme.fonts.font_family.secondary
|
||||
.replace(/\+/g, " ")
|
||||
.replace(/:[ital,]*[ital@]*[wght@]*[0-9,;]+/gi, "");
|
||||
.replace(/:[ital,]*[ital@]*[wght@]*[0-9,;.]+/gi, "");
|
||||
}
|
||||
|
||||
// types for frontmatters
|
||||
@@ -35,18 +34,15 @@ export interface Props {
|
||||
image?: string;
|
||||
noindex?: boolean;
|
||||
canonical?: string;
|
||||
lang?: string;
|
||||
}
|
||||
|
||||
// distructure frontmatters
|
||||
const { title, meta_title, description, image, noindex, canonical, lang } =
|
||||
// destructure frontmatter
|
||||
const { title, meta_title, description, image, noindex, canonical } =
|
||||
Astro.props;
|
||||
|
||||
const language = lang || getLangFromUrl(Astro.url);
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang={language}>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- favicon -->
|
||||
<link rel="shortcut icon" href={config.site.favicon} />
|
||||
@@ -111,7 +107,7 @@ const language = lang || getLangFromUrl(Astro.url);
|
||||
<meta
|
||||
name="description"
|
||||
content={plainify(
|
||||
description ? description : config.metadata.meta_description,
|
||||
description ? description : config.metadata.meta_description
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -124,7 +120,7 @@ const language = lang || getLangFromUrl(Astro.url);
|
||||
<meta
|
||||
property="og:title"
|
||||
content={plainify(
|
||||
meta_title ? meta_title : title ? title : config.site.title,
|
||||
meta_title ? meta_title : title ? title : config.site.title
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -132,7 +128,7 @@ const language = lang || getLangFromUrl(Astro.url);
|
||||
<meta
|
||||
property="og:description"
|
||||
content={plainify(
|
||||
description ? description : config.metadata.meta_description,
|
||||
description ? description : config.metadata.meta_description
|
||||
)}
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
@@ -145,7 +141,7 @@ const language = lang || getLangFromUrl(Astro.url);
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content={plainify(
|
||||
meta_title ? meta_title : title ? title : config.site.title,
|
||||
meta_title ? meta_title : title ? title : config.site.title
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -153,7 +149,7 @@ const language = lang || getLangFromUrl(Astro.url);
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content={plainify(
|
||||
description ? description : config.metadata.meta_description,
|
||||
description ? description : config.metadata.meta_description
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -177,7 +173,7 @@ const language = lang || getLangFromUrl(Astro.url);
|
||||
<body>
|
||||
<TwSizeIndicator />
|
||||
<Header />
|
||||
<SearchModal lang={language} client:load />
|
||||
<SearchModal client:load />
|
||||
<main id="main-content">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
@@ -1,30 +1,18 @@
|
||||
---
|
||||
import BlogCard from "@/components/BlogCard.astro";
|
||||
import Share from "@/components/Share.astro";
|
||||
import config from "@/config/config.json";
|
||||
import Disqus from "@/helpers/Disqus";
|
||||
import { getSinglePage } from "@/lib/contentParser.astro";
|
||||
import dateFormat from "@/lib/utils/dateFormat";
|
||||
import { slugSelector } from "@/lib/utils/languageParser";
|
||||
import similarItems from "@/lib/utils/similarItems";
|
||||
import { humanize, markdownify, slugify } from "@/lib/utils/textConverter";
|
||||
import type { ContentEntryMap } from "astro:content";
|
||||
import { FaRegClock, FaRegFolder, FaRegUserCircle } from "react-icons/fa";
|
||||
import ImageMod from "./components/ImageMod.astro";
|
||||
const { default_language } = config.settings;
|
||||
|
||||
const COLLECTION_FOLDER = "blog";
|
||||
const { post } = Astro.props;
|
||||
let { lang } = Astro.params;
|
||||
|
||||
if (!lang) {
|
||||
lang = default_language;
|
||||
}
|
||||
|
||||
const posts = await getSinglePage(
|
||||
COLLECTION_FOLDER,
|
||||
lang as keyof ContentEntryMap
|
||||
);
|
||||
const posts = await getSinglePage(COLLECTION_FOLDER);
|
||||
const similarPosts = similarItems(post, posts);
|
||||
const { Content } = await post.render();
|
||||
const { title, description, author, categories, image, date, tags } = post.data;
|
||||
@@ -51,7 +39,7 @@ const { title, description, author, categories, image, date, tags } = post.data;
|
||||
<h1 set:html={markdownify(title)} class="h2 mb-4" />
|
||||
<ul class="mb-4">
|
||||
<li class="mr-4 inline-block">
|
||||
<a href={slugSelector(`/authors/${slugify(author)}`, lang)}>
|
||||
<a href={`/authors/${slugify(author)}`}>
|
||||
<FaRegUserCircle className={"mr-2 -mt-1 inline-block"} />
|
||||
{humanize(author)}
|
||||
</a>
|
||||
@@ -60,9 +48,7 @@ const { title, description, author, categories, image, date, tags } = post.data;
|
||||
<FaRegFolder className={"mr-2 -mt-1 inline-block"} />
|
||||
{
|
||||
categories.map((category: string, index: number) => (
|
||||
<a
|
||||
href={slugSelector(`/categories/${slugify(category)}`, lang)}
|
||||
>
|
||||
<a href={`/categories/${slugify(category)}`}>
|
||||
{humanize(category)}
|
||||
{index !== categories.length - 1 && ","}
|
||||
</a>
|
||||
@@ -86,7 +72,7 @@ const { title, description, author, categories, image, date, tags } = post.data;
|
||||
<li class="inline-block">
|
||||
<a
|
||||
class="m-1 block rounded bg-theme-light px-3 py-1 hover:bg-primary hover:text-white dark:bg-darkmode-theme-light dark:hover:bg-darkmode-primary dark:hover:text-dark"
|
||||
href={slugSelector(`/tags/${slugify(tag)}`, lang)}
|
||||
href={`/tags/${slugify(tag)}`}
|
||||
>
|
||||
{humanize(tag)}
|
||||
</a>
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
---
|
||||
import { getLangFromUrl, slugSelector } from "@/lib/utils/languageParser";
|
||||
import { plainify } from "@/lib/utils/textConverter";
|
||||
import ImageMod from "./ImageMod.astro";
|
||||
import Social from "./Social.astro";
|
||||
|
||||
const { data } = Astro.props;
|
||||
const { title, image, social } = data.data;
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
---
|
||||
|
||||
<div
|
||||
@@ -25,7 +23,7 @@ const lang = getLangFromUrl(Astro.url);
|
||||
)
|
||||
}
|
||||
<h4 class="mb-3">
|
||||
<a href={slugSelector(`/${data.slug}`, lang)}>{title}</a>
|
||||
<a href={`/authors/${data.slug}`}>{title}</a>
|
||||
</h4>
|
||||
<p class="mb-4">
|
||||
{plainify(data.body?.slice(0, 100))}
|
||||
|
||||
@@ -1,28 +1,16 @@
|
||||
---
|
||||
import config from "@/config/config.json";
|
||||
import dateFormat from "@/lib/utils/dateFormat";
|
||||
import {
|
||||
getLangFromUrl,
|
||||
getTranslations,
|
||||
slugSelector,
|
||||
} from "@/lib/utils/languageParser";
|
||||
import { humanize, plainify, slugify } from "@/lib/utils/textConverter";
|
||||
import type { ContentEntryMap } from "astro:content";
|
||||
import { FaRegFolder, FaRegUserCircle } from "react-icons/fa";
|
||||
import ImageMod from "./ImageMod.astro";
|
||||
|
||||
const { summary_length }: { summary_length: number; blog_folder: string } =
|
||||
config.settings;
|
||||
const {
|
||||
summary_length,
|
||||
blog_folder,
|
||||
}: { summary_length: number; blog_folder: string } = config.settings;
|
||||
const { data } = Astro.props;
|
||||
const { title, image, date, author, categories } = data.data;
|
||||
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const { read_more } = await getTranslations(lang as keyof ContentEntryMap);
|
||||
|
||||
const slugParts = data.slug.split("/");
|
||||
slugParts[0] = "blog";
|
||||
const modifiedSlug = slugParts.join("/");
|
||||
data.slug = modifiedSlug;
|
||||
---
|
||||
|
||||
<div class="bg-body dark:bg-darkmode-body">
|
||||
@@ -39,23 +27,22 @@ data.slug = modifiedSlug;
|
||||
)
|
||||
}
|
||||
<h4 class="mb-3">
|
||||
<a href={slugSelector(`/${data.slug}`, lang)}>
|
||||
<a href={`/${blog_folder}/${data.slug}`}>
|
||||
{title}
|
||||
</a>
|
||||
</h4>
|
||||
<ul class="mb-4">
|
||||
<li class="mr-4 inline-block">
|
||||
<a href={slugSelector(`/authors/${slugify(author)}`, lang)}>
|
||||
<a href={`/authors/${slugify(author)}`}>
|
||||
<FaRegUserCircle className={"mr-2 -mt-1 inline-block"} />
|
||||
{humanize(author)}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="mr-4 inline-block">
|
||||
<FaRegFolder className={"mr-2 -mt-1 inline-block"} />
|
||||
{
|
||||
categories.map((category: string, index: number) => (
|
||||
<a href={slugSelector(`/categories/${slugify(category)}`, lang)}>
|
||||
<a href={`/categories/${slugify(category)}`}>
|
||||
{humanize(category)}
|
||||
{index !== categories.length - 1 && ","}
|
||||
</a>
|
||||
@@ -67,8 +54,8 @@ data.slug = modifiedSlug;
|
||||
<p class="mb-6">{plainify(data.body?.slice(0, Number(summary_length)))}</p>
|
||||
<a
|
||||
class="btn btn-outline-primary btn-sm"
|
||||
href={slugSelector(`/${data.slug}`, lang)}
|
||||
href={`/${blog_folder}/${data.slug}`}
|
||||
>
|
||||
{read_more}
|
||||
read more
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
---
|
||||
import { supportedLang } from "@/lib/utils/languageParser";
|
||||
import { humanize } from "@/lib/utils/textConverter";
|
||||
|
||||
const { className }: { className?: string } = Astro.props;
|
||||
|
||||
const paths = Astro.url.pathname.split("/").filter((x) => x);
|
||||
|
||||
let lang = "";
|
||||
if (supportedLang.includes(paths[0])) {
|
||||
lang = paths.shift()!;
|
||||
}
|
||||
|
||||
let baseHref = lang ? `/${lang}` : "/";
|
||||
let parts = [
|
||||
{
|
||||
label: "Home",
|
||||
href: baseHref,
|
||||
"aria-label":
|
||||
Astro.url.pathname === baseHref || Astro.url.pathname === `${baseHref}/`
|
||||
? "page"
|
||||
: undefined,
|
||||
href: "/",
|
||||
"aria-label": Astro.url.pathname === "/" ? "page" : undefined,
|
||||
},
|
||||
];
|
||||
|
||||
paths.forEach((label: string, i: number) => {
|
||||
const href = `${baseHref}${paths.slice(0, i + 1).join("/")}`;
|
||||
const href = `/${paths.slice(0, i + 1).join("/")}`;
|
||||
label !== "page" &&
|
||||
parts.push({
|
||||
label: humanize(label.replace(".html", "").replace(/[-_]/g, " ")) || "",
|
||||
@@ -39,7 +28,7 @@ paths.forEach((label: string, i: number) => {
|
||||
{
|
||||
parts.map(({ label, ...attrs }, index) => (
|
||||
<li class="mx-1 capitalize" role="listitem">
|
||||
{index > 0 && <span class="inline-block mr-1">/</span>}
|
||||
{index > 0 && <span class="inlin-block mr-1">/</span>}
|
||||
{index !== parts.length - 1 ? (
|
||||
<a class="text-primary dark:text-darkmode-primary" {...attrs}>
|
||||
{label}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
import config from "@/config/config.json";
|
||||
import ImageMod from "./ImageMod.astro";
|
||||
import { getLangFromUrl, slugSelector } from "@/lib/utils/languageParser";
|
||||
|
||||
const { src, srcDarkmode }: { src?: string; srcDarkmode?: string } =
|
||||
Astro.props;
|
||||
@@ -22,17 +21,9 @@ const {
|
||||
} = config.site;
|
||||
|
||||
const { theme_switcher }: { theme_switcher: boolean } = config.settings;
|
||||
const { default_language } = config.settings;
|
||||
|
||||
let lang = getLangFromUrl(Astro.url);
|
||||
|
||||
const disabledLanguages = config.settings.disable_languages as string[];
|
||||
if (disabledLanguages.includes(lang)) {
|
||||
lang = default_language;
|
||||
}
|
||||
---
|
||||
|
||||
<a href={slugSelector("/", lang)} class="navbar-brand inline-block">
|
||||
<a href="/" class="navbar-brand inline-block">
|
||||
{
|
||||
src || srcDarkmode || logo || logo_darkmode ? (
|
||||
<>
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
---
|
||||
import { getLangFromUrl, slugSelector } from "@/lib/utils/languageParser";
|
||||
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
|
||||
type Pagination = {
|
||||
section?: string;
|
||||
currentPage?: number;
|
||||
@@ -31,11 +27,8 @@ for (let i = 1; i <= totalPages; i++) {
|
||||
<a
|
||||
href={
|
||||
indexPageLink
|
||||
? slugSelector(`/${section ? section : ""}`, lang)
|
||||
: slugSelector(
|
||||
`/${section ? section : ""}/page/${currentPage - 1}`,
|
||||
lang
|
||||
)
|
||||
? `${section ? "/" + section : "/"}`
|
||||
: `${section ? "/" + section : ""}/page/${currentPage - 1}`
|
||||
}
|
||||
class="rounded px-2 py-1.5 text-dark hover:bg-theme-light dark:text-darkmode-dark dark:hover:bg-darkmode-theme-light"
|
||||
>
|
||||
@@ -84,12 +77,11 @@ for (let i = 1; i <= totalPages; i++) {
|
||||
</span>
|
||||
) : (
|
||||
<a
|
||||
href={slugSelector(
|
||||
href={
|
||||
i === 0
|
||||
? `/${section ? section : ""}`
|
||||
: `/${section ? section : ""}/page/${pagination}`,
|
||||
lang
|
||||
)}
|
||||
? `${section ? "/" + section : "/"}`
|
||||
: `${section ? "/" + section : ""}/page/${pagination}`
|
||||
}
|
||||
aria-current="page"
|
||||
class="rounded px-4 py-2 text-dark hover:bg-theme-light dark:text-darkmode-dark dark:hover:bg-darkmode-theme-light"
|
||||
>
|
||||
@@ -101,10 +93,7 @@ for (let i = 1; i <= totalPages; i++) {
|
||||
{/* next page */}
|
||||
{hasNextPage ? (
|
||||
<a
|
||||
href={slugSelector(
|
||||
`/${section ? section : ""}/page/${currentPage + 1}`,
|
||||
lang
|
||||
)}
|
||||
href={`${section ? "/" + section : ""}/page/${currentPage + 1}`}
|
||||
class="rounded px-2 py-1.5 text-dark hover:bg-theme-light dark:text-darkmode-dark dark:hover:bg-darkmode-theme-light"
|
||||
>
|
||||
<span class="sr-only">Next</span>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
import config from "@/config/config.json";
|
||||
|
||||
const { theme_switcher }: { theme_switcher: boolean; default_theme: string } =
|
||||
config.settings;
|
||||
const {
|
||||
theme_switcher,
|
||||
default_theme,
|
||||
}: { theme_switcher: boolean; default_theme: string } = config.settings;
|
||||
const { className }: { className?: string } = Astro.props;
|
||||
---
|
||||
|
||||
@@ -47,7 +49,7 @@ const { className }: { className?: string } = Astro.props;
|
||||
const matchMedia = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
||||
matchMedia.addEventListener("change", () =>
|
||||
toggleTheme(document.querySelectorAll("[data-theme-switcher]")),
|
||||
toggleTheme(document.querySelectorAll("[data-theme-switcher]"))
|
||||
);
|
||||
|
||||
function toggleTheme(themeSwitch: NodeListOf<Element>) {
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import config from "@/config/config.json";
|
||||
import languages from "@/config/language.json";
|
||||
import React from "react";
|
||||
|
||||
const LanguageSwitcher = ({
|
||||
lang,
|
||||
pathname,
|
||||
}: {
|
||||
lang: string;
|
||||
pathname: string;
|
||||
}) => {
|
||||
const { default_language, default_language_in_subdir } = config.settings;
|
||||
|
||||
// Function to remove trailing slash if necessary
|
||||
const removeTrailingSlash = (path: string) => {
|
||||
if (!config.site.trailing_slash) {
|
||||
return path.replace(/\/$/, "");
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
// Sort languages by weight and filter out disabled languages
|
||||
const sortedLanguages = languages
|
||||
// @ts-ignore
|
||||
.filter(language => !config.settings.disable_languages.includes(language.languageCode))
|
||||
.sort((a, b) => a.weight - b.weight);
|
||||
|
||||
return (
|
||||
<div className={`mr-5 ${sortedLanguages.length > 1 ? "block" : "hidden"}`}>
|
||||
<select
|
||||
className="border border-dark text-dark bg-transparent dark:border-darkmode-primary dark:text-white py-1 rounded-sm cursor-pointer focus:ring-0 focus:border-dark dark:focus:border-darkmode-primary"
|
||||
onChange={(e) => {
|
||||
const selectedLang = e.target.value;
|
||||
let newPath;
|
||||
const baseUrl = window.location.origin;
|
||||
|
||||
if (selectedLang === default_language) {
|
||||
if (default_language_in_subdir) {
|
||||
newPath = `${baseUrl}/${default_language}${removeTrailingSlash(pathname.replace(`/${lang}`, ""))}`;
|
||||
} else {
|
||||
newPath = `${baseUrl}${removeTrailingSlash(pathname.replace(`/${lang}`, ""))}`;
|
||||
}
|
||||
} else {
|
||||
newPath = `/${selectedLang}${removeTrailingSlash(pathname.replace(`/${lang}`, ""))}`;
|
||||
}
|
||||
|
||||
window.location.href = newPath;
|
||||
}}
|
||||
value={lang}
|
||||
>
|
||||
{sortedLanguages.map((language) => (
|
||||
<option
|
||||
className="dark:text-dark"
|
||||
key={language.languageCode}
|
||||
value={language.languageCode}
|
||||
>
|
||||
{language.languageName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LanguageSwitcher;
|
||||
@@ -1,11 +1,8 @@
|
||||
import searchData from ".json/search.json";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import SearchResult, { type ISearchItem } from "./SearchResult";
|
||||
import config from "@/config/config.json";
|
||||
const { default_language } = config.settings;
|
||||
|
||||
const SearchModal = ({ lang }: { lang: string | undefined }) => {
|
||||
lang = lang || default_language;
|
||||
const SearchModal = () => {
|
||||
const [searchString, setSearchString] = useState("");
|
||||
|
||||
// handle input change
|
||||
@@ -42,13 +39,9 @@ const SearchModal = ({ lang }: { lang: string | undefined }) => {
|
||||
}
|
||||
};
|
||||
|
||||
// filter language specific search data
|
||||
const filterSearchData = searchData.filter((item) => item.lang === lang);
|
||||
|
||||
|
||||
// get search result
|
||||
const startTime = performance.now();
|
||||
const searchResult = doSearch(filterSearchData);
|
||||
const searchResult = doSearch(searchData);
|
||||
const endTime = performance.now();
|
||||
const totalTime = ((endTime - startTime) / 1000).toFixed(3);
|
||||
|
||||
@@ -176,15 +169,10 @@ const SearchModal = ({ lang }: { lang: string | undefined }) => {
|
||||
name="search"
|
||||
value={searchString}
|
||||
onChange={handleSearch}
|
||||
autoFocus
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
<SearchResult
|
||||
searchResult={searchResult}
|
||||
searchString={searchString}
|
||||
lang={lang}
|
||||
/>
|
||||
<SearchResult searchResult={searchResult} searchString={searchString} />
|
||||
<div className="search-wrapper-footer">
|
||||
<span className="flex items-center">
|
||||
<kbd>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { slugSelector } from "@/lib/utils/languageParser";
|
||||
import { plainify, titleify } from "@/lib/utils/textConverter";
|
||||
import React from "react";
|
||||
|
||||
export interface ISearchItem {
|
||||
lang: string;
|
||||
group: string;
|
||||
slug: string;
|
||||
frontmatter: {
|
||||
@@ -35,13 +33,10 @@ export interface ISearchGroup {
|
||||
const SearchResult = ({
|
||||
searchResult,
|
||||
searchString,
|
||||
lang
|
||||
}: {
|
||||
searchResult: ISearchItem[];
|
||||
searchString: string;
|
||||
lang: string;
|
||||
}) => {
|
||||
|
||||
// generate search result group
|
||||
const generateSearchGroup = (searchResult: ISearchItem[]) => {
|
||||
const joinDataByGroup: ISearchGroup[] = searchResult.reduce(
|
||||
@@ -88,7 +83,6 @@ const SearchResult = ({
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// match underline
|
||||
const matchUnderline = (text: string, substring: string) => {
|
||||
const parts = text?.split(new RegExp(`(${substring})`, "gi"));
|
||||
@@ -154,14 +148,12 @@ const SearchResult = ({
|
||||
<img
|
||||
src={item.frontmatter.image}
|
||||
alt={item.frontmatter.title}
|
||||
width={100}
|
||||
height={100}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="search-result-item-body">
|
||||
<a
|
||||
href={`${slugSelector(item.slug, lang)}`}
|
||||
href={`/${item.slug}`}
|
||||
className="search-result-item-title search-result-item-link"
|
||||
>
|
||||
{matchUnderline(item.frontmatter.title, searchString)}
|
||||
@@ -196,8 +188,8 @@ const SearchResult = ({
|
||||
{matchUnderline(category, searchString)}
|
||||
{item.frontmatter.categories &&
|
||||
index !==
|
||||
item.frontmatter.categories.length -
|
||||
1 && <>, </>}
|
||||
item.frontmatter.categories.length -
|
||||
1 && <>, </>}
|
||||
</span>
|
||||
),
|
||||
)}
|
||||
@@ -219,7 +211,7 @@ const SearchResult = ({
|
||||
{matchUnderline(tag, searchString)}
|
||||
{item.frontmatter.tags &&
|
||||
index !==
|
||||
item.frontmatter.tags.length - 1 && <>, </>}
|
||||
item.frontmatter.tags.length - 1 && <>, </>}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -2,21 +2,11 @@
|
||||
import Logo from "@/components/Logo.astro";
|
||||
import Social from "@/components/Social.astro";
|
||||
import config from "@/config/config.json";
|
||||
import menu from "@/config/menu.json";
|
||||
import social from "@/config/social.json";
|
||||
import {
|
||||
getLangFromUrl,
|
||||
getTranslations,
|
||||
slugSelector,
|
||||
} from "@/lib/utils/languageParser";
|
||||
import { markdownify } from "@/lib/utils/textConverter";
|
||||
import type { ContentEntryMap } from "astro:content";
|
||||
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const menu = await getTranslations(lang as keyof ContentEntryMap);
|
||||
let footer: any = [];
|
||||
if (menu) {
|
||||
footer = menu.footer;
|
||||
}
|
||||
const { footer }: { footer: { name: string; url: string }[] } = menu;
|
||||
---
|
||||
|
||||
<footer class="bg-theme-light dark:bg-darkmode-theme-light">
|
||||
@@ -28,9 +18,9 @@ if (menu) {
|
||||
<div class="mb-8 text-center lg:col-6 lg:mb-0">
|
||||
<ul>
|
||||
{
|
||||
footer.map((menu: any) => (
|
||||
footer.map((menu) => (
|
||||
<li class="m-3 inline-block">
|
||||
<a href={slugSelector(menu.url, lang)}>{menu.name}</a>
|
||||
<a href={menu.url}>{menu.name}</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -2,36 +2,33 @@
|
||||
import Logo from "@/components/Logo.astro";
|
||||
import ThemeSwitcher from "@/components/ThemeSwitcher.astro";
|
||||
import config from "@/config/config.json";
|
||||
import LanguageSwitcher from "@/helpers/LanguageSwitcher";
|
||||
import {
|
||||
getLangFromUrl,
|
||||
getTranslations,
|
||||
slugSelector,
|
||||
} from "@/lib/utils/languageParser";
|
||||
import type { ContentEntryMap } from "astro:content";
|
||||
import menu from "@/config/menu.json";
|
||||
import { IoSearch } from "react-icons/io5";
|
||||
|
||||
let lang = getLangFromUrl(Astro.url);
|
||||
const menu = await getTranslations(lang as keyof ContentEntryMap);
|
||||
|
||||
const { navigation_button, settings } = config;
|
||||
const { default_language } = config.settings;
|
||||
const { pathname } = Astro.url;
|
||||
const { get_started } = await getTranslations(lang as keyof ContentEntryMap);
|
||||
|
||||
const disabledLanguages = config.settings.disable_languages as string[];
|
||||
if (disabledLanguages.includes(lang)) {
|
||||
lang = default_language;
|
||||
export interface ChildNavigationLink {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface NavigationLink {
|
||||
name: string;
|
||||
url: string;
|
||||
hasChildren?: boolean;
|
||||
children?: ChildNavigationLink[];
|
||||
}
|
||||
|
||||
const { main }: { main: NavigationLink[] } = menu;
|
||||
const { navigation_button, settings } = config;
|
||||
const { pathname } = Astro.url;
|
||||
---
|
||||
|
||||
<header class={`header z-30 ${settings.sticky_header && "sticky top-0"}`}>
|
||||
<nav class="navbar container">
|
||||
{/* logo */}
|
||||
<!-- logo -->
|
||||
<div class="order-0">
|
||||
<Logo />
|
||||
</div>
|
||||
{/* navbar toggler */}
|
||||
<!-- navbar toggler -->
|
||||
<input id="nav-toggle" type="checkbox" class="hidden" />
|
||||
<label
|
||||
for="nav-toggle"
|
||||
@@ -48,23 +45,21 @@ if (disabledLanguages.includes(lang)) {
|
||||
transform="rotate(45 10 10)"></polygon>
|
||||
</svg>
|
||||
</label>
|
||||
{/* /navbar toggler */}
|
||||
|
||||
<!-- /navbar toggler -->
|
||||
<ul
|
||||
id="nav-menu"
|
||||
class="navbar-nav order-3 hidden w-full pb-6 lg:order-1 lg:flex lg:w-auto lg:space-x-2 lg:pb-0 xl:space-x-8"
|
||||
>
|
||||
{
|
||||
menu?.main.map((menu: any) => (
|
||||
main.map((menu) => (
|
||||
<>
|
||||
{menu.hasChildren ? (
|
||||
<li class="nav-item nav-dropdown group relative">
|
||||
<span
|
||||
class={`nav-link inline-flex items-center ${
|
||||
menu.children?.map(({ url }) => url).includes(pathname) ||
|
||||
menu.children
|
||||
?.map(({ url }: { url: string }) =>
|
||||
slugSelector(url, lang),
|
||||
)
|
||||
?.map(({ url }) => `${url}/`)
|
||||
.includes(pathname)
|
||||
? "active"
|
||||
: ""
|
||||
@@ -76,13 +71,15 @@ if (disabledLanguages.includes(lang)) {
|
||||
</svg>
|
||||
</span>
|
||||
<ul class="nav-dropdown-list hidden group-hover:block lg:invisible lg:absolute lg:block lg:opacity-0 lg:group-hover:visible lg:group-hover:opacity-100">
|
||||
{menu.children?.map((child: any) => (
|
||||
{menu.children?.map((child) => (
|
||||
<li class="nav-dropdown-item">
|
||||
<a
|
||||
href={slugSelector(child.url, lang)}
|
||||
href={child.url}
|
||||
aria-label={child.name}
|
||||
class={`nav-dropdown-link block ${
|
||||
pathname === slugSelector(child.url, lang) && "active"
|
||||
(pathname === `${child.url}/` ||
|
||||
pathname === child.url) &&
|
||||
"active"
|
||||
}`}
|
||||
>
|
||||
{child.name}
|
||||
@@ -94,9 +91,10 @@ if (disabledLanguages.includes(lang)) {
|
||||
) : (
|
||||
<li class="nav-item">
|
||||
<a
|
||||
href={slugSelector(menu.url, lang)}
|
||||
href={menu.url}
|
||||
class={`nav-link block ${
|
||||
pathname === slugSelector(menu.url, lang) && "active"
|
||||
(pathname === `${menu.url}/` || pathname === menu.url) &&
|
||||
"active"
|
||||
}`}
|
||||
>
|
||||
{menu.name}
|
||||
@@ -106,7 +104,6 @@ if (disabledLanguages.includes(lang)) {
|
||||
</>
|
||||
))
|
||||
}
|
||||
{/* Navigation button */}
|
||||
{
|
||||
navigation_button.enable && (
|
||||
<li class="mt-4 inline-block lg:hidden">
|
||||
@@ -114,15 +111,13 @@ if (disabledLanguages.includes(lang)) {
|
||||
class="btn btn-outline-primary btn-sm"
|
||||
href={navigation_button.link}
|
||||
>
|
||||
{get_started}
|
||||
{navigation_button.label}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
</ul>
|
||||
|
||||
<div class="order-1 ml-auto flex items-center md:order-2 lg:ml-0">
|
||||
{/* Search button */}
|
||||
{
|
||||
settings.search && (
|
||||
<button
|
||||
@@ -134,20 +129,14 @@ if (disabledLanguages.includes(lang)) {
|
||||
</button>
|
||||
)
|
||||
}
|
||||
{/* Theme switcher */}
|
||||
<ThemeSwitcher className="mr-5" />
|
||||
|
||||
{/* Language switcher */}
|
||||
<LanguageSwitcher client:load lang={lang} pathname={pathname} />
|
||||
|
||||
{/* Navigation button */}
|
||||
{
|
||||
navigation_button.enable && (
|
||||
<a
|
||||
class="btn btn-outline-primary btn-sm hidden lg:inline-block"
|
||||
href={navigation_button.link}
|
||||
>
|
||||
{get_started}
|
||||
{navigation_button.label}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
---
|
||||
import { getLangFromUrl, slugSelector } from "@/lib/utils/languageParser";
|
||||
import { humanize } from "@/lib/utils/textConverter";
|
||||
|
||||
const { tags, categories, allCategories } = Astro.props;
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
---
|
||||
|
||||
<div class="lg:col-4">
|
||||
@@ -21,7 +19,7 @@ const lang = getLangFromUrl(Astro.url);
|
||||
<li>
|
||||
<a
|
||||
class="flex justify-between hover:text-primary dark:hover:text-darkmode-primary"
|
||||
href={slugSelector(`/categories/${category}`, lang)}
|
||||
href={`/categories/${category}`}
|
||||
>
|
||||
{humanize(category)} <span>({count})</span>
|
||||
</a>
|
||||
@@ -43,7 +41,7 @@ const lang = getLangFromUrl(Astro.url);
|
||||
<li class="inline-block">
|
||||
<a
|
||||
class="m-1 block rounded bg-white px-3 py-1 hover:bg-primary hover:text-white dark:bg-darkmode-body dark:hover:bg-darkmode-primary dark:hover:text-dark"
|
||||
href={slugSelector(`/tags/${tag}`, lang)}
|
||||
href={`/tags/${tag}`}
|
||||
>
|
||||
{humanize(tag)}
|
||||
</a>
|
||||
|
||||
@@ -67,7 +67,7 @@ const { testimonial } = Astro.props;
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
<div class="testimonial-slider-pagination mt-9 flex items-center justify-center text-center" />
|
||||
|
||||
Reference in New Issue
Block a user