mirror of
https://github.com/10h30/astroplate.git
synced 2026-07-11 18:56:06 +09:00
jsonGenerator Fixed
This commit is contained in:
+17
-12
@@ -10,7 +10,6 @@ const BLOG_FOLDER = "blog";
|
|||||||
|
|
||||||
// get data from markdown
|
// get data from markdown
|
||||||
const getData = (folder, groupDepth, langIndex = 0) => {
|
const getData = (folder, groupDepth, langIndex = 0) => {
|
||||||
// get paths
|
|
||||||
const getPaths = languages
|
const getPaths = languages
|
||||||
.map((lang, index) => {
|
.map((lang, index) => {
|
||||||
const langFolder = lang.contentDir ? lang.contentDir : lang.languageCode;
|
const langFolder = lang.contentDir ? lang.contentDir : lang.languageCode;
|
||||||
@@ -22,7 +21,7 @@ const getData = (folder, groupDepth, langIndex = 0) => {
|
|||||||
!filename.startsWith("-") &&
|
!filename.startsWith("-") &&
|
||||||
(filename.endsWith(".md") || filename.endsWith(".mdx")),
|
(filename.endsWith(".md") || filename.endsWith(".mdx")),
|
||||||
)
|
)
|
||||||
.map((filename) => {
|
.flatMap((filename) => {
|
||||||
const filepath = path.join(dir, filename);
|
const filepath = path.join(dir, filename);
|
||||||
const stats = fs.statSync(filepath);
|
const stats = fs.statSync(filepath);
|
||||||
const isFolder = stats.isDirectory();
|
const isFolder = stats.isDirectory();
|
||||||
@@ -33,18 +32,26 @@ const getData = (folder, groupDepth, langIndex = 0) => {
|
|||||||
const file = fs.readFileSync(filepath, "utf-8");
|
const file = fs.readFileSync(filepath, "utf-8");
|
||||||
const { data, content } = matter(file);
|
const { data, content } = matter(file);
|
||||||
const pathParts = filepath.split(path.sep);
|
const pathParts = filepath.split(path.sep);
|
||||||
const slug =
|
|
||||||
data.slug ||
|
let slug;
|
||||||
pathParts
|
if (data.slug) {
|
||||||
|
const slugParts = data.slug.split("/");
|
||||||
|
slugParts[0] = BLOG_FOLDER;
|
||||||
|
slug = slugParts.join("/");
|
||||||
|
} else {
|
||||||
|
slug = pathParts
|
||||||
.slice(CONTENT_DEPTH)
|
.slice(CONTENT_DEPTH)
|
||||||
.join("/")
|
.join("/")
|
||||||
.replace(/\.[^/.]+$/, "");
|
.replace(/\.[^/.]+$/, "");
|
||||||
const group = pathParts[groupDepth];
|
slug = `${BLOG_FOLDER}/${slug.split("/").slice(1).join("/")}`;
|
||||||
|
}
|
||||||
|
data.slug = slug;
|
||||||
|
const group = "blog";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lang: languages[langIndex].languageCode,
|
lang: languages[index].languageCode, // Set the correct language code dynamically
|
||||||
group: group,
|
group: group,
|
||||||
slug: slug,
|
slug: data.slug,
|
||||||
frontmatter: data,
|
frontmatter: data,
|
||||||
content: content,
|
content: content,
|
||||||
};
|
};
|
||||||
@@ -53,9 +60,7 @@ const getData = (folder, groupDepth, langIndex = 0) => {
|
|||||||
})
|
})
|
||||||
.flat();
|
.flat();
|
||||||
|
|
||||||
const publishedPages = getPaths.filter(
|
const publishedPages = getPaths.filter((page) => !page.frontmatter?.draft);
|
||||||
(page) => !page.frontmatter?.draft && page,
|
|
||||||
);
|
|
||||||
return publishedPages;
|
return publishedPages;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -71,7 +76,7 @@ try {
|
|||||||
JSON.stringify(getData(BLOG_FOLDER, 3)),
|
JSON.stringify(getData(BLOG_FOLDER, 3)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// merger json files for search
|
// merge json files for search
|
||||||
const posts = require(`../${JSON_FOLDER}/posts.json`);
|
const posts = require(`../${JSON_FOLDER}/posts.json`);
|
||||||
const search = [...posts];
|
const search = [...posts];
|
||||||
fs.writeFileSync(`${JSON_FOLDER}/search.json`, JSON.stringify(search));
|
fs.writeFileSync(`${JSON_FOLDER}/search.json`, JSON.stringify(search));
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"title": "Astroplate",
|
"title": "Astroplate",
|
||||||
"base_url": "https://astroplate.netlify.app",
|
"base_url": "https://astroplate.netlify.app",
|
||||||
"base_path": "/",
|
"base_path": "/",
|
||||||
"trailing_slash": true,
|
"trailing_slash": false,
|
||||||
"favicon": "/images/favicon.png",
|
"favicon": "/images/favicon.png",
|
||||||
"logo": "/images/logo.png",
|
"logo": "/images/logo.png",
|
||||||
"logo_darkmode": "/images/logo-darkmode.png",
|
"logo_darkmode": "/images/logo-darkmode.png",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import "@/styles/main.scss";
|
|||||||
import { AstroFont } from "astro-font";
|
import { AstroFont } from "astro-font";
|
||||||
import { ViewTransitions } from "astro:transitions";
|
import { ViewTransitions } from "astro:transitions";
|
||||||
import SearchModal from "./helpers/SearchModal";
|
import SearchModal from "./helpers/SearchModal";
|
||||||
|
import { getLangFromUrl } from "@/lib/utils/languageParser";
|
||||||
|
|
||||||
// font families
|
// font families
|
||||||
const pf = theme.fonts.font_family.primary;
|
const pf = theme.fonts.font_family.primary;
|
||||||
@@ -40,6 +41,8 @@ export interface Props {
|
|||||||
// distructure frontmatters
|
// distructure frontmatters
|
||||||
const { title, meta_title, description, image, noindex, canonical, lang } =
|
const { title, meta_title, description, image, noindex, canonical, lang } =
|
||||||
Astro.props;
|
Astro.props;
|
||||||
|
|
||||||
|
const language = lang || getLangFromUrl(Astro.url);
|
||||||
---
|
---
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
@@ -108,7 +111,7 @@ const { title, meta_title, description, image, noindex, canonical, lang } =
|
|||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content={plainify(
|
content={plainify(
|
||||||
description ? description : config.metadata.meta_description,
|
description ? description : config.metadata.meta_description
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -121,7 +124,7 @@ const { title, meta_title, description, image, noindex, canonical, lang } =
|
|||||||
<meta
|
<meta
|
||||||
property="og:title"
|
property="og:title"
|
||||||
content={plainify(
|
content={plainify(
|
||||||
meta_title ? meta_title : title ? title : config.site.title,
|
meta_title ? meta_title : title ? title : config.site.title
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -129,7 +132,7 @@ const { title, meta_title, description, image, noindex, canonical, lang } =
|
|||||||
<meta
|
<meta
|
||||||
property="og:description"
|
property="og:description"
|
||||||
content={plainify(
|
content={plainify(
|
||||||
description ? description : config.metadata.meta_description,
|
description ? description : config.metadata.meta_description
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
@@ -142,7 +145,7 @@ const { title, meta_title, description, image, noindex, canonical, lang } =
|
|||||||
<meta
|
<meta
|
||||||
name="twitter:title"
|
name="twitter:title"
|
||||||
content={plainify(
|
content={plainify(
|
||||||
meta_title ? meta_title : title ? title : config.site.title,
|
meta_title ? meta_title : title ? title : config.site.title
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -150,7 +153,7 @@ const { title, meta_title, description, image, noindex, canonical, lang } =
|
|||||||
<meta
|
<meta
|
||||||
name="twitter:description"
|
name="twitter:description"
|
||||||
content={plainify(
|
content={plainify(
|
||||||
description ? description : config.metadata.meta_description,
|
description ? description : config.metadata.meta_description
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -174,7 +177,7 @@ const { title, meta_title, description, image, noindex, canonical, lang } =
|
|||||||
<body>
|
<body>
|
||||||
<TwSizeIndicator />
|
<TwSizeIndicator />
|
||||||
<Header />
|
<Header />
|
||||||
<SearchModal client:load />
|
<SearchModal lang={language} client:load />
|
||||||
<main id="main-content">
|
<main id="main-content">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import searchData from ".json/search.json";
|
import searchData from ".json/search.json";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import SearchResult, { type ISearchItem } from "./SearchResult";
|
import SearchResult, { type ISearchItem } from "./SearchResult";
|
||||||
|
import config from "@/config/config.json";
|
||||||
|
const { default_language } = config.settings;
|
||||||
|
|
||||||
const SearchModal = () => {
|
const SearchModal = ({ lang }: { lang: string | undefined }) => {
|
||||||
|
lang = lang || default_language;
|
||||||
const [searchString, setSearchString] = useState("");
|
const [searchString, setSearchString] = useState("");
|
||||||
|
|
||||||
// handle input change
|
// handle input change
|
||||||
@@ -39,9 +42,13 @@ const SearchModal = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// filter language specific search data
|
||||||
|
const filterSearchData = searchData.filter((item) => item.lang === lang);
|
||||||
|
|
||||||
|
|
||||||
// get search result
|
// get search result
|
||||||
const startTime = performance.now();
|
const startTime = performance.now();
|
||||||
const searchResult = doSearch(searchData);
|
const searchResult = doSearch(filterSearchData);
|
||||||
const endTime = performance.now();
|
const endTime = performance.now();
|
||||||
const totalTime = ((endTime - startTime) / 1000).toFixed(3);
|
const totalTime = ((endTime - startTime) / 1000).toFixed(3);
|
||||||
|
|
||||||
@@ -169,10 +176,15 @@ const SearchModal = () => {
|
|||||||
name="search"
|
name="search"
|
||||||
value={searchString}
|
value={searchString}
|
||||||
onChange={handleSearch}
|
onChange={handleSearch}
|
||||||
|
autoFocus
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<SearchResult searchResult={searchResult} searchString={searchString} />
|
<SearchResult
|
||||||
|
searchResult={searchResult}
|
||||||
|
searchString={searchString}
|
||||||
|
lang={lang}
|
||||||
|
/>
|
||||||
<div className="search-wrapper-footer">
|
<div className="search-wrapper-footer">
|
||||||
<span className="flex items-center">
|
<span className="flex items-center">
|
||||||
<kbd>
|
<kbd>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import { slugSelector } from "@/lib/utils/languageParser";
|
||||||
import { plainify, titleify } from "@/lib/utils/textConverter";
|
import { plainify, titleify } from "@/lib/utils/textConverter";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export interface ISearchItem {
|
export interface ISearchItem {
|
||||||
|
lang: string;
|
||||||
group: string;
|
group: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
frontmatter: {
|
frontmatter: {
|
||||||
@@ -33,10 +35,13 @@ export interface ISearchGroup {
|
|||||||
const SearchResult = ({
|
const SearchResult = ({
|
||||||
searchResult,
|
searchResult,
|
||||||
searchString,
|
searchString,
|
||||||
|
lang
|
||||||
}: {
|
}: {
|
||||||
searchResult: ISearchItem[];
|
searchResult: ISearchItem[];
|
||||||
searchString: string;
|
searchString: string;
|
||||||
|
lang: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
// generate search result group
|
// generate search result group
|
||||||
const generateSearchGroup = (searchResult: ISearchItem[]) => {
|
const generateSearchGroup = (searchResult: ISearchItem[]) => {
|
||||||
const joinDataByGroup: ISearchGroup[] = searchResult.reduce(
|
const joinDataByGroup: ISearchGroup[] = searchResult.reduce(
|
||||||
@@ -83,6 +88,7 @@ const SearchResult = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// match underline
|
// match underline
|
||||||
const matchUnderline = (text: string, substring: string) => {
|
const matchUnderline = (text: string, substring: string) => {
|
||||||
const parts = text?.split(new RegExp(`(${substring})`, "gi"));
|
const parts = text?.split(new RegExp(`(${substring})`, "gi"));
|
||||||
@@ -148,12 +154,14 @@ const SearchResult = ({
|
|||||||
<img
|
<img
|
||||||
src={item.frontmatter.image}
|
src={item.frontmatter.image}
|
||||||
alt={item.frontmatter.title}
|
alt={item.frontmatter.title}
|
||||||
|
width={100}
|
||||||
|
height={100}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="search-result-item-body">
|
<div className="search-result-item-body">
|
||||||
<a
|
<a
|
||||||
href={`/${item.slug}`}
|
href={`${slugSelector(item.slug, lang)}`}
|
||||||
className="search-result-item-title search-result-item-link"
|
className="search-result-item-title search-result-item-link"
|
||||||
>
|
>
|
||||||
{matchUnderline(item.frontmatter.title, searchString)}
|
{matchUnderline(item.frontmatter.title, searchString)}
|
||||||
|
|||||||
Reference in New Issue
Block a user