added ImageMod component for image optimization

This commit is contained in:
somrat sorkar
2023-12-24 13:14:41 +06:00
parent 92ec961f80
commit 37d7a190d8
12 changed files with 127 additions and 27 deletions
+6 -6
View File
@@ -1,6 +1,6 @@
{ {
"name": "astroplate", "name": "astroplate",
"version": "3.0.1", "version": "3.1.0",
"description": "Astro and Tailwindcss boilerplate", "description": "Astro and Tailwindcss boilerplate",
"author": "zeon.studio", "author": "zeon.studio",
"license": "MIT", "license": "MIT",
@@ -14,12 +14,12 @@
"remove-darkmode": "node scripts/removeDarkmode.js && yarn format" "remove-darkmode": "node scripts/removeDarkmode.js && yarn format"
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "^2.0.1", "@astrojs/mdx": "^2.0.2",
"@astrojs/react": "^3.0.7", "@astrojs/react": "^3.0.8",
"@astrojs/rss": "^4.0.1", "@astrojs/rss": "^4.0.1",
"@astrojs/sitemap": "^3.0.3", "@astrojs/sitemap": "^3.0.3",
"@astrojs/tailwind": "^5.0.3", "@astrojs/tailwind": "^5.0.4",
"astro": "^4.0.6", "astro": "^4.0.7",
"astro-auto-import": "^0.4.2", "astro-auto-import": "^0.4.2",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"date-fns-tz": "^2.0.0", "date-fns-tz": "^2.0.0",
@@ -53,7 +53,7 @@
"prettier-plugin-astro": "^0.12.2", "prettier-plugin-astro": "^0.12.2",
"prettier-plugin-tailwindcss": "^0.5.9", "prettier-plugin-tailwindcss": "^0.5.9",
"sass": "^1.69.5", "sass": "^1.69.5",
"tailwindcss": "^3.3.7", "tailwindcss": "^3.4.0",
"tailwind-bootstrap-grid": "^5.1.0", "tailwind-bootstrap-grid": "^5.1.0",
"typescript": "5.3.3" "typescript": "5.3.3"
} }
+2 -2
View File
@@ -6,12 +6,12 @@ import { getSinglePage } from "@/lib/contentParser.astro";
import dateFormat from "@/lib/utils/dateFormat"; import dateFormat from "@/lib/utils/dateFormat";
import similarItems from "@/lib/utils/similarItems"; import similarItems from "@/lib/utils/similarItems";
import { humanize, markdownify, slugify } from "@/lib/utils/textConverter"; import { humanize, markdownify, slugify } from "@/lib/utils/textConverter";
import { Image } from "astro:assets";
import { import {
FaRegClock, FaRegClock,
FaRegFolder, FaRegFolder,
FaRegUserCircle, FaRegUserCircle,
} from "react-icons/fa/index.js"; } from "react-icons/fa/index.js";
import ImageMod from "./components/ImageMod.astro";
const COLLECTION_FOLDER = "blog"; const COLLECTION_FOLDER = "blog";
const { post } = Astro.props; const { post } = Astro.props;
@@ -29,7 +29,7 @@ const { title, description, author, categories, image, date, tags } = post.data;
{ {
image && ( image && (
<div class="mb-10"> <div class="mb-10">
<Image <ImageMod
src={image} src={image}
height={500} height={500}
width={1200} width={1200}
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
import { plainify } from "@/lib/utils/textConverter"; import { plainify } from "@/lib/utils/textConverter";
import { Image } from "astro:assets"; import ImageMod from "./ImageMod.astro";
import Social from "./Social.astro"; import Social from "./Social.astro";
const { data } = Astro.props; const { data } = Astro.props;
@@ -12,7 +12,7 @@ const { title, image, social } = data.data;
> >
{ {
image && ( image && (
<Image <ImageMod
class="mx-auto mb-6 rounded" class="mx-auto mb-6 rounded"
src={image} src={image}
alt={title} alt={title}
+2 -2
View File
@@ -2,8 +2,8 @@
import config from "@/config/config.json"; import config from "@/config/config.json";
import dateFormat from "@/lib/utils/dateFormat"; import dateFormat from "@/lib/utils/dateFormat";
import { humanize, plainify, slugify } from "@/lib/utils/textConverter"; import { humanize, plainify, slugify } from "@/lib/utils/textConverter";
import { Image } from "astro:assets";
import { FaRegFolder, FaRegUserCircle } from "react-icons/fa/index.js"; import { FaRegFolder, FaRegUserCircle } from "react-icons/fa/index.js";
import ImageMod from "./ImageMod.astro";
const { const {
summary_length, summary_length,
@@ -16,7 +16,7 @@ const { title, image, date, author, categories } = data.data;
<div class="bg-body dark:bg-darkmode-body"> <div class="bg-body dark:bg-darkmode-body">
{ {
image && ( image && (
<Image <ImageMod
class="mb-6 w-full rounded" class="mb-6 w-full rounded"
src={image} src={image}
alt={title} alt={title}
+60
View File
@@ -0,0 +1,60 @@
---
import type { ImageMetadata } from "astro";
import { Image } from "astro:assets";
// Props interface for the component
interface Props {
src: string;
alt: string;
width: number;
height: number;
loading?: "eager" | "lazy" | null | undefined;
decoding?: "async" | "auto" | "sync" | null | undefined;
format?: "auto" | "avif" | "jpeg" | "png" | "svg" | "webp";
class?: string;
style?: any;
}
// Destructuring Astro.props to get the component's props
let {
src,
alt,
width,
height,
loading,
decoding,
class: className,
format,
style,
} = Astro.props;
src = `/public${src}`;
// Glob pattern to load images from the /public/images folder
const images = import.meta.glob("/public/images/**/*.{jpeg,jpg,png,gif}");
// Check if the source path is valid
const isValidPath = images[src] ? true : false;
// Log a warning message in red if the image is not found
!isValidPath &&
console.error(
`\x1b[31mImage not found - ${src}.\x1b[0m Make sure the image is in the /public/images folder.`,
);
---
{
isValidPath && (
<Image
src={images[src]() as Promise<{ default: ImageMetadata }>}
alt={alt}
width={width}
height={height}
loading={loading}
decoding={decoding}
class={className}
format={format}
style={style}
/>
)
}
+3 -3
View File
@@ -1,6 +1,6 @@
--- ---
import config from "@/config/config.json"; import config from "@/config/config.json";
import { Image } from "astro:assets"; import ImageMod from "./ImageMod.astro";
const { src, srcDarkmode }: { src?: string; srcDarkmode?: string } = const { src, srcDarkmode }: { src?: string; srcDarkmode?: string } =
Astro.props; Astro.props;
@@ -27,7 +27,7 @@ const { theme_switcher }: { theme_switcher: boolean } = config.settings;
{ {
src || srcDarkmode || logo || logo_darkmode ? ( src || srcDarkmode || logo || logo_darkmode ? (
<> <>
<Image <ImageMod
src={src ? src : logo} src={src ? src : logo}
class={`inline-block ${theme_switcher && "dark:hidden"}`} class={`inline-block ${theme_switcher && "dark:hidden"}`}
width={logo_width.replace("px", "") * 2} width={logo_width.replace("px", "") * 2}
@@ -40,7 +40,7 @@ const { theme_switcher }: { theme_switcher: boolean } = config.settings;
format="webp" format="webp"
/> />
{theme_switcher && ( {theme_switcher && (
<Image <ImageMod
src={srcDarkmode ? srcDarkmode : logo_darkmode} src={srcDarkmode ? srcDarkmode : logo_darkmode}
class={"hidden dark:inline-block"} class={"hidden dark:inline-block"}
width={logo_width.replace("px", "") * 2} width={logo_width.replace("px", "") * 2}
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
import ImageMod from "@/components/ImageMod.astro";
import { markdownify } from "@/lib/utils/textConverter"; import { markdownify } from "@/lib/utils/textConverter";
import { Image } from "astro:assets";
const { call_to_action } = Astro.props; const { call_to_action } = Astro.props;
--- ---
@@ -11,7 +11,7 @@ const { call_to_action } = Astro.props;
<div class="rounded-xl bg-theme-light px-4 py-16 dark:bg-darkmode-theme-light xl:p-20"> <div class="rounded-xl bg-theme-light px-4 py-16 dark:bg-darkmode-theme-light xl:p-20">
<div class="row items-center justify-between"> <div class="row items-center justify-between">
<div class="mb-10 md:col-5 lg:col-4 md:order-2 md:mb-0"> <div class="mb-10 md:col-5 lg:col-4 md:order-2 md:mb-0">
<Image <ImageMod
class="w-full" class="w-full"
src={call_to_action.data.image} src={call_to_action.data.image}
width={392} width={392}
+2 -3
View File
@@ -1,6 +1,6 @@
--- ---
import { markdownify } from "@/lib/utils/textConverter"; import { markdownify } from "@/lib/utils/textConverter";
import { Image } from "astro:assets"; import ImageMod from "@/components/ImageMod.astro";
const { testimonial } = Astro.props; const { testimonial } = Astro.props;
--- ---
@@ -45,7 +45,7 @@ const { testimonial } = Astro.props;
/> />
<div class="mt-11 flex items-center"> <div class="mt-11 flex items-center">
<div class="text-dark dark:text-white"> <div class="text-dark dark:text-white">
<Image <ImageMod
height={50} height={50}
width={50} width={50}
class="rounded-full" class="rounded-full"
@@ -91,7 +91,6 @@ const { testimonial } = Astro.props;
modules: [Pagination, Autoplay], modules: [Pagination, Autoplay],
spaceBetween: 24, spaceBetween: 24,
loop: true, loop: true,
loopedSlides: 2,
centeredSlides: true, centeredSlides: true,
autoplay: { autoplay: {
delay: 2500, delay: 2500,
+41
View File
@@ -0,0 +1,41 @@
import { getImage } from "astro:assets";
const bgImageMod = async (
src: string,
format?: "auto" | "avif" | "jpeg" | "png" | "svg" | "webp",
) => {
src = `/public${src}`;
const images = import.meta.glob("/public/images/**/*.{jpeg,jpg,png,gif}");
// Check if the source path is valid
if (!src || !images[src]) {
console.error(
`\x1b[31mImage not found - ${src}.\x1b[0m Make sure the image is in the /public/images folder.`,
);
return ""; // Return an empty string if the image is not found
}
// Function to get the image info like width, height, format, etc.
const getImagePath = async (image: string) => {
try {
const imageData = (await images[image]()) as any;
return imageData;
} catch (error) {
return `Image not found - ${src}. Make sure the image is in the /public/images folder.`;
}
};
// Get the image data for the specified source path
const image = await getImagePath(src);
// Optimize the image for development
const ImageMod = await getImage({
src: image.default,
format: format,
});
return ImageMod.src;
};
export default bgImageMod;
+2 -2
View File
@@ -1,7 +1,7 @@
--- ---
import ImageMod from "@/components/ImageMod.astro";
import Base from "@/layouts/Base.astro"; import Base from "@/layouts/Base.astro";
import { markdownify } from "@/lib/utils/textConverter"; import { markdownify } from "@/lib/utils/textConverter";
import { Image } from "astro:assets";
import { getEntry } from "astro:content"; import { getEntry } from "astro:content";
const about = await getEntry("about", "-index"); const about = await getEntry("about", "-index");
@@ -21,7 +21,7 @@ const { title, description, meta_title, image } = about.data;
<div class="text-center md:col-10 lg:col-7"> <div class="text-center md:col-10 lg:col-7">
{ {
image && ( image && (
<Image <ImageMod
class="mx-auto mb-6 rounded-lg" class="mx-auto mb-6 rounded-lg"
src={image} src={image}
width={200} width={200}
+2 -2
View File
@@ -1,10 +1,10 @@
--- ---
import BlogCard from "@/components/BlogCard.astro"; import BlogCard from "@/components/BlogCard.astro";
import ImageMod from "@/components/ImageMod.astro";
import Social from "@/components/Social.astro"; import Social from "@/components/Social.astro";
import Base from "@/layouts/Base.astro"; import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro"; import { getSinglePage } from "@/lib/contentParser.astro";
import { slugify } from "@/lib/utils/textConverter"; import { slugify } from "@/lib/utils/textConverter";
import { Image } from "astro:assets";
// get all static paths for authors // get all static paths for authors
export async function getStaticPaths() { export async function getStaticPaths() {
@@ -46,7 +46,7 @@ const postFilterByAuthor = posts.filter(
<div class="text-center lg:col-4"> <div class="text-center lg:col-4">
{ {
image && ( image && (
<Image <ImageMod
src={image} src={image}
class="mx-auto mb-10 rounded" class="mx-auto mb-10 rounded"
height={200} height={200}
+3 -3
View File
@@ -1,10 +1,10 @@
--- ---
import ImageMod from "@/components/ImageMod.astro";
import Base from "@/layouts/Base.astro"; import Base from "@/layouts/Base.astro";
import { markdownify } from "@/lib/utils/textConverter"; import { markdownify } from "@/lib/utils/textConverter";
import CallToAction from "@/partials/CallToAction.astro"; import CallToAction from "@/partials/CallToAction.astro";
import Testimonial from "@/partials/Testimonial.astro"; import Testimonial from "@/partials/Testimonial.astro";
import type { Button, Feature } from "@/types"; import type { Button, Feature } from "@/types";
import { Image } from "astro:assets";
import { getEntry } from "astro:content"; import { getEntry } from "astro:content";
import { FaCheck } from "react-icons/fa/index.js"; import { FaCheck } from "react-icons/fa/index.js";
@@ -43,7 +43,7 @@ const { banner, features }: Homepage = homepage.data;
{ {
banner.image && ( banner.image && (
<div class="col-12"> <div class="col-12">
<Image <ImageMod
src={banner.image} src={banner.image}
height={380} height={380}
width={1200} width={1200}
@@ -67,7 +67,7 @@ const { banner, features }: Homepage = homepage.data;
<div <div
class={`mb:md-0 mb-6 md:col-5 ${index % 2 !== 0 && "md:order-2"}`} class={`mb:md-0 mb-6 md:col-5 ${index % 2 !== 0 && "md:order-2"}`}
> >
<Image <ImageMod
src={feature.image} src={feature.image}
height={480} height={480}
width={520} width={520}