Merge branch 'zeon-studio:main' into main

This commit is contained in:
Thuan Bui
2026-03-12 11:04:25 +09:00
committed by GitHub
5 changed files with 70 additions and 62 deletions
+37 -1
View File
@@ -3,11 +3,46 @@ import react from "@astrojs/react";
import sitemap from "@astrojs/sitemap"; import sitemap from "@astrojs/sitemap";
import tailwindcss from "@tailwindcss/vite"; import tailwindcss from "@tailwindcss/vite";
import AutoImport from "astro-auto-import"; import AutoImport from "astro-auto-import";
import { defineConfig } from "astro/config"; import { defineConfig, fontProviders } from "astro/config";
import remarkCollapse from "remark-collapse"; import remarkCollapse from "remark-collapse";
import remarkToc from "remark-toc"; import remarkToc from "remark-toc";
import sharp from "sharp"; import sharp from "sharp";
import config from "./src/config/config.json"; import config from "./src/config/config.json";
import theme from "./src/config/theme.json";
// Helper to parse font string format: "FontName:wght@400;500;600;700"
function parseFontString(fontStr) {
const [name, weightPart] = fontStr.split(":");
let weights = [400]; // default weight
if (weightPart) {
// Extract weights from wght@400;500;600 format
const weightMatch = weightPart.match(/wght@?([\d;]+)/);
if (weightMatch) {
weights = weightMatch[1].split(";").map((w) => parseInt(w, 10));
}
}
return { name, weights };
}
// Build fonts configuration from theme.json
const fontsConfig = Object.entries(theme.fonts.font_family)
.filter(([key]) => !key.includes("_type")) // Filter out type entries
.map(([key, fontStr]) => {
const { name, weights } = parseFontString(fontStr);
const typeKey = `${key}_type`;
const fallback = theme.fonts.font_family[typeKey] || "sans-serif";
return {
name,
cssVariable: `--font-${key}`,
provider: fontProviders.google(),
weights,
display: "swap",
fallbacks: [fallback],
};
});
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
@@ -16,6 +51,7 @@ export default defineConfig({
trailingSlash: config.site.trailing_slash ? "always" : "never", trailingSlash: config.site.trailing_slash ? "always" : "never",
image: { service: sharp() }, image: { service: sharp() },
vite: { plugins: [tailwindcss()] }, vite: { plugins: [tailwindcss()] },
fonts: fontsConfig,
integrations: [ integrations: [
react(), react(),
sitemap(), sitemap(),
+12 -13
View File
@@ -1,6 +1,6 @@
{ {
"name": "astroplate", "name": "astroplate",
"version": "6.0.0", "version": "6.0.1",
"description": "Astro and Tailwindcss boilerplate", "description": "Astro and Tailwindcss boilerplate",
"author": "zeon.studio", "author": "zeon.studio",
"license": "MIT", "license": "MIT",
@@ -18,25 +18,24 @@
"preview:cf-workers": "npm run build && wrangler dev" "preview:cf-workers": "npm run build && wrangler dev"
}, },
"dependencies": { "dependencies": {
"@astrojs/check": "0.9.7-beta.1", "@astrojs/check": "0.9.7",
"@astrojs/mdx": "5.0.0-beta.9", "@astrojs/mdx": "5.0.0",
"@astrojs/react": "5.0.0-beta.3", "@astrojs/react": "5.0.0",
"@astrojs/sitemap": "3.7.0", "@astrojs/sitemap": "3.7.1",
"@digi4care/astro-google-tagmanager": "^1.6.0", "@digi4care/astro-google-tagmanager": "^1.6.0",
"@justinribeiro/lite-youtube": "^1.9.0", "@justinribeiro/lite-youtube": "^1.9.0",
"astro": "6.0.0-beta.17", "astro": "6.0.2",
"astro-auto-import": "^0.5.1", "astro-auto-import": "^0.5.1",
"astro-font": "^1.1.0", "astro-swiper": "^2.2.1",
"astro-swiper": "^2.1.1",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"disqus-react": "^1.1.7", "disqus-react": "^1.1.7",
"github-slugger": "^2.0.0", "github-slugger": "^2.0.0",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"marked": "^17.0.3", "marked": "^17.0.4",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"react": "^19.2.4", "react": "^19.2.4",
"react-dom": "^19.2.4", "react-dom": "^19.2.4",
"react-icons": "^5.5.0", "react-icons": "^5.6.0",
"remark-collapse": "^0.1.2", "remark-collapse": "^0.1.2",
"remark-toc": "^9.0.0", "remark-toc": "^9.0.0",
"sharp": "^0.34.5", "sharp": "^0.34.5",
@@ -46,17 +45,17 @@
"@tailwindcss/forms": "^0.5.11", "@tailwindcss/forms": "^0.5.11",
"@tailwindcss/typography": "^0.5.19", "@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.2.1", "@tailwindcss/vite": "^4.2.1",
"@types/node": "25.3.3", "@types/node": "25.4.0",
"@types/react": "19.2.14", "@types/react": "19.2.14",
"@types/react-dom": "19.2.3", "@types/react-dom": "19.2.3",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"eslint": "^10.0.2", "eslint": "^10.0.3",
"prettier": "^3.8.1", "prettier": "^3.8.1",
"prettier-plugin-astro": "^0.14.1", "prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.7.2", "prettier-plugin-tailwindcss": "^0.7.2",
"tailwind-bootstrap-grid": "^7.0.0", "tailwind-bootstrap-grid": "^7.0.0",
"tailwindcss": "^4.2.1", "tailwindcss": "^4.2.1",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"wrangler": "^4.69.0" "wrangler": "^4.72.0"
} }
} }
+3 -3
View File
@@ -12,8 +12,8 @@
</h2> </h2>
<p align=center> <p align=center>
<a href="https://github.com/withastro/astro/releases/tag/astro%406.0.0-beta.17"> <a href="https://github.com/withastro/astro/releases/tag/astro%406.0.2">
<img src="https://img.shields.io/static/v1?label=ASTRO&message=6.0%20beta&color=000&logo=astro" alt="Astro Version 6.0 beta"/> <img src="https://img.shields.io/static/v1?label=ASTRO&message=6.0.2&color=000&logo=astro" alt="Astro Version 6.0.2"/>
</a> </a>
<a href="https://github.com/zeon-studio/astroplate/blob/main/LICENSE"> <a href="https://github.com/zeon-studio/astroplate/blob/main/LICENSE">
@@ -70,7 +70,7 @@
### 📦 Dependencies ### 📦 Dependencies
- astro v6.0.0-beta+ - astro v6.0.2
- node v22.12.0+ (see `.nvmrc`) - node v22.12.0+ (see `.nvmrc`)
- yarn v1.22+ - yarn v1.22+
- tailwind v4+ - tailwind v4+
+17 -44
View File
@@ -10,26 +10,15 @@ import {
GoogleTagmanager, GoogleTagmanager,
GoogleTagmanagerNoscript, GoogleTagmanagerNoscript,
} from "@digi4care/astro-google-tagmanager"; } from "@digi4care/astro-google-tagmanager";
import { AstroFont } from "astro-font"; import { Font } from "astro:assets";
import { ClientRouter } from "astro:transitions"; import { ClientRouter } from "astro:transitions";
import Announcement from "./helpers/Announcement"; import Announcement from "./helpers/Announcement";
import SearchModal from "./helpers/SearchModal"; import SearchModal from "./helpers/SearchModal";
// font families // font families - extract font names for Font component (filter out type keys)
const pf = theme.fonts.font_family.primary; const fontEntries = Object.entries(theme.fonts.font_family).filter(
const sf = theme.fonts.font_family.secondary; ([key]) => !key.includes("_type"),
);
let fontPrimary, fontSecondary;
if (theme.fonts.font_family.primary) {
fontPrimary = theme.fonts.font_family.primary
.replace(/\+/g, " ")
.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, "");
}
// types for frontmatters // types for frontmatters
export interface Props { export interface Props {
@@ -73,29 +62,13 @@ const { title, meta_title, description, image, noindex, canonical } =
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- google font css --> <!-- google font css - Astro 6 built-in Font API -->
<AstroFont {
config={[ fontEntries.map(([key]) => {
{ const cssVar = `--font-${key}` as any;
src: [], return <Font cssVariable={cssVar} preload />;
preload: false, })
display: "swap", }
name: fontPrimary!,
fallback: "sans-serif",
cssVariable: "font-primary",
googleFontsURL: `https://fonts.googleapis.com/css2?family=${pf}&display=swap`,
},
{
src: [],
preload: false,
display: "swap",
name: fontSecondary!,
fallback: "sans-serif",
cssVariable: "font-secondary",
googleFontsURL: `https://fonts.googleapis.com/css2?family=${sf}&display=swap`,
},
]}
/>
<!-- responsive meta --> <!-- responsive meta -->
<meta <meta
@@ -118,7 +91,7 @@ const { title, meta_title, description, image, noindex, canonical } =
<meta <meta
name="description" name="description"
content={plainify( content={plainify(
description ? description : config.metadata.meta_description description ? description : config.metadata.meta_description,
)} )}
/> />
@@ -131,7 +104,7 @@ const { title, meta_title, description, image, noindex, canonical } =
<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,
)} )}
/> />
@@ -139,7 +112,7 @@ const { title, meta_title, description, image, noindex, canonical } =
<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" />
@@ -152,7 +125,7 @@ const { title, meta_title, description, image, noindex, canonical } =
<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,
)} )}
/> />
@@ -160,7 +133,7 @@ const { title, meta_title, description, image, noindex, canonical } =
<meta <meta
name="twitter:description" name="twitter:description"
content={plainify( content={plainify(
description ? description : config.metadata.meta_description description ? description : config.metadata.meta_description,
)} )}
/> />
+1 -1
View File
@@ -6,7 +6,7 @@ const SearchModal = () => {
const [searchString, setSearchString] = useState(""); const [searchString, setSearchString] = useState("");
// handle input change // handle input change
const handleSearch = (e: React.FormEvent<HTMLInputElement>) => { const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearchString(e.currentTarget.value.replace("\\", "").toLowerCase()); setSearchString(e.currentTarget.value.replace("\\", "").toLowerCase());
}; };