image utils | cache | components
This commit is contained in:
parent
ecde90f89d
commit
c00cae6fde
@ -65,14 +65,33 @@ export default function getFilteredProps(type, props) {
|
|||||||
|
|
||||||
const { search, searchParams } = new URL(props.src, "file://");
|
const { search, searchParams } = new URL(props.src, "file://");
|
||||||
|
|
||||||
|
const paramOptions = Object.fromEntries(searchParams);
|
||||||
|
|
||||||
|
// Separate supported config params from others (like cache busters)
|
||||||
|
const supportedKeys = SupportedProperties[type] || [];
|
||||||
|
const configParams = {};
|
||||||
|
const otherParams = new URLSearchParams();
|
||||||
|
|
||||||
|
for (const [key, value] of searchParams) {
|
||||||
|
if (supportedKeys.includes(key) || GlobalConfigOptions[key]) {
|
||||||
|
configParams[key] = value;
|
||||||
|
} else {
|
||||||
|
otherParams.append(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove ALL params from src initially
|
||||||
props.src = props.src.replace(search, "");
|
props.src = props.src.replace(search, "");
|
||||||
|
|
||||||
const paramOptions = Object.fromEntries(searchParams);
|
// Re-append ONLY the non-config params to src
|
||||||
|
if (otherParams.toString()) {
|
||||||
|
props.src += `?${otherParams.toString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
const filteredLocalProps = filterConfigs(
|
const filteredLocalProps = filterConfigs(
|
||||||
type,
|
type,
|
||||||
{
|
{
|
||||||
...paramOptions,
|
...configParams,
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
SupportedProperties[type]
|
SupportedProperties[type]
|
||||||
|
|||||||
@ -26,8 +26,23 @@ export default async function getSrcset(
|
|||||||
.join("")
|
.join("")
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
const [cleanSrc] = src.split("?");
|
// Extract existing search params from src
|
||||||
const id = `${cleanSrc}?${params.slice(1)}`;
|
const [cleanSrc, search] = src.split("?");
|
||||||
|
|
||||||
|
// Combine existing params (like s=...) with options
|
||||||
|
// Existing params come first so they can be overridden by options if needed,
|
||||||
|
// though 's' should typically be unique.
|
||||||
|
const searchParams = new URLSearchParams(search);
|
||||||
|
|
||||||
|
// Add options to searchParams
|
||||||
|
keys.forEach(key => {
|
||||||
|
const value = Array.isArray(options[key])
|
||||||
|
? options[key].join(";")
|
||||||
|
: options[key];
|
||||||
|
searchParams.set(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const id = `${cleanSrc}?${searchParams.toString()}`;
|
||||||
// @todo : remove this
|
// @todo : remove this
|
||||||
const fullPath = await getSrcPath(id);
|
const fullPath = await getSrcPath(id);
|
||||||
const { default: load } = await import("../../plugin/hooks/load.js");
|
const { default: load } = await import("../../plugin/hooks/load.js");
|
||||||
|
|||||||
@ -2,9 +2,18 @@
|
|||||||
import renderPicture from "../api/renderPicture.js";
|
import renderPicture from "../api/renderPicture.js";
|
||||||
import type { PictureConfigOptions } from "../types.d";
|
import type { PictureConfigOptions } from "../types.d";
|
||||||
|
|
||||||
declare interface Props extends PictureConfigOptions {}
|
declare interface Props extends PictureConfigOptions {
|
||||||
|
s?: string;
|
||||||
|
}
|
||||||
|
|
||||||
const { link, style, picture } = await renderPicture(Astro.props as Props);
|
const { s, ...rest } = Astro.props as Props;
|
||||||
|
|
||||||
|
if (s) {
|
||||||
|
const separator = rest.src.includes("?") ? "&" : "?";
|
||||||
|
rest.src = `${rest.src}${separator}s=${s}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { link, style, picture } = await renderPicture(rest);
|
||||||
---
|
---
|
||||||
|
|
||||||
<Fragment set:html={link + style + picture} />
|
<Fragment set:html={link + style + picture} />
|
||||||
|
|||||||
@ -88,7 +88,6 @@ export default {
|
|||||||
await pMap(
|
await pMap(
|
||||||
[...allAssets.entries()],
|
[...allAssets.entries()],
|
||||||
async ([assetPath, { hash, image, buffer }]) => {
|
async ([assetPath, { hash, image, buffer }]) => {
|
||||||
logger.info(`[imagetools] Processing image ${assetPath}...`);
|
|
||||||
try {
|
try {
|
||||||
await saveAndCopyAsset(
|
await saveAndCopyAsset(
|
||||||
hash,
|
hash,
|
||||||
|
|||||||
@ -42,9 +42,10 @@ export default async function load(id) {
|
|||||||
path.relative("", src).split(path.sep).join(path.posix.sep)
|
path.relative("", src).split(path.sep).join(path.posix.sep)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Include search params in the hash calculation to force re-processing on change
|
||||||
const getHash = (width) =>
|
const getHash = (width) =>
|
||||||
objectHash(
|
objectHash(
|
||||||
{ width, options, rootRelativePosixSrc },
|
{ width, options, rootRelativePosixSrc, search },
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
{ algorithm: "sha256" }
|
{ algorithm: "sha256" }
|
||||||
);
|
);
|
||||||
@ -56,8 +57,11 @@ export default async function load(id) {
|
|||||||
|
|
||||||
const config = Object.fromEntries(searchParams);
|
const config = Object.fromEntries(searchParams);
|
||||||
|
|
||||||
|
// Use the full ID (including search params) + src for the store key
|
||||||
|
// This ensures that the same file with different params is treated as different source
|
||||||
|
const storeKey = src + search;
|
||||||
const { image: loadedImage, width: imageWidth } =
|
const { image: loadedImage, width: imageWidth } =
|
||||||
store.get(src) || store.set(src, await getLoadedImage(src, ext)).get(src);
|
store.get(storeKey) || store.set(storeKey, await getLoadedImage(src, ext)).get(storeKey);
|
||||||
|
|
||||||
const { type, widths, options, extension, raw, inline } = getConfigOptions(
|
const { type, widths, options, extension, raw, inline } = getConfigOptions(
|
||||||
config,
|
config,
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export const items = async (opts: { locale: string }) => {
|
|||||||
"class": "hover:text-orange-600"
|
"class": "hover:text-orange-600"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": `/resources/home`,
|
"href": `/${opts.locale}/resources/home`,
|
||||||
"title": _T("Resources"),
|
"title": _T("Resources"),
|
||||||
"ariaLabel": "Resources",
|
"ariaLabel": "Resources",
|
||||||
"class": "hover:text-orange-600"
|
"class": "hover:text-orange-600"
|
||||||
|
|||||||
@ -9,33 +9,38 @@ interface Props {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
currentPath,
|
currentPath,
|
||||||
collection = '',
|
collection = "",
|
||||||
title = '',
|
title = "",
|
||||||
separator = '/',
|
separator = "/",
|
||||||
showHome = true
|
showHome = true,
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
|
|
||||||
// Parse the current path to generate breadcrumb items
|
// Parse the current path to generate breadcrumb items
|
||||||
function generateBreadcrumbs(path: string, collection: string, pageTitle?: string) {
|
function generateBreadcrumbs(
|
||||||
const segments = path.split('/').filter(segment => segment !== '');
|
path: string,
|
||||||
const breadcrumbs: Array<{ label: string; href?: string; isLast?: boolean }> = [];
|
collection: string,
|
||||||
|
pageTitle?: string,
|
||||||
|
) {
|
||||||
|
const segments = path.split("/").filter((segment) => segment !== "");
|
||||||
|
const breadcrumbs: Array<{ label: string; href?: string; isLast?: boolean }> =
|
||||||
|
[];
|
||||||
|
|
||||||
// Add home if enabled
|
// Add home if enabled
|
||||||
if (showHome) {
|
if (showHome) {
|
||||||
breadcrumbs.push({ label: 'Home', href: '/' });
|
breadcrumbs.push({ label: "Home", href: "/" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build path segments
|
// Build path segments
|
||||||
let currentHref = '';
|
let currentHref = "";
|
||||||
segments.forEach((segment, index) => {
|
segments.forEach((segment, index) => {
|
||||||
currentHref += `/${segment}`;
|
currentHref += `/${segment}`;
|
||||||
const isLast = index === segments.length - 1;
|
const isLast = index === segments.length - 1;
|
||||||
|
|
||||||
// Format segment label
|
// Format segment label
|
||||||
let label = segment
|
let label = segment
|
||||||
.split('-')
|
.split("-")
|
||||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
||||||
.join(' ');
|
.join(" ");
|
||||||
|
|
||||||
// Use page title for the last segment if provided
|
// Use page title for the last segment if provided
|
||||||
if (isLast && pageTitle) {
|
if (isLast && pageTitle) {
|
||||||
@ -44,8 +49,8 @@ function generateBreadcrumbs(path: string, collection: string, pageTitle?: strin
|
|||||||
|
|
||||||
breadcrumbs.push({
|
breadcrumbs.push({
|
||||||
label,
|
label,
|
||||||
href: isLast ? undefined : currentHref + '/',
|
href: isLast ? undefined : currentHref + "/",
|
||||||
isLast
|
isLast,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,7 +62,8 @@ const breadcrumbs = generateBreadcrumbs(currentPath, collection, title);
|
|||||||
|
|
||||||
<nav class="breadcrumb" aria-label="Breadcrumb navigation">
|
<nav class="breadcrumb" aria-label="Breadcrumb navigation">
|
||||||
<ol class="breadcrumb-list">
|
<ol class="breadcrumb-list">
|
||||||
{breadcrumbs.map((crumb, index) => (
|
{
|
||||||
|
breadcrumbs.map((crumb, index) => (
|
||||||
<li class="breadcrumb-item">
|
<li class="breadcrumb-item">
|
||||||
{crumb.href ? (
|
{crumb.href ? (
|
||||||
<a
|
<a
|
||||||
@ -78,7 +84,8 @@ const breadcrumbs = generateBreadcrumbs(currentPath, collection, title);
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))
|
||||||
|
}
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@ -103,10 +110,10 @@ const breadcrumbs = generateBreadcrumbs(currentPath, collection, title);
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-link {
|
.breadcrumb-link {
|
||||||
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
padding: 0.25rem 0.5rem;
|
padding: 0.25rem 0.5rem;
|
||||||
@ -126,7 +133,6 @@ const breadcrumbs = generateBreadcrumbs(currentPath, collection, title);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-current {
|
.breadcrumb-current {
|
||||||
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
padding: 0.25rem 0.5rem;
|
padding: 0.25rem 0.5rem;
|
||||||
|
|||||||
@ -10,6 +10,7 @@ interface Image {
|
|||||||
src: string
|
src: string
|
||||||
title?: string
|
title?: string
|
||||||
description?: string
|
description?: string
|
||||||
|
hash?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@ -29,9 +30,10 @@ export interface Props {
|
|||||||
SHOW_TITLE?: boolean;
|
SHOW_TITLE?: boolean;
|
||||||
SHOW_DESCRIPTION?: boolean;
|
SHOW_DESCRIPTION?: boolean;
|
||||||
};
|
};
|
||||||
|
s?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { images, gallerySettings = {}, lightboxSettings = {} } = Astro.props;
|
const { images, gallerySettings = {}, lightboxSettings = {}, s } = Astro.props;
|
||||||
|
|
||||||
const mergedGallerySettings = {
|
const mergedGallerySettings = {
|
||||||
SIZES_REGULAR: gallerySettings.SIZES_REGULAR || IMAGE_SETTINGS.GALLERY.SIZES_REGULAR,
|
SIZES_REGULAR: gallerySettings.SIZES_REGULAR || IMAGE_SETTINGS.GALLERY.SIZES_REGULAR,
|
||||||
@ -46,7 +48,7 @@ const mergedLightboxSettings = {
|
|||||||
SHOW_DESCRIPTION: lightboxSettings.SHOW_DESCRIPTION ?? IMAGE_SETTINGS.LIGHTBOX.SHOW_DESCRIPTION,
|
SHOW_DESCRIPTION: lightboxSettings.SHOW_DESCRIPTION ?? IMAGE_SETTINGS.LIGHTBOX.SHOW_DESCRIPTION,
|
||||||
};
|
};
|
||||||
const locale = Astro.currentLocale || "en";
|
const locale = Astro.currentLocale || "en";
|
||||||
console.log(`LGallery Images`, images)
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -138,6 +140,8 @@ console.log(`LGallery Images`, images)
|
|||||||
format="avif"
|
format="avif"
|
||||||
placeholder="blurred"
|
placeholder="blurred"
|
||||||
sizes={mergedGallerySettings.SIZES_REGULAR}
|
sizes={mergedGallerySettings.SIZES_REGULAR}
|
||||||
|
sizes={mergedGallerySettings.SIZES_REGULAR}
|
||||||
|
s={s || image.hash}
|
||||||
attributes={{
|
attributes={{
|
||||||
img: { class: "main-image p-4 rounded-lg max-h-[60vh] aspect-square" }
|
img: { class: "main-image p-4 rounded-lg max-h-[60vh] aspect-square" }
|
||||||
}}
|
}}
|
||||||
@ -180,6 +184,7 @@ console.log(`LGallery Images`, images)
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
s={s || image.hash}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
@ -208,6 +213,8 @@ console.log(`LGallery Images`, images)
|
|||||||
format="avif"
|
format="avif"
|
||||||
objectFit="contain"
|
objectFit="contain"
|
||||||
sizes={IMAGE_SETTINGS.LIGHTBOX.SIZES_LARGE}
|
sizes={IMAGE_SETTINGS.LIGHTBOX.SIZES_LARGE}
|
||||||
|
sizes={IMAGE_SETTINGS.LIGHTBOX.SIZES_LARGE}
|
||||||
|
s={s || image.hash}
|
||||||
attributes={{
|
attributes={{
|
||||||
img: { class: "max-w-[90vw] max-h-[90vh] object-contain rounded-lg lightbox-main" }
|
img: { class: "max-w-[90vw] max-h-[90vh] object-contain rounded-lg lightbox-main" }
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -2,10 +2,7 @@
|
|||||||
import Wrapper from "@/components/containers/Wrapper.astro";
|
import Wrapper from "@/components/containers/Wrapper.astro";
|
||||||
import { footer_left, footer_right } from "@/app/navigation.js";
|
import { footer_left, footer_right } from "@/app/navigation.js";
|
||||||
import { ISO_LANGUAGE_LABELS } from "@polymech/i18n";
|
import { ISO_LANGUAGE_LABELS } from "@polymech/i18n";
|
||||||
import {
|
import { LANGUAGES_PROD, I18N_SOURCE_LANGUAGE } from "config/config.js";
|
||||||
LANGUAGES_PROD,
|
|
||||||
I18N_SOURCE_LANGUAGE,
|
|
||||||
} from "config/config.js";
|
|
||||||
|
|
||||||
const locale = Astro.currentLocale || I18N_SOURCE_LANGUAGE;
|
const locale = Astro.currentLocale || I18N_SOURCE_LANGUAGE;
|
||||||
const currentUrl = new URL(Astro.url);
|
const currentUrl = new URL(Astro.url);
|
||||||
@ -16,7 +13,7 @@ const currentUrl = new URL(Astro.url);
|
|||||||
* @returns {string[]} The URL path segments without the language code (if present).
|
* @returns {string[]} The URL path segments without the language code (if present).
|
||||||
*/
|
*/
|
||||||
const getCleanPathSegments = (url) => {
|
const getCleanPathSegments = (url) => {
|
||||||
const segments = url.pathname.split('/').filter(Boolean);
|
const segments = url.pathname.split("/").filter(Boolean);
|
||||||
if (segments.length && LANGUAGES_PROD.includes(segments[0])) {
|
if (segments.length && LANGUAGES_PROD.includes(segments[0])) {
|
||||||
segments.shift();
|
segments.shift();
|
||||||
}
|
}
|
||||||
@ -32,31 +29,30 @@ const getCleanPathSegments = (url) => {
|
|||||||
const buildLocalizedUrl = (lang, segments) => {
|
const buildLocalizedUrl = (lang, segments) => {
|
||||||
const newUrl = new URL(Astro.url);
|
const newUrl = new URL(Astro.url);
|
||||||
// Prepend the language code and join with existing segments, removing any trailing slash.
|
// Prepend the language code and join with existing segments, removing any trailing slash.
|
||||||
newUrl.pathname = `/${lang}/${segments.join('/')}`.replace(/\/+$/, '');
|
newUrl.pathname = `/${lang}/${segments.join("/")}`.replace(/\/+$/, "");
|
||||||
return newUrl.toString();
|
return newUrl.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanSegments = getCleanPathSegments(currentUrl);
|
const cleanSegments = getCleanPathSegments(currentUrl);
|
||||||
|
|
||||||
const languages = LANGUAGES_PROD.filter(
|
const languages = LANGUAGES_PROD.filter((lang) => lang !== locale).map(
|
||||||
(lang) => lang !== locale,
|
(lang) => ({
|
||||||
).map((lang) => ({
|
|
||||||
lang: ISO_LANGUAGE_LABELS[lang] || lang,
|
lang: ISO_LANGUAGE_LABELS[lang] || lang,
|
||||||
url: buildLocalizedUrl(lang, cleanSegments),
|
url: buildLocalizedUrl(lang, cleanSegments),
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const footerLeft = await footer_left(locale);
|
const footerLeft = await footer_left(locale);
|
||||||
const footerRight = await footer_right(locale);
|
const footerRight = await footer_right(locale);
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<Wrapper variant="standard" class="py-12">
|
<Wrapper variant="standard" class="py-12">
|
||||||
<footer class="py-2">
|
<footer class="py-2">
|
||||||
<div class="p-4 xl:pb-0 bg-white dark:bg-gray-800 overflow-hidden rounded-xl">
|
|
||||||
<div class="grid md:grid-cols-3 gap-6">
|
|
||||||
<div
|
<div
|
||||||
class="flex flex-col h-full justify-between xl:pb-2 order-last md:order-none"
|
class="p-4 xl:pb-0 bg-white dark:bg-gray-800 overflow-hidden rounded-xl"
|
||||||
>
|
>
|
||||||
|
<div class="grid grid-cols-2 md:grid-cols-3 gap-6">
|
||||||
|
<div class="flex flex-col gap-4 h-full justify-between xl:pb-2">
|
||||||
<nav role="navigation">
|
<nav role="navigation">
|
||||||
<ul class="text-xs space-y-1 uppercase dark:text-gray-400">
|
<ul class="text-xs space-y-1 uppercase dark:text-gray-400">
|
||||||
{
|
{
|
||||||
@ -69,20 +65,24 @@ const footerRight = await footer_right(locale);
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
<div class="mt-2">
|
<div
|
||||||
|
class="flex flex-col space-y-1 text-xs uppercase dark:text-gray-400"
|
||||||
|
>
|
||||||
{
|
{
|
||||||
languages.map((link) => (
|
languages.map((link) => (
|
||||||
<span>
|
<a class="hover:text-orange-500 block" href={link.url}>
|
||||||
<a class=" hover:text-orange-500 p-2 dark:text-gray-400" href={link.url}>
|
|
||||||
{link.lang}
|
{link.lang}
|
||||||
</a>
|
</a>
|
||||||
</span><br/>
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="flex gap-4 mt-12 items-center">
|
<div class="flex gap-4 mt-8 md:mt-12 items-center">
|
||||||
<img src="/logos/transparent.svg" alt="logo" class="size-4" />
|
<img
|
||||||
|
src="/logos/transparent.svg"
|
||||||
|
alt="logo"
|
||||||
|
class="size-4 hidden md:block"
|
||||||
|
/>
|
||||||
<p
|
<p
|
||||||
class="text-xs leading-5 text-neutral-400 dark:text-gray-500 text-pretty uppercase"
|
class="text-xs leading-5 text-neutral-400 dark:text-gray-500 text-pretty uppercase"
|
||||||
>
|
>
|
||||||
@ -93,11 +93,10 @@ const footerRight = await footer_right(locale);
|
|||||||
<img
|
<img
|
||||||
src="/logos/transparent.svg"
|
src="/logos/transparent.svg"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
class="size-12 md:mx-auto fill-orange-600"
|
class="size-12 md:mx-auto fill-orange-600 hidden md:block"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div class="flex flex-col h-full justify-between text-right xl:pb-2">
|
||||||
<div class="flex flex-col h-full justify-between md:text-right xl:pb-2">
|
|
||||||
<nav role="navigation">
|
<nav role="navigation">
|
||||||
<ul class="text-xs space-y-1 uppercase dark:text-gray-400">
|
<ul class="text-xs space-y-1 uppercase dark:text-gray-400">
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,20 +1,25 @@
|
|||||||
---
|
---
|
||||||
import * as path from "path"
|
import * as path from "path";
|
||||||
import { sync as fileExists } from "@polymech/fs/exists"
|
import { sync as fileExists } from "@polymech/fs/exists";
|
||||||
|
|
||||||
import { specs } from "@/base/specs.js"
|
import { specs } from "@/base/specs.js";
|
||||||
|
|
||||||
import { render, logger } from "@/base/index.js"
|
import { createComponent } from "astro/runtime/server/astro-component.js";
|
||||||
import { translateSheets } from "@/base/i18n.js"
|
import { renderTemplate, unescapeHTML } from "astro/runtime/server/index.js";
|
||||||
import { I18N_SOURCE_LANGUAGE, LANGUAGES, PRODUCT_SPECS } from "config/config.js"
|
|
||||||
|
|
||||||
import DefaultComponent from "./Default.astro"
|
import { logger } from "@/base/index.js";
|
||||||
|
import { translateSheets } from "@/base/i18n.js";
|
||||||
|
import {
|
||||||
|
I18N_SOURCE_LANGUAGE,
|
||||||
|
LANGUAGES,
|
||||||
|
PRODUCT_SPECS,
|
||||||
|
} from "config/config.js";
|
||||||
|
|
||||||
const { frontmatter: data } = Astro.props
|
import DefaultComponent from "./Default.astro";
|
||||||
const locale = Astro.currentLocale || I18N_SOURCE_LANGUAGE
|
const { frontmatter: data } = Astro.props;
|
||||||
|
const locale = Astro.currentLocale || I18N_SOURCE_LANGUAGE;
|
||||||
|
|
||||||
const specs_table = async (relPath) =>
|
const specs_table = async (relPath) => {
|
||||||
{
|
|
||||||
let specsPath = path.join(PRODUCT_SPECS(relPath));
|
let specsPath = path.join(PRODUCT_SPECS(relPath));
|
||||||
if (!fileExists(specsPath)) {
|
if (!fileExists(specsPath)) {
|
||||||
logger.debug(`No specs found for ${specsPath}`);
|
logger.debug(`No specs found for ${specsPath}`);
|
||||||
@ -25,19 +30,26 @@ const specs_table = async (relPath) =>
|
|||||||
if (!i18n) {
|
if (!i18n) {
|
||||||
logger.debug(`No i18n found for ${relPath} : ${locale}`);
|
logger.debug(`No i18n found for ${relPath} : ${locale}`);
|
||||||
} else {
|
} else {
|
||||||
specsPath = i18n
|
specsPath = i18n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return specs(specsPath)
|
return specs(specsPath);
|
||||||
}
|
};
|
||||||
const tableHTML = await specs_table(data.rel)
|
|
||||||
let SpecsComponent
|
const render = async (string) => {
|
||||||
|
const html = `${unescapeHTML(string)}`;
|
||||||
|
return createComponent(() => renderTemplate(html as any, []));
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableHTML = await specs_table(data.rel);
|
||||||
|
let SpecsComponent;
|
||||||
if (tableHTML) {
|
if (tableHTML) {
|
||||||
SpecsComponent = await render(tableHTML)
|
SpecsComponent = await render(tableHTML);
|
||||||
} else {
|
} else {
|
||||||
SpecsComponent = DefaultComponent
|
SpecsComponent = DefaultComponent;
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="bg-white rounded-xl specs specs-table">
|
<div class="bg-white rounded-xl specs specs-table">
|
||||||
<SpecsComponent />
|
<SpecsComponent />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user