@zoyth/simple-site-framework 1.0.4 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.d.mts +74 -1
- package/dist/components/index.d.ts +74 -1
- package/dist/components/index.js +208 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +206 -0
- package/dist/components/index.mjs.map +1 -1
- package/dist/index.d.mts +113 -2
- package/dist/index.d.ts +113 -2
- package/dist/index.js +196 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +187 -16
- package/dist/index.mjs.map +1 -1
- package/docs/BLOG.md +1005 -0
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ThemeConfig,
|
|
1
|
+
import { ThemeConfig, LocalizedString, HeroContent, AboutContent, ServicesContent, HeaderConfig, FooterConfig } from './config/index.mjs';
|
|
2
2
|
export { FooterSection, LogoConfig, NavDropdown, NavDropdownItem, NavItem, NavLink, NavigationConfig, ScriptsConfig, ServiceItem, SiteContent, SiteMetadata, WhyChooseUsContent } from './config/index.mjs';
|
|
3
3
|
import { NextRequest, NextResponse } from 'next/server';
|
|
4
4
|
import { ClassValue } from 'clsx';
|
|
@@ -128,6 +128,117 @@ declare function getAllPolicies(locale: string, contentDir?: string): Promise<Om
|
|
|
128
128
|
*/
|
|
129
129
|
declare function getPolicyLocales(slug: string, contentDir?: string): string[];
|
|
130
130
|
|
|
131
|
+
interface BlogPostMetadata {
|
|
132
|
+
title: string;
|
|
133
|
+
excerpt: string;
|
|
134
|
+
author: string;
|
|
135
|
+
/** ISO date (YYYY-MM-DD) */
|
|
136
|
+
date: string;
|
|
137
|
+
/** Reading time in minutes */
|
|
138
|
+
readTime: number;
|
|
139
|
+
tags: string[];
|
|
140
|
+
featured?: boolean;
|
|
141
|
+
/** Featured image URL */
|
|
142
|
+
image?: string;
|
|
143
|
+
imageAlt?: string;
|
|
144
|
+
[key: string]: unknown;
|
|
145
|
+
}
|
|
146
|
+
interface BlogPost {
|
|
147
|
+
/** Compiled MDX content */
|
|
148
|
+
content: JSX.Element;
|
|
149
|
+
/** Frontmatter metadata */
|
|
150
|
+
metadata: BlogPostMetadata;
|
|
151
|
+
/** Blog post slug (filename without locale/extension) */
|
|
152
|
+
slug: string;
|
|
153
|
+
/** Locale */
|
|
154
|
+
locale: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Load a blog post markdown file and compile it to React
|
|
158
|
+
*
|
|
159
|
+
* @param slug - Blog post slug (e.g., 'getting-started')
|
|
160
|
+
* @param locale - Locale code (e.g., 'en', 'fr')
|
|
161
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
162
|
+
* @returns Compiled blog post with content and metadata
|
|
163
|
+
*/
|
|
164
|
+
declare function loadBlogPost(slug: string, locale: string, contentDir?: string): Promise<BlogPost>;
|
|
165
|
+
/**
|
|
166
|
+
* Get all unique blog post slugs (without locale suffix)
|
|
167
|
+
*
|
|
168
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
169
|
+
* @returns Array of blog post slugs
|
|
170
|
+
*/
|
|
171
|
+
declare function getBlogPostSlugs(contentDir?: string): string[];
|
|
172
|
+
/**
|
|
173
|
+
* Get all blog posts for a specific locale with their metadata, sorted by date descending
|
|
174
|
+
*
|
|
175
|
+
* @param locale - Locale code
|
|
176
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
177
|
+
* @returns Array of blog posts with metadata (without content)
|
|
178
|
+
*/
|
|
179
|
+
declare function getAllBlogPosts(locale: string, contentDir?: string): Promise<Omit<BlogPost, 'content'>[]>;
|
|
180
|
+
/**
|
|
181
|
+
* Get available locales for a specific blog post
|
|
182
|
+
*
|
|
183
|
+
* @param slug - Blog post slug
|
|
184
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
185
|
+
* @returns Array of locale codes
|
|
186
|
+
*/
|
|
187
|
+
declare function getBlogPostLocales(slug: string, contentDir?: string): string[];
|
|
188
|
+
/**
|
|
189
|
+
* Get all blog posts matching a specific tag, sorted by date descending
|
|
190
|
+
*
|
|
191
|
+
* @param tag - Tag to filter by
|
|
192
|
+
* @param locale - Locale code
|
|
193
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
194
|
+
*/
|
|
195
|
+
declare function getBlogPostsByTag(tag: string, locale: string, contentDir?: string): Promise<Omit<BlogPost, 'content'>[]>;
|
|
196
|
+
/**
|
|
197
|
+
* Get featured blog posts, sorted by date descending
|
|
198
|
+
*
|
|
199
|
+
* @param locale - Locale code
|
|
200
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
201
|
+
*/
|
|
202
|
+
declare function getFeaturedBlogPosts(locale: string, contentDir?: string): Promise<Omit<BlogPost, 'content'>[]>;
|
|
203
|
+
/**
|
|
204
|
+
* Get blog posts related to a given post by shared tags
|
|
205
|
+
*
|
|
206
|
+
* Sorted by number of shared tags (descending), then by date (descending).
|
|
207
|
+
*
|
|
208
|
+
* @param slug - Source blog post slug
|
|
209
|
+
* @param locale - Locale code
|
|
210
|
+
* @param count - Maximum number of related posts to return @default 3
|
|
211
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
212
|
+
*/
|
|
213
|
+
declare function getRelatedBlogPosts(slug: string, locale: string, count?: number, contentDir?: string): Promise<Omit<BlogPost, 'content'>[]>;
|
|
214
|
+
interface TagCount {
|
|
215
|
+
tag: string;
|
|
216
|
+
count: number;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get all unique tags across all blog posts with their occurrence count
|
|
220
|
+
*
|
|
221
|
+
* Sorted by count descending.
|
|
222
|
+
*
|
|
223
|
+
* @param locale - Locale code
|
|
224
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
225
|
+
*/
|
|
226
|
+
declare function getAllTags(locale: string, contentDir?: string): Promise<TagCount[]>;
|
|
227
|
+
|
|
228
|
+
interface RssFeedOptions {
|
|
229
|
+
siteUrl: string;
|
|
230
|
+
siteName: string;
|
|
231
|
+
description: LocalizedString | string;
|
|
232
|
+
locale: string;
|
|
233
|
+
contentDir?: string;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Generate an RSS 2.0 feed from blog posts
|
|
237
|
+
*
|
|
238
|
+
* @returns XML string suitable for serving as application/rss+xml
|
|
239
|
+
*/
|
|
240
|
+
declare function generateBlogRssFeed(options: RssFeedOptions): Promise<string>;
|
|
241
|
+
|
|
131
242
|
/**
|
|
132
243
|
* Helper to get localized string from navigation
|
|
133
244
|
*/
|
|
@@ -2181,4 +2292,4 @@ interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'
|
|
|
2181
2292
|
size?: 'sm' | 'md' | 'lg';
|
|
2182
2293
|
}
|
|
2183
2294
|
|
|
2184
|
-
export { type A11yAnnouncerProps, type ABTestEvent, AboutContent, type AboutSectionProps, type AggregateRating, type AnalyticsEvent, type AnnouncementPriority, type Answer, type Article, type BreadcrumbItem, type BreadcrumbList, type BreadcrumbProps, type ButtonProps, type CTAClickEvent, type CTAType, type CardProps, type ChangeFrequency, type CheckboxProps, type CodeBlockProps, type ContactFormConfig, type ContactFormData, type ContactPoint, type ContactSectionProps, type ConversionEvent, type ConversionType, type EventCategory, type FAQPage, type Feature, type FeatureAction, type FeatureCategory, type FeatureEvent, FeaturesGrid, FooterConfig, type FooterProps, type FormAction, type FormEvent, type FormFieldProps, HeaderConfig, type HeaderProps, type HeroAnimations, HeroContent, type HeroSectionProps, type I18nConfig, type IconName, type IconProps, type InputProps, LOCALE_COOKIE_NAME, type LanguagePreference, type LanguageSwitcherProps, type LazySectionProps, type ListItem, type Locale, type LocaleCookieConfig, type LocalePrefix, LocalizedString, type Location, type MetadataOptions, type ModalProps, type NavigationEvent, type NavigationLocation, type Offer, type Organization, type PageViewEvent, type Person, type Policy, type PolicyMetadata, type PostalAddress, type PricingAction, type PricingEvent, type Product, type Question, type RadioProps, type Rating, type Review, type ScrollDepth, type ScrollDepthEvent, type SearchAction, type SelectProps, type ServicePageLayoutProps, ServicesContent, type ServicesSectionProps, type SitemapConfig, type SitemapEntry, type SkipLinkProps, type SlugTranslations, type TabsProps, type TestimonialSectionProps, type TextareaProps, ThemeConfig, type Thing, TrackedLink, type ValidLocale, type VideoAction, type VideoEvent, type WebSite, cn, createArticle, createBreadcrumbList, createFAQPage, createI18nMiddleware, createMultiLanguageEntries, createOrganization, createProduct, createSitemapEntry, createWebSite, creditCardSchema, dateString, defaultLocale, defaultSlugTranslations, emailSchema, fileSchema, formErrorMessages, formatCurrency, formatDate, formatDateRange, formatFileSize, formatList, formatLocaleDisplay, formatNumber, formatRelativeTime, generateArticleMetadata, generateDesignTokens, generateMetadata, generateSitemap, generateThemeCSS, getAllPolicies, getAlternateLocales, getDefaultLocale, getErrorMessage, getFontConfig, getFontVariables, getI18nConfig, getLocaleAutonym, getLocaleCookieConfig, getLocaleFromCookie, getLocaleLabel, getLocaleLabels, getLocaleName, getLocaleNames, getLocalePrefix, getLocales, getLocalizedString, getNavigationString, getPolicyLocales, getPolicySlugs, getRelativeTime, getRtlLocales, getTextDirection, imageSchema, isI18nConfigInitialized, isLocaleDetectionEnabled, isRtlLocale, isSupportedLocale, loadPolicy, locales, matchLocale, mustBeTrue, normalizeLocale, numericString, optionalString, passwordSchema, phoneSchema, postalCodeSchema, replaceVariables, requiredString, serializeStructuredData, setI18nConfig, setLocaleCookie, trackABTestEvent, trackCTAClick, trackConversion, trackError, trackEvent, trackFeatureEngagement, trackFormEvent, trackNavigation, trackOutboundLink, trackPageView, trackPricingEvent, trackResourceDownload, trackScrollDepth, trackSearch, trackVideoEvent, translateSlug, urlSchema, validateLocale, validateSitemap, validateSitemapEntry };
|
|
2295
|
+
export { type A11yAnnouncerProps, type ABTestEvent, AboutContent, type AboutSectionProps, type AggregateRating, type AnalyticsEvent, type AnnouncementPriority, type Answer, type Article, type BlogPost, type BlogPostMetadata, type BreadcrumbItem, type BreadcrumbList, type BreadcrumbProps, type ButtonProps, type CTAClickEvent, type CTAType, type CardProps, type ChangeFrequency, type CheckboxProps, type CodeBlockProps, type ContactFormConfig, type ContactFormData, type ContactPoint, type ContactSectionProps, type ConversionEvent, type ConversionType, type EventCategory, type FAQPage, type Feature, type FeatureAction, type FeatureCategory, type FeatureEvent, FeaturesGrid, FooterConfig, type FooterProps, type FormAction, type FormEvent, type FormFieldProps, HeaderConfig, type HeaderProps, type HeroAnimations, HeroContent, type HeroSectionProps, type I18nConfig, type IconName, type IconProps, type InputProps, LOCALE_COOKIE_NAME, type LanguagePreference, type LanguageSwitcherProps, type LazySectionProps, type ListItem, type Locale, type LocaleCookieConfig, type LocalePrefix, LocalizedString, type Location, type MetadataOptions, type ModalProps, type NavigationEvent, type NavigationLocation, type Offer, type Organization, type PageViewEvent, type Person, type Policy, type PolicyMetadata, type PostalAddress, type PricingAction, type PricingEvent, type Product, type Question, type RadioProps, type Rating, type Review, type RssFeedOptions, type ScrollDepth, type ScrollDepthEvent, type SearchAction, type SelectProps, type ServicePageLayoutProps, ServicesContent, type ServicesSectionProps, type SitemapConfig, type SitemapEntry, type SkipLinkProps, type SlugTranslations, type TabsProps, type TagCount, type TestimonialSectionProps, type TextareaProps, ThemeConfig, type Thing, TrackedLink, type ValidLocale, type VideoAction, type VideoEvent, type WebSite, cn, createArticle, createBreadcrumbList, createFAQPage, createI18nMiddleware, createMultiLanguageEntries, createOrganization, createProduct, createSitemapEntry, createWebSite, creditCardSchema, dateString, defaultLocale, defaultSlugTranslations, emailSchema, fileSchema, formErrorMessages, formatCurrency, formatDate, formatDateRange, formatFileSize, formatList, formatLocaleDisplay, formatNumber, formatRelativeTime, generateArticleMetadata, generateBlogRssFeed, generateDesignTokens, generateMetadata, generateSitemap, generateThemeCSS, getAllBlogPosts, getAllPolicies, getAllTags, getAlternateLocales, getBlogPostLocales, getBlogPostSlugs, getBlogPostsByTag, getDefaultLocale, getErrorMessage, getFeaturedBlogPosts, getFontConfig, getFontVariables, getI18nConfig, getLocaleAutonym, getLocaleCookieConfig, getLocaleFromCookie, getLocaleLabel, getLocaleLabels, getLocaleName, getLocaleNames, getLocalePrefix, getLocales, getLocalizedString, getNavigationString, getPolicyLocales, getPolicySlugs, getRelatedBlogPosts, getRelativeTime, getRtlLocales, getTextDirection, imageSchema, isI18nConfigInitialized, isLocaleDetectionEnabled, isRtlLocale, isSupportedLocale, loadBlogPost, loadPolicy, locales, matchLocale, mustBeTrue, normalizeLocale, numericString, optionalString, passwordSchema, phoneSchema, postalCodeSchema, replaceVariables, requiredString, serializeStructuredData, setI18nConfig, setLocaleCookie, trackABTestEvent, trackCTAClick, trackConversion, trackError, trackEvent, trackFeatureEngagement, trackFormEvent, trackNavigation, trackOutboundLink, trackPageView, trackPricingEvent, trackResourceDownload, trackScrollDepth, trackSearch, trackVideoEvent, translateSlug, urlSchema, validateLocale, validateSitemap, validateSitemapEntry };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ThemeConfig,
|
|
1
|
+
import { ThemeConfig, LocalizedString, HeroContent, AboutContent, ServicesContent, HeaderConfig, FooterConfig } from './config/index.js';
|
|
2
2
|
export { FooterSection, LogoConfig, NavDropdown, NavDropdownItem, NavItem, NavLink, NavigationConfig, ScriptsConfig, ServiceItem, SiteContent, SiteMetadata, WhyChooseUsContent } from './config/index.js';
|
|
3
3
|
import { NextRequest, NextResponse } from 'next/server';
|
|
4
4
|
import { ClassValue } from 'clsx';
|
|
@@ -128,6 +128,117 @@ declare function getAllPolicies(locale: string, contentDir?: string): Promise<Om
|
|
|
128
128
|
*/
|
|
129
129
|
declare function getPolicyLocales(slug: string, contentDir?: string): string[];
|
|
130
130
|
|
|
131
|
+
interface BlogPostMetadata {
|
|
132
|
+
title: string;
|
|
133
|
+
excerpt: string;
|
|
134
|
+
author: string;
|
|
135
|
+
/** ISO date (YYYY-MM-DD) */
|
|
136
|
+
date: string;
|
|
137
|
+
/** Reading time in minutes */
|
|
138
|
+
readTime: number;
|
|
139
|
+
tags: string[];
|
|
140
|
+
featured?: boolean;
|
|
141
|
+
/** Featured image URL */
|
|
142
|
+
image?: string;
|
|
143
|
+
imageAlt?: string;
|
|
144
|
+
[key: string]: unknown;
|
|
145
|
+
}
|
|
146
|
+
interface BlogPost {
|
|
147
|
+
/** Compiled MDX content */
|
|
148
|
+
content: JSX.Element;
|
|
149
|
+
/** Frontmatter metadata */
|
|
150
|
+
metadata: BlogPostMetadata;
|
|
151
|
+
/** Blog post slug (filename without locale/extension) */
|
|
152
|
+
slug: string;
|
|
153
|
+
/** Locale */
|
|
154
|
+
locale: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Load a blog post markdown file and compile it to React
|
|
158
|
+
*
|
|
159
|
+
* @param slug - Blog post slug (e.g., 'getting-started')
|
|
160
|
+
* @param locale - Locale code (e.g., 'en', 'fr')
|
|
161
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
162
|
+
* @returns Compiled blog post with content and metadata
|
|
163
|
+
*/
|
|
164
|
+
declare function loadBlogPost(slug: string, locale: string, contentDir?: string): Promise<BlogPost>;
|
|
165
|
+
/**
|
|
166
|
+
* Get all unique blog post slugs (without locale suffix)
|
|
167
|
+
*
|
|
168
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
169
|
+
* @returns Array of blog post slugs
|
|
170
|
+
*/
|
|
171
|
+
declare function getBlogPostSlugs(contentDir?: string): string[];
|
|
172
|
+
/**
|
|
173
|
+
* Get all blog posts for a specific locale with their metadata, sorted by date descending
|
|
174
|
+
*
|
|
175
|
+
* @param locale - Locale code
|
|
176
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
177
|
+
* @returns Array of blog posts with metadata (without content)
|
|
178
|
+
*/
|
|
179
|
+
declare function getAllBlogPosts(locale: string, contentDir?: string): Promise<Omit<BlogPost, 'content'>[]>;
|
|
180
|
+
/**
|
|
181
|
+
* Get available locales for a specific blog post
|
|
182
|
+
*
|
|
183
|
+
* @param slug - Blog post slug
|
|
184
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
185
|
+
* @returns Array of locale codes
|
|
186
|
+
*/
|
|
187
|
+
declare function getBlogPostLocales(slug: string, contentDir?: string): string[];
|
|
188
|
+
/**
|
|
189
|
+
* Get all blog posts matching a specific tag, sorted by date descending
|
|
190
|
+
*
|
|
191
|
+
* @param tag - Tag to filter by
|
|
192
|
+
* @param locale - Locale code
|
|
193
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
194
|
+
*/
|
|
195
|
+
declare function getBlogPostsByTag(tag: string, locale: string, contentDir?: string): Promise<Omit<BlogPost, 'content'>[]>;
|
|
196
|
+
/**
|
|
197
|
+
* Get featured blog posts, sorted by date descending
|
|
198
|
+
*
|
|
199
|
+
* @param locale - Locale code
|
|
200
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
201
|
+
*/
|
|
202
|
+
declare function getFeaturedBlogPosts(locale: string, contentDir?: string): Promise<Omit<BlogPost, 'content'>[]>;
|
|
203
|
+
/**
|
|
204
|
+
* Get blog posts related to a given post by shared tags
|
|
205
|
+
*
|
|
206
|
+
* Sorted by number of shared tags (descending), then by date (descending).
|
|
207
|
+
*
|
|
208
|
+
* @param slug - Source blog post slug
|
|
209
|
+
* @param locale - Locale code
|
|
210
|
+
* @param count - Maximum number of related posts to return @default 3
|
|
211
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
212
|
+
*/
|
|
213
|
+
declare function getRelatedBlogPosts(slug: string, locale: string, count?: number, contentDir?: string): Promise<Omit<BlogPost, 'content'>[]>;
|
|
214
|
+
interface TagCount {
|
|
215
|
+
tag: string;
|
|
216
|
+
count: number;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get all unique tags across all blog posts with their occurrence count
|
|
220
|
+
*
|
|
221
|
+
* Sorted by count descending.
|
|
222
|
+
*
|
|
223
|
+
* @param locale - Locale code
|
|
224
|
+
* @param contentDir - Directory containing blog files @default 'src/content/blog'
|
|
225
|
+
*/
|
|
226
|
+
declare function getAllTags(locale: string, contentDir?: string): Promise<TagCount[]>;
|
|
227
|
+
|
|
228
|
+
interface RssFeedOptions {
|
|
229
|
+
siteUrl: string;
|
|
230
|
+
siteName: string;
|
|
231
|
+
description: LocalizedString | string;
|
|
232
|
+
locale: string;
|
|
233
|
+
contentDir?: string;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Generate an RSS 2.0 feed from blog posts
|
|
237
|
+
*
|
|
238
|
+
* @returns XML string suitable for serving as application/rss+xml
|
|
239
|
+
*/
|
|
240
|
+
declare function generateBlogRssFeed(options: RssFeedOptions): Promise<string>;
|
|
241
|
+
|
|
131
242
|
/**
|
|
132
243
|
* Helper to get localized string from navigation
|
|
133
244
|
*/
|
|
@@ -2181,4 +2292,4 @@ interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'
|
|
|
2181
2292
|
size?: 'sm' | 'md' | 'lg';
|
|
2182
2293
|
}
|
|
2183
2294
|
|
|
2184
|
-
export { type A11yAnnouncerProps, type ABTestEvent, AboutContent, type AboutSectionProps, type AggregateRating, type AnalyticsEvent, type AnnouncementPriority, type Answer, type Article, type BreadcrumbItem, type BreadcrumbList, type BreadcrumbProps, type ButtonProps, type CTAClickEvent, type CTAType, type CardProps, type ChangeFrequency, type CheckboxProps, type CodeBlockProps, type ContactFormConfig, type ContactFormData, type ContactPoint, type ContactSectionProps, type ConversionEvent, type ConversionType, type EventCategory, type FAQPage, type Feature, type FeatureAction, type FeatureCategory, type FeatureEvent, FeaturesGrid, FooterConfig, type FooterProps, type FormAction, type FormEvent, type FormFieldProps, HeaderConfig, type HeaderProps, type HeroAnimations, HeroContent, type HeroSectionProps, type I18nConfig, type IconName, type IconProps, type InputProps, LOCALE_COOKIE_NAME, type LanguagePreference, type LanguageSwitcherProps, type LazySectionProps, type ListItem, type Locale, type LocaleCookieConfig, type LocalePrefix, LocalizedString, type Location, type MetadataOptions, type ModalProps, type NavigationEvent, type NavigationLocation, type Offer, type Organization, type PageViewEvent, type Person, type Policy, type PolicyMetadata, type PostalAddress, type PricingAction, type PricingEvent, type Product, type Question, type RadioProps, type Rating, type Review, type ScrollDepth, type ScrollDepthEvent, type SearchAction, type SelectProps, type ServicePageLayoutProps, ServicesContent, type ServicesSectionProps, type SitemapConfig, type SitemapEntry, type SkipLinkProps, type SlugTranslations, type TabsProps, type TestimonialSectionProps, type TextareaProps, ThemeConfig, type Thing, TrackedLink, type ValidLocale, type VideoAction, type VideoEvent, type WebSite, cn, createArticle, createBreadcrumbList, createFAQPage, createI18nMiddleware, createMultiLanguageEntries, createOrganization, createProduct, createSitemapEntry, createWebSite, creditCardSchema, dateString, defaultLocale, defaultSlugTranslations, emailSchema, fileSchema, formErrorMessages, formatCurrency, formatDate, formatDateRange, formatFileSize, formatList, formatLocaleDisplay, formatNumber, formatRelativeTime, generateArticleMetadata, generateDesignTokens, generateMetadata, generateSitemap, generateThemeCSS, getAllPolicies, getAlternateLocales, getDefaultLocale, getErrorMessage, getFontConfig, getFontVariables, getI18nConfig, getLocaleAutonym, getLocaleCookieConfig, getLocaleFromCookie, getLocaleLabel, getLocaleLabels, getLocaleName, getLocaleNames, getLocalePrefix, getLocales, getLocalizedString, getNavigationString, getPolicyLocales, getPolicySlugs, getRelativeTime, getRtlLocales, getTextDirection, imageSchema, isI18nConfigInitialized, isLocaleDetectionEnabled, isRtlLocale, isSupportedLocale, loadPolicy, locales, matchLocale, mustBeTrue, normalizeLocale, numericString, optionalString, passwordSchema, phoneSchema, postalCodeSchema, replaceVariables, requiredString, serializeStructuredData, setI18nConfig, setLocaleCookie, trackABTestEvent, trackCTAClick, trackConversion, trackError, trackEvent, trackFeatureEngagement, trackFormEvent, trackNavigation, trackOutboundLink, trackPageView, trackPricingEvent, trackResourceDownload, trackScrollDepth, trackSearch, trackVideoEvent, translateSlug, urlSchema, validateLocale, validateSitemap, validateSitemapEntry };
|
|
2295
|
+
export { type A11yAnnouncerProps, type ABTestEvent, AboutContent, type AboutSectionProps, type AggregateRating, type AnalyticsEvent, type AnnouncementPriority, type Answer, type Article, type BlogPost, type BlogPostMetadata, type BreadcrumbItem, type BreadcrumbList, type BreadcrumbProps, type ButtonProps, type CTAClickEvent, type CTAType, type CardProps, type ChangeFrequency, type CheckboxProps, type CodeBlockProps, type ContactFormConfig, type ContactFormData, type ContactPoint, type ContactSectionProps, type ConversionEvent, type ConversionType, type EventCategory, type FAQPage, type Feature, type FeatureAction, type FeatureCategory, type FeatureEvent, FeaturesGrid, FooterConfig, type FooterProps, type FormAction, type FormEvent, type FormFieldProps, HeaderConfig, type HeaderProps, type HeroAnimations, HeroContent, type HeroSectionProps, type I18nConfig, type IconName, type IconProps, type InputProps, LOCALE_COOKIE_NAME, type LanguagePreference, type LanguageSwitcherProps, type LazySectionProps, type ListItem, type Locale, type LocaleCookieConfig, type LocalePrefix, LocalizedString, type Location, type MetadataOptions, type ModalProps, type NavigationEvent, type NavigationLocation, type Offer, type Organization, type PageViewEvent, type Person, type Policy, type PolicyMetadata, type PostalAddress, type PricingAction, type PricingEvent, type Product, type Question, type RadioProps, type Rating, type Review, type RssFeedOptions, type ScrollDepth, type ScrollDepthEvent, type SearchAction, type SelectProps, type ServicePageLayoutProps, ServicesContent, type ServicesSectionProps, type SitemapConfig, type SitemapEntry, type SkipLinkProps, type SlugTranslations, type TabsProps, type TagCount, type TestimonialSectionProps, type TextareaProps, ThemeConfig, type Thing, TrackedLink, type ValidLocale, type VideoAction, type VideoEvent, type WebSite, cn, createArticle, createBreadcrumbList, createFAQPage, createI18nMiddleware, createMultiLanguageEntries, createOrganization, createProduct, createSitemapEntry, createWebSite, creditCardSchema, dateString, defaultLocale, defaultSlugTranslations, emailSchema, fileSchema, formErrorMessages, formatCurrency, formatDate, formatDateRange, formatFileSize, formatList, formatLocaleDisplay, formatNumber, formatRelativeTime, generateArticleMetadata, generateBlogRssFeed, generateDesignTokens, generateMetadata, generateSitemap, generateThemeCSS, getAllBlogPosts, getAllPolicies, getAllTags, getAlternateLocales, getBlogPostLocales, getBlogPostSlugs, getBlogPostsByTag, getDefaultLocale, getErrorMessage, getFeaturedBlogPosts, getFontConfig, getFontVariables, getI18nConfig, getLocaleAutonym, getLocaleCookieConfig, getLocaleFromCookie, getLocaleLabel, getLocaleLabels, getLocaleName, getLocaleNames, getLocalePrefix, getLocales, getLocalizedString, getNavigationString, getPolicyLocales, getPolicySlugs, getRelatedBlogPosts, getRelativeTime, getRtlLocales, getTextDirection, imageSchema, isI18nConfigInitialized, isLocaleDetectionEnabled, isRtlLocale, isSupportedLocale, loadBlogPost, loadPolicy, locales, matchLocale, mustBeTrue, normalizeLocale, numericString, optionalString, passwordSchema, phoneSchema, postalCodeSchema, replaceVariables, requiredString, serializeStructuredData, setI18nConfig, setLocaleCookie, trackABTestEvent, trackCTAClick, trackConversion, trackError, trackEvent, trackFeatureEngagement, trackFormEvent, trackNavigation, trackOutboundLink, trackPageView, trackPricingEvent, trackResourceDownload, trackScrollDepth, trackSearch, trackVideoEvent, translateSlug, urlSchema, validateLocale, validateSitemap, validateSitemapEntry };
|
package/dist/index.js
CHANGED
|
@@ -204,14 +204,21 @@ __export(src_exports, {
|
|
|
204
204
|
formatNumber: () => formatNumber,
|
|
205
205
|
formatRelativeTime: () => formatRelativeTime,
|
|
206
206
|
generateArticleMetadata: () => generateArticleMetadata,
|
|
207
|
+
generateBlogRssFeed: () => generateBlogRssFeed,
|
|
207
208
|
generateDesignTokens: () => generateDesignTokens,
|
|
208
209
|
generateMetadata: () => generateMetadata,
|
|
209
210
|
generateSitemap: () => generateSitemap,
|
|
210
211
|
generateThemeCSS: () => generateThemeCSS,
|
|
212
|
+
getAllBlogPosts: () => getAllBlogPosts,
|
|
211
213
|
getAllPolicies: () => getAllPolicies,
|
|
214
|
+
getAllTags: () => getAllTags,
|
|
212
215
|
getAlternateLocales: () => getAlternateLocales,
|
|
216
|
+
getBlogPostLocales: () => getBlogPostLocales,
|
|
217
|
+
getBlogPostSlugs: () => getBlogPostSlugs,
|
|
218
|
+
getBlogPostsByTag: () => getBlogPostsByTag,
|
|
213
219
|
getDefaultLocale: () => getDefaultLocale,
|
|
214
220
|
getErrorMessage: () => getErrorMessage,
|
|
221
|
+
getFeaturedBlogPosts: () => getFeaturedBlogPosts,
|
|
215
222
|
getFontConfig: () => getFontConfig,
|
|
216
223
|
getFontVariables: () => getFontVariables,
|
|
217
224
|
getI18nConfig: () => getI18nConfig,
|
|
@@ -228,6 +235,7 @@ __export(src_exports, {
|
|
|
228
235
|
getNavigationString: () => getNavigationString,
|
|
229
236
|
getPolicyLocales: () => getPolicyLocales,
|
|
230
237
|
getPolicySlugs: () => getPolicySlugs,
|
|
238
|
+
getRelatedBlogPosts: () => getRelatedBlogPosts,
|
|
231
239
|
getRelativeTime: () => getRelativeTime,
|
|
232
240
|
getRtlLocales: () => getRtlLocales,
|
|
233
241
|
getTextDirection: () => getTextDirection,
|
|
@@ -236,6 +244,7 @@ __export(src_exports, {
|
|
|
236
244
|
isLocaleDetectionEnabled: () => isLocaleDetectionEnabled,
|
|
237
245
|
isRtlLocale: () => isRtlLocale,
|
|
238
246
|
isSupportedLocale: () => isSupportedLocale,
|
|
247
|
+
loadBlogPost: () => loadBlogPost,
|
|
239
248
|
loadPolicy: () => loadPolicy,
|
|
240
249
|
locales: () => locales,
|
|
241
250
|
matchLocale: () => matchLocale,
|
|
@@ -458,6 +467,168 @@ function getPolicyLocales(slug, contentDir = "src/content/policies") {
|
|
|
458
467
|
return locales2;
|
|
459
468
|
}
|
|
460
469
|
|
|
470
|
+
// src/lib/content/blog.ts
|
|
471
|
+
var import_fs2 = __toESM(require("fs"));
|
|
472
|
+
var import_path2 = __toESM(require("path"));
|
|
473
|
+
var import_rsc2 = require("next-mdx-remote/rsc");
|
|
474
|
+
var import_rehype_slug2 = __toESM(require("rehype-slug"));
|
|
475
|
+
function resolveDir(contentDir) {
|
|
476
|
+
return import_path2.default.isAbsolute(contentDir) ? contentDir : import_path2.default.join(process.cwd(), contentDir);
|
|
477
|
+
}
|
|
478
|
+
var REQUIRED_FIELDS = ["title", "excerpt", "author", "date", "tags"];
|
|
479
|
+
async function loadBlogPost(slug, locale, contentDir = "src/content/blog") {
|
|
480
|
+
const dir = resolveDir(contentDir);
|
|
481
|
+
const filePath = import_path2.default.join(dir, `${slug}.${locale}.md`);
|
|
482
|
+
if (!import_fs2.default.existsSync(filePath)) {
|
|
483
|
+
throw new Error(
|
|
484
|
+
`Blog post file not found: ${slug}.${locale}.md in ${contentDir}
|
|
485
|
+
Looking for: ${filePath}`
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
const source = import_fs2.default.readFileSync(filePath, "utf8");
|
|
489
|
+
const { content, frontmatter } = await (0, import_rsc2.compileMDX)({
|
|
490
|
+
source,
|
|
491
|
+
options: {
|
|
492
|
+
parseFrontmatter: true,
|
|
493
|
+
mdxOptions: {
|
|
494
|
+
rehypePlugins: [import_rehype_slug2.default]
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
for (const field of REQUIRED_FIELDS) {
|
|
499
|
+
if (!frontmatter[field]) {
|
|
500
|
+
throw new Error(
|
|
501
|
+
`Blog post ${slug}.${locale}.md is missing required frontmatter field: ${field}`
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
content,
|
|
507
|
+
metadata: frontmatter,
|
|
508
|
+
slug,
|
|
509
|
+
locale
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function getBlogPostSlugs(contentDir = "src/content/blog") {
|
|
513
|
+
const dir = resolveDir(contentDir);
|
|
514
|
+
if (!import_fs2.default.existsSync(dir)) {
|
|
515
|
+
console.warn(`Blog directory not found: ${dir}`);
|
|
516
|
+
return [];
|
|
517
|
+
}
|
|
518
|
+
const files = import_fs2.default.readdirSync(dir);
|
|
519
|
+
const slugs = Array.from(
|
|
520
|
+
new Set(
|
|
521
|
+
files.filter((file) => file.endsWith(".md") || file.endsWith(".mdx")).map((file) => file.replace(/\.[a-z]{2}(-[A-Z]{2})?\.mdx?$/, ""))
|
|
522
|
+
)
|
|
523
|
+
);
|
|
524
|
+
return slugs;
|
|
525
|
+
}
|
|
526
|
+
async function getAllBlogPosts(locale, contentDir = "src/content/blog") {
|
|
527
|
+
const slugs = getBlogPostSlugs(contentDir);
|
|
528
|
+
const posts = await Promise.all(
|
|
529
|
+
slugs.map(async (slug) => {
|
|
530
|
+
try {
|
|
531
|
+
const post = await loadBlogPost(slug, locale, contentDir);
|
|
532
|
+
return {
|
|
533
|
+
slug: post.slug,
|
|
534
|
+
locale: post.locale,
|
|
535
|
+
metadata: post.metadata
|
|
536
|
+
};
|
|
537
|
+
} catch (error) {
|
|
538
|
+
console.warn(`Skipping ${slug} for locale ${locale}:`, error);
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
})
|
|
542
|
+
);
|
|
543
|
+
return posts.filter((p) => p !== null).sort((a, b) => new Date(b.metadata.date).getTime() - new Date(a.metadata.date).getTime());
|
|
544
|
+
}
|
|
545
|
+
function getBlogPostLocales(slug, contentDir = "src/content/blog") {
|
|
546
|
+
const dir = resolveDir(contentDir);
|
|
547
|
+
if (!import_fs2.default.existsSync(dir)) {
|
|
548
|
+
return [];
|
|
549
|
+
}
|
|
550
|
+
const files = import_fs2.default.readdirSync(dir);
|
|
551
|
+
const locales2 = files.filter((file) => {
|
|
552
|
+
const pattern = new RegExp(`^${slug}\\.[a-z]{2}(-[A-Z]{2})?\\.mdx?$`);
|
|
553
|
+
return pattern.test(file);
|
|
554
|
+
}).map((file) => {
|
|
555
|
+
const match = file.match(/\.([a-z]{2}(-[A-Z]{2})?)\.mdx?$/);
|
|
556
|
+
return match ? match[1] : null;
|
|
557
|
+
}).filter((locale) => locale !== null);
|
|
558
|
+
return locales2;
|
|
559
|
+
}
|
|
560
|
+
async function getBlogPostsByTag(tag, locale, contentDir = "src/content/blog") {
|
|
561
|
+
const posts = await getAllBlogPosts(locale, contentDir);
|
|
562
|
+
return posts.filter((p) => p.metadata.tags.includes(tag));
|
|
563
|
+
}
|
|
564
|
+
async function getFeaturedBlogPosts(locale, contentDir = "src/content/blog") {
|
|
565
|
+
const posts = await getAllBlogPosts(locale, contentDir);
|
|
566
|
+
return posts.filter((p) => p.metadata.featured === true);
|
|
567
|
+
}
|
|
568
|
+
async function getRelatedBlogPosts(slug, locale, count = 3, contentDir = "src/content/blog") {
|
|
569
|
+
const allPosts = await getAllBlogPosts(locale, contentDir);
|
|
570
|
+
const sourcePost = allPosts.find((p) => p.slug === slug);
|
|
571
|
+
if (!sourcePost) return [];
|
|
572
|
+
const sourceTags = new Set(sourcePost.metadata.tags);
|
|
573
|
+
const candidates = allPosts.filter((p) => p.slug !== slug);
|
|
574
|
+
const scored = candidates.map((post) => ({
|
|
575
|
+
post,
|
|
576
|
+
sharedTags: post.metadata.tags.filter((t) => sourceTags.has(t)).length
|
|
577
|
+
}));
|
|
578
|
+
return scored.filter((s) => s.sharedTags > 0).sort((a, b) => {
|
|
579
|
+
if (b.sharedTags !== a.sharedTags) return b.sharedTags - a.sharedTags;
|
|
580
|
+
return new Date(b.post.metadata.date).getTime() - new Date(a.post.metadata.date).getTime();
|
|
581
|
+
}).slice(0, count).map((s) => s.post);
|
|
582
|
+
}
|
|
583
|
+
async function getAllTags(locale, contentDir = "src/content/blog") {
|
|
584
|
+
const posts = await getAllBlogPosts(locale, contentDir);
|
|
585
|
+
const counts = /* @__PURE__ */ new Map();
|
|
586
|
+
for (const post of posts) {
|
|
587
|
+
for (const tag of post.metadata.tags) {
|
|
588
|
+
counts.set(tag, (counts.get(tag) ?? 0) + 1);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return Array.from(counts.entries()).map(([tag, count]) => ({ tag, count })).sort((a, b) => b.count - a.count);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// src/lib/content/rss.ts
|
|
595
|
+
var MAX_ITEMS = 20;
|
|
596
|
+
async function generateBlogRssFeed(options) {
|
|
597
|
+
const { siteUrl, siteName, locale, contentDir } = options;
|
|
598
|
+
const description = typeof options.description === "string" ? options.description : getLocalizedString(options.description, locale);
|
|
599
|
+
const posts = await getAllBlogPosts(locale, contentDir);
|
|
600
|
+
const items = posts.slice(0, MAX_ITEMS);
|
|
601
|
+
const itemsXml = items.map((post) => {
|
|
602
|
+
const link = `${siteUrl}/${locale}/blog/${post.slug}`;
|
|
603
|
+
const pubDate = (/* @__PURE__ */ new Date(`${post.metadata.date}T12:00:00Z`)).toUTCString();
|
|
604
|
+
const categories = post.metadata.tags.map((tag) => ` <category>${escapeXml(tag)}</category>`).join("\n");
|
|
605
|
+
return ` <item>
|
|
606
|
+
<title>${escapeXml(post.metadata.title)}</title>
|
|
607
|
+
<description>${escapeXml(post.metadata.excerpt)}</description>
|
|
608
|
+
<link>${escapeXml(link)}</link>
|
|
609
|
+
<guid>${escapeXml(link)}</guid>
|
|
610
|
+
<pubDate>${pubDate}</pubDate>
|
|
611
|
+
<author>${escapeXml(post.metadata.author)}</author>
|
|
612
|
+
${categories}
|
|
613
|
+
</item>`;
|
|
614
|
+
}).join("\n");
|
|
615
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
616
|
+
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
|
617
|
+
<channel>
|
|
618
|
+
<title>${escapeXml(siteName)}</title>
|
|
619
|
+
<description>${escapeXml(description)}</description>
|
|
620
|
+
<link>${escapeXml(siteUrl)}</link>
|
|
621
|
+
<language>${escapeXml(locale)}</language>
|
|
622
|
+
<lastBuildDate>${(/* @__PURE__ */ new Date()).toUTCString()}</lastBuildDate>
|
|
623
|
+
<atom:link href="${escapeXml(siteUrl)}/${escapeXml(locale)}/blog/feed.xml" rel="self" type="application/rss+xml"/>
|
|
624
|
+
${itemsXml}
|
|
625
|
+
</channel>
|
|
626
|
+
</rss>`;
|
|
627
|
+
}
|
|
628
|
+
function escapeXml(str) {
|
|
629
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
630
|
+
}
|
|
631
|
+
|
|
461
632
|
// src/lib/navigation/utils.ts
|
|
462
633
|
function getNavigationString(localizedString, locale) {
|
|
463
634
|
return localizedString[locale] || localizedString["en"] || "";
|
|
@@ -535,7 +706,7 @@ var defaultSlugTranslations = {
|
|
|
535
706
|
"/anti-spam-policy": "/politique-anti-pourriel"
|
|
536
707
|
}
|
|
537
708
|
};
|
|
538
|
-
function translateSlug(
|
|
709
|
+
function translateSlug(path3, fromLocale, toLocale, customTranslations) {
|
|
539
710
|
let configTranslations = {};
|
|
540
711
|
try {
|
|
541
712
|
const { getI18nConfig: getI18nConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
@@ -550,17 +721,17 @@ function translateSlug(path2, fromLocale, toLocale, customTranslations) {
|
|
|
550
721
|
);
|
|
551
722
|
const translationMap = translations[fromLocale];
|
|
552
723
|
if (!translationMap) {
|
|
553
|
-
return
|
|
724
|
+
return path3;
|
|
554
725
|
}
|
|
555
|
-
if (translationMap[
|
|
556
|
-
return translationMap[
|
|
726
|
+
if (translationMap[path3]) {
|
|
727
|
+
return translationMap[path3];
|
|
557
728
|
}
|
|
558
729
|
for (const [fromSlug, toSlug] of Object.entries(translationMap)) {
|
|
559
|
-
if (
|
|
560
|
-
return
|
|
730
|
+
if (path3.startsWith(fromSlug + "/")) {
|
|
731
|
+
return path3.replace(fromSlug, toSlug);
|
|
561
732
|
}
|
|
562
733
|
}
|
|
563
|
-
return
|
|
734
|
+
return path3;
|
|
564
735
|
}
|
|
565
736
|
function mergeTranslations(...translations) {
|
|
566
737
|
const merged = {};
|
|
@@ -1389,7 +1560,7 @@ function generateSitemap(config) {
|
|
|
1389
1560
|
const urlEntries = entries.map((entry) => {
|
|
1390
1561
|
const parts = [];
|
|
1391
1562
|
parts.push(`${indent}<url>${newline}`);
|
|
1392
|
-
parts.push(`${indent}${indent}<loc>${
|
|
1563
|
+
parts.push(`${indent}${indent}<loc>${escapeXml2(entry.url)}</loc>${newline}`);
|
|
1393
1564
|
if (entry.lastModified) {
|
|
1394
1565
|
const date = entry.lastModified instanceof Date ? entry.lastModified.toISOString() : entry.lastModified;
|
|
1395
1566
|
parts.push(`${indent}${indent}<lastmod>${date}</lastmod>${newline}`);
|
|
@@ -1404,9 +1575,9 @@ function generateSitemap(config) {
|
|
|
1404
1575
|
if (entry.alternates && entry.alternates.length > 0) {
|
|
1405
1576
|
entry.alternates.forEach((alternate) => {
|
|
1406
1577
|
parts.push(
|
|
1407
|
-
`${indent}${indent}<xhtml:link rel="alternate" hreflang="${
|
|
1578
|
+
`${indent}${indent}<xhtml:link rel="alternate" hreflang="${escapeXml2(
|
|
1408
1579
|
alternate.hreflang
|
|
1409
|
-
)}" href="${
|
|
1580
|
+
)}" href="${escapeXml2(alternate.href)}" />${newline}`
|
|
1410
1581
|
);
|
|
1411
1582
|
});
|
|
1412
1583
|
}
|
|
@@ -1423,8 +1594,8 @@ function generateSitemap(config) {
|
|
|
1423
1594
|
].join("");
|
|
1424
1595
|
return xml;
|
|
1425
1596
|
}
|
|
1426
|
-
function createMultiLanguageEntries(baseUrl,
|
|
1427
|
-
const cleanPath =
|
|
1597
|
+
function createMultiLanguageEntries(baseUrl, path3, locales2, defaultLocale2, options) {
|
|
1598
|
+
const cleanPath = path3.startsWith("/") ? path3 : `/${path3}`;
|
|
1428
1599
|
return locales2.map((locale) => {
|
|
1429
1600
|
const alternates = locales2.map((altLocale) => ({
|
|
1430
1601
|
hreflang: altLocale,
|
|
@@ -1443,15 +1614,15 @@ function createMultiLanguageEntries(baseUrl, path2, locales2, defaultLocale2, op
|
|
|
1443
1614
|
};
|
|
1444
1615
|
});
|
|
1445
1616
|
}
|
|
1446
|
-
function createSitemapEntry(baseUrl,
|
|
1447
|
-
const cleanPath =
|
|
1448
|
-
const url =
|
|
1617
|
+
function createSitemapEntry(baseUrl, path3, options) {
|
|
1618
|
+
const cleanPath = path3.startsWith("/") ? path3 : `/${path3}`;
|
|
1619
|
+
const url = path3 === "/" ? baseUrl : `${baseUrl}${cleanPath}`;
|
|
1449
1620
|
return {
|
|
1450
1621
|
url,
|
|
1451
1622
|
...options
|
|
1452
1623
|
};
|
|
1453
1624
|
}
|
|
1454
|
-
function
|
|
1625
|
+
function escapeXml2(unsafe) {
|
|
1455
1626
|
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1456
1627
|
}
|
|
1457
1628
|
function validateSitemapEntry(entry) {
|
|
@@ -1642,14 +1813,21 @@ function FeaturesGrid({ categories, className = "", locale = "en" }) {
|
|
|
1642
1813
|
formatNumber,
|
|
1643
1814
|
formatRelativeTime,
|
|
1644
1815
|
generateArticleMetadata,
|
|
1816
|
+
generateBlogRssFeed,
|
|
1645
1817
|
generateDesignTokens,
|
|
1646
1818
|
generateMetadata,
|
|
1647
1819
|
generateSitemap,
|
|
1648
1820
|
generateThemeCSS,
|
|
1821
|
+
getAllBlogPosts,
|
|
1649
1822
|
getAllPolicies,
|
|
1823
|
+
getAllTags,
|
|
1650
1824
|
getAlternateLocales,
|
|
1825
|
+
getBlogPostLocales,
|
|
1826
|
+
getBlogPostSlugs,
|
|
1827
|
+
getBlogPostsByTag,
|
|
1651
1828
|
getDefaultLocale,
|
|
1652
1829
|
getErrorMessage,
|
|
1830
|
+
getFeaturedBlogPosts,
|
|
1653
1831
|
getFontConfig,
|
|
1654
1832
|
getFontVariables,
|
|
1655
1833
|
getI18nConfig,
|
|
@@ -1666,6 +1844,7 @@ function FeaturesGrid({ categories, className = "", locale = "en" }) {
|
|
|
1666
1844
|
getNavigationString,
|
|
1667
1845
|
getPolicyLocales,
|
|
1668
1846
|
getPolicySlugs,
|
|
1847
|
+
getRelatedBlogPosts,
|
|
1669
1848
|
getRelativeTime,
|
|
1670
1849
|
getRtlLocales,
|
|
1671
1850
|
getTextDirection,
|
|
@@ -1674,6 +1853,7 @@ function FeaturesGrid({ categories, className = "", locale = "en" }) {
|
|
|
1674
1853
|
isLocaleDetectionEnabled,
|
|
1675
1854
|
isRtlLocale,
|
|
1676
1855
|
isSupportedLocale,
|
|
1856
|
+
loadBlogPost,
|
|
1677
1857
|
loadPolicy,
|
|
1678
1858
|
locales,
|
|
1679
1859
|
matchLocale,
|