build(astro): migrate site to Astro 6
This commit is contained in:
10 files changed
+1537
-1073
No files matched your search
Generated
+1485
-1047
File diff suppressed because it is too large.
Load diff
+11
-7
@@ -3,12 +3,13 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.19.0"
|
"node": ">=22.12.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"build": "astro build",
|
"check": "astro check",
|
||||||
"build:sandbox": "NODE_OPTIONS=--require=./tools/localhost-dns.cjs astro build",
|
"build": "astro check && astro build",
|
||||||
|
"build:sandbox": "NODE_OPTIONS=--require=./tools/localhost-dns.cjs astro check && NODE_OPTIONS=--require=./tools/localhost-dns.cjs astro build",
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"extract:blog-footers": "node tools/extract-blog-footers.mjs",
|
"extract:blog-footers": "node tools/extract-blog-footers.mjs",
|
||||||
"crawl:live": "node tools/crawl-live-site.mjs",
|
"crawl:live": "node tools/crawl-live-site.mjs",
|
||||||
@@ -19,13 +20,16 @@
|
|||||||
"generate:redirects": "node tools/generate-redirects.mjs"
|
"generate:redirects": "node tools/generate-redirects.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/mdx": "^4.3.14",
|
"@astrojs/mdx": "^5.0.6",
|
||||||
"astro": "^5.10.0",
|
"astro": "^6.4.8",
|
||||||
"cheerio": "^1.1.0",
|
"cheerio": "^1.1.0",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"swiper": "^12.2.0",
|
"swiper": "^12.2.0",
|
||||||
"turndown": "^7.2.0",
|
"turndown": "^7.2.0"
|
||||||
"zod": "^3.25.0"
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@astrojs/check": "^0.9.10",
|
||||||
|
"typescript": "^6.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
---
|
---
|
||||||
|
import type { CollectionEntry } from 'astro:content';
|
||||||
import LikeViewCounter from './LikeViewCounter.astro';
|
import LikeViewCounter from './LikeViewCounter.astro';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
post: CollectionEntry<'blog'>;
|
||||||
|
prefix?: string;
|
||||||
|
}
|
||||||
|
|
||||||
const { post, prefix = '' } = Astro.props;
|
const { post, prefix = '' } = Astro.props;
|
||||||
const href = `${prefix}/library/${post.data.slug}`.replace('//', '/');
|
const href = `${prefix}/library/${post.data.slug}`.replace('//', '/');
|
||||||
const readMore = { en: 'Read More', es: 'Leer Más', ar: 'اقرأ المزيد' }[post.data.lang] || 'Read More';
|
const readMore = { en: 'Read More', es: 'Leer Más', ar: 'اقرأ المزيد' }[post.data.lang] || 'Read More';
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const encodedText = encode(linkValue);
|
|||||||
const spanId = id ?? `${contactType}-obfuscation-${Math.random().toString(36).slice(2, 10)}`;
|
const spanId = id ?? `${contactType}-obfuscation-${Math.random().toString(36).slice(2, 10)}`;
|
||||||
---
|
---
|
||||||
|
|
||||||
<span id={spanId} class={className}>{fallbackText}</span><script type="text/javascript" define:vars={{ encodedTarget, encodedText, protocol, spanId }}>
|
<span id={spanId} class={className}>{fallbackText}</span><script type="text/javascript" is:inline define:vars={{ encodedTarget, encodedText, protocol, spanId }}>
|
||||||
(() => {
|
(() => {
|
||||||
const contactSpan = document.getElementById(spanId);
|
const contactSpan = document.getElementById(spanId);
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const schema = {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<script type="application/ld+json" set:html={JSON.stringify(schema)} />
|
<script type="application/ld+json" is:inline set:html={JSON.stringify(schema)} />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.blog-faq {
|
.blog-faq {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ import Button from '../Button.astro';
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nodes = [...source.childNodes];
|
const nodes = [...source.childNodes];
|
||||||
const firstQuestionIndex = nodes.findIndex((node) => node.nodeType === Node.ELEMENT_NODE && node.tagName === 'H3');
|
const firstQuestionIndex = nodes.findIndex((node) => node instanceof HTMLElement && node.tagName === 'H3');
|
||||||
|
|
||||||
if (firstQuestionIndex === -1) {
|
if (firstQuestionIndex === -1) {
|
||||||
return;
|
return;
|
||||||
@@ -102,8 +102,12 @@ import Button from '../Button.astro';
|
|||||||
answerInner.className = 'faq-answer__inner';
|
answerInner.className = 'faq-answer__inner';
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
while (index < nodes.length && !(nodes[index] instanceof HTMLElement && nodes[index].tagName === 'H3')) {
|
while (index < nodes.length) {
|
||||||
const answerNode = nodes[index];
|
const answerNode = nodes[index];
|
||||||
|
if (answerNode instanceof HTMLElement && answerNode.tagName === 'H3') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (answerNode.nodeType === Node.TEXT_NODE) {
|
if (answerNode.nodeType === Node.TEXT_NODE) {
|
||||||
const text = answerNode.textContent?.trim();
|
const text = answerNode.textContent?.trim();
|
||||||
if (text) {
|
if (text) {
|
||||||
@@ -128,21 +132,23 @@ import Button from '../Button.astro';
|
|||||||
nodes[i].remove();
|
nodes[i].remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
const faqItems = [...list.querySelectorAll('details.faq')];
|
const faqItems = [...list.querySelectorAll<HTMLDetailsElement>('details.faq')];
|
||||||
|
|
||||||
const closeTimers = new WeakMap();
|
const closeTimers = new WeakMap<HTMLDetailsElement, number>();
|
||||||
const closeHandlers = new WeakMap();
|
const closeHandlers = new WeakMap<HTMLDetailsElement, (event: TransitionEvent) => void>();
|
||||||
|
|
||||||
const getAnswer = (item) => item.querySelector('.interactive-faq-with-seo-schema-integration__list__answer');
|
const getAnswer = (item: HTMLDetailsElement) =>
|
||||||
const getAnswerInner = (item) => item.querySelector('.faq-answer__inner');
|
item.querySelector<HTMLDivElement>('.interactive-faq-with-seo-schema-integration__list__answer');
|
||||||
|
const getAnswerInner = (item: HTMLDetailsElement) =>
|
||||||
|
item.querySelector<HTMLDivElement>('.faq-answer__inner');
|
||||||
|
|
||||||
const setClosedStyles = (answer) => {
|
const setClosedStyles = (answer: HTMLDivElement) => {
|
||||||
answer.style.height = '0px';
|
answer.style.height = '0px';
|
||||||
answer.style.opacity = '0';
|
answer.style.opacity = '0';
|
||||||
answer.style.transform = 'translateY(-.35rem)';
|
answer.style.transform = 'translateY(-.35rem)';
|
||||||
};
|
};
|
||||||
|
|
||||||
const setOpenStyles = (answer) => {
|
const setOpenStyles = (answer: HTMLDivElement) => {
|
||||||
answer.style.opacity = '1';
|
answer.style.opacity = '1';
|
||||||
answer.style.transform = 'translateY(0)';
|
answer.style.transform = 'translateY(0)';
|
||||||
};
|
};
|
||||||
@@ -164,7 +170,7 @@ import Button from '../Button.astro';
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const closeItem = (item) => {
|
const closeItem = (item: HTMLDetailsElement) => {
|
||||||
if (!item.open || item.dataset.state === 'closing') {
|
if (!item.open || item.dataset.state === 'closing') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -183,7 +189,7 @@ import Button from '../Button.astro';
|
|||||||
answer.offsetHeight; // force reflow
|
answer.offsetHeight; // force reflow
|
||||||
setClosedStyles(answer);
|
setClosedStyles(answer);
|
||||||
|
|
||||||
const onTransitionEnd = (event) => {
|
const onTransitionEnd = (event: TransitionEvent) => {
|
||||||
if (event.target !== answer || event.propertyName !== 'height') {
|
if (event.target !== answer || event.propertyName !== 'height') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -217,7 +223,7 @@ import Button from '../Button.astro';
|
|||||||
closeTimers.set(item, timer);
|
closeTimers.set(item, timer);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openItem = (item) => {
|
const openItem = (item: HTMLDetailsElement) => {
|
||||||
if (item.open && item.dataset.state !== 'closing') {
|
if (item.open && item.dataset.state !== 'closing') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -248,7 +254,7 @@ import Button from '../Button.astro';
|
|||||||
setOpenStyles(answer);
|
setOpenStyles(answer);
|
||||||
});
|
});
|
||||||
|
|
||||||
const onTransitionEnd = (event) => {
|
const onTransitionEnd = (event: TransitionEvent) => {
|
||||||
if (event.target !== answer || event.propertyName !== 'height') {
|
if (event.target !== answer || event.propertyName !== 'height') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defineCollection, z } from 'astro:content';
|
import { defineCollection } from 'astro:content';
|
||||||
import { glob } from 'astro/loaders';
|
import { glob } from 'astro/loaders';
|
||||||
|
import { z } from 'astro/zod';
|
||||||
import { homePageSchema, homeSectionsSchema } from './types/home-sections';
|
import { homePageSchema, homeSectionsSchema } from './types/home-sections';
|
||||||
|
|
||||||
const language = z.enum(['en', 'ar', 'es']);
|
const language = z.enum(['en', 'ar', 'es']);
|
||||||
@@ -7,7 +8,7 @@ const shared = {
|
|||||||
title: z.string(),
|
title: z.string(),
|
||||||
description: z.string().default(''),
|
description: z.string().default(''),
|
||||||
slug: z.string(),
|
slug: z.string(),
|
||||||
canonical: z.string().url().optional(),
|
canonical: z.url().optional(),
|
||||||
featuredImage: z.string().optional(),
|
featuredImage: z.string().optional(),
|
||||||
alt: z.string().optional(),
|
alt: z.string().optional(),
|
||||||
lang: language,
|
lang: language,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const organizationSchema = {
|
|||||||
<link rel="icon" href="/assets/images/favicon.svg" />
|
<link rel="icon" href="/assets/images/favicon.svg" />
|
||||||
<Seo title={title} description={description} canonical={canonical} image={image} lang={lang} type={type} />
|
<Seo title={title} description={description} canonical={canonical} image={image} lang={lang} type={type} />
|
||||||
<slot name="head" />
|
<slot name="head" />
|
||||||
<script type="application/ld+json" set:html={JSON.stringify(organizationSchema)} />
|
<script type="application/ld+json" is:inline set:html={JSON.stringify(organizationSchema)} />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a class="skip-link" href="#main">Skip to content</a>
|
<a class="skip-link" href="#main">Skip to content</a>
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
---
|
---
|
||||||
import BaseLayout from './BaseLayout.astro';
|
import BaseLayout from './BaseLayout.astro';
|
||||||
import PageHero from '../components/PageHero.astro';
|
import PageHero from '../components/PageHero.astro';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
intro?: string[];
|
||||||
|
lang?: 'en' | 'ar' | 'es';
|
||||||
|
}
|
||||||
|
|
||||||
const { title, description, intro = [], lang = 'en' } = Astro.props;
|
const { title, description, intro = [], lang = 'en' } = Astro.props;
|
||||||
const languagePrefix = lang === 'en' ? '' : `/${lang}`;
|
const languagePrefix = lang === 'en' ? '' : `/${lang}`;
|
||||||
const canonical = `https://www.azinstitute4autism.com${languagePrefix}/library`;
|
const canonical = `https://www.azinstitute4autism.com${languagePrefix}/library`;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { z } from 'astro:content';
|
import { z } from 'astro/zod';
|
||||||
|
|
||||||
const ctaSchema = z.object({
|
const ctaSchema = z.object({
|
||||||
label: z.string(),
|
label: z.string(),
|
||||||
|
|||||||
Reference in new issue
Block a user